@typed/template 0.9.6 → 0.11.0
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/RenderQueue/package.json +6 -0
- package/dist/cjs/Directive.js +1 -1
- package/dist/cjs/Directive.js.map +1 -1
- package/dist/cjs/ElementRef.js +1 -1
- package/dist/cjs/ElementRef.js.map +1 -1
- package/dist/cjs/ElementSource.js +1 -1
- package/dist/cjs/ElementSource.js.map +1 -1
- package/dist/cjs/EventHandler.js +15 -4
- package/dist/cjs/EventHandler.js.map +1 -1
- package/dist/cjs/Html.js +84 -44
- package/dist/cjs/Html.js.map +1 -1
- package/dist/cjs/HtmlChunk.js +67 -21
- package/dist/cjs/HtmlChunk.js.map +1 -1
- package/dist/cjs/Hydrate.js +6 -6
- package/dist/cjs/Hydrate.js.map +1 -1
- package/dist/cjs/Many.js +4 -4
- package/dist/cjs/Many.js.map +1 -1
- package/dist/cjs/Meta.js +10 -3
- package/dist/cjs/Meta.js.map +1 -1
- package/dist/cjs/Parser.js +1 -1
- package/dist/cjs/Placeholder.js +5 -9
- package/dist/cjs/Placeholder.js.map +1 -1
- package/dist/cjs/Platform.js +7 -5
- package/dist/cjs/Platform.js.map +1 -1
- package/dist/cjs/Render.js +8 -7
- package/dist/cjs/Render.js.map +1 -1
- package/dist/cjs/RenderContext.js +8 -92
- package/dist/cjs/RenderContext.js.map +1 -1
- package/dist/cjs/RenderEvent.js +9 -1
- package/dist/cjs/RenderEvent.js.map +1 -1
- package/dist/cjs/RenderQueue.js +341 -0
- package/dist/cjs/RenderQueue.js.map +1 -0
- package/dist/cjs/RenderTemplate.js +1 -1
- package/dist/cjs/RenderTemplate.js.map +1 -1
- package/dist/cjs/Template.js +12 -0
- package/dist/cjs/Template.js.map +1 -1
- package/dist/cjs/Test.js +64 -33
- package/dist/cjs/Test.js.map +1 -1
- package/dist/cjs/Vitest.js +12 -20
- package/dist/cjs/Vitest.js.map +1 -1
- package/dist/cjs/index.js +6 -3
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/internal/EventSource.js +16 -9
- package/dist/cjs/internal/EventSource.js.map +1 -1
- package/dist/cjs/internal/HydrateContext.js.map +1 -1
- package/dist/cjs/internal/browser.js +11 -10
- package/dist/cjs/internal/browser.js.map +1 -1
- package/dist/cjs/internal/character-entities.js +2141 -0
- package/dist/cjs/internal/character-entities.js.map +1 -0
- package/dist/cjs/internal/errors.js +19 -2
- package/dist/cjs/internal/errors.js.map +1 -1
- package/dist/cjs/internal/indexRefCounter.js +36 -63
- package/dist/cjs/internal/indexRefCounter.js.map +1 -1
- package/dist/cjs/internal/parser.js +18 -17
- package/dist/cjs/internal/parser.js.map +1 -1
- package/dist/cjs/internal/parser2.js +382 -0
- package/dist/cjs/internal/parser2.js.map +1 -0
- package/dist/cjs/internal/server-parts.js +124 -0
- package/dist/cjs/internal/server-parts.js.map +1 -0
- package/dist/cjs/internal/server.js +15 -185
- package/dist/cjs/internal/server.js.map +1 -1
- package/dist/cjs/internal/utils.js +73 -9
- package/dist/cjs/internal/utils.js.map +1 -1
- package/dist/cjs/internal/v2/SyncPart.js +6 -0
- package/dist/cjs/internal/v2/SyncPart.js.map +1 -0
- package/dist/cjs/internal/v2/helpers.js +15 -0
- package/dist/cjs/internal/v2/helpers.js.map +1 -0
- package/dist/cjs/internal/v2/hydrate.js +202 -0
- package/dist/cjs/internal/v2/hydrate.js.map +1 -0
- package/dist/cjs/internal/v2/hydration-template.js +269 -0
- package/dist/cjs/internal/v2/hydration-template.js.map +1 -0
- package/dist/cjs/internal/v2/parts.js +169 -0
- package/dist/cjs/internal/v2/parts.js.map +1 -0
- package/dist/cjs/internal/v2/render-entry.js +110 -0
- package/dist/cjs/internal/v2/render-entry.js.map +1 -0
- package/dist/cjs/internal/v2/render-sync-parts.js +318 -0
- package/dist/cjs/internal/v2/render-sync-parts.js.map +1 -0
- package/dist/cjs/internal/v2/render.js +417 -0
- package/dist/cjs/internal/v2/render.js.map +1 -0
- package/dist/cjs/internal/v2/sync-parts.js +115 -0
- package/dist/cjs/internal/v2/sync-parts.js.map +1 -0
- package/dist/dts/ElementRef.d.ts +1 -1
- package/dist/dts/ElementRef.d.ts.map +1 -1
- package/dist/dts/ElementSource.d.ts +1 -1
- package/dist/dts/ElementSource.d.ts.map +1 -1
- package/dist/dts/EventHandler.d.ts +20 -8
- package/dist/dts/EventHandler.d.ts.map +1 -1
- package/dist/dts/Html.d.ts +6 -5
- package/dist/dts/Html.d.ts.map +1 -1
- package/dist/dts/HtmlChunk.d.ts.map +1 -1
- package/dist/dts/Hydrate.d.ts +1 -3
- package/dist/dts/Hydrate.d.ts.map +1 -1
- package/dist/dts/Many.d.ts +9 -11
- package/dist/dts/Many.d.ts.map +1 -1
- package/dist/dts/Meta.d.ts +5 -1
- package/dist/dts/Meta.d.ts.map +1 -1
- package/dist/dts/Parser.d.ts +1 -1
- package/dist/dts/Parser.d.ts.map +1 -1
- package/dist/dts/Part.d.ts +20 -56
- package/dist/dts/Part.d.ts.map +1 -1
- package/dist/dts/Placeholder.d.ts +6 -10
- package/dist/dts/Placeholder.d.ts.map +1 -1
- package/dist/dts/Platform.d.ts +2 -4
- package/dist/dts/Platform.d.ts.map +1 -1
- package/dist/dts/Render.d.ts +4 -8
- package/dist/dts/Render.d.ts.map +1 -1
- package/dist/dts/RenderContext.d.ts +3 -22
- package/dist/dts/RenderContext.d.ts.map +1 -1
- package/dist/dts/RenderEvent.d.ts +6 -1
- package/dist/dts/RenderEvent.d.ts.map +1 -1
- package/dist/dts/RenderQueue.d.ts +103 -0
- package/dist/dts/RenderQueue.d.ts.map +1 -0
- package/dist/dts/RenderTemplate.d.ts +3 -2
- package/dist/dts/RenderTemplate.d.ts.map +1 -1
- package/dist/dts/Renderable.d.ts +1 -1
- package/dist/dts/Template.d.ts +14 -1
- package/dist/dts/Template.d.ts.map +1 -1
- package/dist/dts/Test.d.ts +14 -1
- package/dist/dts/Test.d.ts.map +1 -1
- package/dist/dts/Vitest.d.ts +11 -8
- package/dist/dts/Vitest.d.ts.map +1 -1
- package/dist/dts/index.d.ts +4 -0
- package/dist/dts/index.d.ts.map +1 -1
- package/dist/dts/internal/EventSource.d.ts +2 -1
- package/dist/dts/internal/EventSource.d.ts.map +1 -1
- package/dist/dts/internal/browser.d.ts +3 -3
- package/dist/dts/internal/browser.d.ts.map +1 -1
- package/dist/dts/internal/character-entities.d.ts +2133 -0
- package/dist/dts/internal/character-entities.d.ts.map +1 -0
- package/dist/dts/internal/errors.d.ts +9 -1
- package/dist/dts/internal/errors.d.ts.map +1 -1
- package/dist/dts/internal/indexRefCounter.d.ts +0 -4
- package/dist/dts/internal/indexRefCounter.d.ts.map +1 -1
- package/dist/dts/internal/parser.d.ts +13 -0
- package/dist/dts/internal/parser.d.ts.map +1 -1
- package/dist/dts/internal/parser2.d.ts +12 -0
- package/dist/dts/internal/parser2.d.ts.map +1 -0
- package/dist/dts/internal/server-parts.d.ts +223 -0
- package/dist/dts/internal/server-parts.d.ts.map +1 -0
- package/dist/dts/internal/server.d.ts +2 -28
- package/dist/dts/internal/server.d.ts.map +1 -1
- package/dist/dts/internal/utils.d.ts +4 -1
- package/dist/dts/internal/utils.d.ts.map +1 -1
- package/dist/dts/internal/v2/SyncPart.d.ts +87 -0
- package/dist/dts/internal/v2/SyncPart.d.ts.map +1 -0
- package/dist/dts/internal/v2/helpers.d.ts +3 -0
- package/dist/dts/internal/v2/helpers.d.ts.map +1 -0
- package/dist/dts/internal/v2/hydrate.d.ts +7 -0
- package/dist/dts/internal/v2/hydrate.d.ts.map +1 -0
- package/dist/dts/internal/v2/hydration-template.d.ts +54 -0
- package/dist/dts/internal/v2/hydration-template.d.ts.map +1 -0
- package/dist/dts/internal/v2/parts.d.ts +245 -0
- package/dist/dts/internal/v2/parts.d.ts.map +1 -0
- package/dist/dts/internal/v2/render-entry.d.ts +6 -0
- package/dist/dts/internal/v2/render-entry.d.ts.map +1 -0
- package/dist/dts/internal/v2/render-sync-parts.d.ts +22 -0
- package/dist/dts/internal/v2/render-sync-parts.d.ts.map +1 -0
- package/dist/dts/internal/v2/render.d.ts +62 -0
- package/dist/dts/internal/v2/render.d.ts.map +1 -0
- package/dist/dts/internal/v2/sync-parts.d.ts +129 -0
- package/dist/dts/internal/v2/sync-parts.d.ts.map +1 -0
- package/dist/esm/ElementRef.js.map +1 -1
- package/dist/esm/EventHandler.js +20 -4
- package/dist/esm/EventHandler.js.map +1 -1
- package/dist/esm/Html.js +91 -50
- package/dist/esm/Html.js.map +1 -1
- package/dist/esm/HtmlChunk.js +75 -24
- package/dist/esm/HtmlChunk.js.map +1 -1
- package/dist/esm/Hydrate.js +5 -5
- package/dist/esm/Hydrate.js.map +1 -1
- package/dist/esm/Many.js +3 -3
- package/dist/esm/Many.js.map +1 -1
- package/dist/esm/Meta.js +7 -1
- package/dist/esm/Meta.js.map +1 -1
- package/dist/esm/Parser.js +1 -1
- package/dist/esm/Parser.js.map +1 -1
- package/dist/esm/Placeholder.js +4 -8
- package/dist/esm/Placeholder.js.map +1 -1
- package/dist/esm/Platform.js +3 -1
- package/dist/esm/Platform.js.map +1 -1
- package/dist/esm/Render.js +6 -5
- package/dist/esm/Render.js.map +1 -1
- package/dist/esm/RenderContext.js +5 -85
- package/dist/esm/RenderContext.js.map +1 -1
- package/dist/esm/RenderEvent.js +8 -1
- package/dist/esm/RenderEvent.js.map +1 -1
- package/dist/esm/RenderQueue.js +336 -0
- package/dist/esm/RenderQueue.js.map +1 -0
- package/dist/esm/RenderTemplate.js.map +1 -1
- package/dist/esm/Template.js +12 -0
- package/dist/esm/Template.js.map +1 -1
- package/dist/esm/Test.js +71 -30
- package/dist/esm/Test.js.map +1 -1
- package/dist/esm/Vitest.js +11 -8
- package/dist/esm/Vitest.js.map +1 -1
- package/dist/esm/index.js +4 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/internal/EventSource.js +12 -7
- package/dist/esm/internal/EventSource.js.map +1 -1
- package/dist/esm/internal/HydrateContext.js.map +1 -1
- package/dist/esm/internal/browser.js +10 -9
- package/dist/esm/internal/browser.js.map +1 -1
- package/dist/esm/internal/character-entities.js +2134 -0
- package/dist/esm/internal/character-entities.js.map +1 -0
- package/dist/esm/internal/errors.js +22 -2
- package/dist/esm/internal/errors.js.map +1 -1
- package/dist/esm/internal/indexRefCounter.js +36 -61
- package/dist/esm/internal/indexRefCounter.js.map +1 -1
- package/dist/esm/internal/parser.js +18 -18
- package/dist/esm/internal/parser.js.map +1 -1
- package/dist/esm/internal/parser2.js +393 -0
- package/dist/esm/internal/parser2.js.map +1 -0
- package/dist/esm/internal/server-parts.js +109 -0
- package/dist/esm/internal/server-parts.js.map +1 -0
- package/dist/esm/internal/server.js +12 -161
- package/dist/esm/internal/server.js.map +1 -1
- package/dist/esm/internal/utils.js +71 -7
- package/dist/esm/internal/utils.js.map +1 -1
- package/dist/esm/internal/v2/SyncPart.js +5 -0
- package/dist/esm/internal/v2/SyncPart.js.map +1 -0
- package/dist/esm/internal/v2/helpers.js +12 -0
- package/dist/esm/internal/v2/helpers.js.map +1 -0
- package/dist/esm/internal/v2/hydrate.js +195 -0
- package/dist/esm/internal/v2/hydrate.js.map +1 -0
- package/dist/esm/internal/v2/hydration-template.js +265 -0
- package/dist/esm/internal/v2/hydration-template.js.map +1 -0
- package/dist/esm/internal/v2/parts.js +150 -0
- package/dist/esm/internal/v2/parts.js.map +1 -0
- package/dist/esm/internal/v2/render-entry.js +102 -0
- package/dist/esm/internal/v2/render-entry.js.map +1 -0
- package/dist/esm/internal/v2/render-sync-parts.js +265 -0
- package/dist/esm/internal/v2/render-sync-parts.js.map +1 -0
- package/dist/esm/internal/v2/render.js +353 -0
- package/dist/esm/internal/v2/render.js.map +1 -0
- package/dist/esm/internal/v2/sync-parts.js +102 -0
- package/dist/esm/internal/v2/sync-parts.js.map +1 -0
- package/package.json +20 -13
- package/src/ElementRef.ts +1 -1
- package/src/ElementSource.ts +1 -1
- package/src/EventHandler.ts +50 -12
- package/src/Html.ts +207 -98
- package/src/HtmlChunk.ts +77 -30
- package/src/Hydrate.ts +20 -14
- package/src/Many.ts +17 -14
- package/src/Meta.ts +8 -1
- package/src/Parser.ts +1 -1
- package/src/Part.ts +22 -66
- package/src/Placeholder.ts +17 -15
- package/src/Platform.ts +5 -5
- package/src/Render.ts +23 -26
- package/src/RenderContext.ts +14 -142
- package/src/RenderEvent.ts +10 -1
- package/src/RenderQueue.ts +445 -0
- package/src/RenderTemplate.ts +7 -2
- package/src/Renderable.ts +1 -1
- package/src/Template.ts +15 -1
- package/src/Test.ts +122 -38
- package/src/Vitest.ts +20 -10
- package/src/index.ts +4 -0
- package/src/internal/EventSource.ts +14 -8
- package/src/internal/HydrateContext.ts +3 -4
- package/src/internal/browser.ts +26 -21
- package/src/internal/character-entities.ts +2136 -0
- package/src/internal/errors.ts +30 -3
- package/src/internal/indexRefCounter.ts +38 -70
- package/src/internal/parser.ts +19 -19
- package/src/internal/parser2.ts +468 -0
- package/src/internal/server-parts.ts +161 -0
- package/src/internal/server.ts +16 -272
- package/src/internal/utils.ts +83 -7
- package/src/internal/v2/SyncPart.ts +112 -0
- package/src/internal/v2/helpers.ts +13 -0
- package/src/internal/v2/hydrate.ts +289 -0
- package/src/internal/v2/hydration-template.ts +308 -0
- package/src/internal/v2/parts.ts +254 -0
- package/src/internal/v2/render-entry.ts +131 -0
- package/src/internal/v2/render-sync-parts.ts +440 -0
- package/src/internal/v2/render.ts +588 -0
- package/src/internal/v2/sync-parts.ts +133 -0
- package/dist/cjs/internal/hydrate.js +0 -274
- package/dist/cjs/internal/hydrate.js.map +0 -1
- package/dist/cjs/internal/parts.js +0 -451
- package/dist/cjs/internal/parts.js.map +0 -1
- package/dist/cjs/internal/render.js +0 -704
- package/dist/cjs/internal/render.js.map +0 -1
- package/dist/dts/internal/hydrate.d.ts +0 -33
- package/dist/dts/internal/hydrate.d.ts.map +0 -1
- package/dist/dts/internal/parts.d.ts +0 -314
- package/dist/dts/internal/parts.d.ts.map +0 -1
- package/dist/dts/internal/render.d.ts +0 -16
- package/dist/dts/internal/render.d.ts.map +0 -1
- package/dist/esm/internal/hydrate.js +0 -239
- package/dist/esm/internal/hydrate.js.map +0 -1
- package/dist/esm/internal/parts.js +0 -373
- package/dist/esm/internal/parts.js.map +0 -1
- package/dist/esm/internal/render.js +0 -689
- package/dist/esm/internal/render.js.map +0 -1
- package/src/internal/hydrate.ts +0 -366
- package/src/internal/parts.ts +0 -609
- package/src/internal/render.ts +0 -971
package/src/internal/parts.ts
DELETED
|
@@ -1,609 +0,0 @@
|
|
|
1
|
-
import { isText } from "@typed/wire"
|
|
2
|
-
import type { Cause } from "effect/Cause"
|
|
3
|
-
import * as Data from "effect/Data"
|
|
4
|
-
import * as Effect from "effect/Effect"
|
|
5
|
-
import { equals } from "effect/Equal"
|
|
6
|
-
import * as Equivalence from "effect/Equivalence"
|
|
7
|
-
import * as ReadonlyArray from "effect/ReadonlyArray"
|
|
8
|
-
import type { Scope } from "effect/Scope"
|
|
9
|
-
import type { ElementSource } from "../ElementSource.js"
|
|
10
|
-
import type { EventHandler } from "../EventHandler.js"
|
|
11
|
-
import { unescape } from "../HtmlChunk.js"
|
|
12
|
-
import type {
|
|
13
|
-
AttributePart,
|
|
14
|
-
BooleanPart,
|
|
15
|
-
ClassNamePart,
|
|
16
|
-
CommentPart,
|
|
17
|
-
DataPart,
|
|
18
|
-
EventPart,
|
|
19
|
-
NodePart,
|
|
20
|
-
Part,
|
|
21
|
-
PropertiesPart,
|
|
22
|
-
PropertyPart,
|
|
23
|
-
RefPart,
|
|
24
|
-
SparseAttributePart,
|
|
25
|
-
SparseClassNamePart,
|
|
26
|
-
SparseCommentPart,
|
|
27
|
-
SparsePart,
|
|
28
|
-
StaticText,
|
|
29
|
-
TextPart
|
|
30
|
-
} from "../Part.js"
|
|
31
|
-
import type { RenderContext } from "../RenderContext.js"
|
|
32
|
-
import { findHoleComment } from "./utils.js"
|
|
33
|
-
|
|
34
|
-
const strictEq = Equivalence.strict<any>()
|
|
35
|
-
|
|
36
|
-
const base = <T extends Part["_tag"]>(tag: T) => (class Base {
|
|
37
|
-
readonly _tag: T = tag
|
|
38
|
-
|
|
39
|
-
constructor(
|
|
40
|
-
readonly index: number,
|
|
41
|
-
readonly commit: (
|
|
42
|
-
params: {
|
|
43
|
-
previous: Extract<Part, { readonly _tag: T }>["value"]
|
|
44
|
-
value: Extract<Part, { readonly _tag: T }>["value"]
|
|
45
|
-
part: Extract<Part, { readonly _tag: T }>
|
|
46
|
-
}
|
|
47
|
-
) => Effect.Effect<void, never, Scope>,
|
|
48
|
-
public value: Extract<Part, { readonly _tag: T }>["value"],
|
|
49
|
-
readonly eq: Equivalence.Equivalence<Extract<Part, { readonly _tag: T }>["value"]> = equals
|
|
50
|
-
) {
|
|
51
|
-
this.update = this.update.bind(this)
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
update(input: this["value"]) {
|
|
55
|
-
const previous = this.value as any
|
|
56
|
-
const value = this.getValue(input) as any
|
|
57
|
-
|
|
58
|
-
if (this.eq(previous as any, value as any)) {
|
|
59
|
-
return Effect.unit
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
return Effect.flatMap(
|
|
63
|
-
this.commit.call(this, {
|
|
64
|
-
previous,
|
|
65
|
-
value,
|
|
66
|
-
part: this as any
|
|
67
|
-
}),
|
|
68
|
-
() => Effect.sync(() => this.value = value)
|
|
69
|
-
)
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
getValue(value: unknown) {
|
|
73
|
-
return value
|
|
74
|
-
}
|
|
75
|
-
})
|
|
76
|
-
|
|
77
|
-
export class AttributePartImpl extends base("attribute") implements AttributePart {
|
|
78
|
-
constructor(
|
|
79
|
-
readonly name: string,
|
|
80
|
-
index: number,
|
|
81
|
-
commit: AttributePartImpl["commit"],
|
|
82
|
-
value: AttributePart["value"]
|
|
83
|
-
) {
|
|
84
|
-
super(index, commit, value, strictEq)
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
static browser(index: number, element: Element, name: string, context: RenderContext): AttributePartImpl {
|
|
88
|
-
return new AttributePartImpl(
|
|
89
|
-
name,
|
|
90
|
-
index,
|
|
91
|
-
({ part, value }) =>
|
|
92
|
-
context.queue.add(
|
|
93
|
-
part,
|
|
94
|
-
() => value == null ? element.removeAttribute(name) : element.setAttribute(name, value)
|
|
95
|
-
),
|
|
96
|
-
element.getAttribute(name)
|
|
97
|
-
)
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
static server(
|
|
101
|
-
name: string,
|
|
102
|
-
index: number,
|
|
103
|
-
commit: AttributePartImpl["commit"]
|
|
104
|
-
) {
|
|
105
|
-
return new AttributePartImpl(name, index, commit, null)
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
export class BooleanPartImpl extends base("boolean") implements BooleanPart {
|
|
110
|
-
constructor(
|
|
111
|
-
readonly name: string,
|
|
112
|
-
index: number,
|
|
113
|
-
commit: BooleanPartImpl["commit"],
|
|
114
|
-
value: BooleanPart["value"]
|
|
115
|
-
) {
|
|
116
|
-
super(index, commit, value, strictEq)
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
static browser(index: number, element: Element, name: string, context: RenderContext): BooleanPartImpl {
|
|
120
|
-
return new BooleanPartImpl(
|
|
121
|
-
name,
|
|
122
|
-
index,
|
|
123
|
-
({ part, value }) =>
|
|
124
|
-
context.queue.add(
|
|
125
|
-
part,
|
|
126
|
-
() => element.toggleAttribute(name, value === true)
|
|
127
|
-
),
|
|
128
|
-
element.hasAttribute(name)
|
|
129
|
-
)
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
static server(
|
|
133
|
-
name: string,
|
|
134
|
-
index: number,
|
|
135
|
-
commit: BooleanPartImpl["commit"]
|
|
136
|
-
) {
|
|
137
|
-
return new BooleanPartImpl(name, index, commit, null)
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
const isString = (x: unknown): x is string => typeof x === "string"
|
|
142
|
-
|
|
143
|
-
export class ClassNamePartImpl extends base("className") implements ClassNamePart {
|
|
144
|
-
constructor(
|
|
145
|
-
index: number,
|
|
146
|
-
commit: ClassNamePartImpl["commit"],
|
|
147
|
-
value: ClassNamePart["value"]
|
|
148
|
-
) {
|
|
149
|
-
super(index, commit, value, strictEq)
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
getValue(value: unknown): ReadonlyArray<string> {
|
|
153
|
-
if (isString(value)) {
|
|
154
|
-
return value.split(" ").filter((x) => isString(x) && x.trim() !== "")
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
if (Array.isArray(value)) {
|
|
158
|
-
return value.filter((x) => isString(x) && x.trim() !== "")
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
return []
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
static browser(index: number, element: Element, context: RenderContext): ClassNamePartImpl {
|
|
165
|
-
return new ClassNamePartImpl(
|
|
166
|
-
index,
|
|
167
|
-
({ part, previous, value }) =>
|
|
168
|
-
context.queue.add(
|
|
169
|
-
part,
|
|
170
|
-
() => {
|
|
171
|
-
const { added, removed } = diffStrings(
|
|
172
|
-
previous,
|
|
173
|
-
value
|
|
174
|
-
)
|
|
175
|
-
|
|
176
|
-
element.classList.add(...added)
|
|
177
|
-
element.classList.remove(...removed)
|
|
178
|
-
}
|
|
179
|
-
),
|
|
180
|
-
Array.from(element.classList)
|
|
181
|
-
)
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
static server(
|
|
185
|
-
index: number,
|
|
186
|
-
commit: ClassNamePartImpl["commit"]
|
|
187
|
-
) {
|
|
188
|
-
return new ClassNamePartImpl(index, commit, null)
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
function diffStrings(
|
|
193
|
-
previous: ReadonlyArray<string> | null | undefined,
|
|
194
|
-
current: ReadonlyArray<string> | null | undefined
|
|
195
|
-
): { added: ReadonlyArray<string>; removed: ReadonlyArray<string>; unchanged: ReadonlyArray<string> } {
|
|
196
|
-
if (previous == null || previous.length === 0) {
|
|
197
|
-
return {
|
|
198
|
-
added: current || [],
|
|
199
|
-
removed: [],
|
|
200
|
-
unchanged: []
|
|
201
|
-
}
|
|
202
|
-
} else if (current == null || current.length === 0) {
|
|
203
|
-
return {
|
|
204
|
-
added: [],
|
|
205
|
-
removed: previous,
|
|
206
|
-
unchanged: []
|
|
207
|
-
}
|
|
208
|
-
} else {
|
|
209
|
-
const added = current.filter((c) => !previous.includes(c))
|
|
210
|
-
const removed: Array<string> = []
|
|
211
|
-
const unchanged: Array<string> = []
|
|
212
|
-
|
|
213
|
-
for (let i = 0; i < previous.length; ++i) {
|
|
214
|
-
if (current.includes(previous[i])) {
|
|
215
|
-
unchanged.push(previous[i])
|
|
216
|
-
} else {
|
|
217
|
-
removed.push(previous[i])
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
return {
|
|
222
|
-
added,
|
|
223
|
-
removed,
|
|
224
|
-
unchanged
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
export class CommentPartImpl extends base("comment") implements CommentPart {
|
|
230
|
-
static browser(index: number, comment: globalThis.Comment, ctx: RenderContext) {
|
|
231
|
-
return new CommentPartImpl(
|
|
232
|
-
index,
|
|
233
|
-
({ part, value }) => ctx.queue.add(part, () => comment.data = value || ""),
|
|
234
|
-
comment.data,
|
|
235
|
-
strictEq
|
|
236
|
-
)
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
static server(index: number, commit: CommentPartImpl["commit"]) {
|
|
240
|
-
return new CommentPartImpl(index, commit, null)
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
export class DataPartImpl extends base("data") implements DataPart {
|
|
245
|
-
static browser(index: number, element: HTMLElement | SVGElement, ctx: RenderContext) {
|
|
246
|
-
return new DataPartImpl(
|
|
247
|
-
index,
|
|
248
|
-
({ part, previous, value }) =>
|
|
249
|
-
ctx.queue.add(
|
|
250
|
-
part,
|
|
251
|
-
() => {
|
|
252
|
-
const diff = diffDataSet(previous, value)
|
|
253
|
-
|
|
254
|
-
if (diff) {
|
|
255
|
-
const { added, removed } = diff
|
|
256
|
-
|
|
257
|
-
removed.forEach((k) => delete element.dataset[k])
|
|
258
|
-
added.forEach(([k, v]) => element.dataset[k] = v)
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
),
|
|
262
|
-
element.dataset
|
|
263
|
-
)
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
static server(index: number, commit: DataPartImpl["commit"]) {
|
|
267
|
-
return new DataPartImpl(index, commit, null)
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
function diffDataSet(
|
|
272
|
-
a: Record<string, string | undefined> | null | undefined,
|
|
273
|
-
b: Record<string, string | undefined> | null | undefined
|
|
274
|
-
):
|
|
275
|
-
| { added: Array<readonly [string, string | undefined]>; removed: ReadonlyArray<string> }
|
|
276
|
-
| null
|
|
277
|
-
{
|
|
278
|
-
if (!a) return b ? { added: Object.entries(b), removed: [] } : null
|
|
279
|
-
if (!b) return { added: [], removed: Object.keys(a) }
|
|
280
|
-
|
|
281
|
-
const { added, removed, unchanged } = diffStrings(Object.keys(a), Object.keys(b))
|
|
282
|
-
|
|
283
|
-
return {
|
|
284
|
-
added: added.concat(unchanged).map((k) => [k, b[k]] as const),
|
|
285
|
-
removed
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
export class EventPartImpl implements EventPart {
|
|
290
|
-
readonly _tag = "event"
|
|
291
|
-
readonly value: EventPart["value"] = null
|
|
292
|
-
|
|
293
|
-
constructor(
|
|
294
|
-
readonly name: string,
|
|
295
|
-
readonly index: number,
|
|
296
|
-
readonly source: ElementSource<any>,
|
|
297
|
-
readonly onCause: <E>(cause: Cause<E>) => Effect.Effect<unknown>,
|
|
298
|
-
readonly addEventListener: <Ev extends Event>(handler: EventHandler<Ev>) => void
|
|
299
|
-
) {
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
export class NodePartImpl extends base("node") implements NodePart {}
|
|
304
|
-
|
|
305
|
-
export class PropertyPartImpl extends base("property") implements PropertyPart {
|
|
306
|
-
constructor(
|
|
307
|
-
readonly name: string,
|
|
308
|
-
index: number,
|
|
309
|
-
commit: PropertyPartImpl["commit"],
|
|
310
|
-
value: PropertyPartImpl["value"]
|
|
311
|
-
) {
|
|
312
|
-
super(index, commit, value, strictEq)
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
static browser(index: number, node: Node, name: string, ctx: RenderContext) {
|
|
316
|
-
const existing = (node as Element).getAttribute(name)
|
|
317
|
-
|
|
318
|
-
return new PropertyPartImpl(
|
|
319
|
-
name,
|
|
320
|
-
index,
|
|
321
|
-
({ part, value }) => ctx.queue.add(part, () => (node as any)[name] = value),
|
|
322
|
-
existing ? unescape(existing) : null
|
|
323
|
-
)
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
export class RefPartImpl implements RefPart {
|
|
328
|
-
readonly _tag = "ref"
|
|
329
|
-
|
|
330
|
-
constructor(readonly value: ElementSource<any>, readonly index: number) {}
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
export class TextPartImpl extends base("text") implements TextPart {
|
|
334
|
-
// TODO: Make this properly
|
|
335
|
-
static browser(document: Document, index: number, element: Element, ctx: RenderContext) {
|
|
336
|
-
const comment = findHoleComment(element, index)
|
|
337
|
-
const text = document.createTextNode("")
|
|
338
|
-
element.insertBefore(text, comment)
|
|
339
|
-
|
|
340
|
-
return new TextPartImpl(
|
|
341
|
-
index,
|
|
342
|
-
({ part, value }) => ctx.queue.add(part, () => text.nodeValue = value ?? null),
|
|
343
|
-
text.nodeValue,
|
|
344
|
-
strictEq
|
|
345
|
-
)
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
static fromText(text: Text, index: number, ctx: RenderContext) {
|
|
349
|
-
return new TextPartImpl(
|
|
350
|
-
index,
|
|
351
|
-
({ part, value }) => ctx.queue.add(part, () => text.nodeValue = value ?? null),
|
|
352
|
-
text.nodeValue,
|
|
353
|
-
strictEq
|
|
354
|
-
)
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
static getOrCreateText(document: Document, index: number, element: Element) {
|
|
358
|
-
const comment = findHoleComment(element, index)
|
|
359
|
-
|
|
360
|
-
return comment.previousSibling && isText(comment.previousSibling)
|
|
361
|
-
? comment.previousSibling.nodeValue
|
|
362
|
-
: document.createTextNode("")
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
export class PropertiesPartImpl extends base("properties") implements PropertiesPart {
|
|
367
|
-
constructor(
|
|
368
|
-
index: number,
|
|
369
|
-
commit: PropertiesPartImpl["commit"],
|
|
370
|
-
value: PropertiesPartImpl["value"]
|
|
371
|
-
) {
|
|
372
|
-
super(index, commit, value, equals)
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
getValue(value: unknown): unknown {
|
|
376
|
-
if (value == null) return null
|
|
377
|
-
return Data.struct(value)
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
static browser(index: number, element: HTMLElement | SVGElement, ctx: RenderContext) {
|
|
381
|
-
return new PropertiesPartImpl(
|
|
382
|
-
index,
|
|
383
|
-
({ part, previous, value }) =>
|
|
384
|
-
ctx.queue.add(
|
|
385
|
-
part,
|
|
386
|
-
() => {
|
|
387
|
-
const diff = diffProperties(previous, value)
|
|
388
|
-
if (diff) {
|
|
389
|
-
const { added, removed } = diff
|
|
390
|
-
|
|
391
|
-
removed.forEach((nv) => removeNameValue(element, nv))
|
|
392
|
-
added.forEach((nv) => {
|
|
393
|
-
if ((nv.name[0] === "o" && nv.name[1] === "n") || nv.name[0] === "@") return
|
|
394
|
-
|
|
395
|
-
return addNameValue(element, nv)
|
|
396
|
-
})
|
|
397
|
-
}
|
|
398
|
-
}
|
|
399
|
-
),
|
|
400
|
-
{}
|
|
401
|
-
)
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
function removeNameValue(element: HTMLElement | SVGElement, { name, type }: NameValue) {
|
|
406
|
-
switch (type) {
|
|
407
|
-
case "attr":
|
|
408
|
-
case "bool":
|
|
409
|
-
return element.removeAttribute(name)
|
|
410
|
-
case "prop":
|
|
411
|
-
return delete (element as any)[name]
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
function addNameValue(element: HTMLElement | SVGElement, { name, type, value }: NameValue) {
|
|
416
|
-
switch (type) {
|
|
417
|
-
case "attr":
|
|
418
|
-
return value == null ? element.removeAttribute(name) : element.setAttribute(name, value)
|
|
419
|
-
case "bool":
|
|
420
|
-
return value == null ? element.removeAttribute(name) : element.toggleAttribute(name, value)
|
|
421
|
-
case "prop":
|
|
422
|
-
return value == null ? (delete (element as any)[name]) : (element as any)[name] = value
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
type AttrNameValue = {
|
|
427
|
-
readonly type: "attr"
|
|
428
|
-
readonly name: string
|
|
429
|
-
readonly value: string
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
type BoolAttrNameValue = {
|
|
433
|
-
readonly type: "bool"
|
|
434
|
-
readonly name: string
|
|
435
|
-
readonly value: boolean
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
type PropNameValue = {
|
|
439
|
-
readonly type: "prop"
|
|
440
|
-
readonly name: string
|
|
441
|
-
readonly value: unknown
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
type NameValue = AttrNameValue | BoolAttrNameValue | PropNameValue
|
|
445
|
-
|
|
446
|
-
function diffProperties(
|
|
447
|
-
a: Record<string, unknown> | null | undefined,
|
|
448
|
-
b: Record<string, unknown> | null | undefined
|
|
449
|
-
): { added: Array<NameValue>; removed: ReadonlyArray<NameValue> } | null {
|
|
450
|
-
if (!a) {
|
|
451
|
-
if (b) {
|
|
452
|
-
return { added: Object.entries(b).flatMap(([k, v]) => fromKeyValue(k, v)), removed: [] }
|
|
453
|
-
} else return null
|
|
454
|
-
} else if (!b) {
|
|
455
|
-
return { added: [], removed: Object.entries(a).flatMap(([k, v]) => fromKeyValue(k, v)) }
|
|
456
|
-
} else {
|
|
457
|
-
const { added, removed, unchanged } = diffStrings(Object.keys(a), Object.keys(b))
|
|
458
|
-
|
|
459
|
-
return {
|
|
460
|
-
added: added.concat(unchanged).flatMap((k) => fromKeyValue(k, b[k])),
|
|
461
|
-
removed: removed.flatMap((k) => fromKeyValue(k, a[k]))
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
function fromKeyValue(name: string, value: unknown): Array<NameValue> {
|
|
467
|
-
if (name[0] === ".") {
|
|
468
|
-
return value == null ? [] : [{
|
|
469
|
-
type: "prop",
|
|
470
|
-
name: name.slice(1),
|
|
471
|
-
value
|
|
472
|
-
}]
|
|
473
|
-
} else if (typeof value === "boolean") {
|
|
474
|
-
return [{
|
|
475
|
-
type: "bool",
|
|
476
|
-
name,
|
|
477
|
-
value
|
|
478
|
-
}]
|
|
479
|
-
} else {
|
|
480
|
-
if (name[0] === "o" || name[1] === "n") return []
|
|
481
|
-
|
|
482
|
-
return value == null ? [] : [{
|
|
483
|
-
type: "attr",
|
|
484
|
-
name,
|
|
485
|
-
value: String(value)
|
|
486
|
-
}]
|
|
487
|
-
}
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
const sparse = <T extends SparsePart["_tag"]>(tag: T) => (class Base {
|
|
491
|
-
readonly _tag: T = tag
|
|
492
|
-
|
|
493
|
-
constructor(
|
|
494
|
-
readonly commit: (
|
|
495
|
-
params: {
|
|
496
|
-
previous: SparseAttributeValues<Extract<SparsePart, { readonly _tag: T }>["parts"]>
|
|
497
|
-
value: SparseAttributeValues<Extract<SparsePart, { readonly _tag: T }>["parts"]>
|
|
498
|
-
part: Extract<SparsePart, { readonly _tag: T }>
|
|
499
|
-
}
|
|
500
|
-
) => Effect.Effect<void, never, Scope>,
|
|
501
|
-
public value: SparseAttributeValues<Extract<SparsePart, { readonly _tag: T }>["parts"]>,
|
|
502
|
-
readonly eq: Equivalence.Equivalence<SparseAttributeValues<Extract<SparsePart, { readonly _tag: T }>["parts"]>> =
|
|
503
|
-
equals
|
|
504
|
-
) {}
|
|
505
|
-
|
|
506
|
-
update = (value: this["value"]) => {
|
|
507
|
-
if (this.eq(this.value as any, value as any)) {
|
|
508
|
-
return Effect.unit
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
return this.commit({
|
|
512
|
-
previous: this.value,
|
|
513
|
-
value: this.value = value as any,
|
|
514
|
-
part: this
|
|
515
|
-
} as any)
|
|
516
|
-
}
|
|
517
|
-
})
|
|
518
|
-
|
|
519
|
-
type SparseAttributeValues<T extends ReadonlyArray<AttributePart | ClassNamePart | CommentPart | StaticText>> =
|
|
520
|
-
ReadonlyArray<
|
|
521
|
-
SparseAttributeValue<T[number]>
|
|
522
|
-
>
|
|
523
|
-
type SparseAttributeValue<T extends AttributePart | ClassNamePart | CommentPart | StaticText> = T["value"]
|
|
524
|
-
|
|
525
|
-
export class SparseAttributePartImpl extends sparse("sparse/attribute") implements SparseAttributePart {
|
|
526
|
-
constructor(
|
|
527
|
-
readonly name: string,
|
|
528
|
-
readonly parts: ReadonlyArray<AttributePart | StaticText>,
|
|
529
|
-
commit: SparseAttributePartImpl["commit"]
|
|
530
|
-
) {
|
|
531
|
-
super(commit, [], ReadonlyArray.getEquivalence(strictEq))
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
static browser(
|
|
535
|
-
name: string,
|
|
536
|
-
parts: ReadonlyArray<AttributePart | StaticText>,
|
|
537
|
-
element: HTMLElement | SVGElement,
|
|
538
|
-
ctx: RenderContext
|
|
539
|
-
) {
|
|
540
|
-
return new SparseAttributePartImpl(
|
|
541
|
-
name,
|
|
542
|
-
parts,
|
|
543
|
-
({ part, value }) =>
|
|
544
|
-
ctx.queue.add(part, () => element.setAttribute(name, value.flatMap((s) => isNonEmptyString(s, true)).join("")))
|
|
545
|
-
)
|
|
546
|
-
}
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
export class SparseClassNamePartImpl extends sparse("sparse/className") implements SparseClassNamePart {
|
|
550
|
-
constructor(
|
|
551
|
-
readonly parts: ReadonlyArray<ClassNamePart | StaticText>,
|
|
552
|
-
commit: SparseClassNamePartImpl["commit"],
|
|
553
|
-
values: Array<string | Array<string>>
|
|
554
|
-
) {
|
|
555
|
-
super(commit, values, ReadonlyArray.getEquivalence(strictEq))
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
static browser(
|
|
559
|
-
parts: ReadonlyArray<ClassNamePart | StaticText>,
|
|
560
|
-
element: HTMLElement | SVGElement,
|
|
561
|
-
ctx: RenderContext,
|
|
562
|
-
values: Array<string | Array<string>> = []
|
|
563
|
-
) {
|
|
564
|
-
return new SparseClassNamePartImpl(
|
|
565
|
-
parts,
|
|
566
|
-
({ part, value }) =>
|
|
567
|
-
ctx.queue.add(part, () => {
|
|
568
|
-
return element.setAttribute("class", value.flatMap((s) => isNonEmptyString(s, true)).join(" "))
|
|
569
|
-
}),
|
|
570
|
-
values
|
|
571
|
-
)
|
|
572
|
-
}
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
export class SparseCommentPartImpl extends sparse("sparse/comment") implements SparseCommentPart {
|
|
576
|
-
constructor(
|
|
577
|
-
readonly parts: ReadonlyArray<CommentPart | StaticText>,
|
|
578
|
-
commit: SparseCommentPartImpl["commit"],
|
|
579
|
-
value: SparseCommentPartImpl["value"]
|
|
580
|
-
) {
|
|
581
|
-
super(commit, value, ReadonlyArray.getEquivalence(strictEq))
|
|
582
|
-
}
|
|
583
|
-
|
|
584
|
-
static browser(comment: Comment, parts: ReadonlyArray<CommentPart | StaticText>, ctx: RenderContext) {
|
|
585
|
-
return new SparseCommentPartImpl(
|
|
586
|
-
parts,
|
|
587
|
-
({ part, value }) =>
|
|
588
|
-
ctx.queue.add(part, () => comment.nodeValue = value.flatMap((s) => isNonEmptyString(s, false)).join("")),
|
|
589
|
-
[]
|
|
590
|
-
)
|
|
591
|
-
}
|
|
592
|
-
}
|
|
593
|
-
|
|
594
|
-
export class StaticTextImpl implements StaticText {
|
|
595
|
-
readonly _tag = "static/text"
|
|
596
|
-
|
|
597
|
-
constructor(readonly value: string) {}
|
|
598
|
-
}
|
|
599
|
-
|
|
600
|
-
function isNonEmptyString(s: string | ReadonlyArray<string> | null | undefined, trim: boolean): Array<string> {
|
|
601
|
-
if (s == null) return []
|
|
602
|
-
if (Array.isArray(s)) return s.flatMap((s) => isNonEmptyString(s, trim))
|
|
603
|
-
|
|
604
|
-
const trimmed = trim ? (s as string).trim() : s
|
|
605
|
-
|
|
606
|
-
if (trimmed.length === 0) return []
|
|
607
|
-
|
|
608
|
-
return [trimmed as string]
|
|
609
|
-
}
|