@typed/template 0.13.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 -223
- 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 -383
- 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 -242
- 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 -66
- 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 -341
- 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 -77
- 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 -240
- 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 -43
- 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 -336
- 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 -126
- package/src/ElementSource.ts +0 -432
- 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 -71
- 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
package/src/HtmlChunk.ts
CHANGED
|
@@ -1,407 +1,365 @@
|
|
|
1
|
+
import type * as Template from "./Template.js";
|
|
2
|
+
import * as Array from "effect/Array";
|
|
3
|
+
import { constVoid } from "effect/Function";
|
|
4
|
+
import * as Order from "effect/Order";
|
|
5
|
+
import * as Predicate from "effect/Predicate";
|
|
6
|
+
import { renderToEscapedString, renderToString } from "./internal/encoding.js";
|
|
7
|
+
import { TEMPLATE_END_COMMENT, TEMPLATE_START_COMMENT } from "./internal/meta.js";
|
|
8
|
+
|
|
1
9
|
/**
|
|
10
|
+
* Represents a piece of a pre-compiled HTML template.
|
|
11
|
+
*
|
|
12
|
+
* Chunks allow the renderer to stream static parts of the HTML immediately
|
|
13
|
+
* while waiting for dynamic parts to be resolved.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* import type { HtmlChunk } from "@typed/template/HtmlChunk"
|
|
18
|
+
* import { templateToHtmlChunks } from "@typed/template/HtmlChunk"
|
|
19
|
+
* import { parse } from "@typed/template/Parser"
|
|
20
|
+
*
|
|
21
|
+
* const template = parse`<div>Hello ${"world"}</div>`
|
|
22
|
+
* const chunks = templateToHtmlChunks(template)
|
|
23
|
+
*
|
|
24
|
+
* // chunks will contain:
|
|
25
|
+
* // - HtmlTextChunk with text "<div>Hello "
|
|
26
|
+
* // - HtmlPartChunk for the dynamic part
|
|
27
|
+
* // - HtmlTextChunk with text "</div>"
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
2
30
|
* @since 1.0.0
|
|
31
|
+
* @category models
|
|
3
32
|
*/
|
|
4
|
-
|
|
5
|
-
import { isNullOrUndefined } from "./internal/v2/helpers.js"
|
|
6
|
-
import type {
|
|
7
|
-
Attribute,
|
|
8
|
-
ElementNode,
|
|
9
|
-
Node,
|
|
10
|
-
PartNode,
|
|
11
|
-
SelfClosingElementNode,
|
|
12
|
-
SparseAttrNode,
|
|
13
|
-
SparseClassNameNode,
|
|
14
|
-
Template,
|
|
15
|
-
Text,
|
|
16
|
-
TextOnlyElement
|
|
17
|
-
} from "./Template.js"
|
|
33
|
+
export type HtmlChunk = HtmlTextChunk | HtmlPartChunk | HtmlSparsePartChunk;
|
|
18
34
|
|
|
19
35
|
/**
|
|
36
|
+
* A static text chunk.
|
|
37
|
+
*
|
|
20
38
|
* @since 1.0.0
|
|
39
|
+
* @category models
|
|
21
40
|
*/
|
|
22
|
-
export
|
|
41
|
+
export interface HtmlTextChunk {
|
|
42
|
+
readonly _tag: "text";
|
|
43
|
+
readonly text: string;
|
|
44
|
+
}
|
|
23
45
|
|
|
24
46
|
/**
|
|
47
|
+
* A chunk representing a dynamic part (interpolation).
|
|
48
|
+
*
|
|
25
49
|
* @since 1.0.0
|
|
50
|
+
* @category models
|
|
26
51
|
*/
|
|
27
|
-
export
|
|
28
|
-
readonly _tag
|
|
29
|
-
|
|
52
|
+
export interface HtmlPartChunk {
|
|
53
|
+
readonly _tag: "part";
|
|
54
|
+
readonly node: Template.PartNode;
|
|
55
|
+
/**
|
|
56
|
+
* Function to render the value of this part into a string.
|
|
57
|
+
*/
|
|
58
|
+
readonly render: (value: unknown) => string;
|
|
30
59
|
}
|
|
31
60
|
|
|
32
61
|
/**
|
|
62
|
+
* A chunk representing a sparse part (mixed static/dynamic text).
|
|
63
|
+
*
|
|
33
64
|
* @since 1.0.0
|
|
65
|
+
* @category models
|
|
34
66
|
*/
|
|
35
|
-
export
|
|
36
|
-
readonly _tag
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
)
|
|
67
|
+
export interface HtmlSparsePartChunk {
|
|
68
|
+
readonly _tag: "sparse-part";
|
|
69
|
+
readonly node: Template.SparsePartNode;
|
|
70
|
+
/**
|
|
71
|
+
* Function to render the value of this part into a string.
|
|
72
|
+
*/
|
|
73
|
+
readonly render: (value: unknown) => string;
|
|
42
74
|
}
|
|
43
75
|
|
|
44
76
|
/**
|
|
45
|
-
*
|
|
77
|
+
* Helper class for constructing a list of `HtmlChunk`s.
|
|
78
|
+
* @internal
|
|
46
79
|
*/
|
|
47
|
-
export class
|
|
48
|
-
|
|
80
|
+
export class HtmlChunksBuilder {
|
|
81
|
+
private chunks: Array<HtmlChunk> = [];
|
|
82
|
+
|
|
83
|
+
text(text: string): HtmlChunksBuilder {
|
|
84
|
+
const lastIndex = this.chunks.length - 1;
|
|
85
|
+
const lastChunk = this.chunks[lastIndex];
|
|
86
|
+
if (lastChunk?._tag === "text") {
|
|
87
|
+
this.chunks[lastIndex] = { _tag: "text", text: lastChunk.text + text };
|
|
88
|
+
} else {
|
|
89
|
+
this.chunks.push({ _tag: "text", text });
|
|
90
|
+
}
|
|
91
|
+
return this;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
part(node: Template.PartNode, render: (value: unknown) => string): HtmlChunksBuilder {
|
|
95
|
+
this.chunks.push({ _tag: "part", node, render });
|
|
96
|
+
return this;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
sparsePart(node: Template.SparsePartNode, render: (value: unknown) => string): HtmlChunksBuilder {
|
|
100
|
+
this.chunks.push({ _tag: "sparse-part", node, render });
|
|
101
|
+
return this;
|
|
102
|
+
}
|
|
49
103
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
104
|
+
build(): ReadonlyArray<HtmlChunk> {
|
|
105
|
+
const chunks = this.chunks;
|
|
106
|
+
this.chunks = [];
|
|
107
|
+
return chunks;
|
|
108
|
+
}
|
|
54
109
|
}
|
|
55
110
|
|
|
111
|
+
// TODO: Add support for unsafe HTML content.
|
|
112
|
+
|
|
56
113
|
/**
|
|
114
|
+
* Converts a parsed `Template` into a sequence of `HtmlChunk`s.
|
|
115
|
+
* This optimization pre-calculates the static HTML strings to minimize work at render time.
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* ```ts
|
|
119
|
+
* import { templateToHtmlChunks } from "@typed/template/HtmlChunk"
|
|
120
|
+
* import { parse } from "@typed/template/Parser"
|
|
121
|
+
*
|
|
122
|
+
* const template = parse`<div class="container">Hello ${"world"}</div>`
|
|
123
|
+
* const chunks = templateToHtmlChunks(template)
|
|
124
|
+
*
|
|
125
|
+
* // chunks is an array of HtmlChunk objects
|
|
126
|
+
* // Static parts are pre-rendered as text chunks
|
|
127
|
+
* // Dynamic parts are represented as part chunks
|
|
128
|
+
* ```
|
|
129
|
+
*
|
|
57
130
|
* @since 1.0.0
|
|
131
|
+
* @category utilities
|
|
58
132
|
*/
|
|
59
|
-
export
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
133
|
+
export function templateToHtmlChunks({ nodes }: Template.Template) {
|
|
134
|
+
const builder = new HtmlChunksBuilder();
|
|
135
|
+
for (const node of nodes) nodeToHtmlChunk(builder, node);
|
|
136
|
+
return builder.build();
|
|
137
|
+
}
|
|
63
138
|
|
|
64
139
|
/**
|
|
140
|
+
* Wraps the HTML chunks with comments containing the template hash.
|
|
141
|
+
* This is crucial for hydration to identify which template rendered a section of HTML.
|
|
142
|
+
*
|
|
143
|
+
* @example
|
|
144
|
+
* ```ts
|
|
145
|
+
* import { addTemplateHash, templateToHtmlChunks } from "@typed/template/HtmlChunk"
|
|
146
|
+
* import { parse } from "@typed/template/Parser"
|
|
147
|
+
*
|
|
148
|
+
* const template = parse`<div>Hello</div>`
|
|
149
|
+
* const chunks = templateToHtmlChunks(template)
|
|
150
|
+
* const chunksWithHash = addTemplateHash(chunks, template)
|
|
151
|
+
*
|
|
152
|
+
* // chunksWithHash will have template hash comments added
|
|
153
|
+
* // for hydration purposes
|
|
154
|
+
* ```
|
|
155
|
+
*
|
|
65
156
|
* @since 1.0.0
|
|
157
|
+
* @category utilities
|
|
66
158
|
*/
|
|
67
|
-
export function
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
templateEnd(hash)
|
|
76
|
-
])
|
|
77
|
-
|
|
78
|
-
return chunks
|
|
159
|
+
export function addTemplateHash(
|
|
160
|
+
chunks: ReadonlyArray<HtmlChunk>,
|
|
161
|
+
{ hash }: Template.Template,
|
|
162
|
+
): ReadonlyArray<HtmlChunk> {
|
|
163
|
+
const start = TEMPLATE_START_COMMENT(hash);
|
|
164
|
+
const end = TEMPLATE_END_COMMENT(hash);
|
|
165
|
+
if (chunks.length === 0) return [{ _tag: "text", text: start + end }];
|
|
166
|
+
return appendTextChunk(prependTextChunk(chunks, start), end);
|
|
79
167
|
}
|
|
80
168
|
|
|
81
|
-
function
|
|
82
|
-
|
|
169
|
+
function prependTextChunk(
|
|
170
|
+
chunks: ReadonlyArray<HtmlChunk>,
|
|
171
|
+
text: string,
|
|
172
|
+
): ReadonlyArray<HtmlChunk> {
|
|
173
|
+
if (chunks.length === 0) return [{ _tag: "text", text }];
|
|
174
|
+
const firstChunk = chunks[0];
|
|
175
|
+
if (firstChunk._tag === "text")
|
|
176
|
+
return [{ _tag: "text", text: text + firstChunk.text }, ...chunks.slice(1)];
|
|
177
|
+
return [{ _tag: "text", text }, ...chunks];
|
|
83
178
|
}
|
|
84
179
|
|
|
85
|
-
function
|
|
86
|
-
return
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
for (let i = 0; i < chunks.length; i++) {
|
|
93
|
-
if (i > 0) {
|
|
94
|
-
const prevIndex = output.length - 1
|
|
95
|
-
const prev = output[prevIndex]
|
|
96
|
-
const curr = chunks[i]
|
|
97
|
-
|
|
98
|
-
if (prev._tag === "text" && curr._tag === "text") {
|
|
99
|
-
output[prevIndex] = new TextChunk(prev.value + curr.value)
|
|
100
|
-
} else {
|
|
101
|
-
output.push(curr)
|
|
102
|
-
}
|
|
103
|
-
} else {
|
|
104
|
-
output.push(chunks[i])
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
return output
|
|
180
|
+
function appendTextChunk(chunks: ReadonlyArray<HtmlChunk>, text: string): ReadonlyArray<HtmlChunk> {
|
|
181
|
+
if (chunks.length === 0) return [{ _tag: "text", text }];
|
|
182
|
+
const lastChunk = chunks[chunks.length - 1];
|
|
183
|
+
if (lastChunk._tag === "text")
|
|
184
|
+
return [...chunks.slice(0, -1), { _tag: "text", text: lastChunk.text + text }];
|
|
185
|
+
return [...chunks, { _tag: "text", text }];
|
|
109
186
|
}
|
|
110
187
|
|
|
111
188
|
type NodeMap = {
|
|
112
|
-
readonly [K in Node["_tag"]]: (
|
|
113
|
-
|
|
189
|
+
readonly [K in Template.Node["_tag"]]: (
|
|
190
|
+
builder: HtmlChunksBuilder,
|
|
191
|
+
node: Extract<Template.Node, { _tag: K }>,
|
|
192
|
+
) => void;
|
|
193
|
+
};
|
|
114
194
|
|
|
115
195
|
const nodeMap: NodeMap = {
|
|
116
|
-
doctype: (node) =>
|
|
196
|
+
doctype: (builder, node) => builder.text(`<!DOCTYPE ${node.name}>`),
|
|
117
197
|
element: elementToHtmlChunks,
|
|
118
|
-
|
|
198
|
+
text: (builder, node) => builder.text(node.value),
|
|
199
|
+
node: (builder, part) => builder.part(part, (v) => renderToEscapedString(v, "")),
|
|
119
200
|
"self-closing-element": selfClosingElementToHtmlChunks,
|
|
120
|
-
text: (node) => [textToHtmlChunks(node)],
|
|
121
201
|
"text-only-element": textOnlyElementToHtmlChunks,
|
|
122
|
-
comment: (node) =>
|
|
123
|
-
"comment-part": (
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
...node.nodes.map((node) => {
|
|
129
|
-
if (node._tag === "text") {
|
|
130
|
-
return textToHtmlChunks(node)
|
|
131
|
-
} else {
|
|
132
|
-
return new PartChunk(node, (value) => `${value}`)
|
|
133
|
-
}
|
|
134
|
-
}),
|
|
135
|
-
new TextChunk("-->")
|
|
136
|
-
]
|
|
137
|
-
}
|
|
202
|
+
comment: (builder, node) => builder.text(`<!--${node.value}-->`),
|
|
203
|
+
"comment-part": (builder, part) =>
|
|
204
|
+
builder.part(part, (v) => `<!--${renderToEscapedString(v, "")}-->`),
|
|
205
|
+
"sparse-comment": (builder, part) =>
|
|
206
|
+
builder.sparsePart(part, (v) => `<!--${renderToEscapedString(v, "")}-->`),
|
|
207
|
+
};
|
|
138
208
|
|
|
139
|
-
function
|
|
140
|
-
|
|
209
|
+
function selfClosingElementToHtmlChunks(
|
|
210
|
+
builder: HtmlChunksBuilder,
|
|
211
|
+
node: Template.SelfClosingElementNode,
|
|
212
|
+
) {
|
|
213
|
+
builder.text(`<${node.tagName}`);
|
|
214
|
+
addAttributes(builder, node.attributes);
|
|
215
|
+
builder.text(`/>`);
|
|
141
216
|
}
|
|
142
217
|
|
|
143
|
-
function
|
|
144
|
-
{
|
|
145
|
-
)
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
...children.flatMap((c) => nodeToHtmlChunk(c)),
|
|
150
|
-
new TextChunk(closeTag(tagName))
|
|
151
|
-
]
|
|
218
|
+
function textOnlyElementToHtmlChunks(builder: HtmlChunksBuilder, node: Template.TextOnlyElement) {
|
|
219
|
+
builder.text(`<${node.tagName}`);
|
|
220
|
+
addAttributes(builder, node.attributes);
|
|
221
|
+
builder.text(">");
|
|
222
|
+
if (node.textContent !== null) {
|
|
223
|
+
textContentToHtml(builder, node.textContent);
|
|
152
224
|
}
|
|
153
225
|
|
|
154
|
-
|
|
155
|
-
new TextChunk(openTag(tagName)),
|
|
156
|
-
...attributes.map((a) => attributeToHtmlChunk(a)),
|
|
157
|
-
new TextChunk(">"),
|
|
158
|
-
...children.flatMap((c) => nodeToHtmlChunk(c)),
|
|
159
|
-
new TextChunk(closeTag(tagName))
|
|
160
|
-
]
|
|
161
|
-
|
|
162
|
-
return chunks
|
|
226
|
+
builder.text(`</${node.tagName}>`);
|
|
163
227
|
}
|
|
164
228
|
|
|
165
|
-
function
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
229
|
+
function textContentToHtml(builder: HtmlChunksBuilder, textContent: Template.Text) {
|
|
230
|
+
switch (textContent._tag) {
|
|
231
|
+
case "text":
|
|
232
|
+
return builder.text(textContent.value);
|
|
233
|
+
case "text-part":
|
|
234
|
+
return builder.part(textContent, (v) => renderToString(v, ""));
|
|
235
|
+
case "sparse-text":
|
|
236
|
+
return builder.sparsePart(textContent, (v) => renderToString(v, ""));
|
|
170
237
|
}
|
|
238
|
+
}
|
|
171
239
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
new TextChunk(`/>`)
|
|
176
|
-
]
|
|
177
|
-
|
|
178
|
-
return chunks
|
|
240
|
+
function nodeToHtmlChunk(builder: HtmlChunksBuilder, node: Template.Node) {
|
|
241
|
+
const handler = nodeMap[node._tag];
|
|
242
|
+
handler(builder, node as never);
|
|
179
243
|
}
|
|
180
244
|
|
|
181
|
-
function
|
|
182
|
-
|
|
245
|
+
function elementToHtmlChunks(
|
|
246
|
+
builder: HtmlChunksBuilder,
|
|
247
|
+
{ attributes, children, tagName }: Template.ElementNode,
|
|
248
|
+
) {
|
|
249
|
+
builder.text(`<${tagName}`);
|
|
250
|
+
addAttributes(builder, attributes);
|
|
251
|
+
builder.text(">");
|
|
252
|
+
for (const child of children) nodeToHtmlChunk(builder, child);
|
|
253
|
+
builder.text(`</${tagName}>`);
|
|
183
254
|
}
|
|
184
255
|
|
|
185
|
-
function
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
256
|
+
function addAttributes(builder: HtmlChunksBuilder, attributes: ReadonlyArray<Template.Attribute>) {
|
|
257
|
+
if (attributes.length > 0) {
|
|
258
|
+
const lastIndex = attributes.length - 1;
|
|
259
|
+
for (const [index, attribute] of sortAttributes(attributes).entries()) {
|
|
260
|
+
attributeToHtmlChunk(builder, attribute, {
|
|
261
|
+
isFirst: index === 0,
|
|
262
|
+
isLast: index === lastIndex,
|
|
263
|
+
});
|
|
264
|
+
}
|
|
194
265
|
}
|
|
195
|
-
|
|
196
|
-
const chunks: Array<HtmlChunk> = [
|
|
197
|
-
new TextChunk(openTag(tagName)),
|
|
198
|
-
...attributes.map((a) => attributeToHtmlChunk(a)),
|
|
199
|
-
new TextChunk(">"),
|
|
200
|
-
...children.map((c) => textToHtmlChunks(c)),
|
|
201
|
-
new TextChunk(closeTag(tagName))
|
|
202
|
-
]
|
|
203
|
-
|
|
204
|
-
return chunks
|
|
205
266
|
}
|
|
206
267
|
|
|
207
|
-
type
|
|
208
|
-
|
|
268
|
+
type Placement = {
|
|
269
|
+
readonly isFirst: boolean;
|
|
270
|
+
readonly isLast: boolean;
|
|
271
|
+
};
|
|
272
|
+
|
|
273
|
+
type AttributeMap = {
|
|
274
|
+
readonly [K in Template.Attribute["_tag"]]: (
|
|
275
|
+
builder: HtmlChunksBuilder,
|
|
276
|
+
attribute: Extract<Template.Attribute, { _tag: K }>,
|
|
277
|
+
placement: Placement,
|
|
278
|
+
) => void;
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
function attributeToHtmlChunk(
|
|
282
|
+
builder: HtmlChunksBuilder,
|
|
283
|
+
attr: Template.Attribute,
|
|
284
|
+
placement: Placement,
|
|
285
|
+
): void {
|
|
286
|
+
attributeMap[attr._tag](builder, attr as never, placement);
|
|
209
287
|
}
|
|
210
288
|
|
|
211
|
-
const
|
|
212
|
-
attribute: (
|
|
213
|
-
|
|
214
|
-
boolean: (
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
return ` class="${escape(v)}"`
|
|
244
|
-
case "data": {
|
|
245
|
-
const d = datasetToString(v)
|
|
246
|
-
return d.length === 0 ? "" : ` ${d}`
|
|
247
|
-
}
|
|
248
|
-
default:
|
|
249
|
-
return ""
|
|
250
|
-
}
|
|
251
|
-
}
|
|
289
|
+
const attributeMap: AttributeMap = {
|
|
290
|
+
attribute: (builder, attribute, placement) =>
|
|
291
|
+
builder.text(addAttributeSpace(`${attribute.name}="${attribute.value}"`, placement)),
|
|
292
|
+
boolean: (builder, attribute, placement) =>
|
|
293
|
+
builder.text(addAttributeSpace(`${attribute.name}`, placement)),
|
|
294
|
+
attr: (builder, attribute, placement) =>
|
|
295
|
+
builder.part(attribute, (v) =>
|
|
296
|
+
addAttributeSpace(`${attribute.name}="${renderToEscapedString(v, "")}"`, placement),
|
|
297
|
+
),
|
|
298
|
+
"sparse-attr": (builder, attribute, placement) =>
|
|
299
|
+
builder.sparsePart(attribute, (v) =>
|
|
300
|
+
addAttributeSpace(`${attribute.name}="${renderToEscapedString(v, "")}"`, placement),
|
|
301
|
+
),
|
|
302
|
+
"boolean-part": (builder, attribute, placement) =>
|
|
303
|
+
builder.part(attribute, (v) => addAttributeSpace(v ? `${attribute.name}` : "", placement)),
|
|
304
|
+
"className-part": (builder, attribute, placement) =>
|
|
305
|
+
builder.part(attribute, (v) =>
|
|
306
|
+
addAttributeSpace(`class="${renderToEscapedString(v, " ")}"`, placement),
|
|
307
|
+
),
|
|
308
|
+
"sparse-class-name": (builder, attribute, placement) =>
|
|
309
|
+
builder.sparsePart(attribute, (v) =>
|
|
310
|
+
addAttributeSpace(`class="${renderToEscapedString(v, "")}"`, placement),
|
|
311
|
+
),
|
|
312
|
+
data: (builder, attribute) =>
|
|
313
|
+
builder.part(attribute, (v) => (Predicate.isObject(v) ? recordWithPrefix(`data-`, v) : "")),
|
|
314
|
+
property: (builder, attribute, placement) =>
|
|
315
|
+
builder.part(attribute, (v) =>
|
|
316
|
+
addAttributeSpace(`${attribute.name}="${renderToEscapedString(v, "")}"`, placement),
|
|
317
|
+
),
|
|
318
|
+
properties: (builder, attribute, placement) =>
|
|
319
|
+
builder.part(attribute, (v) =>
|
|
320
|
+
addAttributeSpace(Predicate.isObject(v) ? recordWithPrefix(``, v) : "", placement),
|
|
252
321
|
),
|
|
253
|
-
ref: () => new TextChunk(""),
|
|
254
|
-
"sparse-attr": (attr) =>
|
|
255
|
-
new SparsePartChunk(attr, (values) => {
|
|
256
|
-
return values == null
|
|
257
|
-
? ``
|
|
258
|
-
: ` ${attr.name}="${Array.isArray(values) ? escape(values.filter(isString).join("")) : escape(values)}"`
|
|
259
|
-
}),
|
|
260
|
-
"sparse-class-name": (attr) =>
|
|
261
|
-
new SparsePartChunk(attr, (values) => {
|
|
262
|
-
return values == null
|
|
263
|
-
? ``
|
|
264
|
-
: ` class="${Array.isArray(values) ? escape(values.filter(isString).join("")) : escape(values)}"`
|
|
265
|
-
}),
|
|
266
|
-
text: (attr) => new TextChunk(attr.value)
|
|
267
|
-
}
|
|
268
322
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
323
|
+
// Don't have HTML representations for these
|
|
324
|
+
ref: constVoid,
|
|
325
|
+
event: constVoid,
|
|
326
|
+
};
|
|
272
327
|
|
|
273
|
-
function
|
|
274
|
-
|
|
328
|
+
function addAttributeSpace(str: string, placement: Placement) {
|
|
329
|
+
if (str.length === 0) return str;
|
|
330
|
+
if (placement.isFirst) return " " + str + (placement.isLast ? "" : " ");
|
|
331
|
+
return str + (placement.isLast ? "" : " ");
|
|
275
332
|
}
|
|
276
333
|
|
|
277
|
-
function
|
|
278
|
-
const s = Object.entries(
|
|
279
|
-
.map(([key, value]) =>
|
|
280
|
-
|
|
334
|
+
function recordWithPrefix(prefix: string, r: {}) {
|
|
335
|
+
const s = Object.entries(r)
|
|
336
|
+
.map(([key, value]) =>
|
|
337
|
+
value === undefined
|
|
338
|
+
? `${prefix}${key}`
|
|
339
|
+
: `${prefix}${key}="${renderToEscapedString(value, "")}"`,
|
|
340
|
+
)
|
|
341
|
+
.join(" ");
|
|
281
342
|
|
|
282
|
-
return s.length === 0 ? "" : " " + s
|
|
343
|
+
return s.length === 0 ? "" : " " + s;
|
|
283
344
|
}
|
|
284
345
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
346
|
+
const AttributeOrder = Order.mapInput(
|
|
347
|
+
Order.Number,
|
|
348
|
+
// Order such that static attributes can be streamed out first
|
|
349
|
+
// and sparse attributes can be streamed out last
|
|
350
|
+
(attr: Template.Attribute) => (isStaticAttribute(attr) ? -1 : isSparseAttribute(attr) ? 1 : 0),
|
|
351
|
+
);
|
|
288
352
|
|
|
289
|
-
|
|
290
|
-
return `</${tagName}>`
|
|
291
|
-
}
|
|
353
|
+
const sortAttributes = Array.sortBy(AttributeOrder);
|
|
292
354
|
|
|
293
|
-
|
|
294
|
-
* @since 1.0.0
|
|
295
|
-
*/
|
|
296
|
-
export function escape(s: unknown): string {
|
|
297
|
-
switch (typeof s) {
|
|
298
|
-
case "string":
|
|
299
|
-
case "number":
|
|
300
|
-
case "boolean":
|
|
301
|
-
case "bigint":
|
|
302
|
-
return escapeHtml(String(s))
|
|
303
|
-
case "object": {
|
|
304
|
-
if (isNullOrUndefined(s)) {
|
|
305
|
-
return ""
|
|
306
|
-
} else if (Array.isArray(s)) {
|
|
307
|
-
return s.map(escape).join("")
|
|
308
|
-
} else if (s instanceof Date) {
|
|
309
|
-
return escapeHtml(s.toISOString())
|
|
310
|
-
} else if (s instanceof RegExp) {
|
|
311
|
-
return escapeHtml(s.toString())
|
|
312
|
-
} else {
|
|
313
|
-
return escapeHtml(JSON.stringify(s))
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
default:
|
|
317
|
-
return escapeHtml(JSON.stringify(s))
|
|
318
|
-
}
|
|
319
|
-
}
|
|
355
|
+
const staticAttributes = new Set<Template.Attribute["_tag"]>(["attribute", "boolean"]);
|
|
320
356
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
*/
|
|
324
|
-
export function unescape(s: string) {
|
|
325
|
-
const unescaped = unescapeHtml(s)
|
|
326
|
-
const couldBeJson = unescaped[0] === "[" || unescaped === "{"
|
|
327
|
-
if (couldBeJson) {
|
|
328
|
-
try {
|
|
329
|
-
return JSON.parse(unescaped)
|
|
330
|
-
} catch {
|
|
331
|
-
return unescaped
|
|
332
|
-
}
|
|
333
|
-
} else {
|
|
334
|
-
return unescaped
|
|
335
|
-
}
|
|
357
|
+
function isStaticAttribute(attr: Template.Attribute) {
|
|
358
|
+
return staticAttributes.has(attr._tag);
|
|
336
359
|
}
|
|
337
360
|
|
|
338
|
-
const
|
|
339
|
-
[/"/g, "\""],
|
|
340
|
-
[/'/g, "'"],
|
|
341
|
-
[/:/g, ":"],
|
|
342
|
-
[/</g, "<"],
|
|
343
|
-
[/>/g, ">"],
|
|
344
|
-
[/&/g, "&"]
|
|
345
|
-
] as const
|
|
346
|
-
|
|
347
|
-
const matchHtmlRegExp = /["'&<>]/
|
|
348
|
-
|
|
349
|
-
/**
|
|
350
|
-
* @since 1.0.0
|
|
351
|
-
*/
|
|
352
|
-
export function escapeHtml(str: string): string {
|
|
353
|
-
const match = matchHtmlRegExp.exec(str)
|
|
354
|
-
|
|
355
|
-
if (!match) {
|
|
356
|
-
return str
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
let escape
|
|
360
|
-
let html = ""
|
|
361
|
-
let index = 0
|
|
362
|
-
let lastIndex = 0
|
|
363
|
-
|
|
364
|
-
for (index = match.index; index < str.length; index++) {
|
|
365
|
-
switch (str.charCodeAt(index)) {
|
|
366
|
-
case 34: // "
|
|
367
|
-
escape = """
|
|
368
|
-
break
|
|
369
|
-
case 38: // &
|
|
370
|
-
escape = "&"
|
|
371
|
-
break
|
|
372
|
-
case 39: // '
|
|
373
|
-
escape = "'"
|
|
374
|
-
break
|
|
375
|
-
case 60: // <
|
|
376
|
-
escape = "<"
|
|
377
|
-
break
|
|
378
|
-
case 62: // >
|
|
379
|
-
escape = ">"
|
|
380
|
-
break
|
|
381
|
-
default:
|
|
382
|
-
continue
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
if (lastIndex !== index) {
|
|
386
|
-
html += str.substring(lastIndex, index)
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
lastIndex = index + 1
|
|
390
|
-
html += escape
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
return lastIndex !== index
|
|
394
|
-
? html + str.substring(lastIndex, index)
|
|
395
|
-
: html
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
/**
|
|
399
|
-
* @since 1.0.0
|
|
400
|
-
*/
|
|
401
|
-
export function unescapeHtml(html: string) {
|
|
402
|
-
for (const [from, to] of unescapeHtmlRules) {
|
|
403
|
-
html = html.replace(from, to)
|
|
404
|
-
}
|
|
361
|
+
const sparseAttributes = new Set<Template.Attribute["_tag"]>(["sparse-attr", "sparse-class-name"]);
|
|
405
362
|
|
|
406
|
-
|
|
363
|
+
function isSparseAttribute(attr: Template.Attribute) {
|
|
364
|
+
return sparseAttributes.has(attr._tag);
|
|
407
365
|
}
|