From 6c0c12c90aead86ddd5722437cad1f3faa9204c7 Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Fri, 16 Oct 2020 16:30:38 +0200 Subject: [PATCH] static: fix messages update only working once --- passbook/admin/api/tasks.py | 2 +- passbook/static/static/passbook/passbook.js | 6 +++--- .../static/static/passbook/passbook.js.map | 2 +- passbook/static/static/src/ActionButton.js | 3 ++- passbook/static/static/src/Messages.js | 20 ++++++++++++------- 5 files changed, 20 insertions(+), 13 deletions(-) diff --git a/passbook/admin/api/tasks.py b/passbook/admin/api/tasks.py index ccb40db06..b0c752747 100644 --- a/passbook/admin/api/tasks.py +++ b/passbook/admin/api/tasks.py @@ -53,7 +53,7 @@ class TaskViewSet(ViewSet): task_module = import_module(task.task_call_module) task_func = getattr(task_module, task.task_call_func) task_func.delay(*task.task_call_args, **task.task_call_kwargs) - messages.success(self.request, _("Successfully re-scheduled Task!")) + messages.success(self.request, _("Successfully re-scheduled Task %(name)s!" % {'name': task.task_name})) return Response( { "successful": True, diff --git a/passbook/static/static/passbook/passbook.js b/passbook/static/static/passbook/passbook.js index 5e5feb7ee..4c8168d58 100644 --- a/passbook/static/static/passbook/passbook.js +++ b/passbook/static/static/passbook/passbook.js @@ -65,7 +65,7 @@ class y{constructor(e,t,s){this.__parts=[],this.template=e,this.processor=t,this * Code distributed by Google as part of the polymer project is also * subject to an additional IP rights grant found at * http://polymer.github.io/PATENTS.txt - */const b=e=>null===e||!("object"==typeof e||"function"==typeof e),x=e=>Array.isArray(e)||!(!e||!e[Symbol.iterator]);class P{constructor(e,t,s){this.dirty=!0,this.element=e,this.name=t,this.strings=s,this.parts=[];for(let e=0;e{try{const e={get capture(){return k=!0,!1}};window.addEventListener("test",e,e),window.removeEventListener("test",e,e)}catch(e){}})();class V{constructor(e,t,s){this.value=void 0,this.__pendingValue=void 0,this.element=e,this.eventName=t,this.eventContext=s,this.__boundHandleEvent=e=>this.handleEvent(e)}setValue(e){this.__pendingValue=e}commit(){for(;f(this.__pendingValue);){const e=this.__pendingValue;this.__pendingValue=_,e(this)}if(this.__pendingValue===_)return;const e=this.__pendingValue,t=this.value,s=null==e||null!=t&&(e.capture!==t.capture||e.once!==t.once||e.passive!==t.passive),n=null!=e&&(null==t||s);s&&this.element.removeEventListener(this.eventName,this.__boundHandleEvent,this.__options),n&&(this.__options=q(e),this.element.addEventListener(this.eventName,this.__boundHandleEvent,this.__options)),this.value=e,this.__pendingValue=_}handleEvent(e){"function"==typeof this.value?this.value.call(this.eventContext||this.element,e):this.value.handleEvent(e)}}const q=e=>e&&(k?{capture:e.capture,passive:e.passive,once:e.once}:e.capture) + */const b=e=>null===e||!("object"==typeof e||"function"==typeof e),x=e=>Array.isArray(e)||!(!e||!e[Symbol.iterator]);class P{constructor(e,t,s){this.dirty=!0,this.element=e,this.name=t,this.strings=s,this.parts=[];for(let e=0;e{try{const e={get capture(){return k=!0,!1}};window.addEventListener("test",e,e),window.removeEventListener("test",e,e)}catch(e){}})();class V{constructor(e,t,s){this.value=void 0,this.__pendingValue=void 0,this.element=e,this.eventName=t,this.eventContext=s,this.__boundHandleEvent=e=>this.handleEvent(e)}setValue(e){this.__pendingValue=e}commit(){for(;f(this.__pendingValue);){const e=this.__pendingValue;this.__pendingValue=_,e(this)}if(this.__pendingValue===_)return;const e=this.__pendingValue,t=this.value,s=null==e||null!=t&&(e.capture!==t.capture||e.once!==t.once||e.passive!==t.passive),n=null!=e&&(null==t||s);s&&this.element.removeEventListener(this.eventName,this.__boundHandleEvent,this.__options),n&&(this.__options=q(e),this.element.addEventListener(this.eventName,this.__boundHandleEvent,this.__options)),this.value=e,this.__pendingValue=_}handleEvent(e){"function"==typeof this.value?this.value.call(this.eventContext||this.element,e):this.value.handleEvent(e)}}const q=e=>e&&(k?{capture:e.capture,passive:e.passive,once:e.once}:e.capture) /** * @license * Copyright (c) 2017 The Polymer Project Authors. All rights reserved. @@ -105,7 +105,7 @@ class y{constructor(e,t,s){this.__parts=[],this.template=e,this.processor=t,this * subject to an additional IP rights grant found at * http://polymer.github.io/PATENTS.txt */ -class{handleAttributeExpressions(e,t,s,n){const r=t[0];if("."===r){return new A(e,t.slice(1),s).parts}if("@"===r)return[new V(e,t.slice(1),n.eventContext)];if("?"===r)return[new C(e,t.slice(1),s)];return new P(e,t,s).parts}handleTextExpression(e){return new N(e)}}; +class{handleAttributeExpressions(e,t,s,n){const r=t[0];if("."===r){return new A(e,t.slice(1),s).parts}if("@"===r)return[new V(e,t.slice(1),n.eventContext)];if("?"===r)return[new N(e,t.slice(1),s)];return new P(e,t,s).parts}handleTextExpression(e){return new C(e)}}; /** * @license * Copyright (c) 2017 The Polymer Project Authors. All rights reserved. @@ -156,5 +156,5 @@ const X=window.ShadowRoot&&(void 0===window.ShadyCSS||window.ShadyCSS.nativeShad * subject to an additional IP rights grant found at * http://polymer.github.io/PATENTS.txt */ -(window.litElementVersions||(window.litElementVersions=[])).push("2.4.0");const Y={};class Z extends K{static getStyles(){return this.styles}static _getUniqueStyles(){if(this.hasOwnProperty(JSCompiler_renameProperty("_styles",this)))return;const e=this.getStyles();if(Array.isArray(e)){const t=(e,s)=>e.reduceRight(((e,s)=>Array.isArray(s)?t(s,e):(e.add(s),e)),s),s=t(e,new Set),n=[];s.forEach((e=>n.unshift(e))),this._styles=n}else this._styles=void 0===e?[]:[e];this._styles=this._styles.map((e=>{if(e instanceof CSSStyleSheet&&!X){const t=Array.prototype.slice.call(e.cssRules).reduce(((e,t)=>e+t.cssText),"");return new Q(String(t),G)}return e}))}initialize(){super.initialize(),this.constructor._getUniqueStyles(),this.renderRoot=this.createRenderRoot(),window.ShadowRoot&&this.renderRoot instanceof window.ShadowRoot&&this.adoptStyles()}createRenderRoot(){return this.attachShadow({mode:"open"})}adoptStyles(){const e=this.constructor._styles;0!==e.length&&(void 0===window.ShadyCSS||window.ShadyCSS.nativeShadow?X?this.renderRoot.adoptedStyleSheets=e.map((e=>e instanceof CSSStyleSheet?e:e.styleSheet)):this._needsShimAdoptedStyleSheets=!0:window.ShadyCSS.ScopingShim.prepareAdoptedCssText(e.map((e=>e.cssText)),this.localName))}connectedCallback(){super.connectedCallback(),this.hasUpdated&&void 0!==window.ShadyCSS&&window.ShadyCSS.styleElement(this)}update(e){const t=this.render();super.update(e),t!==Y&&this.constructor.render(t,this.renderRoot,{scopeName:this.localName,eventContext:this}),this._needsShimAdoptedStyleSheets&&(this._needsShimAdoptedStyleSheets=!1,this.constructor._styles.forEach((e=>{const t=document.createElement("style");t.textContent=e.cssText,this.renderRoot.appendChild(t)})))}render(){return Y}}Z.finalized=!0,Z.render=(e,s,n)=>{if(!n||"object"!=typeof n||!n.scopeName)throw new Error("The `scopeName` option is required.");const r=n.scopeName,i=R.has(s),o=j&&11===s.nodeType&&!!s.host,a=o&&!B.has(r),l=a?document.createDocumentFragment():s;if(((e,s,n)=>{let r=R.get(s);void 0===r&&(t(s,s.firstChild),R.set(s,r=new N(Object.assign({templateFactory:L},n))),r.appendInto(s)),r.setValue(e),r.commit()})(e,l,Object.assign({templateFactory:F(r)},n)),a){const e=R.get(l);R.delete(l);const n=e.value instanceof y?e.value.template:void 0;H(r,l,n),t(s,s.firstChild),s.appendChild(l),R.set(s,e)}!i&&o&&window.ShadyCSS.styleElement(s.host)};customElements.define("fetch-fill-slot",class extends Z{static get properties(){return{url:{type:String},key:{type:String},value:{type:Number}}}comparison(e){var t={"<":function(e,t){return e":function(e,t){return e>t},">=":function(e,t){return e>=t},"<=":function(e,t){return e<=t},"==":function(e,t){return e==t},"!=":function(e,t){return e!=t},"===":function(e,t){return e===t},"!==":function(e,t){return e!==t}};const s=e.split(" ");if(s.length<3)throw new Error("nah");let n=s[0];n="value"===n?this.value:parseInt(n,10);let r=s[2];r="value"===r?this.value:parseInt(r,10);const i=s[1];if(!(i in t))throw new Error("Invalid comparison");return t[i](n,r)}firstUpdated(){fetch(this.url).then((e=>e.json())).then((e=>e[this.key])).then((e=>this.value=e))}render(){if(void 0===this.value)return M``;let e="";return this.querySelectorAll("[slot]").forEach((t=>{const s=t.getAttribute("slot");this.comparison(s)&&(e=s)})),this.querySelectorAll("[data-value]").forEach((e=>{e.textContent=this.value})),M``}});const ee="pf-m-primary",te=["pf-m-progress","pf-m-in-progress"];class se extends HTMLButtonElement{constructor(){super(),this.addEventListener("click",(e=>this.callAction()))}isRunning=!1;oldBody="";setLoading(){this.classList.add(...te),this.oldBody=this.innerText,this.innerHTML='\n \n \n \n \n \n '+this.oldBody}setDone(e){this.isRunning=!1,this.classList.remove(...te),this.innerText=this.oldBody,this.classList.replace(ee,e),setTimeout((()=>{console.log("test"),this.classList.replace(e,ee)}),1e3)}callAction(){if(!0===this.isRunning)return;this.setLoading();const e=function(e){let t=null;if(document.cookie&&""!==document.cookie){const s=document.cookie.split(";");for(let n=0;ne.json())).then((e=>{this.setDone("pf-m-success")})).catch((()=>{this.setDone("pf-m-danger")}))}}customElements.define("action-button",se,{extends:"button"});const ne={error:"fas fa-exclamation-circle",warning:"fas fa-exclamation-triangle",success:"fas fa-check-circle",info:"fas fa-info"};customElements.define("pb-messages",class extends Z{static get properties(){return{url:{type:String},messages:{type:Array}}}createRenderRoot(){return this}firstUpdated(){fetch(this.url).then((e=>e.json())).then((e=>this.messages=e))}renderMessage(e){const t="pb-message-"+("_"+Math.random().toString(36).substr(2,9)),s=M`
  • ${e.message}

  • `;return setTimeout((()=>{this.querySelector("#"+t).remove()}),1500),s}render(){return void 0===this.messages?M`
      `:M`
        ${this.messages.map((e=>this.renderMessage(e)))}
      `}}),document.querySelectorAll("button.pf-c-dropdown__toggle").forEach((e=>{e.addEventListener("click",(e=>{const t=e.target.closest(".pf-c-dropdown").querySelector(".pf-c-dropdown__menu");t.hidden=!t.hidden}))})),document.querySelectorAll("input[type=search]").forEach((e=>{e.addEventListener("search",(t=>{""===e.value&&e.parentElement.submit()}))})),document.querySelectorAll("[data-pb-fetch-fill]").forEach((e=>{const t=e.dataset.pbFetchFill,s=e.dataset.pbFetchKey;fetch(t).then((e=>e.json())).then((t=>{e.textContent=t[s],e.value=t[s]}))})),document.querySelectorAll("[data-target='modal']").forEach((e=>{e.addEventListener("click",(e=>{const t=e.target.closest('[data-target="modal"]').attributes["data-modal"].value;document.querySelector("#"+t).removeAttribute("hidden")}))})),document.querySelectorAll(".pf-c-modal-box [data-modal-close]").forEach((e=>{e.addEventListener("click",(e=>{e.target.closest(".pf-c-backdrop").setAttribute("hidden",!0)}))})),document.querySelectorAll(".pf-c-check__label").forEach((e=>{e.addEventListener("click",(e=>{const t=e.target.parentElement.querySelector("input[type=checkbox]");t.checked=!t.checked}))})),document.querySelectorAll(".codemirror").forEach((e=>{let t="xml";"data-cm-mode"in e.attributes&&(t=e.attributes["data-cm-mode"].value),e.removeAttribute("required"),CodeMirror.fromTextArea(e,{mode:t,theme:"monokai",lineNumbers:!1,readOnly:e.readOnly,autoRefresh:!0})}));document.querySelectorAll("input[name=name]").forEach((e=>{e.addEventListener("input",(e=>{const t=e.target.closest("form");if(null===t)return;t.querySelector("input[name=slug]").value=e.target.value.toLowerCase().replace(/ /g,"-").replace(/[^\w-]+/g,"")}))})),document.querySelectorAll(".pf-c-page__header-brand-toggle>button").forEach((e=>{e.addEventListener("click",(e=>{const t=document.querySelector(".pf-c-page__sidebar");t.classList.contains("pf-m-expanded")?(t.classList.remove("pf-m-expanded"),t.style.zIndex=0):(t.classList.add("pf-m-expanded"),t.style.zIndex=200)}))})),document.querySelectorAll(".pf-m-expandable>.pf-c-nav__link").forEach((e=>{e.addEventListener("click",(t=>{t.preventDefault(),e.parentElement.classList.toggle("pf-m-expanded")}))}))}(); +(window.litElementVersions||(window.litElementVersions=[])).push("2.4.0");const Y={};class Z extends K{static getStyles(){return this.styles}static _getUniqueStyles(){if(this.hasOwnProperty(JSCompiler_renameProperty("_styles",this)))return;const e=this.getStyles();if(Array.isArray(e)){const t=(e,s)=>e.reduceRight(((e,s)=>Array.isArray(s)?t(s,e):(e.add(s),e)),s),s=t(e,new Set),n=[];s.forEach((e=>n.unshift(e))),this._styles=n}else this._styles=void 0===e?[]:[e];this._styles=this._styles.map((e=>{if(e instanceof CSSStyleSheet&&!X){const t=Array.prototype.slice.call(e.cssRules).reduce(((e,t)=>e+t.cssText),"");return new Q(String(t),G)}return e}))}initialize(){super.initialize(),this.constructor._getUniqueStyles(),this.renderRoot=this.createRenderRoot(),window.ShadowRoot&&this.renderRoot instanceof window.ShadowRoot&&this.adoptStyles()}createRenderRoot(){return this.attachShadow({mode:"open"})}adoptStyles(){const e=this.constructor._styles;0!==e.length&&(void 0===window.ShadyCSS||window.ShadyCSS.nativeShadow?X?this.renderRoot.adoptedStyleSheets=e.map((e=>e instanceof CSSStyleSheet?e:e.styleSheet)):this._needsShimAdoptedStyleSheets=!0:window.ShadyCSS.ScopingShim.prepareAdoptedCssText(e.map((e=>e.cssText)),this.localName))}connectedCallback(){super.connectedCallback(),this.hasUpdated&&void 0!==window.ShadyCSS&&window.ShadyCSS.styleElement(this)}update(e){const t=this.render();super.update(e),t!==Y&&this.constructor.render(t,this.renderRoot,{scopeName:this.localName,eventContext:this}),this._needsShimAdoptedStyleSheets&&(this._needsShimAdoptedStyleSheets=!1,this.constructor._styles.forEach((e=>{const t=document.createElement("style");t.textContent=e.cssText,this.renderRoot.appendChild(t)})))}render(){return Y}}Z.finalized=!0,Z.render=(e,s,n)=>{if(!n||"object"!=typeof n||!n.scopeName)throw new Error("The `scopeName` option is required.");const r=n.scopeName,i=R.has(s),o=j&&11===s.nodeType&&!!s.host,a=o&&!B.has(r),l=a?document.createDocumentFragment():s;if(((e,s,n)=>{let r=R.get(s);void 0===r&&(t(s,s.firstChild),R.set(s,r=new C(Object.assign({templateFactory:L},n))),r.appendInto(s)),r.setValue(e),r.commit()})(e,l,Object.assign({templateFactory:F(r)},n)),a){const e=R.get(l);R.delete(l);const n=e.value instanceof y?e.value.template:void 0;H(r,l,n),t(s,s.firstChild),s.appendChild(l),R.set(s,e)}!i&&o&&window.ShadyCSS.styleElement(s.host)};customElements.define("fetch-fill-slot",class extends Z{static get properties(){return{url:{type:String},key:{type:String},value:{type:Number}}}comparison(e){var t={"<":function(e,t){return e":function(e,t){return e>t},">=":function(e,t){return e>=t},"<=":function(e,t){return e<=t},"==":function(e,t){return e==t},"!=":function(e,t){return e!=t},"===":function(e,t){return e===t},"!==":function(e,t){return e!==t}};const s=e.split(" ");if(s.length<3)throw new Error("nah");let n=s[0];n="value"===n?this.value:parseInt(n,10);let r=s[2];r="value"===r?this.value:parseInt(r,10);const i=s[1];if(!(i in t))throw new Error("Invalid comparison");return t[i](n,r)}firstUpdated(){fetch(this.url).then((e=>e.json())).then((e=>e[this.key])).then((e=>this.value=e))}render(){if(void 0===this.value)return M``;let e="";return this.querySelectorAll("[slot]").forEach((t=>{const s=t.getAttribute("slot");this.comparison(s)&&(e=s)})),this.querySelectorAll("[data-value]").forEach((e=>{e.textContent=this.value})),M``}});const ee="pf-m-primary",te=["pf-m-progress","pf-m-in-progress"];class se extends HTMLButtonElement{constructor(){super(),this.addEventListener("click",(e=>this.callAction()))}isRunning=!1;oldBody="";setLoading(){this.classList.add(...te),this.oldBody=this.innerText,this.innerHTML='\n \n \n \n \n \n '+this.oldBody}setDone(e){this.isRunning=!1,this.classList.remove(...te),this.innerText=this.oldBody,this.classList.replace(ee,e),document.querySelector("pb-messages").setAttribute("touch",Date.now()),setTimeout((()=>{this.classList.replace(e,ee)}),1e3)}callAction(){if(!0===this.isRunning)return;this.setLoading();const e=function(e){let t=null;if(document.cookie&&""!==document.cookie){const s=document.cookie.split(";");for(let n=0;ne.json())).then((e=>{this.setDone("pf-m-success")})).catch((()=>{this.setDone("pf-m-danger")}))}}customElements.define("action-button",se,{extends:"button"});const ne={error:"fas fa-exclamation-circle",warning:"fas fa-exclamation-triangle",success:"fas fa-check-circle",info:"fas fa-info"};customElements.define("pb-messages",class extends Z{static get properties(){return{url:{type:String},messages:{type:Array},touch:{type:Object}}}set touch(e){this.firstUpdated()}createRenderRoot(){return this}firstUpdated(){return fetch(this.url).then((e=>e.json())).then((e=>this.messages=e))}renderMessage(e){const t="pb-message"+Math.random().toString(36).substr(2,9);const s=document.createElement("template");return s.innerHTML=`
    • \n
      \n
      \n \n
      \n

      \n ${e.message}\n

      \n
      \n
    • `,setTimeout((()=>{this.querySelector("#"+t).remove()}),1500),s.content.firstChild}render(){return void 0===this.messages?M`
        `:M`
          ${this.messages.map((e=>this.renderMessage(e)))}
        `}}),document.querySelectorAll("button.pf-c-dropdown__toggle").forEach((e=>{e.addEventListener("click",(e=>{const t=e.target.closest(".pf-c-dropdown").querySelector(".pf-c-dropdown__menu");t.hidden=!t.hidden}))})),document.querySelectorAll("input[type=search]").forEach((e=>{e.addEventListener("search",(t=>{""===e.value&&e.parentElement.submit()}))})),document.querySelectorAll("[data-pb-fetch-fill]").forEach((e=>{const t=e.dataset.pbFetchFill,s=e.dataset.pbFetchKey;fetch(t).then((e=>e.json())).then((t=>{e.textContent=t[s],e.value=t[s]}))})),document.querySelectorAll("[data-target='modal']").forEach((e=>{e.addEventListener("click",(e=>{const t=e.target.closest('[data-target="modal"]').attributes["data-modal"].value;document.querySelector("#"+t).removeAttribute("hidden")}))})),document.querySelectorAll(".pf-c-modal-box [data-modal-close]").forEach((e=>{e.addEventListener("click",(e=>{e.target.closest(".pf-c-backdrop").setAttribute("hidden",!0)}))})),document.querySelectorAll(".pf-c-check__label").forEach((e=>{e.addEventListener("click",(e=>{const t=e.target.parentElement.querySelector("input[type=checkbox]");t.checked=!t.checked}))})),document.querySelectorAll(".codemirror").forEach((e=>{let t="xml";"data-cm-mode"in e.attributes&&(t=e.attributes["data-cm-mode"].value),e.removeAttribute("required"),CodeMirror.fromTextArea(e,{mode:t,theme:"monokai",lineNumbers:!1,readOnly:e.readOnly,autoRefresh:!0})}));document.querySelectorAll("input[name=name]").forEach((e=>{e.addEventListener("input",(e=>{const t=e.target.closest("form");if(null===t)return;t.querySelector("input[name=slug]").value=e.target.value.toLowerCase().replace(/ /g,"-").replace(/[^\w-]+/g,"")}))})),document.querySelectorAll(".pf-c-page__header-brand-toggle>button").forEach((e=>{e.addEventListener("click",(e=>{const t=document.querySelector(".pf-c-page__sidebar");t.classList.contains("pf-m-expanded")?(t.classList.remove("pf-m-expanded"),t.style.zIndex=0):(t.classList.add("pf-m-expanded"),t.style.zIndex=200)}))})),document.querySelectorAll(".pf-m-expandable>.pf-c-nav__link").forEach((e=>{e.addEventListener("click",(t=>{t.preventDefault(),e.parentElement.classList.toggle("pf-m-expanded")}))}))}(); //# sourceMappingURL=passbook.js.map diff --git a/passbook/static/static/passbook/passbook.js.map b/passbook/static/static/passbook/passbook.js.map index c62f4e043..3f5c8c5cc 100644 --- a/passbook/static/static/passbook/passbook.js.map +++ b/passbook/static/static/passbook/passbook.js.map @@ -1 +1 @@ -{"version":3,"file":"passbook.js","sources":["../node_modules/lit-html/src/lib/dom.ts","../node_modules/lit-html/src/lib/template.ts","../node_modules/lit-html/src/lib/modify-template.ts","../node_modules/lit-html/src/lib/directive.ts","../node_modules/lit-html/src/lib/part.ts","../node_modules/lit-html/src/lib/template-instance.ts","../node_modules/lit-html/src/lib/template-result.ts","../node_modules/lit-html/src/lib/parts.ts","../node_modules/lit-html/src/lib/template-factory.ts","../node_modules/lit-html/src/lib/render.ts","../node_modules/lit-html/src/lib/default-template-processor.ts","../node_modules/lit-html/src/lit-html.ts","../node_modules/lit-html/src/lib/shady-render.ts","../node_modules/lit-element/src/lib/updating-element.ts","../node_modules/lit-element/src/lib/css-tag.ts","../node_modules/lit-element/src/lit-element.ts","../src/FetchFillSlot.js","../src/ActionButton.js","../src/utils.js","../src/Messages.js","../src/passbook.js"],"sourcesContent":["/**\n * @license\n * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.\n * This code may only be used under the BSD style license found at\n * http://polymer.github.io/LICENSE.txt\n * The complete set of authors may be found at\n * http://polymer.github.io/AUTHORS.txt\n * The complete set of contributors may be found at\n * http://polymer.github.io/CONTRIBUTORS.txt\n * Code distributed by Google as part of the polymer project is also\n * subject to an additional IP rights grant found at\n * http://polymer.github.io/PATENTS.txt\n */\n\ninterface MaybePolyfilledCe extends CustomElementRegistry {\n readonly polyfillWrapFlushCallback?: object;\n}\n\n/**\n * True if the custom elements polyfill is in use.\n */\nexport const isCEPolyfill = typeof window !== 'undefined' &&\n window.customElements != null &&\n (window.customElements as MaybePolyfilledCe).polyfillWrapFlushCallback !==\n undefined;\n\n/**\n * Reparents nodes, starting from `start` (inclusive) to `end` (exclusive),\n * into another container (could be the same container), before `before`. If\n * `before` is null, it appends the nodes to the container.\n */\nexport const reparentNodes =\n (container: Node,\n start: Node|null,\n end: Node|null = null,\n before: Node|null = null): void => {\n while (start !== end) {\n const n = start!.nextSibling;\n container.insertBefore(start!, before);\n start = n;\n }\n };\n\n/**\n * Removes nodes, starting from `start` (inclusive) to `end` (exclusive), from\n * `container`.\n */\nexport const removeNodes =\n (container: Node, start: Node|null, end: Node|null = null): void => {\n while (start !== end) {\n const n = start!.nextSibling;\n container.removeChild(start!);\n start = n;\n }\n };\n","/**\n * @license\n * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.\n * This code may only be used under the BSD style license found at\n * http://polymer.github.io/LICENSE.txt\n * The complete set of authors may be found at\n * http://polymer.github.io/AUTHORS.txt\n * The complete set of contributors may be found at\n * http://polymer.github.io/CONTRIBUTORS.txt\n * Code distributed by Google as part of the polymer project is also\n * subject to an additional IP rights grant found at\n * http://polymer.github.io/PATENTS.txt\n */\n\nimport {TemplateResult} from './template-result.js';\n\n/**\n * An expression marker with embedded unique key to avoid collision with\n * possible text in templates.\n */\nexport const marker = `{{lit-${String(Math.random()).slice(2)}}}`;\n\n/**\n * An expression marker used text-positions, multi-binding attributes, and\n * attributes with markup-like text values.\n */\nexport const nodeMarker = ``;\n\nexport const markerRegex = new RegExp(`${marker}|${nodeMarker}`);\n\n/**\n * Suffix appended to all bound attribute names.\n */\nexport const boundAttributeSuffix = '$lit$';\n\n/**\n * An updatable Template that tracks the location of dynamic parts.\n */\nexport class Template {\n readonly parts: TemplatePart[] = [];\n readonly element: HTMLTemplateElement;\n\n constructor(result: TemplateResult, element: HTMLTemplateElement) {\n this.element = element;\n\n const nodesToRemove: Node[] = [];\n const stack: Node[] = [];\n // Edge needs all 4 parameters present; IE11 needs 3rd parameter to be null\n const walker = document.createTreeWalker(\n element.content,\n 133 /* NodeFilter.SHOW_{ELEMENT|COMMENT|TEXT} */,\n null,\n false);\n // Keeps track of the last index associated with a part. We try to delete\n // unnecessary nodes, but we never want to associate two different parts\n // to the same index. They must have a constant node between.\n let lastPartIndex = 0;\n let index = -1;\n let partIndex = 0;\n const {strings, values: {length}} = result;\n while (partIndex < length) {\n const node = walker.nextNode() as Element | Comment | Text | null;\n if (node === null) {\n // We've exhausted the content inside a nested template element.\n // Because we still have parts (the outer for-loop), we know:\n // - There is a template in the stack\n // - The walker will find a nextNode outside the template\n walker.currentNode = stack.pop()!;\n continue;\n }\n index++;\n\n if (node.nodeType === 1 /* Node.ELEMENT_NODE */) {\n if ((node as Element).hasAttributes()) {\n const attributes = (node as Element).attributes;\n const {length} = attributes;\n // Per\n // https://developer.mozilla.org/en-US/docs/Web/API/NamedNodeMap,\n // attributes are not guaranteed to be returned in document order.\n // In particular, Edge/IE can return them out of order, so we cannot\n // assume a correspondence between part index and attribute index.\n let count = 0;\n for (let i = 0; i < length; i++) {\n if (endsWith(attributes[i].name, boundAttributeSuffix)) {\n count++;\n }\n }\n while (count-- > 0) {\n // Get the template literal section leading up to the first\n // expression in this attribute\n const stringForPart = strings[partIndex];\n // Find the attribute name\n const name = lastAttributeNameRegex.exec(stringForPart)![2];\n // Find the corresponding attribute\n // All bound attributes have had a suffix added in\n // TemplateResult#getHTML to opt out of special attribute\n // handling. To look up the attribute value we also need to add\n // the suffix.\n const attributeLookupName =\n name.toLowerCase() + boundAttributeSuffix;\n const attributeValue =\n (node as Element).getAttribute(attributeLookupName)!;\n (node as Element).removeAttribute(attributeLookupName);\n const statics = attributeValue.split(markerRegex);\n this.parts.push({type: 'attribute', index, name, strings: statics});\n partIndex += statics.length - 1;\n }\n }\n if ((node as Element).tagName === 'TEMPLATE') {\n stack.push(node);\n walker.currentNode = (node as HTMLTemplateElement).content;\n }\n } else if (node.nodeType === 3 /* Node.TEXT_NODE */) {\n const data = (node as Text).data;\n if (data.indexOf(marker) >= 0) {\n const parent = node.parentNode!;\n const strings = data.split(markerRegex);\n const lastIndex = strings.length - 1;\n // Generate a new text node for each literal section\n // These nodes are also used as the markers for node parts\n for (let i = 0; i < lastIndex; i++) {\n let insert: Node;\n let s = strings[i];\n if (s === '') {\n insert = createMarker();\n } else {\n const match = lastAttributeNameRegex.exec(s);\n if (match !== null && endsWith(match[2], boundAttributeSuffix)) {\n s = s.slice(0, match.index) + match[1] +\n match[2].slice(0, -boundAttributeSuffix.length) + match[3];\n }\n insert = document.createTextNode(s);\n }\n parent.insertBefore(insert, node);\n this.parts.push({type: 'node', index: ++index});\n }\n // If there's no text, we must insert a comment to mark our place.\n // Else, we can trust it will stick around after cloning.\n if (strings[lastIndex] === '') {\n parent.insertBefore(createMarker(), node);\n nodesToRemove.push(node);\n } else {\n (node as Text).data = strings[lastIndex];\n }\n // We have a part for each match found\n partIndex += lastIndex;\n }\n } else if (node.nodeType === 8 /* Node.COMMENT_NODE */) {\n if ((node as Comment).data === marker) {\n const parent = node.parentNode!;\n // Add a new marker node to be the startNode of the Part if any of\n // the following are true:\n // * We don't have a previousSibling\n // * The previousSibling is already the start of a previous part\n if (node.previousSibling === null || index === lastPartIndex) {\n index++;\n parent.insertBefore(createMarker(), node);\n }\n lastPartIndex = index;\n this.parts.push({type: 'node', index});\n // If we don't have a nextSibling, keep this node so we have an end.\n // Else, we can remove it to save future costs.\n if (node.nextSibling === null) {\n (node as Comment).data = '';\n } else {\n nodesToRemove.push(node);\n index--;\n }\n partIndex++;\n } else {\n let i = -1;\n while ((i = (node as Comment).data.indexOf(marker, i + 1)) !== -1) {\n // Comment node has a binding marker inside, make an inactive part\n // The binding won't work, but subsequent bindings will\n // TODO (justinfagnani): consider whether it's even worth it to\n // make bindings in comments work\n this.parts.push({type: 'node', index: -1});\n partIndex++;\n }\n }\n }\n }\n\n // Remove text binding nodes after the walk to not disturb the TreeWalker\n for (const n of nodesToRemove) {\n n.parentNode!.removeChild(n);\n }\n }\n}\n\nconst endsWith = (str: string, suffix: string): boolean => {\n const index = str.length - suffix.length;\n return index >= 0 && str.slice(index) === suffix;\n};\n\n/**\n * A placeholder for a dynamic expression in an HTML template.\n *\n * There are two built-in part types: AttributePart and NodePart. NodeParts\n * always represent a single dynamic expression, while AttributeParts may\n * represent as many expressions are contained in the attribute.\n *\n * A Template's parts are mutable, so parts can be replaced or modified\n * (possibly to implement different template semantics). The contract is that\n * parts can only be replaced, not removed, added or reordered, and parts must\n * always consume the correct number of values in their `update()` method.\n *\n * TODO(justinfagnani): That requirement is a little fragile. A\n * TemplateInstance could instead be more careful about which values it gives\n * to Part.update().\n */\nexport type TemplatePart = {\n readonly type: 'node'; index: number;\n}|{\n readonly type: 'attribute';\n index: number;\n readonly name: string;\n readonly strings: ReadonlyArray;\n};\n\nexport const isTemplatePartActive = (part: TemplatePart) => part.index !== -1;\n\n// Allows `document.createComment('')` to be renamed for a\n// small manual size-savings.\nexport const createMarker = () => document.createComment('');\n\n/**\n * This regex extracts the attribute name preceding an attribute-position\n * expression. It does this by matching the syntax allowed for attributes\n * against the string literal directly preceding the expression, assuming that\n * the expression is in an attribute-value position.\n *\n * See attributes in the HTML spec:\n * https://www.w3.org/TR/html5/syntax.html#elements-attributes\n *\n * \" \\x09\\x0a\\x0c\\x0d\" are HTML space characters:\n * https://www.w3.org/TR/html5/infrastructure.html#space-characters\n *\n * \"\\0-\\x1F\\x7F-\\x9F\" are Unicode control characters, which includes every\n * space character except \" \".\n *\n * So an attribute is:\n * * The name: any character except a control character, space character, ('),\n * (\"), \">\", \"=\", or \"/\"\n * * Followed by zero or more space characters\n * * Followed by \"=\"\n * * Followed by zero or more space characters\n * * Followed by:\n * * Any character except space, ('), (\"), \"<\", \">\", \"=\", (`), or\n * * (\") then any non-(\"), or\n * * (') then any non-(')\n */\nexport const lastAttributeNameRegex =\n // eslint-disable-next-line no-control-regex\n /([ \\x09\\x0a\\x0c\\x0d])([^\\0-\\x1F\\x7F-\\x9F \"'>=/]+)([ \\x09\\x0a\\x0c\\x0d]*=[ \\x09\\x0a\\x0c\\x0d]*(?:[^ \\x09\\x0a\\x0c\\x0d\"'`<>=]*|\"[^\"]*|'[^']*))$/;\n","/**\n * @license\n * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.\n * This code may only be used under the BSD style license found at\n * http://polymer.github.io/LICENSE.txt\n * The complete set of authors may be found at\n * http://polymer.github.io/AUTHORS.txt\n * The complete set of contributors may be found at\n * http://polymer.github.io/CONTRIBUTORS.txt\n * Code distributed by Google as part of the polymer project is also\n * subject to an additional IP rights grant found at\n * http://polymer.github.io/PATENTS.txt\n */\n\nimport {isTemplatePartActive, Template, TemplatePart} from './template.js';\n\nconst walkerNodeFilter = 133 /* NodeFilter.SHOW_{ELEMENT|COMMENT|TEXT} */;\n\n/**\n * Removes the list of nodes from a Template safely. In addition to removing\n * nodes from the Template, the Template part indices are updated to match\n * the mutated Template DOM.\n *\n * As the template is walked the removal state is tracked and\n * part indices are adjusted as needed.\n *\n * div\n * div#1 (remove) <-- start removing (removing node is div#1)\n * div\n * div#2 (remove) <-- continue removing (removing node is still div#1)\n * div\n * div <-- stop removing since previous sibling is the removing node (div#1,\n * removed 4 nodes)\n */\nexport function removeNodesFromTemplate(\n template: Template, nodesToRemove: Set) {\n const {element: {content}, parts} = template;\n const walker =\n document.createTreeWalker(content, walkerNodeFilter, null, false);\n let partIndex = nextActiveIndexInTemplateParts(parts);\n let part = parts[partIndex];\n let nodeIndex = -1;\n let removeCount = 0;\n const nodesToRemoveInTemplate = [];\n let currentRemovingNode: Node|null = null;\n while (walker.nextNode()) {\n nodeIndex++;\n const node = walker.currentNode as Element;\n // End removal if stepped past the removing node\n if (node.previousSibling === currentRemovingNode) {\n currentRemovingNode = null;\n }\n // A node to remove was found in the template\n if (nodesToRemove.has(node)) {\n nodesToRemoveInTemplate.push(node);\n // Track node we're removing\n if (currentRemovingNode === null) {\n currentRemovingNode = node;\n }\n }\n // When removing, increment count by which to adjust subsequent part indices\n if (currentRemovingNode !== null) {\n removeCount++;\n }\n while (part !== undefined && part.index === nodeIndex) {\n // If part is in a removed node deactivate it by setting index to -1 or\n // adjust the index as needed.\n part.index = currentRemovingNode !== null ? -1 : part.index - removeCount;\n // go to the next active part.\n partIndex = nextActiveIndexInTemplateParts(parts, partIndex);\n part = parts[partIndex];\n }\n }\n nodesToRemoveInTemplate.forEach((n) => n.parentNode!.removeChild(n));\n}\n\nconst countNodes = (node: Node) => {\n let count = (node.nodeType === 11 /* Node.DOCUMENT_FRAGMENT_NODE */) ? 0 : 1;\n const walker = document.createTreeWalker(node, walkerNodeFilter, null, false);\n while (walker.nextNode()) {\n count++;\n }\n return count;\n};\n\nconst nextActiveIndexInTemplateParts =\n (parts: TemplatePart[], startIndex = -1) => {\n for (let i = startIndex + 1; i < parts.length; i++) {\n const part = parts[i];\n if (isTemplatePartActive(part)) {\n return i;\n }\n }\n return -1;\n };\n\n/**\n * Inserts the given node into the Template, optionally before the given\n * refNode. In addition to inserting the node into the Template, the Template\n * part indices are updated to match the mutated Template DOM.\n */\nexport function insertNodeIntoTemplate(\n template: Template, node: Node, refNode: Node|null = null) {\n const {element: {content}, parts} = template;\n // If there's no refNode, then put node at end of template.\n // No part indices need to be shifted in this case.\n if (refNode === null || refNode === undefined) {\n content.appendChild(node);\n return;\n }\n const walker =\n document.createTreeWalker(content, walkerNodeFilter, null, false);\n let partIndex = nextActiveIndexInTemplateParts(parts);\n let insertCount = 0;\n let walkerIndex = -1;\n while (walker.nextNode()) {\n walkerIndex++;\n const walkerNode = walker.currentNode as Element;\n if (walkerNode === refNode) {\n insertCount = countNodes(node);\n refNode.parentNode!.insertBefore(node, refNode);\n }\n while (partIndex !== -1 && parts[partIndex].index === walkerIndex) {\n // If we've inserted the node, simply adjust all subsequent parts\n if (insertCount > 0) {\n while (partIndex !== -1) {\n parts[partIndex].index += insertCount;\n partIndex = nextActiveIndexInTemplateParts(parts, partIndex);\n }\n return;\n }\n partIndex = nextActiveIndexInTemplateParts(parts, partIndex);\n }\n }\n}\n","/**\n * @license\n * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.\n * This code may only be used under the BSD style license found at\n * http://polymer.github.io/LICENSE.txt\n * The complete set of authors may be found at\n * http://polymer.github.io/AUTHORS.txt\n * The complete set of contributors may be found at\n * http://polymer.github.io/CONTRIBUTORS.txt\n * Code distributed by Google as part of the polymer project is also\n * subject to an additional IP rights grant found at\n * http://polymer.github.io/PATENTS.txt\n */\n\nimport {Part} from './part.js';\n\nconst directives = new WeakMap();\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type DirectiveFactory = (...args: any[]) => object;\n\nexport type DirectiveFn = (part: Part) => void;\n\n/**\n * Brands a function as a directive factory function so that lit-html will call\n * the function during template rendering, rather than passing as a value.\n *\n * A _directive_ is a function that takes a Part as an argument. It has the\n * signature: `(part: Part) => void`.\n *\n * A directive _factory_ is a function that takes arguments for data and\n * configuration and returns a directive. Users of directive usually refer to\n * the directive factory as the directive. For example, \"The repeat directive\".\n *\n * Usually a template author will invoke a directive factory in their template\n * with relevant arguments, which will then return a directive function.\n *\n * Here's an example of using the `repeat()` directive factory that takes an\n * array and a function to render an item:\n *\n * ```js\n * html`
          <${repeat(items, (item) => html`
        • ${item}
        • `)}
        `\n * ```\n *\n * When `repeat` is invoked, it returns a directive function that closes over\n * `items` and the template function. When the outer template is rendered, the\n * return directive function is called with the Part for the expression.\n * `repeat` then performs it's custom logic to render multiple items.\n *\n * @param f The directive factory function. Must be a function that returns a\n * function of the signature `(part: Part) => void`. The returned function will\n * be called with the part object.\n *\n * @example\n *\n * import {directive, html} from 'lit-html';\n *\n * const immutable = directive((v) => (part) => {\n * if (part.value !== v) {\n * part.setValue(v)\n * }\n * });\n */\nexport const directive = (f: F): F =>\n ((...args: unknown[]) => {\n const d = f(...args);\n directives.set(d, true);\n return d;\n }) as F;\n\nexport const isDirective = (o: unknown): o is DirectiveFn => {\n return typeof o === 'function' && directives.has(o);\n};\n","/**\n * @license\n * Copyright (c) 2018 The Polymer Project Authors. All rights reserved.\n * This code may only be used under the BSD style license found at\n * http://polymer.github.io/LICENSE.txt\n * The complete set of authors may be found at\n * http://polymer.github.io/AUTHORS.txt\n * The complete set of contributors may be found at\n * http://polymer.github.io/CONTRIBUTORS.txt\n * Code distributed by Google as part of the polymer project is also\n * subject to an additional IP rights grant found at\n * http://polymer.github.io/PATENTS.txt\n */\n\n/**\n * The Part interface represents a dynamic part of a template instance rendered\n * by lit-html.\n */\nexport interface Part {\n readonly value: unknown;\n\n /**\n * Sets the current part value, but does not write it to the DOM.\n * @param value The value that will be committed.\n */\n setValue(value: unknown): void;\n\n /**\n * Commits the current part value, causing it to actually be written to the\n * DOM.\n *\n * Directives are run at the start of `commit`, so that if they call\n * `part.setValue(...)` synchronously that value will be used in the current\n * commit, and there's no need to call `part.commit()` within the directive.\n * If directives set a part value asynchronously, then they must call\n * `part.commit()` manually.\n */\n commit(): void;\n}\n\n/**\n * A sentinel value that signals that a value was handled by a directive and\n * should not be written to the DOM.\n */\nexport const noChange = {};\n\n/**\n * A sentinel value that signals a NodePart to fully clear its content.\n */\nexport const nothing = {};\n","/**\n * @license\n * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.\n * This code may only be used under the BSD style license found at\n * http://polymer.github.io/LICENSE.txt\n * The complete set of authors may be found at\n * http://polymer.github.io/AUTHORS.txt\n * The complete set of contributors may be found at\n * http://polymer.github.io/CONTRIBUTORS.txt\n * Code distributed by Google as part of the polymer project is also\n * subject to an additional IP rights grant found at\n * http://polymer.github.io/PATENTS.txt\n */\n\nimport {isCEPolyfill} from './dom.js';\nimport {Part} from './part.js';\nimport {RenderOptions} from './render-options.js';\nimport {TemplateProcessor} from './template-processor.js';\nimport {isTemplatePartActive, Template, TemplatePart} from './template.js';\n\n/**\n * An instance of a `Template` that can be attached to the DOM and updated\n * with new values.\n */\nexport class TemplateInstance {\n private readonly __parts: Array = [];\n readonly processor: TemplateProcessor;\n readonly options: RenderOptions;\n readonly template: Template;\n\n constructor(\n template: Template, processor: TemplateProcessor,\n options: RenderOptions) {\n this.template = template;\n this.processor = processor;\n this.options = options;\n }\n\n update(values: readonly unknown[]) {\n let i = 0;\n for (const part of this.__parts) {\n if (part !== undefined) {\n part.setValue(values[i]);\n }\n i++;\n }\n for (const part of this.__parts) {\n if (part !== undefined) {\n part.commit();\n }\n }\n }\n\n _clone(): DocumentFragment {\n // There are a number of steps in the lifecycle of a template instance's\n // DOM fragment:\n // 1. Clone - create the instance fragment\n // 2. Adopt - adopt into the main document\n // 3. Process - find part markers and create parts\n // 4. Upgrade - upgrade custom elements\n // 5. Update - set node, attribute, property, etc., values\n // 6. Connect - connect to the document. Optional and outside of this\n // method.\n //\n // We have a few constraints on the ordering of these steps:\n // * We need to upgrade before updating, so that property values will pass\n // through any property setters.\n // * We would like to process before upgrading so that we're sure that the\n // cloned fragment is inert and not disturbed by self-modifying DOM.\n // * We want custom elements to upgrade even in disconnected fragments.\n //\n // Given these constraints, with full custom elements support we would\n // prefer the order: Clone, Process, Adopt, Upgrade, Update, Connect\n //\n // But Safari does not implement CustomElementRegistry#upgrade, so we\n // can not implement that order and still have upgrade-before-update and\n // upgrade disconnected fragments. So we instead sacrifice the\n // process-before-upgrade constraint, since in Custom Elements v1 elements\n // must not modify their light DOM in the constructor. We still have issues\n // when co-existing with CEv0 elements like Polymer 1, and with polyfills\n // that don't strictly adhere to the no-modification rule because shadow\n // DOM, which may be created in the constructor, is emulated by being placed\n // in the light DOM.\n //\n // The resulting order is on native is: Clone, Adopt, Upgrade, Process,\n // Update, Connect. document.importNode() performs Clone, Adopt, and Upgrade\n // in one step.\n //\n // The Custom Elements v1 polyfill supports upgrade(), so the order when\n // polyfilled is the more ideal: Clone, Process, Adopt, Upgrade, Update,\n // Connect.\n\n const fragment = isCEPolyfill ?\n this.template.element.content.cloneNode(true) as DocumentFragment :\n document.importNode(this.template.element.content, true);\n\n const stack: Node[] = [];\n const parts = this.template.parts;\n // Edge needs all 4 parameters present; IE11 needs 3rd parameter to be null\n const walker = document.createTreeWalker(\n fragment,\n 133 /* NodeFilter.SHOW_{ELEMENT|COMMENT|TEXT} */,\n null,\n false);\n let partIndex = 0;\n let nodeIndex = 0;\n let part: TemplatePart;\n let node = walker.nextNode();\n // Loop through all the nodes and parts of a template\n while (partIndex < parts.length) {\n part = parts[partIndex];\n if (!isTemplatePartActive(part)) {\n this.__parts.push(undefined);\n partIndex++;\n continue;\n }\n\n // Progress the tree walker until we find our next part's node.\n // Note that multiple parts may share the same node (attribute parts\n // on a single element), so this loop may not run at all.\n while (nodeIndex < part.index) {\n nodeIndex++;\n if (node!.nodeName === 'TEMPLATE') {\n stack.push(node!);\n walker.currentNode = (node as HTMLTemplateElement).content;\n }\n if ((node = walker.nextNode()) === null) {\n // We've exhausted the content inside a nested template element.\n // Because we still have parts (the outer for-loop), we know:\n // - There is a template in the stack\n // - The walker will find a nextNode outside the template\n walker.currentNode = stack.pop()!;\n node = walker.nextNode();\n }\n }\n\n // We've arrived at our part's node.\n if (part.type === 'node') {\n const part = this.processor.handleTextExpression(this.options);\n part.insertAfterNode(node!.previousSibling!);\n this.__parts.push(part);\n } else {\n this.__parts.push(...this.processor.handleAttributeExpressions(\n node as Element, part.name, part.strings, this.options));\n }\n partIndex++;\n }\n\n if (isCEPolyfill) {\n document.adoptNode(fragment);\n customElements.upgrade(fragment);\n }\n return fragment;\n }\n}\n","/**\n * @license\n * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.\n * This code may only be used under the BSD style license found at\n * http://polymer.github.io/LICENSE.txt\n * The complete set of authors may be found at\n * http://polymer.github.io/AUTHORS.txt\n * The complete set of contributors may be found at\n * http://polymer.github.io/CONTRIBUTORS.txt\n * Code distributed by Google as part of the polymer project is also\n * subject to an additional IP rights grant found at\n * http://polymer.github.io/PATENTS.txt\n */\n\n/**\n * @module lit-html\n */\n\nimport {reparentNodes} from './dom.js';\nimport {TemplateProcessor} from './template-processor.js';\nimport {boundAttributeSuffix, lastAttributeNameRegex, marker, nodeMarker} from './template.js';\n\ndeclare const trustedTypes: typeof window.trustedTypes;\n/**\n * Our TrustedTypePolicy for HTML which is declared using the html template\n * tag function.\n *\n * That HTML is a developer-authored constant, and is parsed with innerHTML\n * before any untrusted expressions have been mixed in. Therefor it is\n * considered safe by construction.\n */\nconst policy = window.trustedTypes &&\n trustedTypes!.createPolicy('lit-html', {createHTML: (s) => s});\n\nconst commentMarker = ` ${marker} `;\n\n/**\n * The return type of `html`, which holds a Template and the values from\n * interpolated expressions.\n */\nexport class TemplateResult {\n readonly strings: TemplateStringsArray;\n readonly values: readonly unknown[];\n readonly type: string;\n readonly processor: TemplateProcessor;\n\n constructor(\n strings: TemplateStringsArray, values: readonly unknown[], type: string,\n processor: TemplateProcessor) {\n this.strings = strings;\n this.values = values;\n this.type = type;\n this.processor = processor;\n }\n\n /**\n * Returns a string of HTML used to create a `