-
Notifications
You must be signed in to change notification settings - Fork 4.1k
Expand file tree
/
Copy pathamp-ad-template-helper.js
More file actions
138 lines (126 loc) · 4.08 KB
/
Copy pathamp-ad-template-helper.js
File metadata and controls
138 lines (126 loc) · 4.08 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
import {LruCache} from '#core/data-structures/lru-cache';
import {createElementWithAttributes} from '#core/dom';
import {isArray} from '#core/types';
import {Services} from '#service';
import {devAssert} from '#utils/log';
import * as urls from '../../../src/config/urls';
import {getMode} from '../../../src/mode';
import {
getServiceForDoc,
registerServiceBuilderForDoc,
} from '../../../src/service-helpers';
import {isProxyOrigin, parseUrlDeprecated} from '../../../src/url';
/** @private {!{[key: string]: string|boolean}} */
const TEMPLATE_CORS_CONFIG = {
mode: 'cors',
method: 'GET',
// This should be cached across publisher domains, so don't append
// __amp_source_origin to the URL.
ampCors: false,
credentials: 'omit',
};
const SERVICE_ID = 'AmpAdTemplateHelper';
export class AmpAdTemplateHelper {
/**
* @param {!../../../src/service/ampdoc-impl.AmpDoc} ampdoc
*/
constructor(ampdoc) {
/** @private @const */
this.parentAmpdoc_ = ampdoc;
/** @private {LruCache} */
this.cache_ = new LruCache(5);
}
/**
* Fetch and parse template from AMP cache. Result is stored in global in
* order to reduce overhead when template is used multiple times.
* @param {string} templateUrl Canonical URL to template.
* @return {!Promise<string>}
*/
fetch(templateUrl) {
const {win} = this.parentAmpdoc_;
const proxyUrl =
getMode(win).localDev && !isNaN(templateUrl)
? `http://ads.localhost:${win.location.port}` +
`/a4a_template/adzerk/${templateUrl}`
: this.getTemplateProxyUrl_(templateUrl);
let templatePromise = this.cache_.get(proxyUrl);
if (!templatePromise) {
templatePromise = Services.xhrFor(win)
.fetchText(proxyUrl, TEMPLATE_CORS_CONFIG)
.then((response) => response.text());
this.cache_.put(proxyUrl, templatePromise);
}
devAssert(templatePromise);
return /** @type {!Promise<string>} */ (templatePromise);
}
/**
* @param {!JsonObject} templateValues The values to macro in.
* @param {!Element} element Parent element containing template.
* @return {!Promise<!Element>} Promise which resolves after rendering completes.
*/
render(templateValues, element) {
return Services.templatesForDoc(element).findAndRenderTemplate(
element,
templateValues
);
}
/**
* @param {!Element} element
* @param {!Array|!JsonObject} analyticsValue
*/
insertAnalytics(element, analyticsValue) {
analyticsValue = /**@type {!Array}*/ (
isArray(analyticsValue) ? analyticsValue : [analyticsValue]
);
for (let i = 0; i < analyticsValue.length; i++) {
const config = analyticsValue[i];
const analyticsEle = element.ownerDocument.createElement('amp-analytics');
if (config['remote']) {
analyticsEle.setAttribute('config', config['remote']);
}
if (config['type']) {
analyticsEle.setAttribute('type', config['type']);
}
if (config['inline']) {
const scriptElem = createElementWithAttributes(
element.ownerDocument,
'script',
{
'type': 'application/json',
}
);
scriptElem.textContent = JSON.stringify(config['inline']);
analyticsEle.appendChild(scriptElem);
}
element.appendChild(analyticsEle);
}
}
/**
* Converts the canonical template URL to the CDN proxy URL.
* @param {string} url
* @return {string}
*/
getTemplateProxyUrl_(url) {
const cdnUrlSuffix = urls.cdn.slice(8);
const loc = parseUrlDeprecated(url);
return isProxyOrigin(loc)
? url
: 'https://' +
loc.hostname.replace(/-/g, '--').replace(/\./g, '-') +
'.' +
cdnUrlSuffix +
'/ad/s/' +
loc.hostname +
loc.pathname;
}
}
/**
* @param {!Element|!../../../src/service/ampdoc-impl.AmpDoc} target
* @return {!AmpAdTemplateHelper}
*/
export function getAmpAdTemplateHelper(target) {
registerServiceBuilderForDoc(target, SERVICE_ID, AmpAdTemplateHelper);
return /** @type {!AmpAdTemplateHelper} */ (
getServiceForDoc(target, SERVICE_ID)
);
}