PageSourceSearch

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

js cudi.edu.mx collected 2026-10-02 03:32:09 UTC 13,589 bytes, 315 lines download raw bytes

1/// BareSpecifier=lit-html/lib/shady-render
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 * Module to add shady DOM/shady CSS polyfill support to lit-html template
19 * rendering. See the [[render]] method for details.
20 *
21 * @packageDocumentation
22 */
23
24/**
25 * Do not remove this comment; it keeps typedoc from misplacing the module
26 * docs.
27 */
28import { removeNodes } from "./dom.js?version=aa97bd14";
29import { insertNodeIntoTemplate, removeNodesFromTemplate } from "./modify-template.js?version=aa97bd14";
30import { parts, render as litRender } from "./render.js?version=aa97bd14";
31import { templateCaches } from "./template-factory.js?version=aa97bd14";
32import { TemplateInstance } from "./template-instance.js?version=aa97bd14";
33import { marker, Template } from "./template.js?version=aa97bd14";
34export { html, svg, TemplateResult } from "../lit-html.js?version=aa97bd14"; // Get a key to lookup in `templateCaches`.
35
36const getTemplateCacheKey = (type, scopeName) => `${type}--${scopeName}`;
37
38let compatibleShadyCSSVersion = true;
39
40if (typeof window.ShadyCSS === 'undefined') {
41  compatibleShadyCSSVersion = false;
42} else if (typeof window.ShadyCSS.prepareTemplateDom === 'undefined') {
43  console.warn(`Incompatible ShadyCSS version detected. ` + `Please update to at least @webcomponents/[email protected] and ` + `@webcomponents/[email protected].`);
44  compatibleShadyCSSVersion = false;
45}
46/**
47 * Template factory which scopes template DOM using ShadyCSS.
48 * @param scopeName {string}
49 */
50
51
52export const shadyTemplateFactory = scopeName => result => {
53  const cacheKey = getTemplateCacheKey(result.type, scopeName);
54  let templateCache = templateCaches.get(cacheKey);
55
56  if (templateCache === undefined) {
57    templateCache = {
58      stringsArray: new WeakMap(),
59      keyString: new Map()
60    };
61    templateCaches.set(cacheKey, templateCache);
62  }
63
64  let template = templateCache.stringsArray.get(result.strings);
65
66  if (template !== undefined) {
67    return template;
68  }
69
70  const key = result.strings.join(marker);
71  template = templateCache.keyString.get(key);
72
73  if (template === undefined) {
74    const element = result.getTemplateElement();
75
76    if (compatibleShadyCSSVersion) {
77      window.ShadyCSS.prepareTemplateDom(element, scopeName);
78    }
79
80    template = new Template(result, element);
81    templateCache.keyString.set(key, template);
82  }
83
84  templateCache.stringsArray.set(result.strings, template);
85  return template;
86};
87const TEMPLATE_TYPES = ['html', 'svg'];
88/**
89 * Removes all style elements from Templates for the given scopeName.
90 */
91
92const removeStylesFromLitTemplates = scopeName => {
93  TEMPLATE_TYPES.forEach(type => {
94    const templates = templateCaches.get(getTemplateCacheKey(type, scopeName));
95
96    if (templates !== undefined) {
97      templates.keyString.forEach(template => {
98        const {
99          element: {
100            content
101          }
102        } = template; // IE 11 doesn't support the iterable param Set constructor
103
104        const styles = new Set();
105        Array.from(content.querySelectorAll('style')).forEach(s => {
106          styles.add(s);
107        });
108        removeNodesFromTemplate(template, styles);
109      });
110    }
111  });
112};
113
114const shadyRenderSet = new Set();
115/**
116 * For the given scope name, ensures that ShadyCSS style scoping is performed.
117 * This is done just once per scope name so the fragment and template cannot
118 * be modified.
119 * (1) extracts styles from the rendered fragment and hands them to ShadyCSS
120 * to be scoped and appended to the document
121 * (2) removes style elements from all lit-html Templates for this scope name.
122 *
123 * Note, <style> elements can only be placed into templates for the
124 * initial rendering of the scope. If <style> elements are included in templates
125 * dynamically rendered to the scope (after the first scope render), they will
126 * not be scoped and the <style> will be left in the template and rendered
127 * output.
128 */
129
130const prepareTemplateStyles = (scopeName, renderedDOM, template) => {
131  shadyRenderSet.add(scopeName); // If `renderedDOM` is stamped from a Template, then we need to edit that
132  // Template's underlying template element. Otherwise, we create one here
133  // to give to ShadyCSS, which still requires one while scoping.
134
135  const templateElement = !!template ? template.element : document.createElement('template'); // Move styles out of rendered DOM and store.
136
137  const styles = renderedDOM.querySelectorAll('style');
138  const {
139    length
140  } = styles; // If there are no styles, skip unnecessary work
141
142  if (length === 0) {
143    // Ensure prepareTemplateStyles is called to support adding
144    // styles via `prepareAdoptedCssText` since that requires that
145    // `prepareTemplateStyles` is called.
146    //
147    // ShadyCSS will only update styles containing @apply in the template
148    // given to `prepareTemplateStyles`. If no lit Template was given,
149    // ShadyCSS will not be able to update uses of @apply in any relevant
150    // template. However, this is not a problem because we only create the
151    // template for the purpose of supporting `prepareAdoptedCssText`,
152    // which doesn't support @apply at all.
153    window.ShadyCSS.prepareTemplateStyles(templateElement, scopeName);
154    return;
155  }
156
157  const condensedStyle = document.createElement('style'); // Collect styles into a single style. This helps us make sure ShadyCSS
158  // manipulations will not prevent us from being able to fix up template
159  // part indices.
160  // NOTE: collecting styles is inefficient for browsers but ShadyCSS
161  // currently does this anyway. When it does not, this should be changed.
162
163  for (let i = 0; i < length; i++) {
164    const style = styles[i];
165    style.parentNode.removeChild(style);
166    condensedStyle.textContent += style.textContent;
167  } // Remove styles from nested templates in this scope.
168
169
170  removeStylesFromLitTemplates(scopeName); // And then put the condensed style into the "root" template passed in as
171  // `template`.
172
173  const content = templateElement.content;
174
175  if (!!template) {
176    insertNodeIntoTemplate(template, condensedStyle, content.firstChild);
177  } else {
178    content.insertBefore(condensedStyle, content.firstChild);
179  } // Note, it's important that ShadyCSS gets the template that `lit-html`
180  // will actually render so that it can update the style inside when
181  // needed (e.g. @apply native Shadow DOM case).
182
183
184  window.ShadyCSS.prepareTemplateStyles(templateElement, scopeName);
185  const style = content.querySelector('style');
186
187  if (window.ShadyCSS.nativeShadow && style !== null) {
188    // When in native Shadow DOM, ensure the style created by ShadyCSS is
189    // included in initially rendered output (`renderedDOM`).
190    renderedDOM.insertBefore(style.cloneNode(true), renderedDOM.firstChild);
191  } else if (!!template) {
192    // When no style is left in the template, parts will be broken as a
193    // result. To fix this, we put back the style node ShadyCSS removed
194    // and then tell lit to remove that node from the template.
195    // There can be no style in the template in 2 cases (1) when Shady DOM
196    // is in use, ShadyCSS removes all styles, (2) when native Shadow DOM
197    // is in use ShadyCSS removes the style if it contains no content.
198    // NOTE, ShadyCSS creates its own style so we can safely add/remove
199    // `condensedStyle` here.
200    content.insertBefore(condensedStyle, content.firstChild);
201    const removes = new Set();
202    removes.add(condensedStyle);
203    removeNodesFromTemplate(template, removes);
204  }
205};
206/**
207 * Extension to the standard `render` method which supports rendering
208 * to ShadowRoots when the ShadyDOM (https://github.com/webcomponents/shadydom)
209 * and ShadyCSS (https://github.com/webcomponents/shadycss) polyfills are used
210 * or when the webcomponentsjs
211 * (https://github.com/webcomponents/webcomponentsjs) polyfill is used.
212 *
213 * Adds a `scopeName` option which is used to scope element DOM and stylesheets
214 * when native ShadowDOM is unavailable. The `scopeName` will be added to
215 * the class attribute of all rendered DOM. In addition, any style elements will
216 * be automatically re-written with this `scopeName` selector and moved out
217 * of the rendered DOM and into the document `<head>`.
218 *
219 * It is common to use this render method in conjunction with a custom element
220 * which renders a shadowRoot. When this is done, typically the element's
221 * `localName` should be used as the `scopeName`.
222 *
223 * In addition to DOM scoping, ShadyCSS also supports a basic shim for css
224 * custom properties (needed only on older browsers like IE11) and a shim for
225 * a deprecated feature called `@apply` that supports applying a set of css
226 * custom properties to a given location.
227 *
228 * Usage considerations:
229 *
230 * * Part values in `<style>` elements are only applied the first time a given
231 * `scopeName` renders. Subsequent changes to parts in style elements will have
232 * no effect. Because of this, parts in style elements should only be used for
233 * values that will never change, for example parts that set scope-wide theme
234 * values or parts which render shared style elements.
235 *
236 * * Note, due to a limitation of the ShadyDOM polyfill, rendering in a
237 * custom element's `constructor` is not supported. Instead rendering should
238 * either done asynchronously, for example at microtask timing (for example
239 * `Promise.resolve()`), or be deferred until the first time the element's
240 * `connectedCallback` runs.
241 *
242 * Usage considerations when using shimmed custom properties or `@apply`:
243 *
244 * * Whenever any dynamic changes are made which affect
245 * css custom properties, `ShadyCSS.styleElement(element)` must be called
246 * to update the element. There are two cases when this is needed:
247 * (1) the element is connected to a new parent, (2) a class is added to the
248 * element that causes it to match different custom properties.
249 * To address the first case when rendering a custom element, `styleElement`
250 * should be called in the element's `connectedCallback`.
251 *
252 * * Shimmed custom properties may only be defined either for an entire
253 * shadowRoot (for example, in a `:host` rule) or via a rule that directly
254 * matches an element with a shadowRoot. In other words, instead of flowing from
255 * parent to child as do native css custom properties, shimmed custom properties
256 * flow only from shadowRoots to nested shadowRoots.
257 *
258 * * When using `@apply` mixing css shorthand property names with
259 * non-shorthand names (for example `border` and `border-width`) is not
260 * supported.
261 */
262
263
264export const render = (result, container, options) => {
265  if (!options || typeof options !== 'object' || !options.scopeName) {
266    throw new Error('The `scopeName` option is required.');
267  }
268
269  const scopeName = options.scopeName;
270  const hasRendered = parts.has(container);
271  const needsScoping = compatibleShadyCSSVersion && container.nodeType === 11
272  /* Node.DOCUMENT_FRAGMENT_NODE */
273  && !!container.host; // Handle first render to a scope specially...
274
275  const firstScopeRender = needsScoping && !shadyRenderSet.has(scopeName); // On first scope render, render into a fragment; this cannot be a single
276  // fragment that is reused since nested renders can occur synchronously.
277
278  const renderContainer = firstScopeRender ? document.createDocumentFragment() : container;
279  litRender(result, renderContainer, Object.assign({
280    templateFactory: shadyTemplateFactory(scopeName)
281  }, options)); // When performing first scope render,
282  // (1) We've rendered into a fragment so that there's a chance to
283  // `prepareTemplateStyles` before sub-elements hit the DOM
284  // (which might cause them to render based on a common pattern of
285  // rendering in a custom element's `connectedCallback`);
286  // (2) Scope the template with ShadyCSS one time only for this scope.
287  // (3) Render the fragment into the container and make sure the
288  // container knows its `part` is the one we just rendered. This ensures
289  // DOM will be re-used on subsequent renders.
290
291  if (firstScopeRender) {
292    const part = parts.get(renderContainer);
293    parts.delete(renderContainer); // ShadyCSS might have style sheets (e.g. from `prepareAdoptedCssText`)
294    // that should apply to `renderContainer` even if the rendered value is
295    // not a TemplateInstance. However, it will only insert scoped styles
296    // into the document if `prepareTemplateStyles` has already been called
297    // for the given scope name.
298
299    const template = part.value instanceof TemplateInstance ? part.value.template : undefined;
300    prepareTemplateStyles(scopeName, renderContainer, template);
301    removeNodes(container, container.firstChild);
302    container.appendChild(renderContainer);
303    parts.set(container, part);
304  } // After elements have hit the DOM, update styling if this is the
305  // initial render to this container.
306  // This is needed whenever dynamic changes are made so it would be
307  // safest to do every render; however, this would regress performance
308  // so we leave it up to the user to call `ShadyCSS.styleElement`
309  // for dynamic changes.
310
311
312  if (!hasRendered && needsScoping) {
313    window.ShadyCSS.styleElement(container.host);
314  }
315};

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.