Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 21 additions & 7 deletions cjs/html/template-element.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,39 @@ 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';

/**
* @implements globalThis.HTMLTemplateElement
*/
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('></template>', () => `>${this.innerHTML}</template>`);
}
}

registerHTMLClass(tagName, HTMLTemplateElement);
Expand Down
9 changes: 8 additions & 1 deletion cjs/shared/parse-from-string.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand All @@ -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);
Expand Down Expand Up @@ -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;
}
}, {
Expand Down
21 changes: 17 additions & 4 deletions esm/html/template-element.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';

/**
Expand All @@ -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('></template>', () => `>${this.innerHTML}</template>`);
}
}

registerHTMLClass(tagName, HTMLTemplateElement);
Expand Down
9 changes: 8 additions & 1 deletion esm/shared/parse-from-string.js
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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);
Expand Down Expand Up @@ -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;
}
}, {
Expand Down
22 changes: 21 additions & 1 deletion test/html/template-element.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ assert(document.querySelector('template > *'), null);
assert(template.content, template.content);

template.replaceChildren();
assert(template.innerHTML, '');
assert(template.innerHTML, '<div>foo</div><div>bar</div>');

template.innerHTML = '<p>ok</p>';
assert(template.innerHTML, '<p>ok</p>');
Expand Down Expand Up @@ -47,3 +47,23 @@ const docWithTemplateAttribute = parseHTML(`<div template="anything"><p>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='<a>child element</a>';
fragment.append(div);
template.content.append(fragment);
assert(template.innerHTML, '<div><a>child element</a></div>', 'template.innerHTML');
assert(template.innerText, '', 'template.innerText');

template = document.createElement('template');
template.innerHTML='<div><a>child element innerHTML</a></div>';
fragment = document.createDocumentFragment();
div = document.createElement('div');
div.innerHTML='<a>new child element</a>';
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, '<div><a>child element innerHTML</a></div>', 'template.innerHTML The template maintains internal HTML even with additional children');