Skip to content

Commit 2b0c01b

Browse files
committed
fix(html): prepare codebase for render & content merge
1 parent 36d6e39 commit 2b0c01b

File tree

6 files changed

+61
-54
lines changed

6 files changed

+61
-54
lines changed

src/localize.js

+5
Original file line numberDiff line numberDiff line change
@@ -166,12 +166,16 @@ export function msg(parts, ...args) {
166166
return getString(parts, args).replace(EXP_REGEX, (_, index) => args[index]);
167167
}
168168

169+
const PLACEHOLDER_SVG = getPlaceholder("svg");
170+
const PLACEHOLDER_MSG = getPlaceholder("msg");
171+
169172
msg.html = function html(parts, ...args) {
170173
const input = getString(parts, args);
171174

172175
return compile(
173176
input.replace(EXP_REGEX, (_, index) => getPlaceholder(index)),
174177
args,
178+
input + PLACEHOLDER_MSG,
175179
false,
176180
true,
177181
);
@@ -183,6 +187,7 @@ msg.svg = function svg(parts, ...args) {
183187
return compile(
184188
input.replace(EXP_REGEX, (_, index) => getPlaceholder(index)),
185189
args,
190+
input + PLACEHOLDER_SVG + PLACEHOLDER_MSG,
186191
true,
187192
true,
188193
);

src/render.js

+10-25
Original file line numberDiff line numberDiff line change
@@ -22,35 +22,20 @@ export default function render(key, desc) {
2222
},
2323
};
2424

25+
let shadowOptions = undefined;
2526
if (key === "render") {
2627
const options = desc.options || {};
27-
28-
const shadowOptions = {
28+
shadowOptions = {
2929
mode: options.mode || "open",
3030
delegatesFocus: options.delegatesFocus || false,
3131
};
32-
33-
return {
34-
value: (host) => {
35-
const updateDOM = fn(host);
36-
return () => {
37-
const target = host.shadowRoot || host.attachShadow(shadowOptions);
38-
updateDOM(host, target);
39-
return target;
40-
};
41-
},
42-
...rest,
43-
};
44-
} else {
45-
return {
46-
value: (host) => {
47-
const updateDOM = fn(host);
48-
return () => {
49-
updateDOM(host, host);
50-
return host;
51-
};
52-
},
53-
...rest,
54-
};
5532
}
33+
34+
return {
35+
value: (host) => {
36+
const updateDOM = fn(host);
37+
return () => updateDOM(host, null, shadowOptions);
38+
},
39+
...rest,
40+
};
5641
}

src/template/core.js

+22-11
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ const PLACEHOLDER_REGEXP_EQUAL = new RegExp(`^${PLACEHOLDER_REGEXP_TEXT}$`);
1717
const PLACEHOLDER_REGEXP_ALL = new RegExp(PLACEHOLDER_REGEXP_TEXT, "g");
1818
const PLACEHOLDER_REGEXP_ONLY = /^[^A-Za-z]+$/;
1919

20-
function createSignature(parts) {
20+
function createContent(parts) {
2121
let signature = parts[0];
2222
let tableMode = false;
2323
for (let index = 1; index < parts.length; index += 1) {
@@ -190,12 +190,10 @@ function updateStyleElement(target, styles) {
190190
}
191191

192192
export function compileTemplate(rawParts, isSVG, isMsg, useLayout) {
193-
let template = globalThis.document.createElement("template");
194-
const parts = {};
195-
196-
const signature = isMsg ? rawParts : createSignature(rawParts);
193+
const content = isMsg ? rawParts : createContent(rawParts);
197194

198-
template.innerHTML = isSVG ? `<svg>${signature}</svg>` : signature;
195+
let template = globalThis.document.createElement("template");
196+
template.innerHTML = isSVG ? `<svg>${content}</svg>` : content;
199197

200198
if (isSVG) {
201199
const svgRoot = template.content.firstChild;
@@ -235,7 +233,9 @@ export function compileTemplate(rawParts, isSVG, isMsg, useLayout) {
235233
}
236234

237235
const compileWalker = createWalker(template.content);
236+
const parts = {};
238237
const notDefinedElements = [];
238+
239239
let compileIndex = 0;
240240
let noTranslate = null;
241241

@@ -443,12 +443,20 @@ export function compileTemplate(rawParts, isSVG, isMsg, useLayout) {
443443
.map((e) => `<${e}>`)
444444
.join(", ")} element${
445445
notDefinedElements.length > 1 ? "s" : ""
446-
} found in the template:\n${beautifyTemplateLog(signature, -1)}`,
446+
} found in the template:\n${beautifyTemplateLog(content, -1)}`,
447447
);
448448
}
449449

450450
const partsKeys = Object.keys(parts);
451-
return function updateTemplateInstance(host, target, args, { styleSheets }) {
451+
return function updateTemplateInstance(host, target, options) {
452+
const { args, shadowOptions, styleSheets } = options;
453+
454+
if (shadowOptions) {
455+
target = host.shadowRoot || host.attachShadow(shadowOptions);
456+
} else {
457+
target = target || host;
458+
}
459+
452460
let meta = getMeta(target);
453461

454462
if (template !== meta.template) {
@@ -522,17 +530,20 @@ export function compileTemplate(rawParts, isSVG, isMsg, useLayout) {
522530

523531
for (const marker of meta.markers) {
524532
const value = args[marker.index];
525-
const prevValue = meta.prevArgs && meta.prevArgs[marker.index];
533+
let prevValue = undefined;
526534

527-
if (meta.prevArgs && value === prevValue) continue;
535+
if (meta.prevArgs) {
536+
prevValue = meta.prevArgs[marker.index];
537+
if (prevValue === value) continue;
538+
}
528539

529540
try {
530541
marker.fn(host, marker.node, value, prevValue, useLayout);
531542
} catch (error) {
532543
console.error(
533544
`Error while updating template expression in ${stringifyElement(
534545
host,
535-
)}:\n${beautifyTemplateLog(signature, marker.index)}`,
546+
)}:\n${beautifyTemplateLog(content, marker.index)}`,
536547
);
537548

538549
throw error;

src/template/index.js

+18-16
Original file line numberDiff line numberDiff line change
@@ -6,42 +6,44 @@ import * as methods from "./methods.js";
66

77
const PLACEHOLDER = getPlaceholder();
88
const PLACEHOLDER_SVG = getPlaceholder("svg");
9-
const PLACEHOLDER_MSG = getPlaceholder("msg");
10-
const PLACEHOLDER_LAYOUT = getPlaceholder("layout");
119

1210
const templates = new Map();
13-
export function compile(parts, args, isSVG, isMsg) {
14-
function template(host, target = host) {
15-
let id = isMsg ? parts + PLACEHOLDER_MSG : parts.join(PLACEHOLDER);
16-
if (isSVG) id += PLACEHOLDER_SVG;
17-
const useLayout = template.useLayout;
18-
if (useLayout) id += PLACEHOLDER_LAYOUT;
11+
export function compile(parts, args, id, isSVG, isMsg) {
12+
function fn(host, target, shadowOptions) {
13+
id = id + fn.useLayout;
1914

2015
let render = templates.get(id);
2116
if (!render) {
22-
render = compileTemplate(parts, isSVG, isMsg, useLayout);
17+
render = compileTemplate(parts, isSVG, isMsg, fn.useLayout);
2318
templates.set(id, render);
2419
}
2520

26-
if (template.plugins) {
27-
template.plugins.reduce(
21+
fn.shadowOptions = shadowOptions;
22+
23+
if (fn.plugins) {
24+
fn.plugins.reduce(
2825
(acc, plugin) => plugin(acc),
29-
() => render(host, target, args, template),
26+
() => render(host, target, fn),
3027
)(host, target);
3128
} else {
32-
render(host, target, args, template);
29+
render(host, target, fn);
3330
}
31+
32+
return target;
3433
}
3534

36-
return Object.assign(template, methods);
35+
fn.args = args;
36+
return Object.assign(fn, methods);
3737
}
3838

3939
export function html(parts, ...args) {
40-
return compile(parts, args, false, false);
40+
const id = parts.join(PLACEHOLDER);
41+
return compile(parts, args, id, false, false);
4142
}
4243

4344
export function svg(parts, ...args) {
44-
return compile(parts, args, true, false);
45+
const id = parts.join(PLACEHOLDER) + PLACEHOLDER_SVG;
46+
return compile(parts, args, id, true, false);
4547
}
4648

4749
Object.freeze(Object.assign(html, helpers));

src/template/layout.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ export function inject(target) {
214214
const sheet = getCSSStyleSheet();
215215

216216
/* istanbul ignore else */
217-
if (hasAdoptedStylesheets) {
217+
if (hasAdoptedStylesheets && root.adoptedStyleSheets) {
218218
root.adoptedStyleSheets = [...root.adoptedStyleSheets, sheet];
219219
} else {
220220
if (root === globalThis.document) return;

test/spec/layout.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -98,12 +98,16 @@ describe("layout:", () => {
9898
expect(nestedHost.hasAttribute("layout")).toBe(false);
9999
});
100100

101-
it("uses layout engine for nested templates", () => {
101+
it("uses layout engine for nested templates when parent is in layout mode", () => {
102102
html`
103103
<template layout="row">${html`<div layout="column"></div>`}</template>
104104
`(host, host.attachShadow({ mode: "open" }));
105105

106106
expect(host.shadowRoot.children[0].className).not.toBeFalsy();
107+
108+
const el = document.createElement("div");
109+
html`<div layout="column"></div>`(el);
110+
expect(el.children[0].getAttribute("layout")).toBe("column");
107111
});
108112

109113
it("uses layout engine for nested array templates", () => {

0 commit comments

Comments
 (0)