1 | /**
|
---|
2 | * @license
|
---|
3 | * Copyright Google LLC All Rights Reserved.
|
---|
4 | *
|
---|
5 | * Use of this source code is governed by an MIT-style license that can be
|
---|
6 | * found in the LICENSE file at https://angular.io/license
|
---|
7 | */
|
---|
8 | import { computeDecimalDigest, computeDigest, decimalDigest } from '../../../i18n/digest';
|
---|
9 | import * as i18n from '../../../i18n/i18n_ast';
|
---|
10 | import { createI18nMessageFactory } from '../../../i18n/i18n_parser';
|
---|
11 | import { I18nError } from '../../../i18n/parse_util';
|
---|
12 | import * as html from '../../../ml_parser/ast';
|
---|
13 | import { DEFAULT_INTERPOLATION_CONFIG } from '../../../ml_parser/interpolation_config';
|
---|
14 | import { ParseTreeResult } from '../../../ml_parser/parser';
|
---|
15 | import * as o from '../../../output/output_ast';
|
---|
16 | import { isTrustedTypesSink } from '../../../schema/trusted_types_sinks';
|
---|
17 | import { hasI18nAttrs, I18N_ATTR, I18N_ATTR_PREFIX, icuFromI18nMessage } from './util';
|
---|
18 | const setI18nRefs = (htmlNode, i18nNode) => {
|
---|
19 | if (htmlNode instanceof html.NodeWithI18n) {
|
---|
20 | if (i18nNode instanceof i18n.IcuPlaceholder && htmlNode.i18n instanceof i18n.Message) {
|
---|
21 | // This html node represents an ICU but this is a second processing pass, and the legacy id
|
---|
22 | // was computed in the previous pass and stored in the `i18n` property as a message.
|
---|
23 | // We are about to wipe out that property so capture the previous message to be reused when
|
---|
24 | // generating the message for this ICU later. See `_generateI18nMessage()`.
|
---|
25 | i18nNode.previousMessage = htmlNode.i18n;
|
---|
26 | }
|
---|
27 | htmlNode.i18n = i18nNode;
|
---|
28 | }
|
---|
29 | return i18nNode;
|
---|
30 | };
|
---|
31 | /**
|
---|
32 | * This visitor walks over HTML parse tree and converts information stored in
|
---|
33 | * i18n-related attributes ("i18n" and "i18n-*") into i18n meta object that is
|
---|
34 | * stored with other element's and attribute's information.
|
---|
35 | */
|
---|
36 | export class I18nMetaVisitor {
|
---|
37 | constructor(interpolationConfig = DEFAULT_INTERPOLATION_CONFIG, keepI18nAttrs = false, enableI18nLegacyMessageIdFormat = false) {
|
---|
38 | this.interpolationConfig = interpolationConfig;
|
---|
39 | this.keepI18nAttrs = keepI18nAttrs;
|
---|
40 | this.enableI18nLegacyMessageIdFormat = enableI18nLegacyMessageIdFormat;
|
---|
41 | // whether visited nodes contain i18n information
|
---|
42 | this.hasI18nMeta = false;
|
---|
43 | this._errors = [];
|
---|
44 | // i18n message generation factory
|
---|
45 | this._createI18nMessage = createI18nMessageFactory(this.interpolationConfig);
|
---|
46 | }
|
---|
47 | _generateI18nMessage(nodes, meta = '', visitNodeFn) {
|
---|
48 | const { meaning, description, customId } = this._parseMetadata(meta);
|
---|
49 | const message = this._createI18nMessage(nodes, meaning, description, customId, visitNodeFn);
|
---|
50 | this._setMessageId(message, meta);
|
---|
51 | this._setLegacyIds(message, meta);
|
---|
52 | return message;
|
---|
53 | }
|
---|
54 | visitAllWithErrors(nodes) {
|
---|
55 | const result = nodes.map(node => node.visit(this, null));
|
---|
56 | return new ParseTreeResult(result, this._errors);
|
---|
57 | }
|
---|
58 | visitElement(element) {
|
---|
59 | if (hasI18nAttrs(element)) {
|
---|
60 | this.hasI18nMeta = true;
|
---|
61 | const attrs = [];
|
---|
62 | const attrsMeta = {};
|
---|
63 | for (const attr of element.attrs) {
|
---|
64 | if (attr.name === I18N_ATTR) {
|
---|
65 | // root 'i18n' node attribute
|
---|
66 | const i18n = element.i18n || attr.value;
|
---|
67 | const message = this._generateI18nMessage(element.children, i18n, setI18nRefs);
|
---|
68 | // do not assign empty i18n meta
|
---|
69 | if (message.nodes.length) {
|
---|
70 | element.i18n = message;
|
---|
71 | }
|
---|
72 | }
|
---|
73 | else if (attr.name.startsWith(I18N_ATTR_PREFIX)) {
|
---|
74 | // 'i18n-*' attributes
|
---|
75 | const name = attr.name.slice(I18N_ATTR_PREFIX.length);
|
---|
76 | if (isTrustedTypesSink(element.name, name)) {
|
---|
77 | this._reportError(attr, `Translating attribute '${name}' is disallowed for security reasons.`);
|
---|
78 | }
|
---|
79 | else {
|
---|
80 | attrsMeta[name] = attr.value;
|
---|
81 | }
|
---|
82 | }
|
---|
83 | else {
|
---|
84 | // non-i18n attributes
|
---|
85 | attrs.push(attr);
|
---|
86 | }
|
---|
87 | }
|
---|
88 | // set i18n meta for attributes
|
---|
89 | if (Object.keys(attrsMeta).length) {
|
---|
90 | for (const attr of attrs) {
|
---|
91 | const meta = attrsMeta[attr.name];
|
---|
92 | // do not create translation for empty attributes
|
---|
93 | if (meta !== undefined && attr.value) {
|
---|
94 | attr.i18n = this._generateI18nMessage([attr], attr.i18n || meta);
|
---|
95 | }
|
---|
96 | }
|
---|
97 | }
|
---|
98 | if (!this.keepI18nAttrs) {
|
---|
99 | // update element's attributes,
|
---|
100 | // keeping only non-i18n related ones
|
---|
101 | element.attrs = attrs;
|
---|
102 | }
|
---|
103 | }
|
---|
104 | html.visitAll(this, element.children, element.i18n);
|
---|
105 | return element;
|
---|
106 | }
|
---|
107 | visitExpansion(expansion, currentMessage) {
|
---|
108 | let message;
|
---|
109 | const meta = expansion.i18n;
|
---|
110 | this.hasI18nMeta = true;
|
---|
111 | if (meta instanceof i18n.IcuPlaceholder) {
|
---|
112 | // set ICU placeholder name (e.g. "ICU_1"),
|
---|
113 | // generated while processing root element contents,
|
---|
114 | // so we can reference it when we output translation
|
---|
115 | const name = meta.name;
|
---|
116 | message = this._generateI18nMessage([expansion], meta);
|
---|
117 | const icu = icuFromI18nMessage(message);
|
---|
118 | icu.name = name;
|
---|
119 | }
|
---|
120 | else {
|
---|
121 | // ICU is a top level message, try to use metadata from container element if provided via
|
---|
122 | // `context` argument. Note: context may not be available for standalone ICUs (without
|
---|
123 | // wrapping element), so fallback to ICU metadata in this case.
|
---|
124 | message = this._generateI18nMessage([expansion], currentMessage || meta);
|
---|
125 | }
|
---|
126 | expansion.i18n = message;
|
---|
127 | return expansion;
|
---|
128 | }
|
---|
129 | visitText(text) {
|
---|
130 | return text;
|
---|
131 | }
|
---|
132 | visitAttribute(attribute) {
|
---|
133 | return attribute;
|
---|
134 | }
|
---|
135 | visitComment(comment) {
|
---|
136 | return comment;
|
---|
137 | }
|
---|
138 | visitExpansionCase(expansionCase) {
|
---|
139 | return expansionCase;
|
---|
140 | }
|
---|
141 | /**
|
---|
142 | * Parse the general form `meta` passed into extract the explicit metadata needed to create a
|
---|
143 | * `Message`.
|
---|
144 | *
|
---|
145 | * There are three possibilities for the `meta` variable
|
---|
146 | * 1) a string from an `i18n` template attribute: parse it to extract the metadata values.
|
---|
147 | * 2) a `Message` from a previous processing pass: reuse the metadata values in the message.
|
---|
148 | * 4) other: ignore this and just process the message metadata as normal
|
---|
149 | *
|
---|
150 | * @param meta the bucket that holds information about the message
|
---|
151 | * @returns the parsed metadata.
|
---|
152 | */
|
---|
153 | _parseMetadata(meta) {
|
---|
154 | return typeof meta === 'string' ? parseI18nMeta(meta) :
|
---|
155 | meta instanceof i18n.Message ? meta : {};
|
---|
156 | }
|
---|
157 | /**
|
---|
158 | * Generate (or restore) message id if not specified already.
|
---|
159 | */
|
---|
160 | _setMessageId(message, meta) {
|
---|
161 | if (!message.id) {
|
---|
162 | message.id = meta instanceof i18n.Message && meta.id || decimalDigest(message);
|
---|
163 | }
|
---|
164 | }
|
---|
165 | /**
|
---|
166 | * Update the `message` with a `legacyId` if necessary.
|
---|
167 | *
|
---|
168 | * @param message the message whose legacy id should be set
|
---|
169 | * @param meta information about the message being processed
|
---|
170 | */
|
---|
171 | _setLegacyIds(message, meta) {
|
---|
172 | if (this.enableI18nLegacyMessageIdFormat) {
|
---|
173 | message.legacyIds = [computeDigest(message), computeDecimalDigest(message)];
|
---|
174 | }
|
---|
175 | else if (typeof meta !== 'string') {
|
---|
176 | // This occurs if we are doing the 2nd pass after whitespace removal (see `parseTemplate()` in
|
---|
177 | // `packages/compiler/src/render3/view/template.ts`).
|
---|
178 | // In that case we want to reuse the legacy message generated in the 1st pass (see
|
---|
179 | // `setI18nRefs()`).
|
---|
180 | const previousMessage = meta instanceof i18n.Message ?
|
---|
181 | meta :
|
---|
182 | meta instanceof i18n.IcuPlaceholder ? meta.previousMessage : undefined;
|
---|
183 | message.legacyIds = previousMessage ? previousMessage.legacyIds : [];
|
---|
184 | }
|
---|
185 | }
|
---|
186 | _reportError(node, msg) {
|
---|
187 | this._errors.push(new I18nError(node.sourceSpan, msg));
|
---|
188 | }
|
---|
189 | }
|
---|
190 | /** I18n separators for metadata **/
|
---|
191 | const I18N_MEANING_SEPARATOR = '|';
|
---|
192 | const I18N_ID_SEPARATOR = '@@';
|
---|
193 | /**
|
---|
194 | * Parses i18n metas like:
|
---|
195 | * - "@@id",
|
---|
196 | * - "description[@@id]",
|
---|
197 | * - "meaning|description[@@id]"
|
---|
198 | * and returns an object with parsed output.
|
---|
199 | *
|
---|
200 | * @param meta String that represents i18n meta
|
---|
201 | * @returns Object with id, meaning and description fields
|
---|
202 | */
|
---|
203 | export function parseI18nMeta(meta = '') {
|
---|
204 | let customId;
|
---|
205 | let meaning;
|
---|
206 | let description;
|
---|
207 | meta = meta.trim();
|
---|
208 | if (meta) {
|
---|
209 | const idIndex = meta.indexOf(I18N_ID_SEPARATOR);
|
---|
210 | const descIndex = meta.indexOf(I18N_MEANING_SEPARATOR);
|
---|
211 | let meaningAndDesc;
|
---|
212 | [meaningAndDesc, customId] =
|
---|
213 | (idIndex > -1) ? [meta.slice(0, idIndex), meta.slice(idIndex + 2)] : [meta, ''];
|
---|
214 | [meaning, description] = (descIndex > -1) ?
|
---|
215 | [meaningAndDesc.slice(0, descIndex), meaningAndDesc.slice(descIndex + 1)] :
|
---|
216 | ['', meaningAndDesc];
|
---|
217 | }
|
---|
218 | return { customId, meaning, description };
|
---|
219 | }
|
---|
220 | // Converts i18n meta information for a message (id, description, meaning)
|
---|
221 | // to a JsDoc statement formatted as expected by the Closure compiler.
|
---|
222 | export function i18nMetaToJSDoc(meta) {
|
---|
223 | const tags = [];
|
---|
224 | if (meta.description) {
|
---|
225 | tags.push({ tagName: "desc" /* Desc */, text: meta.description });
|
---|
226 | }
|
---|
227 | if (meta.meaning) {
|
---|
228 | tags.push({ tagName: "meaning" /* Meaning */, text: meta.meaning });
|
---|
229 | }
|
---|
230 | return tags.length == 0 ? null : o.jsDocComment(tags);
|
---|
231 | }
|
---|
232 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWV0YS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL2NvbXBpbGVyL3NyYy9yZW5kZXIzL3ZpZXcvaTE4bi9tZXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7R0FNRztBQUVILE9BQU8sRUFBQyxvQkFBb0IsRUFBRSxhQUFhLEVBQUUsYUFBYSxFQUFDLE1BQU0sc0JBQXNCLENBQUM7QUFDeEYsT0FBTyxLQUFLLElBQUksTUFBTSx3QkFBd0IsQ0FBQztBQUMvQyxPQUFPLEVBQUMsd0JBQXdCLEVBQWMsTUFBTSwyQkFBMkIsQ0FBQztBQUNoRixPQUFPLEVBQUMsU0FBUyxFQUFDLE1BQU0sMEJBQTBCLENBQUM7QUFDbkQsT0FBTyxLQUFLLElBQUksTUFBTSx3QkFBd0IsQ0FBQztBQUMvQyxPQUFPLEVBQUMsNEJBQTRCLEVBQXNCLE1BQU0seUNBQXlDLENBQUM7QUFDMUcsT0FBTyxFQUFDLGVBQWUsRUFBQyxNQUFNLDJCQUEyQixDQUFDO0FBQzFELE9BQU8sS0FBSyxDQUFDLE1BQU0sNEJBQTRCLENBQUM7QUFDaEQsT0FBTyxFQUFDLGtCQUFrQixFQUFDLE1BQU0scUNBQXFDLENBQUM7QUFFdkUsT0FBTyxFQUFDLFlBQVksRUFBRSxTQUFTLEVBQUUsZ0JBQWdCLEVBQUUsa0JBQWtCLEVBQUMsTUFBTSxRQUFRLENBQUM7QUFXckYsTUFBTSxXQUFXLEdBQWdCLENBQUMsUUFBUSxFQUFFLFFBQVEsRUFBRSxFQUFFO0lBQ3RELElBQUksUUFBUSxZQUFZLElBQUksQ0FBQyxZQUFZLEVBQUU7UUFDekMsSUFBSSxRQUFRLFlBQVksSUFBSSxDQUFDLGNBQWMsSUFBSSxRQUFRLENBQUMsSUFBSSxZQUFZLElBQUksQ0FBQyxPQUFPLEVBQUU7WUFDcEYsMkZBQTJGO1lBQzNGLG9GQUFvRjtZQUNwRiwyRkFBMkY7WUFDM0YsMkVBQTJFO1lBQzNFLFFBQVEsQ0FBQyxlQUFlLEdBQUcs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RSxDQUFDO0lBQzlCLElBQUksSUFBSSxDQUFDLFdBQVcsRUFBRTtRQUNwQixJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUMsT0FBTyxtQkFBcUIsRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLFdBQVcsRUFBQyxDQUFDLENBQUM7S0FDbkU7SUFDRCxJQUFJLElBQUksQ0FBQyxPQUFPLEVBQUU7UUFDaEIsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFDLE9BQU8seUJBQXdCLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxPQUFPLEVBQUMsQ0FBQyxDQUFDO0tBQ2xFO0lBQ0QsT0FBTyxJQUFJLENBQUMsTUFBTSxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFDO0FBQ3hELENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgR29vZ2xlIExMQyBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICpcbiAqIFVzZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IGFuIE1JVC1zdHlsZSBsaWNlbnNlIHRoYXQgY2FuIGJlXG4gKiBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlIGF0IGh0dHBzOi8vYW5ndWxhci5pby9saWNlbnNlXG4gKi9cblxuaW1wb3J0IHtjb21wdXRlRGVjaW1hbERpZ2VzdCwgY29tcHV0ZURpZ2VzdCwgZGVjaW1hbERpZ2VzdH0gZnJvbSAnLi4vLi4vLi4vaTE4bi9kaWdlc3QnO1xuaW1wb3J0ICogYXMgaTE4biBmcm9tICcuLi8uLi8uLi9pMThuL2kxOG5fYXN0JztcbmltcG9ydCB7Y3JlYXRlSTE4bk1lc3NhZ2VGYWN0b3J5LCBWaXNpdE5vZGVGbn0gZnJvbSAnLi4vLi4vLi4vaTE4bi9pMThuX3BhcnNlcic7XG5pbXBvcnQge0kxOG5FcnJvcn0gZnJvbSAnLi4vLi4vLi4vaTE4bi9wYXJzZV91dGlsJztcbmltcG9ydCAqIGFzIGh0bWwgZnJvbSAnLi4vLi4vLi4vbWxfcGFyc2VyL2FzdCc7XG5pbXBvcnQge0RFRkFVTFRfSU5URVJQT0xBVElPTl9DT05GSUcsIEludGVycG9sYXRpb25Db25maWd9IGZyb20gJy4uLy4uLy4uL21sX3BhcnNlci9pbnRlcnBvbGF0aW9uX2NvbmZpZyc7XG5pbXBvcnQge1BhcnNlVHJlZVJlc3VsdH0gZnJvbSAnLi4vLi4vLi4vbWxfcGFyc2VyL3BhcnNlcic7XG5pbXBvcnQgKiBhcyBvIGZyb20gJy4uLy4uLy4uL291dHB1dC9vdXRwdXRfYXN0JztcbmltcG9ydCB7aXNUcnVzdGVkVHlwZXNTaW5rfSBmcm9tICcuLi8uLi8uLi9zY2hlbWEvdHJ1c3RlZF90eXBlc19zaW5rcyc7XG5cbmltcG9ydCB7aGFzSTE4bkF0dHJzLCBJMThOX0FUVFIsIEkxOE5fQVRUUl9QUkVGSVgsIGljdUZyb21JMThuTWVzc2FnZX0gZnJvbSAnLi91dGlsJztcblxuZXhwb3J0IHR5cGUgSTE4bk1ldGEgPSB7XG4gIGlkPzogc3RyaW5nLFxuICBjdXN0b21JZD86IHN0cmluZyxcbiAgbGVnYWN5SWRzPzogc3RyaW5nW10sXG4gIGRlc2NyaXB0aW9uPzogc3RyaW5nLFxuICBtZWFuaW5nPzogc3RyaW5nXG59O1xuXG5cbmNvbnN0IHNldEkxOG5SZWZzOiBWaXNpdE5vZGVGbiA9IChodG1sTm9kZSwgaTE4bk5vZGUpID0+IHtcbiAgaWYgKGh0bWxOb2RlIGluc3RhbmNlb2YgaHRtbC5Ob2RlV2l0aEkxOG4pIHtcbiAgICBpZiAoaTE4bk5vZGUgaW5zdGFuY2VvZiBpMThuLkljdVBsYWNlaG9sZGVyICYmIGh0bWxOb2RlLmkxOG4gaW5zdGFuY2VvZiBpMThuLk1lc3NhZ2UpIHtcbiAgICAgIC8vIFRoaXMgaHRtbCBub2RlIHJlcHJlc2VudHMgYW4gSUNVIGJ1dCB0aGlzIGlzIGEgc2Vjb25kIHByb2Nlc3NpbmcgcGFzcywgYW5kIHRoZSBsZWdhY3kgaWRcbiAgICAgIC8vIHdhcyBjb21wdXRlZCBpbiB0aGUgcHJldmlvdXMgcGFzcyBhbmQgc3RvcmVkIGluIHRoZSBgaTE4bmAgcHJvcGVydHkgYXMgYSBtZXNzYWdlLlxuICAgICAgLy8gV2UgYXJlIGFib3V0IHRvIHdpcGUgb3V0IHRoYXQgcHJvcGVydHkgc28gY2FwdHVyZSB0aGUgcHJldmlvdXMgbWVzc2FnZSB0byBiZSByZXVzZWQgd2hlblxuICAgICAgLy8gZ2VuZXJhdGluZyB0aGUgbWVzc2FnZSBmb3IgdGhpcyBJQ1UgbGF0ZXIuIFNlZSBgX2dlbmVyYXRlSTE4bk1lc3NhZ2UoKWAuXG4gICAgICBpMThuTm9kZS5wcmV2aW91c01lc3NhZ2UgPSBodG1sTm9kZS5pMThuO1xuICAgIH1cbiAgICBodG1sTm9kZS5pMThuID0gaTE4bk5vZGU7XG4gIH1cbiAgcmV0dXJuIGkxOG5Ob2RlO1xufTtcblxuLyoqXG4gKiBUaGlzIHZpc2l0b3Igd2Fsa3Mgb3ZlciBIVE1MIHBhcnNlIHRyZWUgYW5kIGNvbnZlcnRzIGluZm9ybWF0aW9uIHN0b3JlZCBpblxuICogaTE4bi1yZWxhdGVkIGF0dHJpYnV0ZXMgKFwiaTE4blwiIGFuZCBcImkxOG4tKlwiKSBpbnRvIGkxOG4gbWV0YSBvYmplY3QgdGhhdCBpc1xuICogc3RvcmVkIHdpdGggb3RoZXIgZWxlbWVudCdzIGFuZCBhdHRyaWJ1dGUncyBpbmZvcm1hdGlvbi5cbiAqL1xuZXhwb3J0IGNsYXNzIEkxOG5NZXRhVmlzaXRvciBpbXBsZW1lbnRzIGh0bWwuVmlzaXRvciB7XG4gIC8vIHdoZXRoZXIgdmlzaXRlZCBub2RlcyBjb250YWluIGkxOG4gaW5mb3JtYXRpb25cbiAgcHVibGljIGhhc0kxOG5NZXRhOiBib29sZWFuID0gZmFsc2U7XG4gIHByaXZhdGUgX2Vycm9yczogSTE4bkVycm9yW10gPSBbXTtcblxuICAvLyBpMThuIG1lc3NhZ2UgZ2VuZXJhdGlvbiBmYWN0b3J5XG4gIHByaXZhdGUgX2NyZWF0ZUkxOG5NZXNzYWdlID0gY3JlYXRlSTE4bk1lc3NhZ2VGYWN0b3J5KHRoaXMuaW50ZXJwb2xhdGlvbkNvbmZpZyk7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgICBwcml2YXRlIGludGVycG9sYXRpb25Db25maWc6IEludGVycG9sYXRpb25Db25maWcgPSBERUZBVUxUX0lOVEVSUE9MQVRJT05fQ09ORklHLFxuICAgICAgcHJpdmF0ZSBrZWVwSTE4bkF0dHJzID0gZmFsc2UsIHByaXZhdGUgZW5hYmxlSTE4bkxlZ2FjeU1lc3NhZ2VJZEZvcm1hdCA9IGZhbHNlKSB7fVxuXG4gIHByaXZhdGUgX2dlbmVyYXRlSTE4bk1lc3NhZ2UoXG4gICAgICBub2RlczogaHRtbC5Ob2RlW10sIG1ldGE6IHN0cmluZ3xpMThuLkkxOG5NZXRhID0gJycsXG4gICAgICB2aXNpdE5vZGVGbj86IFZpc2l0Tm9kZUZuKTogaTE4bi5NZXNzYWdlIHtcbiAgICBjb25zdCB7bWVhbmluZywgZGVzY3JpcHRpb24sIGN1c3RvbUlkfSA9IHRoaXMuX3BhcnNlTWV0YWRhdGEobWV0YSk7XG4gICAgY29uc3QgbWVzc2FnZSA9IHRoaXMuX2NyZWF0ZUkxOG5NZXNzYWdlKG5vZGVzLCBtZWFuaW5nLCBkZXNjcmlwdGlvbiwgY3VzdG9tSWQsIHZpc2l0Tm9kZUZuKTtcbiAgICB0aGlzLl9zZXRNZXNzYWdlSWQobWVzc2FnZSwgbWV0YSk7XG4gICAgdGhpcy5fc2V0TGVnYWN5SWRzKG1lc3NhZ2UsIG1ldGEpO1xuICAgIHJldHVybiBtZXNzYWdlO1xuICB9XG5cbiAgdmlzaXRBbGxXaXRoRXJyb3JzKG5vZGVzOiBodG1sLk5vZGVbXSk6IFBhcnNlVHJlZVJlc3VsdCB7XG4gICAgY29uc3QgcmVzdWx0ID0gbm9kZXMubWFwKG5vZGUgPT4gbm9kZS52aXNpdCh0aGlzLCBudWxsKSk7XG4gICAgcmV0dXJuIG5ldyBQYXJzZVRyZWVSZXN1bHQocmVzdWx0LCB0aGlzLl9lcnJvcnMpO1xuICB9XG5cbiAgdmlzaXRFbGVtZW50KGVsZW1lbnQ6IGh0bWwuRWxlbWVudCk6IGFueSB7XG4gICAgaWYgKGhhc0kxOG5BdHRycyhlbGVtZW50KSkge1xuICAgICAgdGhpcy5oYXNJMThuTWV0YSA9IHRydWU7XG4gICAgICBjb25zdCBhdHRyczogaHRtbC5BdHRyaWJ1dGVbXSA9IFtdO1xuICAgICAgY29uc3QgYXR0cnNNZXRhOiB7W2tleTogc3RyaW5nXTogc3RyaW5nfSA9IHt9O1xuXG4gICAgICBmb3IgKGNvbnN0IGF0dHIgb2YgZWxlbWVudC5hdHRycykge1xuICAgICAgICBpZiAoYXR0ci5uYW1lID09PSBJMThOX0FUVFIpIHtcbiAgICAgICAgICAvLyByb290ICdpMThuJyBub2RlIGF0dHJpYnV0ZVxuICAgICAgICAgIGNvbnN0IGkxOG4gPSBlbGVtZW50LmkxOG4gfHwgYXR0ci52YWx1ZTtcbiAgICAgICAgICBjb25zdCBtZXNzYWdlID0gdGhpcy5fZ2VuZXJhdGVJMThuTWVzc2FnZShlbGVtZW50LmNoaWxkcmVuLCBpMThuLCBzZXRJMThuUmVmcyk7XG4gICAgICAgICAgLy8gZG8gbm90IGFzc2lnbiBlbXB0eSBpMThuIG1ldGFcbiAgICAgICAgICBpZiAobWVzc2FnZS5ub2Rlcy5sZW5ndGgpIHtcbiAgICAgICAgICAgIGVsZW1lbnQuaTE4biA9IG1lc3NhZ2U7XG4gICAgICAgICAgfVxuXG4gICAgICAgIH0gZWxzZSBpZiAoYXR0ci5uYW1lLnN0YXJ0c1dpdGgoSTE4Tl9BVFRSX1BSRUZJWCkpIHtcbiAgICAgICAgICAvLyAnaTE4bi0qJyBhdHRyaWJ1dGVzXG4gICAgICAgICAgY29uc3QgbmFtZSA9IGF0dHIubmFtZS5zbGljZShJMThOX0FUVFJfUFJFRklYLmxlbmd0aCk7XG4gICAgICAgICAgaWYgKGlzVHJ1c3RlZFR5cGVzU2luayhlbGVtZW50Lm5hbWUsIG5hbWUpKSB7XG4gICAgICAgICAgICB0aGlzLl9yZXBvcnRFcnJvcihcbiAgICAgICAgICAgICAgICBhdHRyLCBgVHJhbnNsYXRpbmcgYXR0cmlidXRlICcke25hbWV9JyBpcyBkaXNhbGxvd2VkIGZvciBzZWN1cml0eSByZWFzb25zLmApO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBhdHRyc01ldGFbbmFtZV0gPSBhdHRyLnZhbHVlO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyBub24taTE4biBhdHRyaWJ1dGVzXG4gICAgICAgICAgYXR0cnMucHVzaChhdHRyKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyBzZXQgaTE4biBtZXRhIGZvciBhdHRyaWJ1dGVzXG4gICAgICBpZiAoT2JqZWN0LmtleXMoYXR0cnNNZXRhKS5sZW5ndGgpIHtcbiAgICAgICAgZm9yIChjb25zdCBhdHRyIG9mIGF0dHJzKSB7XG4gICAgICAgICAgY29uc3QgbWV0YSA9IGF0dHJzTWV0YVthdHRyLm5hbWVdO1xuICAgICAgICAgIC8vIGRvIG5vdCBjcmVhdGUgdHJhbnNsYXRpb24gZm9yIGVtcHR5IGF0dHJpYnV0ZXNcbiAgICAgICAgICBpZiAobWV0YSAhPT0gdW5kZWZpbmVkICYmIGF0dHIudmFsdWUpIHtcbiAgICAgICAgICAgIGF0dHIuaTE4biA9IHRoaXMuX2dlbmVyYXRlSTE4bk1lc3NhZ2UoW2F0dHJdLCBhdHRyLmkxOG4gfHwgbWV0YSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmICghdGhpcy5rZWVwSTE4bkF0dHJzKSB7XG4gICAgICAgIC8vIHVwZGF0ZSBlbGVtZW50J3MgYXR0cmlidXRlcyxcbiAgICAgICAgLy8ga2VlcGluZyBvbmx5IG5vbi1pMThuIHJlbGF0ZWQgb25lc1xuICAgICAgICBlbGVtZW50LmF0dHJzID0gYXR0cnM7XG4gICAgICB9XG4gICAgfVxuICAgIGh0bWwudmlzaXRBbGwodGhpcywgZWxlbWVudC5jaGlsZHJlbiwgZWxlbWVudC5pMThuKTtcbiAgICByZXR1cm4gZWxlbWVudDtcbiAgfVxuXG4gIHZpc2l0RXhwYW5zaW9uKGV4cGFuc2lvbjogaHRtbC5FeHBhbnNpb24sIGN1cnJlbnRNZXNzYWdlOiBpMThuLk1lc3NhZ2V8dW5kZWZpbmVkKTogYW55IHtcbiAgICBsZXQgbWVzc2FnZTtcbiAgICBjb25zdCBtZXRhID0gZXhwYW5zaW9uLmkxOG47XG4gICAgdGhpcy5oYXNJMThuTWV0YSA9IHRydWU7XG4gICAgaWYgKG1ldGEgaW5zdGFuY2VvZiBpMThuLkljdVBsYWNlaG9sZGVyKSB7XG4gICAgICAvLyBzZXQgSUNVIHBsYWNlaG9sZGVyIG5hbWUgKGUuZy4gXCJJQ1VfMVwiKSxcbiAgICAgIC8vIGdlbmVyYXRlZCB3aGlsZSBwcm9jZXNzaW5nIHJvb3QgZWxlbWVudCBjb250ZW50cyxcbiAgICAgIC8vIHNvIHdlIGNhbiByZWZlcmVuY2UgaXQgd2hlbiB3ZSBvdXRwdXQgdHJhbnNsYXRpb25cbiAgICAgIGNvbnN0IG5hbWUgPSBtZXRhLm5hbWU7XG4gICAgICBtZXNzYWdlID0gdGhpcy5fZ2VuZXJhdGVJMThuTWVzc2FnZShbZXhwYW5zaW9uXSwgbWV0YSk7XG4gICAgICBjb25zdCBpY3UgPSBpY3VGcm9tSTE4bk1lc3NhZ2UobWVzc2FnZSk7XG4gICAgICBpY3UubmFtZSA9IG5hbWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIElDVSBpcyBhIHRvcCBsZXZlbCBtZXNzYWdlLCB0cnkgdG8gdXNlIG1ldGFkYXRhIGZyb20gY29udGFpbmVyIGVsZW1lbnQgaWYgcHJvdmlkZWQgdmlhXG4gICAgICAvLyBgY29udGV4dGAgYXJndW1lbnQuIE5vdGU6IGNvbnRleHQgbWF5IG5vdCBiZSBhdmFpbGFibGUgZm9yIHN0YW5kYWxvbmUgSUNVcyAod2l0aG91dFxuICAgICAgLy8gd3JhcHBpbmcgZWxlbWVudCksIHNvIGZhbGxiYWNrIHRvIElDVSBtZXRhZGF0YSBpbiB0aGlzIGNhc2UuXG4gICAgICBtZXNzYWdlID0gdGhpcy5fZ2VuZXJhdGVJMThuTWVzc2FnZShbZXhwYW5zaW9uXSwgY3VycmVudE1lc3NhZ2UgfHwgbWV0YSk7XG4gICAgfVxuICAgIGV4cGFuc2lvbi5pMThuID0gbWVzc2FnZTtcbiAgICByZXR1cm4gZXhwYW5zaW9uO1xuICB9XG5cbiAgdmlzaXRUZXh0KHRleHQ6IGh0bWwuVGV4dCk6IGFueSB7XG4gICAgcmV0dXJuIHRleHQ7XG4gIH1cbiAgdmlzaXRBdHRyaWJ1dGUoYXR0cmlidXRlOiBodG1sLkF0dHJpYnV0ZSk6IGFueSB7XG4gICAgcmV0dXJuIGF0dHJpYnV0ZTtcbiAgfVxuICB2aXNpdENvbW1lbnQoY29tbWVudDogaHRtbC5Db21tZW50KTogYW55IHtcbiAgICByZXR1cm4gY29tbWVudDtcbiAgfVxuICB2aXNpdEV4cGFuc2lvbkNhc2UoZXhwYW5zaW9uQ2FzZTogaHRtbC5FeHBhbnNpb25DYXNlKTogYW55IHtcbiAgICByZXR1cm4gZXhwYW5zaW9uQ2FzZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQYXJzZSB0aGUgZ2VuZXJhbCBmb3JtIGBtZXRhYCBwYXNzZWQgaW50byBleHRyYWN0IHRoZSBleHBsaWNpdCBtZXRhZGF0YSBuZWVkZWQgdG8gY3JlYXRlIGFcbiAgICogYE1lc3NhZ2VgLlxuICAgKlxuICAgKiBUaGVyZSBhcmUgdGhyZWUgcG9zc2liaWxpdGllcyBmb3IgdGhlIGBtZXRhYCB2YXJpYWJsZVxuICAgKiAxKSBhIHN0cmluZyBmcm9tIGFuIGBpMThuYCB0ZW1wbGF0ZSBhdHRyaWJ1dGU6IHBhcnNlIGl0IHRvIGV4dHJhY3QgdGhlIG1ldGFkYXRhIHZhbHVlcy5cbiAgICogMikgYSBgTWVzc2FnZWAgZnJvbSBhIHByZXZpb3VzIHByb2Nlc3NpbmcgcGFzczogcmV1c2UgdGhlIG1ldGFkYXRhIHZhbHVlcyBpbiB0aGUgbWVzc2FnZS5cbiAgICogNCkgb3RoZXI6IGlnbm9yZSB0aGlzIGFuZCBqdXN0IHByb2Nlc3MgdGhlIG1lc3NhZ2UgbWV0YWRhdGEgYXMgbm9ybWFsXG4gICAqXG4gICAqIEBwYXJhbSBtZXRhIHRoZSBidWNrZXQgdGhhdCBob2xkcyBpbmZvcm1hdGlvbiBhYm91dCB0aGUgbWVzc2FnZVxuICAgKiBAcmV0dXJucyB0aGUgcGFyc2VkIG1ldGFkYXRhLlxuICAgKi9cbiAgcHJpdmF0ZSBfcGFyc2VNZXRhZGF0YShtZXRhOiBzdHJpbmd8aTE4bi5JMThuTWV0YSk6IEkxOG5NZXRhIHtcbiAgICByZXR1cm4gdHlwZW9mIG1ldGEgPT09ICdzdHJpbmcnID8gcGFyc2VJMThuTWV0YShtZXRhKSA6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldGEgaW5zdGFuY2VvZiBpMThuLk1lc3NhZ2UgPyBtZXRhIDoge307XG4gIH1cblxuICAvKipcbiAgICogR2VuZXJhdGUgKG9yIHJlc3RvcmUpIG1lc3NhZ2UgaWQgaWYgbm90IHNwZWNpZmllZCBhbHJlYWR5LlxuICAgKi9cbiAgcHJpdmF0ZSBfc2V0TWVzc2FnZUlkKG1lc3NhZ2U6IGkxOG4uTWVzc2FnZSwgbWV0YTogc3RyaW5nfGkxOG4uSTE4bk1ldGEpOiB2b2lkIHtcbiAgICBpZiAoIW1lc3NhZ2UuaWQpIHtcbiAgICAgIG1lc3NhZ2UuaWQgPSBtZXRhIGluc3RhbmNlb2YgaTE4bi5NZXNzYWdlICYmIG1ldGEuaWQgfHwgZGVjaW1hbERpZ2VzdChtZXNzYWdlKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVXBkYXRlIHRoZSBgbWVzc2FnZWAgd2l0aCBhIGBsZWdhY3lJZGAgaWYgbmVjZXNzYXJ5LlxuICAgKlxuICAgKiBAcGFyYW0gbWVzc2FnZSB0aGUgbWVzc2FnZSB3aG9zZSBsZWdhY3kgaWQgc2hvdWxkIGJlIHNldFxuICAgKiBAcGFyYW0gbWV0YSBpbmZvcm1hdGlvbiBhYm91dCB0aGUgbWVzc2FnZSBiZWluZyBwcm9jZXNzZWRcbiAgICovXG4gIHByaXZhdGUgX3NldExlZ2FjeUlkcyhtZXNzYWdlOiBpMThuLk1lc3NhZ2UsIG1ldGE6IHN0cmluZ3xpMThuLkkxOG5NZXRhKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuZW5hYmxlSTE4bkxlZ2FjeU1lc3NhZ2VJZEZvcm1hdCkge1xuICAgICAgbWVzc2FnZS5sZWdhY3lJZHMgPSBbY29tcHV0ZURpZ2VzdChtZXNzYWdlKSwgY29tcHV0ZURlY2ltYWxEaWdlc3QobWVzc2FnZSldO1xuICAgIH0gZWxzZSBpZiAodHlwZW9mIG1ldGEgIT09ICdzdHJpbmcnKSB7XG4gICAgICAvLyBUaGlzIG9jY3VycyBpZiB3ZSBhcmUgZG9pbmcgdGhlIDJuZCBwYXNzIGFmdGVyIHdoaXRlc3BhY2UgcmVtb3ZhbCAoc2VlIGBwYXJzZVRlbXBsYXRlKClgIGluXG4gICAgICAvLyBgcGFja2FnZXMvY29tcGlsZXIvc3JjL3JlbmRlcjMvdmlldy90ZW1wbGF0ZS50c2ApLlxuICAgICAgLy8gSW4gdGhhdCBjYXNlIHdlIHdhbnQgdG8gcmV1c2UgdGhlIGxlZ2FjeSBtZXNzYWdlIGdlbmVyYXRlZCBpbiB0aGUgMXN0IHBhc3MgKHNlZVxuICAgICAgLy8gYHNldEkxOG5SZWZzKClgKS5cbiAgICAgIGNvbnN0IHByZXZpb3VzTWVzc2FnZSA9IG1ldGEgaW5zdGFuY2VvZiBpMThuLk1lc3NhZ2UgP1xuICAgICAgICAgIG1ldGEgOlxuICAgICAgICAgIG1ldGEgaW5zdGFuY2VvZiBpMThuLkljdVBsYWNlaG9sZGVyID8gbWV0YS5wcmV2aW91c01lc3NhZ2UgOiB1bmRlZmluZWQ7XG4gICAgICBtZXNzYWdlLmxlZ2FjeUlkcyA9IHByZXZpb3VzTWVzc2FnZSA/IHByZXZpb3VzTWVzc2FnZS5sZWdhY3lJZHMgOiBbXTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIF9yZXBvcnRFcnJvcihub2RlOiBodG1sLk5vZGUsIG1zZzogc3RyaW5nKTogdm9pZCB7XG4gICAgdGhpcy5fZXJyb3JzLnB1c2gobmV3IEkxOG5FcnJvcihub2RlLnNvdXJjZVNwYW4sIG1zZykpO1xuICB9XG59XG5cbi8qKiBJMThuIHNlcGFyYXRvcnMgZm9yIG1ldGFkYXRhICoqL1xuY29uc3QgSTE4Tl9NRUFOSU5HX1NFUEFSQVRPUiA9ICd8JztcbmNvbnN0IEkxOE5fSURfU0VQQVJBVE9SID0gJ0BAJztcblxuLyoqXG4gKiBQYXJzZXMgaTE4biBtZXRhcyBsaWtlOlxuICogIC0gXCJAQGlkXCIsXG4gKiAgLSBcImRlc2NyaXB0aW9uW0BAaWRdXCIsXG4gKiAgLSBcIm1lYW5pbmd8ZGVzY3JpcHRpb25bQEBpZF1cIlxuICogYW5kIHJldHVybnMgYW4gb2JqZWN0IHdpdGggcGFyc2VkIG91dHB1dC5cbiAqXG4gKiBAcGFyYW0gbWV0YSBTdHJpbmcgdGhhdCByZXByZXNlbnRzIGkxOG4gbWV0YVxuICogQHJldHVybnMgT2JqZWN0IHdpdGggaWQsIG1lYW5pbmcgYW5kIGRlc2NyaXB0aW9uIGZpZWxkc1xuICovXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VJMThuTWV0YShtZXRhOiBzdHJpbmcgPSAnJyk6IEkxOG5NZXRhIHtcbiAgbGV0IGN1c3RvbUlkOiBzdHJpbmd8dW5kZWZpbmVkO1xuICBsZXQgbWVhbmluZzogc3RyaW5nfHVuZGVmaW5lZDtcbiAgbGV0IGRlc2NyaXB0aW9uOiBzdHJpbmd8dW5kZWZpbmVkO1xuXG4gIG1ldGEgPSBtZXRhLnRyaW0oKTtcbiAgaWYgKG1ldGEpIHtcbiAgICBjb25zdCBpZEluZGV4ID0gbWV0YS5pbmRleE9mKEkxOE5fSURfU0VQQVJBVE9SKTtcbiAgICBjb25zdCBkZXNjSW5kZXggPSBtZXRhLmluZGV4T2YoSTE4Tl9NRUFOSU5HX1NFUEFSQVRPUik7XG4gICAgbGV0IG1lYW5pbmdBbmREZXNjOiBzdHJpbmc7XG4gICAgW21lYW5pbmdBbmREZXNjLCBjdXN0b21JZF0gPVxuICAgICAgICAoaWRJbmRleCA+IC0xKSA/IFttZXRhLnNsaWNlKDAsIGlkSW5kZXgpLCBtZXRhLnNsaWNlKGlkSW5kZXggKyAyKV0gOiBbbWV0YSwgJyddO1xuICAgIFttZWFuaW5nLCBkZXNjcmlwdGlvbl0gPSAoZGVzY0luZGV4ID4gLTEpID9cbiAgICAgICAgW21lYW5pbmdBbmREZXNjLnNsaWNlKDAsIGRlc2NJbmRleCksIG1lYW5pbmdBbmREZXNjLnNsaWNlKGRlc2NJbmRleCArIDEpXSA6XG4gICAgICAgIFsnJywgbWVhbmluZ0FuZERlc2NdO1xuICB9XG5cbiAgcmV0dXJuIHtjdXN0b21JZCwgbWVhbmluZywgZGVzY3JpcHRpb259O1xufVxuXG4vLyBDb252ZXJ0cyBpMThuIG1ldGEgaW5mb3JtYXRpb24gZm9yIGEgbWVzc2FnZSAoaWQsIGRlc2NyaXB0aW9uLCBtZWFuaW5nKVxuLy8gdG8gYSBKc0RvYyBzdGF0ZW1lbnQgZm9ybWF0dGVkIGFzIGV4cGVjdGVkIGJ5IHRoZSBDbG9zdXJlIGNvbXBpbGVyLlxuZXhwb3J0IGZ1bmN0aW9uIGkxOG5NZXRhVG9KU0RvYyhtZXRhOiBJMThuTWV0YSk6IG8uSlNEb2NDb21tZW50fG51bGwge1xuICBjb25zdCB0YWdzOiBvLkpTRG9jVGFnW10gPSBbXTtcbiAgaWYgKG1ldGEuZGVzY3JpcHRpb24pIHtcbiAgICB0YWdzLnB1c2goe3RhZ05hbWU6IG8uSlNEb2NUYWdOYW1lLkRlc2MsIHRleHQ6IG1ldGEuZGVzY3JpcHRpb259KTtcbiAgfVxuICBpZiAobWV0YS5tZWFuaW5nKSB7XG4gICAgdGFncy5wdXNoKHt0YWdOYW1lOiBvLkpTRG9jVGFnTmFtZS5NZWFuaW5nLCB0ZXh0OiBtZXRhLm1lYW5pbmd9KTtcbiAgfVxuICByZXR1cm4gdGFncy5sZW5ndGggPT0gMCA/IG51bGwgOiBvLmpzRG9jQ29tbWVudCh0YWdzKTtcbn1cbiJdfQ== |
---|