{"version":3,"file":"polyfill-support.js","sources":["src/polyfill-support.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2017 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\n\n/**\n * lit-html patch to support browsers without native web components.\n *\n * This module should be used in addition to loading the web components\n * polyfills via @webcomponents/webcomponentjs. When using those polyfills\n * support for polyfilled Shadow DOM is automatic via the ShadyDOM polyfill.\n * Scoping classes are added to DOM nodes to facilitate CSS scoping that\n * simulates the style scoping Shadow DOM provides. ShadyDOM does this scoping\n * to all elements added to the DOM. This module provides an important\n * optimization for this process by pre-scoping lit-html template\n * DOM. This means ShadyDOM does not have to scope each instance of the\n * template DOM. Instead, each template is scoped only once.\n *\n * Creating scoped CSS is not covered by this module. It is, however, integrated\n * into the lit-element and @lit/reactive-element packages. See the ShadyCSS docs\n * for how to apply scoping to CSS:\n * https://github.com/webcomponents/polyfills/tree/master/packages/shadycss#usage.\n *\n * @packageDocumentation\n */\n\nexport {};\n\ninterface RenderOptions {\n  readonly renderBefore?: ChildNode | null;\n  scope?: string;\n}\n\ninterface ShadyTemplateResult {\n  strings: TemplateStringsArray;\n  // This property needs to remain unminified.\n  ['_$litType$']?: string;\n}\n\n// Note, this is a dummy type as the full type here is big.\ninterface Directive {\n  __directive?: Directive;\n}\n\ninterface DirectiveParent {\n  _$parent?: DirectiveParent;\n  __directive?: Directive;\n  __directives?: Array<Directive | undefined>;\n}\n\ninterface PatchableChildPartConstructor {\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-misused-new\n  new (...args: any[]): PatchableChildPart;\n}\n\ninterface PatchableChildPart {\n  __directive?: Directive;\n  _$committedValue: unknown;\n  _$startNode: ChildNode;\n  _$endNode: ChildNode | null;\n  options: RenderOptions;\n  _$setValue(value: unknown, directiveParent: DirectiveParent): void;\n  _$getTemplate(result: ShadyTemplateResult): HTMLTemplateElement;\n}\n\ninterface PatchableTemplate {\n  el: HTMLTemplateElement;\n}\n\ninterface PatchableTemplateConstructor {\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-misused-new\n  new (...args: any[]): PatchableTemplate;\n  createElement(html: string, options?: RenderOptions): HTMLTemplateElement;\n}\n\ninterface PatchableTemplateInstance {\n  _$template: PatchableTemplate;\n}\n\n// Scopes that have had styling prepared. Note, must only be done once per\n// scope.\nconst styledScopes: Set<string> = new Set();\n// Map of css per scope. This is collected during first scope render, used when\n// styling is prepared, and then discarded.\nconst scopeCssStore: Map<string, string[]> = new Map();\n\nconst ENABLE_SHADYDOM_NOPATCH = true;\n\n// Note, explicitly use `var` here so that this can be re-defined when\n// bundled.\n// eslint-disable-next-line no-var\nvar DEV_MODE = true;\n\n/**\n * lit-html patches. These properties cannot be renamed.\n * * ChildPart.prototype._$getTemplate\n * * ChildPart.prototype._$setValue\n */\nconst polyfillSupport: NonNullable<typeof litHtmlPolyfillSupport> = (\n  Template: PatchableTemplateConstructor,\n  ChildPart: PatchableChildPartConstructor\n) => {\n  // polyfill-support is only needed if ShadyCSS or the ApplyShim is in use\n  // We test at the point of patching, which makes it safe to load\n  // webcomponentsjs and polyfill-support in either order\n  if (\n    window.ShadyCSS === undefined ||\n    (window.ShadyCSS.nativeShadow && !window.ShadyCSS.ApplyShim)\n  ) {\n    return;\n  }\n\n  // console.log(\n  //   '%c Making lit-html compatible with ShadyDOM/CSS.',\n  //   'color: lightgreen; font-style: italic'\n  // );\n\n  const wrap =\n    ENABLE_SHADYDOM_NOPATCH &&\n    window.ShadyDOM?.inUse &&\n    window.ShadyDOM?.noPatch === true\n      ? window.ShadyDOM!.wrap\n      : (node: Node) => node;\n\n  const needsPrepareStyles = (name: string | undefined) =>\n    name !== undefined && !styledScopes.has(name);\n\n  const cssForScope = (name: string) => {\n    let scopeCss = scopeCssStore.get(name);\n    if (scopeCss === undefined) {\n      scopeCssStore.set(name, (scopeCss = []));\n    }\n    return scopeCss;\n  };\n\n  const prepareStyles = (name: string, template: HTMLTemplateElement) => {\n    // Get styles\n    const scopeCss = cssForScope(name);\n    const hasScopeCss = scopeCss.length !== 0;\n    if (hasScopeCss) {\n      const style = document.createElement('style');\n      style.textContent = scopeCss.join('\\n');\n      // Note, it's important to add the style to the *end* of the template so\n      // it doesn't mess up part indices.\n      template.content.appendChild(style);\n    }\n    // Mark this scope as styled.\n    styledScopes.add(name);\n    // Remove stored data since it's no longer needed.\n    scopeCssStore.delete(name);\n    // ShadyCSS removes scopes and removes the style under ShadyDOM and leaves\n    // it under native Shadow DOM\n    window.ShadyCSS!.prepareTemplateStyles(template, name);\n    // Note, under native Shadow DOM, the style is added to the beginning of the\n    // template. It must be moved to the *end* of the template so it doesn't\n    // mess up part indices.\n    if (hasScopeCss && window.ShadyCSS!.nativeShadow) {\n      // If there were styles but the CSS text was empty, ShadyCSS will\n      // eliminate the style altogether, so the style here could be null\n      const style = template.content.querySelector('style');\n      if (style !== null) {\n        template.content.appendChild(style);\n      }\n    }\n  };\n\n  const scopedTemplateCache = new Map<\n    string | undefined,\n    Map<TemplateStringsArray, PatchableTemplate>\n  >();\n\n  /**\n   * Override to extract style elements from the template\n   * and store all style.textContent in the shady scope data.\n   * Note, it's ok to patch Template since it's only used via ChildPart.\n   */\n  const originalCreateElement = Template.createElement;\n  Template.createElement = function (html: string, options?: RenderOptions) {\n    const element = originalCreateElement.call(Template, html, options);\n    const scope = options?.scope;\n    if (scope !== undefined) {\n      if (!window.ShadyCSS!.nativeShadow) {\n        window.ShadyCSS!.prepareTemplateDom(element, scope);\n      }\n      // Process styles only if this scope is being prepared. Otherwise,\n      // leave styles as is for back compat with Lit1.\n      if (needsPrepareStyles(scope)) {\n        const scopeCss = cssForScope(scope);\n        // Remove styles and store textContent.\n        const styles = element.content.querySelectorAll(\n          'style'\n        ) as NodeListOf<HTMLStyleElement>;\n        // Store the css in this template in the scope css and remove the <style>\n        // from the template _before_ the node-walk captures part indices\n        scopeCss.push(\n          ...Array.from(styles).map((style) => {\n            style.parentNode?.removeChild(style);\n            return style.textContent!;\n          })\n        );\n      }\n    }\n    return element;\n  };\n\n  const renderContainer = document.createDocumentFragment();\n  const renderContainerMarker = document.createComment('');\n\n  const childPartProto = ChildPart.prototype;\n  /**\n   * Patch to apply gathered css via ShadyCSS. This is done only once per scope.\n   */\n  const setValue = childPartProto._$setValue;\n  childPartProto._$setValue = function (\n    this: PatchableChildPart,\n    value: unknown,\n    directiveParent: DirectiveParent = this\n  ) {\n    const container = wrap(this._$startNode).parentNode!;\n    const scope = this.options?.scope;\n    if (container instanceof ShadowRoot && needsPrepareStyles(scope)) {\n      // Note, @apply requires outer => inner scope rendering on initial\n      // scope renders to apply property values correctly. Style preparation\n      // is tied to rendering into `shadowRoot`'s and this is typically done by\n      // custom elements. If this is done in `connectedCallback`, as is typical,\n      // the code below ensures the right order since content is rendered\n      // into a fragment first so the hosting element can prepare styles first.\n      // If rendering is done in the constructor, this won't work, but that's\n      // not supported in ShadyDOM anyway.\n      const startNode = this._$startNode;\n      const endNode = this._$endNode;\n\n      // Temporarily move this part into the renderContainer.\n      renderContainer.appendChild(renderContainerMarker);\n      this._$startNode = renderContainerMarker;\n      this._$endNode = null;\n\n      // Note, any nested template results render here and their styles will\n      // be extracted and collected.\n      setValue.call(this, value, directiveParent);\n\n      // Get the template for this result or create a dummy one if a result\n      // is not being rendered.\n      // This property needs to remain unminified.\n      const template = (value as ShadyTemplateResult)?.['_$litType$']\n        ? (this._$committedValue as PatchableTemplateInstance)._$template.el\n        : document.createElement('template');\n      prepareStyles(scope!, template);\n\n      // Note, this is the temporary startNode.\n      renderContainer.removeChild(renderContainerMarker);\n      // When using native Shadow DOM, include prepared style in shadowRoot.\n      if (window.ShadyCSS?.nativeShadow) {\n        const style = template.content.querySelector('style');\n        if (style !== null) {\n          renderContainer.appendChild(style.cloneNode(true));\n        }\n      }\n      container.insertBefore(renderContainer, endNode);\n      // Move part back to original container.\n      this._$startNode = startNode;\n      this._$endNode = endNode;\n    } else {\n      setValue.call(this, value, directiveParent);\n    }\n  };\n\n  /**\n   * Patch ChildPart._$getTemplate to look up templates in a cache bucketed\n   * by element name.\n   */\n  childPartProto._$getTemplate = function (\n    this: PatchableChildPart,\n    result: ShadyTemplateResult\n  ) {\n    const scope = this.options?.scope;\n    let templateCache = scopedTemplateCache.get(scope);\n    if (templateCache === undefined) {\n      scopedTemplateCache.set(scope, (templateCache = new Map()));\n    }\n    let template = templateCache.get(result.strings);\n    if (template === undefined) {\n      templateCache.set(\n        result.strings,\n        (template = new Template(result, this.options))\n      );\n    }\n    return template;\n  };\n};\n\nif (ENABLE_SHADYDOM_NOPATCH) {\n  polyfillSupport.noPatchSupported = ENABLE_SHADYDOM_NOPATCH;\n}\n\nif (DEV_MODE) {\n  globalThis.litHtmlPolyfillSupportDevMode ??= polyfillSupport;\n} else {\n  globalThis.litHtmlPolyfillSupport ??= polyfillSupport;\n}\n"],"names":["styledScopes","Set","scopeCssStore","Map","_b","globalThis","litHtmlPolyfillSupport","Template","ChildPart","undefined","window","ShadyCSS","nativeShadow","ApplyShim","needsPrepareStyles","name","has","cssForScope","scopeCss","get","set","scopedTemplateCache","originalCreateElement","createElement","html","options","element","call","scope","prepareTemplateDom","styles","content","querySelectorAll","push","apply","Array","from","map","style","_a","parentNode","removeChild","textContent","renderContainer","document","createDocumentFragment","renderContainerMarker","createComment","childPartProto","prototype","setValue","_$setValue","value","directiveParent","this","container","_$startNode","ShadowRoot","startNode","endNode","_$endNode","appendChild","template","_$committedValue","_$template","el","hasScopeCss","length","join","add","delete","prepareTemplateStyles","querySelector","prepareStyles","cloneNode","insertBefore","_$getTemplate","result","templateCache","strings"],"mappings":"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"}