@typed/template 0.14.0 → 1.0.0-beta.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/README.md +108 -2
- package/dist/EventHandler.d.ts +273 -0
- package/dist/EventHandler.d.ts.map +1 -0
- package/dist/EventHandler.js +261 -0
- package/dist/EventSource.d.ts +82 -0
- package/dist/EventSource.d.ts.map +1 -0
- package/dist/EventSource.js +127 -0
- package/dist/Html.d.ts +122 -0
- package/dist/Html.d.ts.map +1 -0
- package/dist/Html.js +250 -0
- package/dist/HtmlChunk.d.ts +118 -0
- package/dist/HtmlChunk.d.ts.map +1 -0
- package/dist/HtmlChunk.js +211 -0
- package/dist/HydrateContext.d.ts +28 -0
- package/dist/HydrateContext.d.ts.map +1 -0
- package/dist/HydrateContext.js +25 -0
- package/dist/Parser.d.ts +35 -0
- package/dist/Parser.d.ts.map +1 -0
- package/dist/Parser.js +437 -0
- package/dist/Render.d.ts +195 -0
- package/dist/Render.d.ts.map +1 -0
- package/dist/Render.js +609 -0
- package/dist/RenderEvent.d.ts +179 -0
- package/dist/RenderEvent.d.ts.map +1 -0
- package/dist/RenderEvent.js +102 -0
- package/dist/RenderQueue.d.ts +167 -0
- package/dist/RenderQueue.d.ts.map +1 -0
- package/dist/RenderQueue.js +297 -0
- package/dist/RenderTemplate.d.ts +90 -0
- package/dist/RenderTemplate.d.ts.map +1 -0
- package/dist/RenderTemplate.js +87 -0
- package/dist/Renderable.d.ts +88 -0
- package/dist/Renderable.d.ts.map +1 -0
- package/dist/Renderable.js +3 -0
- package/dist/{dts/Template.d.ts → Template.d.ts} +109 -74
- package/dist/Template.d.ts.map +1 -0
- package/dist/{esm/Template.js → Template.js} +96 -56
- package/dist/Wire.d.ts +169 -0
- package/dist/Wire.d.ts.map +1 -0
- package/dist/Wire.js +217 -0
- package/dist/errors.d.ts +145 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +159 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/internal/IndexRefCounter.d.ts +11 -0
- package/dist/internal/IndexRefCounter.d.ts.map +1 -0
- package/dist/internal/IndexRefCounter.js +42 -0
- package/dist/internal/ParentChildNodes.d.ts +6 -0
- package/dist/internal/ParentChildNodes.d.ts.map +1 -0
- package/dist/internal/ParentChildNodes.js +1 -0
- package/dist/internal/PathStack.d.ts +9 -0
- package/dist/internal/PathStack.d.ts.map +1 -0
- package/dist/internal/PathStack.js +18 -0
- package/dist/internal/buildTemplateFragement.d.ts +3 -0
- package/dist/internal/buildTemplateFragement.d.ts.map +1 -0
- package/dist/internal/buildTemplateFragement.js +61 -0
- package/dist/internal/diff.d.ts +2 -0
- package/dist/internal/diff.d.ts.map +1 -0
- package/dist/internal/diff.js +119 -0
- package/dist/internal/dom.d.ts +45 -0
- package/dist/internal/dom.d.ts.map +1 -0
- package/dist/internal/dom.js +304 -0
- package/dist/internal/encoding.d.ts +7 -0
- package/dist/internal/encoding.d.ts.map +1 -0
- package/dist/internal/encoding.js +134 -0
- package/dist/{dts/internal/v2/hydration-template.d.ts → internal/hydration.d.ts} +10 -7
- package/dist/internal/hydration.d.ts.map +1 -0
- package/dist/{esm/internal/v2/hydration-template.js → internal/hydration.js} +80 -26
- package/dist/internal/keyToPartType.d.ts +2 -0
- package/dist/internal/keyToPartType.d.ts.map +1 -0
- package/dist/internal/keyToPartType.js +110 -0
- package/dist/internal/meta.d.ts +17 -0
- package/dist/internal/meta.d.ts.map +1 -0
- package/dist/internal/meta.js +14 -0
- package/dist/internal/takeOneIfNotRenderEvent.d.ts +4 -0
- package/dist/internal/takeOneIfNotRenderEvent.d.ts.map +1 -0
- package/dist/internal/takeOneIfNotRenderEvent.js +10 -0
- package/dist/internal/templateHash.d.ts +2 -0
- package/dist/internal/templateHash.d.ts.map +1 -0
- package/dist/internal/templateHash.js +14 -0
- package/dist/many.d.ts +68 -0
- package/dist/many.d.ts.map +1 -0
- package/dist/many.js +107 -0
- package/package.json +22 -224
- package/src/EventHandler.ts +318 -86
- package/src/EventSource.ts +202 -0
- package/src/Html.test.ts +490 -0
- package/src/Html.ts +292 -333
- package/src/HtmlChunk.ts +290 -332
- package/src/HydrateContext.ts +40 -0
- package/src/Hydration.test.ts +409 -0
- package/src/Parser.test.ts +924 -0
- package/src/Parser.ts +598 -10
- package/src/Render.test.ts +338 -0
- package/src/Render.ts +878 -63
- package/src/RenderEvent.ts +169 -40
- package/src/RenderQueue.ts +290 -385
- package/src/RenderTemplate.ts +98 -31
- package/src/Renderable.ts +122 -24
- package/src/Template.ts +246 -145
- package/src/Wire.ts +309 -0
- package/src/errors.ts +173 -0
- package/src/index.ts +14 -66
- package/src/internal/IndexRefCounter.ts +53 -0
- package/src/internal/ParentChildNodes.ts +7 -0
- package/src/internal/PathStack.ts +23 -0
- package/src/internal/buildTemplateFragement.ts +82 -0
- package/src/internal/diff.ts +127 -0
- package/src/internal/dom.ts +357 -0
- package/src/internal/encoding.ts +147 -0
- package/src/internal/hydration.ts +406 -0
- package/src/internal/keyToPartType.ts +113 -0
- package/src/internal/meta.ts +25 -0
- package/src/internal/takeOneIfNotRenderEvent.ts +19 -0
- package/src/internal/templateHash.ts +18 -0
- package/src/many.ts +148 -0
- package/tsconfig.json +6 -0
- package/Directive/package.json +0 -6
- package/ElementRef/package.json +0 -6
- package/ElementSource/package.json +0 -6
- package/Entry/package.json +0 -6
- package/EventHandler/package.json +0 -6
- package/Html/package.json +0 -6
- package/HtmlChunk/package.json +0 -6
- package/Hydrate/package.json +0 -6
- package/LICENSE +0 -21
- package/Many/package.json +0 -6
- package/Meta/package.json +0 -6
- package/Parser/package.json +0 -6
- package/Part/package.json +0 -6
- package/Placeholder/package.json +0 -6
- package/Platform/package.json +0 -6
- package/Render/package.json +0 -6
- package/RenderContext/package.json +0 -6
- package/RenderEvent/package.json +0 -6
- package/RenderQueue/package.json +0 -6
- package/RenderTemplate/package.json +0 -6
- package/Renderable/package.json +0 -6
- package/Template/package.json +0 -6
- package/Test/package.json +0 -6
- package/Vitest/package.json +0 -6
- package/compiler-tools/package.json +0 -6
- package/dist/cjs/Directive.js +0 -76
- package/dist/cjs/Directive.js.map +0 -1
- package/dist/cjs/ElementRef.js +0 -92
- package/dist/cjs/ElementRef.js.map +0 -1
- package/dist/cjs/ElementSource.js +0 -246
- package/dist/cjs/ElementSource.js.map +0 -1
- package/dist/cjs/Entry.js +0 -6
- package/dist/cjs/Entry.js.map +0 -1
- package/dist/cjs/EventHandler.js +0 -76
- package/dist/cjs/EventHandler.js.map +0 -1
- package/dist/cjs/Html.js +0 -224
- package/dist/cjs/Html.js.map +0 -1
- package/dist/cjs/HtmlChunk.js +0 -306
- package/dist/cjs/HtmlChunk.js.map +0 -1
- package/dist/cjs/Hydrate.js +0 -43
- package/dist/cjs/Hydrate.js.map +0 -1
- package/dist/cjs/Many.js +0 -66
- package/dist/cjs/Many.js.map +0 -1
- package/dist/cjs/Meta.js +0 -50
- package/dist/cjs/Meta.js.map +0 -1
- package/dist/cjs/Parser.js +0 -19
- package/dist/cjs/Parser.js.map +0 -1
- package/dist/cjs/Part.js +0 -6
- package/dist/cjs/Part.js.map +0 -1
- package/dist/cjs/Placeholder.js +0 -34
- package/dist/cjs/Placeholder.js.map +0 -1
- package/dist/cjs/Platform.js +0 -65
- package/dist/cjs/Platform.js.map +0 -1
- package/dist/cjs/Render.js +0 -50
- package/dist/cjs/Render.js.map +0 -1
- package/dist/cjs/RenderContext.js +0 -67
- package/dist/cjs/RenderContext.js.map +0 -1
- package/dist/cjs/RenderEvent.js +0 -52
- package/dist/cjs/RenderEvent.js.map +0 -1
- package/dist/cjs/RenderQueue.js +0 -343
- package/dist/cjs/RenderQueue.js.map +0 -1
- package/dist/cjs/RenderTemplate.js +0 -26
- package/dist/cjs/RenderTemplate.js.map +0 -1
- package/dist/cjs/Renderable.js +0 -6
- package/dist/cjs/Renderable.js.map +0 -1
- package/dist/cjs/Template.js +0 -305
- package/dist/cjs/Template.js.map +0 -1
- package/dist/cjs/Test.js +0 -184
- package/dist/cjs/Test.js.map +0 -1
- package/dist/cjs/Vitest.js +0 -52
- package/dist/cjs/Vitest.js.map +0 -1
- package/dist/cjs/compiler-tools.js +0 -100
- package/dist/cjs/compiler-tools.js.map +0 -1
- package/dist/cjs/index.js +0 -138
- package/dist/cjs/index.js.map +0 -1
- package/dist/cjs/internal/EventSource.js +0 -129
- package/dist/cjs/internal/EventSource.js.map +0 -1
- package/dist/cjs/internal/HydrateContext.js +0 -13
- package/dist/cjs/internal/HydrateContext.js.map +0 -1
- package/dist/cjs/internal/browser.js +0 -110
- package/dist/cjs/internal/browser.js.map +0 -1
- package/dist/cjs/internal/character-entities.js +0 -2141
- package/dist/cjs/internal/character-entities.js.map +0 -1
- package/dist/cjs/internal/chunks.js +0 -68
- package/dist/cjs/internal/chunks.js.map +0 -1
- package/dist/cjs/internal/errors.js +0 -52
- package/dist/cjs/internal/errors.js.map +0 -1
- package/dist/cjs/internal/indexRefCounter.js +0 -52
- package/dist/cjs/internal/indexRefCounter.js.map +0 -1
- package/dist/cjs/internal/module-augmentation.js +0 -6
- package/dist/cjs/internal/module-augmentation.js.map +0 -1
- package/dist/cjs/internal/parser.js +0 -568
- package/dist/cjs/internal/parser.js.map +0 -1
- package/dist/cjs/internal/parser2.js +0 -382
- package/dist/cjs/internal/parser2.js.map +0 -1
- package/dist/cjs/internal/server-parts.js +0 -124
- package/dist/cjs/internal/server-parts.js.map +0 -1
- package/dist/cjs/internal/server.js +0 -48
- package/dist/cjs/internal/server.js.map +0 -1
- package/dist/cjs/internal/utils.js +0 -136
- package/dist/cjs/internal/utils.js.map +0 -1
- package/dist/cjs/internal/v2/SyncPart.js +0 -6
- package/dist/cjs/internal/v2/SyncPart.js.map +0 -1
- package/dist/cjs/internal/v2/helpers.js +0 -15
- package/dist/cjs/internal/v2/helpers.js.map +0 -1
- package/dist/cjs/internal/v2/hydration-template.js +0 -269
- package/dist/cjs/internal/v2/hydration-template.js.map +0 -1
- package/dist/cjs/internal/v2/parts.js +0 -169
- package/dist/cjs/internal/v2/parts.js.map +0 -1
- package/dist/cjs/internal/v2/render-entry.js +0 -110
- package/dist/cjs/internal/v2/render-entry.js.map +0 -1
- package/dist/cjs/internal/v2/render-sync-parts.js +0 -318
- package/dist/cjs/internal/v2/render-sync-parts.js.map +0 -1
- package/dist/cjs/internal/v2/render.js +0 -592
- package/dist/cjs/internal/v2/render.js.map +0 -1
- package/dist/cjs/internal/v2/sync-parts.js +0 -115
- package/dist/cjs/internal/v2/sync-parts.js.map +0 -1
- package/dist/dts/Directive.d.ts +0 -70
- package/dist/dts/Directive.d.ts.map +0 -1
- package/dist/dts/ElementRef.d.ts +0 -42
- package/dist/dts/ElementRef.d.ts.map +0 -1
- package/dist/dts/ElementSource.d.ts +0 -79
- package/dist/dts/ElementSource.d.ts.map +0 -1
- package/dist/dts/Entry.d.ts +0 -26
- package/dist/dts/Entry.d.ts.map +0 -1
- package/dist/dts/EventHandler.d.ts +0 -73
- package/dist/dts/EventHandler.d.ts.map +0 -1
- package/dist/dts/Html.d.ts +0 -35
- package/dist/dts/Html.d.ts.map +0 -1
- package/dist/dts/HtmlChunk.d.ts +0 -56
- package/dist/dts/HtmlChunk.d.ts.map +0 -1
- package/dist/dts/Hydrate.d.ts +0 -19
- package/dist/dts/Hydrate.d.ts.map +0 -1
- package/dist/dts/Many.d.ts +0 -32
- package/dist/dts/Many.d.ts.map +0 -1
- package/dist/dts/Meta.d.ts +0 -33
- package/dist/dts/Meta.d.ts.map +0 -1
- package/dist/dts/Parser.d.ts +0 -13
- package/dist/dts/Parser.d.ts.map +0 -1
- package/dist/dts/Part.d.ts +0 -121
- package/dist/dts/Part.d.ts.map +0 -1
- package/dist/dts/Placeholder.d.ts +0 -48
- package/dist/dts/Placeholder.d.ts.map +0 -1
- package/dist/dts/Platform.d.ts +0 -21
- package/dist/dts/Platform.d.ts.map +0 -1
- package/dist/dts/Render.d.ts +0 -31
- package/dist/dts/Render.d.ts.map +0 -1
- package/dist/dts/RenderContext.d.ts +0 -70
- package/dist/dts/RenderContext.d.ts.map +0 -1
- package/dist/dts/RenderEvent.d.ts +0 -42
- package/dist/dts/RenderEvent.d.ts.map +0 -1
- package/dist/dts/RenderQueue.d.ts +0 -103
- package/dist/dts/RenderQueue.d.ts.map +0 -1
- package/dist/dts/RenderTemplate.d.ts +0 -25
- package/dist/dts/RenderTemplate.d.ts.map +0 -1
- package/dist/dts/Renderable.d.ts +0 -28
- package/dist/dts/Renderable.d.ts.map +0 -1
- package/dist/dts/Template.d.ts.map +0 -1
- package/dist/dts/Test.d.ts +0 -85
- package/dist/dts/Test.d.ts.map +0 -1
- package/dist/dts/Vitest.d.ts +0 -43
- package/dist/dts/Vitest.d.ts.map +0 -1
- package/dist/dts/compiler-tools.d.ts +0 -143
- package/dist/dts/compiler-tools.d.ts.map +0 -1
- package/dist/dts/index.d.ts +0 -65
- package/dist/dts/index.d.ts.map +0 -1
- package/dist/dts/internal/EventSource.d.ts +0 -13
- package/dist/dts/internal/EventSource.d.ts.map +0 -1
- package/dist/dts/internal/HydrateContext.d.ts +0 -2
- package/dist/dts/internal/HydrateContext.d.ts.map +0 -1
- package/dist/dts/internal/browser.d.ts +0 -8
- package/dist/dts/internal/browser.d.ts.map +0 -1
- package/dist/dts/internal/character-entities.d.ts +0 -2133
- package/dist/dts/internal/character-entities.d.ts.map +0 -1
- package/dist/dts/internal/chunks.d.ts +0 -23
- package/dist/dts/internal/chunks.d.ts.map +0 -1
- package/dist/dts/internal/errors.d.ts +0 -22
- package/dist/dts/internal/errors.d.ts.map +0 -1
- package/dist/dts/internal/indexRefCounter.d.ts +0 -7
- package/dist/dts/internal/indexRefCounter.d.ts.map +0 -1
- package/dist/dts/internal/module-augmentation.d.ts +0 -32
- package/dist/dts/internal/module-augmentation.d.ts.map +0 -1
- package/dist/dts/internal/parser.d.ts +0 -33
- package/dist/dts/internal/parser.d.ts.map +0 -1
- package/dist/dts/internal/parser2.d.ts +0 -12
- package/dist/dts/internal/parser2.d.ts.map +0 -1
- package/dist/dts/internal/server-parts.d.ts +0 -223
- package/dist/dts/internal/server-parts.d.ts.map +0 -1
- package/dist/dts/internal/server.d.ts +0 -5
- package/dist/dts/internal/server.d.ts.map +0 -1
- package/dist/dts/internal/utils.d.ts +0 -19
- package/dist/dts/internal/utils.d.ts.map +0 -1
- package/dist/dts/internal/v2/SyncPart.d.ts +0 -87
- package/dist/dts/internal/v2/SyncPart.d.ts.map +0 -1
- package/dist/dts/internal/v2/helpers.d.ts +0 -3
- package/dist/dts/internal/v2/helpers.d.ts.map +0 -1
- package/dist/dts/internal/v2/hydration-template.d.ts.map +0 -1
- package/dist/dts/internal/v2/parts.d.ts +0 -245
- package/dist/dts/internal/v2/parts.d.ts.map +0 -1
- package/dist/dts/internal/v2/render-entry.d.ts +0 -6
- package/dist/dts/internal/v2/render-entry.d.ts.map +0 -1
- package/dist/dts/internal/v2/render-sync-parts.d.ts +0 -22
- package/dist/dts/internal/v2/render-sync-parts.d.ts.map +0 -1
- package/dist/dts/internal/v2/render.d.ts +0 -83
- package/dist/dts/internal/v2/render.d.ts.map +0 -1
- package/dist/dts/internal/v2/sync-parts.d.ts +0 -129
- package/dist/dts/internal/v2/sync-parts.d.ts.map +0 -1
- package/dist/esm/Directive.js +0 -64
- package/dist/esm/Directive.js.map +0 -1
- package/dist/esm/ElementRef.js +0 -76
- package/dist/esm/ElementRef.js.map +0 -1
- package/dist/esm/ElementSource.js +0 -246
- package/dist/esm/ElementSource.js.map +0 -1
- package/dist/esm/Entry.js +0 -2
- package/dist/esm/Entry.js.map +0 -1
- package/dist/esm/EventHandler.js +0 -68
- package/dist/esm/EventHandler.js.map +0 -1
- package/dist/esm/Html.js +0 -230
- package/dist/esm/Html.js.map +0 -1
- package/dist/esm/HtmlChunk.js +0 -330
- package/dist/esm/HtmlChunk.js.map +0 -1
- package/dist/esm/Hydrate.js +0 -31
- package/dist/esm/Hydrate.js.map +0 -1
- package/dist/esm/Many.js +0 -54
- package/dist/esm/Many.js.map +0 -1
- package/dist/esm/Meta.js +0 -40
- package/dist/esm/Meta.js.map +0 -1
- package/dist/esm/Parser.js +0 -13
- package/dist/esm/Parser.js.map +0 -1
- package/dist/esm/Part.js +0 -5
- package/dist/esm/Part.js.map +0 -1
- package/dist/esm/Placeholder.js +0 -26
- package/dist/esm/Placeholder.js.map +0 -1
- package/dist/esm/Platform.js +0 -42
- package/dist/esm/Platform.js.map +0 -1
- package/dist/esm/Render.js +0 -36
- package/dist/esm/Render.js.map +0 -1
- package/dist/esm/RenderContext.js +0 -54
- package/dist/esm/RenderContext.js.map +0 -1
- package/dist/esm/RenderEvent.js +0 -43
- package/dist/esm/RenderEvent.js.map +0 -1
- package/dist/esm/RenderQueue.js +0 -338
- package/dist/esm/RenderQueue.js.map +0 -1
- package/dist/esm/RenderTemplate.js +0 -16
- package/dist/esm/RenderTemplate.js.map +0 -1
- package/dist/esm/Renderable.js +0 -2
- package/dist/esm/Renderable.js.map +0 -1
- package/dist/esm/Template.js.map +0 -1
- package/dist/esm/Test.js +0 -167
- package/dist/esm/Test.js.map +0 -1
- package/dist/esm/Vitest.js +0 -44
- package/dist/esm/Vitest.js.map +0 -1
- package/dist/esm/compiler-tools.js +0 -91
- package/dist/esm/compiler-tools.js.map +0 -1
- package/dist/esm/index.js +0 -65
- package/dist/esm/index.js.map +0 -1
- package/dist/esm/internal/EventSource.js +0 -126
- package/dist/esm/internal/EventSource.js.map +0 -1
- package/dist/esm/internal/HydrateContext.js +0 -7
- package/dist/esm/internal/HydrateContext.js.map +0 -1
- package/dist/esm/internal/browser.js +0 -103
- package/dist/esm/internal/browser.js.map +0 -1
- package/dist/esm/internal/character-entities.js +0 -2134
- package/dist/esm/internal/character-entities.js.map +0 -1
- package/dist/esm/internal/chunks.js +0 -60
- package/dist/esm/internal/chunks.js.map +0 -1
- package/dist/esm/internal/errors.js +0 -46
- package/dist/esm/internal/errors.js.map +0 -1
- package/dist/esm/internal/indexRefCounter.js +0 -47
- package/dist/esm/internal/indexRefCounter.js.map +0 -1
- package/dist/esm/internal/module-augmentation.js +0 -2
- package/dist/esm/internal/module-augmentation.js.map +0 -1
- package/dist/esm/internal/parser.js +0 -596
- package/dist/esm/internal/parser.js.map +0 -1
- package/dist/esm/internal/parser2.js +0 -393
- package/dist/esm/internal/parser2.js.map +0 -1
- package/dist/esm/internal/server-parts.js +0 -109
- package/dist/esm/internal/server-parts.js.map +0 -1
- package/dist/esm/internal/server.js +0 -22
- package/dist/esm/internal/server.js.map +0 -1
- package/dist/esm/internal/utils.js +0 -119
- package/dist/esm/internal/utils.js.map +0 -1
- package/dist/esm/internal/v2/SyncPart.js +0 -5
- package/dist/esm/internal/v2/SyncPart.js.map +0 -1
- package/dist/esm/internal/v2/helpers.js +0 -12
- package/dist/esm/internal/v2/helpers.js.map +0 -1
- package/dist/esm/internal/v2/hydration-template.js.map +0 -1
- package/dist/esm/internal/v2/parts.js +0 -150
- package/dist/esm/internal/v2/parts.js.map +0 -1
- package/dist/esm/internal/v2/render-entry.js +0 -102
- package/dist/esm/internal/v2/render-entry.js.map +0 -1
- package/dist/esm/internal/v2/render-sync-parts.js +0 -265
- package/dist/esm/internal/v2/render-sync-parts.js.map +0 -1
- package/dist/esm/internal/v2/render.js +0 -521
- package/dist/esm/internal/v2/render.js.map +0 -1
- package/dist/esm/internal/v2/sync-parts.js +0 -102
- package/dist/esm/internal/v2/sync-parts.js.map +0 -1
- package/dist/esm/package.json +0 -4
- package/src/Directive.ts +0 -114
- package/src/ElementRef.ts +0 -148
- package/src/ElementSource.ts +0 -510
- package/src/Entry.ts +0 -28
- package/src/Hydrate.ts +0 -51
- package/src/Many.ts +0 -161
- package/src/Meta.ts +0 -45
- package/src/Part.ts +0 -154
- package/src/Placeholder.ts +0 -78
- package/src/Platform.ts +0 -70
- package/src/RenderContext.ts +0 -121
- package/src/Test.ts +0 -354
- package/src/Vitest.ts +0 -141
- package/src/compiler-tools.ts +0 -250
- package/src/internal/EventSource.ts +0 -188
- package/src/internal/HydrateContext.ts +0 -22
- package/src/internal/browser.ts +0 -138
- package/src/internal/character-entities.ts +0 -2136
- package/src/internal/chunks.ts +0 -89
- package/src/internal/errors.ts +0 -49
- package/src/internal/external.d.ts +0 -11
- package/src/internal/indexRefCounter.ts +0 -54
- package/src/internal/module-augmentation.ts +0 -44
- package/src/internal/parser.ts +0 -757
- package/src/internal/parser2.ts +0 -468
- package/src/internal/server-parts.ts +0 -161
- package/src/internal/server.ts +0 -37
- package/src/internal/utils.ts +0 -153
- package/src/internal/v2/SyncPart.ts +0 -112
- package/src/internal/v2/helpers.ts +0 -13
- package/src/internal/v2/hydration-template.ts +0 -308
- package/src/internal/v2/parts.ts +0 -254
- package/src/internal/v2/render-entry.ts +0 -131
- package/src/internal/v2/render-sync-parts.ts +0 -440
- package/src/internal/v2/render.ts +0 -813
- package/src/internal/v2/sync-parts.ts +0 -133
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import type * as Template from "../Template.js";
|
|
2
|
+
|
|
3
|
+
export function buildTemplateFragment(
|
|
4
|
+
document: Document,
|
|
5
|
+
template: Template.Template,
|
|
6
|
+
): DocumentFragment {
|
|
7
|
+
const root = document.createDocumentFragment();
|
|
8
|
+
for (const node of template.nodes) {
|
|
9
|
+
root.appendChild(buildTemplateNode(document, node));
|
|
10
|
+
}
|
|
11
|
+
return root;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function buildTemplateNode(document: Document, node: Template.Node): Node {
|
|
15
|
+
switch (node._tag) {
|
|
16
|
+
case "comment":
|
|
17
|
+
return document.createComment(node.value);
|
|
18
|
+
case "comment-part":
|
|
19
|
+
return document.createComment(`c_${node.index}`);
|
|
20
|
+
case "sparse-comment": {
|
|
21
|
+
return document.createComment(
|
|
22
|
+
`c_${node.nodes.map((n) => (n._tag === "text" ? "" : n.index)).join("_")}`,
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
case "doctype":
|
|
26
|
+
return document.implementation.createDocumentType(
|
|
27
|
+
node.name,
|
|
28
|
+
node.publicId ?? "",
|
|
29
|
+
node.systemId ?? "",
|
|
30
|
+
);
|
|
31
|
+
case "element":
|
|
32
|
+
return buildTemplateElement(document, node);
|
|
33
|
+
case "self-closing-element":
|
|
34
|
+
return buildTemplateSelfClosingElement(document, node);
|
|
35
|
+
case "text-only-element":
|
|
36
|
+
return buildTemplateTextOnlyElement(document, node);
|
|
37
|
+
case "text":
|
|
38
|
+
return document.createTextNode(node.value);
|
|
39
|
+
case "node":
|
|
40
|
+
return document.createComment(`/n_${node.index}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function buildTemplateElement(document: Document, node: Template.ElementNode): HTMLElement {
|
|
45
|
+
const element = document.createElement(node.tagName);
|
|
46
|
+
addStaticAttributes(element, node.attributes);
|
|
47
|
+
for (const child of node.children) {
|
|
48
|
+
element.appendChild(buildTemplateNode(document, child));
|
|
49
|
+
}
|
|
50
|
+
return element;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function addStaticAttributes(element: HTMLElement, attributes: Array<Template.Attribute>): void {
|
|
54
|
+
for (const attribute of attributes) {
|
|
55
|
+
if (attribute._tag === "attribute") {
|
|
56
|
+
element.setAttribute(attribute.name, attribute.value);
|
|
57
|
+
} else if (attribute._tag === "boolean") {
|
|
58
|
+
element.toggleAttribute(attribute.name, true);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function buildTemplateSelfClosingElement(
|
|
64
|
+
document: Document,
|
|
65
|
+
node: Template.SelfClosingElementNode,
|
|
66
|
+
): HTMLElement {
|
|
67
|
+
const element = document.createElement(node.tagName);
|
|
68
|
+
addStaticAttributes(element, node.attributes);
|
|
69
|
+
return element;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function buildTemplateTextOnlyElement(
|
|
73
|
+
document: Document,
|
|
74
|
+
node: Template.TextOnlyElement,
|
|
75
|
+
): HTMLElement {
|
|
76
|
+
const element = document.createElement(node.tagName);
|
|
77
|
+
addStaticAttributes(element, node.attributes);
|
|
78
|
+
if (node.textContent && node.textContent._tag === "text") {
|
|
79
|
+
element.textContent = node.textContent.value;
|
|
80
|
+
}
|
|
81
|
+
return element;
|
|
82
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
// @see https://github.com/WebReflection/udomdiff
|
|
2
|
+
|
|
3
|
+
export const diff = (
|
|
4
|
+
a: Array<Node>,
|
|
5
|
+
b: Array<Node>,
|
|
6
|
+
get: (entry: Node, action: number) => Node,
|
|
7
|
+
before: Node,
|
|
8
|
+
) => {
|
|
9
|
+
const parentNode = before.parentNode!;
|
|
10
|
+
const bLength = b.length;
|
|
11
|
+
let aEnd = a.length;
|
|
12
|
+
let bEnd = bLength;
|
|
13
|
+
let aStart = 0;
|
|
14
|
+
let bStart = 0;
|
|
15
|
+
let map = null;
|
|
16
|
+
while (aStart < aEnd || bStart < bEnd) {
|
|
17
|
+
// append head, tail, or nodes in between: fast path
|
|
18
|
+
if (aEnd === aStart) {
|
|
19
|
+
// we could be in a situation where the rest of nodes that
|
|
20
|
+
// need to be added are not at the end, and in such case
|
|
21
|
+
// the node to `insertBefore`, if the index is more than 0
|
|
22
|
+
// must be retrieved, otherwise it's gonna be the first item.
|
|
23
|
+
const node =
|
|
24
|
+
bEnd < bLength ? (bStart ? get(b[bStart - 1], -0).nextSibling : get(b[bEnd], 0)) : before;
|
|
25
|
+
while (bStart < bEnd) {
|
|
26
|
+
parentNode!.insertBefore(get(b[bStart++], 1), node);
|
|
27
|
+
}
|
|
28
|
+
} // remove head or tail: fast path
|
|
29
|
+
else if (bEnd === bStart) {
|
|
30
|
+
while (aStart < aEnd) {
|
|
31
|
+
// remove the node only if it's unknown or not live
|
|
32
|
+
if (!map || !map.has(a[aStart])) {
|
|
33
|
+
// @ts-ignore
|
|
34
|
+
get(a[aStart], -1).remove();
|
|
35
|
+
}
|
|
36
|
+
aStart++;
|
|
37
|
+
}
|
|
38
|
+
} // same node: fast path
|
|
39
|
+
else if (a[aStart] === b[bStart]) {
|
|
40
|
+
aStart++;
|
|
41
|
+
bStart++;
|
|
42
|
+
} // same tail: fast path
|
|
43
|
+
else if (a[aEnd - 1] === b[bEnd - 1]) {
|
|
44
|
+
aEnd--;
|
|
45
|
+
bEnd--;
|
|
46
|
+
} // The once here single last swap "fast path" has been removed in v1.1.0
|
|
47
|
+
// https://github.com/WebReflection/udomdiff/blob/single-final-swap/esm/index.js#L69-L85
|
|
48
|
+
// reverse swap: also fast path
|
|
49
|
+
else if (a[aStart] === b[bEnd - 1] && b[bStart] === a[aEnd - 1]) {
|
|
50
|
+
// this is a "shrink" operation that could happen in these cases:
|
|
51
|
+
// [1, 2, 3, 4, 5]
|
|
52
|
+
// [1, 4, 3, 2, 5]
|
|
53
|
+
// or asymmetric too
|
|
54
|
+
// [1, 2, 3, 4, 5]
|
|
55
|
+
// [1, 2, 3, 5, 6, 4]
|
|
56
|
+
const node = get(a[--aEnd], -0).nextSibling;
|
|
57
|
+
parentNode.insertBefore(get(b[bStart++], 1), get(a[aStart++], -0).nextSibling);
|
|
58
|
+
parentNode.insertBefore(get(b[--bEnd], 1), node);
|
|
59
|
+
// mark the future index as identical (yeah, it's dirty, but cheap 👍)
|
|
60
|
+
// The main reason to do this, is that when a[aEnd] will be reached,
|
|
61
|
+
// the loop will likely be on the fast path, as identical to b[bEnd].
|
|
62
|
+
// In the best case scenario, the next loop will skip the tail,
|
|
63
|
+
// but in the worst one, this node will be considered as already
|
|
64
|
+
// processed, bailing out pretty quickly from the map index check
|
|
65
|
+
a[aEnd] = b[bEnd];
|
|
66
|
+
} // map based fallback, "slow" path
|
|
67
|
+
else {
|
|
68
|
+
// the map requires an O(bEnd - bStart) operation once
|
|
69
|
+
// to store all future nodes indexes for later purposes.
|
|
70
|
+
// In the worst case scenario, this is a full O(N) cost,
|
|
71
|
+
// and such scenario happens at least when all nodes are different,
|
|
72
|
+
// but also if both first and last items of the lists are different
|
|
73
|
+
if (!map) {
|
|
74
|
+
map = new Map();
|
|
75
|
+
let i = bStart;
|
|
76
|
+
while (i < bEnd) {
|
|
77
|
+
map.set(b[i], i++);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const index = map.get(a[aStart]) ?? -1;
|
|
82
|
+
|
|
83
|
+
// this node has no meaning in the future list, so it's more than safe
|
|
84
|
+
// to remove it, and check the next live node out instead, meaning
|
|
85
|
+
// that only the live list index should be forwarded
|
|
86
|
+
if (index < 0) (get(a[aStart++], -1) as ChildNode).remove();
|
|
87
|
+
// it's a future node, hence it needs some handling
|
|
88
|
+
else {
|
|
89
|
+
// if it's not already processed, look on demand for the next LCS
|
|
90
|
+
if (bStart < index && index < bEnd) {
|
|
91
|
+
let i = aStart;
|
|
92
|
+
// counts the amount of nodes that are the same in the future
|
|
93
|
+
let sequence = 1;
|
|
94
|
+
while (++i < aEnd && i < bEnd && map.get(a[i]) === index + sequence) {
|
|
95
|
+
sequence++;
|
|
96
|
+
}
|
|
97
|
+
// effort decision here: if the sequence is longer than replaces
|
|
98
|
+
// needed to reach such sequence, which would brings again this loop
|
|
99
|
+
// to the fast path, prepend the difference before a sequence,
|
|
100
|
+
// and move only the future list index forward, so that aStart
|
|
101
|
+
// and bStart will be aligned again, hence on the fast path.
|
|
102
|
+
// An example considering aStart and bStart are both 0:
|
|
103
|
+
// a: [1, 2, 3, 4]
|
|
104
|
+
// b: [7, 1, 2, 3, 6]
|
|
105
|
+
// this would place 7 before 1 and, from that time on, 1, 2, and 3
|
|
106
|
+
// will be processed at zero cost
|
|
107
|
+
if (sequence > index - bStart) {
|
|
108
|
+
const node = get(a[aStart], 0);
|
|
109
|
+
while (bStart < index) {
|
|
110
|
+
parentNode.insertBefore(get(b[bStart++], 1), node);
|
|
111
|
+
}
|
|
112
|
+
} // if the effort wasn't good enough, fallback to a replace,
|
|
113
|
+
// moving both source and target indexes forward, hoping that some
|
|
114
|
+
// similar node will be found later on, to go back to the fast path
|
|
115
|
+
else {
|
|
116
|
+
// TODO: benchmark replaceWith instead
|
|
117
|
+
parentNode.replaceChild(get(b[bStart++], 1), get(a[aStart++], -1));
|
|
118
|
+
}
|
|
119
|
+
} // otherwise move the source forward, 'cause there's nothing to do
|
|
120
|
+
else {
|
|
121
|
+
aStart++;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return b;
|
|
127
|
+
};
|
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
import * as Effect from "effect/Effect";
|
|
2
|
+
import { isNullish, isObject } from "effect/Predicate";
|
|
3
|
+
import { CouldNotFindCommentError } from "../errors.js";
|
|
4
|
+
import { type EventHandler, fromEffectOrEventHandler, isEventHandler } from "../EventHandler.js";
|
|
5
|
+
import {
|
|
6
|
+
type DomRenderEvent,
|
|
7
|
+
type HtmlRenderEvent,
|
|
8
|
+
isRenderEvent,
|
|
9
|
+
type RenderEvent,
|
|
10
|
+
RenderEventTypeId,
|
|
11
|
+
} from "../RenderEvent.js";
|
|
12
|
+
import { diffable, isComment } from "../Wire.js";
|
|
13
|
+
import { diff } from "./diff.js";
|
|
14
|
+
import { renderToString } from "./encoding.js";
|
|
15
|
+
|
|
16
|
+
export function makeTextContentUpdater(element: Node) {
|
|
17
|
+
return (value: unknown) => {
|
|
18
|
+
element.textContent = renderToString(value, "");
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function makeAttributeValueUpdater(element: HTMLElement | SVGElement, attr: Attr) {
|
|
23
|
+
let isSet = false;
|
|
24
|
+
const setValue = (value: string | null | undefined) => {
|
|
25
|
+
if (isNullish(value)) {
|
|
26
|
+
element.removeAttribute(attr.name);
|
|
27
|
+
isSet = false;
|
|
28
|
+
} else {
|
|
29
|
+
attr.value = value;
|
|
30
|
+
if (isSet === false) {
|
|
31
|
+
element.setAttributeNode(attr);
|
|
32
|
+
isSet = true;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
return setValue;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function makeClassListUpdater(element: HTMLElement | SVGElement) {
|
|
41
|
+
// We do double-bookeeping such that we don't assume we know everything about the classList
|
|
42
|
+
// Other DOM-based libraries might have additional classes in the classList, so we need to allow them to exist
|
|
43
|
+
// outside of our control.
|
|
44
|
+
let classList: ReadonlyArray<string> = Array.from(element.classList);
|
|
45
|
+
return (classNames: ReadonlyArray<string>) => {
|
|
46
|
+
const { added, removed } = diffStrings(classList, classNames);
|
|
47
|
+
if (added.length > 0) {
|
|
48
|
+
element.classList.add(...added);
|
|
49
|
+
}
|
|
50
|
+
if (removed.length > 0) {
|
|
51
|
+
element.classList.remove(...removed);
|
|
52
|
+
}
|
|
53
|
+
classList = classNames;
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function makeDatasetUpdater(element: HTMLElement | SVGElement) {
|
|
58
|
+
// We do double-bookeeping such that we don't assume we know everything about the dataset
|
|
59
|
+
// Other DOM-based libraries might have additional keys in the dataset, so we need to allow them to exist
|
|
60
|
+
// outside of our control.
|
|
61
|
+
const previous = { ...element.dataset };
|
|
62
|
+
return (value: unknown) => {
|
|
63
|
+
const diff = diffDataSet(previous, value as Record<string, string | undefined>);
|
|
64
|
+
if (diff) {
|
|
65
|
+
const { added, removed } = diff;
|
|
66
|
+
removed.forEach((k) => {
|
|
67
|
+
delete element.dataset[k];
|
|
68
|
+
delete previous[k];
|
|
69
|
+
});
|
|
70
|
+
added.forEach(([k, v]) => {
|
|
71
|
+
element.dataset[k] = v;
|
|
72
|
+
previous[k] = v;
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function diffStrings(
|
|
79
|
+
previous: ReadonlyArray<string> | null | undefined,
|
|
80
|
+
current: ReadonlyArray<string> | null | undefined,
|
|
81
|
+
): {
|
|
82
|
+
added: ReadonlyArray<string>;
|
|
83
|
+
removed: ReadonlyArray<string>;
|
|
84
|
+
unchanged: ReadonlyArray<string>;
|
|
85
|
+
} {
|
|
86
|
+
if (previous == null || previous.length === 0) {
|
|
87
|
+
return {
|
|
88
|
+
added: current || [],
|
|
89
|
+
removed: [],
|
|
90
|
+
unchanged: [],
|
|
91
|
+
};
|
|
92
|
+
} else if (current == null || current.length === 0) {
|
|
93
|
+
return {
|
|
94
|
+
added: [],
|
|
95
|
+
removed: previous,
|
|
96
|
+
unchanged: [],
|
|
97
|
+
};
|
|
98
|
+
} else {
|
|
99
|
+
const previousSet = new Set(previous);
|
|
100
|
+
const currentSet = new Set(current);
|
|
101
|
+
const added = current.filter((c) => !previousSet.has(c));
|
|
102
|
+
const removed: Array<string> = [];
|
|
103
|
+
const unchanged: Array<string> = [];
|
|
104
|
+
|
|
105
|
+
for (let i = 0; i < previous.length; ++i) {
|
|
106
|
+
if (currentSet.has(previous[i])) {
|
|
107
|
+
unchanged.push(previous[i]);
|
|
108
|
+
} else {
|
|
109
|
+
removed.push(previous[i]);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return {
|
|
114
|
+
added,
|
|
115
|
+
removed,
|
|
116
|
+
unchanged,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export function diffDataSet(
|
|
122
|
+
a: Record<string, string | undefined> | null | undefined,
|
|
123
|
+
b: Record<string, string | undefined> | null | undefined,
|
|
124
|
+
): { added: Array<readonly [string, string | undefined]>; removed: ReadonlyArray<string> } | null {
|
|
125
|
+
if (!a) return b ? { added: Object.entries(b), removed: [] } : null;
|
|
126
|
+
if (!b) return { added: [], removed: Object.keys(a) };
|
|
127
|
+
|
|
128
|
+
const { added, removed, unchanged } = diffStrings(Object.keys(a), Object.keys(b));
|
|
129
|
+
|
|
130
|
+
return {
|
|
131
|
+
added: added.concat(unchanged).map((k) => [k, b[k]] as const),
|
|
132
|
+
removed,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export function getClassList(value: unknown): ReadonlyArray<string> {
|
|
137
|
+
if (isNullish(value)) return [];
|
|
138
|
+
if (Array.isArray(value)) return value.flatMap(getClassList);
|
|
139
|
+
return splitClassNames(renderToString(value, ""));
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const ASCII_SPACE_CODE = 32;
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Splits a string of class names (like those used in HTML `class=""` attributes)
|
|
146
|
+
* into an array of individual class names (words), separated by whitespace.
|
|
147
|
+
*
|
|
148
|
+
* This function avoids creating intermediate arrays and unnecessary string copying by:
|
|
149
|
+
* - Scanning the string one character at a time
|
|
150
|
+
* - Skipping over all leading whitespace for each word
|
|
151
|
+
* - Collecting all consecutive non-whitespace characters as a "word"
|
|
152
|
+
* - Repeating until the input is exhausted
|
|
153
|
+
*
|
|
154
|
+
* All ASCII "whitespace" characters with code <= 32 are considered as delimiters.
|
|
155
|
+
* This is more efficient than `String.prototype.trim` and `String.prototype.split(/\s+/)`
|
|
156
|
+
* as it only allocates memory for the result array, not for intermediate or empty strings.
|
|
157
|
+
*
|
|
158
|
+
* Example:
|
|
159
|
+
* splitClassNames(" foo bar\tbaz\nqux ") // => ["foo", "bar", "baz", "qux"]
|
|
160
|
+
*/
|
|
161
|
+
export function splitClassNames(value: string): Array<string> {
|
|
162
|
+
const result: Array<string> = [];
|
|
163
|
+
let start = 0;
|
|
164
|
+
const len = value.length;
|
|
165
|
+
|
|
166
|
+
while (start < len) {
|
|
167
|
+
// Skip leading whitespace (all ASCII <= 32)
|
|
168
|
+
while (start < len && value.charCodeAt(start) <= ASCII_SPACE_CODE) start++;
|
|
169
|
+
if (start >= len) break;
|
|
170
|
+
// Find the end of the word (next whitespace)
|
|
171
|
+
let end = start + 1;
|
|
172
|
+
while (end < len && value.charCodeAt(end) > ASCII_SPACE_CODE) end++;
|
|
173
|
+
result.push(value.slice(start, end));
|
|
174
|
+
// Move start past the end of the last word (one char after end)
|
|
175
|
+
start = end + 1;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return result;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export function matchNodeValue<A, B>(
|
|
182
|
+
document: Document,
|
|
183
|
+
value: unknown,
|
|
184
|
+
onText: (text: string) => A,
|
|
185
|
+
onNodes: (nodes: Array<Node>) => B,
|
|
186
|
+
): A | B {
|
|
187
|
+
switch (typeof value) {
|
|
188
|
+
// primitives are handled as text content
|
|
189
|
+
case "string":
|
|
190
|
+
case "symbol":
|
|
191
|
+
case "number":
|
|
192
|
+
case "bigint":
|
|
193
|
+
case "boolean":
|
|
194
|
+
return onText(String(value));
|
|
195
|
+
case "undefined":
|
|
196
|
+
case "function":
|
|
197
|
+
case "object": {
|
|
198
|
+
if (isNullish(value)) {
|
|
199
|
+
return onNodes([]);
|
|
200
|
+
} else if (isRenderEvent(value)) {
|
|
201
|
+
return onNodes(unwrapRenderEvent(document, value));
|
|
202
|
+
} else if (Array.isArray(value)) {
|
|
203
|
+
return onNodes(value.flatMap((_) => renderEventToArray(document, _)));
|
|
204
|
+
} else {
|
|
205
|
+
return onNodes(renderEventToArray(document, value));
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
export function renderEventToArray(document: Document, x: unknown): Array<Node> {
|
|
212
|
+
switch (typeof x) {
|
|
213
|
+
case "string":
|
|
214
|
+
case "number":
|
|
215
|
+
case "bigint":
|
|
216
|
+
case "boolean":
|
|
217
|
+
case "symbol":
|
|
218
|
+
return [document.createTextNode(String(x))];
|
|
219
|
+
case "undefined":
|
|
220
|
+
case "function":
|
|
221
|
+
case "object":
|
|
222
|
+
if (isNullish(x)) return [];
|
|
223
|
+
if (isRenderEvent(x)) return unwrapRenderEvent(document, x);
|
|
224
|
+
if (Array.isArray(x)) return x.flatMap((_) => renderEventToArray(document, _));
|
|
225
|
+
return [x as Node];
|
|
226
|
+
default:
|
|
227
|
+
return [];
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
function unwrapRenderEvent(document: Document, x: RenderEvent): Array<Node> {
|
|
232
|
+
if (x[RenderEventTypeId] === "dom") return unwrapDomRenderEvent(x);
|
|
233
|
+
return unwrapHtmlRenderEvent(document, x);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
function unwrapDomRenderEvent(x: DomRenderEvent): Array<Node> {
|
|
237
|
+
const value = x.content;
|
|
238
|
+
return Array.isArray(value) ? value : [value as Node];
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function unwrapHtmlRenderEvent(document: Document, x: HtmlRenderEvent): Array<Node> {
|
|
242
|
+
const tmp = document.createElement("template");
|
|
243
|
+
tmp.innerHTML = x.html;
|
|
244
|
+
return Array.from(tmp.childNodes);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
export function diffChildren(
|
|
248
|
+
comment: Comment,
|
|
249
|
+
currentNodes: Array<Node>,
|
|
250
|
+
nextNodes: Array<Node>,
|
|
251
|
+
get: (entry: Node, action: number) => Node,
|
|
252
|
+
) {
|
|
253
|
+
return diff(currentNodes, nextNodes, get, comment);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
const commentCache = new WeakMap<Element, Map<number, Comment>>();
|
|
257
|
+
|
|
258
|
+
function getCommentCacheKey(index: number, isEnd: boolean): number {
|
|
259
|
+
return isEnd ? -index - 1 : index;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
function findCommentInElement(parent: Element, index: number, isEnd: boolean): Comment {
|
|
263
|
+
let cache = commentCache.get(parent);
|
|
264
|
+
if (cache === undefined) {
|
|
265
|
+
cache = new Map();
|
|
266
|
+
commentCache.set(parent, cache);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
const cacheKey = getCommentCacheKey(index, isEnd);
|
|
270
|
+
const cached = cache.get(cacheKey);
|
|
271
|
+
if (cached !== undefined) {
|
|
272
|
+
return cached;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
const childNodes = parent.childNodes;
|
|
276
|
+
const searchValue = isEnd ? `/n_${index}` : `n_${index}`;
|
|
277
|
+
|
|
278
|
+
for (let i = 0; i < childNodes.length; ++i) {
|
|
279
|
+
const node = childNodes[i];
|
|
280
|
+
if (isCommentWithValue(node, searchValue)) {
|
|
281
|
+
cache.set(cacheKey, node);
|
|
282
|
+
return node;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
throw new CouldNotFindCommentError(index);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
export function findNodePartEndComment(parent: Element, index: number) {
|
|
290
|
+
return findCommentInElement(parent, index, true);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
export function findNodePartStartComment(parent: Element, index: number) {
|
|
294
|
+
return findCommentInElement(parent, index, false);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
function isCommentWithValue(node: Node, value: string): node is Comment {
|
|
298
|
+
return isComment(node) && node.nodeValue === value;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
export function makeNodeUpdater(
|
|
302
|
+
document: Document,
|
|
303
|
+
comment: Comment,
|
|
304
|
+
text: Text | null = null,
|
|
305
|
+
nodes: Array<Node> = [],
|
|
306
|
+
) {
|
|
307
|
+
const element = comment.parentNode as HTMLElement | SVGElement;
|
|
308
|
+
const get = diffable(document);
|
|
309
|
+
const updateCommentText = (value: unknown) => {
|
|
310
|
+
if (text === null) {
|
|
311
|
+
text = document.createTextNode("");
|
|
312
|
+
element.insertBefore(text, comment);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
text.textContent = renderToString(value, "");
|
|
316
|
+
nodes = diffChildren(comment, nodes, [text], get);
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
const updateNodes = (updatedNodes: Array<Node>) => {
|
|
320
|
+
nodes = diffChildren(comment, nodes, updatedNodes, get);
|
|
321
|
+
};
|
|
322
|
+
|
|
323
|
+
return (value: unknown) => {
|
|
324
|
+
matchNodeValue(document, value, updateCommentText, updateNodes);
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
export function makeBooleanUpdater(element: HTMLElement | SVGElement, name: string) {
|
|
329
|
+
return (value: boolean) => {
|
|
330
|
+
element.toggleAttribute(name, value);
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
export function getAttributeValue(value: unknown): string | null | undefined {
|
|
335
|
+
if (isNullish(value)) return null;
|
|
336
|
+
return renderToString(value, "");
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
export function getBooleanValue(value: unknown): boolean {
|
|
340
|
+
return !!value;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
export function getDatasetValue(
|
|
344
|
+
value: unknown,
|
|
345
|
+
): Record<string, string | undefined> | null | undefined {
|
|
346
|
+
if (isNullish(value)) return null;
|
|
347
|
+
if (isObject(value)) return value as Record<string, string | undefined>;
|
|
348
|
+
return null;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
export function getEventHandlerValue<E, R>(
|
|
352
|
+
value: unknown,
|
|
353
|
+
): EventHandler<Event, E, R> | null | undefined {
|
|
354
|
+
if (isNullish(value)) return null;
|
|
355
|
+
if (isEventHandler(value) || Effect.isEffect(value)) return fromEffectOrEventHandler(value);
|
|
356
|
+
return null;
|
|
357
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { isOption, match } from "effect/Option";
|
|
2
|
+
import { hasProperty, isNullish } from "effect/Predicate";
|
|
3
|
+
import { isHtmlRenderEvent } from "../RenderEvent.js";
|
|
4
|
+
|
|
5
|
+
export function escape(s: unknown): string {
|
|
6
|
+
switch (typeof s) {
|
|
7
|
+
case "string":
|
|
8
|
+
case "number":
|
|
9
|
+
case "boolean":
|
|
10
|
+
case "bigint":
|
|
11
|
+
return escapeHtml(String(s));
|
|
12
|
+
case "object": {
|
|
13
|
+
if (isNullish(s)) {
|
|
14
|
+
return "";
|
|
15
|
+
} else if (Array.isArray(s)) {
|
|
16
|
+
return s.map(escape).join("");
|
|
17
|
+
} else if (s instanceof Date) {
|
|
18
|
+
return escapeHtml(s.toISOString());
|
|
19
|
+
} else if (s instanceof RegExp) {
|
|
20
|
+
return escapeHtml(s.toString());
|
|
21
|
+
} else {
|
|
22
|
+
return escapeHtml(JSON.stringify(s));
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
default:
|
|
26
|
+
return escapeHtml(JSON.stringify(s));
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function unescape(s: string) {
|
|
31
|
+
const unescaped = unescapeHtml(s);
|
|
32
|
+
const couldBeJson = unescaped[0] === "[" || unescaped === "{";
|
|
33
|
+
if (couldBeJson) {
|
|
34
|
+
try {
|
|
35
|
+
return JSON.parse(unescaped);
|
|
36
|
+
} catch {
|
|
37
|
+
return unescaped;
|
|
38
|
+
}
|
|
39
|
+
} else {
|
|
40
|
+
return unescaped;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const unescapeHtmlRules = [
|
|
45
|
+
[/"/g, '"'],
|
|
46
|
+
[/'/g, "'"],
|
|
47
|
+
[/:/g, ":"],
|
|
48
|
+
[/</g, "<"],
|
|
49
|
+
[/>/g, ">"],
|
|
50
|
+
[/&/g, "&"],
|
|
51
|
+
] as const;
|
|
52
|
+
|
|
53
|
+
const matchHtmlRegExp = /["'&<>]/;
|
|
54
|
+
|
|
55
|
+
export function escapeHtml(str: string): string {
|
|
56
|
+
if (str.length === 0) {
|
|
57
|
+
return str;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const match = matchHtmlRegExp.exec(str);
|
|
61
|
+
|
|
62
|
+
if (!match) {
|
|
63
|
+
return str;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
let escape;
|
|
67
|
+
let html = "";
|
|
68
|
+
let index = 0;
|
|
69
|
+
let lastIndex = 0;
|
|
70
|
+
|
|
71
|
+
for (index = match.index; index < str.length; index++) {
|
|
72
|
+
switch (str.charCodeAt(index)) {
|
|
73
|
+
case 34: // "
|
|
74
|
+
escape = """;
|
|
75
|
+
break;
|
|
76
|
+
case 38: // &
|
|
77
|
+
escape = "&";
|
|
78
|
+
break;
|
|
79
|
+
case 39: // '
|
|
80
|
+
escape = "'";
|
|
81
|
+
break;
|
|
82
|
+
case 60: // <
|
|
83
|
+
escape = "<";
|
|
84
|
+
break;
|
|
85
|
+
case 62: // >
|
|
86
|
+
escape = ">";
|
|
87
|
+
break;
|
|
88
|
+
default:
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (lastIndex !== index) {
|
|
93
|
+
html += str.substring(lastIndex, index);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
lastIndex = index + 1;
|
|
97
|
+
html += escape;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return lastIndex !== index ? html + str.substring(lastIndex, index) : html;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export function unescapeHtml(html: string) {
|
|
104
|
+
for (const [from, to] of unescapeHtmlRules) {
|
|
105
|
+
html = html.replace(from, to);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return html;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export function renderToString(value: unknown, delimiter: string = ""): string {
|
|
112
|
+
if (Array.isArray(value)) {
|
|
113
|
+
return value.map((v) => renderToString(v, delimiter)).join(delimiter);
|
|
114
|
+
}
|
|
115
|
+
if (isNullish(value)) {
|
|
116
|
+
return "";
|
|
117
|
+
}
|
|
118
|
+
if (isOption(value)) {
|
|
119
|
+
return match(value, {
|
|
120
|
+
onNone: () => "",
|
|
121
|
+
onSome: (v: unknown) => renderToString(v, delimiter),
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
if (isHtmlRenderEvent(value)) {
|
|
125
|
+
return value.html;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (typeof value === "string") {
|
|
129
|
+
return value;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (hasProperty(value, "toString") && typeof value.toString === "function") {
|
|
133
|
+
const s = value.toString();
|
|
134
|
+
if (s !== "[object Object]") {
|
|
135
|
+
return s;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (typeof value === "object") {
|
|
140
|
+
return JSON.stringify(value);
|
|
141
|
+
}
|
|
142
|
+
return String(value);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export function renderToEscapedString(value: unknown, delimiter: string): string {
|
|
146
|
+
return escape(renderToString(value, delimiter));
|
|
147
|
+
}
|