@torpor/view 0.0.10 → 0.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/dist/{ServerSlotRender-AWF3bD5B.d.cts → ServerSlotRender-t1sOutne.d.cts} +1 -1
- package/dist/{ServerSlotRender-AWF3bD5B.d.ts → ServerSlotRender-t1sOutne.d.ts} +1 -1
- package/dist/{chunk-GO2L324Q.js → chunk-T6JGCJ5T.js} +5 -2
- package/dist/chunk-T6JGCJ5T.js.map +1 -0
- package/dist/compile.cjs +39 -32
- package/dist/compile.cjs.map +1 -1
- package/dist/compile.d.cts +1 -0
- package/dist/compile.d.ts +1 -0
- package/dist/compile.js +39 -32
- package/dist/compile.js.map +1 -1
- package/dist/index.cjs +4 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/metafile-cjs.json +1 -1
- package/dist/metafile-esm.json +1 -1
- package/dist/ssr.cjs +4 -1
- package/dist/ssr.cjs.map +1 -1
- package/dist/ssr.d.cts +2 -2
- package/dist/ssr.d.ts +2 -2
- package/dist/ssr.js +1 -1
- package/dist/ssr.js.map +1 -1
- package/package.json +7 -7
- package/scripts/buildTestOutput.ts +2 -121
- package/src/compile/build/client/buildAddFragment.ts +1 -1
- package/src/compile/build/client/buildAwaitNode.ts +1 -1
- package/src/compile/build/client/buildComponentNode.ts +1 -1
- package/src/compile/build/client/buildControlNode.ts +1 -1
- package/src/compile/build/client/buildElementNode.ts +7 -1
- package/src/compile/build/client/buildForNode.ts +1 -1
- package/src/compile/build/client/buildFragment.ts +1 -1
- package/src/compile/build/client/buildFragmentText.ts +7 -1
- package/src/compile/build/client/buildHeadNode.ts +1 -1
- package/src/compile/build/client/buildHtmlNode.ts +2 -6
- package/src/compile/build/client/buildIfNode.ts +1 -1
- package/src/compile/build/client/buildMount.ts +1 -1
- package/src/compile/build/client/buildNode.ts +1 -1
- package/src/compile/build/client/buildReplaceNode.ts +1 -1
- package/src/compile/build/client/buildRootNode.ts +1 -1
- package/src/compile/build/client/buildRun.ts +1 -1
- package/src/compile/build/client/buildScriptNode.ts +1 -1
- package/src/compile/build/client/buildSlotNode.ts +1 -1
- package/src/compile/build/client/buildSwitchNode.ts +1 -1
- package/src/compile/build/client/buildTextNode.ts +1 -1
- package/src/compile/build/client/replaceForVarNames.ts +1 -1
- package/src/compile/build/server/buildServerAwaitNode.ts +1 -1
- package/src/compile/build/server/buildServerComponentNode.ts +1 -1
- package/src/compile/build/server/buildServerControlNode.ts +1 -1
- package/src/compile/build/server/buildServerElementNode.ts +9 -1
- package/src/compile/build/server/buildServerForNode.ts +1 -1
- package/src/compile/build/server/buildServerHtmlNode.ts +1 -1
- package/src/compile/build/server/buildServerIfNode.ts +1 -1
- package/src/compile/build/server/buildServerNode.ts +5 -1
- package/src/compile/build/server/buildServerReplaceNode.ts +1 -1
- package/src/compile/build/server/buildServerRootNode.ts +5 -1
- package/src/compile/build/server/buildServerScriptNode.ts +1 -1
- package/src/compile/build/server/buildServerSlotNode.ts +1 -1
- package/src/compile/build/server/buildServerSpecialNode.ts +1 -1
- package/src/compile/build/server/buildServerSwitchNode.ts +1 -1
- package/src/compile/build/server/buildServerTextNode.ts +1 -1
- package/src/compile/build/utils/isFullyReactive.ts +1 -1
- package/src/compile/build/utils/isReactive.ts +1 -1
- package/src/compile/build/utils/isReactiveAttribute.ts +1 -1
- package/src/compile/parse/addSpaceElement.ts +4 -1
- package/src/compile/parse/parseControl.ts +4 -1
- package/src/compile/parse/parseImports.ts +1 -1
- package/src/compile/parse/parseMarkup.ts +1 -1
- package/src/compile/parse/parseStyles.ts +1 -1
- package/src/compile/parse/scopeStyles.ts +13 -21
- package/src/compile/parse/slottifyChildNodes.ts +1 -1
- package/src/compile/parse/utils/addError.ts +5 -1
- package/src/compile/parse/utils/consumeUntil.ts +1 -1
- package/src/compile/parse/utils/isAlphaNumeric.ts +1 -1
- package/src/compile/parse/utils/isAlphaNumericChar.ts +1 -1
- package/src/compile/parse/utils/isSpace.ts +1 -1
- package/src/compile/parse/utils/isSpaceChar.ts +1 -1
- package/src/compile/types/nodes/TemplateNode.ts +3 -0
- package/src/compile/utils/Builder.ts +3 -3
- package/src/compile/utils/trimEnd.ts +1 -1
- package/src/compile/utils/trimMatched.ts +1 -1
- package/src/compile/utils/trimQuotes.ts +1 -1
- package/src/compile/utils/trimStart.ts +1 -1
- package/src/compile/utils/trimStartAndEnd.ts +1 -1
- package/src/compile/utils/voidTags.ts +1 -1
- package/src/debug/printHtml.ts +1 -1
- package/src/motion/animate.ts +1 -1
- package/src/render/$mount.ts +1 -1
- package/src/render/$run.ts +1 -1
- package/src/render/$serverMount.ts +1 -1
- package/src/render/$serverRun.ts +1 -1
- package/src/render/$stream.ts +1 -1
- package/src/render/addAnimation.ts +1 -1
- package/src/render/addEvent.ts +1 -1
- package/src/render/addFragment.ts +1 -1
- package/src/render/applyProps.ts +1 -1
- package/src/render/clearRange.ts +1 -1
- package/src/render/createComment.ts +1 -1
- package/src/render/createElement.ts +1 -1
- package/src/render/createFragment.ts +1 -1
- package/src/render/createText.ts +1 -1
- package/src/render/flushMountEffects.ts +1 -1
- package/src/render/getClasses.ts +4 -1
- package/src/render/hydrate.ts +1 -1
- package/src/render/hydrateRoot.ts +1 -1
- package/src/render/mount.ts +1 -1
- package/src/render/moveRange.ts +1 -1
- package/src/render/popRange.ts +1 -1
- package/src/render/runControl.ts +1 -1
- package/src/render/runControlBranch.ts +1 -1
- package/src/render/runList.ts +1 -1
- package/src/render/runListItems.ts +1 -1
- package/src/render/setAttribute.ts +1 -1
- package/src/render/setDynamicElement.ts +1 -1
- package/src/watch/proxyGet.ts +1 -1
- package/src/watch/removeEffect.ts +1 -1
- package/src/watch/runEffect.ts +1 -1
- package/src/watch/symbols.ts +1 -1
- package/src/watch/trackEffect.ts +1 -1
- package/src/watch/transferEffects.ts +1 -1
- package/src/watch/triggerEffects.ts +1 -1
- package/test/bench/components/output/Bench-client.ts +0 -204
- package/test/bench/components/output/Bench-server.ts +0 -130
- package/test/bench/components/temp/Bench-client-5fee290225ae4771aa847360006123671e8f17f1.ts +208 -0
- package/test/bench/components/temp/Bench-server-00cefa588803c01ca4f2741c595e4f045cdd101e.ts +130 -0
- package/test/build-server/components/{output/IfNested-client.ts → temp/IfNested-client-979db97eea5b4595550b9b46f297f3fbc31796d2.ts} +11 -0
- package/test/buildHtml.ts +1 -1
- package/test/buildOutputFiles.ts +47 -12
- package/test/class/class.test.ts +29 -6
- package/test/class/components/Class.torp +15 -1
- package/test/class/components/output/Class-client.ts +10 -6
- package/test/class/components/output/Class-server.ts +1 -1
- package/test/class/components/temp/{Class-client-600bf865c14f1052d24e1c79242f837aaf5ae5e8.ts → Class-client-8c3f9e0257cc2b687e9bb7106cccbab94a4b5adf.ts} +10 -6
- package/test/class/components/temp/Class-server-2218c3284845fdab80d1a41ebace9a9e2ddd6fc1.ts +17 -0
- package/test/component/components/temp/Header-client-ac151eea86e3f6b058fab101661e13ae73864968.ts +34 -0
- package/test/component/components/temp/Header-server-4f10f2332f3ca7a097517cfb938ab1e6f31d68ac.ts +17 -0
- package/test/console/components/temp/{Console-client-254d7d4799471401334d698b1631ab1cb5b70558.ts → Console-client-2f206752ce59e59fba9bb91263b4102fd515951e.ts} +1 -1
- package/test/console/components/temp/Console-server-b4b15f7a0d1d2b50d87bad4870e1b8d368707c04.ts +17 -0
- package/test/globalSetup.ts +1 -1
- package/test/helpers.ts +6 -2
- package/test/hydrateComponent.ts +1 -1
- package/test/importComponent.ts +12 -40
- package/test/mountComponent.ts +5 -1
- package/test/party/components/temp/AnswerButton-client-243454cd7bf84c648f244b3587e60d01a0401039.ts +33 -0
- package/test/party/components/temp/AnswerButton-server-938e46c1d2510ea37454854ef527e4aa64eb8e52.ts +16 -0
- package/test/party/components/temp/FunnyButton-client-2e6bec8259065b5bc9ae16d1ca93dd1bd0c56b7c.ts +40 -0
- package/test/party/components/temp/FunnyButton-server-e8ab55e47c735f7e42c55d2b7504dfa4190a1b40.ts +32 -0
- package/test/party/components/temp/Time-client-7ba4ca9322af2cb88a873c812fc776760c337c64.ts +47 -0
- package/test/party/components/temp/Time-server-08f66c7f3f32b13de06d75fe679cf58b5727c473.ts +31 -0
- package/test/party/components/temp/UserProfile-client-938bcef20a2555de22aca939022a32742ac5e729.ts +51 -0
- package/test/party/components/temp/UserProfile-server-9df5c59b8797fa67c479bc76450104d45e6076f9.ts +22 -0
- package/test/party/components/temp/UserProfileContext-client-93211cdba795b8baf926f60f5b17da90701743b3.ts +44 -0
- package/test/party/components/temp/UserProfileContext-server-cf58767df1e2d1dde919f59de73cdd9764bbc006.ts +20 -0
- package/test/slots/components/temp/Article-client-741f94eab2e96655f4c9d69ccd7d9c7cc998f4ce.ts +41 -0
- package/test/slots/components/temp/Article-server-a6bd47a621cc213db4313eb775a52246541dd203.ts +28 -0
- package/test/slots/components/temp/Header-client-e2e1e7d60b48b0841cd0c20224f520330ca96458.ts +38 -0
- package/test/slots/components/temp/Header-server-1c195508a91c32822da22a08576c8a30c9070636.ts +22 -0
- package/test/slots/components/temp/List-client-0659d999cfb48b865fe5b8aaaf2a4ddac3a8a8b6.ts +76 -0
- package/test/slots/components/temp/List-server-4b76485a259d054187edad8aa691d80ac918ad86.ts +25 -0
- package/test/special-component/components/temp/BigTitle-client-881a9f84876fb3f6d994736edb253b96e71de926.ts +32 -0
- package/test/special-component/components/temp/BigTitle-server-9efc738f5eb131a4b859c4a99a8e255d93834e9a.ts +20 -0
- package/test/special-component/components/temp/SmallTitle-client-25b3097b7ae47848dd82967403faf7745fc43388.ts +32 -0
- package/test/special-component/components/temp/SmallTitle-server-fc105db9a91b83644d67e049ce583a3d1a61f50c.ts +20 -0
- package/tsconfig.json +1 -1
- package/tsup.config.ts +7 -2
- package/vitest.config.ts +2 -2
- package/dist/chunk-GO2L324Q.js.map +0 -1
- package/test/bench/components/temp/Bench-client-3efcd3b6c03c7a51368df3b8b1bdf2e7fa722432.ts +0 -126
- package/test/build-server/components/IfNested.d.ts +0 -18
- package/test/class/components/temp/Class-server-082505b03612c762384ffff329472db3f55b8097.ts +0 -17
- /package/test/build-server/components/{output/IfNested-server.ts → temp/IfNested-server-3c4e4b6f2162c0906cef685830219b9ea9ee985c.ts} +0 -0
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import $watch from "../../../../src/render/$serverWatch";
|
|
2
|
+
import { type ServerSlotRender } from "../../../../src/types/ServerSlotRender";
|
|
3
|
+
import t_class from "../../../../src/render/getClasses";
|
|
4
|
+
import t_fmt from "../../../../src/render/formatText";
|
|
5
|
+
|
|
6
|
+
export default function Bench(
|
|
7
|
+
// @ts-ignore
|
|
8
|
+
$props?: Record<PropertyKey, any>,
|
|
9
|
+
// @ts-ignore
|
|
10
|
+
$context?: Record<PropertyKey, any>,
|
|
11
|
+
// @ts-ignore
|
|
12
|
+
$slots?: Record<string, ServerSlotRender>
|
|
13
|
+
) {
|
|
14
|
+
let rowId = 1;
|
|
15
|
+
let $state = $watch({
|
|
16
|
+
data: [],
|
|
17
|
+
selected: null,
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const adjectives = [
|
|
21
|
+
"pretty",
|
|
22
|
+
"large",
|
|
23
|
+
"big",
|
|
24
|
+
"small",
|
|
25
|
+
"tall",
|
|
26
|
+
"short",
|
|
27
|
+
"long",
|
|
28
|
+
"handsome",
|
|
29
|
+
"plain",
|
|
30
|
+
"quaint",
|
|
31
|
+
"clean",
|
|
32
|
+
"elegant",
|
|
33
|
+
"easy",
|
|
34
|
+
"angry",
|
|
35
|
+
"crazy",
|
|
36
|
+
"helpful",
|
|
37
|
+
"mushy",
|
|
38
|
+
"odd",
|
|
39
|
+
"unsightly",
|
|
40
|
+
"adorable",
|
|
41
|
+
"important",
|
|
42
|
+
"inexpensive",
|
|
43
|
+
"cheap",
|
|
44
|
+
"expensive",
|
|
45
|
+
"fancy",
|
|
46
|
+
];
|
|
47
|
+
const colours = ["red", "yellow", "blue", "green", "pink", "brown", "purple", "brown", "white", "black", "orange"];
|
|
48
|
+
const nouns = [
|
|
49
|
+
"table",
|
|
50
|
+
"chair",
|
|
51
|
+
"house",
|
|
52
|
+
"bbq",
|
|
53
|
+
"desk",
|
|
54
|
+
"car",
|
|
55
|
+
"pony",
|
|
56
|
+
"cookie",
|
|
57
|
+
"sandwich",
|
|
58
|
+
"burger",
|
|
59
|
+
"pizza",
|
|
60
|
+
"mouse",
|
|
61
|
+
"keyboard",
|
|
62
|
+
];
|
|
63
|
+
|
|
64
|
+
function append() {
|
|
65
|
+
$state.data = [...$state.data, ...buildData(1000)];
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function clear() {
|
|
69
|
+
$state.data = [];
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function partialUpdate() {
|
|
73
|
+
for (let i = 0; i < $state.data.length; i += 10) {
|
|
74
|
+
const row = $state.data[i];
|
|
75
|
+
row.label = row.label + " !!!";
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function remove(row) {
|
|
80
|
+
const clone = $state.data.slice();
|
|
81
|
+
clone.splice(clone.indexOf(row), 1);
|
|
82
|
+
$state.data = clone;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function create() {
|
|
86
|
+
// TODO: Build this up to 1000:
|
|
87
|
+
$state.data = buildData(10);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function createLots() {
|
|
91
|
+
$state.data = buildData(10000);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function swapRows() {
|
|
95
|
+
if ($state.data.length > 998) {
|
|
96
|
+
const clone = $state.data.slice();
|
|
97
|
+
const tmp = clone[1];
|
|
98
|
+
clone[1] = clone[998];
|
|
99
|
+
clone[998] = tmp;
|
|
100
|
+
$state.data = clone;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function _random(max) {
|
|
105
|
+
return Math.round(Math.random() * 1000) % max;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
class Item {
|
|
109
|
+
id = rowId++;
|
|
110
|
+
label = `${adjectives[_random(adjectives.length)]} ${colours[_random(colours.length)]} ${nouns[_random(nouns.length)]}`;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function buildData(count = 1000) {
|
|
114
|
+
const data = new Array(count);
|
|
115
|
+
for (let i = 0; i < count; i++) {
|
|
116
|
+
data[i] = $watch(new Item());
|
|
117
|
+
}
|
|
118
|
+
return data;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/* User interface */
|
|
122
|
+
let $output = "";
|
|
123
|
+
$output += `<div id="main" class="container"> <div class="jumbotron"> <div class="row"> <div class="col-md-6"> <h1>Torpor (keyed)</h1> </div> <div class="col-md-6"> <div class="row"> <div class="col-sm-6 smallpad"> <button type="button" class="btn btn-primary btn-block" id="create">Create 1,000 rows</button> </div> <div class="col-sm-6 smallpad"> <button type="button" class="btn btn-primary btn-block" id="createlots"> Create 10,000 rows </button> </div> <div class="col-sm-6 smallpad"> <button type="button" class="btn btn-primary btn-block" id="append"> Append 1,000 rows </button> </div> <div class="col-sm-6 smallpad"> <button type="button" class="btn btn-primary btn-block" id="update"> Update every 10th row </button> </div> <div class="col-sm-6 smallpad"> <button type="button" class="btn btn-primary btn-block" id="clear">Clear</button> </div> <div class="col-sm-6 smallpad"> <button type="button" class="btn btn-primary btn-block" id="swaprows">Swap Rows</button> </div> </div> </div> </div> </div> <table class="table table-hover table-striped test-data"> <tbody> <![>`;
|
|
124
|
+
for (let row of $state.data) {
|
|
125
|
+
$output += `<!^> <tr class="${t_class({ danger: $state.selected === row.id })}"> <td class="col-md-1">${t_fmt(row.id)}</td> <td class="col-md-4"> <a> ${t_fmt(row.label)} </a> </td> <td class="col-md-1"> <a> <span class="glyphicon glyphicon-remove" aria-hidden="true"></span> </a> </td> <td class="col-md-6"></td> </tr> `;
|
|
126
|
+
}
|
|
127
|
+
$output += `<!]><!> </tbody> </table> <span class="preloadicon glyphicon glyphicon-remove" aria-hidden="true"></span> </div>`;
|
|
128
|
+
|
|
129
|
+
return $output;
|
|
130
|
+
}
|
|
@@ -18,11 +18,13 @@ export default function IfNested(
|
|
|
18
18
|
// @ts-ignore
|
|
19
19
|
$slots?: Record<string, SlotRender>
|
|
20
20
|
) {
|
|
21
|
+
$props ??= {};
|
|
21
22
|
|
|
22
23
|
/* User interface */
|
|
23
24
|
const t_fragments: DocumentFragment[] = [];
|
|
24
25
|
|
|
25
26
|
const t_fragment_0 = t_fragment($parent.ownerDocument!, t_fragments, 0, `<div> <!> </div>`);
|
|
27
|
+
// @ts-ignore
|
|
26
28
|
const t_div_1 = t_root(t_fragment_0) as HTMLDivElement;
|
|
27
29
|
const t_if_anchor_1 = t_anchor(t_next(t_child(t_div_1))) as HTMLElement;
|
|
28
30
|
|
|
@@ -32,6 +34,7 @@ export default function IfNested(
|
|
|
32
34
|
if ($props.counter > 5) {
|
|
33
35
|
t_run_branch(t_if_range_1, 0, () => {
|
|
34
36
|
const t_fragment_1 = t_fragment($parent.ownerDocument!, t_fragments, 1, ` <!> `);
|
|
37
|
+
// @ts-ignore
|
|
35
38
|
const t_root_1 = t_root(t_fragment_1);
|
|
36
39
|
const t_if_anchor_2 = t_anchor(t_next(t_root_1)) as HTMLElement;
|
|
37
40
|
|
|
@@ -41,7 +44,9 @@ export default function IfNested(
|
|
|
41
44
|
if ($props.counter > 10) {
|
|
42
45
|
t_run_branch(t_if_range_2, 0, () => {
|
|
43
46
|
const t_fragment_2 = t_fragment($parent.ownerDocument!, t_fragments, 2, ` <p> It's both true! </p> `);
|
|
47
|
+
// @ts-ignore
|
|
44
48
|
const t_root_2 = t_root(t_fragment_2);
|
|
49
|
+
// @ts-ignore
|
|
45
50
|
const t_text_1 = t_next(t_next(t_root_2));
|
|
46
51
|
t_add_fragment(t_fragment_2, t_fragment_1, t_before);
|
|
47
52
|
t_next(t_text_1);
|
|
@@ -50,7 +55,9 @@ export default function IfNested(
|
|
|
50
55
|
else {
|
|
51
56
|
t_run_branch(t_if_range_2, 1, () => {
|
|
52
57
|
const t_fragment_3 = t_fragment($parent.ownerDocument!, t_fragments, 3, ` <p> The second is not true! </p> `);
|
|
58
|
+
// @ts-ignore
|
|
53
59
|
const t_root_3 = t_root(t_fragment_3);
|
|
60
|
+
// @ts-ignore
|
|
54
61
|
const t_text_2 = t_next(t_next(t_root_3));
|
|
55
62
|
t_add_fragment(t_fragment_3, t_fragment_1, t_before);
|
|
56
63
|
t_next(t_text_2);
|
|
@@ -58,6 +65,7 @@ export default function IfNested(
|
|
|
58
65
|
}
|
|
59
66
|
});
|
|
60
67
|
|
|
68
|
+
// @ts-ignore
|
|
61
69
|
const t_text_3 = t_next(t_if_anchor_2);
|
|
62
70
|
t_add_fragment(t_fragment_1, t_div_1, t_before);
|
|
63
71
|
t_next(t_text_3);
|
|
@@ -66,7 +74,9 @@ export default function IfNested(
|
|
|
66
74
|
else {
|
|
67
75
|
t_run_branch(t_if_range_1, 1, () => {
|
|
68
76
|
const t_fragment_4 = t_fragment($parent.ownerDocument!, t_fragments, 4, ` <p> The first is not true! </p> `);
|
|
77
|
+
// @ts-ignore
|
|
69
78
|
const t_root_4 = t_root(t_fragment_4);
|
|
79
|
+
// @ts-ignore
|
|
70
80
|
const t_text_4 = t_next(t_next(t_root_4));
|
|
71
81
|
t_add_fragment(t_fragment_4, t_div_1, t_before);
|
|
72
82
|
t_next(t_text_4);
|
|
@@ -75,5 +85,6 @@ export default function IfNested(
|
|
|
75
85
|
});
|
|
76
86
|
|
|
77
87
|
t_add_fragment(t_fragment_0, $parent, $anchor);
|
|
88
|
+
t_next(t_div_1);
|
|
78
89
|
|
|
79
90
|
}
|
package/test/buildHtml.ts
CHANGED
|
@@ -8,7 +8,7 @@ import { type BuildResult } from "../src/compile/types/BuildResult";
|
|
|
8
8
|
|
|
9
9
|
const debugPrint = false;
|
|
10
10
|
|
|
11
|
-
export default function buildHtml(source: string, state?: any, componentPath?: string) {
|
|
11
|
+
export default function buildHtml(source: string, state?: any, componentPath?: string): string {
|
|
12
12
|
// HACK: we may be running this from the top level, or from within the view folder
|
|
13
13
|
if (componentPath && !fs.existsSync(componentPath)) {
|
|
14
14
|
componentPath = path.join("view", componentPath);
|
package/test/buildOutputFiles.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import fg from "fast-glob";
|
|
2
|
-
import
|
|
2
|
+
import crypto from "node:crypto";
|
|
3
|
+
import { existsSync, promises as fs, unlinkSync } from "node:fs";
|
|
3
4
|
import path from "node:path";
|
|
4
|
-
import { buildType } from "../src/compile";
|
|
5
5
|
import build from "../src/compile/build";
|
|
6
6
|
import parse from "../src/compile/parse";
|
|
7
7
|
|
|
8
|
-
export default async function buildOutputFiles(componentPath: string) {
|
|
8
|
+
export default async function buildOutputFiles(componentPath: string): Promise<void> {
|
|
9
9
|
//console.log("Building test output files", componentPath);
|
|
10
10
|
const files = await fg("**/*.torp", {
|
|
11
11
|
absolute: true,
|
|
@@ -15,7 +15,7 @@ export default async function buildOutputFiles(componentPath: string) {
|
|
|
15
15
|
//console.log("Done\n");
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
async function buildFiles(file: string) {
|
|
18
|
+
export async function buildFiles(file: string): Promise<void> {
|
|
19
19
|
//console.log(`Building files for ${file.substring(path.resolve("./test").length)}`);
|
|
20
20
|
|
|
21
21
|
const source = await fs.readFile(file, "utf8");
|
|
@@ -23,22 +23,57 @@ async function buildFiles(file: string) {
|
|
|
23
23
|
if (parsed.ok && parsed.template) {
|
|
24
24
|
let serverCode = formatCode(build(parsed.template, { server: true }).code, "server");
|
|
25
25
|
let clientCode = formatCode(build(parsed.template).code, "client");
|
|
26
|
+
await maybeWriteFile(file, clientCode, "client");
|
|
27
|
+
await maybeWriteFile(file, serverCode, "server");
|
|
28
|
+
} else {
|
|
29
|
+
// Just log the message and continue with output/testing
|
|
30
|
+
console.log("PARSE FAILED for " + file);
|
|
31
|
+
console.log(parsed.errors.map((e) => e.message).join("\n"));
|
|
32
|
+
}
|
|
33
|
+
}
|
|
26
34
|
|
|
27
|
-
|
|
28
|
-
|
|
35
|
+
async function maybeWriteFile(file: string, code: string, suffix: string) {
|
|
36
|
+
//const hash = await hashFileContents(code);
|
|
37
|
+
const hash = hashFileCode(code);
|
|
38
|
+
|
|
39
|
+
// If the hashed file doesn't exist, update it and the output file
|
|
40
|
+
let outputFile = file
|
|
41
|
+
.replace("/components/", "/components/temp/")
|
|
42
|
+
.replace(".torp", `-${suffix}-${hash}.ts`);
|
|
43
|
+
if (!existsSync(outputFile)) {
|
|
44
|
+
console.log(`Building files for ${file}`);
|
|
45
|
+
|
|
46
|
+
let outputFolder = path.dirname(outputFile);
|
|
47
|
+
if (!existsSync(outputFolder)) {
|
|
48
|
+
await fs.mkdir(outputFolder);
|
|
49
|
+
}
|
|
29
50
|
|
|
30
|
-
|
|
51
|
+
// Delete old files
|
|
52
|
+
const glob = `${path.basename(file, ".torp")}-${suffix}-*.ts`;
|
|
53
|
+
const oldFiles = await fg(glob, {
|
|
54
|
+
absolute: true,
|
|
55
|
+
cwd: path.resolve(outputFolder),
|
|
56
|
+
});
|
|
57
|
+
oldFiles.forEach((f) => unlinkSync(f));
|
|
58
|
+
|
|
59
|
+
// Create the new hash file
|
|
60
|
+
await fs.writeFile(outputFile, code);
|
|
61
|
+
|
|
62
|
+
// Create the new output file
|
|
63
|
+
outputFile = file
|
|
64
|
+
.replace("/components/", "/components/output/")
|
|
65
|
+
.replace(".torp", `-${suffix}.ts`);
|
|
31
66
|
if (!existsSync(path.dirname(outputFile))) {
|
|
32
67
|
await fs.mkdir(path.dirname(outputFile));
|
|
33
68
|
}
|
|
34
|
-
await fs.writeFile(outputFile
|
|
35
|
-
await fs.writeFile(outputFile.replace(".torp", "-client.ts"), clientCode);
|
|
36
|
-
} else {
|
|
37
|
-
// Just log the message and continue with output/testing
|
|
38
|
-
console.log("Parse failed for " + file);
|
|
69
|
+
await fs.writeFile(outputFile, code);
|
|
39
70
|
}
|
|
40
71
|
}
|
|
41
72
|
|
|
73
|
+
function hashFileCode(code: string) {
|
|
74
|
+
return crypto.createHash("sha1").update(code).digest("hex");
|
|
75
|
+
}
|
|
76
|
+
|
|
42
77
|
function formatCode(code: string, suffix: string): string {
|
|
43
78
|
// Replace imports from the built @torpor/view to the source code, so that
|
|
44
79
|
// a) we don't have to build @torpor/view before testing, and
|
package/test/class/class.test.ts
CHANGED
|
@@ -49,21 +49,44 @@ test("class -- hydrated", async () => {
|
|
|
49
49
|
});
|
|
50
50
|
|
|
51
51
|
function check(container: HTMLElement, state: State) {
|
|
52
|
-
expect(queryByText(container, "
|
|
53
|
-
expect(queryByText(container, "
|
|
52
|
+
expect(queryByText(container, "From string")).not.toBeNull();
|
|
53
|
+
expect(queryByText(container, "From string")).toHaveClass("yo torp-1ljxz83", {
|
|
54
|
+
exact: true,
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
expect(queryByText(container, "From state")).not.toBeNull();
|
|
58
|
+
expect(queryByText(container, "From state")).toHaveClass("hello red blue torp-1ljxz83", {
|
|
59
|
+
exact: true,
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
expect(queryByText(container, "From state with scope")).not.toBeNull();
|
|
63
|
+
expect(queryByText(container, "From state with scope")).toHaveClass(
|
|
64
|
+
"hello red blue torp-1ljxz83",
|
|
65
|
+
{
|
|
66
|
+
exact: true,
|
|
67
|
+
},
|
|
68
|
+
);
|
|
54
69
|
|
|
55
70
|
expect(queryByText(container, "Class object")).not.toBeNull();
|
|
56
|
-
expect(queryByText(container, "Class object")).toHaveClass("foo baz", {
|
|
71
|
+
expect(queryByText(container, "Class object")).toHaveClass("foo baz torp-1ljxz83", {
|
|
72
|
+
exact: true,
|
|
73
|
+
});
|
|
57
74
|
|
|
58
75
|
expect(queryByText(container, "Class array")).not.toBeNull();
|
|
59
|
-
expect(queryByText(container, "Class array")).toHaveClass("foo baz", {
|
|
76
|
+
expect(queryByText(container, "Class array")).toHaveClass("foo baz torp-1ljxz83", {
|
|
77
|
+
exact: true,
|
|
78
|
+
});
|
|
60
79
|
|
|
61
80
|
expect(queryByText(container, "Class nested")).not.toBeNull();
|
|
62
|
-
expect(queryByText(container, "Class nested")).toHaveClass("foo bar baz qux", {
|
|
81
|
+
expect(queryByText(container, "Class nested")).toHaveClass("foo bar baz qux torp-1ljxz83", {
|
|
82
|
+
exact: true,
|
|
83
|
+
});
|
|
63
84
|
|
|
64
85
|
// Change state
|
|
65
86
|
state.green = true;
|
|
66
87
|
state.blue = false;
|
|
67
88
|
|
|
68
|
-
expect(queryByText(container, "
|
|
89
|
+
expect(queryByText(container, "From state")).toHaveClass("hello red green torp-1ljxz83", {
|
|
90
|
+
exact: true,
|
|
91
|
+
});
|
|
69
92
|
}
|
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
export default function Class() {
|
|
2
2
|
@render {
|
|
3
3
|
<div>
|
|
4
|
+
<div class="yo">
|
|
5
|
+
From string
|
|
6
|
+
</div>
|
|
7
|
+
|
|
8
|
+
<a :class={{ hello: true, red: $props.red, green: $props.green, blue: $props.blue }}>
|
|
9
|
+
From state
|
|
10
|
+
</a>
|
|
11
|
+
|
|
4
12
|
<div :class={{ hello: true, red: $props.red, green: $props.green, blue: $props.blue }}>
|
|
5
|
-
|
|
13
|
+
From state with scope
|
|
6
14
|
</div>
|
|
7
15
|
|
|
8
16
|
<div :class={{ foo: true, bar: false, baz: 5, qux: null }}>
|
|
@@ -18,4 +26,10 @@ export default function Class() {
|
|
|
18
26
|
</div>
|
|
19
27
|
</div>
|
|
20
28
|
}
|
|
29
|
+
|
|
30
|
+
@style {
|
|
31
|
+
div {
|
|
32
|
+
color: blue;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
21
35
|
}
|
|
@@ -21,24 +21,28 @@ export default function Class(
|
|
|
21
21
|
/* User interface */
|
|
22
22
|
const t_fragments: DocumentFragment[] = [];
|
|
23
23
|
|
|
24
|
-
const t_fragment_0 = t_fragment($parent.ownerDocument!, t_fragments, 0, `<div> <div>
|
|
24
|
+
const t_fragment_0 = t_fragment($parent.ownerDocument!, t_fragments, 0, `<div> <div class="yo torp-1ljxz83"> From string </div> <a> From state </a> <div> From state with scope </div> <div> Class object </div> <div> Class array </div> <div> Class nested </div> </div>`);
|
|
25
25
|
// @ts-ignore
|
|
26
26
|
const t_div_1 = t_root(t_fragment_0) as HTMLDivElement;
|
|
27
|
-
const
|
|
27
|
+
const t_a_1 = t_next(t_next(t_next(t_child(t_div_1)))) as HTMLElement;
|
|
28
|
+
const t_div_2 = t_next(t_next(t_a_1)) as HTMLDivElement;
|
|
28
29
|
const t_div_3 = t_next(t_next(t_div_2)) as HTMLDivElement;
|
|
29
30
|
const t_div_4 = t_next(t_next(t_div_3)) as HTMLDivElement;
|
|
30
31
|
const t_div_5 = t_next(t_next(t_div_4)) as HTMLDivElement;
|
|
31
32
|
$run(function setClasses() {
|
|
32
|
-
|
|
33
|
+
t_a_1.className = t_class({ hello: true, red: $props.red, green: $props.green, blue: $props.blue }, "torp-1ljxz83");
|
|
33
34
|
});
|
|
34
35
|
$run(function setClasses() {
|
|
35
|
-
|
|
36
|
+
t_div_2.className = t_class({ hello: true, red: $props.red, green: $props.green, blue: $props.blue }, "torp-1ljxz83");
|
|
36
37
|
});
|
|
37
38
|
$run(function setClasses() {
|
|
38
|
-
|
|
39
|
+
t_div_3.className = t_class({ foo: true, bar: false, baz: 5, qux: null }, "torp-1ljxz83");
|
|
39
40
|
});
|
|
40
41
|
$run(function setClasses() {
|
|
41
|
-
|
|
42
|
+
t_div_4.className = t_class([ "foo", false, true && "baz", undefined ], "torp-1ljxz83");
|
|
43
|
+
});
|
|
44
|
+
$run(function setClasses() {
|
|
45
|
+
t_div_5.className = t_class([ "foo", 0, { bar: true }, "", [1 && "baz", ["qux"]] ], "torp-1ljxz83");
|
|
42
46
|
});
|
|
43
47
|
t_add_fragment(t_fragment_0, $parent, $anchor);
|
|
44
48
|
t_next(t_div_1);
|
|
@@ -11,7 +11,7 @@ export default function Class(
|
|
|
11
11
|
|
|
12
12
|
/* User interface */
|
|
13
13
|
let $output = "";
|
|
14
|
-
$output += `<div> <div class="${t_class({ hello: true, red: $props.red, green: $props.green, blue: $props.blue })}">
|
|
14
|
+
$output += `<div> <div class="yo torp-1ljxz83"> From string </div> <a class="${t_class({ hello: true, red: $props.red, green: $props.green, blue: $props.blue }, "torp-1ljxz83")}"> From state </a> <div class="${t_class({ hello: true, red: $props.red, green: $props.green, blue: $props.blue }, "torp-1ljxz83")}"> From state with scope </div> <div class="${t_class({ foo: true, bar: false, baz: 5, qux: null }, "torp-1ljxz83")}"> Class object </div> <div class="${t_class([ "foo", false, true && "baz", undefined ], "torp-1ljxz83")}"> Class array </div> <div class="${t_class([ "foo", 0, { bar: true }, "", [1 && "baz", ["qux"]] ], "torp-1ljxz83")}"> Class nested </div> </div>`;
|
|
15
15
|
|
|
16
16
|
return $output;
|
|
17
17
|
}
|
|
@@ -21,24 +21,28 @@ export default function Class(
|
|
|
21
21
|
/* User interface */
|
|
22
22
|
const t_fragments: DocumentFragment[] = [];
|
|
23
23
|
|
|
24
|
-
const t_fragment_0 = t_fragment($parent.ownerDocument!, t_fragments, 0, `<div> <div>
|
|
24
|
+
const t_fragment_0 = t_fragment($parent.ownerDocument!, t_fragments, 0, `<div> <div class="yo torp-1ljxz83"> From string </div> <a> From state </a> <div> From state with scope </div> <div> Class object </div> <div> Class array </div> <div> Class nested </div> </div>`);
|
|
25
25
|
// @ts-ignore
|
|
26
26
|
const t_div_1 = t_root(t_fragment_0) as HTMLDivElement;
|
|
27
|
-
const
|
|
27
|
+
const t_a_1 = t_next(t_next(t_next(t_child(t_div_1)))) as HTMLElement;
|
|
28
|
+
const t_div_2 = t_next(t_next(t_a_1)) as HTMLDivElement;
|
|
28
29
|
const t_div_3 = t_next(t_next(t_div_2)) as HTMLDivElement;
|
|
29
30
|
const t_div_4 = t_next(t_next(t_div_3)) as HTMLDivElement;
|
|
30
31
|
const t_div_5 = t_next(t_next(t_div_4)) as HTMLDivElement;
|
|
31
32
|
$run(function setClasses() {
|
|
32
|
-
|
|
33
|
+
t_a_1.className = t_class({ hello: true, red: $props.red, green: $props.green, blue: $props.blue }, "torp-1ljxz83");
|
|
33
34
|
});
|
|
34
35
|
$run(function setClasses() {
|
|
35
|
-
|
|
36
|
+
t_div_2.className = t_class({ hello: true, red: $props.red, green: $props.green, blue: $props.blue }, "torp-1ljxz83");
|
|
36
37
|
});
|
|
37
38
|
$run(function setClasses() {
|
|
38
|
-
|
|
39
|
+
t_div_3.className = t_class({ foo: true, bar: false, baz: 5, qux: null }, "torp-1ljxz83");
|
|
39
40
|
});
|
|
40
41
|
$run(function setClasses() {
|
|
41
|
-
|
|
42
|
+
t_div_4.className = t_class([ "foo", false, true && "baz", undefined ], "torp-1ljxz83");
|
|
43
|
+
});
|
|
44
|
+
$run(function setClasses() {
|
|
45
|
+
t_div_5.className = t_class([ "foo", 0, { bar: true }, "", [1 && "baz", ["qux"]] ], "torp-1ljxz83");
|
|
42
46
|
});
|
|
43
47
|
t_add_fragment(t_fragment_0, $parent, $anchor);
|
|
44
48
|
t_next(t_div_1);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type ServerSlotRender } from "../../../../src/types/ServerSlotRender";
|
|
2
|
+
import t_class from "../../../../src/render/getClasses";
|
|
3
|
+
|
|
4
|
+
export default function Class(
|
|
5
|
+
$props: Record<PropertyKey, any>,
|
|
6
|
+
// @ts-ignore
|
|
7
|
+
$context?: Record<PropertyKey, any>,
|
|
8
|
+
// @ts-ignore
|
|
9
|
+
$slots?: Record<string, ServerSlotRender>
|
|
10
|
+
) {
|
|
11
|
+
|
|
12
|
+
/* User interface */
|
|
13
|
+
let $output = "";
|
|
14
|
+
$output += `<div> <div class="yo torp-1ljxz83"> From string </div> <a class="${t_class({ hello: true, red: $props.red, green: $props.green, blue: $props.blue }, "torp-1ljxz83")}"> From state </a> <div class="${t_class({ hello: true, red: $props.red, green: $props.green, blue: $props.blue }, "torp-1ljxz83")}"> From state with scope </div> <div class="${t_class({ foo: true, bar: false, baz: 5, qux: null }, "torp-1ljxz83")}"> Class object </div> <div class="${t_class([ "foo", false, true && "baz", undefined ], "torp-1ljxz83")}"> Class array </div> <div class="${t_class([ "foo", 0, { bar: true }, "", [1 && "baz", ["qux"]] ], "torp-1ljxz83")}"> Class nested </div> </div>`;
|
|
15
|
+
|
|
16
|
+
return $output;
|
|
17
|
+
}
|
package/test/component/components/temp/Header-client-ac151eea86e3f6b058fab101661e13ae73864968.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import $run from "../../../../src/render/$run";
|
|
2
|
+
import { type SlotRender } from "../../../../src/types/SlotRender";
|
|
3
|
+
import t_add_fragment from "../../../../src/render/addFragment";
|
|
4
|
+
import t_child from "../../../../src/render/nodeChild";
|
|
5
|
+
import t_fmt from "../../../../src/render/formatText";
|
|
6
|
+
import t_fragment from "../../../../src/render/getFragment";
|
|
7
|
+
import t_next from "../../../../src/render/nodeNext";
|
|
8
|
+
import t_root from "../../../../src/render/nodeRoot";
|
|
9
|
+
|
|
10
|
+
export default function Header(
|
|
11
|
+
$parent: ParentNode,
|
|
12
|
+
$anchor: Node | null,
|
|
13
|
+
$props: Record<PropertyKey, any>,
|
|
14
|
+
// @ts-ignore
|
|
15
|
+
$context?: Record<PropertyKey, any>,
|
|
16
|
+
// @ts-ignore
|
|
17
|
+
$slots?: Record<string, SlotRender>
|
|
18
|
+
) {
|
|
19
|
+
$props ??= {};
|
|
20
|
+
|
|
21
|
+
/* User interface */
|
|
22
|
+
const t_fragments: DocumentFragment[] = [];
|
|
23
|
+
|
|
24
|
+
const t_fragment_0 = t_fragment($parent.ownerDocument!, t_fragments, 0, `<h2>#</h2>`);
|
|
25
|
+
// @ts-ignore
|
|
26
|
+
const t_h2_1 = t_root(t_fragment_0) as HTMLElement;
|
|
27
|
+
const t_text_1 = t_child(t_h2_1);
|
|
28
|
+
$run(function setTextContent() {
|
|
29
|
+
t_text_1.textContent = `Hi, ${t_fmt($props.name)}`;
|
|
30
|
+
});
|
|
31
|
+
t_add_fragment(t_fragment_0, $parent, $anchor);
|
|
32
|
+
t_next(t_h2_1);
|
|
33
|
+
|
|
34
|
+
}
|
package/test/component/components/temp/Header-server-4f10f2332f3ca7a097517cfb938ab1e6f31d68ac.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type ServerSlotRender } from "../../../../src/types/ServerSlotRender";
|
|
2
|
+
import t_fmt from "../../../../src/render/formatText";
|
|
3
|
+
|
|
4
|
+
export default function Header(
|
|
5
|
+
$props: Record<PropertyKey, any>,
|
|
6
|
+
// @ts-ignore
|
|
7
|
+
$context?: Record<PropertyKey, any>,
|
|
8
|
+
// @ts-ignore
|
|
9
|
+
$slots?: Record<string, ServerSlotRender>
|
|
10
|
+
) {
|
|
11
|
+
|
|
12
|
+
/* User interface */
|
|
13
|
+
let $output = "";
|
|
14
|
+
$output += `<h2>Hi, ${t_fmt($props.name)}</h2>`;
|
|
15
|
+
|
|
16
|
+
return $output;
|
|
17
|
+
}
|
|
@@ -18,7 +18,7 @@ export default function Console(
|
|
|
18
18
|
/* User interface */
|
|
19
19
|
const t_fragments: DocumentFragment[] = [];
|
|
20
20
|
|
|
21
|
-
const t_fragment_0 = t_fragment($parent.ownerDocument!, t_fragments, 0, `<div> </div
|
|
21
|
+
const t_fragment_0 = t_fragment($parent.ownerDocument!, t_fragments, 0, `<div> </div>`);
|
|
22
22
|
// @ts-ignore
|
|
23
23
|
const t_div_1 = t_root(t_fragment_0) as HTMLDivElement;
|
|
24
24
|
/* @console */
|
package/test/console/components/temp/Console-server-b4b15f7a0d1d2b50d87bad4870e1b8d368707c04.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type ServerSlotRender } from "../../../../src/types/ServerSlotRender";
|
|
2
|
+
|
|
3
|
+
export default function Console(
|
|
4
|
+
// @ts-ignore
|
|
5
|
+
$props?: Record<PropertyKey, any>,
|
|
6
|
+
// @ts-ignore
|
|
7
|
+
$context?: Record<PropertyKey, any>,
|
|
8
|
+
// @ts-ignore
|
|
9
|
+
$slots?: Record<string, ServerSlotRender>
|
|
10
|
+
) {
|
|
11
|
+
|
|
12
|
+
/* User interface */
|
|
13
|
+
let $output = "";
|
|
14
|
+
$output += `<div> </div>`;
|
|
15
|
+
|
|
16
|
+
return $output;
|
|
17
|
+
}
|
package/test/globalSetup.ts
CHANGED
package/test/helpers.ts
CHANGED
|
@@ -28,12 +28,16 @@ export function el(
|
|
|
28
28
|
children?: TemplateNode[],
|
|
29
29
|
selfClosed?: boolean,
|
|
30
30
|
): ElementNode {
|
|
31
|
+
let scopeStyles = !!attributes?.find((a) => a.name === "class" && a.value?.startsWith(`"torp-`));
|
|
31
32
|
return {
|
|
32
33
|
type: "element",
|
|
33
34
|
tagName,
|
|
34
|
-
attributes: attributes || []
|
|
35
|
+
attributes: (attributes || []).filter(
|
|
36
|
+
(a) => !(a.name === "class" && a.value?.startsWith(`"torp-`)),
|
|
37
|
+
),
|
|
35
38
|
children: children || [],
|
|
36
39
|
selfClosed,
|
|
40
|
+
scopeStyles: scopeStyles || undefined,
|
|
37
41
|
closed: true,
|
|
38
42
|
};
|
|
39
43
|
}
|
|
@@ -116,7 +120,7 @@ function trimElement(el: RootNode | ElementNode | ControlNode) {
|
|
|
116
120
|
}
|
|
117
121
|
}
|
|
118
122
|
|
|
119
|
-
export function trimCode(code: string) {
|
|
123
|
+
export function trimCode(code: string): string {
|
|
120
124
|
//return code.split('\n').filter(l => !l.trim().startsWith("import"))
|
|
121
125
|
return code.replace(/\/\*\*.+\*\/\n/gms, "");
|
|
122
126
|
}
|
package/test/hydrateComponent.ts
CHANGED
|
@@ -7,7 +7,7 @@ export default function hydrateComponent(
|
|
|
7
7
|
clientComponent: Component,
|
|
8
8
|
serverComponent: ServerComponent,
|
|
9
9
|
state?: any,
|
|
10
|
-
) {
|
|
10
|
+
): void {
|
|
11
11
|
const html = serverComponent(state);
|
|
12
12
|
container.innerHTML = html;
|
|
13
13
|
container.ownerDocument.body.appendChild(container);
|