@typed/template 0.1.4 → 0.3.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/Directive/package.json +6 -0
- package/ElementRef/package.json +6 -0
- package/ElementSource/package.json +6 -0
- package/Entry/package.json +6 -0
- package/EventHandler/package.json +6 -0
- package/Html/package.json +6 -0
- package/HtmlChunk/package.json +6 -0
- package/Hydrate/package.json +6 -0
- package/Many/package.json +6 -0
- package/Meta/package.json +6 -0
- package/Parser/package.json +6 -0
- package/Part/package.json +6 -0
- package/Placeholder/package.json +6 -0
- package/Platform/package.json +6 -0
- package/Render/package.json +6 -0
- package/RenderContext/package.json +6 -0
- package/RenderEvent/package.json +6 -0
- package/RenderTemplate/package.json +6 -0
- package/Renderable/package.json +6 -0
- package/Template/package.json +6 -0
- package/TemplateInstance/package.json +6 -0
- package/Test/package.json +6 -0
- package/Vitest/package.json +6 -0
- 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/hydrate.js +49 -50
- 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 +60 -17
- 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 +486 -53
- 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/hydrate.d.ts +5 -5
- 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 +7 -7
- 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/hydrate.js +45 -46
- 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 +84 -17
- 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 +476 -58
- 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 +49 -21
- 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/hydrate.ts +68 -61
- package/src/internal/indexRefCounter.ts +63 -2
- package/src/internal/module-augmentation.ts +0 -4
- package/src/internal/parser.ts +92 -19
- package/src/internal/parts.ts +158 -73
- package/src/internal/render.ts +701 -89
- package/src/internal/server.ts +5 -3
- 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
package/src/internal/parts.ts
CHANGED
|
@@ -1,18 +1,13 @@
|
|
|
1
|
-
import
|
|
2
|
-
import * as Fx from "@typed/fx/Fx"
|
|
3
|
-
import { WithContext } from "@typed/fx/Sink"
|
|
4
|
-
import { isText, type Rendered } from "@typed/wire"
|
|
1
|
+
import { isText } from "@typed/wire"
|
|
5
2
|
import type { Cause } from "effect/Cause"
|
|
3
|
+
import * as Data from "effect/Data"
|
|
6
4
|
import * as Effect from "effect/Effect"
|
|
7
5
|
import { equals } from "effect/Equal"
|
|
8
|
-
import
|
|
9
|
-
import type { Equivalence } from "effect/Equivalence"
|
|
10
|
-
import * as Fiber from "effect/Fiber"
|
|
6
|
+
import * as Equivalence from "effect/Equivalence"
|
|
11
7
|
import * as ReadonlyArray from "effect/ReadonlyArray"
|
|
12
8
|
import type { Scope } from "effect/Scope"
|
|
13
|
-
import * as SynchronizedRef from "effect/SynchronizedRef"
|
|
14
|
-
import type { ElementRef } from "../ElementRef.js"
|
|
15
9
|
import type { ElementSource } from "../ElementSource.js"
|
|
10
|
+
import type { EventHandler } from "../EventHandler.js"
|
|
16
11
|
import { unescape } from "../HtmlChunk.js"
|
|
17
12
|
import type {
|
|
18
13
|
AttributePart,
|
|
@@ -23,6 +18,7 @@ import type {
|
|
|
23
18
|
EventPart,
|
|
24
19
|
NodePart,
|
|
25
20
|
Part,
|
|
21
|
+
PropertiesPart,
|
|
26
22
|
PropertyPart,
|
|
27
23
|
RefPart,
|
|
28
24
|
SparseAttributePart,
|
|
@@ -35,7 +31,7 @@ import type {
|
|
|
35
31
|
import type { RenderContext } from "../RenderContext.js"
|
|
36
32
|
import { findHoleComment } from "./utils.js"
|
|
37
33
|
|
|
38
|
-
const strictEq = strict<any>()
|
|
34
|
+
const strictEq = Equivalence.strict<any>()
|
|
39
35
|
|
|
40
36
|
const base = <T extends Part["_tag"]>(tag: T) =>
|
|
41
37
|
class Base {
|
|
@@ -51,7 +47,7 @@ const base = <T extends Part["_tag"]>(tag: T) =>
|
|
|
51
47
|
}
|
|
52
48
|
) => Effect.Effect<Scope, never, void>,
|
|
53
49
|
public value: Extract<Part, { readonly _tag: T }>["value"],
|
|
54
|
-
readonly eq: Equivalence<Extract<Part, { readonly _tag: T }>["value"]> = equals
|
|
50
|
+
readonly eq: Equivalence.Equivalence<Extract<Part, { readonly _tag: T }>["value"]> = equals
|
|
55
51
|
) {
|
|
56
52
|
this.update = this.update.bind(this)
|
|
57
53
|
}
|
|
@@ -64,7 +60,7 @@ const base = <T extends Part["_tag"]>(tag: T) =>
|
|
|
64
60
|
return Effect.unit
|
|
65
61
|
}
|
|
66
62
|
|
|
67
|
-
return Effect.
|
|
63
|
+
return Effect.flatMap(
|
|
68
64
|
this.commit.call(this, {
|
|
69
65
|
previous,
|
|
70
66
|
value,
|
|
@@ -291,73 +287,20 @@ function diffDataSet(
|
|
|
291
287
|
}
|
|
292
288
|
}
|
|
293
289
|
|
|
294
|
-
export class EventPartImpl
|
|
290
|
+
export class EventPartImpl implements EventPart {
|
|
291
|
+
readonly _tag = "event"
|
|
292
|
+
readonly value: EventPart["value"] = null
|
|
293
|
+
|
|
295
294
|
constructor(
|
|
296
295
|
readonly name: string,
|
|
296
|
+
readonly index: number,
|
|
297
|
+
readonly source: ElementSource<any>,
|
|
297
298
|
readonly onCause: <E>(cause: Cause<E>) => Effect.Effect<never, never, unknown>,
|
|
298
|
-
|
|
299
|
-
commit: EventPartImpl["commit"],
|
|
300
|
-
value: EventPart["value"]
|
|
299
|
+
readonly addEventListener: <Ev extends Event>(handler: EventHandler<never, never, Ev>) => void
|
|
301
300
|
) {
|
|
302
|
-
super(index, commit, value, strictEq)
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
static browser<T extends Rendered, E>(
|
|
306
|
-
name: string,
|
|
307
|
-
index: number,
|
|
308
|
-
ref: ElementRef<T>,
|
|
309
|
-
element: HTMLElement | SVGElement,
|
|
310
|
-
onCause: (cause: Cause<E>) => Effect.Effect<never, never, unknown>
|
|
311
|
-
): Effect.Effect<unknown, never, void> {
|
|
312
|
-
return withSwitchFork((fork, ctx) => {
|
|
313
|
-
const source = ref.query(element)
|
|
314
|
-
|
|
315
|
-
return Effect.succeed(
|
|
316
|
-
new EventPartImpl(
|
|
317
|
-
name,
|
|
318
|
-
onCause as any,
|
|
319
|
-
index,
|
|
320
|
-
({ value }) => {
|
|
321
|
-
return value
|
|
322
|
-
? Fx.run(
|
|
323
|
-
source.events(name as keyof HTMLElementEventMap | keyof SVGElementEventMap, value.options),
|
|
324
|
-
WithContext(onCause, value.handler)
|
|
325
|
-
).pipe(
|
|
326
|
-
Effect.provide(ctx),
|
|
327
|
-
fork
|
|
328
|
-
)
|
|
329
|
-
: fork(Effect.unit)
|
|
330
|
-
},
|
|
331
|
-
null
|
|
332
|
-
)
|
|
333
|
-
)
|
|
334
|
-
})
|
|
335
301
|
}
|
|
336
302
|
}
|
|
337
303
|
|
|
338
|
-
function withScopedFork<R, E, A>(f: (fork: Fx.ScopedFork) => Effect.Effect<R, E, A>): Effect.Effect<R | Scope, E, A> {
|
|
339
|
-
return Effect.scopeWith((scope) => f(Effect.forkIn(scope)))
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
// Ensures only a single fiber is executing
|
|
343
|
-
function withSwitchFork<R, E, A>(
|
|
344
|
-
f: (fork: Fx.FxFork, ctx: Context<R | Scope>) => Effect.Effect<R, E, A>
|
|
345
|
-
): Effect.Effect<R | Scope, E, A> {
|
|
346
|
-
return Effect.contextWithEffect((ctx) =>
|
|
347
|
-
withScopedFork((fork) =>
|
|
348
|
-
Effect.flatMap(
|
|
349
|
-
SynchronizedRef.make<Fiber.Fiber<never, void>>(Fiber.unit),
|
|
350
|
-
(ref) =>
|
|
351
|
-
f((effect) =>
|
|
352
|
-
SynchronizedRef.updateAndGetEffect(
|
|
353
|
-
ref,
|
|
354
|
-
(fiber) => Effect.flatMap(Fiber.interrupt(fiber), () => fork(effect))
|
|
355
|
-
), ctx)
|
|
356
|
-
)
|
|
357
|
-
)
|
|
358
|
-
)
|
|
359
|
-
}
|
|
360
|
-
|
|
361
304
|
export class NodePartImpl extends base("node") implements NodePart {}
|
|
362
305
|
|
|
363
306
|
export class PropertyPartImpl extends base("property") implements PropertyPart {
|
|
@@ -403,6 +346,147 @@ export class TextPartImpl extends base("text") implements TextPart {
|
|
|
403
346
|
strictEq
|
|
404
347
|
)
|
|
405
348
|
}
|
|
349
|
+
|
|
350
|
+
static fromText(text: Text, index: number, ctx: RenderContext) {
|
|
351
|
+
return new TextPartImpl(
|
|
352
|
+
index,
|
|
353
|
+
({ part, value }) => ctx.queue.add(part, () => text.nodeValue = value ?? null),
|
|
354
|
+
text.nodeValue,
|
|
355
|
+
strictEq
|
|
356
|
+
)
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
static getOrCreateText(document: Document, index: number, element: Element) {
|
|
360
|
+
const comment = findHoleComment(element, index)
|
|
361
|
+
|
|
362
|
+
return comment.previousSibling && isText(comment.previousSibling)
|
|
363
|
+
? comment.previousSibling.nodeValue
|
|
364
|
+
: document.createTextNode("")
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
export class PropertiesPartImpl extends base("properties") implements PropertiesPart {
|
|
369
|
+
constructor(
|
|
370
|
+
index: number,
|
|
371
|
+
commit: PropertiesPartImpl["commit"],
|
|
372
|
+
value: PropertiesPartImpl["value"]
|
|
373
|
+
) {
|
|
374
|
+
super(index, commit, value, equals)
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
getValue(value: unknown): unknown {
|
|
378
|
+
if (value == null) return null
|
|
379
|
+
return Data.struct(value)
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
static browser(index: number, element: HTMLElement | SVGElement, ctx: RenderContext) {
|
|
383
|
+
return new PropertiesPartImpl(
|
|
384
|
+
index,
|
|
385
|
+
({ part, previous, value }) =>
|
|
386
|
+
ctx.queue.add(
|
|
387
|
+
part,
|
|
388
|
+
() => {
|
|
389
|
+
const diff = diffProperties(previous, value)
|
|
390
|
+
if (diff) {
|
|
391
|
+
const { added, removed } = diff
|
|
392
|
+
|
|
393
|
+
removed.forEach((nv) => removeNameValue(element, nv))
|
|
394
|
+
added.forEach((nv) => {
|
|
395
|
+
if ((nv.name[0] === "o" && nv.name[1] === "n") || nv.name[0] === "@") return
|
|
396
|
+
|
|
397
|
+
return addNameValue(element, nv)
|
|
398
|
+
})
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
),
|
|
402
|
+
{}
|
|
403
|
+
)
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
function removeNameValue(element: HTMLElement | SVGElement, { name, type }: NameValue) {
|
|
408
|
+
switch (type) {
|
|
409
|
+
case "attr":
|
|
410
|
+
case "bool":
|
|
411
|
+
return element.removeAttribute(name)
|
|
412
|
+
case "prop":
|
|
413
|
+
return delete (element as any)[name]
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
function addNameValue(element: HTMLElement | SVGElement, { name, type, value }: NameValue) {
|
|
418
|
+
switch (type) {
|
|
419
|
+
case "attr":
|
|
420
|
+
return value == null ? element.removeAttribute(name) : element.setAttribute(name, value)
|
|
421
|
+
case "bool":
|
|
422
|
+
return value == null ? element.removeAttribute(name) : element.toggleAttribute(name, value)
|
|
423
|
+
case "prop":
|
|
424
|
+
return value == null ? (delete (element as any)[name]) : (element as any)[name] = value
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
type AttrNameValue = {
|
|
429
|
+
readonly type: "attr"
|
|
430
|
+
readonly name: string
|
|
431
|
+
readonly value: string
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
type BoolAttrNameValue = {
|
|
435
|
+
readonly type: "bool"
|
|
436
|
+
readonly name: string
|
|
437
|
+
readonly value: boolean
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
type PropNameValue = {
|
|
441
|
+
readonly type: "prop"
|
|
442
|
+
readonly name: string
|
|
443
|
+
readonly value: unknown
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
type NameValue = AttrNameValue | BoolAttrNameValue | PropNameValue
|
|
447
|
+
|
|
448
|
+
function diffProperties(
|
|
449
|
+
a: Record<string, unknown> | null | undefined,
|
|
450
|
+
b: Record<string, unknown> | null | undefined
|
|
451
|
+
): { added: Array<NameValue>; removed: ReadonlyArray<NameValue> } | null {
|
|
452
|
+
if (!a) {
|
|
453
|
+
if (b) {
|
|
454
|
+
return { added: Object.entries(b).flatMap(([k, v]) => fromKeyValue(k, v)), removed: [] }
|
|
455
|
+
} else return null
|
|
456
|
+
} else if (!b) {
|
|
457
|
+
return { added: [], removed: Object.entries(a).flatMap(([k, v]) => fromKeyValue(k, v)) }
|
|
458
|
+
} else {
|
|
459
|
+
const { added, removed, unchanged } = diffStrings(Object.keys(a), Object.keys(b))
|
|
460
|
+
|
|
461
|
+
return {
|
|
462
|
+
added: added.concat(unchanged).flatMap((k) => fromKeyValue(k, b[k])),
|
|
463
|
+
removed: removed.flatMap((k) => fromKeyValue(k, a[k]))
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
function fromKeyValue(name: string, value: unknown): Array<NameValue> {
|
|
469
|
+
if (name[0] === ".") {
|
|
470
|
+
return value == null ? [] : [{
|
|
471
|
+
type: "prop",
|
|
472
|
+
name: name.slice(1),
|
|
473
|
+
value
|
|
474
|
+
}]
|
|
475
|
+
} else if (typeof value === "boolean") {
|
|
476
|
+
return [{
|
|
477
|
+
type: "bool",
|
|
478
|
+
name,
|
|
479
|
+
value
|
|
480
|
+
}]
|
|
481
|
+
} else {
|
|
482
|
+
if (name[0] === "o" || name[1] === "n") return []
|
|
483
|
+
|
|
484
|
+
return value == null ? [] : [{
|
|
485
|
+
type: "attr",
|
|
486
|
+
name,
|
|
487
|
+
value: String(value)
|
|
488
|
+
}]
|
|
489
|
+
}
|
|
406
490
|
}
|
|
407
491
|
|
|
408
492
|
const sparse = <T extends SparsePart["_tag"]>(tag: T) =>
|
|
@@ -418,7 +502,8 @@ const sparse = <T extends SparsePart["_tag"]>(tag: T) =>
|
|
|
418
502
|
}
|
|
419
503
|
) => Effect.Effect<Scope, never, void>,
|
|
420
504
|
public value: SparseAttributeValues<Extract<SparsePart, { readonly _tag: T }>["parts"]>,
|
|
421
|
-
readonly eq: Equivalence<SparseAttributeValues<Extract<SparsePart, { readonly _tag: T }>["parts"]>> =
|
|
505
|
+
readonly eq: Equivalence.Equivalence<SparseAttributeValues<Extract<SparsePart, { readonly _tag: T }>["parts"]>> =
|
|
506
|
+
equals
|
|
422
507
|
) {}
|
|
423
508
|
|
|
424
509
|
update = (value: this["value"]) => {
|