UNPKG

9.08 kBJavaScriptView Raw
1/**
2 * @license
3 * Copyright 2017 Google LLC
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6var _a, _b;
7// Scopes that have had styling prepared. Note, must only be done once per
8// scope.
9var styledScopes = new Set();
10// Map of css per scope. This is collected during first scope render, used when
11// styling is prepared, and then discarded.
12var scopeCssStore = new Map();
13var ENABLE_SHADYDOM_NOPATCH = true;
14// Note, explicitly use `var` here so that this can be re-defined when
15// bundled.
16// eslint-disable-next-line no-var
17var DEV_MODE = true;
18/**
19 * lit-html patches. These properties cannot be renamed.
20 * * ChildPart.prototype._$getTemplate
21 * * ChildPart.prototype._$setValue
22 */
23var polyfillSupport = function (Template, ChildPart) {
24 var _a, _b;
25 // polyfill-support is only needed if ShadyCSS or the ApplyShim is in use
26 // We test at the point of patching, which makes it safe to load
27 // webcomponentsjs and polyfill-support in either order
28 if (window.ShadyCSS === undefined ||
29 (window.ShadyCSS.nativeShadow && !window.ShadyCSS.ApplyShim)) {
30 return;
31 }
32 // console.log(
33 // '%c Making lit-html compatible with ShadyDOM/CSS.',
34 // 'color: lightgreen; font-style: italic'
35 // );
36 var wrap = ENABLE_SHADYDOM_NOPATCH &&
37 ((_a = window.ShadyDOM) === null || _a === void 0 ? void 0 : _a.inUse) &&
38 ((_b = window.ShadyDOM) === null || _b === void 0 ? void 0 : _b.noPatch) === true
39 ? window.ShadyDOM.wrap
40 : function (node) { return node; };
41 var needsPrepareStyles = function (name) {
42 return name !== undefined && !styledScopes.has(name);
43 };
44 var cssForScope = function (name) {
45 var scopeCss = scopeCssStore.get(name);
46 if (scopeCss === undefined) {
47 scopeCssStore.set(name, (scopeCss = []));
48 }
49 return scopeCss;
50 };
51 var prepareStyles = function (name, template) {
52 // Get styles
53 var scopeCss = cssForScope(name);
54 var hasScopeCss = scopeCss.length !== 0;
55 if (hasScopeCss) {
56 var style = document.createElement('style');
57 style.textContent = scopeCss.join('\n');
58 // Note, it's important to add the style to the *end* of the template so
59 // it doesn't mess up part indices.
60 template.content.appendChild(style);
61 }
62 // Mark this scope as styled.
63 styledScopes.add(name);
64 // Remove stored data since it's no longer needed.
65 scopeCssStore.delete(name);
66 // ShadyCSS removes scopes and removes the style under ShadyDOM and leaves
67 // it under native Shadow DOM
68 window.ShadyCSS.prepareTemplateStyles(template, name);
69 // Note, under native Shadow DOM, the style is added to the beginning of the
70 // template. It must be moved to the *end* of the template so it doesn't
71 // mess up part indices.
72 if (hasScopeCss && window.ShadyCSS.nativeShadow) {
73 // If there were styles but the CSS text was empty, ShadyCSS will
74 // eliminate the style altogether, so the style here could be null
75 var style = template.content.querySelector('style');
76 if (style !== null) {
77 template.content.appendChild(style);
78 }
79 }
80 };
81 var scopedTemplateCache = new Map();
82 /**
83 * Override to extract style elements from the template
84 * and store all style.textContent in the shady scope data.
85 * Note, it's ok to patch Template since it's only used via ChildPart.
86 */
87 var originalCreateElement = Template.createElement;
88 Template.createElement = function (html, options) {
89 var element = originalCreateElement.call(Template, html, options);
90 var scope = options === null || options === void 0 ? void 0 : options.scope;
91 if (scope !== undefined) {
92 if (!window.ShadyCSS.nativeShadow) {
93 window.ShadyCSS.prepareTemplateDom(element, scope);
94 }
95 // Process styles only if this scope is being prepared. Otherwise,
96 // leave styles as is for back compat with Lit1.
97 if (needsPrepareStyles(scope)) {
98 var scopeCss = cssForScope(scope);
99 // Remove styles and store textContent.
100 var styles = element.content.querySelectorAll('style');
101 // Store the css in this template in the scope css and remove the <style>
102 // from the template _before_ the node-walk captures part indices
103 scopeCss.push.apply(scopeCss, Array.from(styles).map(function (style) {
104 var _a;
105 (_a = style.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(style);
106 return style.textContent;
107 }));
108 }
109 }
110 return element;
111 };
112 var renderContainer = document.createDocumentFragment();
113 var renderContainerMarker = document.createComment('');
114 var childPartProto = ChildPart.prototype;
115 /**
116 * Patch to apply gathered css via ShadyCSS. This is done only once per scope.
117 */
118 var setValue = childPartProto._$setValue;
119 childPartProto._$setValue = function (value, directiveParent) {
120 var _a, _b;
121 if (directiveParent === void 0) { directiveParent = this; }
122 var container = wrap(this._$startNode).parentNode;
123 var scope = (_a = this.options) === null || _a === void 0 ? void 0 : _a.scope;
124 if (container instanceof ShadowRoot && needsPrepareStyles(scope)) {
125 // Note, @apply requires outer => inner scope rendering on initial
126 // scope renders to apply property values correctly. Style preparation
127 // is tied to rendering into `shadowRoot`'s and this is typically done by
128 // custom elements. If this is done in `connectedCallback`, as is typical,
129 // the code below ensures the right order since content is rendered
130 // into a fragment first so the hosting element can prepare styles first.
131 // If rendering is done in the constructor, this won't work, but that's
132 // not supported in ShadyDOM anyway.
133 var startNode = this._$startNode;
134 var endNode = this._$endNode;
135 // Temporarily move this part into the renderContainer.
136 renderContainer.appendChild(renderContainerMarker);
137 this._$startNode = renderContainerMarker;
138 this._$endNode = null;
139 // Note, any nested template results render here and their styles will
140 // be extracted and collected.
141 setValue.call(this, value, directiveParent);
142 // Get the template for this result or create a dummy one if a result
143 // is not being rendered.
144 // This property needs to remain unminified.
145 var template = (value === null || value === void 0 ? void 0 : value['_$litType$'])
146 ? this._$committedValue._$template.el
147 : document.createElement('template');
148 prepareStyles(scope, template);
149 // Note, this is the temporary startNode.
150 renderContainer.removeChild(renderContainerMarker);
151 // When using native Shadow DOM, include prepared style in shadowRoot.
152 if ((_b = window.ShadyCSS) === null || _b === void 0 ? void 0 : _b.nativeShadow) {
153 var style = template.content.querySelector('style');
154 if (style !== null) {
155 renderContainer.appendChild(style.cloneNode(true));
156 }
157 }
158 container.insertBefore(renderContainer, endNode);
159 // Move part back to original container.
160 this._$startNode = startNode;
161 this._$endNode = endNode;
162 }
163 else {
164 setValue.call(this, value, directiveParent);
165 }
166 };
167 /**
168 * Patch ChildPart._$getTemplate to look up templates in a cache bucketed
169 * by element name.
170 */
171 childPartProto._$getTemplate = function (result) {
172 var _a;
173 var scope = (_a = this.options) === null || _a === void 0 ? void 0 : _a.scope;
174 var templateCache = scopedTemplateCache.get(scope);
175 if (templateCache === undefined) {
176 scopedTemplateCache.set(scope, (templateCache = new Map()));
177 }
178 var template = templateCache.get(result.strings);
179 if (template === undefined) {
180 templateCache.set(result.strings, (template = new Template(result, this.options)));
181 }
182 return template;
183 };
184};
185if (ENABLE_SHADYDOM_NOPATCH) {
186 polyfillSupport.noPatchSupported = ENABLE_SHADYDOM_NOPATCH;
187}
188if (DEV_MODE) {
189 (_a = globalThis.litHtmlPolyfillSupportDevMode) !== null && _a !== void 0 ? _a : (globalThis.litHtmlPolyfillSupportDevMode = polyfillSupport);
190}
191else {
192 (_b = globalThis.litHtmlPolyfillSupport) !== null && _b !== void 0 ? _b : (globalThis.litHtmlPolyfillSupport = polyfillSupport);
193}
194export {};
195//# sourceMappingURL=polyfill-support.js.map
\No newline at end of file