diff --git a/packages/html2/src/html.ts b/packages/html2/src/html.ts
index dc14a4d..686a218 100644
--- a/packages/html2/src/html.ts
+++ b/packages/html2/src/html.ts
@@ -308,17 +308,17 @@ export type HtmlTemplater =
=> ChildNode[];
export function template(): HtmlTemplater {
- let instance: HtmlFragmentInstance | null = null;
+ let cache: null | { instance: HtmlFragmentInstance, builder: HtmlFragmentBuilder } = null;
return (constantParts, ... variableParts) => {
let b = templateCache.get(constantParts);
if (b === void 0) {
b = new HtmlFragmentBuilder(constantParts);
templateCache.set(constantParts, b);
}
- if (instance === null) {
- instance = b.clone();
+ if (cache === null || cache.builder !== b) {
+ cache = { instance: b.clone(), builder: b };
}
- b.update(instance, variableParts);
- return instance.container;
+ b.update(cache.instance, variableParts);
+ return cache.instance.container;
};
}
diff --git a/packages/html2/test/html.test.ts b/packages/html2/test/html.test.ts
index 6a85c50..c7c8921 100644
--- a/packages/html2/test/html.test.ts
+++ b/packages/html2/test/html.test.ts
@@ -1,7 +1,7 @@
/// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2024 Tony Garnock-Jones
-import { template } from '../src/html';
+import { HtmlTemplater, template } from '../src/html';
import './test-utils';
function compareHTML(nodes: ChildNode[], expected: string) {
@@ -89,6 +89,18 @@ describe('basic templating', () => {
compareHTML(t`${ps.map(p => p())}
`, 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 = '123234345
';
+ const t = template();
+ const f = () => compareHTML(t`${ps.map(p => p())}
`, expected);
+ f();
+ f();
+ f();
+ });
+
it('should be callable multiple times with extra items', () => {
const v = () => 'aaa';
const t = template();
@@ -99,4 +111,16 @@ describe('basic templating', () => {
ps.push(() => '3');
compareHTML(t`${ps.map(p => p())}
`, '123
');
});
+
+ it('should be reusable for supplying arguments to itself', () => {
+ const inner = (t: HtmlTemplater) => t`middle`;
+ const t = template();
+ compareHTML(t`n${inner(t)}n
`, 'nmiddlen
');
+ });
+
+ it('should accept strings', () => {
+ const inner = (_t: HtmlTemplater) => `middle`;
+ const t = template();
+ compareHTML(t`n${inner(t)}n
`, 'n<i>middle</i>n
');
+ });
});