From 0ca372cc265c02ecebc566eec0e134a7cffa00db Mon Sep 17 00:00:00 2001 From: Michael Rawlings Date: Tue, 5 Apr 2022 15:18:35 -0400 Subject: [PATCH] feat: basic nested hydration --- .sizes.json | 22 +- packages/runtime/package.json | 2 +- packages/runtime/src/dom/hydrate.ts | 4 +- .../__snapshots__/html.expected.js | 20 +- .../__snapshots__/html.expected.js | 2 + .../__snapshots__/html.expected.js | 4 +- .../__snapshots__/html.expected.js | 18 +- .../__snapshots__/html.expected.js | 47 +- .../attr-style/__snapshots__/html.expected.js | 5 +- .../__snapshots__/html.expected.js | 4 +- .../html.expected/components/my-button.js | 5 +- .../__snapshots__/html.expected.js | 6 +- .../__snapshots__/dom.expected.js | 21 + .../dom.expected/components/comments.js | 124 +++++ .../__snapshots__/html.expected.js | 17 + .../html.expected/components/comments.js | 49 ++ .../__snapshots__/ssr.expected.md | 470 ++++++++++++++++++ .../components/comments.marko | 16 + .../template.marko | 2 + .../basic-inert-collapsible-tree/test.ts | 29 ++ .../__snapshots__/html.expected.js | 8 +- .../__snapshots__/html.expected.js | 12 +- .../__snapshots__/html.expected.js | 2 + .../__snapshots__/html.expected.js | 6 +- .../__snapshots__/html.expected.js | 11 +- .../__snapshots__/html.expected.js | 5 +- .../__snapshots__/html.expected.js | 4 + .../for-tag/__snapshots__/html.expected.js | 24 +- .../__snapshots__/html.expected.js | 5 +- .../if-tag/__snapshots__/html.expected.js | 33 +- .../__snapshots__/html.expected.js | 4 +- .../yield-tag/__snapshots__/html.expected.js | 15 +- packages/translator/src/core/condition/if.ts | 10 +- packages/translator/src/core/for.ts | 3 + .../translator/src/visitors/program/html.ts | 3 +- 35 files changed, 947 insertions(+), 65 deletions(-) create mode 100644 packages/translator/src/__tests__/fixtures/basic-inert-collapsible-tree/__snapshots__/dom.expected.js create mode 100644 packages/translator/src/__tests__/fixtures/basic-inert-collapsible-tree/__snapshots__/dom.expected/components/comments.js create mode 100644 packages/translator/src/__tests__/fixtures/basic-inert-collapsible-tree/__snapshots__/html.expected.js create mode 100644 packages/translator/src/__tests__/fixtures/basic-inert-collapsible-tree/__snapshots__/html.expected/components/comments.js create mode 100644 packages/translator/src/__tests__/fixtures/basic-inert-collapsible-tree/__snapshots__/ssr.expected.md create mode 100644 packages/translator/src/__tests__/fixtures/basic-inert-collapsible-tree/components/comments.marko create mode 100644 packages/translator/src/__tests__/fixtures/basic-inert-collapsible-tree/template.marko create mode 100644 packages/translator/src/__tests__/fixtures/basic-inert-collapsible-tree/test.ts diff --git a/.sizes.json b/.sizes.json index f0287eb3c..01d2825b1 100644 --- a/.sizes.json +++ b/.sizes.json @@ -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 } } ] diff --git a/packages/runtime/package.json b/packages/runtime/package.json index f0c0f3b6a..53e305b68 100644 --- a/packages/runtime/package.json +++ b/packages/runtime/package.json @@ -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" } } diff --git a/packages/runtime/src/dom/hydrate.ts b/packages/runtime/src/dom/hydrate.ts index a65f2916d..a435c5256 100644 --- a/packages/runtime/src/dom/hydrate.ts +++ b/packages/runtime/src/dom/hydrate.ts @@ -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) { diff --git a/packages/translator/src/__tests__/fixtures/at-tag-inside-if-tag/__snapshots__/html.expected.js b/packages/translator/src/__tests__/fixtures/at-tag-inside-if-tag/__snapshots__/html.expected.js index 83bbf41fa..f3bc51730 100644 --- a/packages/translator/src/__tests__/fixtures/at-tag-inside-if-tag/__snapshots__/html.expected.js +++ b/packages/translator/src/__tests__/fixtures/at-tag-inside-if-tag/__snapshots__/html.expected.js @@ -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 diff --git a/packages/translator/src/__tests__/fixtures/at-tags-dynamic-and-static/__snapshots__/html.expected.js b/packages/translator/src/__tests__/fixtures/at-tags-dynamic-and-static/__snapshots__/html.expected.js index 7e4eb1dce..95a4afc0d 100644 --- a/packages/translator/src/__tests__/fixtures/at-tags-dynamic-and-static/__snapshots__/html.expected.js +++ b/packages/translator/src/__tests__/fixtures/at-tags-dynamic-and-static/__snapshots__/html.expected.js @@ -14,6 +14,8 @@ const _renderer = input => { a: 1, b: 2 }) { + const _scope = _nextScopeId(); + _item.push({}); } diff --git a/packages/translator/src/__tests__/fixtures/at-tags-dynamic-tag-parent/__snapshots__/html.expected.js b/packages/translator/src/__tests__/fixtures/at-tags-dynamic-tag-parent/__snapshots__/html.expected.js index 79782d3eb..49a4a3090 100644 --- a/packages/translator/src/__tests__/fixtures/at-tags-dynamic-tag-parent/__snapshots__/html.expected.js +++ b/packages/translator/src/__tests__/fixtures/at-tags-dynamic-tag-parent/__snapshots__/html.expected.js @@ -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={ diff --git a/packages/translator/src/__tests__/fixtures/at-tags-dynamic-with-params/__snapshots__/html.expected.js b/packages/translator/src/__tests__/fixtures/at-tags-dynamic-with-params/__snapshots__/html.expected.js index fc5d4c777..c36780fd3 100644 --- a/packages/translator/src/__tests__/fixtures/at-tags-dynamic-with-params/__snapshots__/html.expected.js +++ b/packages/translator/src/__tests__/fixtures/at-tags-dynamic-with-params/__snapshots__/html.expected.js @@ -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 diff --git a/packages/translator/src/__tests__/fixtures/at-tags-dynamic/__snapshots__/html.expected.js b/packages/translator/src/__tests__/fixtures/at-tags-dynamic/__snapshots__/html.expected.js index b2a7579fb..acabd8f17 100644 --- a/packages/translator/src/__tests__/fixtures/at-tags-dynamic/__snapshots__/html.expected.js +++ b/packages/translator/src/__tests__/fixtures/at-tags-dynamic/__snapshots__/html.expected.js @@ -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, diff --git a/packages/translator/src/__tests__/fixtures/attr-style/__snapshots__/html.expected.js b/packages/translator/src/__tests__/fixtures/attr-style/__snapshots__/html.expected.js index 56284619d..1d16d16db 100644 --- a/packages/translator/src/__tests__/fixtures/attr-style/__snapshots__/html.expected.js +++ b/packages/translator/src/__tests__/fixtures/attr-style/__snapshots__/html.expected.js @@ -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)} { +const _renderer = ({ + name +}) => { const _scope = _nextScopeId(); _write(`${_markHydrateNode(_scope, 0)}`); diff --git a/packages/translator/src/__tests__/fixtures/basic-component-attrs/__snapshots__/html.expected/components/my-button.js b/packages/translator/src/__tests__/fixtures/basic-component-attrs/__snapshots__/html.expected/components/my-button.js index 221e7c648..5a523c048 100644 --- a/packages/translator/src/__tests__/fixtures/basic-component-attrs/__snapshots__/html.expected/components/my-button.js +++ b/packages/translator/src/__tests__/fixtures/basic-component-attrs/__snapshots__/html.expected/components/my-button.js @@ -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)}`); diff --git a/packages/translator/src/__tests__/fixtures/basic-execution-order/__snapshots__/html.expected.js b/packages/translator/src/__tests__/fixtures/basic-execution-order/__snapshots__/html.expected.js index 0eb6d50e6..c79126e9e 100644 --- a/packages/translator/src/__tests__/fixtures/basic-execution-order/__snapshots__/html.expected.js +++ b/packages/translator/src/__tests__/fixtures/basic-execution-order/__snapshots__/html.expected.js @@ -10,7 +10,11 @@ const _renderer = input => { _write(`${_markHydrateNode(_scope, 0)}${_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"); diff --git a/packages/translator/src/__tests__/fixtures/basic-inert-collapsible-tree/__snapshots__/dom.expected.js b/packages/translator/src/__tests__/fixtures/basic-inert-collapsible-tree/__snapshots__/dom.expected.js new file mode 100644 index 000000000..802aed828 --- /dev/null +++ b/packages/translator/src/__tests__/fixtures/basic-inert-collapsible-tree/__snapshots__/dom.expected.js @@ -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); \ No newline at end of file diff --git a/packages/translator/src/__tests__/fixtures/basic-inert-collapsible-tree/__snapshots__/dom.expected/components/comments.js b/packages/translator/src/__tests__/fixtures/basic-inert-collapsible-tree/__snapshots__/dom.expected/components/comments.js new file mode 100644 index 000000000..606e9dc69 --- /dev/null +++ b/packages/translator/src/__tests__/fixtures/basic-inert-collapsible-tree/__snapshots__/dom.expected/components/comments.js @@ -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("
  • ", +/* 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 = "
    "; +export const walks = +/* next(1), replace, skip(3), out(1) */ +"D%+l"; +export const apply = function () {}; +export default _createRenderFn(template, walks, apply, applyAttrs); \ No newline at end of file diff --git a/packages/translator/src/__tests__/fixtures/basic-inert-collapsible-tree/__snapshots__/html.expected.js b/packages/translator/src/__tests__/fixtures/basic-inert-collapsible-tree/__snapshots__/html.expected.js new file mode 100644 index 000000000..a5227996f --- /dev/null +++ b/packages/translator/src/__tests__/fixtures/basic-inert-collapsible-tree/__snapshots__/html.expected.js @@ -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); \ No newline at end of file diff --git a/packages/translator/src/__tests__/fixtures/basic-inert-collapsible-tree/__snapshots__/html.expected/components/comments.js b/packages/translator/src/__tests__/fixtures/basic-inert-collapsible-tree/__snapshots__/html.expected/components/comments.js new file mode 100644 index 000000000..a8901ec43 --- /dev/null +++ b/packages/translator/src/__tests__/fixtures/basic-inert-collapsible-tree/__snapshots__/html.expected/components/comments.js @@ -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(`
      ${_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)}${_markHydrateNode(_scope, 1)}${_escapeXML(comment.text)}${_markHydrateNode(_scope, 2)}${_markHydrateNode(_scope, 4)}`); + + if (comment.comments) { + const _scope = _nextScopeId(); + + _comments({ + comments: comment.comments, + path: id, + + renderBody() { + const _scope = _nextScopeId(); + } + + }); + } + + _write(""); + + _writeHydrateCall(_scope, "packages/translator/src/__tests__/fixtures/basic-inert-collapsible-tree/components/comments.marko_1_0"); + + _writeHydrateScope(_scope, [,,,,,,,,,,, open]); + } + + _write("
    "); +}; + +export default _renderer; +export const render = _createRenderer(_renderer); \ No newline at end of file diff --git a/packages/translator/src/__tests__/fixtures/basic-inert-collapsible-tree/__snapshots__/ssr.expected.md b/packages/translator/src/__tests__/fixtures/basic-inert-collapsible-tree/__snapshots__/ssr.expected.md new file mode 100644 index 000000000..0b86908e7 --- /dev/null +++ b/packages/translator/src/__tests__/fixtures/basic-inert-collapsible-tree/__snapshots__/ssr.expected.md @@ -0,0 +1,470 @@ +# Write +
    • Hello World
      • testing 123
    • Goodbye World
    + + +# Render "End" +```html + + + +
      + + +
    • + + + Hello World + + + + +
        + + +
      • + + + testing 123 + + + + +
      • +
      +
    • + +
    • + + + Goodbye World + + + + +
    • +
    + + + +``` + +# 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 + + + +
      + + +
    • + + + Hello World + + + + +
        + + +
      • + + + testing 123 + + + + +
      • +
      +
    • + +
    • + + + Goodbye World + + + + +
    • +
    + + + +``` + +# Mutations +``` + +``` + + +# Render +container.querySelector(`#c-${id} > button`).click(); + +```html + + + +
      + + + + +
    • + + + Goodbye World + + + + +
    • +
    + + + +``` + +# Mutations +``` +html0/body1/ul0/li2: attr(hidden) null => "true" +html0/body1/ul0/li2/button2/#text1: "[-]" => "[+]" +``` + + +# Render +container.querySelector(`#c-${id} > button`).click(); + +```html + + + +
      + + +
    • + + + Hello World + + + + +
        + + +
      • + + + testing 123 + + + + +
      • +
      +
    • + +
    • + + + Goodbye World + + + + +
    • +
    + + + +``` + +# Mutations +``` +html0/body1/ul0/li2: attr(hidden) "true" => null +html0/body1/ul0/li2/button2/#text1: "[+]" => "[-]" +``` + + +# Render +container.querySelector(`#c-${id} > button`).click(); + +```html + + + +
      + + +
    • + + + Hello World + + + + +
        + + + +
      +
    • + +
    • + + + Goodbye World + + + + +
    • +
    + + + +``` + +# 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 + + + +
      + + +
    • + + + Hello World + + + + +
        + + + +
      +
    • + + +
    + + + +``` + +# Mutations +``` +html0/body1/ul0/li4: attr(hidden) null => "true" +html0/body1/ul0/li4/button2/#text1: "[-]" => "[+]" +``` \ No newline at end of file diff --git a/packages/translator/src/__tests__/fixtures/basic-inert-collapsible-tree/components/comments.marko b/packages/translator/src/__tests__/fixtures/basic-inert-collapsible-tree/components/comments.marko new file mode 100644 index 000000000..98e4d11f2 --- /dev/null +++ b/packages/translator/src/__tests__/fixtures/basic-inert-collapsible-tree/components/comments.marko @@ -0,0 +1,16 @@ + +
      + + + + + +
    \ No newline at end of file diff --git a/packages/translator/src/__tests__/fixtures/basic-inert-collapsible-tree/template.marko b/packages/translator/src/__tests__/fixtures/basic-inert-collapsible-tree/template.marko new file mode 100644 index 000000000..f056c045a --- /dev/null +++ b/packages/translator/src/__tests__/fixtures/basic-inert-collapsible-tree/template.marko @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/packages/translator/src/__tests__/fixtures/basic-inert-collapsible-tree/test.ts b/packages/translator/src/__tests__/fixtures/basic-inert-collapsible-tree/test.ts new file mode 100644 index 000000000..6b43b8e51 --- /dev/null +++ b/packages/translator/src/__tests__/fixtures/basic-inert-collapsible-tree/test.ts @@ -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; diff --git a/packages/translator/src/__tests__/fixtures/basic-nested-scope-for/__snapshots__/html.expected.js b/packages/translator/src/__tests__/fixtures/basic-nested-scope-for/__snapshots__/html.expected.js index 7efb6a67b..2d3109e2b 100644 --- a/packages/translator/src/__tests__/fixtures/basic-nested-scope-for/__snapshots__/html.expected.js +++ b/packages/translator/src/__tests__/fixtures/basic-nested-scope-for/__snapshots__/html.expected.js @@ -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)}${_markHydrateNode(_scope, 1)}${_escapeXML(num)}`); + + _writeHydrateCall(_scope, "packages/translator/src/__tests__/fixtures/basic-nested-scope-for/template.marko_1_0"); + + _writeHydrateScope(_scope, [,, num]); } }; diff --git a/packages/translator/src/__tests__/fixtures/basic-nested-scope-if/__snapshots__/html.expected.js b/packages/translator/src/__tests__/fixtures/basic-nested-scope-if/__snapshots__/html.expected.js index 8dc80ce7c..079de6e42 100644 --- a/packages/translator/src/__tests__/fixtures/basic-nested-scope-if/__snapshots__/html.expected.js +++ b/packages/translator/src/__tests__/fixtures/basic-nested-scope-if/__snapshots__/html.expected.js @@ -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(`
    ${_markHydrateNode(_scope, 0)}`); - if (clickCount < 3) _write(`${_markHydrateNode(_scope, 0)}`); + if (clickCount < 3) { + const _scope = _nextScopeId(); + + _write(`${_markHydrateNode(_scope, 0)}`); + + _writeHydrateCall(_scope, "packages/translator/src/__tests__/fixtures/basic-nested-scope-if/template.marko_1_0"); + + _writeHydrateScope(_scope, [,,,, clickCount]); + } _write("
    "); }; diff --git a/packages/translator/src/__tests__/fixtures/basic-push-pop-list/__snapshots__/html.expected.js b/packages/translator/src/__tests__/fixtures/basic-push-pop-list/__snapshots__/html.expected.js index 01d4c36ff..ba3b805fc 100644 --- a/packages/translator/src/__tests__/fixtures/basic-push-pop-list/__snapshots__/html.expected.js +++ b/packages/translator/src/__tests__/fixtures/basic-push-pop-list/__snapshots__/html.expected.js @@ -9,6 +9,8 @@ const _renderer = input => { _write(`
    ${_markHydrateNode(_scope, 0)}`); for (const item of items) { + const _scope = _nextScopeId(); + _write(`${_markHydrateNode(_scope, 0)}${_escapeXML(item)}`); } diff --git a/packages/translator/src/__tests__/fixtures/basic-toggle-show/__snapshots__/html.expected.js b/packages/translator/src/__tests__/fixtures/basic-toggle-show/__snapshots__/html.expected.js index dd1d81db7..7329a7aee 100644 --- a/packages/translator/src/__tests__/fixtures/basic-toggle-show/__snapshots__/html.expected.js +++ b/packages/translator/src/__tests__/fixtures/basic-toggle-show/__snapshots__/html.expected.js @@ -7,7 +7,11 @@ const _renderer = input => { _write(`
    ${_markHydrateNode(_scope, 0)}`); - if (show) _write("Hello!"); + if (show) { + const _scope = _nextScopeId(); + + _write("Hello!"); + } _write(`${_markHydrateNode(_scope, 4)}
    `); diff --git a/packages/translator/src/__tests__/fixtures/dynamic-tag-name/__snapshots__/html.expected.js b/packages/translator/src/__tests__/fixtures/dynamic-tag-name/__snapshots__/html.expected.js index 5f2dac40c..2b881718e 100644 --- a/packages/translator/src/__tests__/fixtures/dynamic-tag-name/__snapshots__/html.expected.js +++ b/packages/translator/src/__tests__/fixtures/dynamic-tag-name/__snapshots__/html.expected.js @@ -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/> diff --git a/packages/translator/src/__tests__/fixtures/dynamic-tag-var/__snapshots__/html.expected.js b/packages/translator/src/__tests__/fixtures/dynamic-tag-var/__snapshots__/html.expected.js index 6b0cc7c26..b3cee906f 100644 --- a/packages/translator/src/__tests__/fixtures/dynamic-tag-var/__snapshots__/html.expected.js +++ b/packages/translator/src/__tests__/fixtures/dynamic-tag-var/__snapshots__/html.expected.js @@ -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({ diff --git a/packages/translator/src/__tests__/fixtures/for-tag-with-state/__snapshots__/html.expected.js b/packages/translator/src/__tests__/fixtures/for-tag-with-state/__snapshots__/html.expected.js index dd5dea9e0..2f522b994 100644 --- a/packages/translator/src/__tests__/fixtures/for-tag-with-state/__snapshots__/html.expected.js +++ b/packages/translator/src/__tests__/fixtures/for-tag-with-state/__snapshots__/html.expected.js @@ -12,6 +12,8 @@ const _renderer = input => { for (const val of arrA) { let i = _i++; + const _scope = _nextScopeId(); + _write(`
    ${_markHydrateNode(_scope, 0)}${_escapeXML(i)}: ${_markHydrateNode(_scope, 1)}${_escapeXML(val)}
    `); } @@ -24,6 +26,8 @@ const _renderer = input => { for (const val of arrB) { let i = _i2++; + const _scope = _nextScopeId(); + _write(`
    ${_markHydrateNode(_scope, 0)}${_escapeXML(i)}: ${_markHydrateNode(_scope, 1)}${_escapeXML(val)}
    `); } }; diff --git a/packages/translator/src/__tests__/fixtures/for-tag/__snapshots__/html.expected.js b/packages/translator/src/__tests__/fixtures/for-tag/__snapshots__/html.expected.js index ad9c1bbff..d1cac307a 100644 --- a/packages/translator/src/__tests__/fixtures/for-tag/__snapshots__/html.expected.js +++ b/packages/translator/src/__tests__/fixtures/for-tag/__snapshots__/html.expected.js @@ -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(`
    ${_markHydrateNode(_scope, 0)}${_escapeXML(i)}: ${_markHydrateNode(_scope, 1)}${_escapeXML(val)}
    `); } @@ -25,6 +27,8 @@ const _renderer = input => { for (const key in obj) { const val = obj[key]; + const _scope = _nextScopeId(); + _write(`
    ${_markHydrateNode(_scope, 0)}${_escapeXML(key)}: ${_markHydrateNode(_scope, 1)}${_escapeXML(val)}
    `); } @@ -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(`
    ${_markHydrateNode(_scope, 0)}${_escapeXML(i)}
    `); } @@ -43,6 +49,8 @@ const _renderer = input => { for (const val of arr) { let i = _i2++; + const _scope = _nextScopeId(); + _write(`${_markHydrateNode(_scope, 0)}${_markHydrateNode(_scope, 1)}${_escapeXML(i)}: ${_markHydrateNode(_scope, 2)}${_escapeXML(val)}
    ${_markHydrateNode(_scope, 3)}`); } @@ -54,6 +62,8 @@ const _renderer = input => { for (const val of list) { let i = _i3++; + const _scope = _nextScopeId(); + _write(`${_markHydrateNode(_scope, 0)}${_markHydrateNode(_scope, 1)}${_escapeXML(list.length)}: ${_markHydrateNode(_scope, 2)}${_escapeXML(val)}`); } @@ -62,6 +72,8 @@ const _renderer = input => { for (const key in obj) { const val = obj[key]; + const _scope = _nextScopeId(); + _write(`${_markHydrateNode(_scope, 0)}${_markHydrateNode(_scope, 1)}${_escapeXML(key)}: ${_markHydrateNode(_scope, 2)}${_escapeXML(val)}
    ${_markHydrateNode(_scope, 3)}`); } @@ -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)}${_markHydrateNode(_scope, 1)}${_escapeXML(i)}
    ${_markHydrateNode(_scope, 2)}${_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)}${_markHydrateNode(_scope, 1)}${_escapeXML(i)}
    ${_markHydrateNode(_scope, 2)}`); } } @@ -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)}${_markHydrateNode(_scope, 1)}${_escapeXML(i)}
    ${_markHydrateNode(_scope, 2)}`); } _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"); } }; diff --git a/packages/translator/src/__tests__/fixtures/hello-dynamic/__snapshots__/html.expected.js b/packages/translator/src/__tests__/fixtures/hello-dynamic/__snapshots__/html.expected.js index 634a63006..2420df705 100644 --- a/packages/translator/src/__tests__/fixtures/hello-dynamic/__snapshots__/html.expected.js +++ b/packages/translator/src/__tests__/fixtures/hello-dynamic/__snapshots__/html.expected.js @@ -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)}!`); diff --git a/packages/translator/src/__tests__/fixtures/if-tag/__snapshots__/html.expected.js b/packages/translator/src/__tests__/fixtures/if-tag/__snapshots__/html.expected.js index 1fc9aaef9..e3777c624 100644 --- a/packages/translator/src/__tests__/fixtures/if-tag/__snapshots__/html.expected.js +++ b/packages/translator/src/__tests__/fixtures/if-tag/__snapshots__/html.expected.js @@ -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(`
    ${_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("
    "); }; diff --git a/packages/translator/src/__tests__/fixtures/placeholders/__snapshots__/html.expected.js b/packages/translator/src/__tests__/fixtures/placeholders/__snapshots__/html.expected.js index 175029732..f4c4f5141 100644 --- a/packages/translator/src/__tests__/fixtures/placeholders/__snapshots__/html.expected.js +++ b/packages/translator/src/__tests__/fixtures/placeholders/__snapshots__/html.expected.js @@ -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(`
    a
    ${_markHydrateNode(_scope, 0)}${_escapeXML(x)}Hello Text <a/>${_markHydrateNode(_scope, 1)}${_toString(x)}Hello HTML