feat: basic nested hydration

This commit is contained in:
Michael Rawlings 2022-04-05 15:18:35 -04:00
parent 34d5ded435
commit 0ca372cc26
35 changed files with 947 additions and 65 deletions

View File

@ -6,9 +6,9 @@
{
"name": "*",
"total": {
"min": 9174,
"gzip": 4102,
"brotli": 3749
"min": 9194,
"gzip": 4113,
"brotli": 3759
}
},
{
@ -33,18 +33,18 @@
"name": "counter 💧",
"user": {
"min": 249,
"gzip": 196,
"brotli": 176
"gzip": 195,
"brotli": 194
},
"runtime": {
"min": 2149,
"gzip": 1168,
"brotli": 1043
"min": 2169,
"gzip": 1180,
"brotli": 1061
},
"total": {
"min": 2398,
"gzip": 1364,
"brotli": 1219
"min": 2418,
"gzip": 1375,
"brotli": 1255
}
}
]

View File

@ -22,7 +22,7 @@
"scripts": {
"build": "npm run build:types && npm run build:js",
"build:js": "node -r esbuild-register esbuild.ts",
"build:types": "tsc -b",
"build:types": "tsc -d",
"prepublishOnly": "npm run build"
}
}

View File

@ -93,7 +93,9 @@ export function init(runtimeId = "M" /* [a-zA-Z0-9]+ */) {
const scopeId = parseInt(
nodeValue.slice(nodeValue.lastIndexOf(" ") + 1)
);
const scope = scopeLookup[scopeId];
const scope = (scopeLookup[scopeId] = scopeLookup[scopeId] || {
___id: scopeId * SCOPE_ID_MULTIPLIER,
});
scope[data] = node;
} else if (token === HydrateSymbols.SECTION_START) {
if (currentScope) {

View File

@ -1,7 +1,9 @@
import { markHydrateNode as _markHydrateNode, write as _write, nextScopeId as _nextScopeId, createRenderer as _createRenderer } from "@marko/runtime-fluurt/src/html";
import _customTag from "./components/custom-tag/index.marko";
const _renderer = input => {
const _renderer = ({
x
}) => {
const _scope = _nextScopeId();
let _thing;
@ -10,14 +12,18 @@ const _renderer = input => {
_write(`${_markHydrateNode(_scope, 0)}`);
if (x) _thing = {
x: 1,
if (x) {
const _scope = _nextScopeId();
renderBody() {
_write("Hello");
}
_thing = {
x: 1,
};
renderBody() {
_write("Hello");
}
};
}
_customTag({
thing: _thing

View File

@ -14,6 +14,8 @@ const _renderer = input => {
a: 1,
b: 2
}) {
const _scope = _nextScopeId();
_item.push({});
}

View File

@ -1,6 +1,8 @@
import { write as _write, nextScopeId as _nextScopeId, createRenderer as _createRenderer } from "@marko/runtime-fluurt/src/html";
const _renderer = input => {
const _renderer = ({
x
}) => {
const _scope = _nextScopeId();
<${x} header={

View File

@ -1,7 +1,9 @@
import { markHydrateNode as _markHydrateNode, write as _write, escapeXML as _escapeXML, nextScopeId as _nextScopeId, createRenderer as _createRenderer } from "@marko/runtime-fluurt/src/html";
import _hello from "./components/hello/index.marko";
const _renderer = input => {
const _renderer = ({
x
}) => {
const _scope = _nextScopeId();
let _item;
@ -10,12 +12,16 @@ const _renderer = input => {
_write(`${_markHydrateNode(_scope, 0)}`);
if (x) _item = {
renderBody(y) {
_write(`${_markHydrateNode(_scope, 0)}${_escapeXML(y)}`);
}
if (x) {
const _scope = _nextScopeId();
};
_item = {
renderBody(y) {
_write(`${_markHydrateNode(_scope, 0)}${_escapeXML(y)}`);
}
};
}
_hello({
item: _item

View File

@ -1,4 +1,4 @@
import { markHydrateNode as _markHydrateNode, write as _write, escapeXML as _escapeXML, nextScopeId as _nextScopeId, createRenderer as _createRenderer } from "@marko/runtime-fluurt/src/html";
import { markHydrateNode as _markHydrateNode, write as _write, nextScopeId as _nextScopeId, escapeXML as _escapeXML, createRenderer as _createRenderer } from "@marko/runtime-fluurt/src/html";
import _hello from "./components/hello/index.marko";
const _renderer = input => {
@ -13,27 +13,37 @@ const _renderer = input => {
_write(`${_markHydrateNode(_scope, 0)}`);
for (const color of ["red", "blue", "green"]) {
const _scope = _nextScopeId();
_write(`${_markHydrateNode(_scope, 0)}`);
if (color === "red") _item.push({
style: {
color
},
if (color === "red") {
const _scope = _nextScopeId();
renderBody() {
_write("foo");
}
_item.push({
style: {
color
},
});else _item.push({
style: {
color
},
renderBody() {
_write("foo");
}
renderBody() {
_write("bar");
}
});
} else {
const _scope = _nextScopeId();
});
_item.push({
style: {
color
},
renderBody() {
_write("bar");
}
});
}
}
_write(`${_markHydrateNode(_scope, 0)}`);
@ -42,11 +52,16 @@ const _renderer = input => {
for (const col of [["a", "b"], ["c", "d"]]) {
let i = _i++;
const _scope = _nextScopeId();
const _row = [];
_write(`${_markHydrateNode(_scope, 0)}`);
for (const row of col) {
const _scope = _nextScopeId();
_row.push({
row: row,

View File

@ -1,7 +1,10 @@
import { markHydrateNode as _markHydrateNode, styleAttr as _styleAttr, write as _write, nextScopeId as _nextScopeId, createRenderer as _createRenderer } from "@marko/runtime-fluurt/src/html";
import _customTag from "./components/custom-tag.marko";
const _renderer = input => {
const _renderer = ({
color,
test
}) => {
const _scope = _nextScopeId();
_write(`${_markHydrateNode(_scope, 0)}<div${_styleAttr({

View File

@ -1,6 +1,8 @@
import { markHydrateNode as _markHydrateNode, attr as _attr, write as _write, nextScopeId as _nextScopeId, createRenderer as _createRenderer } from "@marko/runtime-fluurt/src/html";
const _renderer = input => {
const _renderer = ({
name
}) => {
const _scope = _nextScopeId();
_write(`${_markHydrateNode(_scope, 0)}<div${_attr("foo", `Hello ${name}`)}></div>`);

View File

@ -1,6 +1,9 @@
import { markHydrateNode as _markHydrateNode, escapeXML as _escapeXML, write as _write, nextScopeId as _nextScopeId, writeHydrateCall as _writeHydrateCall, writeHydrateScope as _writeHydrateScope, createRenderer as _createRenderer } from "@marko/runtime-fluurt/src/html";
const _renderer = input => {
const _renderer = ({
onclick,
text
}) => {
const _scope = _nextScopeId();
_write(`${_markHydrateNode(_scope, 0)}<button>${_markHydrateNode(_scope, 1)}${_escapeXML(text)}</button>`);

View File

@ -10,7 +10,11 @@ const _renderer = input => {
_write(`${_markHydrateNode(_scope, 0)}<button>hide</button>${_markHydrateNode(_scope, 1)}`);
if (show) _write(`${_markHydrateNode(_scope, 0)}${_escapeXML(message.text)}`);
if (show) {
const _scope = _nextScopeId();
_write(`${_markHydrateNode(_scope, 0)}${_escapeXML(message.text)}`);
}
_writeHydrateCall(_scope, "packages/translator/src/__tests__/fixtures/basic-execution-order/template.marko_0_0");

View File

@ -0,0 +1,21 @@
import { apply as _comments, applyAttrs as _comments_attrs, template as _comments_template, walks as _comments_walks } from "./components/comments.marko";
import { write as _write, createRenderFn as _createRenderFn } from "@marko/runtime-fluurt/src/dom";
function _apply_input(_scope, input) {
if (_write(_scope, 1, input)) _comments_attrs(_scope[0], input);
}
function _apply(_scope) {
_comments(_scope[0]);
}
export const applyAttrs = function (_scope, input) {
_apply_input(_scope, input);
};
export { _apply_input };
export const template = `${_comments_template}`;
export const walks =
/* beginChild(0), _comments_walks, endChild */
`/${_comments_walks}&`;
export const apply = _apply;
export default _createRenderFn(template, walks, apply, applyAttrs);

View File

@ -0,0 +1,124 @@
import { queue as _queue, attr as _attr, data as _data, on as _on, setConditionalRenderer as _setConditionalRenderer, setLoopOf as _setLoopOf, queueInBranch as _queueInBranch, register as _register, bind as _bind, queueHydrate as _queueHydrate, write as _write, queueForEach as _queueForEach, createRenderer as _createRenderer, createRenderFn as _createRenderFn } from "@marko/runtime-fluurt/src/dom";
import { apply as _comments, applyAttrs as _comments_attrs, template as _comments_template, walks as _comments_walks } from "./comments.marko";
function _applyWith_comment_id(_scope, comment = _scope._[8], id = _scope._[10]) {
_comments_attrs(_scope[0], {
comments: comment.comments,
path: id
});
}
function _apply_id2(_scope, id = _scope._[10]) {
_queue(_scope, _applyWith_comment_id, 2);
}
function _apply_comment2(_scope, comment = _scope._[8]) {
_queue(_scope, _applyWith_comment_id, 2);
}
function _apply2(_scope) {
_comments(_scope[0]);
_queue(_scope, _apply_id2, 1);
_queue(_scope, _apply_comment2, 0);
}
const _onclick = function (_scope) {
const open = _scope[11];
_queue(_scope, _apply_open, 4, !open);
};
function _hydrate_open(_scope, open = _scope[11]) {
_on(_scope, 2, "click", _bind(_scope, _onclick));
}
_register("packages/translator/src/__tests__/fixtures/basic-inert-collapsible-tree/components/comments.marko_1_0", _hydrate_open);
function _applyWith_path_i(_scope, path = _scope._[5], i = _scope[9]) {
_apply_id(`${path}-${i}`);
}
function _apply_open(_scope, open) {
if (_write(_scope, 11, open)) {
_attr(_scope, 0, "hidden", !open);
_data(_scope, 3, open ? "[-]" : "[+]");
_queueHydrate(_scope, _hydrate_open);
}
}
function _apply_id(_scope, id) {
if (_write(_scope, 10, id)) {
_attr(_scope, 0, "id", id);
_queueInBranch(_scope, 4, _if, _apply_id2, 1, 3);
}
}
function _apply_i(_scope, i) {
if (_write(_scope, 9, i)) _queue(_scope, _applyWith_path_i, 5);
}
function _apply_comment(_scope, comment) {
if (_write(_scope, 8, comment)) {
_data(_scope, 1, comment.text);
_setConditionalRenderer(_scope, 4, comment.comments ? _if : null);
_queueInBranch(_scope, 4, _if, _apply_comment2, 0, 4);
}
}
function _apply_path(_scope, path = _scope._[5]) {
_queue(_scope, _applyWith_path_i, 5);
}
function _apply_path(_scope, path = _scope._[5]) {
_queue(_scope, _applyWith_path_i, 5);
}
function _apply(_scope) {
_apply_open(_scope, true);
_queue(_scope, _apply_path, 0);
_queue(_scope, _apply_path, 0);
}
function _apply_path2(_scope, path) {
if (_write(_scope, 5, path)) {
_queueForEach(_scope, 0, _apply_path, 0, 6);
_queueForEach(_scope, 0, _apply_path, 0, 7);
}
}
function _apply_comments(_scope, comments) {
if (_write(_scope, 4, comments)) _setLoopOf(_scope, 0, comments, _for, null, _apply_comment);
}
const _for = _createRenderer("<li><span><!></span><button><!></button><!></li>",
/* get, next(2), replace, out(1), get, next(1), replace, out(1), replace, skip(3) */
" E%l D%l%+", _apply),
_if = _createRenderer(`${_comments_template}`,
/* beginChild(0), _comments_walks, endChild */
`/${_comments_walks}&`, _apply2);
export const applyAttrs = function (_scope, {
comments,
path = "c"
}) {
_apply_comments(_scope, comments);
_apply_path2(_scope, path);
};
export { _apply_comments, _apply_path2 as _apply_path };
export const template = "<ul><!></ul>";
export const walks =
/* next(1), replace, skip(3), out(1) */
"D%+l";
export const apply = function () {};
export default _createRenderFn(template, walks, apply, applyAttrs);

View File

@ -0,0 +1,17 @@
import { nextScopeId as _nextScopeId, createRenderer as _createRenderer } from "@marko/runtime-fluurt/src/html";
import _comments from "./components/comments.marko";
const _renderer = input => {
const _scope = _nextScopeId();
_comments({ ...input,
renderBody() {
const _scope = _nextScopeId();
}
});
};
export default _renderer;
export const render = _createRenderer(_renderer);

View File

@ -0,0 +1,49 @@
import { markHydrateNode as _markHydrateNode, write as _write, attr as _attr, escapeXML as _escapeXML, nextScopeId as _nextScopeId, writeHydrateCall as _writeHydrateCall, writeHydrateScope as _writeHydrateScope, createRenderer as _createRenderer } from "@marko/runtime-fluurt/src/html";
import _comments from "./comments.marko";
const _renderer = ({
comments,
path = "c"
}) => {
const _scope = _nextScopeId();
_write(`<ul>${_markHydrateNode(_scope, 0)}`);
let _i = 0;
for (const comment of comments) {
let i = _i++;
const _scope = _nextScopeId();
const id = `${path}-${i}`;
const open = true;
_write(`${_markHydrateNode(_scope, 0)}<li${_attr("id", id)}${_attr("hidden", !open)}><span>${_markHydrateNode(_scope, 1)}${_escapeXML(comment.text)}</span>${_markHydrateNode(_scope, 2)}<button>${_markHydrateNode(_scope, 3)}${_escapeXML(open ? "[-]" : "[+]")}</button>${_markHydrateNode(_scope, 4)}`);
if (comment.comments) {
const _scope = _nextScopeId();
_comments({
comments: comment.comments,
path: id,
renderBody() {
const _scope = _nextScopeId();
}
});
}
_write("</li>");
_writeHydrateCall(_scope, "packages/translator/src/__tests__/fixtures/basic-inert-collapsible-tree/components/comments.marko_1_0");
_writeHydrateScope(_scope, [,,,,,,,,,,, open]);
}
_write("</ul>");
};
export default _renderer;
export const render = _createRenderer(_renderer);

View File

@ -0,0 +1,470 @@
# Write
<ul><!M#0 1><!M#0 2><li id=c-0><span><!M#1 2>Hello World</span><!M#2 2><button><!M#3 2>[-]</button><!M#4 2><ul><!M#0 4><!M#0 5><li id=c-0-0><span><!M#1 5>testing 123</span><!M#2 5><button><!M#3 5>[-]</button><!M#4 5></li></ul></li><!M#0 6><li id=c-1><span><!M#1 6>Goodbye World</span><!M#2 6><button><!M#3 6>[-]</button><!M#4 6></li></ul><script>(M$h=[]).push((b,s)=>({"2":[,,,,,,,,,,,!0],"5":[,,,,,,,,,,,!0],"6":[,,,,,,,,,,,!0]}),["packages/translator/src/__tests__/fixtures/basic-inert-collapsible-tree/components/comments.marko_1_0",5,"packages/translator/src/__tests__/fixtures/basic-inert-collapsible-tree/components/comments.marko_1_0",2,"packages/translator/src/__tests__/fixtures/basic-inert-collapsible-tree/components/comments.marko_1_0",6,])</script>
# Render "End"
```html
<html>
<head />
<body>
<ul>
<!--M#0 1-->
<!--M#0 2-->
<li
id="c-0"
>
<span>
<!--M#1 2-->
Hello World
</span>
<!--M#2 2-->
<button>
<!--M#3 2-->
[-]
</button>
<!--M#4 2-->
<ul>
<!--M#0 4-->
<!--M#0 5-->
<li
id="c-0-0"
>
<span>
<!--M#1 5-->
testing 123
</span>
<!--M#2 5-->
<button>
<!--M#3 5-->
[-]
</button>
<!--M#4 5-->
</li>
</ul>
</li>
<!--M#0 6-->
<li
id="c-1"
>
<span>
<!--M#1 6-->
Goodbye World
</span>
<!--M#2 6-->
<button>
<!--M#3 6-->
[-]
</button>
<!--M#4 6-->
</li>
</ul>
<script>
(M$h=[]).push((b,s)=&gt;({"2":[,,,,,,,,,,,!0],"5":[,,,,,,,,,,,!0],"6":[,,,,,,,,,,,!0]}),["packages/translator/src/__tests__/fixtures/basic-inert-collapsible-tree/components/comments.marko_1_0",5,"packages/translator/src/__tests__/fixtures/basic-inert-collapsible-tree/components/comments.marko_1_0",2,"packages/translator/src/__tests__/fixtures/basic-inert-collapsible-tree/components/comments.marko_1_0",6,])
</script>
</body>
</html>
```
# Mutations
```
inserted html0
inserted html0/head0
inserted html0/body1
inserted html0/body1/ul0
inserted html0/body1/ul0/#comment0
inserted html0/body1/ul0/#comment1
inserted html0/body1/ul0/li2
inserted html0/body1/ul0/li2/span0
inserted html0/body1/ul0/li2/span0/#comment0
inserted html0/body1/ul0/li2/span0/#text1
inserted html0/body1/ul0/li2/#comment1
inserted html0/body1/ul0/li2/button2
inserted html0/body1/ul0/li2/button2/#comment0
inserted html0/body1/ul0/li2/button2/#text1
inserted html0/body1/ul0/li2/#comment3
inserted html0/body1/ul0/li2/ul4
inserted html0/body1/ul0/li2/ul4/#comment0
inserted html0/body1/ul0/li2/ul4/#comment1
inserted html0/body1/ul0/li2/ul4/li2
inserted html0/body1/ul0/li2/ul4/li2/span0
inserted html0/body1/ul0/li2/ul4/li2/span0/#comment0
inserted html0/body1/ul0/li2/ul4/li2/span0/#text1
inserted html0/body1/ul0/li2/ul4/li2/#comment1
inserted html0/body1/ul0/li2/ul4/li2/button2
inserted html0/body1/ul0/li2/ul4/li2/button2/#comment0
inserted html0/body1/ul0/li2/ul4/li2/button2/#text1
inserted html0/body1/ul0/li2/ul4/li2/#comment3
inserted html0/body1/ul0/#comment3
inserted html0/body1/ul0/li4
inserted html0/body1/ul0/li4/span0
inserted html0/body1/ul0/li4/span0/#comment0
inserted html0/body1/ul0/li4/span0/#text1
inserted html0/body1/ul0/li4/#comment1
inserted html0/body1/ul0/li4/button2
inserted html0/body1/ul0/li4/button2/#comment0
inserted html0/body1/ul0/li4/button2/#text1
inserted html0/body1/ul0/li4/#comment3
inserted html0/body1/script1
inserted html0/body1/script1/#text0
```
# Render "Hydrate"
```html
<html>
<head />
<body>
<ul>
<!--M#0 1-->
<!--M#0 2-->
<li
id="c-0"
>
<span>
<!--M#1 2-->
Hello World
</span>
<!--M#2 2-->
<button>
<!--M#3 2-->
[-]
</button>
<!--M#4 2-->
<ul>
<!--M#0 4-->
<!--M#0 5-->
<li
id="c-0-0"
>
<span>
<!--M#1 5-->
testing 123
</span>
<!--M#2 5-->
<button>
<!--M#3 5-->
[-]
</button>
<!--M#4 5-->
</li>
</ul>
</li>
<!--M#0 6-->
<li
id="c-1"
>
<span>
<!--M#1 6-->
Goodbye World
</span>
<!--M#2 6-->
<button>
<!--M#3 6-->
[-]
</button>
<!--M#4 6-->
</li>
</ul>
<script>
(M$h=[]).push((b,s)=&gt;({"2":[,,,,,,,,,,,!0],"5":[,,,,,,,,,,,!0],"6":[,,,,,,,,,,,!0]}),["packages/translator/src/__tests__/fixtures/basic-inert-collapsible-tree/components/comments.marko_1_0",5,"packages/translator/src/__tests__/fixtures/basic-inert-collapsible-tree/components/comments.marko_1_0",2,"packages/translator/src/__tests__/fixtures/basic-inert-collapsible-tree/components/comments.marko_1_0",6,])
</script>
</body>
</html>
```
# Mutations
```
```
# Render
container.querySelector(`#c-${id} > button`).click();
```html
<html>
<head />
<body>
<ul>
<!--M#0 1-->
<!--M#0 2-->
<li
hidden="true"
id="c-0"
>
<span>
<!--M#1 2-->
Hello World
</span>
<!--M#2 2-->
<button>
<!--M#3 2-->
[+]
</button>
<!--M#4 2-->
<ul>
<!--M#0 4-->
<!--M#0 5-->
<li
id="c-0-0"
>
<span>
<!--M#1 5-->
testing 123
</span>
<!--M#2 5-->
<button>
<!--M#3 5-->
[-]
</button>
<!--M#4 5-->
</li>
</ul>
</li>
<!--M#0 6-->
<li
id="c-1"
>
<span>
<!--M#1 6-->
Goodbye World
</span>
<!--M#2 6-->
<button>
<!--M#3 6-->
[-]
</button>
<!--M#4 6-->
</li>
</ul>
<script>
(M$h=[]).push((b,s)=&gt;({"2":[,,,,,,,,,,,!0],"5":[,,,,,,,,,,,!0],"6":[,,,,,,,,,,,!0]}),["packages/translator/src/__tests__/fixtures/basic-inert-collapsible-tree/components/comments.marko_1_0",5,"packages/translator/src/__tests__/fixtures/basic-inert-collapsible-tree/components/comments.marko_1_0",2,"packages/translator/src/__tests__/fixtures/basic-inert-collapsible-tree/components/comments.marko_1_0",6,])
</script>
</body>
</html>
```
# Mutations
```
html0/body1/ul0/li2: attr(hidden) null => "true"
html0/body1/ul0/li2/button2/#text1: "[-]" => "[+]"
```
# Render
container.querySelector(`#c-${id} > button`).click();
```html
<html>
<head />
<body>
<ul>
<!--M#0 1-->
<!--M#0 2-->
<li
id="c-0"
>
<span>
<!--M#1 2-->
Hello World
</span>
<!--M#2 2-->
<button>
<!--M#3 2-->
[-]
</button>
<!--M#4 2-->
<ul>
<!--M#0 4-->
<!--M#0 5-->
<li
id="c-0-0"
>
<span>
<!--M#1 5-->
testing 123
</span>
<!--M#2 5-->
<button>
<!--M#3 5-->
[-]
</button>
<!--M#4 5-->
</li>
</ul>
</li>
<!--M#0 6-->
<li
id="c-1"
>
<span>
<!--M#1 6-->
Goodbye World
</span>
<!--M#2 6-->
<button>
<!--M#3 6-->
[-]
</button>
<!--M#4 6-->
</li>
</ul>
<script>
(M$h=[]).push((b,s)=&gt;({"2":[,,,,,,,,,,,!0],"5":[,,,,,,,,,,,!0],"6":[,,,,,,,,,,,!0]}),["packages/translator/src/__tests__/fixtures/basic-inert-collapsible-tree/components/comments.marko_1_0",5,"packages/translator/src/__tests__/fixtures/basic-inert-collapsible-tree/components/comments.marko_1_0",2,"packages/translator/src/__tests__/fixtures/basic-inert-collapsible-tree/components/comments.marko_1_0",6,])
</script>
</body>
</html>
```
# Mutations
```
html0/body1/ul0/li2: attr(hidden) "true" => null
html0/body1/ul0/li2/button2/#text1: "[+]" => "[-]"
```
# Render
container.querySelector(`#c-${id} > button`).click();
```html
<html>
<head />
<body>
<ul>
<!--M#0 1-->
<!--M#0 2-->
<li
id="c-0"
>
<span>
<!--M#1 2-->
Hello World
</span>
<!--M#2 2-->
<button>
<!--M#3 2-->
[-]
</button>
<!--M#4 2-->
<ul>
<!--M#0 4-->
<!--M#0 5-->
<li
hidden="true"
id="c-0-0"
>
<span>
<!--M#1 5-->
testing 123
</span>
<!--M#2 5-->
<button>
<!--M#3 5-->
[+]
</button>
<!--M#4 5-->
</li>
</ul>
</li>
<!--M#0 6-->
<li
id="c-1"
>
<span>
<!--M#1 6-->
Goodbye World
</span>
<!--M#2 6-->
<button>
<!--M#3 6-->
[-]
</button>
<!--M#4 6-->
</li>
</ul>
<script>
(M$h=[]).push((b,s)=&gt;({"2":[,,,,,,,,,,,!0],"5":[,,,,,,,,,,,!0],"6":[,,,,,,,,,,,!0]}),["packages/translator/src/__tests__/fixtures/basic-inert-collapsible-tree/components/comments.marko_1_0",5,"packages/translator/src/__tests__/fixtures/basic-inert-collapsible-tree/components/comments.marko_1_0",2,"packages/translator/src/__tests__/fixtures/basic-inert-collapsible-tree/components/comments.marko_1_0",6,])
</script>
</body>
</html>
```
# Mutations
```
html0/body1/ul0/li2/ul4/li2: attr(hidden) null => "true"
html0/body1/ul0/li2/ul4/li2/button2/#text1: "[-]" => "[+]"
```
# Render
container.querySelector(`#c-${id} > button`).click();
```html
<html>
<head />
<body>
<ul>
<!--M#0 1-->
<!--M#0 2-->
<li
id="c-0"
>
<span>
<!--M#1 2-->
Hello World
</span>
<!--M#2 2-->
<button>
<!--M#3 2-->
[-]
</button>
<!--M#4 2-->
<ul>
<!--M#0 4-->
<!--M#0 5-->
<li
hidden="true"
id="c-0-0"
>
<span>
<!--M#1 5-->
testing 123
</span>
<!--M#2 5-->
<button>
<!--M#3 5-->
[+]
</button>
<!--M#4 5-->
</li>
</ul>
</li>
<!--M#0 6-->
<li
hidden="true"
id="c-1"
>
<span>
<!--M#1 6-->
Goodbye World
</span>
<!--M#2 6-->
<button>
<!--M#3 6-->
[+]
</button>
<!--M#4 6-->
</li>
</ul>
<script>
(M$h=[]).push((b,s)=&gt;({"2":[,,,,,,,,,,,!0],"5":[,,,,,,,,,,,!0],"6":[,,,,,,,,,,,!0]}),["packages/translator/src/__tests__/fixtures/basic-inert-collapsible-tree/components/comments.marko_1_0",5,"packages/translator/src/__tests__/fixtures/basic-inert-collapsible-tree/components/comments.marko_1_0",2,"packages/translator/src/__tests__/fixtures/basic-inert-collapsible-tree/components/comments.marko_1_0",6,])
</script>
</body>
</html>
```
# Mutations
```
html0/body1/ul0/li4: attr(hidden) null => "true"
html0/body1/ul0/li4/button2/#text1: "[-]" => "[+]"
```

View File

@ -0,0 +1,16 @@
<attrs/{ comments, path = "c" }/>
<ul>
<for|comment, i| of=comments>
<const/id=`${path}-${i}`/>
<let/open=true/>
<li id=id hidden=!open>
<span>${comment.text}</span>
<button onclick() { open = !open }>
${open ? "[-]" : "[+]"}
</button>
<if=comment.comments>
<comments comments=comment.comments path=id/>
</if>
</li>
</for>
</ul>

View File

@ -0,0 +1,2 @@
<attrs/input/>
<comments ...input/>

View File

@ -0,0 +1,29 @@
export const steps = [
{
comments: [
{
text: "Hello World",
comments: [
{
text: "testing 123",
},
],
},
{
text: "Goodbye World",
},
],
},
toggle("0"),
toggle("0"),
toggle("0-0"),
toggle("1"),
];
function toggle(id: string) {
return (container: Element) => {
(container.querySelector(`#c-${id} > button`) as HTMLButtonElement).click();
};
}
export const skip_csr = true;

View File

@ -1,4 +1,4 @@
import { markHydrateNode as _markHydrateNode, write as _write, attr as _attr, escapeXML as _escapeXML, nextScopeId as _nextScopeId, createRenderer as _createRenderer } from "@marko/runtime-fluurt/src/html";
import { markHydrateNode as _markHydrateNode, write as _write, attr as _attr, escapeXML as _escapeXML, nextScopeId as _nextScopeId, writeHydrateCall as _writeHydrateCall, writeHydrateScope as _writeHydrateScope, createRenderer as _createRenderer } from "@marko/runtime-fluurt/src/html";
const _renderer = input => {
const _scope = _nextScopeId();
@ -8,7 +8,13 @@ const _renderer = input => {
_write(`${_markHydrateNode(_scope, 0)}`);
for (const num of [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]) {
const _scope = _nextScopeId();
_write(`${_markHydrateNode(_scope, 0)}<button${_attr("data-selected", selected === num)}${_attr("data-multiple", num % selected === 0)}>${_markHydrateNode(_scope, 1)}${_escapeXML(num)}</button>`);
_writeHydrateCall(_scope, "packages/translator/src/__tests__/fixtures/basic-nested-scope-for/template.marko_1_0");
_writeHydrateScope(_scope, [,, num]);
}
};

View File

@ -1,4 +1,4 @@
import { markHydrateNode as _markHydrateNode, write as _write, escapeXML as _escapeXML, nextScopeId as _nextScopeId, createRenderer as _createRenderer } from "@marko/runtime-fluurt/src/html";
import { markHydrateNode as _markHydrateNode, write as _write, escapeXML as _escapeXML, nextScopeId as _nextScopeId, writeHydrateCall as _writeHydrateCall, writeHydrateScope as _writeHydrateScope, createRenderer as _createRenderer } from "@marko/runtime-fluurt/src/html";
const _renderer = input => {
const _scope = _nextScopeId();
@ -7,7 +7,15 @@ const _renderer = input => {
_write(`<div>${_markHydrateNode(_scope, 0)}`);
if (clickCount < 3) _write(`${_markHydrateNode(_scope, 0)}<button>${_markHydrateNode(_scope, 1)}${_escapeXML(clickCount)}</button>`);
if (clickCount < 3) {
const _scope = _nextScopeId();
_write(`${_markHydrateNode(_scope, 0)}<button>${_markHydrateNode(_scope, 1)}${_escapeXML(clickCount)}</button>`);
_writeHydrateCall(_scope, "packages/translator/src/__tests__/fixtures/basic-nested-scope-if/template.marko_1_0");
_writeHydrateScope(_scope, [,,,, clickCount]);
}
_write("</div>");
};

View File

@ -9,6 +9,8 @@ const _renderer = input => {
_write(`<div>${_markHydrateNode(_scope, 0)}`);
for (const item of items) {
const _scope = _nextScopeId();
_write(`${_markHydrateNode(_scope, 0)}${_escapeXML(item)}`);
}

View File

@ -7,7 +7,11 @@ const _renderer = input => {
_write(`<div>${_markHydrateNode(_scope, 0)}`);
if (show) _write("Hello!");
if (show) {
const _scope = _nextScopeId();
_write("Hello!");
}
_write(`${_markHydrateNode(_scope, 4)}<button>Toggle</button></div>`);

View File

@ -2,7 +2,16 @@ import tagA from "./components/tag-a/index.marko";
import tagB from "./components/tag-b/index.marko";
import { markHydrateNode as _markHydrateNode, attr as _attr, write as _write, nextScopeId as _nextScopeId, createRenderer as _createRenderer } from "@marko/runtime-fluurt/src/html";
const _renderer = input => {
const _renderer = ({
renderBody,
x,
show,
showTagA,
isLarge,
tag,
level,
other
}) => {
const _scope = _nextScopeId();
<${renderBody} class=["a", "b"] other=other/>

View File

@ -1,7 +1,10 @@
import child from "./components/child/index.marko";
import { nextScopeId as _nextScopeId, markHydrateNode as _markHydrateNode, write as _write, createRenderer as _createRenderer } from "@marko/runtime-fluurt/src/html";
const _renderer = input => {
const _renderer = ({
show,
dynamic
}) => {
const _scope = _nextScopeId();
const data1 = child({

View File

@ -12,6 +12,8 @@ const _renderer = input => {
for (const val of arrA) {
let i = _i++;
const _scope = _nextScopeId();
_write(`<div>${_markHydrateNode(_scope, 0)}${_escapeXML(i)}: ${_markHydrateNode(_scope, 1)}${_escapeXML(val)}</div>`);
}
@ -24,6 +26,8 @@ const _renderer = input => {
for (const val of arrB) {
let i = _i2++;
const _scope = _nextScopeId();
_write(`<div>${_markHydrateNode(_scope, 0)}${_escapeXML(i)}: ${_markHydrateNode(_scope, 1)}${_escapeXML(val)}</div>`);
}
};

View File

@ -1,4 +1,4 @@
import { markHydrateNode as _markHydrateNode, write as _write, escapeXML as _escapeXML, attr as _attr, nextScopeId as _nextScopeId, createRenderer as _createRenderer } from "@marko/runtime-fluurt/src/html";
import { markHydrateNode as _markHydrateNode, write as _write, escapeXML as _escapeXML, nextScopeId as _nextScopeId, attr as _attr, createRenderer as _createRenderer } from "@marko/runtime-fluurt/src/html";
const _renderer = input => {
const _scope = _nextScopeId();
@ -17,6 +17,8 @@ const _renderer = input => {
for (const val of arr) {
let i = _i++;
const _scope = _nextScopeId();
_write(`<div>${_markHydrateNode(_scope, 0)}${_escapeXML(i)}: ${_markHydrateNode(_scope, 1)}${_escapeXML(val)}</div><div></div><div></div>`);
}
@ -25,6 +27,8 @@ const _renderer = input => {
for (const key in obj) {
const val = obj[key];
const _scope = _nextScopeId();
_write(`<div>${_markHydrateNode(_scope, 0)}${_escapeXML(key)}: ${_markHydrateNode(_scope, 1)}${_escapeXML(val)}</div><div></div><div></div>`);
}
@ -33,6 +37,8 @@ const _renderer = input => {
for (let _steps = (10 - 0) / 2, _step = 0; _step <= _steps; _step++) {
const i = 0 + _step * 2;
const _scope = _nextScopeId();
_write(`<div>${_markHydrateNode(_scope, 0)}${_escapeXML(i)}</div><div></div><div></div>`);
}
@ -43,6 +49,8 @@ const _renderer = input => {
for (const val of arr) {
let i = _i2++;
const _scope = _nextScopeId();
_write(`${_markHydrateNode(_scope, 0)}<div${_attr("key", i)}>${_markHydrateNode(_scope, 1)}${_escapeXML(i)}: ${_markHydrateNode(_scope, 2)}${_escapeXML(val)}</div><div></div>${_markHydrateNode(_scope, 3)}<div${_attr("key", `other-${i}`)}></div>`);
}
@ -54,6 +62,8 @@ const _renderer = input => {
for (const val of list) {
let i = _i3++;
const _scope = _nextScopeId();
_write(`${_markHydrateNode(_scope, 0)}<div${_attr("key", i)}>${_markHydrateNode(_scope, 1)}${_escapeXML(list.length)}: ${_markHydrateNode(_scope, 2)}${_escapeXML(val)}</div>`);
}
@ -62,6 +72,8 @@ const _renderer = input => {
for (const key in obj) {
const val = obj[key];
const _scope = _nextScopeId();
_write(`${_markHydrateNode(_scope, 0)}<div${_attr("key", key)}>${_markHydrateNode(_scope, 1)}${_escapeXML(key)}: ${_markHydrateNode(_scope, 2)}${_escapeXML(val)}</div><div></div>${_markHydrateNode(_scope, 3)}<div${_attr("key", `other-${key}`)}></div>`);
}
@ -70,11 +82,15 @@ const _renderer = input => {
for (let _steps3 = (10 - 0) / 2, _step3 = 0; _step3 <= _steps3; _step3++) {
const i = 0 + _step3 * 2;
const _scope = _nextScopeId();
_write(`${_markHydrateNode(_scope, 0)}<div${_attr("key", i)}>${_markHydrateNode(_scope, 1)}${_escapeXML(i)}</div><div></div>${_markHydrateNode(_scope, 2)}<div${_attr("key", `other-${i}`)}></div>${_markHydrateNode(_scope, 3)}`);
for (let _steps2 = (10 - 0) / 2, _step2 = 0; _step2 <= _steps2; _step2++) {
const i = 0 + _step2 * 2;
const _scope = _nextScopeId();
_write(`${_markHydrateNode(_scope, 0)}<div${_attr("key", i)}>${_markHydrateNode(_scope, 1)}${_escapeXML(i)}</div><div></div>${_markHydrateNode(_scope, 2)}<div${_attr("key", `other-${i}`)}></div>`);
}
}
@ -84,18 +100,24 @@ const _renderer = input => {
for (let _steps4 = (0 - 10) / -2, _step4 = 0; _step4 <= _steps4; _step4++) {
const i = 10 + _step4 * -2;
const _scope = _nextScopeId();
_write(`${_markHydrateNode(_scope, 0)}<div${_attr("key", i)}>${_markHydrateNode(_scope, 1)}${_escapeXML(i)}</div><div></div>${_markHydrateNode(_scope, 2)}<div${_attr("key", `other-${i}`)}></div>`);
}
_write(`${_markHydrateNode(_scope, 32)}`);
for (let _steps5 = (10 - 0) / 1, _step5 = 0; _step5 <= _steps5; _step5++) {
const _scope = _nextScopeId();
_write("Hello");
}
_write(`${_markHydrateNode(_scope, 36)}`);
for (let _steps6 = (10 - 0) / 1, _step6 = 0; _step6 <= _steps6; _step6++) {
const _scope = _nextScopeId();
_write("Hello");
}
};

View File

@ -1,6 +1,9 @@
import { markHydrateNode as _markHydrateNode, escapeXML as _escapeXML, toString as _toString, write as _write, nextScopeId as _nextScopeId, createRenderer as _createRenderer } from "@marko/runtime-fluurt/src/html";
const _renderer = input => {
const _renderer = ({
name,
missing
}) => {
const _scope = _nextScopeId();
_write(`Hello ${_markHydrateNode(_scope, 0)}${_escapeXML(name)}! Hello ${_markHydrateNode(_scope, 1)}${_toString(name)}! Hello ${_markHydrateNode(_scope, 2)}${_toString(missing)}!`);

View File

@ -1,19 +1,44 @@
import { markHydrateNode as _markHydrateNode, write as _write, nextScopeId as _nextScopeId, createRenderer as _createRenderer } from "@marko/runtime-fluurt/src/html";
const _renderer = input => {
const _renderer = ({
a,
b,
x,
y
}) => {
const _scope = _nextScopeId();
_write(`${_markHydrateNode(_scope, 0)}`);
if (a + b) _write("Hello");
if (a + b) {
const _scope = _nextScopeId();
_write("Hello");
}
_write(`${_markHydrateNode(_scope, 4)}`);
if (a, b) _write("World");
if (a, b) {
const _scope = _nextScopeId();
_write("World");
}
_write(`<div>${_markHydrateNode(_scope, 8)}`);
if (x) _write("A");else if (y) _write("B");else _write("C");
if (x) {
const _scope = _nextScopeId();
_write("A");
} else if (y) {
const _scope = _nextScopeId();
_write("B");
} else {
const _scope = _nextScopeId();
_write("C");
}
_write("</div>");
};

View File

@ -1,6 +1,8 @@
import { markHydrateNode as _markHydrateNode, escapeXML as _escapeXML, toString as _toString, write as _write, nextScopeId as _nextScopeId, createRenderer as _createRenderer } from "@marko/runtime-fluurt/src/html";
const _renderer = input => {
const _renderer = ({
x
}) => {
const _scope = _nextScopeId();
_write(`<div><div>a</div>${_markHydrateNode(_scope, 0)}${_escapeXML(x)}Hello Text &lt;a/>${_markHydrateNode(_scope, 1)}${_toString(x)}Hello HTML <a/><script>

View File

@ -1,13 +1,24 @@
import { markHydrateNode as _markHydrateNode, write as _write, nextScopeId as _nextScopeId, createRenderer as _createRenderer } from "@marko/runtime-fluurt/src/html";
const _renderer = input => {
const _renderer = ({
show
}) => {
var _return;
const _scope = _nextScopeId();
_write(`${_markHydrateNode(_scope, 0)}`);
if (show) _return = 1;else _return = 2;
if (show) {
const _scope = _nextScopeId();
_return = 1;
} else {
const _scope = _nextScopeId();
_return = 2;
}
return _return;
};

View File

@ -3,7 +3,11 @@ import { Tag, assertNoParams, assertNoVar } from "@marko/babel-utils";
import * as writer from "../../util/writer";
import * as walks from "../../util/walks";
import * as sorted from "../../util/sorted-arr";
import { addStatement, setQueueBuilder } from "../../util/apply-hydrate";
import {
addStatement,
setQueueBuilder,
writeHTMLHydrateStatements,
} from "../../util/apply-hydrate";
import { callRuntime } from "../../util/runtime";
import { isCoreTagName } from "../../util/is-core-tag";
import toFirstStatementOrBlock from "../../util/to-first-statement-or-block";
@ -96,7 +100,8 @@ const BRANCHES_LOOKUP = new WeakMap<
>();
export function exitBranch(tag: t.NodePath<t.MarkoTag>) {
const bodySectionId = getSectionId(tag.get("body"));
const tagBody = tag.get("body");
const bodySectionId = getSectionId(tagBody);
const nextTag = tag.getNextSibling();
const isLast = !(
isCoreTagName(nextTag, "else") || isCoreTagName(nextTag, "else-if")
@ -123,6 +128,7 @@ export function exitBranch(tag: t.NodePath<t.MarkoTag>) {
if (isOutputHTML()) {
writer.flushInto(tag);
writeHTMLHydrateStatements(tagBody);
}
if (isLast) {

View File

@ -7,6 +7,7 @@ import {
addStatement,
bindingToApplyGroup,
setQueueBuilder,
writeHTMLHydrateStatements,
} from "../util/apply-hydrate";
import { getOrCreateSectionId, getSectionId } from "../util/sections";
import { ReserveType, reserveScope } from "../util/reserve";
@ -185,6 +186,7 @@ const translateDOM = {
const translateHTML = {
exit(tag: t.NodePath<t.MarkoTag>) {
const tagBody = tag.get("body");
const { node } = tag;
const {
attributes,
@ -199,6 +201,7 @@ const translateHTML = {
let forNode: t.Node | t.Node[];
writer.flushInto(tag);
writeHTMLHydrateStatements(tagBody);
if (inAttr) {
const [keyParam, valParam] = params;

View File

@ -20,12 +20,13 @@ export default {
}
const rendererId = program.scope.generateUidIdentifier("renderer");
const { attrs } = program.node.extra;
program.pushContainer("body", [
t.variableDeclaration("const", [
t.variableDeclarator(
rendererId,
t.arrowFunctionExpression(
[t.identifier("input")],
[attrs ? (attrs.var as any) : t.identifier("input")],
t.blockStatement(renderContent)
)
),