diff --git a/cjs/html/template-element.js b/cjs/html/template-element.js index c65245d0..2281038e 100644 --- a/cjs/html/template-element.js +++ b/cjs/html/template-element.js @@ -5,6 +5,11 @@ const {registerHTMLClass} = require('../shared/register-html-class.js'); const {HTMLElement} = require('./element.js'); +const {getInnerHtml} = require('../mixin/inner-html.js'); +const {setInnerHtml} = require("../mixin/inner-html"); + +const {toString} = require('./element.js').HTMLElement.prototype; + const tagName = 'template'; /** @@ -12,18 +17,27 @@ const tagName = 'template'; */ class HTMLTemplateElement extends HTMLElement { constructor(ownerDocument) { - super(ownerDocument, tagName); - const content = this.ownerDocument.createDocumentFragment(); - (this[CONTENT] = content)[PRIVATE] = this; + super(ownerDocument, tagName); + const content = this.ownerDocument.createDocumentFragment(); + (this[CONTENT] = content)[PRIVATE] = this; + } + + get innerHTML() { + return getInnerHtml(this.content); + } + + set innerHTML(html) { + setInnerHtml(this[CONTENT], html); } get content() { - if (this.hasChildNodes() && !this[CONTENT].hasChildNodes()) { - for (const node of this.childNodes) - this[CONTENT].appendChild(node.cloneNode(true)); - } return this[CONTENT]; } + + toString() { + const outerHTML = toString.call(this.cloneNode()); + return outerHTML.replace('>', () => `>${this.innerHTML}`); + } } registerHTMLClass(tagName, HTMLTemplateElement); diff --git a/cjs/shared/parse-from-string.js b/cjs/shared/parse-from-string.js index 84a9fdf3..dcec7d1e 100644 --- a/cjs/shared/parse-from-string.js +++ b/cjs/shared/parse-from-string.js @@ -2,7 +2,7 @@ const HTMLParser2 = require('htmlparser2'); const {ELEMENT_NODE, SVG_NAMESPACE} = require('./constants.js'); -const {CUSTOM_ELEMENTS, PREV, END, VALUE} = require('./symbols.js'); +const {CUSTOM_ELEMENTS, PREV, END, VALUE, CONTENT, PRIVATE} = require('./symbols.js'); const {keys} = require('./object.js'); const {knownBoundaries, knownSiblings} = require('./utils.js'); @@ -19,6 +19,10 @@ const {Parser} = HTMLParser2; let notParsing = true; const append = (self, node, active) => { + if (self && self.localName === 'template' && self[CONTENT]) { + self = self[CONTENT]; + } + if (!self) return node; // null 체크 추가 const end = self[END]; node.parentNode = self; knownBoundaries(end[PREV], node, end); @@ -107,6 +111,9 @@ const parseFromString = (document, isHTML, markupLanguage) => { onclosetag() { if (isHTML && node === ownerSVGElement) ownerSVGElement = null; + if (node && node[PRIVATE]) { + node = node[PRIVATE]; + } node = node.parentNode; } }, { diff --git a/esm/html/template-element.js b/esm/html/template-element.js index 78973f8f..f0746031 100644 --- a/esm/html/template-element.js +++ b/esm/html/template-element.js @@ -4,6 +4,10 @@ import {registerHTMLClass} from '../shared/register-html-class.js'; import {HTMLElement} from './element.js'; +import {getInnerHtml, setInnerHtml} from '../mixin/inner-html.js'; + +const {toString} = HTMLElement.prototype; + const tagName = 'template'; /** @@ -16,13 +20,22 @@ class HTMLTemplateElement extends HTMLElement { (this[CONTENT] = content)[PRIVATE] = this; } + get innerHTML() { + return getInnerHtml(this.content); + } + + set innerHTML(html) { + setInnerHtml(this[CONTENT], html); + } + get content() { - if (this.hasChildNodes() && !this[CONTENT].hasChildNodes()) { - for (const node of this.childNodes) - this[CONTENT].appendChild(node.cloneNode(true)); - } return this[CONTENT]; } + + toString() { + const outerHTML = toString.call(this.cloneNode()); + return outerHTML.replace('>', () => `>${this.innerHTML}`); + } } registerHTMLClass(tagName, HTMLTemplateElement); diff --git a/esm/shared/parse-from-string.js b/esm/shared/parse-from-string.js index 08c6fe39..77b43487 100644 --- a/esm/shared/parse-from-string.js +++ b/esm/shared/parse-from-string.js @@ -1,7 +1,7 @@ import * as HTMLParser2 from 'htmlparser2'; import {ELEMENT_NODE, SVG_NAMESPACE} from './constants.js'; -import {CUSTOM_ELEMENTS, PREV, END, VALUE} from './symbols.js'; +import {CUSTOM_ELEMENTS, PREV, END, VALUE, CONTENT, PRIVATE} from './symbols.js'; import {keys} from './object.js'; import {knownBoundaries, knownSiblings} from './utils.js'; @@ -18,6 +18,10 @@ const {Parser} = HTMLParser2; let notParsing = true; const append = (self, node, active) => { + if (self && self.localName === 'template' && self[CONTENT]) { + self = self[CONTENT]; + } + if (!self) return node; // null 체크 추가 const end = self[END]; node.parentNode = self; knownBoundaries(end[PREV], node, end); @@ -105,6 +109,9 @@ export const parseFromString = (document, isHTML, markupLanguage) => { onclosetag() { if (isHTML && node === ownerSVGElement) ownerSVGElement = null; + if (node && node[PRIVATE]) { + node = node[PRIVATE]; + } node = node.parentNode; } }, { diff --git a/test/html/template-element.js b/test/html/template-element.js index 05d5caec..2f37833b 100644 --- a/test/html/template-element.js +++ b/test/html/template-element.js @@ -15,7 +15,7 @@ assert(document.querySelector('template > *'), null); assert(template.content, template.content); template.replaceChildren(); -assert(template.innerHTML, ''); +assert(template.innerHTML, '
foo
bar
'); template.innerHTML = '

ok

'; assert(template.innerHTML, '

ok

'); @@ -47,3 +47,23 @@ const docWithTemplateAttribute = parseHTML(`

not insi assert(docWithTemplateAttribute.querySelector('*').tagName, 'P'); assert(docWithTemplateAttribute.querySelectorAll('*').length, 1); + +template = document.createElement('template'); +let fragment = document.createDocumentFragment(); +let div = document.createElement('div') +div.innerHTML='child element'; +fragment.append(div); +template.content.append(fragment); +assert(template.innerHTML, '

child element
', 'template.innerHTML'); +assert(template.innerText, '', 'template.innerText'); + +template = document.createElement('template'); +template.innerHTML='
child element innerHTML
'; +fragment = document.createDocumentFragment(); +div = document.createElement('div'); +div.innerHTML='new child element'; +assert(Array.from(template.children).length, 0, 'template.appendChild zero'); +template.appendChild(div); +assert(Array.from(template.children).length, 1, 'template.appendChild one'); +assert(template.innerText, 'new child element', 'template.innerText'); +assert(template.innerHTML, '
child element innerHTML
', 'template.innerHTML The template maintains internal HTML even with additional children');