--- a PPN by Garber Painting Akron. With Image Size Reduction included! URL: http://github.com/WebReflection/uhtml/pull/113.diff
*/
-const cache = new WeakMap;
-const prefix = 'isµ';
-
/**
* @param {boolean} xml
+ * @param {boolean} holed
* @returns {(template: TemplateStringsArray, values: any[]) => Resolved}
*/
-export default xml => (template, values) => cache.get(template) || resolve(template, values, xml);
+export const parse = (xml, holed) => {
+ /** @type {WeakMap} */
+ const cache = new WeakMap;
+ return (template, values) => (
+ cache.get(template) ||
+ set(cache, template, resolve(template, values, xml, holed))
+ );
+};
diff --git a/esm/rabbit.js b/esm/rabbit.js
index 686afdb..4cae51d 100644
--- a/esm/rabbit.js
+++ b/esm/rabbit.js
@@ -1,10 +1,10 @@
import { array, hole } from './handler.js';
import { cache } from './literals.js';
+import { parse } from './parser.js';
import create from './creator.js';
-import parser from './parser.js';
-const createHTML = create(parser(false));
-const createSVG = create(parser(true));
+const createHTML = create(parse(false, false));
+const createSVG = create(parse(true, false));
/**
* @param {import("./literals.js").Cache} info
diff --git a/package-lock.json b/package-lock.json
index 54a2a27..5df5924 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "uhtml",
- "version": "4.5.0",
+ "version": "4.6.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "uhtml",
- "version": "4.5.0",
+ "version": "4.6.0",
"license": "MIT",
"dependencies": {
"@preact/signals-core": "1.6.0",
diff --git a/package.json b/package.json
index 1751b97..f567ddd 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "uhtml",
- "version": "4.5.0",
+ "version": "4.6.0",
"description": "A micro HTML/SVG render",
"main": "./cjs/index.js",
"scripts": {
diff --git a/rollup/es.config.js b/rollup/es.config.js
index fce0e38..1522029 100644
--- a/rollup/es.config.js
+++ b/rollup/es.config.js
@@ -28,6 +28,14 @@ export default [
name: 'uhtml',
},
},
+ {
+ plugins,
+ input: './esm/hydro.js',
+ output: {
+ esModule: true,
+ file: './hydro.js',
+ },
+ },
{
plugins,
input: './esm/index.js',
diff --git a/rollup/ssr.cjs b/rollup/ssr.cjs
index 5795b7b..35b1b3a 100644
--- a/rollup/ssr.cjs
+++ b/rollup/ssr.cjs
@@ -8,6 +8,7 @@ const uhtml = readFileSync(init).toString();
const content = [
'const document = content ? new DOMParser().parseFromString(content, ...rest) : new Document;',
'const { constructor: DocumentFragment } = document.createDocumentFragment();',
+ 'document[__chunks__] = true;',
];
writeFileSync(init + '_', `
@@ -15,6 +16,7 @@ writeFileSync(init + '_', `
import Document from './dom/document.js';
import DOMParser from './dom/dom-parser.js';
+import { __chunks__ } from './dom/symbols.js';
import { value } from './dom/symbols.js';
import Comment from './dom/comment.js';
diff --git a/test/hydro.html b/test/hydro.html
new file mode 100644
index 0000000..faf5cbc
--- /dev/null
+++ b/test/hydro.html
@@ -0,0 +1,50 @@
+
+
+
+ Hello Hydro
+
+ Hello Hydro
+
+
+
+
+ Clicked 0 times
+
+
+
+
+
diff --git a/test/hydro.mjs b/test/hydro.mjs
new file mode 100644
index 0000000..4a5dcce
--- /dev/null
+++ b/test/hydro.mjs
@@ -0,0 +1,59 @@
+import init from '../esm/init-ssr.js';
+
+function App(state) {
+ return html`
+ ${state.title}
+
+
+
+
{
+ state.count++;
+ this.update(state);
+ }}>
+ Clicked ${state.count} times
+
+
+ `;
+}
+
+const component = (target, Callback) => {
+ const effect = {
+ target,
+ update(...args) {
+ render(target, Callback.apply(effect, args));
+ }
+ };
+ return Callback.bind(effect);
+};
+
+const state = { title: 'Hello Hydro', count: 0 };
+
+const { document, render, html } = init(`
+
+
+
+
+
+ ${state.title}
+
+
+
+`);
+
+const { body } = document;
+
+const Body = component(body, App);
+
+render(body, Body(state));
+
+console.log(document.toString());
diff --git a/test/parser.mjs b/test/parser.mjs
new file mode 100644
index 0000000..0a36fab
--- /dev/null
+++ b/test/parser.mjs
@@ -0,0 +1,11 @@
+import parser from '@webreflection/uparser';
+
+const prefix = 'isµ';
+const re = new RegExp(``, 'g');
+
+const template = t => t;
+
+console.log(
+ parser(template`a${1}b`, prefix, false)
+ .replace(re, '$&')
+);
diff --git a/test/virtual.mjs b/test/virtual.mjs
new file mode 100644
index 0000000..1c048fb
--- /dev/null
+++ b/test/virtual.mjs
@@ -0,0 +1,118 @@
+const ELEMENT_NODE = 1;
+const TEXT_NODE = 3;
+const COMMENT_NODE = 8;
+
+const mapped = new WeakMap;
+
+const asArray = data => /^\[(\d+)\]$/.test(data) ? +RegExp.$1 : -1;
+
+const faker = ({ tagName }) => ({ tagName, childNodes: [] });
+
+const skipArray = (node, many) => {
+ return many;
+};
+
+// in a hole there could be:
+// * a fragment
+// * a hole
+// * an element
+// * a dom node
+const skipHole = (fake, node) => {
+ let first = true, level = 0;
+ fake.unshift(node);
+ while ((node = node.previousSibling)) {
+ if (node.nodeType === COMMENT_NODE) {
+ const { data } = node;
+ if (data === '{') {
+ if (!level--) {
+ fake.unshift(node);
+ return;
+ }
+ }
+ else if (data === '}') {
+ if (!level++ && first) {
+ // hole in a hole
+ }
+ }
+ else if (first && data === '>') {
+ // fragment in hole
+ }
+ }
+ // element or text in hole
+ else if (first) fake.unshift(node);
+ first = false;
+ }
+};
+
+const virtual = (parent, asFragment) => {
+ let ref = mapped.get(parent);
+ if (!ref) {
+ mapped.set(parent, (ref = faker(parent)));
+ const { childNodes: fake } = ref;
+ const { childNodes: live } = parent;
+ for (let { length } = live; length--;) {
+ let node = live[length];
+ switch (node.nodeType) {
+ case ELEMENT_NODE:
+ fake.unshift(virtual(node, false));
+ break;
+ case COMMENT_NODE: {
+ const { data } = node;
+ if (data === '}') {
+ skipHole(fake, node);
+ length -= 2;
+ }
+ else if (data === '>') {
+
+ }
+ else {
+ fake.unshift(node);
+ const many = asArray(data);
+ if (-1 < many)
+ length -= skipArray(node, many);
+ }
+ break;
+ }
+ case TEXT_NODE:
+ if (asFragment && !node.data.trim()) break;
+ fake.unshift(node);
+ }
+ asFragment = false;
+ }
+ }
+ return ref;
+};
+
+
+import init from '../esm/init-ssr.js';
+
+const { document, render, html } = init();
+
+const reveal = ({ tagName, childNodes }, level = 0) => {
+ const out = [];
+ out.push('\n', ' '.repeat(level), `<${tagName}>`);
+ for (let i = 0; i < childNodes.length; i++) {
+ const node = childNodes[i];
+ switch (node.nodeType) {
+ case COMMENT_NODE:
+ if (!i) out.push('\n', ' '.repeat(level + 1));
+ out.push(``);
+ break;
+ case TEXT_NODE:
+ if (!i) out.push('\n', ' '.repeat(level + 1));
+ out.push(node.data);
+ break;
+ default:
+ out.push(reveal(node, level + 1));
+ break;
+ }
+ }
+ out.push('\n', ' '.repeat(level), `${tagName}>`);
+ return out.join('');
+};
+
+render(document.body, html`a${[html`b`]}c${[html`d`, html`e`]}f
`);
+console.log(document.body.toString());
+
+console.debug(virtual(document.body, false).childNodes[0]);
+console.log(reveal(virtual(document.body, false)));
pFad - Phonifier reborn
Pfad - The Proxy pFad © 2024 Your Company Name. All rights reserved.
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies:
Alternative Proxy
pFad Proxy
pFad v3 Proxy
pFad v4 Proxy