@b9g/crank 0.5.0-debug.0 → 0.5.1

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/dom.cjs CHANGED
@@ -1,49 +1,61 @@
1
1
  'use strict';
2
2
 
3
- Object.defineProperty(exports, '__esModule', { value: true });
4
-
5
3
  var crank = require('./crank.cjs');
6
4
 
7
5
  const SVG_NAMESPACE = "http://www.w3.org/2000/svg";
8
6
  const impl = {
9
- parse(text) {
10
- if (typeof document.createRange === "function") {
11
- const fragment = document.createRange().createContextualFragment(text);
12
- return Array.from(fragment.childNodes);
13
- }
14
- else {
15
- const childNodes = new DOMParser().parseFromString(text, "text/html").body
16
- .childNodes;
17
- return Array.from(childNodes);
18
- }
19
- },
20
- scope(scope, tag) {
7
+ scope(xmlns, tag) {
21
8
  // TODO: Should we handle xmlns???
22
9
  switch (tag) {
23
10
  case crank.Portal:
24
11
  case "foreignObject":
25
- return undefined;
12
+ xmlns = undefined;
13
+ break;
26
14
  case "svg":
27
- return SVG_NAMESPACE;
28
- default:
29
- return scope;
15
+ xmlns = SVG_NAMESPACE;
16
+ break;
30
17
  }
18
+ return xmlns;
31
19
  },
32
- create(tag, _props, ns) {
20
+ create(tag, _props, xmlns) {
33
21
  if (typeof tag !== "string") {
34
22
  throw new Error(`Unknown tag: ${tag.toString()}`);
35
23
  }
36
24
  else if (tag.toLowerCase() === "svg") {
37
- ns = SVG_NAMESPACE;
25
+ xmlns = SVG_NAMESPACE;
38
26
  }
39
- return ns ? document.createElementNS(ns, tag) : document.createElement(tag);
27
+ return xmlns
28
+ ? document.createElementNS(xmlns, tag)
29
+ : document.createElement(tag);
30
+ },
31
+ hydrate(tag, node, props) {
32
+ if (typeof tag !== "string" && tag !== crank.Portal) {
33
+ throw new Error(`Unknown tag: ${tag.toString()}`);
34
+ }
35
+ if (typeof tag === "string" &&
36
+ tag.toUpperCase() !== node.tagName) {
37
+ console.error(`Expected <${tag}> while hydrating but found:`, node);
38
+ return undefined;
39
+ }
40
+ const children = [];
41
+ for (let i = 0; i < node.childNodes.length; i++) {
42
+ const child = node.childNodes[i];
43
+ if (child.nodeType === Node.TEXT_NODE) {
44
+ children.push(child.data);
45
+ }
46
+ else if (child.nodeType === Node.ELEMENT_NODE) {
47
+ children.push(child);
48
+ }
49
+ }
50
+ // TODO: extract props from nodes
51
+ return { props, children };
40
52
  },
41
53
  patch(_tag,
42
54
  // TODO: Why does this assignment work?
43
55
  node, name,
44
56
  // TODO: Stricter typings?
45
- value, oldValue, scope) {
46
- const isSVG = scope === SVG_NAMESPACE;
57
+ value, oldValue, xmlns) {
58
+ const isSVG = xmlns === SVG_NAMESPACE;
47
59
  switch (name) {
48
60
  case "style": {
49
61
  const style = node.style;
@@ -119,7 +131,9 @@ const impl = {
119
131
  const descriptor = Object.getOwnPropertyDescriptor(obj, name);
120
132
  if (descriptor != null &&
121
133
  (descriptor.writable === true || descriptor.set !== undefined)) {
122
- node[name] = value;
134
+ if (node[name] !== value) {
135
+ node[name] = value;
136
+ }
123
137
  return;
124
138
  }
125
139
  // if the property wasn't writable, fall through to the code below
@@ -206,17 +220,79 @@ const impl = {
206
220
  }
207
221
  }
208
222
  },
223
+ text(text, _scope, hydrationData) {
224
+ if (hydrationData != null) {
225
+ let value = hydrationData.children.shift();
226
+ if (typeof value !== "string" || !value.startsWith(text)) {
227
+ console.error(`Expected "${text}" while hydrating but found:`, value);
228
+ }
229
+ else if (text.length < value.length) {
230
+ value = value.slice(text.length);
231
+ hydrationData.children.unshift(value);
232
+ }
233
+ }
234
+ return text;
235
+ },
236
+ raw(value, xmlns, hydrationData) {
237
+ let result;
238
+ if (typeof value === "string") {
239
+ const el = xmlns == null
240
+ ? document.createElement("div")
241
+ : document.createElementNS(xmlns, "svg");
242
+ el.innerHTML = value;
243
+ if (el.childNodes.length === 0) {
244
+ result = undefined;
245
+ }
246
+ else if (el.childNodes.length === 1) {
247
+ result = el.childNodes[0];
248
+ }
249
+ else {
250
+ result = Array.from(el.childNodes);
251
+ }
252
+ }
253
+ else {
254
+ result = value;
255
+ }
256
+ if (hydrationData != null) {
257
+ // TODO: maybe we should warn on incorrect values
258
+ if (Array.isArray(result)) {
259
+ for (let i = 0; i < result.length; i++) {
260
+ const node = result[i];
261
+ if (typeof node !== "string" &&
262
+ (node.nodeType === Node.ELEMENT_NODE ||
263
+ node.nodeType === Node.TEXT_NODE)) {
264
+ hydrationData.children.shift();
265
+ }
266
+ }
267
+ }
268
+ else if (result != null && typeof result !== "string") {
269
+ if (result.nodeType === Node.ELEMENT_NODE ||
270
+ result.nodeType === Node.TEXT_NODE) {
271
+ hydrationData.children.shift();
272
+ }
273
+ }
274
+ }
275
+ return result;
276
+ },
209
277
  };
210
278
  class DOMRenderer extends crank.Renderer {
211
279
  constructor() {
212
280
  super(impl);
213
281
  }
214
282
  render(children, root, ctx) {
215
- if (root == null || typeof root.nodeType !== "number") {
216
- throw new TypeError(`Render root is not a node. Received: ${JSON.stringify(root && root.toString())}`);
217
- }
283
+ validateRoot(root);
218
284
  return super.render(children, root, ctx);
219
285
  }
286
+ hydrate(children, root, ctx) {
287
+ validateRoot(root);
288
+ return super.hydrate(children, root, ctx);
289
+ }
290
+ }
291
+ function validateRoot(root) {
292
+ if (root === null ||
293
+ (typeof root === "object" && typeof root.nodeType !== "number")) {
294
+ throw new TypeError(`Render root is not a node. Received: ${JSON.stringify(root && root.toString())}`);
295
+ }
220
296
  }
221
297
  const renderer = new DOMRenderer();
222
298
 
package/dom.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"dom.cjs","sources":["../src/dom.ts"],"sourcesContent":["import {\n\tChildren,\n\tContext,\n\tElementValue,\n\tPortal,\n\tRenderer,\n\tRendererImpl,\n} from \"./crank.js\";\n\nconst SVG_NAMESPACE = \"http://www.w3.org/2000/svg\";\n\nexport const impl: Partial<RendererImpl<Node, string>> = {\n\tparse(text: string): ElementValue<Node> {\n\t\tif (typeof document.createRange === \"function\") {\n\t\t\tconst fragment = document.createRange().createContextualFragment(text);\n\t\t\treturn Array.from(fragment.childNodes);\n\t\t} else {\n\t\t\tconst childNodes = new DOMParser().parseFromString(text, \"text/html\").body\n\t\t\t\t.childNodes;\n\t\t\treturn Array.from(childNodes);\n\t\t}\n\t},\n\n\tscope(scope: string, tag: string | symbol): string | undefined {\n\t\t// TODO: Should we handle xmlns???\n\t\tswitch (tag) {\n\t\t\tcase Portal:\n\t\t\tcase \"foreignObject\":\n\t\t\t\treturn undefined;\n\t\t\tcase \"svg\":\n\t\t\t\treturn SVG_NAMESPACE;\n\t\t\tdefault:\n\t\t\t\treturn scope;\n\t\t}\n\t},\n\n\tcreate(tag: string | symbol, _props: unknown, ns: string | undefined): Node {\n\t\tif (typeof tag !== \"string\") {\n\t\t\tthrow new Error(`Unknown tag: ${tag.toString()}`);\n\t\t} else if (tag.toLowerCase() === \"svg\") {\n\t\t\tns = SVG_NAMESPACE;\n\t\t}\n\n\t\treturn ns ? document.createElementNS(ns, tag) : document.createElement(tag);\n\t},\n\n\tpatch(\n\t\t_tag: string | symbol,\n\t\t// TODO: Why does this assignment work?\n\t\tnode: HTMLElement | SVGElement,\n\t\tname: string,\n\t\t// TODO: Stricter typings?\n\t\tvalue: unknown,\n\t\toldValue: unknown,\n\t\tscope: string | undefined,\n\t): void {\n\t\tconst isSVG = scope === SVG_NAMESPACE;\n\t\tswitch (name) {\n\t\t\tcase \"style\": {\n\t\t\t\tconst style: CSSStyleDeclaration = node.style;\n\t\t\t\tif (style == null) {\n\t\t\t\t\tnode.setAttribute(\"style\", value as string);\n\t\t\t\t} else if (value == null || value === false) {\n\t\t\t\t\tnode.removeAttribute(\"style\");\n\t\t\t\t} else if (value === true) {\n\t\t\t\t\tnode.setAttribute(\"style\", \"\");\n\t\t\t\t} else if (typeof value === \"string\") {\n\t\t\t\t\tif (style.cssText !== value) {\n\t\t\t\t\t\tstyle.cssText = value;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (typeof oldValue === \"string\") {\n\t\t\t\t\t\tstyle.cssText = \"\";\n\t\t\t\t\t}\n\n\t\t\t\t\tfor (const styleName in {...(oldValue as {}), ...(value as {})}) {\n\t\t\t\t\t\tconst styleValue = value && (value as any)[styleName];\n\t\t\t\t\t\tif (styleValue == null) {\n\t\t\t\t\t\t\tstyle.removeProperty(styleName);\n\t\t\t\t\t\t} else if (style.getPropertyValue(styleName) !== styleValue) {\n\t\t\t\t\t\t\tstyle.setProperty(styleName, styleValue);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"class\":\n\t\t\tcase \"className\":\n\t\t\t\tif (value === true) {\n\t\t\t\t\tnode.setAttribute(\"class\", \"\");\n\t\t\t\t} else if (value == null) {\n\t\t\t\t\tnode.removeAttribute(\"class\");\n\t\t\t\t} else if (!isSVG) {\n\t\t\t\t\tif (node.className !== value) {\n\t\t\t\t\t\t(node as any)[\"className\"] = value;\n\t\t\t\t\t}\n\t\t\t\t} else if (node.getAttribute(\"class\") !== value) {\n\t\t\t\t\tnode.setAttribute(\"class\", value as string);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"innerHTML\":\n\t\t\t\tif (value !== oldValue) {\n\t\t\t\t\tnode.innerHTML = value as any;\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\tdefault: {\n\t\t\t\tif (\n\t\t\t\t\tname in node &&\n\t\t\t\t\t// boolean properties will coerce strings, but sometimes they map to\n\t\t\t\t\t// enumerated attributes, where truthy strings (\"false\", \"no\") map to\n\t\t\t\t\t// falsy properties, so we use attributes in this case.\n\t\t\t\t\t!(\n\t\t\t\t\t\ttypeof value === \"string\" &&\n\t\t\t\t\t\ttypeof (node as any)[name] === \"boolean\"\n\t\t\t\t\t)\n\t\t\t\t) {\n\t\t\t\t\t// walk up the object's prototype chain to find the owner of the\n\t\t\t\t\t// named property\n\t\t\t\t\tlet obj = node;\n\t\t\t\t\tdo {\n\t\t\t\t\t\tif (Object.prototype.hasOwnProperty.call(obj, name)) {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t} while ((obj = Object.getPrototypeOf(obj)));\n\n\t\t\t\t\t// get the descriptor for the named property and check whether it\n\t\t\t\t\t// implies that the property is writable\n\t\t\t\t\tconst descriptor = Object.getOwnPropertyDescriptor(obj, name);\n\t\t\t\t\tif (\n\t\t\t\t\t\tdescriptor != null &&\n\t\t\t\t\t\t(descriptor.writable === true || descriptor.set !== undefined)\n\t\t\t\t\t) {\n\t\t\t\t\t\t(node as any)[name] = value;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\t// if the property wasn't writable, fall through to the code below\n\t\t\t\t\t// which uses setAttribute() instead of assigning directly.\n\t\t\t\t}\n\n\t\t\t\tif (value === true) {\n\t\t\t\t\tvalue = \"\";\n\t\t\t\t} else if (value == null || value === false) {\n\t\t\t\t\tnode.removeAttribute(name);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (node.getAttribute(name) !== value) {\n\t\t\t\t\tnode.setAttribute(name, value as any);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tarrange(\n\t\ttag: string | symbol,\n\t\tnode: Node,\n\t\tprops: Record<string, any>,\n\t\tchildren: Array<Element | string>,\n\t\t_oldProps: Record<string, any> | undefined,\n\t\toldChildren: Array<Element | string> | undefined,\n\t): void {\n\t\tif (tag === Portal && (node == null || typeof node.nodeType !== \"number\")) {\n\t\t\tthrow new TypeError(\n\t\t\t\t`Portal root is not a node. Received: ${JSON.stringify(\n\t\t\t\t\tnode && node.toString(),\n\t\t\t\t)}`,\n\t\t\t);\n\t\t}\n\n\t\tif (\n\t\t\t!(\"innerHTML\" in props) &&\n\t\t\t// We don’t want to update elements without explicit children (<div/>),\n\t\t\t// because these elements sometimes have child nodes added via raw\n\t\t\t// DOM manipulations.\n\t\t\t// However, if an element has previously rendered children, we clear the\n\t\t\t// them because it would be surprising not to clear Crank managed\n\t\t\t// children, even if the new element does not have explicit children.\n\t\t\t(\"children\" in props || (oldChildren && oldChildren.length))\n\t\t) {\n\t\t\tif (children.length === 0) {\n\t\t\t\tnode.textContent = \"\";\n\t\t\t} else {\n\t\t\t\tlet oldChild = node.firstChild;\n\t\t\t\tlet i = 0;\n\t\t\t\twhile (oldChild !== null && i < children.length) {\n\t\t\t\t\tconst newChild = children[i];\n\t\t\t\t\tif (oldChild === newChild) {\n\t\t\t\t\t\toldChild = oldChild.nextSibling;\n\t\t\t\t\t\ti++;\n\t\t\t\t\t} else if (typeof newChild === \"string\") {\n\t\t\t\t\t\tif (oldChild.nodeType === Node.TEXT_NODE) {\n\t\t\t\t\t\t\tif ((oldChild as Text).data !== newChild) {\n\t\t\t\t\t\t\t\t(oldChild as Text).data = newChild;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\toldChild = oldChild.nextSibling;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tnode.insertBefore(document.createTextNode(newChild), oldChild);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\ti++;\n\t\t\t\t\t} else if (oldChild.nodeType === Node.TEXT_NODE) {\n\t\t\t\t\t\tconst nextSibling = oldChild.nextSibling;\n\t\t\t\t\t\tnode.removeChild(oldChild);\n\t\t\t\t\t\toldChild = nextSibling;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnode.insertBefore(newChild, oldChild);\n\t\t\t\t\t\ti++;\n\t\t\t\t\t\t// TODO: This is an optimization but we need to think a little more about other cases like prepending.\n\t\t\t\t\t\tif (oldChild !== children[i]) {\n\t\t\t\t\t\t\tconst nextSibling = oldChild.nextSibling;\n\t\t\t\t\t\t\tnode.removeChild(oldChild);\n\t\t\t\t\t\t\toldChild = nextSibling;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// remove excess DOM nodes\n\t\t\t\twhile (oldChild !== null) {\n\t\t\t\t\tconst nextSibling = oldChild.nextSibling;\n\t\t\t\t\tnode.removeChild(oldChild);\n\t\t\t\t\toldChild = nextSibling;\n\t\t\t\t}\n\n\t\t\t\t// append excess children\n\t\t\t\tfor (; i < children.length; i++) {\n\t\t\t\t\tconst newChild = children[i];\n\t\t\t\t\tnode.appendChild(\n\t\t\t\t\t\ttypeof newChild === \"string\"\n\t\t\t\t\t\t\t? document.createTextNode(newChild)\n\t\t\t\t\t\t\t: newChild,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n};\n\nexport class DOMRenderer extends Renderer<Node, string> {\n\tconstructor() {\n\t\tsuper(impl);\n\t}\n\n\trender(\n\t\tchildren: Children,\n\t\troot: Node,\n\t\tctx?: Context,\n\t): Promise<ElementValue<Node>> | ElementValue<Node> {\n\t\tif (root == null || typeof root.nodeType !== \"number\") {\n\t\t\tthrow new TypeError(\n\t\t\t\t`Render root is not a node. Received: ${JSON.stringify(\n\t\t\t\t\troot && root.toString(),\n\t\t\t\t)}`,\n\t\t\t);\n\t\t}\n\n\t\treturn super.render(children, root, ctx);\n\t}\n}\n\nexport const renderer = new DOMRenderer();\n\ndeclare global {\n\tmodule Crank {\n\t\tinterface EventMap extends GlobalEventHandlersEventMap {}\n\t}\n}\n"],"names":["Portal","Renderer"],"mappings":";;;;;;AASA,MAAM,aAAa,GAAG,4BAA4B,CAAC;AAEtC,MAAA,IAAI,GAAwC;AACxD,IAAA,KAAK,CAAC,IAAY,EAAA;AACjB,QAAA,IAAI,OAAO,QAAQ,CAAC,WAAW,KAAK,UAAU,EAAE;YAC/C,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC,wBAAwB,CAAC,IAAI,CAAC,CAAC;YACvE,OAAO,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;AACvC,SAAA;AAAM,aAAA;AACN,YAAA,MAAM,UAAU,GAAG,IAAI,SAAS,EAAE,CAAC,eAAe,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC,IAAI;AACxE,iBAAA,UAAU,CAAC;AACb,YAAA,OAAO,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;AAC9B,SAAA;KACD;IAED,KAAK,CAAC,KAAa,EAAE,GAAoB,EAAA;;AAExC,QAAA,QAAQ,GAAG;AACV,YAAA,KAAKA,YAAM,CAAC;AACZ,YAAA,KAAK,eAAe;AACnB,gBAAA,OAAO,SAAS,CAAC;AAClB,YAAA,KAAK,KAAK;AACT,gBAAA,OAAO,aAAa,CAAC;AACtB,YAAA;AACC,gBAAA,OAAO,KAAK,CAAC;AACd,SAAA;KACD;AAED,IAAA,MAAM,CAAC,GAAoB,EAAE,MAAe,EAAE,EAAsB,EAAA;AACnE,QAAA,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE;YAC5B,MAAM,IAAI,KAAK,CAAC,CAAgB,aAAA,EAAA,GAAG,CAAC,QAAQ,EAAE,CAAE,CAAA,CAAC,CAAC;AAClD,SAAA;AAAM,aAAA,IAAI,GAAG,CAAC,WAAW,EAAE,KAAK,KAAK,EAAE;YACvC,EAAE,GAAG,aAAa,CAAC;AACnB,SAAA;QAED,OAAO,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC,EAAE,EAAE,GAAG,CAAC,GAAG,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;KAC5E;AAED,IAAA,KAAK,CACJ,IAAqB;;AAErB,IAAA,IAA8B,EAC9B,IAAY;;IAEZ,KAAc,EACd,QAAiB,EACjB,KAAyB,EAAA;AAEzB,QAAA,MAAM,KAAK,GAAG,KAAK,KAAK,aAAa,CAAC;AACtC,QAAA,QAAQ,IAAI;YACX,KAAK,OAAO,EAAE;AACb,gBAAA,MAAM,KAAK,GAAwB,IAAI,CAAC,KAAK,CAAC;gBAC9C,IAAI,KAAK,IAAI,IAAI,EAAE;AAClB,oBAAA,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,KAAe,CAAC,CAAC;AAC5C,iBAAA;AAAM,qBAAA,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,KAAK,KAAK,EAAE;AAC5C,oBAAA,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;AAC9B,iBAAA;qBAAM,IAAI,KAAK,KAAK,IAAI,EAAE;AAC1B,oBAAA,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;AAC/B,iBAAA;AAAM,qBAAA,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;AACrC,oBAAA,IAAI,KAAK,CAAC,OAAO,KAAK,KAAK,EAAE;AAC5B,wBAAA,KAAK,CAAC,OAAO,GAAG,KAAK,CAAC;AACtB,qBAAA;AACD,iBAAA;AAAM,qBAAA;AACN,oBAAA,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE;AACjC,wBAAA,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC;AACnB,qBAAA;oBAED,KAAK,MAAM,SAAS,IAAI,EAAC,GAAI,QAAe,EAAE,GAAI,KAAY,EAAC,EAAE;wBAChE,MAAM,UAAU,GAAG,KAAK,IAAK,KAAa,CAAC,SAAS,CAAC,CAAC;wBACtD,IAAI,UAAU,IAAI,IAAI,EAAE;AACvB,4BAAA,KAAK,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;AAChC,yBAAA;6BAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,SAAS,CAAC,KAAK,UAAU,EAAE;AAC5D,4BAAA,KAAK,CAAC,WAAW,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;AACzC,yBAAA;AACD,qBAAA;AACD,iBAAA;gBAED,MAAM;AACN,aAAA;AACD,YAAA,KAAK,OAAO,CAAC;AACb,YAAA,KAAK,WAAW;gBACf,IAAI,KAAK,KAAK,IAAI,EAAE;AACnB,oBAAA,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;AAC/B,iBAAA;qBAAM,IAAI,KAAK,IAAI,IAAI,EAAE;AACzB,oBAAA,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;AAC9B,iBAAA;qBAAM,IAAI,CAAC,KAAK,EAAE;AAClB,oBAAA,IAAI,IAAI,CAAC,SAAS,KAAK,KAAK,EAAE;AAC5B,wBAAA,IAAY,CAAC,WAAW,CAAC,GAAG,KAAK,CAAC;AACnC,qBAAA;AACD,iBAAA;qBAAM,IAAI,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,KAAK,KAAK,EAAE;AAChD,oBAAA,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,KAAe,CAAC,CAAC;AAC5C,iBAAA;gBACD,MAAM;AACP,YAAA,KAAK,WAAW;gBACf,IAAI,KAAK,KAAK,QAAQ,EAAE;AACvB,oBAAA,IAAI,CAAC,SAAS,GAAG,KAAY,CAAC;AAC9B,iBAAA;gBAED,MAAM;AACP,YAAA,SAAS;gBACR,IACC,IAAI,IAAI,IAAI;;;;AAIZ,oBAAA,EACC,OAAO,KAAK,KAAK,QAAQ;AACzB,wBAAA,OAAQ,IAAY,CAAC,IAAI,CAAC,KAAK,SAAS,CACxC,EACA;;;oBAGD,IAAI,GAAG,GAAG,IAAI,CAAC;oBACf,GAAG;AACF,wBAAA,IAAI,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE;4BACpD,MAAM;AACN,yBAAA;qBACD,SAAS,GAAG,GAAG,MAAM,CAAC,cAAc,CAAC,GAAG,CAAC,GAAG;;;oBAI7C,MAAM,UAAU,GAAG,MAAM,CAAC,wBAAwB,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;oBAC9D,IACC,UAAU,IAAI,IAAI;AAClB,yBAAC,UAAU,CAAC,QAAQ,KAAK,IAAI,IAAI,UAAU,CAAC,GAAG,KAAK,SAAS,CAAC,EAC7D;AACA,wBAAA,IAAY,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;wBAC5B,OAAO;AACP,qBAAA;;;AAID,iBAAA;gBAED,IAAI,KAAK,KAAK,IAAI,EAAE;oBACnB,KAAK,GAAG,EAAE,CAAC;AACX,iBAAA;AAAM,qBAAA,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,KAAK,KAAK,EAAE;AAC5C,oBAAA,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;oBAC3B,OAAO;AACP,iBAAA;gBAED,IAAI,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,KAAK,EAAE;AACtC,oBAAA,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,KAAY,CAAC,CAAC;AACtC,iBAAA;AACD,aAAA;AACD,SAAA;KACD;IAED,OAAO,CACN,GAAoB,EACpB,IAAU,EACV,KAA0B,EAC1B,QAAiC,EACjC,SAA0C,EAC1C,WAAgD,EAAA;AAEhD,QAAA,IAAI,GAAG,KAAKA,YAAM,KAAK,IAAI,IAAI,IAAI,IAAI,OAAO,IAAI,CAAC,QAAQ,KAAK,QAAQ,CAAC,EAAE;AAC1E,YAAA,MAAM,IAAI,SAAS,CAClB,CAAwC,qCAAA,EAAA,IAAI,CAAC,SAAS,CACrD,IAAI,IAAI,IAAI,CAAC,QAAQ,EAAE,CACvB,CAAA,CAAE,CACH,CAAC;AACF,SAAA;AAED,QAAA,IACC,EAAE,WAAW,IAAI,KAAK,CAAC;;;;;;;AAOvB,aAAC,UAAU,IAAI,KAAK,KAAK,WAAW,IAAI,WAAW,CAAC,MAAM,CAAC,CAAC,EAC3D;AACD,YAAA,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE;AAC1B,gBAAA,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC;AACtB,aAAA;AAAM,iBAAA;AACN,gBAAA,IAAI,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC;gBAC/B,IAAI,CAAC,GAAG,CAAC,CAAC;gBACV,OAAO,QAAQ,KAAK,IAAI,IAAI,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE;AAChD,oBAAA,MAAM,QAAQ,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;oBAC7B,IAAI,QAAQ,KAAK,QAAQ,EAAE;AAC1B,wBAAA,QAAQ,GAAG,QAAQ,CAAC,WAAW,CAAC;AAChC,wBAAA,CAAC,EAAE,CAAC;AACJ,qBAAA;AAAM,yBAAA,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE;AACxC,wBAAA,IAAI,QAAQ,CAAC,QAAQ,KAAK,IAAI,CAAC,SAAS,EAAE;AACzC,4BAAA,IAAK,QAAiB,CAAC,IAAI,KAAK,QAAQ,EAAE;AACxC,gCAAA,QAAiB,CAAC,IAAI,GAAG,QAAQ,CAAC;AACnC,6BAAA;AAED,4BAAA,QAAQ,GAAG,QAAQ,CAAC,WAAW,CAAC;AAChC,yBAAA;AAAM,6BAAA;AACN,4BAAA,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,CAAC;AAC/D,yBAAA;AAED,wBAAA,CAAC,EAAE,CAAC;AACJ,qBAAA;AAAM,yBAAA,IAAI,QAAQ,CAAC,QAAQ,KAAK,IAAI,CAAC,SAAS,EAAE;AAChD,wBAAA,MAAM,WAAW,GAAG,QAAQ,CAAC,WAAW,CAAC;AACzC,wBAAA,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;wBAC3B,QAAQ,GAAG,WAAW,CAAC;AACvB,qBAAA;AAAM,yBAAA;AACN,wBAAA,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;AACtC,wBAAA,CAAC,EAAE,CAAC;;AAEJ,wBAAA,IAAI,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE;AAC7B,4BAAA,MAAM,WAAW,GAAG,QAAQ,CAAC,WAAW,CAAC;AACzC,4BAAA,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;4BAC3B,QAAQ,GAAG,WAAW,CAAC;AACvB,yBAAA;AACD,qBAAA;AACD,iBAAA;;gBAGD,OAAO,QAAQ,KAAK,IAAI,EAAE;AACzB,oBAAA,MAAM,WAAW,GAAG,QAAQ,CAAC,WAAW,CAAC;AACzC,oBAAA,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;oBAC3B,QAAQ,GAAG,WAAW,CAAC;AACvB,iBAAA;;gBAGD,OAAO,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;AAChC,oBAAA,MAAM,QAAQ,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;AAC7B,oBAAA,IAAI,CAAC,WAAW,CACf,OAAO,QAAQ,KAAK,QAAQ;AAC3B,0BAAE,QAAQ,CAAC,cAAc,CAAC,QAAQ,CAAC;0BACjC,QAAQ,CACX,CAAC;AACF,iBAAA;AACD,aAAA;AACD,SAAA;KACD;EACA;AAEI,MAAO,WAAY,SAAQC,cAAsB,CAAA;AACtD,IAAA,WAAA,GAAA;QACC,KAAK,CAAC,IAAI,CAAC,CAAC;KACZ;AAED,IAAA,MAAM,CACL,QAAkB,EAClB,IAAU,EACV,GAAa,EAAA;QAEb,IAAI,IAAI,IAAI,IAAI,IAAI,OAAO,IAAI,CAAC,QAAQ,KAAK,QAAQ,EAAE;AACtD,YAAA,MAAM,IAAI,SAAS,CAClB,CAAwC,qCAAA,EAAA,IAAI,CAAC,SAAS,CACrD,IAAI,IAAI,IAAI,CAAC,QAAQ,EAAE,CACvB,CAAA,CAAE,CACH,CAAC;AACF,SAAA;QAED,OAAO,KAAK,CAAC,MAAM,CAAC,QAAQ,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;KACzC;AACD,CAAA;AAEY,MAAA,QAAQ,GAAG,IAAI,WAAW;;;;;;"}
1
+ {"version":3,"file":"dom.cjs","sources":["../src/dom.ts"],"sourcesContent":["import {\n\tChildren,\n\tContext,\n\tElementValue,\n\tHydrationData,\n\tPortal,\n\tRenderer,\n\tRendererImpl,\n} from \"./crank.js\";\n\nconst SVG_NAMESPACE = \"http://www.w3.org/2000/svg\";\n\nexport const impl: Partial<RendererImpl<Node, string>> = {\n\tscope(xmlns: string | undefined, tag: string | symbol): string | undefined {\n\t\t// TODO: Should we handle xmlns???\n\t\tswitch (tag) {\n\t\t\tcase Portal:\n\t\t\tcase \"foreignObject\":\n\t\t\t\txmlns = undefined;\n\t\t\t\tbreak;\n\t\t\tcase \"svg\":\n\t\t\t\txmlns = SVG_NAMESPACE;\n\t\t\t\tbreak;\n\t\t}\n\n\t\treturn xmlns;\n\t},\n\n\tcreate(\n\t\ttag: string | symbol,\n\t\t_props: unknown,\n\t\txmlns: string | undefined,\n\t): Node {\n\t\tif (typeof tag !== \"string\") {\n\t\t\tthrow new Error(`Unknown tag: ${tag.toString()}`);\n\t\t} else if (tag.toLowerCase() === \"svg\") {\n\t\t\txmlns = SVG_NAMESPACE;\n\t\t}\n\n\t\treturn xmlns\n\t\t\t? document.createElementNS(xmlns, tag)\n\t\t\t: document.createElement(tag);\n\t},\n\n\thydrate(\n\t\ttag: string | symbol,\n\t\tnode: Element,\n\t\tprops: Record<string, unknown>,\n\t): HydrationData<Element> | undefined {\n\t\tif (typeof tag !== \"string\" && tag !== Portal) {\n\t\t\tthrow new Error(`Unknown tag: ${tag.toString()}`);\n\t\t}\n\n\t\tif (\n\t\t\ttypeof tag === \"string\" &&\n\t\t\ttag.toUpperCase() !== (node as Element).tagName\n\t\t) {\n\t\t\tconsole.error(`Expected <${tag}> while hydrating but found:`, node);\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst children: Array<string | Element> = [];\n\t\tfor (let i = 0; i < node.childNodes.length; i++) {\n\t\t\tconst child = node.childNodes[i];\n\t\t\tif (child.nodeType === Node.TEXT_NODE) {\n\t\t\t\tchildren.push((child as Text).data);\n\t\t\t} else if (child.nodeType === Node.ELEMENT_NODE) {\n\t\t\t\tchildren.push(child as Element);\n\t\t\t}\n\t\t}\n\n\t\t// TODO: extract props from nodes\n\t\treturn {props, children};\n\t},\n\n\tpatch(\n\t\t_tag: string | symbol,\n\t\t// TODO: Why does this assignment work?\n\t\tnode: HTMLElement | SVGElement,\n\t\tname: string,\n\t\t// TODO: Stricter typings?\n\t\tvalue: unknown,\n\t\toldValue: unknown,\n\t\txmlns: string | undefined,\n\t): void {\n\t\tconst isSVG = xmlns === SVG_NAMESPACE;\n\t\tswitch (name) {\n\t\t\tcase \"style\": {\n\t\t\t\tconst style: CSSStyleDeclaration = node.style;\n\t\t\t\tif (style == null) {\n\t\t\t\t\tnode.setAttribute(\"style\", value as string);\n\t\t\t\t} else if (value == null || value === false) {\n\t\t\t\t\tnode.removeAttribute(\"style\");\n\t\t\t\t} else if (value === true) {\n\t\t\t\t\tnode.setAttribute(\"style\", \"\");\n\t\t\t\t} else if (typeof value === \"string\") {\n\t\t\t\t\tif (style.cssText !== value) {\n\t\t\t\t\t\tstyle.cssText = value;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (typeof oldValue === \"string\") {\n\t\t\t\t\t\tstyle.cssText = \"\";\n\t\t\t\t\t}\n\n\t\t\t\t\tfor (const styleName in {...(oldValue as {}), ...(value as {})}) {\n\t\t\t\t\t\tconst styleValue = value && (value as any)[styleName];\n\t\t\t\t\t\tif (styleValue == null) {\n\t\t\t\t\t\t\tstyle.removeProperty(styleName);\n\t\t\t\t\t\t} else if (style.getPropertyValue(styleName) !== styleValue) {\n\t\t\t\t\t\t\tstyle.setProperty(styleName, styleValue);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"class\":\n\t\t\tcase \"className\":\n\t\t\t\tif (value === true) {\n\t\t\t\t\tnode.setAttribute(\"class\", \"\");\n\t\t\t\t} else if (value == null) {\n\t\t\t\t\tnode.removeAttribute(\"class\");\n\t\t\t\t} else if (!isSVG) {\n\t\t\t\t\tif (node.className !== value) {\n\t\t\t\t\t\t(node as any)[\"className\"] = value;\n\t\t\t\t\t}\n\t\t\t\t} else if (node.getAttribute(\"class\") !== value) {\n\t\t\t\t\tnode.setAttribute(\"class\", value as string);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"innerHTML\":\n\t\t\t\tif (value !== oldValue) {\n\t\t\t\t\tnode.innerHTML = value as any;\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\tdefault: {\n\t\t\t\tif (\n\t\t\t\t\tname in node &&\n\t\t\t\t\t// boolean properties will coerce strings, but sometimes they map to\n\t\t\t\t\t// enumerated attributes, where truthy strings (\"false\", \"no\") map to\n\t\t\t\t\t// falsy properties, so we use attributes in this case.\n\t\t\t\t\t!(\n\t\t\t\t\t\ttypeof value === \"string\" &&\n\t\t\t\t\t\ttypeof (node as any)[name] === \"boolean\"\n\t\t\t\t\t)\n\t\t\t\t) {\n\t\t\t\t\t// walk up the object's prototype chain to find the owner of the\n\t\t\t\t\t// named property\n\t\t\t\t\tlet obj = node;\n\t\t\t\t\tdo {\n\t\t\t\t\t\tif (Object.prototype.hasOwnProperty.call(obj, name)) {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t} while ((obj = Object.getPrototypeOf(obj)));\n\n\t\t\t\t\t// get the descriptor for the named property and check whether it\n\t\t\t\t\t// implies that the property is writable\n\t\t\t\t\tconst descriptor = Object.getOwnPropertyDescriptor(obj, name);\n\t\t\t\t\tif (\n\t\t\t\t\t\tdescriptor != null &&\n\t\t\t\t\t\t(descriptor.writable === true || descriptor.set !== undefined)\n\t\t\t\t\t) {\n\t\t\t\t\t\tif ((node as any)[name] !== value) {\n\t\t\t\t\t\t\t(node as any)[name] = value;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\t// if the property wasn't writable, fall through to the code below\n\t\t\t\t\t// which uses setAttribute() instead of assigning directly.\n\t\t\t\t}\n\n\t\t\t\tif (value === true) {\n\t\t\t\t\tvalue = \"\";\n\t\t\t\t} else if (value == null || value === false) {\n\t\t\t\t\tnode.removeAttribute(name);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (node.getAttribute(name) !== value) {\n\t\t\t\t\tnode.setAttribute(name, value as any);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tarrange(\n\t\ttag: string | symbol,\n\t\tnode: Node,\n\t\tprops: Record<string, any>,\n\t\tchildren: Array<Element | string>,\n\t\t_oldProps: Record<string, any> | undefined,\n\t\toldChildren: Array<Element | string> | undefined,\n\t): void {\n\t\tif (tag === Portal && (node == null || typeof node.nodeType !== \"number\")) {\n\t\t\tthrow new TypeError(\n\t\t\t\t`Portal root is not a node. Received: ${JSON.stringify(\n\t\t\t\t\tnode && node.toString(),\n\t\t\t\t)}`,\n\t\t\t);\n\t\t}\n\n\t\tif (\n\t\t\t!(\"innerHTML\" in props) &&\n\t\t\t// We don’t want to update elements without explicit children (<div/>),\n\t\t\t// because these elements sometimes have child nodes added via raw\n\t\t\t// DOM manipulations.\n\t\t\t// However, if an element has previously rendered children, we clear the\n\t\t\t// them because it would be surprising not to clear Crank managed\n\t\t\t// children, even if the new element does not have explicit children.\n\t\t\t(\"children\" in props || (oldChildren && oldChildren.length))\n\t\t) {\n\t\t\tif (children.length === 0) {\n\t\t\t\tnode.textContent = \"\";\n\t\t\t} else {\n\t\t\t\tlet oldChild = node.firstChild;\n\t\t\t\tlet i = 0;\n\t\t\t\twhile (oldChild !== null && i < children.length) {\n\t\t\t\t\tconst newChild = children[i];\n\t\t\t\t\tif (oldChild === newChild) {\n\t\t\t\t\t\toldChild = oldChild.nextSibling;\n\t\t\t\t\t\ti++;\n\t\t\t\t\t} else if (typeof newChild === \"string\") {\n\t\t\t\t\t\tif (oldChild.nodeType === Node.TEXT_NODE) {\n\t\t\t\t\t\t\tif ((oldChild as Text).data !== newChild) {\n\t\t\t\t\t\t\t\t(oldChild as Text).data = newChild;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\toldChild = oldChild.nextSibling;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tnode.insertBefore(document.createTextNode(newChild), oldChild);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\ti++;\n\t\t\t\t\t} else if (oldChild.nodeType === Node.TEXT_NODE) {\n\t\t\t\t\t\tconst nextSibling = oldChild.nextSibling;\n\t\t\t\t\t\tnode.removeChild(oldChild);\n\t\t\t\t\t\toldChild = nextSibling;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnode.insertBefore(newChild, oldChild);\n\t\t\t\t\t\ti++;\n\t\t\t\t\t\t// TODO: This is an optimization but we need to think a little more about other cases like prepending.\n\t\t\t\t\t\tif (oldChild !== children[i]) {\n\t\t\t\t\t\t\tconst nextSibling = oldChild.nextSibling;\n\t\t\t\t\t\t\tnode.removeChild(oldChild);\n\t\t\t\t\t\t\toldChild = nextSibling;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// remove excess DOM nodes\n\t\t\t\twhile (oldChild !== null) {\n\t\t\t\t\tconst nextSibling = oldChild.nextSibling;\n\t\t\t\t\tnode.removeChild(oldChild);\n\t\t\t\t\toldChild = nextSibling;\n\t\t\t\t}\n\n\t\t\t\t// append excess children\n\t\t\t\tfor (; i < children.length; i++) {\n\t\t\t\t\tconst newChild = children[i];\n\t\t\t\t\tnode.appendChild(\n\t\t\t\t\t\ttypeof newChild === \"string\"\n\t\t\t\t\t\t\t? document.createTextNode(newChild)\n\t\t\t\t\t\t\t: newChild,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\ttext(\n\t\ttext: string,\n\t\t_scope: string | undefined,\n\t\thydrationData: HydrationData<Element> | undefined,\n\t): string {\n\t\tif (hydrationData != null) {\n\t\t\tlet value = hydrationData.children.shift();\n\t\t\tif (typeof value !== \"string\" || !value.startsWith(text)) {\n\t\t\t\tconsole.error(`Expected \"${text}\" while hydrating but found:`, value);\n\t\t\t} else if (text.length < value.length) {\n\t\t\t\tvalue = value.slice(text.length);\n\t\t\t\thydrationData.children.unshift(value);\n\t\t\t}\n\t\t}\n\n\t\treturn text;\n\t},\n\n\traw(\n\t\tvalue: string | Node,\n\t\txmlns: string | undefined,\n\t\thydrationData: HydrationData<Element> | undefined,\n\t): ElementValue<Node> {\n\t\tlet result: ElementValue<Node>;\n\t\tif (typeof value === \"string\") {\n\t\t\tconst el =\n\t\t\t\txmlns == null\n\t\t\t\t\t? document.createElement(\"div\")\n\t\t\t\t\t: document.createElementNS(xmlns, \"svg\");\n\t\t\tel.innerHTML = value;\n\t\t\tif (el.childNodes.length === 0) {\n\t\t\t\tresult = undefined;\n\t\t\t} else if (el.childNodes.length === 1) {\n\t\t\t\tresult = el.childNodes[0];\n\t\t\t} else {\n\t\t\t\tresult = Array.from(el.childNodes);\n\t\t\t}\n\t\t} else {\n\t\t\tresult = value;\n\t\t}\n\n\t\tif (hydrationData != null) {\n\t\t\t// TODO: maybe we should warn on incorrect values\n\t\t\tif (Array.isArray(result)) {\n\t\t\t\tfor (let i = 0; i < result.length; i++) {\n\t\t\t\t\tconst node = result[i];\n\t\t\t\t\tif (\n\t\t\t\t\t\ttypeof node !== \"string\" &&\n\t\t\t\t\t\t(node.nodeType === Node.ELEMENT_NODE ||\n\t\t\t\t\t\t\tnode.nodeType === Node.TEXT_NODE)\n\t\t\t\t\t) {\n\t\t\t\t\t\thydrationData.children.shift();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (result != null && typeof result !== \"string\") {\n\t\t\t\tif (\n\t\t\t\t\tresult.nodeType === Node.ELEMENT_NODE ||\n\t\t\t\t\tresult.nodeType === Node.TEXT_NODE\n\t\t\t\t) {\n\t\t\t\t\thydrationData.children.shift();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t},\n};\n\nexport class DOMRenderer extends Renderer<Node, string> {\n\tconstructor() {\n\t\tsuper(impl);\n\t}\n\n\trender(\n\t\tchildren: Children,\n\t\troot: Node,\n\t\tctx?: Context,\n\t): Promise<ElementValue<Node>> | ElementValue<Node> {\n\t\tvalidateRoot(root);\n\t\treturn super.render(children, root, ctx);\n\t}\n\n\thydrate(\n\t\tchildren: Children,\n\t\troot: Node,\n\t\tctx?: Context,\n\t): Promise<ElementValue<Node>> | ElementValue<Node> {\n\t\tvalidateRoot(root);\n\t\treturn super.hydrate(children, root, ctx);\n\t}\n}\n\nfunction validateRoot(root: unknown): asserts root is Node {\n\tif (\n\t\troot === null ||\n\t\t(typeof root === \"object\" && typeof (root as any).nodeType !== \"number\")\n\t) {\n\t\tthrow new TypeError(\n\t\t\t`Render root is not a node. Received: ${JSON.stringify(\n\t\t\t\troot && root.toString(),\n\t\t\t)}`,\n\t\t);\n\t}\n}\n\nexport const renderer = new DOMRenderer();\n\ndeclare global {\n\tmodule Crank {\n\t\tinterface EventMap extends GlobalEventHandlersEventMap {}\n\t}\n}\n"],"names":["Portal","Renderer"],"mappings":"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"}
package/dom.d.ts CHANGED
@@ -3,6 +3,7 @@ export declare const impl: Partial<RendererImpl<Node, string>>;
3
3
  export declare class DOMRenderer extends Renderer<Node, string> {
4
4
  constructor();
5
5
  render(children: Children, root: Node, ctx?: Context): Promise<ElementValue<Node>> | ElementValue<Node>;
6
+ hydrate(children: Children, root: Node, ctx?: Context): Promise<ElementValue<Node>> | ElementValue<Node>;
6
7
  }
7
8
  export declare const renderer: DOMRenderer;
8
9
  declare global {
package/dom.js CHANGED
@@ -3,44 +3,58 @@ import { Portal, Renderer } from './crank.js';
3
3
 
4
4
  const SVG_NAMESPACE = "http://www.w3.org/2000/svg";
5
5
  const impl = {
6
- parse(text) {
7
- if (typeof document.createRange === "function") {
8
- const fragment = document.createRange().createContextualFragment(text);
9
- return Array.from(fragment.childNodes);
10
- }
11
- else {
12
- const childNodes = new DOMParser().parseFromString(text, "text/html").body
13
- .childNodes;
14
- return Array.from(childNodes);
15
- }
16
- },
17
- scope(scope, tag) {
6
+ scope(xmlns, tag) {
18
7
  // TODO: Should we handle xmlns???
19
8
  switch (tag) {
20
9
  case Portal:
21
10
  case "foreignObject":
22
- return undefined;
11
+ xmlns = undefined;
12
+ break;
23
13
  case "svg":
24
- return SVG_NAMESPACE;
25
- default:
26
- return scope;
14
+ xmlns = SVG_NAMESPACE;
15
+ break;
27
16
  }
17
+ return xmlns;
28
18
  },
29
- create(tag, _props, ns) {
19
+ create(tag, _props, xmlns) {
30
20
  if (typeof tag !== "string") {
31
21
  throw new Error(`Unknown tag: ${tag.toString()}`);
32
22
  }
33
23
  else if (tag.toLowerCase() === "svg") {
34
- ns = SVG_NAMESPACE;
24
+ xmlns = SVG_NAMESPACE;
25
+ }
26
+ return xmlns
27
+ ? document.createElementNS(xmlns, tag)
28
+ : document.createElement(tag);
29
+ },
30
+ hydrate(tag, node, props) {
31
+ if (typeof tag !== "string" && tag !== Portal) {
32
+ throw new Error(`Unknown tag: ${tag.toString()}`);
35
33
  }
36
- return ns ? document.createElementNS(ns, tag) : document.createElement(tag);
34
+ if (typeof tag === "string" &&
35
+ tag.toUpperCase() !== node.tagName) {
36
+ console.error(`Expected <${tag}> while hydrating but found:`, node);
37
+ return undefined;
38
+ }
39
+ const children = [];
40
+ for (let i = 0; i < node.childNodes.length; i++) {
41
+ const child = node.childNodes[i];
42
+ if (child.nodeType === Node.TEXT_NODE) {
43
+ children.push(child.data);
44
+ }
45
+ else if (child.nodeType === Node.ELEMENT_NODE) {
46
+ children.push(child);
47
+ }
48
+ }
49
+ // TODO: extract props from nodes
50
+ return { props, children };
37
51
  },
38
52
  patch(_tag,
39
53
  // TODO: Why does this assignment work?
40
54
  node, name,
41
55
  // TODO: Stricter typings?
42
- value, oldValue, scope) {
43
- const isSVG = scope === SVG_NAMESPACE;
56
+ value, oldValue, xmlns) {
57
+ const isSVG = xmlns === SVG_NAMESPACE;
44
58
  switch (name) {
45
59
  case "style": {
46
60
  const style = node.style;
@@ -116,7 +130,9 @@ const impl = {
116
130
  const descriptor = Object.getOwnPropertyDescriptor(obj, name);
117
131
  if (descriptor != null &&
118
132
  (descriptor.writable === true || descriptor.set !== undefined)) {
119
- node[name] = value;
133
+ if (node[name] !== value) {
134
+ node[name] = value;
135
+ }
120
136
  return;
121
137
  }
122
138
  // if the property wasn't writable, fall through to the code below
@@ -203,17 +219,79 @@ const impl = {
203
219
  }
204
220
  }
205
221
  },
222
+ text(text, _scope, hydrationData) {
223
+ if (hydrationData != null) {
224
+ let value = hydrationData.children.shift();
225
+ if (typeof value !== "string" || !value.startsWith(text)) {
226
+ console.error(`Expected "${text}" while hydrating but found:`, value);
227
+ }
228
+ else if (text.length < value.length) {
229
+ value = value.slice(text.length);
230
+ hydrationData.children.unshift(value);
231
+ }
232
+ }
233
+ return text;
234
+ },
235
+ raw(value, xmlns, hydrationData) {
236
+ let result;
237
+ if (typeof value === "string") {
238
+ const el = xmlns == null
239
+ ? document.createElement("div")
240
+ : document.createElementNS(xmlns, "svg");
241
+ el.innerHTML = value;
242
+ if (el.childNodes.length === 0) {
243
+ result = undefined;
244
+ }
245
+ else if (el.childNodes.length === 1) {
246
+ result = el.childNodes[0];
247
+ }
248
+ else {
249
+ result = Array.from(el.childNodes);
250
+ }
251
+ }
252
+ else {
253
+ result = value;
254
+ }
255
+ if (hydrationData != null) {
256
+ // TODO: maybe we should warn on incorrect values
257
+ if (Array.isArray(result)) {
258
+ for (let i = 0; i < result.length; i++) {
259
+ const node = result[i];
260
+ if (typeof node !== "string" &&
261
+ (node.nodeType === Node.ELEMENT_NODE ||
262
+ node.nodeType === Node.TEXT_NODE)) {
263
+ hydrationData.children.shift();
264
+ }
265
+ }
266
+ }
267
+ else if (result != null && typeof result !== "string") {
268
+ if (result.nodeType === Node.ELEMENT_NODE ||
269
+ result.nodeType === Node.TEXT_NODE) {
270
+ hydrationData.children.shift();
271
+ }
272
+ }
273
+ }
274
+ return result;
275
+ },
206
276
  };
207
277
  class DOMRenderer extends Renderer {
208
278
  constructor() {
209
279
  super(impl);
210
280
  }
211
281
  render(children, root, ctx) {
212
- if (root == null || typeof root.nodeType !== "number") {
213
- throw new TypeError(`Render root is not a node. Received: ${JSON.stringify(root && root.toString())}`);
214
- }
282
+ validateRoot(root);
215
283
  return super.render(children, root, ctx);
216
284
  }
285
+ hydrate(children, root, ctx) {
286
+ validateRoot(root);
287
+ return super.hydrate(children, root, ctx);
288
+ }
289
+ }
290
+ function validateRoot(root) {
291
+ if (root === null ||
292
+ (typeof root === "object" && typeof root.nodeType !== "number")) {
293
+ throw new TypeError(`Render root is not a node. Received: ${JSON.stringify(root && root.toString())}`);
294
+ }
217
295
  }
218
296
  const renderer = new DOMRenderer();
219
297