@typed/template 0.2.0 → 0.3.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/dist/cjs/Directive.js +1 -1
- package/dist/cjs/Directive.js.map +1 -1
- package/dist/cjs/ElementRef.js +23 -13
- package/dist/cjs/ElementRef.js.map +1 -1
- package/dist/cjs/ElementSource.js +16 -18
- package/dist/cjs/ElementSource.js.map +1 -1
- package/dist/cjs/EventHandler.js +1 -1
- package/dist/cjs/EventHandler.js.map +1 -1
- package/dist/cjs/Html.js +31 -32
- package/dist/cjs/Html.js.map +1 -1
- package/dist/cjs/HtmlChunk.js +4 -1
- package/dist/cjs/HtmlChunk.js.map +1 -1
- package/dist/cjs/Hydrate.js +1 -1
- package/dist/cjs/Hydrate.js.map +1 -1
- package/dist/cjs/Many.js +14 -13
- package/dist/cjs/Many.js.map +1 -1
- package/dist/cjs/Parser.js +11 -323
- package/dist/cjs/Parser.js.map +1 -1
- package/dist/cjs/Placeholder.js +3 -3
- package/dist/cjs/Placeholder.js.map +1 -1
- package/dist/cjs/Platform.js +4 -4
- package/dist/cjs/Platform.js.map +1 -1
- package/dist/cjs/Render.js +1 -1
- package/dist/cjs/Render.js.map +1 -1
- package/dist/cjs/RenderContext.js +48 -27
- package/dist/cjs/RenderContext.js.map +1 -1
- package/dist/cjs/RenderTemplate.js +2 -17
- package/dist/cjs/RenderTemplate.js.map +1 -1
- package/dist/cjs/Template.js +27 -1
- package/dist/cjs/Template.js.map +1 -1
- package/dist/cjs/TemplateInstance.js +2 -2
- package/dist/cjs/TemplateInstance.js.map +1 -1
- package/dist/cjs/Test.js +20 -7
- package/dist/cjs/Test.js.map +1 -1
- package/dist/cjs/index.js +0 -12
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/internal/EventSource.js +95 -0
- package/dist/cjs/internal/EventSource.js.map +1 -0
- package/dist/cjs/internal/browser.js +11 -11
- package/dist/cjs/internal/browser.js.map +1 -1
- package/dist/cjs/internal/chunks.js +4 -1
- package/dist/cjs/internal/chunks.js.map +1 -1
- package/dist/cjs/internal/errors.js +4 -0
- package/dist/cjs/internal/errors.js.map +1 -1
- package/dist/cjs/internal/hydrate.js +113 -80
- package/dist/cjs/internal/hydrate.js.map +1 -1
- package/dist/cjs/internal/indexRefCounter.js +49 -2
- package/dist/cjs/internal/indexRefCounter.js.map +1 -1
- package/dist/cjs/internal/parser.js +72 -21
- package/dist/cjs/internal/parser.js.map +1 -1
- package/dist/cjs/internal/parts.js +128 -28
- package/dist/cjs/internal/parts.js.map +1 -1
- package/dist/cjs/internal/render.js +460 -161
- package/dist/cjs/internal/render.js.map +1 -1
- package/dist/cjs/internal/server.js +5 -2
- package/dist/cjs/internal/server.js.map +1 -1
- package/dist/dts/Directive.d.ts.map +1 -1
- package/dist/dts/ElementRef.d.ts +4 -2
- package/dist/dts/ElementRef.d.ts.map +1 -1
- package/dist/dts/ElementSource.d.ts +10 -5
- package/dist/dts/ElementSource.d.ts.map +1 -1
- package/dist/dts/EventHandler.d.ts.map +1 -1
- package/dist/dts/Html.d.ts +1 -1
- package/dist/dts/Html.d.ts.map +1 -1
- package/dist/dts/HtmlChunk.d.ts.map +1 -1
- package/dist/dts/Many.d.ts +13 -11
- package/dist/dts/Many.d.ts.map +1 -1
- package/dist/dts/Parser.d.ts +3 -6
- package/dist/dts/Parser.d.ts.map +1 -1
- package/dist/dts/Part.d.ts +13 -3
- package/dist/dts/Part.d.ts.map +1 -1
- package/dist/dts/Placeholder.d.ts +2 -2
- package/dist/dts/Placeholder.d.ts.map +1 -1
- package/dist/dts/Render.d.ts +2 -1
- package/dist/dts/Render.d.ts.map +1 -1
- package/dist/dts/RenderContext.d.ts +5 -4
- package/dist/dts/RenderContext.d.ts.map +1 -1
- package/dist/dts/RenderTemplate.d.ts +2 -16
- package/dist/dts/RenderTemplate.d.ts.map +1 -1
- package/dist/dts/Renderable.d.ts +2 -2
- package/dist/dts/Renderable.d.ts.map +1 -1
- package/dist/dts/Template.d.ts +21 -3
- package/dist/dts/Template.d.ts.map +1 -1
- package/dist/dts/TemplateInstance.d.ts +3 -2
- package/dist/dts/TemplateInstance.d.ts.map +1 -1
- package/dist/dts/Test.d.ts +4 -6
- package/dist/dts/Test.d.ts.map +1 -1
- package/dist/dts/index.d.ts +0 -4
- package/dist/dts/index.d.ts.map +1 -1
- package/dist/dts/internal/EventSource.d.ts +12 -0
- package/dist/dts/internal/EventSource.d.ts.map +1 -0
- package/dist/dts/internal/browser.d.ts.map +1 -1
- package/dist/dts/internal/chunks.d.ts +1 -0
- package/dist/dts/internal/chunks.d.ts.map +1 -1
- package/dist/dts/internal/errors.d.ts +1 -0
- package/dist/dts/internal/errors.d.ts.map +1 -1
- package/dist/dts/internal/hydrate.d.ts +9 -16
- package/dist/dts/internal/hydrate.d.ts.map +1 -1
- package/dist/dts/internal/indexRefCounter.d.ts +5 -0
- package/dist/dts/internal/indexRefCounter.d.ts.map +1 -1
- package/dist/dts/internal/module-augmentation.d.ts +0 -4
- package/dist/dts/internal/module-augmentation.d.ts.map +1 -1
- package/dist/dts/internal/parser.d.ts +8 -0
- package/dist/dts/internal/parser.d.ts.map +1 -1
- package/dist/dts/internal/parts.d.ts +66 -56
- package/dist/dts/internal/parts.d.ts.map +1 -1
- package/dist/dts/internal/render.d.ts +1 -15
- package/dist/dts/internal/render.d.ts.map +1 -1
- package/dist/dts/internal/server.d.ts.map +1 -1
- package/dist/esm/Directive.js +1 -1
- package/dist/esm/Directive.js.map +1 -1
- package/dist/esm/ElementRef.js +12 -7
- package/dist/esm/ElementRef.js.map +1 -1
- package/dist/esm/ElementSource.js +16 -13
- package/dist/esm/ElementSource.js.map +1 -1
- package/dist/esm/EventHandler.js +1 -1
- package/dist/esm/EventHandler.js.map +1 -1
- package/dist/esm/Html.js +29 -24
- package/dist/esm/Html.js.map +1 -1
- package/dist/esm/HtmlChunk.js +6 -1
- package/dist/esm/HtmlChunk.js.map +1 -1
- package/dist/esm/Hydrate.js +1 -1
- package/dist/esm/Hydrate.js.map +1 -1
- package/dist/esm/Many.js +14 -10
- package/dist/esm/Many.js.map +1 -1
- package/dist/esm/Parser.js +6 -335
- package/dist/esm/Parser.js.map +1 -1
- package/dist/esm/Placeholder.js +2 -2
- package/dist/esm/Placeholder.js.map +1 -1
- package/dist/esm/Platform.js +2 -2
- package/dist/esm/Platform.js.map +1 -1
- package/dist/esm/Render.js +1 -1
- package/dist/esm/Render.js.map +1 -1
- package/dist/esm/RenderContext.js +38 -17
- package/dist/esm/RenderContext.js.map +1 -1
- package/dist/esm/RenderTemplate.js +2 -12
- package/dist/esm/RenderTemplate.js.map +1 -1
- package/dist/esm/Template.js +24 -0
- package/dist/esm/Template.js.map +1 -1
- package/dist/esm/TemplateInstance.js +2 -2
- package/dist/esm/TemplateInstance.js.map +1 -1
- package/dist/esm/Test.js +20 -7
- package/dist/esm/Test.js.map +1 -1
- package/dist/esm/index.js +0 -4
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/internal/EventSource.js +91 -0
- package/dist/esm/internal/EventSource.js.map +1 -0
- package/dist/esm/internal/browser.js +12 -12
- package/dist/esm/internal/browser.js.map +1 -1
- package/dist/esm/internal/chunks.js +2 -0
- package/dist/esm/internal/chunks.js.map +1 -1
- package/dist/esm/internal/errors.js +3 -0
- package/dist/esm/internal/errors.js.map +1 -1
- package/dist/esm/internal/hydrate.js +113 -76
- package/dist/esm/internal/hydrate.js.map +1 -1
- package/dist/esm/internal/indexRefCounter.js +50 -2
- package/dist/esm/internal/indexRefCounter.js.map +1 -1
- package/dist/esm/internal/parser.js +98 -22
- package/dist/esm/internal/parser.js.map +1 -1
- package/dist/esm/internal/parts.js +110 -27
- package/dist/esm/internal/parts.js.map +1 -1
- package/dist/esm/internal/render.js +446 -157
- package/dist/esm/internal/render.js.map +1 -1
- package/dist/esm/internal/server.js +5 -4
- package/dist/esm/internal/server.js.map +1 -1
- package/package.json +10 -26
- package/src/Directive.ts +1 -1
- package/src/ElementRef.ts +18 -14
- package/src/ElementSource.ts +62 -47
- package/src/EventHandler.ts +1 -1
- package/src/Html.ts +58 -57
- package/src/HtmlChunk.ts +15 -1
- package/src/Hydrate.ts +1 -1
- package/src/Many.ts +53 -43
- package/src/Parser.ts +10 -453
- package/src/Part.ts +15 -3
- package/src/Placeholder.ts +4 -4
- package/src/Platform.ts +2 -2
- package/src/Render.ts +7 -2
- package/src/RenderContext.ts +47 -19
- package/src/RenderTemplate.ts +9 -54
- package/src/Renderable.ts +2 -1
- package/src/Template.ts +26 -0
- package/src/TemplateInstance.ts +9 -9
- package/src/Test.ts +40 -21
- package/src/index.ts +0 -4
- package/src/internal/EventSource.ts +153 -0
- package/src/internal/browser.ts +26 -25
- package/src/internal/chunks.ts +4 -0
- package/src/internal/errors.ts +4 -0
- package/src/internal/hydrate.ts +161 -107
- package/src/internal/indexRefCounter.ts +63 -2
- package/src/internal/module-augmentation.ts +0 -4
- package/src/internal/parser.ts +107 -25
- package/src/internal/parts.ts +158 -73
- package/src/internal/render.ts +638 -289
- package/src/internal/server.ts +5 -3
- package/Token/package.json +0 -6
- package/Tokenizer/package.json +0 -6
- package/dist/cjs/Token.js +0 -270
- package/dist/cjs/Token.js.map +0 -1
- package/dist/cjs/Tokenizer.js +0 -18
- package/dist/cjs/Tokenizer.js.map +0 -1
- package/dist/cjs/internal/readAttribute.js +0 -34
- package/dist/cjs/internal/readAttribute.js.map +0 -1
- package/dist/cjs/internal/tokenizer.js +0 -264
- package/dist/cjs/internal/tokenizer.js.map +0 -1
- package/dist/dts/Token.d.ts +0 -202
- package/dist/dts/Token.d.ts.map +0 -1
- package/dist/dts/Tokenizer.d.ts +0 -6
- package/dist/dts/Tokenizer.d.ts.map +0 -1
- package/dist/dts/internal/readAttribute.d.ts +0 -9
- package/dist/dts/internal/readAttribute.d.ts.map +0 -1
- package/dist/dts/internal/tokenizer.d.ts +0 -3
- package/dist/dts/internal/tokenizer.d.ts.map +0 -1
- package/dist/esm/Token.js +0 -264
- package/dist/esm/Token.js.map +0 -1
- package/dist/esm/Tokenizer.js +0 -9
- package/dist/esm/Tokenizer.js.map +0 -1
- package/dist/esm/internal/readAttribute.js +0 -24
- package/dist/esm/internal/readAttribute.js.map +0 -1
- package/dist/esm/internal/tokenizer.js +0 -296
- package/dist/esm/internal/tokenizer.js.map +0 -1
- package/src/Token.ts +0 -269
- package/src/Tokenizer.ts +0 -10
- package/src/internal/readAttribute.ts +0 -28
- package/src/internal/tokenizer.ts +0 -338
|
@@ -1,92 +1,405 @@
|
|
|
1
1
|
import * as Fx from "@typed/fx/Fx";
|
|
2
|
-
import * as Subject from "@typed/fx/Subject";
|
|
3
2
|
import { TypeId } from "@typed/fx/TypeId";
|
|
4
3
|
import { persistent } from "@typed/wire";
|
|
5
4
|
import { Effect } from "effect";
|
|
6
|
-
import
|
|
5
|
+
import * as Context from "effect/Context";
|
|
6
|
+
import { Scope } from "effect/Scope";
|
|
7
7
|
import { isDirective } from "../Directive.js";
|
|
8
8
|
import * as ElementRef from "../ElementRef.js";
|
|
9
|
+
import * as ElementSource from "../ElementSource.js";
|
|
9
10
|
import * as EventHandler from "../EventHandler.js";
|
|
10
11
|
import { DomRenderEvent } from "../RenderEvent.js";
|
|
11
|
-
import { TemplateInstance } from "../TemplateInstance.js";
|
|
12
12
|
import { makeRenderNodePart } from "./browser.js";
|
|
13
|
+
import { makeEventSource } from "./EventSource.js";
|
|
13
14
|
import { HydrateContext } from "./HydrateContext.js";
|
|
14
|
-
import {
|
|
15
|
+
import { indexRefCounter2 } from "./indexRefCounter.js";
|
|
15
16
|
import { parse } from "./parser.js";
|
|
16
|
-
import { AttributePartImpl, BooleanPartImpl, ClassNamePartImpl, CommentPartImpl, DataPartImpl,
|
|
17
|
-
import { findPath } from "./utils.js";
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
17
|
+
import { AttributePartImpl, BooleanPartImpl, ClassNamePartImpl, CommentPartImpl, DataPartImpl, PropertyPartImpl, RefPartImpl, TextPartImpl } from "./parts.js";
|
|
18
|
+
import { findHoleComment, findPath } from "./utils.js";
|
|
19
|
+
const RenderPartMap = {
|
|
20
|
+
"attr": (templatePart, node, ctx) => {
|
|
21
|
+
const { document, refCounter, renderContext, values } = ctx;
|
|
22
|
+
const element = node;
|
|
23
|
+
const attr = createAttribute(document, element, templatePart.name);
|
|
24
|
+
const renderable = values[templatePart.index];
|
|
25
|
+
let isSet = true;
|
|
26
|
+
const setValue = (value) => {
|
|
27
|
+
if (isNullOrUndefined(value)) {
|
|
28
|
+
element.removeAttribute(templatePart.name);
|
|
29
|
+
isSet = false;
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
attr.value = String(value);
|
|
33
|
+
if (isSet === false) {
|
|
34
|
+
element.setAttributeNode(attr);
|
|
35
|
+
isSet = true;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
return matchSettablePart(renderable, setValue, () => AttributePartImpl.browser(templatePart.index, element, templatePart.name, renderContext), (f) => Effect.zipRight(renderContext.queue.add(element, f), refCounter.release(templatePart.index)), () => ctx.expected++);
|
|
40
|
+
},
|
|
41
|
+
"boolean-part": (templatePart, node, ctx) => {
|
|
42
|
+
const { refCounter, renderContext, values } = ctx;
|
|
43
|
+
const element = node;
|
|
44
|
+
const renderable = values[templatePart.index];
|
|
45
|
+
const setValue = (value) => {
|
|
46
|
+
element.toggleAttribute(templatePart.name, isNullOrUndefined(value) ? false : Boolean(value));
|
|
47
|
+
};
|
|
48
|
+
return matchSettablePart(renderable, setValue, () => BooleanPartImpl.browser(templatePart.index, element, templatePart.name, renderContext), (f) => Effect.zipRight(renderContext.queue.add(element, f), refCounter.release(templatePart.index)), () => ctx.expected++);
|
|
49
|
+
},
|
|
50
|
+
"className-part": (templatePart, node, ctx) => {
|
|
51
|
+
const { refCounter, renderContext, values } = ctx;
|
|
52
|
+
const element = node;
|
|
53
|
+
const renderable = values[templatePart.index];
|
|
54
|
+
let classNames = new Set();
|
|
55
|
+
const setValue = (value) => {
|
|
56
|
+
if (isNullOrUndefined(value)) {
|
|
57
|
+
element.classList.remove(...classNames);
|
|
58
|
+
classNames.clear();
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
const newClassNames = new Set(Array.isArray(value) ? value : [String(value)]);
|
|
62
|
+
const { added, removed } = diffClassNames(classNames, newClassNames);
|
|
63
|
+
if (removed.length > 0) {
|
|
64
|
+
element.classList.remove(...removed);
|
|
65
|
+
}
|
|
66
|
+
if (added.length > 0)
|
|
67
|
+
element.classList.add(...added);
|
|
68
|
+
classNames = newClassNames;
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
return matchSettablePart(renderable, setValue, () => ClassNamePartImpl.browser(templatePart.index, element, renderContext), (f) => Effect.zipRight(renderContext.queue.add(element, f), refCounter.release(templatePart.index)), () => ctx.expected++);
|
|
72
|
+
},
|
|
73
|
+
"comment-part": (templatePart, node, ctx) => {
|
|
74
|
+
const { refCounter, renderContext, values } = ctx;
|
|
75
|
+
const comment = findHoleComment(node, templatePart.index);
|
|
76
|
+
const renderable = values[templatePart.index];
|
|
77
|
+
const setValue = (value) => {
|
|
78
|
+
comment.textContent = isNullOrUndefined(value) ? "" : String(value);
|
|
79
|
+
};
|
|
80
|
+
return matchSettablePart(renderable, setValue, () => CommentPartImpl.browser(templatePart.index, comment, renderContext), (f) => Effect.zipRight(renderContext.queue.add(comment, f), refCounter.release(templatePart.index)), () => ctx.expected++);
|
|
81
|
+
},
|
|
82
|
+
"data": (templatePart, node, ctx) => {
|
|
83
|
+
const element = node;
|
|
84
|
+
const renderable = ctx.values[templatePart.index];
|
|
85
|
+
const previousKeys = new Set(Object.keys(element.dataset));
|
|
86
|
+
const setValue = (value) => {
|
|
87
|
+
if (isNullOrUndefined(value)) {
|
|
88
|
+
for (const key of previousKeys) {
|
|
89
|
+
delete element.dataset[key];
|
|
90
|
+
}
|
|
91
|
+
previousKeys.clear();
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
for (const key of previousKeys) {
|
|
95
|
+
if (!(key in value)) {
|
|
96
|
+
delete element.dataset[key];
|
|
97
|
+
previousKeys.delete(key);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
for (const key of Object.keys(value)) {
|
|
101
|
+
if (!previousKeys.has(key)) {
|
|
102
|
+
previousKeys.add(key);
|
|
103
|
+
}
|
|
104
|
+
element.dataset[key] = value[key] || "";
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
return matchSettablePart(renderable, setValue, () => DataPartImpl.browser(templatePart.index, element, ctx.renderContext), (f) => Effect.zipRight(ctx.renderContext.queue.add(element, f), ctx.refCounter.release(templatePart.index)), () => ctx.expected++);
|
|
109
|
+
},
|
|
110
|
+
"event": (templatePart, node, ctx) => {
|
|
111
|
+
const element = node;
|
|
112
|
+
const renderable = ctx.values[templatePart.index];
|
|
113
|
+
const handler = getEventHandler(renderable, ctx.context, ctx.onCause);
|
|
114
|
+
if (handler) {
|
|
115
|
+
ctx.eventSource.addEventListener(element, templatePart.name, handler);
|
|
116
|
+
}
|
|
117
|
+
return null;
|
|
118
|
+
},
|
|
119
|
+
"node": (templatePart, node, ctx) => {
|
|
120
|
+
const makeHydrateContext = ctx.makeHydrateContext;
|
|
121
|
+
const part = makeRenderNodePart(templatePart.index, node, ctx.renderContext, ctx.document, !!makeHydrateContext);
|
|
122
|
+
ctx.expected++;
|
|
123
|
+
const handle = handlePart(ctx.values[templatePart.index], (value) => Effect.zipRight(part.update(value), ctx.refCounter.release(templatePart.index)));
|
|
124
|
+
if (makeHydrateContext) {
|
|
125
|
+
return Effect.provideService(handle, HydrateContext, makeHydrateContext(templatePart.index));
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
return handle;
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
"property": (templatePart, node, ctx) => {
|
|
132
|
+
const element = node;
|
|
133
|
+
const renderable = ctx.values[templatePart.index];
|
|
134
|
+
const setValue = (value) => {
|
|
135
|
+
if (isNullOrUndefined(value)) {
|
|
136
|
+
delete element[templatePart.name];
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
;
|
|
140
|
+
element[templatePart.name] = value;
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
return matchSettablePart(renderable, setValue, () => PropertyPartImpl.browser(templatePart.index, element, templatePart.name, ctx.renderContext), (f) => Effect.zipRight(ctx.renderContext.queue.add(element, f), ctx.refCounter.release(templatePart.index)), () => ctx.expected++);
|
|
144
|
+
},
|
|
145
|
+
"properties": (templatePart, node, ctx) => {
|
|
146
|
+
const renderable = ctx.values[templatePart.index];
|
|
147
|
+
if (isNullOrUndefined(renderable))
|
|
148
|
+
return null;
|
|
149
|
+
else if (Fx.isFx(renderable) || Effect.isEffect(renderable)) {
|
|
150
|
+
throw new Error(`Properties Part must utilize an Record of renderable values.`);
|
|
151
|
+
}
|
|
152
|
+
else if (typeof renderable === "object" && !Array.isArray(renderable)) {
|
|
153
|
+
const element = node;
|
|
154
|
+
const toggleBoolean = (key, value) => {
|
|
155
|
+
element.toggleAttribute(key, isNullOrUndefined(value) ? false : Boolean(value));
|
|
156
|
+
};
|
|
157
|
+
const setAttribute = (key, value) => {
|
|
158
|
+
if (isNullOrUndefined(value)) {
|
|
159
|
+
element.removeAttribute(key);
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
element.setAttribute(key, String(value));
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
const setProperty = (key, value) => {
|
|
166
|
+
if (isNullOrUndefined(value)) {
|
|
167
|
+
delete element[key];
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
;
|
|
171
|
+
element[key] = value;
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
const effects = [];
|
|
175
|
+
// We need indexes to track async values that won't conflict
|
|
176
|
+
// with any other Parts, we can start end of the current values.length
|
|
177
|
+
// As there should only ever be exactly 1 properties part.
|
|
178
|
+
let i = ctx.values.length;
|
|
179
|
+
loop: for (const [key, value] of Object.entries(renderable)) {
|
|
180
|
+
const index = ++i;
|
|
181
|
+
switch (key[0]) {
|
|
182
|
+
case "?": {
|
|
183
|
+
const name = key.slice(1);
|
|
184
|
+
const eff = matchSettablePart(value, (value) => toggleBoolean(name, value), () => BooleanPartImpl.browser(index, element, name, ctx.renderContext), (f) => Effect.zipRight(ctx.renderContext.queue.add(element, f), ctx.refCounter.release(index)), () => ctx.expected++);
|
|
185
|
+
if (eff !== null) {
|
|
186
|
+
effects.push(eff);
|
|
187
|
+
}
|
|
188
|
+
continue loop;
|
|
189
|
+
}
|
|
190
|
+
case ".": {
|
|
191
|
+
const name = key.slice(1);
|
|
192
|
+
const eff = matchSettablePart(value, (value) => setProperty(name, value), () => PropertyPartImpl.browser(index, element, name, ctx.renderContext), (f) => Effect.zipRight(ctx.renderContext.queue.add(element, f), ctx.refCounter.release(index)), () => ctx.expected++);
|
|
193
|
+
if (eff !== null) {
|
|
194
|
+
effects.push(eff);
|
|
195
|
+
}
|
|
196
|
+
continue loop;
|
|
197
|
+
}
|
|
198
|
+
case "@": {
|
|
199
|
+
const name = key.slice(1);
|
|
200
|
+
const handler = getEventHandler(value, ctx.context, ctx.onCause);
|
|
201
|
+
if (handler) {
|
|
202
|
+
ctx.eventSource.addEventListener(element, name, handler);
|
|
203
|
+
}
|
|
204
|
+
continue loop;
|
|
205
|
+
}
|
|
206
|
+
case "o": {
|
|
207
|
+
if (key[1] === "n") {
|
|
208
|
+
const name = key.slice(2);
|
|
209
|
+
const handler = getEventHandler(value, ctx.context, ctx.onCause);
|
|
210
|
+
if (handler) {
|
|
211
|
+
ctx.eventSource.addEventListener(element, name, handler);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
continue loop;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
const eff = matchSettablePart(value, (value) => setAttribute(key, value), () => AttributePartImpl.browser(index, element, key, ctx.renderContext), (f) => Effect.zipRight(ctx.renderContext.queue.add(element, f), ctx.refCounter.release(index)), () => ctx.expected++);
|
|
218
|
+
if (eff !== null) {
|
|
219
|
+
effects.push(eff);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
return effects;
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
return null;
|
|
226
|
+
}
|
|
227
|
+
},
|
|
228
|
+
"ref": (templatePart, node, ctx) => {
|
|
229
|
+
const element = node;
|
|
230
|
+
const renderable = ctx.values[templatePart.index];
|
|
231
|
+
if (isDirective(renderable)) {
|
|
232
|
+
return renderable(new RefPartImpl(ElementSource.fromElement(element), templatePart.index));
|
|
233
|
+
}
|
|
234
|
+
else if (ElementRef.isElementRef(renderable)) {
|
|
235
|
+
return ElementRef.set(renderable, element);
|
|
236
|
+
}
|
|
237
|
+
return null;
|
|
238
|
+
},
|
|
239
|
+
"sparse-attr": (templatePart, node, ctx) => {
|
|
240
|
+
const values = Array.from({ length: templatePart.nodes.length }, () => "");
|
|
241
|
+
const element = node;
|
|
242
|
+
const attr = createAttribute(ctx.document, element, templatePart.name);
|
|
243
|
+
const setValue = (value, index) => Effect.suspend(() => {
|
|
244
|
+
values[index] = value || "";
|
|
245
|
+
return ctx.renderContext.queue.add(element, () => attr.value = values.join(""));
|
|
246
|
+
});
|
|
247
|
+
const effects = [];
|
|
248
|
+
for (let i = 0; i < templatePart.nodes.length; ++i) {
|
|
249
|
+
const node = templatePart.nodes[i];
|
|
250
|
+
if (node._tag === "text") {
|
|
251
|
+
values[i] = node.value;
|
|
252
|
+
}
|
|
253
|
+
else {
|
|
254
|
+
const renderable = ctx.values[node.index];
|
|
255
|
+
const index = i;
|
|
256
|
+
const effect = matchSettablePart(renderable, (value) => setValue(value, index), () => new AttributePartImpl(templatePart.name, node.index, ({ value }) => setValue(value, index), null), (f) => Effect.zipRight(ctx.renderContext.queue.add(element, f), ctx.refCounter.release(node.index)), () => ctx.expected++);
|
|
257
|
+
if (effect !== null) {
|
|
258
|
+
effects.push(effect);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
return effects;
|
|
263
|
+
},
|
|
264
|
+
"sparse-class-name": (templatePart, node, ctx) => {
|
|
265
|
+
const element = node;
|
|
266
|
+
const effects = templatePart.nodes.flatMap((node) => {
|
|
267
|
+
if (node._tag === "text") {
|
|
268
|
+
const split = splitClassNames(node.value);
|
|
269
|
+
if (split.length > 0)
|
|
270
|
+
element.classList.add(...split);
|
|
271
|
+
return [];
|
|
272
|
+
}
|
|
273
|
+
else {
|
|
274
|
+
const eff = RenderPartMap[node._tag](node, element, ctx);
|
|
275
|
+
if (eff === null)
|
|
276
|
+
return [];
|
|
277
|
+
return Array.isArray(eff) ? eff : [eff];
|
|
278
|
+
}
|
|
279
|
+
});
|
|
280
|
+
return effects;
|
|
281
|
+
},
|
|
282
|
+
"sparse-comment": (templatePart, node, ctx) => {
|
|
283
|
+
const values = Array.from({ length: templatePart.nodes.length }, () => "");
|
|
284
|
+
const comment = node;
|
|
285
|
+
const setValue = (value, index) => Effect.suspend(() => {
|
|
286
|
+
values[index] = value || "";
|
|
287
|
+
return ctx.renderContext.queue.add(comment, () => comment.textContent = values.join(""));
|
|
288
|
+
});
|
|
289
|
+
const effects = [];
|
|
290
|
+
for (let i = 0; i < templatePart.nodes.length; ++i) {
|
|
291
|
+
const node = templatePart.nodes[i];
|
|
292
|
+
if (node._tag === "text") {
|
|
293
|
+
values[i] = node.value;
|
|
294
|
+
}
|
|
295
|
+
else {
|
|
296
|
+
const renderable = ctx.values[node.index];
|
|
297
|
+
const index = i;
|
|
298
|
+
const effect = matchSettablePart(renderable, (value) => setValue(value, index), () => new CommentPartImpl(node.index, ({ value }) => setValue(value, index), null), (f) => Effect.zipRight(ctx.renderContext.queue.add(comment, f), ctx.refCounter.release(node.index)), () => ctx.expected++);
|
|
299
|
+
if (effect !== null) {
|
|
300
|
+
effects.push(effect);
|
|
301
|
+
}
|
|
49
302
|
}
|
|
50
|
-
default:
|
|
51
|
-
return renderPart(values, part, refCounter, onCause, makeHydrateContext ? () => makeHydrateContext(index) : undefined);
|
|
52
303
|
}
|
|
53
|
-
|
|
304
|
+
return effects;
|
|
305
|
+
},
|
|
306
|
+
"text-part": (templatePart, node, ctx) => {
|
|
307
|
+
const part = TextPartImpl.browser(ctx.document, templatePart.index, node, ctx.renderContext);
|
|
308
|
+
ctx.expected++;
|
|
309
|
+
return handlePart(ctx.values[templatePart.index], (value) => Effect.zipRight(part.update(value), ctx.refCounter.release(templatePart.index)));
|
|
310
|
+
}
|
|
311
|
+
};
|
|
312
|
+
const SPACE_REGEXP = /\s+/g;
|
|
313
|
+
function splitClassNames(value) {
|
|
314
|
+
return value.split(SPACE_REGEXP).flatMap((a) => {
|
|
315
|
+
const trimmed = a.trim();
|
|
316
|
+
return trimmed.length > 0 ? [trimmed] : [];
|
|
317
|
+
});
|
|
54
318
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
return Effect.forkScoped(Fx.observe(unwrapSparsePartRenderables(part.parts.map((p) => p._tag === "static/text" ? Fx.succeed(p.value) : values[p.index]), part), (value) => Effect.tap(part.update(value), () => Effect.forEach(indexes, (a) => refCounter.release(a)))));
|
|
319
|
+
function isNullOrUndefined(value) {
|
|
320
|
+
return value === null || value === undefined;
|
|
58
321
|
}
|
|
59
|
-
|
|
60
|
-
const
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
return refCounter.release(partIndex);
|
|
67
|
-
}
|
|
68
|
-
else if (part._tag === "event") {
|
|
69
|
-
return Effect.tap(part.update(getEventHandler(values[partIndex], onCause)), () => refCounter.release(partIndex));
|
|
70
|
-
}
|
|
71
|
-
else if (part._tag === "node" && hydrateCtx) {
|
|
72
|
-
if (renderable === null || renderable === undefined)
|
|
73
|
-
return refCounter.release(partIndex);
|
|
74
|
-
return handlePart(values[partIndex], (value) => Effect.tap(part.update(value), () => refCounter.release(partIndex))).pipe(HydrateContext.provide(hydrateCtx()), Effect.forkScoped);
|
|
322
|
+
function diffClassNames(oldClassNames, newClassNames) {
|
|
323
|
+
const added = [];
|
|
324
|
+
const removed = [];
|
|
325
|
+
for (const className of oldClassNames) {
|
|
326
|
+
if (!newClassNames.has(className)) {
|
|
327
|
+
removed.push(className);
|
|
328
|
+
}
|
|
75
329
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
return handlePart(values[partIndex], (value) => Effect.tap(part.update(value), () => refCounter.release(partIndex)));
|
|
330
|
+
for (const className of newClassNames) {
|
|
331
|
+
if (!oldClassNames.has(className) && className.trim()) {
|
|
332
|
+
added.push(className);
|
|
333
|
+
}
|
|
81
334
|
}
|
|
335
|
+
return { added, removed };
|
|
82
336
|
}
|
|
83
|
-
|
|
337
|
+
/**
|
|
338
|
+
* @internal
|
|
339
|
+
*/
|
|
340
|
+
export function renderPart2(part, content, path, ctx) {
|
|
341
|
+
return RenderPartMap[part._tag](part, findPath(content, path), ctx);
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Here for "standard" browser rendering, a TemplateInstance is effectively a live
|
|
345
|
+
* view into the contents rendered by the Template.
|
|
346
|
+
*/
|
|
347
|
+
export const renderTemplate = (document, renderContext) => (templateStrings, values) => {
|
|
348
|
+
const entry = getBrowserEntry(document, renderContext, templateStrings);
|
|
349
|
+
if (values.length === 0) {
|
|
350
|
+
return Fx.sync(() => DomRenderEvent(persistent(document.importNode(entry.content, true))));
|
|
351
|
+
}
|
|
352
|
+
return Fx.make((sink) => {
|
|
353
|
+
return Effect.gen(function* (_) {
|
|
354
|
+
const content = document.importNode(entry.content, true);
|
|
355
|
+
const context = yield* _(Effect.context());
|
|
356
|
+
const refCounter = yield* _(indexRefCounter2());
|
|
357
|
+
const ctx = {
|
|
358
|
+
context,
|
|
359
|
+
document,
|
|
360
|
+
eventSource: makeEventSource(),
|
|
361
|
+
expected: 0,
|
|
362
|
+
refCounter,
|
|
363
|
+
renderContext,
|
|
364
|
+
onCause: sink.onFailure,
|
|
365
|
+
values
|
|
366
|
+
};
|
|
367
|
+
// Connect our interpolated values to our template parts
|
|
368
|
+
const effects = [];
|
|
369
|
+
for (const [part, path] of entry.template.parts) {
|
|
370
|
+
const eff = renderPart2(part, content, path, ctx);
|
|
371
|
+
if (eff !== null) {
|
|
372
|
+
effects.push(...(Array.isArray(eff) ? eff : [eff]));
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
// Fork any effects necessary
|
|
376
|
+
if (effects.length > 0) {
|
|
377
|
+
yield* _(Effect.forkAll(effects));
|
|
378
|
+
}
|
|
379
|
+
// If there's anything to wait on and it's not already done, wait for an initial value
|
|
380
|
+
// for all asynchronous sources.
|
|
381
|
+
if (ctx.expected > 0 && (yield* _(refCounter.expect(ctx.expected)))) {
|
|
382
|
+
yield* _(refCounter.wait);
|
|
383
|
+
}
|
|
384
|
+
// Create a persistent wire from our content
|
|
385
|
+
const wire = persistent(content);
|
|
386
|
+
// Set the element when it is ready
|
|
387
|
+
yield* _(ctx.eventSource.setup(wire, Context.get(context, Scope)));
|
|
388
|
+
// Emit our DomRenderEvent
|
|
389
|
+
yield* _(sink.onSuccess(DomRenderEvent(wire)));
|
|
390
|
+
// Ensure our templates last forever in the DOM environment
|
|
391
|
+
// so event listeners are kept attached to the current Scope.
|
|
392
|
+
yield* _(Effect.never);
|
|
393
|
+
});
|
|
394
|
+
});
|
|
395
|
+
};
|
|
396
|
+
function getEventHandler(renderable, ctx, onCause) {
|
|
84
397
|
if (renderable && typeof renderable === "object") {
|
|
85
398
|
if (EventHandler.EventHandlerTypeId in renderable) {
|
|
86
|
-
return EventHandler.make((ev) => Effect.catchAllCause(renderable.handler(ev), onCause), renderable.options);
|
|
399
|
+
return EventHandler.make((ev) => Effect.provide(Effect.catchAllCause(renderable.handler(ev), onCause), ctx), renderable.options);
|
|
87
400
|
}
|
|
88
401
|
else if (Effect.EffectTypeId in renderable) {
|
|
89
|
-
return EventHandler.make(() => Effect.catchAllCause(renderable, onCause));
|
|
402
|
+
return EventHandler.make(() => Effect.provide(Effect.catchAllCause(renderable, onCause), ctx));
|
|
90
403
|
}
|
|
91
404
|
}
|
|
92
405
|
return null;
|
|
@@ -100,7 +413,7 @@ function handlePart(renderable, update) {
|
|
|
100
413
|
else if (Array.isArray(renderable)) {
|
|
101
414
|
return renderable.length === 0
|
|
102
415
|
? update(null)
|
|
103
|
-
: Effect.forkScoped(Fx.observe(Fx.
|
|
416
|
+
: Effect.forkScoped(Fx.observe(Fx.tuple(renderable.map(unwrapRenderable)), update));
|
|
104
417
|
}
|
|
105
418
|
else if (TypeId in renderable) {
|
|
106
419
|
return Effect.forkScoped(Fx.observe(renderable, update));
|
|
@@ -122,7 +435,7 @@ function unwrapRenderable(renderable) {
|
|
|
122
435
|
if (renderable === null || renderable === undefined)
|
|
123
436
|
return Fx.succeed(null);
|
|
124
437
|
else if (Array.isArray(renderable)) {
|
|
125
|
-
return renderable.length === 0 ? Fx.succeed(null) : Fx.
|
|
438
|
+
return renderable.length === 0 ? Fx.succeed(null) : Fx.tuple(renderable.map(unwrapRenderable));
|
|
126
439
|
}
|
|
127
440
|
else if (TypeId in renderable) {
|
|
128
441
|
return renderable;
|
|
@@ -137,20 +450,6 @@ function unwrapRenderable(renderable) {
|
|
|
137
450
|
return Fx.succeed(renderable);
|
|
138
451
|
}
|
|
139
452
|
}
|
|
140
|
-
function unwrapSparsePartRenderables(renderables, part) {
|
|
141
|
-
return Fx.combine(
|
|
142
|
-
// @ts-ignore type too deep
|
|
143
|
-
renderables.map((renderable, i) => {
|
|
144
|
-
const p = part.parts[i];
|
|
145
|
-
if (p._tag === "static/text") {
|
|
146
|
-
return Fx.succeed(p.value);
|
|
147
|
-
}
|
|
148
|
-
if (isDirective(renderable)) {
|
|
149
|
-
return Fx.fromEffect(Effect.map(renderable(p), () => p.value));
|
|
150
|
-
}
|
|
151
|
-
return Fx.mapEffect(unwrapRenderable(renderable), (u) => Effect.map(p.update(u), () => p.value));
|
|
152
|
-
}));
|
|
153
|
-
}
|
|
154
453
|
export function attachRoot(cache, where, what // TODO: Should we support HTML RenderEvents here too?
|
|
155
454
|
) {
|
|
156
455
|
return Effect.sync(() => {
|
|
@@ -196,80 +495,6 @@ export function getBrowserEntry(document, ctx, templateStrings) {
|
|
|
196
495
|
return cached;
|
|
197
496
|
}
|
|
198
497
|
}
|
|
199
|
-
export function buildParts(document, ctx, template, content, ref, onCause, isHydrating) {
|
|
200
|
-
return Effect.all(template.parts.map(([part, path]) => buildPartWithNode(document, ctx, part, findPath(content, path), ref, onCause, isHydrating)));
|
|
201
|
-
}
|
|
202
|
-
function buildPartWithNode(document, ctx, part, node, ref, onCause, isHydrating) {
|
|
203
|
-
switch (part._tag) {
|
|
204
|
-
case "attr":
|
|
205
|
-
return Effect.succeed(AttributePartImpl.browser(part.index, node, part.name, ctx));
|
|
206
|
-
case "boolean-part":
|
|
207
|
-
return Effect.succeed(BooleanPartImpl.browser(part.index, node, part.name, ctx));
|
|
208
|
-
case "className-part":
|
|
209
|
-
return Effect.succeed(ClassNamePartImpl.browser(part.index, node, ctx));
|
|
210
|
-
case "comment-part":
|
|
211
|
-
return Effect.succeed(CommentPartImpl.browser(part.index, node, ctx));
|
|
212
|
-
case "data":
|
|
213
|
-
return Effect.succeed(DataPartImpl.browser(part.index, node, ctx));
|
|
214
|
-
case "event":
|
|
215
|
-
return EventPartImpl.browser(part.name, part.index, ref, node, onCause);
|
|
216
|
-
case "node":
|
|
217
|
-
return Effect.succeed(makeRenderNodePart(part.index, node, ctx, document, isHydrating));
|
|
218
|
-
case "property":
|
|
219
|
-
return Effect.succeed(PropertyPartImpl.browser(part.index, node, part.name, ctx));
|
|
220
|
-
case "ref":
|
|
221
|
-
return Effect.succeed(new RefPartImpl(ref.query(node), part.index));
|
|
222
|
-
case "sparse-attr": {
|
|
223
|
-
const parts = Array(part.nodes.length);
|
|
224
|
-
const sparse = SparseAttributePartImpl.browser(part.name, parts, node, ctx);
|
|
225
|
-
for (let i = 0; i < part.nodes.length; ++i) {
|
|
226
|
-
const node = part.nodes[i];
|
|
227
|
-
if (node._tag === "text") {
|
|
228
|
-
parts.push(new StaticTextImpl(node.value));
|
|
229
|
-
sparse.value[i] = node.value;
|
|
230
|
-
}
|
|
231
|
-
else {
|
|
232
|
-
parts.push(new AttributePartImpl(node.name, node.index, ({ value }) => sparse.update(replace(sparse.value, i, value || "")), sparse.value[i]));
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
return Effect.succeed(sparse);
|
|
236
|
-
}
|
|
237
|
-
case "sparse-class-name": {
|
|
238
|
-
const parts = [];
|
|
239
|
-
const values = []; // TODO: Do this for all other sparse attrs
|
|
240
|
-
const sparse = SparseClassNamePartImpl.browser(parts, node, ctx, values);
|
|
241
|
-
for (let i = 0; i < part.nodes.length; ++i) {
|
|
242
|
-
const node = part.nodes[i];
|
|
243
|
-
if (node._tag === "text") {
|
|
244
|
-
parts.push(new StaticTextImpl(node.value));
|
|
245
|
-
values.push(node.value);
|
|
246
|
-
}
|
|
247
|
-
else {
|
|
248
|
-
values.push([]);
|
|
249
|
-
parts.push(new ClassNamePartImpl(node.index, ({ value }) => sparse.update(replace(sparse.value, i, value || "")), []));
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
return Effect.succeed(sparse);
|
|
253
|
-
}
|
|
254
|
-
case "sparse-comment": {
|
|
255
|
-
const parts = Array(part.nodes.length);
|
|
256
|
-
const sparse = SparseCommentPartImpl.browser(node, parts, ctx);
|
|
257
|
-
for (let i = 0; i < part.nodes.length; ++i) {
|
|
258
|
-
const node = part.nodes[i];
|
|
259
|
-
if (node._tag === "text") {
|
|
260
|
-
parts.push(new StaticTextImpl(node.value));
|
|
261
|
-
sparse.value[i] = node.value;
|
|
262
|
-
}
|
|
263
|
-
else {
|
|
264
|
-
parts.push(new CommentPartImpl(node.index, ({ value }) => sparse.update(replace(sparse.value, i, value || "")), sparse.value[i]));
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
return Effect.succeed(sparse);
|
|
268
|
-
}
|
|
269
|
-
case "text-part":
|
|
270
|
-
return Effect.succeed(TextPartImpl.browser(document, part.index, node, ctx));
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
498
|
export function buildTemplate(document, { nodes }) {
|
|
274
499
|
const fragment = document.createDocumentFragment();
|
|
275
500
|
for (let i = 0; i < nodes.length; ++i) {
|
|
@@ -293,6 +518,33 @@ function buildNode(document, node, isSvgContext) {
|
|
|
293
518
|
case "comment-part":
|
|
294
519
|
case "node":
|
|
295
520
|
return document.createComment(`hole${node.index}`);
|
|
521
|
+
case "doctype":
|
|
522
|
+
return document.implementation.createDocumentType(node.name, docTypeNameToPublicId(node.name), docTypeNameToSystemId(node.name));
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
function docTypeNameToPublicId(name) {
|
|
526
|
+
switch (name) {
|
|
527
|
+
case "html":
|
|
528
|
+
return "-//W3C//DTD HTML 4.01//EN";
|
|
529
|
+
case "svg":
|
|
530
|
+
return "-//W3C//DTD SVG 1.1//EN";
|
|
531
|
+
case "math":
|
|
532
|
+
return "-//W3C//DTD MathML 2.0//EN";
|
|
533
|
+
default:
|
|
534
|
+
return "";
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
function docTypeNameToSystemId(name) {
|
|
538
|
+
switch (name) {
|
|
539
|
+
// HTML5
|
|
540
|
+
case "html":
|
|
541
|
+
return "http://www.w3.org/TR/html4/strict.dtd";
|
|
542
|
+
case "svg":
|
|
543
|
+
return "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd";
|
|
544
|
+
case "math":
|
|
545
|
+
return "http://www.w3.org/Math/DTD/mathml2/mathml2.dtd";
|
|
546
|
+
default:
|
|
547
|
+
return "";
|
|
296
548
|
}
|
|
297
549
|
}
|
|
298
550
|
const SVG_NAMESPACE = "http://www.w3.org/2000/svg";
|
|
@@ -326,4 +578,41 @@ function buildTextChild(document, node) {
|
|
|
326
578
|
}
|
|
327
579
|
return document.createComment(`hole${node.index}`);
|
|
328
580
|
}
|
|
581
|
+
function createAttribute(document, element, name) {
|
|
582
|
+
return element.getAttributeNode(name) ?? document.createAttribute(name);
|
|
583
|
+
}
|
|
584
|
+
function matchSettablePart(renderable, setValue, makePart, schedule, expect) {
|
|
585
|
+
return matchRenderable(renderable, {
|
|
586
|
+
Fx: (fx) => {
|
|
587
|
+
expect();
|
|
588
|
+
return Fx.observe(fx, (a) => schedule(() => setValue(a)));
|
|
589
|
+
},
|
|
590
|
+
Effect: (effect) => {
|
|
591
|
+
expect();
|
|
592
|
+
return Effect.flatMap(effect, (a) => schedule(() => setValue(a)));
|
|
593
|
+
},
|
|
594
|
+
Directive: (directive) => {
|
|
595
|
+
expect();
|
|
596
|
+
return directive(makePart());
|
|
597
|
+
},
|
|
598
|
+
Otherwise: (otherwise) => {
|
|
599
|
+
setValue(otherwise);
|
|
600
|
+
return null;
|
|
601
|
+
}
|
|
602
|
+
});
|
|
603
|
+
}
|
|
604
|
+
function matchRenderable(renderable, matches) {
|
|
605
|
+
if (Fx.isFx(renderable)) {
|
|
606
|
+
return matches.Fx(renderable);
|
|
607
|
+
}
|
|
608
|
+
else if (Effect.isEffect(renderable)) {
|
|
609
|
+
return matches.Effect(renderable);
|
|
610
|
+
}
|
|
611
|
+
else if (isDirective(renderable)) {
|
|
612
|
+
return matches.Directive(renderable);
|
|
613
|
+
}
|
|
614
|
+
else {
|
|
615
|
+
return matches.Otherwise(renderable);
|
|
616
|
+
}
|
|
617
|
+
}
|
|
329
618
|
//# sourceMappingURL=render.js.map
|