PageSourceSearch

https://virtual.cudi.edu.mx/webcomponents/assets/lit-html/lib/template.js?version=aa97bd14

js cudi.edu.mx collected 2026-09-24 18:00:41 UTC 9,325 bytes, 263 lines download raw bytes

1/// BareSpecifier=lit-html/lib/template
2
3/**
4 * @license
5 * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
6 * This code may only be used under the BSD style license found at
7 * http://polymer.github.io/LICENSE.txt
8 * The complete set of authors may be found at
9 * http://polymer.github.io/AUTHORS.txt
10 * The complete set of contributors may be found at
11 * http://polymer.github.io/CONTRIBUTORS.txt
12 * Code distributed by Google as part of the polymer project is also
13 * subject to an additional IP rights grant found at
14 * http://polymer.github.io/PATENTS.txt
15 */
16
17/**
18 * An expression marker with embedded unique key to avoid collision with
19 * possible text in templates.
20 */
21export const marker = `{{lit-${String(Math.random()).slice(2)}}}`;
22/**
23 * An expression marker used text-positions, multi-binding attributes, and
24 * attributes with markup-like text values.
25 */
26
27export const nodeMarker = `<!--${marker}-->`;
28export const markerRegex = new RegExp(`${marker}|${nodeMarker}`);
29/**
30 * Suffix appended to all bound attribute names.
31 */
32
33export const boundAttributeSuffix = '$lit$';
34/**
35 * An updatable Template that tracks the location of dynamic parts.
36 */
37
38export class Template {
39  constructor(result, element) {
40    this.parts = [];
41    this.element = element;
42    const nodesToRemove = [];
43    const stack = []; // Edge needs all 4 parameters present; IE11 needs 3rd parameter to be null
44
45    const walker = document.createTreeWalker(element.content, 133
46    /* NodeFilter.SHOW_{ELEMENT|COMMENT|TEXT} */
47    , null, false); // Keeps track of the last index associated with a part. We try to delete
48    // unnecessary nodes, but we never want to associate two different parts
49    // to the same index. They must have a constant node between.
50
51    let lastPartIndex = 0;
52    let index = -1;
53    let partIndex = 0;
54    const {
55      strings,
56      values: {
57        length
58      }
59    } = result;
60
61    while (partIndex < length) {
62      const node = walker.nextNode();
63
64      if (node === null) {
65        // We've exhausted the content inside a nested template element.
66        // Because we still have parts (the outer for-loop), we know:
67        // - There is a template in the stack
68        // - The walker will find a nextNode outside the template
69        walker.currentNode = stack.pop();
70        continue;
71      }
72
73      index++;
74
75      if (node.nodeType === 1
76      /* Node.ELEMENT_NODE */
77      ) {
78          if (node.hasAttributes()) {
79            const attributes = node.attributes;
80            const {
81              length
82            } = attributes; // Per
83            // https://developer.mozilla.org/en-US/docs/Web/API/NamedNodeMap,
84            // attributes are not guaranteed to be returned in document order.
85            // In particular, Edge/IE can return them out of order, so we cannot
86            // assume a correspondence between part index and attribute index.
87
88            let count = 0;
89
90            for (let i = 0; i < length; i++) {
91              if (endsWith(attributes[i].name, boundAttributeSuffix)) {
92                count++;
93              }
94            }
95
96            while (count-- > 0) {
97              // Get the template literal section leading up to the first
98              // expression in this attribute
99              const stringForPart = strings[partIndex]; // Find the attribute name
100
101              const name = lastAttributeNameRegex.exec(stringForPart)[2]; // Find the corresponding attribute
102              // All bound attributes have had a suffix added in
103              // TemplateResult#getHTML to opt out of special attribute
104              // handling. To look up the attribute value we also need to add
105              // the suffix.
106
107              const attributeLookupName = name.toLowerCase() + boundAttributeSuffix;
108              const attributeValue = node.getAttribute(attributeLookupName);
109              node.removeAttribute(attributeLookupName);
110              const statics = attributeValue.split(markerRegex);
111              this.parts.push({
112                type: 'attribute',
113                index,
114                name,
115                strings: statics
116              });
117              partIndex += statics.length - 1;
118            }
119          }
120
121          if (node.tagName === 'TEMPLATE') {
122            stack.push(node);
123            walker.currentNode = node.content;
124          }
125        } else if (node.nodeType === 3
126      /* Node.TEXT_NODE */
127      ) {
128          const data = node.data;
129
130          if (data.indexOf(marker) >= 0) {
131            const parent = node.parentNode;
132            const strings = data.split(markerRegex);
133            const lastIndex = strings.length - 1; // Generate a new text node for each literal section
134            // These nodes are also used as the markers for node parts
135
136            for (let i = 0; i < lastIndex; i++) {
137              let insert;
138              let s = strings[i];
139
140              if (s === '') {
141                insert = createMarker();
142              } else {
143                const match = lastAttributeNameRegex.exec(s);
144
145                if (match !== null && endsWith(match[2], boundAttributeSuffix)) {
146                  s = s.slice(0, match.index) + match[1] + match[2].slice(0, -boundAttributeSuffix.length) + match[3];
147                }
148
149                insert = document.createTextNode(s);
150              }
151
152              parent.insertBefore(insert, node);
153              this.parts.push({
154                type: 'node',
155                index: ++index
156              });
157            } // If there's no text, we must insert a comment to mark our place.
158            // Else, we can trust it will stick around after cloning.
159
160
161            if (strings[lastIndex] === '') {
162              parent.insertBefore(createMarker(), node);
163              nodesToRemove.push(node);
164            } else {
165              node.data = strings[lastIndex];
166            } // We have a part for each match found
167
168
169            partIndex += lastIndex;
170          }
171        } else if (node.nodeType === 8
172      /* Node.COMMENT_NODE */
173      ) {
174          if (node.data === marker) {
175            const parent = node.parentNode; // Add a new marker node to be the startNode of the Part if any of
176            // the following are true:
177            //  * We don't have a previousSibling
178            //  * The previousSibling is already the start of a previous part
179
180            if (node.previousSibling === null || index === lastPartIndex) {
181              index++;
182              parent.insertBefore(createMarker(), node);
183            }
184
185            lastPartIndex = index;
186            this.parts.push({
187              type: 'node',
188              index
189            }); // If we don't have a nextSibling, keep this node so we have an end.
190            // Else, we can remove it to save future costs.
191
192            if (node.nextSibling === null) {
193              node.data = '';
194            } else {
195              nodesToRemove.push(node);
196              index--;
197            }
198
199            partIndex++;
200          } else {
201            let i = -1;
202
203            while ((i = node.data.indexOf(marker, i + 1)) !== -1) {
204              // Comment node has a binding marker inside, make an inactive part
205              // The binding won't work, but subsequent bindings will
206              // TODO (justinfagnani): consider whether it's even worth it to
207              // make bindings in comments work
208              this.parts.push({
209                type: 'node',
210                index: -1
211              });
212              partIndex++;
213            }
214          }
215        }
216    } // Remove text binding nodes after the walk to not disturb the TreeWalker
217
218
219    for (const n of nodesToRemove) {
220      n.parentNode.removeChild(n);
221    }
222  }
223
224}
225
226const endsWith = (str, suffix) => {
227  const index = str.length - suffix.length;
228  return index >= 0 && str.slice(index) === suffix;
229};
230
231export const isTemplatePartActive = part => part.index !== -1; // Allows `document.createComment('')` to be renamed for a
232// small manual size-savings.
233
234export const createMarker = () => document.createComment('');
235/**
236 * This regex extracts the attribute name preceding an attribute-position
237 * expression. It does this by matching the syntax allowed for attributes
238 * against the string literal directly preceding the expression, assuming that
239 * the expression is in an attribute-value position.
240 *
241 * See attributes in the HTML spec:
242 * https://www.w3.org/TR/html5/syntax.html#elements-attributes
243 *
244 * " \x09\x0a\x0c\x0d" are HTML space characters:
245 * https://www.w3.org/TR/html5/infrastructure.html#space-characters
246 *
247 * "\0-\x1F\x7F-\x9F" are Unicode control characters, which includes every
248 * space character except " ".
249 *
250 * So an attribute is:
251 *  * The name: any character except a control character, space character, ('),
252 *    ("), ">", "=", or "/"
253 *  * Followed by zero or more space characters
254 *  * Followed by "="
255 *  * Followed by zero or more space characters
256 *  * Followed by:
257 *    * Any character except space, ('), ("), "<", ">", "=", (`), or
258 *    * (") then any non-("), or
259 *    * (') then any non-(')
260 */
261
262export const lastAttributeNameRegex = // eslint-disable-next-line no-control-regex
263/([ \x09\x0a\x0c\x0d])([^\0-\x1F\x7F-\x9F "'>=/]+)([ \x09\x0a\x0c\x0d]*=[ \x09\x0a\x0c\x0d]*(?:[^ \x09\x0a\x0c\x0d"'`<>=]*|"[^"]*|'[^']*))$/;

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.