Repair reuse of templater at different constant-portions
This commit is contained in:
parent
600d9b3c15
commit
7e439b9bb1
|
@ -308,17 +308,17 @@ export type HtmlTemplater =
|
||||||
=> ChildNode[];
|
=> ChildNode[];
|
||||||
|
|
||||||
export function template(): HtmlTemplater {
|
export function template(): HtmlTemplater {
|
||||||
let instance: HtmlFragmentInstance | null = null;
|
let cache: null | { instance: HtmlFragmentInstance, builder: HtmlFragmentBuilder } = null;
|
||||||
return (constantParts, ... variableParts) => {
|
return (constantParts, ... variableParts) => {
|
||||||
let b = templateCache.get(constantParts);
|
let b = templateCache.get(constantParts);
|
||||||
if (b === void 0) {
|
if (b === void 0) {
|
||||||
b = new HtmlFragmentBuilder(constantParts);
|
b = new HtmlFragmentBuilder(constantParts);
|
||||||
templateCache.set(constantParts, b);
|
templateCache.set(constantParts, b);
|
||||||
}
|
}
|
||||||
if (instance === null) {
|
if (cache === null || cache.builder !== b) {
|
||||||
instance = b.clone();
|
cache = { instance: b.clone(), builder: b };
|
||||||
}
|
}
|
||||||
b.update(instance, variableParts);
|
b.update(cache.instance, variableParts);
|
||||||
return instance.container;
|
return cache.instance.container;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/// SPDX-License-Identifier: GPL-3.0-or-later
|
/// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
/// SPDX-FileCopyrightText: Copyright © 2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
|
/// SPDX-FileCopyrightText: Copyright © 2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
|
||||||
|
|
||||||
import { template } from '../src/html';
|
import { HtmlTemplater, template } from '../src/html';
|
||||||
import './test-utils';
|
import './test-utils';
|
||||||
|
|
||||||
function compareHTML(nodes: ChildNode[], expected: string) {
|
function compareHTML(nodes: ChildNode[], expected: string) {
|
||||||
|
@ -89,6 +89,18 @@ describe('basic templating', () => {
|
||||||
compareHTML(t`<q><x t="${v()}">${ps.map(p => p())}</x></q>`, expected);
|
compareHTML(t`<q><x t="${v()}">${ps.map(p => p())}</x></q>`, expected);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should be callable multiple times with the same syntactic location', () => {
|
||||||
|
// Because the fixed portion of a template string, the TemplateStringsArray, is hashconsed
|
||||||
|
const v = () => 'aaa';
|
||||||
|
const ps = [() => '123', () => '234', () => '345'];
|
||||||
|
const expected = '<q><x t="aaa">123234345</x></q>';
|
||||||
|
const t = template();
|
||||||
|
const f = () => compareHTML(t`<q><x t="${v()}">${ps.map(p => p())}</x></q>`, expected);
|
||||||
|
f();
|
||||||
|
f();
|
||||||
|
f();
|
||||||
|
});
|
||||||
|
|
||||||
it('should be callable multiple times with extra items', () => {
|
it('should be callable multiple times with extra items', () => {
|
||||||
const v = () => 'aaa';
|
const v = () => 'aaa';
|
||||||
const t = template();
|
const t = template();
|
||||||
|
@ -99,4 +111,16 @@ describe('basic templating', () => {
|
||||||
ps.push(() => '3');
|
ps.push(() => '3');
|
||||||
compareHTML(t`<q><x t="${v()}">${ps.map(p => p())}</x></q>`, '<q><x t="aaa">123</x></q>');
|
compareHTML(t`<q><x t="${v()}">${ps.map(p => p())}</x></q>`, '<q><x t="aaa">123</x></q>');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should be reusable for supplying arguments to itself', () => {
|
||||||
|
const inner = (t: HtmlTemplater) => t`<i>middle</i>`;
|
||||||
|
const t = template();
|
||||||
|
compareHTML(t`<p>n${inner(t)}n</p>`, '<p>n<i>middle</i>n</p>');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should accept strings', () => {
|
||||||
|
const inner = (_t: HtmlTemplater) => `<i>middle</i>`;
|
||||||
|
const t = template();
|
||||||
|
compareHTML(t`<p>n${inner(t)}n</p>`, '<p>n<i>middle</i>n</p>');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue