@maizzle/framework 6.0.0-rc.1 → 6.0.0-rc.11
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/bin/maizzle.mjs +1 -1
- package/dist/_virtual/_rolldown/runtime.mjs +32 -0
- package/dist/build.mjs +6 -3
- package/dist/build.mjs.map +1 -1
- package/dist/components/Body.vue +111 -0
- package/dist/components/Button.vue +68 -14
- package/dist/components/CodeBlock.vue +68 -0
- package/dist/components/CodeInline.vue +49 -0
- package/dist/components/Column.vue +78 -0
- package/dist/components/Container.vue +53 -0
- package/dist/components/Divider.vue +28 -0
- package/dist/components/Head.vue +30 -0
- package/dist/components/Heading.vue +28 -0
- package/dist/components/Html.vue +104 -0
- package/dist/components/Img.vue +70 -0
- package/dist/components/Layout.vue +93 -0
- package/dist/components/Link.vue +26 -0
- package/dist/components/Markdown.vue +89 -0
- package/dist/components/Outlook.vue +36 -0
- package/dist/components/Overlap.vue +84 -0
- package/dist/components/Preheader.vue +20 -0
- package/dist/components/Row.vue +91 -0
- package/dist/components/Section.vue +83 -0
- package/dist/components/Spacer.vue +50 -7
- package/dist/components/Text.vue +29 -0
- package/dist/components/Vml.vue +165 -13
- package/dist/composables/renderContext.d.mts +5 -0
- package/dist/composables/renderContext.d.mts.map +1 -1
- package/dist/composables/renderContext.mjs.map +1 -1
- package/dist/composables/usePreheader.d.mts +24 -0
- package/dist/composables/usePreheader.d.mts.map +1 -0
- package/dist/composables/usePreheader.mjs +29 -0
- package/dist/composables/usePreheader.mjs.map +1 -0
- package/dist/config/defaults.mjs +1 -3
- package/dist/config/defaults.mjs.map +1 -1
- package/dist/config/index.mjs +7 -0
- package/dist/config/index.mjs.map +1 -1
- package/dist/index.d.mts +4 -2
- package/dist/index.mjs +3 -1
- package/dist/node_modules/picomatch/index.mjs +13 -0
- package/dist/node_modules/picomatch/index.mjs.map +1 -0
- package/dist/node_modules/picomatch/lib/constants.mjs +174 -0
- package/dist/node_modules/picomatch/lib/constants.mjs.map +1 -0
- package/dist/node_modules/picomatch/lib/parse.mjs +1067 -0
- package/dist/node_modules/picomatch/lib/parse.mjs.map +1 -0
- package/dist/node_modules/picomatch/lib/picomatch.mjs +304 -0
- package/dist/node_modules/picomatch/lib/picomatch.mjs.map +1 -0
- package/dist/node_modules/picomatch/lib/scan.mjs +296 -0
- package/dist/node_modules/picomatch/lib/scan.mjs.map +1 -0
- package/dist/node_modules/picomatch/lib/utils.mjs +53 -0
- package/dist/node_modules/picomatch/lib/utils.mjs.map +1 -0
- package/dist/plugin.d.mts.map +1 -1
- package/dist/plugin.mjs +24 -7
- package/dist/plugin.mjs.map +1 -1
- package/dist/plugins/postcss/resolveProps.d.mts +8 -0
- package/dist/plugins/postcss/resolveProps.d.mts.map +1 -0
- package/dist/plugins/postcss/resolveProps.mjs +144 -0
- package/dist/plugins/postcss/resolveProps.mjs.map +1 -0
- package/dist/plugins/postcss/tailwindCleanup.d.mts.map +1 -1
- package/dist/plugins/postcss/tailwindCleanup.mjs +46 -13
- package/dist/plugins/postcss/tailwindCleanup.mjs.map +1 -1
- package/dist/render/createRenderer.d.mts +8 -3
- package/dist/render/createRenderer.d.mts.map +1 -1
- package/dist/render/createRenderer.mjs +146 -10
- package/dist/render/createRenderer.mjs.map +1 -1
- package/dist/render/index.mjs +6 -3
- package/dist/render/index.mjs.map +1 -1
- package/dist/serve.d.mts.map +1 -1
- package/dist/serve.mjs +157 -63
- package/dist/serve.mjs.map +1 -1
- package/dist/server/compatibility.d.mts +1 -2
- package/dist/server/compatibility.d.mts.map +1 -1
- package/dist/server/compatibility.mjs +30 -16
- package/dist/server/compatibility.mjs.map +1 -1
- package/dist/server/email.d.mts +17 -0
- package/dist/server/email.d.mts.map +1 -0
- package/dist/server/email.mjs +41 -0
- package/dist/server/email.mjs.map +1 -0
- package/dist/server/linter.d.mts +1 -2
- package/dist/server/linter.d.mts.map +1 -1
- package/dist/server/linter.mjs +60 -71
- package/dist/server/linter.mjs.map +1 -1
- package/dist/server/ui/App.vue +206 -70
- package/dist/server/ui/components/ui/checkbox/Checkbox.vue +35 -0
- package/dist/server/ui/components/ui/checkbox/index.ts +1 -0
- package/dist/server/ui/components/ui/command/CommandDialog.vue +1 -1
- package/dist/server/ui/components/ui/command/CommandInput.vue +19 -1
- package/dist/server/ui/components/ui/command/CommandItem.vue +1 -1
- package/dist/server/ui/components/ui/command/CommandList.vue +1 -1
- package/dist/server/ui/components/ui/command/CommandShortcut.vue +1 -1
- package/dist/server/ui/components/ui/dialog/DialogOverlay.vue +9 -1
- package/dist/server/ui/components/ui/dropdown-menu/DropdownMenuItem.vue +1 -1
- package/dist/server/ui/components/ui/scroll-area/ScrollBar.vue +1 -1
- package/dist/server/ui/components/ui/sheet/SheetContent.vue +1 -1
- package/dist/server/ui/components/ui/sheet/SheetOverlay.vue +9 -1
- package/dist/server/ui/components/ui/sidebar/Sidebar.vue +8 -1
- package/dist/server/ui/components/ui/sidebar/SidebarProvider.vue +1 -1
- package/dist/server/ui/components/ui/sidebar/SidebarTrigger.vue +5 -4
- package/dist/server/ui/components/ui/tags-input/TagsInput.vue +26 -0
- package/dist/server/ui/components/ui/tags-input/TagsInputInput.vue +17 -0
- package/dist/server/ui/components/ui/tags-input/TagsInputItem.vue +19 -0
- package/dist/server/ui/components/ui/tags-input/TagsInputItemDelete.vue +22 -0
- package/dist/server/ui/components/ui/tags-input/TagsInputItemText.vue +17 -0
- package/dist/server/ui/components/ui/tags-input/index.ts +5 -0
- package/dist/server/ui/components/ui/toggle/index.ts +3 -3
- package/dist/server/ui/components/ui/toggle-group/ToggleGroup.vue +1 -1
- package/dist/server/ui/components/ui/toggle-group/ToggleGroupItem.vue +2 -2
- package/dist/server/ui/main.css +20 -20
- package/dist/server/ui/pages/Home.vue +12 -5
- package/dist/server/ui/pages/Preview.vue +506 -216
- package/dist/transformers/entities.d.mts.map +1 -1
- package/dist/transformers/entities.mjs +3 -0
- package/dist/transformers/entities.mjs.map +1 -1
- package/dist/transformers/filters/defaults.d.mts +6 -0
- package/dist/transformers/filters/defaults.d.mts.map +1 -0
- package/dist/transformers/filters/defaults.mjs +78 -0
- package/dist/transformers/filters/defaults.mjs.map +1 -0
- package/dist/transformers/filters/index.d.mts +22 -0
- package/dist/transformers/filters/index.d.mts.map +1 -0
- package/dist/transformers/filters/index.mjs +67 -0
- package/dist/transformers/filters/index.mjs.map +1 -0
- package/dist/transformers/index.d.mts +11 -9
- package/dist/transformers/index.d.mts.map +1 -1
- package/dist/transformers/index.mjs +19 -11
- package/dist/transformers/index.mjs.map +1 -1
- package/dist/transformers/inlineCSS.d.mts +1 -14
- package/dist/transformers/inlineCSS.d.mts.map +1 -1
- package/dist/transformers/inlineCSS.mjs +32 -36
- package/dist/transformers/inlineCSS.mjs.map +1 -1
- package/dist/transformers/purgeCSS.d.mts.map +1 -1
- package/dist/transformers/purgeCSS.mjs +67 -1
- package/dist/transformers/purgeCSS.mjs.map +1 -1
- package/dist/transformers/sixHex.d.mts +16 -0
- package/dist/transformers/sixHex.d.mts.map +1 -0
- package/dist/transformers/sixHex.mjs +30 -0
- package/dist/transformers/sixHex.mjs.map +1 -0
- package/dist/transformers/tailwindcss.d.mts +6 -2
- package/dist/transformers/tailwindcss.d.mts.map +1 -1
- package/dist/transformers/tailwindcss.mjs +54 -30
- package/dist/transformers/tailwindcss.mjs.map +1 -1
- package/dist/types/config.d.mts +436 -23
- package/dist/types/config.d.mts.map +1 -1
- package/dist/types/index.d.mts +2 -2
- package/dist/utils/ast/serializer.d.mts +3 -2
- package/dist/utils/ast/serializer.d.mts.map +1 -1
- package/dist/utils/ast/serializer.mjs +24 -0
- package/dist/utils/ast/serializer.mjs.map +1 -1
- package/dist/utils/detect.d.mts +5 -0
- package/dist/utils/detect.d.mts.map +1 -0
- package/dist/utils/detect.mjs +11 -0
- package/dist/utils/detect.mjs.map +1 -0
- package/node_modules/@clack/core/CHANGELOG.md +87 -4
- package/node_modules/@clack/core/README.md +1 -1
- package/node_modules/@clack/core/dist/index.d.mts +186 -48
- package/node_modules/@clack/core/dist/index.mjs +10 -14
- package/node_modules/@clack/core/dist/index.mjs.map +1 -1
- package/node_modules/@clack/core/package.json +7 -9
- package/node_modules/@clack/prompts/CHANGELOG.md +171 -7
- package/node_modules/@clack/prompts/README.md +66 -3
- package/node_modules/@clack/prompts/dist/index.d.mts +302 -76
- package/node_modules/@clack/prompts/dist/index.mjs +134 -84
- package/node_modules/@clack/prompts/dist/index.mjs.map +1 -1
- package/node_modules/@clack/prompts/package.json +14 -10
- package/node_modules/citty/LICENSE +0 -15
- package/node_modules/citty/README.md +166 -69
- package/node_modules/citty/dist/index.d.mts +88 -56
- package/node_modules/citty/dist/index.mjs +399 -437
- package/node_modules/citty/package.json +28 -35
- package/node_modules/giget/README.md +59 -11
- package/node_modules/giget/dist/THIRD-PARTY-LICENSES.md +205 -0
- package/node_modules/giget/dist/_chunks/giget.mjs +508 -0
- package/node_modules/giget/dist/_chunks/libs/citty.mjs +269 -0
- package/node_modules/giget/dist/_chunks/libs/nypm.d.mts +1 -0
- package/node_modules/giget/dist/_chunks/libs/nypm.mjs +669 -0
- package/node_modules/giget/dist/_chunks/libs/tar.mjs +2931 -0
- package/node_modules/giget/dist/_chunks/rolldown-runtime.mjs +14 -0
- package/node_modules/giget/dist/cli.d.mts +1 -0
- package/node_modules/giget/dist/cli.mjs +89 -111
- package/node_modules/giget/dist/index.d.mts +46 -35
- package/node_modules/giget/dist/index.mjs +2 -22
- package/node_modules/giget/package.json +32 -45
- package/node_modules/maizzle/README.md +140 -0
- package/node_modules/maizzle/bin/maizzle.mjs +5 -0
- package/node_modules/maizzle/dist/commands/new.d.mts +7 -0
- package/node_modules/maizzle/dist/commands/new.mjs +253 -0
- package/node_modules/{@maizzle/cli → maizzle}/dist/index.d.mts +1 -1
- package/node_modules/maizzle/dist/index.mjs +44 -0
- package/node_modules/{commander → maizzle/node_modules/commander}/Readme.md +94 -67
- package/node_modules/{commander → maizzle/node_modules/commander}/lib/argument.js +5 -4
- package/node_modules/{commander → maizzle/node_modules/commander}/lib/command.js +154 -39
- package/node_modules/{commander → maizzle/node_modules/commander}/lib/help.js +77 -39
- package/node_modules/{commander → maizzle/node_modules/commander}/lib/option.js +16 -3
- package/node_modules/{commander → maizzle/node_modules/commander}/package-support.json +4 -1
- package/node_modules/{commander → maizzle/node_modules/commander}/package.json +8 -8
- package/node_modules/{commander → maizzle/node_modules/commander}/typings/index.d.ts +71 -3
- package/node_modules/{@maizzle/cli → maizzle}/package.json +14 -12
- package/node_modules/tinyexec/README.md +49 -3
- package/node_modules/tinyexec/dist/main.d.mts +25 -14
- package/node_modules/tinyexec/dist/main.mjs +148 -100
- package/node_modules/tinyexec/package.json +9 -8
- package/package.json +17 -13
- package/dist/server/ui/components/ui/resizable/ResizableHandle.vue +0 -30
- package/dist/server/ui/components/ui/resizable/ResizablePanel.vue +0 -21
- package/dist/server/ui/components/ui/resizable/ResizablePanelGroup.vue +0 -25
- package/dist/server/ui/components/ui/resizable/index.ts +0 -3
- package/node_modules/@clack/core/dist/index.cjs +0 -15
- package/node_modules/@clack/core/dist/index.cjs.map +0 -1
- package/node_modules/@clack/core/dist/index.d.cts +0 -211
- package/node_modules/@clack/core/dist/index.d.ts +0 -211
- package/node_modules/@clack/prompts/dist/index.cjs +0 -87
- package/node_modules/@clack/prompts/dist/index.cjs.map +0 -1
- package/node_modules/@clack/prompts/dist/index.d.cts +0 -165
- package/node_modules/@clack/prompts/dist/index.d.ts +0 -165
- package/node_modules/@maizzle/cli/README.md +0 -58
- package/node_modules/@maizzle/cli/dist/index.mjs +0 -42
- package/node_modules/citty/dist/index.cjs +0 -475
- package/node_modules/citty/dist/index.d.cts +0 -80
- package/node_modules/citty/dist/index.d.ts +0 -80
- package/node_modules/consola/LICENSE +0 -47
- package/node_modules/consola/README.md +0 -352
- package/node_modules/consola/basic.d.ts +0 -1
- package/node_modules/consola/browser.d.ts +0 -1
- package/node_modules/consola/core.d.ts +0 -1
- package/node_modules/consola/dist/basic.cjs +0 -32
- package/node_modules/consola/dist/basic.d.cts +0 -23
- package/node_modules/consola/dist/basic.d.mts +0 -21
- package/node_modules/consola/dist/basic.d.ts +0 -23
- package/node_modules/consola/dist/basic.mjs +0 -24
- package/node_modules/consola/dist/browser.cjs +0 -84
- package/node_modules/consola/dist/browser.d.cts +0 -23
- package/node_modules/consola/dist/browser.d.mts +0 -21
- package/node_modules/consola/dist/browser.d.ts +0 -23
- package/node_modules/consola/dist/browser.mjs +0 -76
- package/node_modules/consola/dist/chunks/prompt.cjs +0 -288
- package/node_modules/consola/dist/chunks/prompt.mjs +0 -280
- package/node_modules/consola/dist/core.cjs +0 -517
- package/node_modules/consola/dist/core.d.cts +0 -459
- package/node_modules/consola/dist/core.d.mts +0 -459
- package/node_modules/consola/dist/core.d.ts +0 -459
- package/node_modules/consola/dist/core.mjs +0 -512
- package/node_modules/consola/dist/index.cjs +0 -663
- package/node_modules/consola/dist/index.d.cts +0 -24
- package/node_modules/consola/dist/index.d.mts +0 -22
- package/node_modules/consola/dist/index.d.ts +0 -24
- package/node_modules/consola/dist/index.mjs +0 -651
- package/node_modules/consola/dist/shared/consola.DCGIlDNP.cjs +0 -75
- package/node_modules/consola/dist/shared/consola.DRwqZj3T.mjs +0 -72
- package/node_modules/consola/dist/shared/consola.DXBYu-KD.mjs +0 -288
- package/node_modules/consola/dist/shared/consola.DwRq1yyg.cjs +0 -312
- package/node_modules/consola/dist/utils.cjs +0 -64
- package/node_modules/consola/dist/utils.d.cts +0 -286
- package/node_modules/consola/dist/utils.d.mts +0 -286
- package/node_modules/consola/dist/utils.d.ts +0 -286
- package/node_modules/consola/dist/utils.mjs +0 -54
- package/node_modules/consola/lib/index.cjs +0 -10
- package/node_modules/consola/package.json +0 -136
- package/node_modules/consola/utils.d.ts +0 -1
- package/node_modules/create-maizzle/README.md +0 -86
- package/node_modules/create-maizzle/bin/create-maizzle.mjs +0 -4
- package/node_modules/create-maizzle/node_modules/@clack/core/CHANGELOG.md +0 -340
- package/node_modules/create-maizzle/node_modules/@clack/core/LICENSE +0 -9
- package/node_modules/create-maizzle/node_modules/@clack/core/README.md +0 -22
- package/node_modules/create-maizzle/node_modules/@clack/core/dist/index.d.mts +0 -349
- package/node_modules/create-maizzle/node_modules/@clack/core/dist/index.mjs +0 -11
- package/node_modules/create-maizzle/node_modules/@clack/core/dist/index.mjs.map +0 -1
- package/node_modules/create-maizzle/node_modules/@clack/core/package.json +0 -60
- package/node_modules/create-maizzle/node_modules/@clack/prompts/CHANGELOG.md +0 -576
- package/node_modules/create-maizzle/node_modules/@clack/prompts/LICENSE +0 -9
- package/node_modules/create-maizzle/node_modules/@clack/prompts/README.md +0 -270
- package/node_modules/create-maizzle/node_modules/@clack/prompts/dist/index.d.mts +0 -391
- package/node_modules/create-maizzle/node_modules/@clack/prompts/dist/index.mjs +0 -137
- package/node_modules/create-maizzle/node_modules/@clack/prompts/dist/index.mjs.map +0 -1
- package/node_modules/create-maizzle/node_modules/@clack/prompts/package.json +0 -65
- package/node_modules/create-maizzle/package.json +0 -47
- package/node_modules/create-maizzle/src/index.js +0 -242
- package/node_modules/defu/LICENSE +0 -21
- package/node_modules/defu/README.md +0 -171
- package/node_modules/defu/dist/defu.cjs +0 -77
- package/node_modules/defu/dist/defu.d.cts +0 -31
- package/node_modules/defu/dist/defu.d.mts +0 -29
- package/node_modules/defu/dist/defu.d.ts +0 -31
- package/node_modules/defu/dist/defu.mjs +0 -69
- package/node_modules/defu/lib/defu.cjs +0 -10
- package/node_modules/defu/lib/defu.d.cts +0 -12
- package/node_modules/defu/package.json +0 -48
- package/node_modules/giget/dist/shared/giget.OCaTp9b-.mjs +0 -468
- package/node_modules/node-fetch-native/LICENSE +0 -114
- package/node_modules/node-fetch-native/README.md +0 -225
- package/node_modules/node-fetch-native/dist/chunks/multipart-parser.cjs +0 -2
- package/node_modules/node-fetch-native/dist/chunks/multipart-parser.mjs +0 -2
- package/node_modules/node-fetch-native/dist/index.cjs +0 -1
- package/node_modules/node-fetch-native/dist/index.mjs +0 -1
- package/node_modules/node-fetch-native/dist/native.cjs +0 -1
- package/node_modules/node-fetch-native/dist/native.mjs +0 -1
- package/node_modules/node-fetch-native/dist/node.cjs +0 -19
- package/node_modules/node-fetch-native/dist/node.mjs +0 -19
- package/node_modules/node-fetch-native/dist/polyfill.cjs +0 -1
- package/node_modules/node-fetch-native/dist/polyfill.mjs +0 -1
- package/node_modules/node-fetch-native/dist/proxy-stub.cjs +0 -1
- package/node_modules/node-fetch-native/dist/proxy-stub.mjs +0 -1
- package/node_modules/node-fetch-native/dist/proxy.cjs +0 -58
- package/node_modules/node-fetch-native/dist/shared/node-fetch-native.DfbY2q-x.mjs +0 -1
- package/node_modules/node-fetch-native/dist/shared/node-fetch-native.DhEqb06g.cjs +0 -1
- package/node_modules/node-fetch-native/index.d.ts +0 -1
- package/node_modules/node-fetch-native/lib/empty.cjs +0 -0
- package/node_modules/node-fetch-native/lib/empty.mjs +0 -0
- package/node_modules/node-fetch-native/lib/index.cjs +0 -11
- package/node_modules/node-fetch-native/lib/index.d.cts +0 -10
- package/node_modules/node-fetch-native/lib/index.d.mts +0 -10
- package/node_modules/node-fetch-native/lib/index.d.ts +0 -10
- package/node_modules/node-fetch-native/lib/native.cjs +0 -11
- package/node_modules/node-fetch-native/lib/polyfill.d.cts +0 -1
- package/node_modules/node-fetch-native/lib/polyfill.d.mts +0 -1
- package/node_modules/node-fetch-native/lib/polyfill.d.ts +0 -1
- package/node_modules/node-fetch-native/lib/proxy.d.ts +0 -32
- package/node_modules/node-fetch-native/node.d.ts +0 -1
- package/node_modules/node-fetch-native/package.json +0 -138
- package/node_modules/node-fetch-native/polyfill.d.ts +0 -1
- package/node_modules/node-fetch-native/proxy.d.ts +0 -1
- package/node_modules/nypm/node_modules/citty/LICENSE +0 -21
- package/node_modules/nypm/node_modules/citty/README.md +0 -231
- package/node_modules/nypm/node_modules/citty/dist/index.d.mts +0 -112
- package/node_modules/nypm/node_modules/citty/dist/index.mjs +0 -425
- package/node_modules/nypm/node_modules/citty/package.json +0 -42
- /package/node_modules/{nypm/node_modules/citty → citty}/dist/THIRD-PARTY-LICENSES.md +0 -0
- /package/node_modules/{nypm/node_modules/citty → citty}/dist/_chunks/libs/scule.mjs +0 -0
- /package/node_modules/{@maizzle/cli → maizzle}/LICENSE +0 -0
- /package/node_modules/{@maizzle/cli → maizzle}/dist/commands/make/component.d.mts +0 -0
- /package/node_modules/{@maizzle/cli → maizzle}/dist/commands/make/component.mjs +0 -0
- /package/node_modules/{@maizzle/cli → maizzle}/dist/commands/make/config.d.mts +0 -0
- /package/node_modules/{@maizzle/cli → maizzle}/dist/commands/make/config.mjs +0 -0
- /package/node_modules/{@maizzle/cli → maizzle}/dist/commands/make/layout.d.mts +0 -0
- /package/node_modules/{@maizzle/cli → maizzle}/dist/commands/make/layout.mjs +0 -0
- /package/node_modules/{@maizzle/cli → maizzle}/dist/commands/make/scaffold.d.mts +0 -0
- /package/node_modules/{@maizzle/cli → maizzle}/dist/commands/make/scaffold.mjs +0 -0
- /package/node_modules/{@maizzle/cli → maizzle}/dist/commands/make/stubs/component.vue +0 -0
- /package/node_modules/{@maizzle/cli → maizzle}/dist/commands/make/stubs/config.ts +0 -0
- /package/node_modules/{@maizzle/cli → maizzle}/dist/commands/make/stubs/layout.vue +0 -0
- /package/node_modules/{@maizzle/cli → maizzle}/dist/commands/make/stubs/template.vue +0 -0
- /package/node_modules/{@maizzle/cli → maizzle}/dist/commands/make/template.d.mts +0 -0
- /package/node_modules/{@maizzle/cli → maizzle}/dist/commands/make/template.mjs +0 -0
- /package/node_modules/{commander → maizzle/node_modules/commander}/LICENSE +0 -0
- /package/node_modules/{commander → maizzle/node_modules/commander}/esm.mjs +0 -0
- /package/node_modules/{commander → maizzle/node_modules/commander}/index.js +0 -0
- /package/node_modules/{commander → maizzle/node_modules/commander}/lib/error.js +0 -0
- /package/node_modules/{commander → maizzle/node_modules/commander}/lib/suggestSimilar.js +0 -0
- /package/node_modules/{commander → maizzle/node_modules/commander}/typings/esm.d.mts +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entities.d.mts","names":[],"sources":["../../src/transformers/entities.ts"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"entities.d.mts","names":[],"sources":["../../src/transformers/entities.ts"],"mappings":";;;;iBA8BgB,QAAA,CAAS,GAAA,EAAK,SAAA,IAAa,MAAA,GAAQ,cAAA,GAAwB,SAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entities.mjs","names":["merge"],"sources":["../../src/transformers/entities.ts"],"sourcesContent":["import { defu as merge } from 'defu'\nimport { walk } from '../utils/ast/index.ts'\nimport type { ChildNode } from 'domhandler'\nimport type { EntitiesConfig } from '../types/index.ts'\n\nconst DEFAULT_ENTITIES: Record<string, string> = {\n '\\u200D': '‍',\n '\\u200C': '‌',\n '\\u00A0': ' ',\n '\\u200B': '​',\n '\\u2003': ' ',\n '\\u2028': '&LineSeparator;',\n '\\u2029': '&ParagraphSeparator;',\n '\\u00B7': '·',\n '\\u2013': '–',\n '\\u2014': '—',\n '\\u2018': '‘',\n '\\u2019': '’',\n '\\u201C': '“',\n '\\u201D': '”',\n '\\u00AB': '«',\n '\\u00BB': '»',\n '\\u2022': '•',\n '\\u2039': '‹',\n '\\u203A': '›'\n}\n\nexport function entities(dom: ChildNode[], config: EntitiesConfig = true): ChildNode[] {\n if (!config) return dom\n\n const map = typeof config === 'object'\n ? merge(config as Record<string, string>, DEFAULT_ENTITIES)\n : DEFAULT_ENTITIES\n\n walk(dom, (node) => {\n if (node.type === 'text') {\n for (const [char, entity] of Object.entries(map)) {\n node.data = node.data.split(char).join(entity)\n }\n }\n })\n\n return dom\n}\n"],"mappings":";;;;;AAKA,MAAM,mBAA2C;CAC/C,KAAU;CACV,KAAU;CACV,QAAU;CACV,KAAU;CACV,KAAU;CACV,UAAU;CACV,UAAU;CACV,KAAU;CACV,KAAU;CACV,KAAU;CACV,KAAU;CACV,KAAU;CACV,KAAU;CACV,KAAU;CACV,KAAU;CACV,KAAU;CACV,KAAU;CACV,KAAU;CACV,KAAU;CACX;AAED,SAAgB,SAAS,KAAkB,SAAyB,MAAmB;AACrF,KAAI,CAAC,OAAQ,QAAO;CAEpB,MAAM,MAAM,OAAO,WAAW,WAC1BA,KAAM,QAAkC,iBAAiB,GACzD;AAEJ,MAAK,MAAM,SAAS;AAClB,MAAI,KAAK,SAAS,OAChB,MAAK,MAAM,CAAC,MAAM,WAAW,OAAO,QAAQ,IAAI,CAC9C,MAAK,OAAO,KAAK,KAAK,MAAM,KAAK,CAAC,KAAK,OAAO;GAGlD;AAEF,QAAO"}
|
|
1
|
+
{"version":3,"file":"entities.mjs","names":["merge"],"sources":["../../src/transformers/entities.ts"],"sourcesContent":["import { defu as merge } from 'defu'\nimport { walk } from '../utils/ast/index.ts'\nimport type { ChildNode } from 'domhandler'\nimport type { EntitiesConfig } from '../types/index.ts'\n\nconst DEFAULT_ENTITIES: Record<string, string> = {\n '\\u200D': '‍',\n '\\u200C': '‌',\n '\\u00A0': ' ',\n '\\u00AD': '­',\n '\\u200B': '​',\n '\\u2007': ' ',\n '\\u034F': '͏',\n '\\u2003': ' ',\n '\\u2028': '&LineSeparator;',\n '\\u2029': '&ParagraphSeparator;',\n '\\u00B7': '·',\n '\\u2013': '–',\n '\\u2014': '—',\n '\\u2018': '‘',\n '\\u2019': '’',\n '\\u201C': '“',\n '\\u201D': '”',\n '\\u00AB': '«',\n '\\u00BB': '»',\n '\\u2022': '•',\n '\\u2039': '‹',\n '\\u203A': '›'\n}\n\nexport function entities(dom: ChildNode[], config: EntitiesConfig = true): ChildNode[] {\n if (!config) return dom\n\n const map = typeof config === 'object'\n ? merge(config as Record<string, string>, DEFAULT_ENTITIES)\n : DEFAULT_ENTITIES\n\n walk(dom, (node) => {\n if (node.type === 'text') {\n for (const [char, entity] of Object.entries(map)) {\n node.data = node.data.split(char).join(entity)\n }\n }\n })\n\n return dom\n}\n"],"mappings":";;;;;AAKA,MAAM,mBAA2C;CAC/C,KAAU;CACV,KAAU;CACV,QAAU;CACV,KAAU;CACV,KAAU;CACV,KAAU;CACV,KAAU;CACV,KAAU;CACV,UAAU;CACV,UAAU;CACV,KAAU;CACV,KAAU;CACV,KAAU;CACV,KAAU;CACV,KAAU;CACV,KAAU;CACV,KAAU;CACV,KAAU;CACV,KAAU;CACV,KAAU;CACV,KAAU;CACV,KAAU;CACX;AAED,SAAgB,SAAS,KAAkB,SAAyB,MAAmB;AACrF,KAAI,CAAC,OAAQ,QAAO;CAEpB,MAAM,MAAM,OAAO,WAAW,WAC1BA,KAAM,QAAkC,iBAAiB,GACzD;AAEJ,MAAK,MAAM,SAAS;AAClB,MAAI,KAAK,SAAS,OAChB,MAAK,MAAM,CAAC,MAAM,WAAW,OAAO,QAAQ,IAAI,CAC9C,MAAK,OAAO,KAAK,KAAK,MAAM,KAAK,CAAC,KAAK,OAAO;GAGlD;AAEF,QAAO"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defaults.d.mts","names":[],"sources":["../../../src/transformers/filters/defaults.ts"],"mappings":";KAAY,cAAA,IAAkB,GAAA,UAAa,KAAA;AAAA,cAgB9B,QAAA,EAAU,MAAA,SAAe,cAAA"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
//#region src/transformers/filters/defaults.ts
|
|
2
|
+
const escapeMap = {
|
|
3
|
+
"\"": """,
|
|
4
|
+
"&": "&",
|
|
5
|
+
"'": "'",
|
|
6
|
+
"<": "<",
|
|
7
|
+
">": ">"
|
|
8
|
+
};
|
|
9
|
+
const escapeRegex = /["&'<>]/g;
|
|
10
|
+
function escapeHtml(str) {
|
|
11
|
+
return str.replace(escapeRegex, (ch) => escapeMap[ch]);
|
|
12
|
+
}
|
|
13
|
+
const defaults = {
|
|
14
|
+
append: (str, value) => str + value,
|
|
15
|
+
prepend: (str, value) => value + str,
|
|
16
|
+
uppercase: (str) => str.toUpperCase(),
|
|
17
|
+
lowercase: (str) => str.toLowerCase(),
|
|
18
|
+
capitalize: (str) => str.charAt(0).toUpperCase() + str.slice(1),
|
|
19
|
+
ceil: (str) => String(Math.ceil(Number.parseFloat(str))),
|
|
20
|
+
floor: (str) => String(Math.floor(Number.parseFloat(str))),
|
|
21
|
+
round: (str) => String(Math.round(Number.parseFloat(str))),
|
|
22
|
+
escape: (str) => escapeHtml(str),
|
|
23
|
+
"escape-once": (str) => {
|
|
24
|
+
return escapeHtml(str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, "\"").replace(/"/g, "\"").replace(/'/g, "'").replace(/'/g, "'"));
|
|
25
|
+
},
|
|
26
|
+
lstrip: (str) => str.trimStart(),
|
|
27
|
+
rstrip: (str) => str.trimEnd(),
|
|
28
|
+
trim: (str) => str.trim(),
|
|
29
|
+
minus: (str, value) => String(Number.parseFloat(str) - Number.parseFloat(value)),
|
|
30
|
+
plus: (str, value) => String(Number.parseFloat(str) + Number.parseFloat(value)),
|
|
31
|
+
multiply: (str, value) => String(Number.parseFloat(str) * Number.parseFloat(value)),
|
|
32
|
+
times: (str, value) => String(Number.parseFloat(str) * Number.parseFloat(value)),
|
|
33
|
+
"divide-by": (str, value) => String(Number.parseFloat(str) / Number.parseFloat(value)),
|
|
34
|
+
divide: (str, value) => String(Number.parseFloat(str) / Number.parseFloat(value)),
|
|
35
|
+
modulo: (str, value) => String(Number.parseFloat(str) % Number.parseFloat(value)),
|
|
36
|
+
"newline-to-br": (str) => str.replace(/\n/g, "<br>"),
|
|
37
|
+
"strip-newlines": (str) => str.replace(/\n/g, ""),
|
|
38
|
+
remove: (str, value) => str.split(value).join(""),
|
|
39
|
+
"remove-first": (str, value) => {
|
|
40
|
+
const i = str.indexOf(value);
|
|
41
|
+
return i === -1 ? str : str.slice(0, i) + str.slice(i + value.length);
|
|
42
|
+
},
|
|
43
|
+
replace: (str, value) => {
|
|
44
|
+
const [search = "", replacement = ""] = value.split("|");
|
|
45
|
+
return str.split(search).join(replacement);
|
|
46
|
+
},
|
|
47
|
+
"replace-first": (str, value) => {
|
|
48
|
+
const [search = "", replacement = ""] = value.split("|");
|
|
49
|
+
const i = str.indexOf(search);
|
|
50
|
+
return i === -1 ? str : str.slice(0, i) + replacement + str.slice(i + search.length);
|
|
51
|
+
},
|
|
52
|
+
size: (str) => String(str.length),
|
|
53
|
+
slice: (str, value) => {
|
|
54
|
+
const args = value.split(",").map((s) => Number.parseInt(s.trim(), 10));
|
|
55
|
+
return str.slice(args[0], args[1]);
|
|
56
|
+
},
|
|
57
|
+
truncate: (str, value) => {
|
|
58
|
+
const commaIndex = value.indexOf(",");
|
|
59
|
+
const length = Number.parseInt(commaIndex === -1 ? value : value.slice(0, commaIndex), 10);
|
|
60
|
+
const ellipsis = commaIndex === -1 ? "..." : value.slice(commaIndex + 1);
|
|
61
|
+
if (str.length <= length) return str;
|
|
62
|
+
return str.slice(0, length) + ellipsis;
|
|
63
|
+
},
|
|
64
|
+
"truncate-words": (str, value) => {
|
|
65
|
+
const commaIndex = value.indexOf(",");
|
|
66
|
+
const count = Number.parseInt(commaIndex === -1 ? value : value.slice(0, commaIndex), 10);
|
|
67
|
+
const ellipsis = commaIndex === -1 ? "..." : value.slice(commaIndex + 1);
|
|
68
|
+
const words = str.split(/\s+/).filter(Boolean);
|
|
69
|
+
if (words.length <= count) return str;
|
|
70
|
+
return words.slice(0, count).join(" ") + ellipsis;
|
|
71
|
+
},
|
|
72
|
+
"url-decode": (str) => decodeURIComponent(str.replace(/\+/g, " ")),
|
|
73
|
+
"url-encode": (str) => encodeURIComponent(str)
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
//#endregion
|
|
77
|
+
export { defaults };
|
|
78
|
+
//# sourceMappingURL=defaults.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defaults.mjs","names":[],"sources":["../../../src/transformers/filters/defaults.ts"],"sourcesContent":["export type FilterFunction = (str: string, value: string) => string\n\nconst escapeMap: Record<string, string> = {\n '\"': '"',\n '&': '&',\n \"'\": ''',\n '<': '<',\n '>': '>',\n}\n\nconst escapeRegex = /[\"&'<>]/g\n\nfunction escapeHtml(str: string): string {\n return str.replace(escapeRegex, ch => escapeMap[ch])\n}\n\nexport const defaults: Record<string, FilterFunction> = {\n append: (str, value) => str + value,\n prepend: (str, value) => value + str,\n uppercase: str => str.toUpperCase(),\n lowercase: str => str.toLowerCase(),\n capitalize: str => str.charAt(0).toUpperCase() + str.slice(1),\n ceil: str => String(Math.ceil(Number.parseFloat(str))),\n floor: str => String(Math.floor(Number.parseFloat(str))),\n round: str => String(Math.round(Number.parseFloat(str))),\n escape: str => escapeHtml(str),\n 'escape-once': str => {\n const decoded = str\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/"/g, '\"')\n .replace(/"/g, '\"')\n .replace(/'/g, \"'\")\n .replace(/'/g, \"'\")\n\n return escapeHtml(decoded)\n },\n lstrip: str => str.trimStart(),\n rstrip: str => str.trimEnd(),\n trim: str => str.trim(),\n minus: (str, value) => String(Number.parseFloat(str) - Number.parseFloat(value)),\n plus: (str, value) => String(Number.parseFloat(str) + Number.parseFloat(value)),\n multiply: (str, value) => String(Number.parseFloat(str) * Number.parseFloat(value)),\n times: (str, value) => String(Number.parseFloat(str) * Number.parseFloat(value)),\n 'divide-by': (str, value) => String(Number.parseFloat(str) / Number.parseFloat(value)),\n divide: (str, value) => String(Number.parseFloat(str) / Number.parseFloat(value)),\n modulo: (str, value) => String(Number.parseFloat(str) % Number.parseFloat(value)),\n 'newline-to-br': str => str.replace(/\\n/g, '<br>'),\n 'strip-newlines': str => str.replace(/\\n/g, ''),\n remove: (str, value) => str.split(value).join(''),\n 'remove-first': (str, value) => {\n const i = str.indexOf(value)\n return i === -1 ? str : str.slice(0, i) + str.slice(i + value.length)\n },\n replace: (str, value) => {\n const [search = '', replacement = ''] = value.split('|')\n return str.split(search).join(replacement)\n },\n 'replace-first': (str, value) => {\n const [search = '', replacement = ''] = value.split('|')\n const i = str.indexOf(search)\n return i === -1 ? str : str.slice(0, i) + replacement + str.slice(i + search.length)\n },\n size: str => String(str.length),\n slice: (str, value) => {\n const args = value.split(',').map(s => Number.parseInt(s.trim(), 10))\n return str.slice(args[0], args[1])\n },\n truncate: (str, value) => {\n const commaIndex = value.indexOf(',')\n const length = Number.parseInt(commaIndex === -1 ? value : value.slice(0, commaIndex), 10)\n const ellipsis = commaIndex === -1 ? '...' : value.slice(commaIndex + 1)\n\n if (str.length <= length) return str\n\n return str.slice(0, length) + ellipsis\n },\n 'truncate-words': (str, value) => {\n const commaIndex = value.indexOf(',')\n const count = Number.parseInt(commaIndex === -1 ? value : value.slice(0, commaIndex), 10)\n const ellipsis = commaIndex === -1 ? '...' : value.slice(commaIndex + 1)\n const words = str.split(/\\s+/).filter(Boolean)\n\n if (words.length <= count) return str\n\n return words.slice(0, count).join(' ') + ellipsis\n },\n 'url-decode': str => decodeURIComponent(str.replace(/\\+/g, ' ')),\n 'url-encode': str => encodeURIComponent(str),\n}\n"],"mappings":";AAEA,MAAM,YAAoC;CACxC,MAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACN;AAED,MAAM,cAAc;AAEpB,SAAS,WAAW,KAAqB;AACvC,QAAO,IAAI,QAAQ,cAAa,OAAM,UAAU,IAAI;;AAGtD,MAAa,WAA2C;CACtD,SAAS,KAAK,UAAU,MAAM;CAC9B,UAAU,KAAK,UAAU,QAAQ;CACjC,YAAW,QAAO,IAAI,aAAa;CACnC,YAAW,QAAO,IAAI,aAAa;CACnC,aAAY,QAAO,IAAI,OAAO,EAAE,CAAC,aAAa,GAAG,IAAI,MAAM,EAAE;CAC7D,OAAM,QAAO,OAAO,KAAK,KAAK,OAAO,WAAW,IAAI,CAAC,CAAC;CACtD,QAAO,QAAO,OAAO,KAAK,MAAM,OAAO,WAAW,IAAI,CAAC,CAAC;CACxD,QAAO,QAAO,OAAO,KAAK,MAAM,OAAO,WAAW,IAAI,CAAC,CAAC;CACxD,SAAQ,QAAO,WAAW,IAAI;CAC9B,gBAAe,QAAO;AAUpB,SAAO,WATS,IACb,QAAQ,UAAU,IAAI,CACtB,QAAQ,SAAS,IAAI,CACrB,QAAQ,SAAS,IAAI,CACrB,QAAQ,UAAU,KAAI,CACtB,QAAQ,WAAW,KAAI,CACvB,QAAQ,UAAU,IAAI,CACtB,QAAQ,WAAW,IAAI,CAEA;;CAE5B,SAAQ,QAAO,IAAI,WAAW;CAC9B,SAAQ,QAAO,IAAI,SAAS;CAC5B,OAAM,QAAO,IAAI,MAAM;CACvB,QAAQ,KAAK,UAAU,OAAO,OAAO,WAAW,IAAI,GAAG,OAAO,WAAW,MAAM,CAAC;CAChF,OAAO,KAAK,UAAU,OAAO,OAAO,WAAW,IAAI,GAAG,OAAO,WAAW,MAAM,CAAC;CAC/E,WAAW,KAAK,UAAU,OAAO,OAAO,WAAW,IAAI,GAAG,OAAO,WAAW,MAAM,CAAC;CACnF,QAAQ,KAAK,UAAU,OAAO,OAAO,WAAW,IAAI,GAAG,OAAO,WAAW,MAAM,CAAC;CAChF,cAAc,KAAK,UAAU,OAAO,OAAO,WAAW,IAAI,GAAG,OAAO,WAAW,MAAM,CAAC;CACtF,SAAS,KAAK,UAAU,OAAO,OAAO,WAAW,IAAI,GAAG,OAAO,WAAW,MAAM,CAAC;CACjF,SAAS,KAAK,UAAU,OAAO,OAAO,WAAW,IAAI,GAAG,OAAO,WAAW,MAAM,CAAC;CACjF,kBAAiB,QAAO,IAAI,QAAQ,OAAO,OAAO;CAClD,mBAAkB,QAAO,IAAI,QAAQ,OAAO,GAAG;CAC/C,SAAS,KAAK,UAAU,IAAI,MAAM,MAAM,CAAC,KAAK,GAAG;CACjD,iBAAiB,KAAK,UAAU;EAC9B,MAAM,IAAI,IAAI,QAAQ,MAAM;AAC5B,SAAO,MAAM,KAAK,MAAM,IAAI,MAAM,GAAG,EAAE,GAAG,IAAI,MAAM,IAAI,MAAM,OAAO;;CAEvE,UAAU,KAAK,UAAU;EACvB,MAAM,CAAC,SAAS,IAAI,cAAc,MAAM,MAAM,MAAM,IAAI;AACxD,SAAO,IAAI,MAAM,OAAO,CAAC,KAAK,YAAY;;CAE5C,kBAAkB,KAAK,UAAU;EAC/B,MAAM,CAAC,SAAS,IAAI,cAAc,MAAM,MAAM,MAAM,IAAI;EACxD,MAAM,IAAI,IAAI,QAAQ,OAAO;AAC7B,SAAO,MAAM,KAAK,MAAM,IAAI,MAAM,GAAG,EAAE,GAAG,cAAc,IAAI,MAAM,IAAI,OAAO,OAAO;;CAEtF,OAAM,QAAO,OAAO,IAAI,OAAO;CAC/B,QAAQ,KAAK,UAAU;EACrB,MAAM,OAAO,MAAM,MAAM,IAAI,CAAC,KAAI,MAAK,OAAO,SAAS,EAAE,MAAM,EAAE,GAAG,CAAC;AACrE,SAAO,IAAI,MAAM,KAAK,IAAI,KAAK,GAAG;;CAEpC,WAAW,KAAK,UAAU;EACxB,MAAM,aAAa,MAAM,QAAQ,IAAI;EACrC,MAAM,SAAS,OAAO,SAAS,eAAe,KAAK,QAAQ,MAAM,MAAM,GAAG,WAAW,EAAE,GAAG;EAC1F,MAAM,WAAW,eAAe,KAAK,QAAQ,MAAM,MAAM,aAAa,EAAE;AAExE,MAAI,IAAI,UAAU,OAAQ,QAAO;AAEjC,SAAO,IAAI,MAAM,GAAG,OAAO,GAAG;;CAEhC,mBAAmB,KAAK,UAAU;EAChC,MAAM,aAAa,MAAM,QAAQ,IAAI;EACrC,MAAM,QAAQ,OAAO,SAAS,eAAe,KAAK,QAAQ,MAAM,MAAM,GAAG,WAAW,EAAE,GAAG;EACzF,MAAM,WAAW,eAAe,KAAK,QAAQ,MAAM,MAAM,aAAa,EAAE;EACxE,MAAM,QAAQ,IAAI,MAAM,MAAM,CAAC,OAAO,QAAQ;AAE9C,MAAI,MAAM,UAAU,MAAO,QAAO;AAElC,SAAO,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,IAAI,GAAG;;CAE3C,eAAc,QAAO,mBAAmB,IAAI,QAAQ,OAAO,IAAI,CAAC;CAChE,eAAc,QAAO,mBAAmB,IAAI;CAC7C"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { FilterFunction } from "./defaults.mjs";
|
|
2
|
+
import { ChildNode } from "domhandler";
|
|
3
|
+
|
|
4
|
+
//#region src/transformers/filters/index.d.ts
|
|
5
|
+
type FiltersConfig = false | Record<string, (str: string, value: string) => string>;
|
|
6
|
+
/**
|
|
7
|
+
* Filters transformer.
|
|
8
|
+
*
|
|
9
|
+
* Applies transformation functions to the content of elements that
|
|
10
|
+
* have matching filter attributes. Multiple filters on the same element
|
|
11
|
+
* are executed in the order the attributes are defined.
|
|
12
|
+
*
|
|
13
|
+
* Default filters include string manipulation (uppercase, lowercase, trim, etc.),
|
|
14
|
+
* math operations (plus, minus, multiply, etc.), and more.
|
|
15
|
+
*
|
|
16
|
+
* Custom filters can be added via config, and will be merged with defaults.
|
|
17
|
+
* Set config to `false` to disable all filters.
|
|
18
|
+
*/
|
|
19
|
+
declare function filters(dom: ChildNode[], config?: FiltersConfig): ChildNode[];
|
|
20
|
+
//#endregion
|
|
21
|
+
export { type FilterFunction, FiltersConfig, filters };
|
|
22
|
+
//# sourceMappingURL=index.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../../../src/transformers/filters/index.ts"],"mappings":";;;;KAMY,aAAA,WAAwB,MAAA,UAAgB,GAAA,UAAa,KAAA;;AAAjE;;;;;;;;;AA4BA;;;iBAAgB,OAAA,CAAQ,GAAA,EAAK,SAAA,IAAa,MAAA,GAAQ,aAAA,GAAqB,SAAA"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { parse } from "../../utils/ast/parser.mjs";
|
|
2
|
+
import { serialize } from "../../utils/ast/serializer.mjs";
|
|
3
|
+
import "../../utils/ast/index.mjs";
|
|
4
|
+
import { defaults } from "./defaults.mjs";
|
|
5
|
+
import { Text } from "domhandler";
|
|
6
|
+
|
|
7
|
+
//#region src/transformers/filters/index.ts
|
|
8
|
+
/**
|
|
9
|
+
* Process children before parents so nested filter elements work correctly.
|
|
10
|
+
*/
|
|
11
|
+
function walkBottomUp(nodes, callback) {
|
|
12
|
+
for (const node of [...nodes]) {
|
|
13
|
+
if ("children" in node && node.children?.length) walkBottomUp(node.children, callback);
|
|
14
|
+
callback(node);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Filters transformer.
|
|
19
|
+
*
|
|
20
|
+
* Applies transformation functions to the content of elements that
|
|
21
|
+
* have matching filter attributes. Multiple filters on the same element
|
|
22
|
+
* are executed in the order the attributes are defined.
|
|
23
|
+
*
|
|
24
|
+
* Default filters include string manipulation (uppercase, lowercase, trim, etc.),
|
|
25
|
+
* math operations (plus, minus, multiply, etc.), and more.
|
|
26
|
+
*
|
|
27
|
+
* Custom filters can be added via config, and will be merged with defaults.
|
|
28
|
+
* Set config to `false` to disable all filters.
|
|
29
|
+
*/
|
|
30
|
+
function filters(dom, config = {}) {
|
|
31
|
+
if (config === false) return dom;
|
|
32
|
+
const allFilters = {
|
|
33
|
+
...defaults,
|
|
34
|
+
...config
|
|
35
|
+
};
|
|
36
|
+
const filterNames = new Set(Object.keys(allFilters));
|
|
37
|
+
walkBottomUp(dom, (node) => {
|
|
38
|
+
const el = node;
|
|
39
|
+
if (!el.attribs) return;
|
|
40
|
+
const matched = [];
|
|
41
|
+
for (const attr of Object.keys(el.attribs)) if (filterNames.has(attr)) matched.push({
|
|
42
|
+
name: attr,
|
|
43
|
+
value: el.attribs[attr]
|
|
44
|
+
});
|
|
45
|
+
if (matched.length === 0) return;
|
|
46
|
+
let content = serialize(el.children);
|
|
47
|
+
for (const { name, value } of matched) {
|
|
48
|
+
content = allFilters[name](content, value);
|
|
49
|
+
delete el.attribs[name];
|
|
50
|
+
}
|
|
51
|
+
if (content === "") el.children = [];
|
|
52
|
+
else if (/<[a-z/!]/i.test(content)) {
|
|
53
|
+
const newChildren = parse(content);
|
|
54
|
+
for (const child of newChildren) child.parent = el;
|
|
55
|
+
el.children = newChildren;
|
|
56
|
+
} else {
|
|
57
|
+
const textNode = new Text(content);
|
|
58
|
+
textNode.parent = el;
|
|
59
|
+
el.children = [textNode];
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
return dom;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
//#endregion
|
|
66
|
+
export { filters };
|
|
67
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../../src/transformers/filters/index.ts"],"sourcesContent":["import { Text } from 'domhandler'\nimport type { ChildNode, Element } from 'domhandler'\nimport { parse, serialize } from '../../utils/ast/index.ts'\nimport { defaults } from './defaults.ts'\n\nexport type { FilterFunction } from './defaults.ts'\nexport type FiltersConfig = false | Record<string, (str: string, value: string) => string>\n\n/**\n * Process children before parents so nested filter elements work correctly.\n */\nfunction walkBottomUp(nodes: ChildNode[], callback: (node: ChildNode) => void): void {\n for (const node of [...nodes]) {\n if ('children' in node && node.children?.length) {\n walkBottomUp(node.children as ChildNode[], callback)\n }\n\n callback(node)\n }\n}\n\n/**\n * Filters transformer.\n *\n * Applies transformation functions to the content of elements that\n * have matching filter attributes. Multiple filters on the same element\n * are executed in the order the attributes are defined.\n *\n * Default filters include string manipulation (uppercase, lowercase, trim, etc.),\n * math operations (plus, minus, multiply, etc.), and more.\n *\n * Custom filters can be added via config, and will be merged with defaults.\n * Set config to `false` to disable all filters.\n */\nexport function filters(dom: ChildNode[], config: FiltersConfig = {}): ChildNode[] {\n if (config === false) return dom\n\n const allFilters = { ...defaults, ...config }\n const filterNames = new Set(Object.keys(allFilters))\n\n walkBottomUp(dom, (node) => {\n const el = node as Element\n\n if (!el.attribs) return\n\n // Collect matching filter attributes in source order\n const matched: Array<{ name: string; value: string }> = []\n\n for (const attr of Object.keys(el.attribs)) {\n if (filterNames.has(attr)) {\n matched.push({ name: attr, value: el.attribs[attr] })\n }\n }\n\n if (matched.length === 0) return\n\n // Serialize children to get innerHTML\n let content = serialize(el.children as ChildNode[])\n\n // Apply each filter in attribute order\n for (const { name, value } of matched) {\n content = allFilters[name](content, value)\n delete el.attribs[name]\n }\n\n // Replace children with the filtered content\n if (content === '') {\n el.children = []\n } else if (/<[a-z/!]/i.test(content)) {\n // Result contains HTML elements — parse back to DOM\n const newChildren = parse(content)\n\n for (const child of newChildren) {\n child.parent = el as any\n }\n\n el.children = newChildren as ChildNode[]\n } else {\n // Text-only result — create a text node directly to preserve entity strings\n const textNode = new Text(content)\n textNode.parent = el as any\n el.children = [textNode]\n }\n })\n\n return dom\n}\n"],"mappings":";;;;;;;;;;AAWA,SAAS,aAAa,OAAoB,UAA2C;AACnF,MAAK,MAAM,QAAQ,CAAC,GAAG,MAAM,EAAE;AAC7B,MAAI,cAAc,QAAQ,KAAK,UAAU,OACvC,cAAa,KAAK,UAAyB,SAAS;AAGtD,WAAS,KAAK;;;;;;;;;;;;;;;;AAiBlB,SAAgB,QAAQ,KAAkB,SAAwB,EAAE,EAAe;AACjF,KAAI,WAAW,MAAO,QAAO;CAE7B,MAAM,aAAa;EAAE,GAAG;EAAU,GAAG;EAAQ;CAC7C,MAAM,cAAc,IAAI,IAAI,OAAO,KAAK,WAAW,CAAC;AAEpD,cAAa,MAAM,SAAS;EAC1B,MAAM,KAAK;AAEX,MAAI,CAAC,GAAG,QAAS;EAGjB,MAAM,UAAkD,EAAE;AAE1D,OAAK,MAAM,QAAQ,OAAO,KAAK,GAAG,QAAQ,CACxC,KAAI,YAAY,IAAI,KAAK,CACvB,SAAQ,KAAK;GAAE,MAAM;GAAM,OAAO,GAAG,QAAQ;GAAO,CAAC;AAIzD,MAAI,QAAQ,WAAW,EAAG;EAG1B,IAAI,UAAU,UAAU,GAAG,SAAwB;AAGnD,OAAK,MAAM,EAAE,MAAM,WAAW,SAAS;AACrC,aAAU,WAAW,MAAM,SAAS,MAAM;AAC1C,UAAO,GAAG,QAAQ;;AAIpB,MAAI,YAAY,GACd,IAAG,WAAW,EAAE;WACP,YAAY,KAAK,QAAQ,EAAE;GAEpC,MAAM,cAAc,MAAM,QAAQ;AAElC,QAAK,MAAM,SAAS,YAClB,OAAM,SAAS;AAGjB,MAAG,WAAW;SACT;GAEL,MAAM,WAAW,IAAI,KAAK,QAAQ;AAClC,YAAS,SAAS;AAClB,MAAG,WAAW,CAAC,SAAS;;GAE1B;AAEF,QAAO"}
|
|
@@ -19,17 +19,19 @@ import { MaizzleConfig } from "../types/config.mjs";
|
|
|
19
19
|
* 4. CSS inliner
|
|
20
20
|
* 5. Remove attributes
|
|
21
21
|
* 6. Shorthand CSS
|
|
22
|
-
* 7.
|
|
23
|
-
* 8.
|
|
24
|
-
* 9.
|
|
25
|
-
* 10.
|
|
26
|
-
* 11.
|
|
22
|
+
* 7. Six-digit HEX
|
|
23
|
+
* 8. Add attributes
|
|
24
|
+
* 9. Filters
|
|
25
|
+
* 10. Base URL
|
|
26
|
+
* 11. URL query
|
|
27
|
+
* 12. Purge CSS (serializes/parses internally around email-comb)
|
|
28
|
+
* 13. Entities
|
|
27
29
|
* + Vue-generated comments stripped here (on serialized string)
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
30
|
+
* 14. Replace strings
|
|
31
|
+
* 15. Prettify
|
|
32
|
+
* 16. Minify
|
|
31
33
|
*/
|
|
32
|
-
declare function runTransformers(html: string, config: MaizzleConfig, filePath?: string): Promise<string>;
|
|
34
|
+
declare function runTransformers(html: string, config: MaizzleConfig, filePath?: string, doctype?: string): Promise<string>;
|
|
33
35
|
//#endregion
|
|
34
36
|
export { runTransformers };
|
|
35
37
|
//# sourceMappingURL=index.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/transformers/index.ts"],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/transformers/index.ts"],"mappings":";;;;;AAkDA;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAAsB,eAAA,CACpB,IAAA,UACA,MAAA,EAAQ,aAAA,EACR,QAAA,WACA,OAAA,YACC,OAAA"}
|
|
@@ -8,7 +8,9 @@ import { attributeToStyle } from "./attributeToStyle.mjs";
|
|
|
8
8
|
import { inlineCSS } from "./inlineCSS.mjs";
|
|
9
9
|
import { removeAttributes } from "./removeAttributes.mjs";
|
|
10
10
|
import { shorthandCSS } from "./shorthandCSS.mjs";
|
|
11
|
+
import { sixHex } from "./sixHex.mjs";
|
|
11
12
|
import { addAttributes } from "./addAttributes.mjs";
|
|
13
|
+
import { filters } from "./filters/index.mjs";
|
|
12
14
|
import { base } from "./base.mjs";
|
|
13
15
|
import { entities } from "./entities.mjs";
|
|
14
16
|
import { urlQuery } from "./urlQuery.mjs";
|
|
@@ -36,17 +38,19 @@ import { minify } from "./minify.mjs";
|
|
|
36
38
|
* 4. CSS inliner
|
|
37
39
|
* 5. Remove attributes
|
|
38
40
|
* 6. Shorthand CSS
|
|
39
|
-
* 7.
|
|
40
|
-
* 8.
|
|
41
|
-
* 9.
|
|
42
|
-
* 10.
|
|
43
|
-
* 11.
|
|
41
|
+
* 7. Six-digit HEX
|
|
42
|
+
* 8. Add attributes
|
|
43
|
+
* 9. Filters
|
|
44
|
+
* 10. Base URL
|
|
45
|
+
* 11. URL query
|
|
46
|
+
* 12. Purge CSS (serializes/parses internally around email-comb)
|
|
47
|
+
* 13. Entities
|
|
44
48
|
* + Vue-generated comments stripped here (on serialized string)
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
49
|
+
* 14. Replace strings
|
|
50
|
+
* 15. Prettify
|
|
51
|
+
* 16. Minify
|
|
48
52
|
*/
|
|
49
|
-
async function runTransformers(html, config, filePath) {
|
|
53
|
+
async function runTransformers(html, config, filePath, doctype) {
|
|
50
54
|
let dom = parse(html);
|
|
51
55
|
dom = await inlineLink(dom, filePath);
|
|
52
56
|
dom = await tailwindcss(dom, config, filePath);
|
|
@@ -55,16 +59,20 @@ async function runTransformers(html, config, filePath) {
|
|
|
55
59
|
dom = inlineCSS(dom, config.css);
|
|
56
60
|
dom = removeAttributes(dom, config.html?.attributes);
|
|
57
61
|
dom = shorthandCSS(dom, config.css);
|
|
62
|
+
dom = sixHex(dom, config.css);
|
|
58
63
|
dom = addAttributes(dom, config.html?.attributes);
|
|
64
|
+
dom = filters(dom, config.filters);
|
|
59
65
|
dom = base(dom, config.url);
|
|
60
66
|
dom = urlQuery(dom, config.url);
|
|
61
67
|
dom = purgeCSS(dom, config.css);
|
|
62
68
|
dom = entities(dom, config.html?.decodeEntities);
|
|
63
|
-
|
|
64
|
-
result =
|
|
69
|
+
const isXhtml = doctype ? /xhtml/i.test(doctype) : false;
|
|
70
|
+
let result = serialize(dom, { selfClosingTags: isXhtml });
|
|
71
|
+
result = result.replaceAll("<!--[-->", "").replaceAll("<!--]-->", "").replaceAll("<!--teleport start anchor-->", "").replaceAll("<!--teleport anchor-->", "").replaceAll("<!--teleport start-->", "").replaceAll("<!--teleport end-->", "");
|
|
65
72
|
result = replaceStrings(result, config);
|
|
66
73
|
result = await format(result, config);
|
|
67
74
|
result = minify(result, config);
|
|
75
|
+
if (!isXhtml) result = result.replace(/ \/>/g, ">");
|
|
68
76
|
return result;
|
|
69
77
|
}
|
|
70
78
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/transformers/index.ts"],"sourcesContent":["import { parse, serialize } from '../utils/ast/index.ts'\nimport { inlineLink } from './inlineLink.ts'\nimport { tailwindcss } from './tailwindcss.ts'\nimport { safeClassNames } from './safeClassNames.ts'\nimport { attributeToStyle } from './attributeToStyle.ts'\nimport { inlineCSS } from './inlineCSS.ts'\nimport { removeAttributes } from './removeAttributes.ts'\nimport { shorthandCSS } from './shorthandCSS.ts'\nimport { addAttributes } from './addAttributes.ts'\nimport { base } from './base.ts'\nimport { entities } from './entities.ts'\nimport { urlQuery } from './urlQuery.ts'\nimport { purgeCSS } from './purgeCSS.ts'\nimport { replaceStrings } from './replaceStrings.ts'\nimport { format } from './format.ts'\nimport { minify } from './minify.ts'\nimport type { MaizzleConfig } from '../types/config.ts'\n\n/**\n * Run all Maizzle transformers on the rendered HTML.\n *\n * The HTML is parsed into a DOM once at the start and passed through all\n * DOM-based transformers as a shared `ChildNode[]`. After all DOM transformers\n * complete, the DOM is serialized back to a string exactly once.\n *\n * String-only transformers (those that rely on external tools that require a\n * raw HTML string) then run on the serialized output.\n *\n * Transformers run in a specific order:\n * 0. Inline link stylesheets — replace `<link rel=\"stylesheet\">` with `<style>` tags\n * 1. Tailwind CSS — compile CSS, lower syntax, optimize (cleanup + merge media queries)\n * 2. Safe class names\n * 3. Attribute to style\n * 4. CSS inliner\n * 5. Remove attributes\n * 6. Shorthand CSS\n * 7. Add attributes\n *
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/transformers/index.ts"],"sourcesContent":["import { parse, serialize } from '../utils/ast/index.ts'\nimport { inlineLink } from './inlineLink.ts'\nimport { tailwindcss } from './tailwindcss.ts'\nimport { safeClassNames } from './safeClassNames.ts'\nimport { attributeToStyle } from './attributeToStyle.ts'\nimport { inlineCSS } from './inlineCSS.ts'\nimport { removeAttributes } from './removeAttributes.ts'\nimport { shorthandCSS } from './shorthandCSS.ts'\nimport { sixHex } from './sixHex.ts'\nimport { addAttributes } from './addAttributes.ts'\nimport { filters } from './filters/index.ts'\nimport { base } from './base.ts'\nimport { entities } from './entities.ts'\nimport { urlQuery } from './urlQuery.ts'\nimport { purgeCSS } from './purgeCSS.ts'\nimport { replaceStrings } from './replaceStrings.ts'\nimport { format } from './format.ts'\nimport { minify } from './minify.ts'\nimport type { MaizzleConfig } from '../types/config.ts'\n\n/**\n * Run all Maizzle transformers on the rendered HTML.\n *\n * The HTML is parsed into a DOM once at the start and passed through all\n * DOM-based transformers as a shared `ChildNode[]`. After all DOM transformers\n * complete, the DOM is serialized back to a string exactly once.\n *\n * String-only transformers (those that rely on external tools that require a\n * raw HTML string) then run on the serialized output.\n *\n * Transformers run in a specific order:\n * 0. Inline link stylesheets — replace `<link rel=\"stylesheet\">` with `<style>` tags\n * 1. Tailwind CSS — compile CSS, lower syntax, optimize (cleanup + merge media queries)\n * 2. Safe class names\n * 3. Attribute to style\n * 4. CSS inliner\n * 5. Remove attributes\n * 6. Shorthand CSS\n * 7. Six-digit HEX\n * 8. Add attributes\n * 9. Filters\n * 10. Base URL\n * 11. URL query\n * 12. Purge CSS (serializes/parses internally around email-comb)\n * 13. Entities\n * + Vue-generated comments stripped here (on serialized string)\n * 14. Replace strings\n * 15. Prettify\n * 16. Minify\n */\nexport async function runTransformers(\n html: string,\n config: MaizzleConfig,\n filePath?: string,\n doctype?: string,\n): Promise<string> {\n // Parse once — all DOM transformers share this array\n let dom = parse(html)\n\n // 0. Inline <link> stylesheets\n dom = await inlineLink(dom, filePath)\n\n // 1. Tailwind CSS — always runs first\n dom = await tailwindcss(dom, config, filePath)\n\n // 2. Safe class names\n dom = safeClassNames(dom, config.css)\n\n // 3. Attribute to style\n dom = attributeToStyle(dom, config.css)\n\n // 4. CSS inliner (serializes/parses internally around juice)\n dom = inlineCSS(dom, config.css)\n\n // 5. Remove attributes\n dom = removeAttributes(dom, config.html?.attributes)\n\n // 6. Shorthand CSS\n dom = shorthandCSS(dom, config.css)\n\n // 7. Six-digit HEX\n dom = sixHex(dom, config.css)\n\n // 8. Add attributes\n dom = addAttributes(dom, config.html?.attributes)\n\n // 9. Filters\n dom = filters(dom, config.filters)\n\n // 10. Base URL (serializes/parses internally for VML/MSO regex passes)\n dom = base(dom, config.url)\n\n // 11. URL query\n dom = urlQuery(dom, config.url)\n\n // 12. Purge CSS (serializes/parses internally around email-comb)\n dom = purgeCSS(dom, config.css)\n\n // 13. Entities\n dom = entities(dom, config.html?.decodeEntities)\n\n // Serialize once — remaining transformers operate on the HTML string\n const isXhtml = doctype ? /xhtml/i.test(doctype) : false\n let result = serialize(dom, { selfClosingTags: isXhtml })\n\n // Remove Vue-generated comments after serializing\n result = result\n .replaceAll('<!--[-->', '')\n .replaceAll('<!--]-->', '')\n .replaceAll('<!--teleport start anchor-->', '')\n .replaceAll('<!--teleport anchor-->', '')\n .replaceAll('<!--teleport start-->', '')\n .replaceAll('<!--teleport end-->', '')\n\n // 14. Replace strings\n result = replaceStrings(result, config)\n\n // 15. Format\n result = await format(result, config)\n\n // 16. Minify\n result = minify(result, config)\n\n // Strip self-closing slashes for HTML5 doctypes\n if (!isXhtml) {\n result = result.replace(/ \\/>/g, '>')\n }\n\n return result\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkDA,eAAsB,gBACpB,MACA,QACA,UACA,SACiB;CAEjB,IAAI,MAAM,MAAM,KAAK;AAGrB,OAAM,MAAM,WAAW,KAAK,SAAS;AAGrC,OAAM,MAAM,YAAY,KAAK,QAAQ,SAAS;AAG9C,OAAM,eAAe,KAAK,OAAO,IAAI;AAGrC,OAAM,iBAAiB,KAAK,OAAO,IAAI;AAGvC,OAAM,UAAU,KAAK,OAAO,IAAI;AAGhC,OAAM,iBAAiB,KAAK,OAAO,MAAM,WAAW;AAGpD,OAAM,aAAa,KAAK,OAAO,IAAI;AAGnC,OAAM,OAAO,KAAK,OAAO,IAAI;AAG7B,OAAM,cAAc,KAAK,OAAO,MAAM,WAAW;AAGjD,OAAM,QAAQ,KAAK,OAAO,QAAQ;AAGlC,OAAM,KAAK,KAAK,OAAO,IAAI;AAG3B,OAAM,SAAS,KAAK,OAAO,IAAI;AAG/B,OAAM,SAAS,KAAK,OAAO,IAAI;AAG/B,OAAM,SAAS,KAAK,OAAO,MAAM,eAAe;CAGhD,MAAM,UAAU,UAAU,SAAS,KAAK,QAAQ,GAAG;CACnD,IAAI,SAAS,UAAU,KAAK,EAAE,iBAAiB,SAAS,CAAC;AAGzD,UAAS,OACN,WAAW,YAAY,GAAG,CAC1B,WAAW,YAAY,GAAG,CAC1B,WAAW,gCAAgC,GAAG,CAC9C,WAAW,0BAA0B,GAAG,CACxC,WAAW,yBAAyB,GAAG,CACvC,WAAW,uBAAuB,GAAG;AAGxC,UAAS,eAAe,QAAQ,OAAO;AAGvC,UAAS,MAAM,OAAO,QAAQ,OAAO;AAGrC,UAAS,OAAO,QAAQ,OAAO;AAG/B,KAAI,CAAC,QACH,UAAS,OAAO,QAAQ,SAAS,IAAI;AAGvC,QAAO"}
|
|
@@ -9,20 +9,7 @@ import { ChildNode } from "domhandler";
|
|
|
9
9
|
* This is important for email client compatibility (especially Outlook on Windows).
|
|
10
10
|
*
|
|
11
11
|
* Enabled when `css.inline` is set to `true` or an object with options.
|
|
12
|
-
*
|
|
13
|
-
* Options:
|
|
14
|
-
* - removeStyleTags: Remove style tags after inlining (default: false)
|
|
15
|
-
* - removeInlinedSelectors: Remove classes after they've been inlined (default: true)
|
|
16
|
-
* - preferUnitlessValues: Convert 0px, 0em, etc. to 0 (default: true)
|
|
17
|
-
* - safelist: Selectors that should not be removed after inlining
|
|
18
|
-
* - styleToAttribute: Map CSS properties to HTML attributes (e.g., background-color -> bgcolor)
|
|
19
|
-
* - applyWidthAttributes: Add width attributes based on inline CSS (default: true)
|
|
20
|
-
* - applyHeightAttributes: Add height attributes based on inline CSS (default: true)
|
|
21
|
-
* - widthElements: Elements that can receive width attributes (default: ['img', 'video'])
|
|
22
|
-
* - heightElements: Elements that can receive height attributes (default: ['img', 'video'])
|
|
23
|
-
* - excludedProperties: CSS properties to exclude from inlining
|
|
24
|
-
* - codeBlocks: Fenced code blocks to ignore (default: { EJS: { start: '<%', end: '%>' }, HBS: { start: '{{', end: '}}' } })
|
|
25
|
-
* - customCSS: Additional CSS to inline
|
|
12
|
+
* All Juice options are supported and passed through directly.
|
|
26
13
|
*/
|
|
27
14
|
declare function inlineCSS(dom: ChildNode[], config?: CssConfig): ChildNode[];
|
|
28
15
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inlineCSS.d.mts","names":[],"sources":["../../src/transformers/inlineCSS.ts"],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"inlineCSS.d.mts","names":[],"sources":["../../src/transformers/inlineCSS.ts"],"mappings":";;;;;;AAeA;;;;;;;iBAAgB,SAAA,CAAU,GAAA,EAAK,SAAA,IAAa,MAAA,GAAQ,SAAA,GAAiB,SAAA"}
|
|
@@ -12,32 +12,17 @@ import juice from "juice";
|
|
|
12
12
|
* This is important for email client compatibility (especially Outlook on Windows).
|
|
13
13
|
*
|
|
14
14
|
* Enabled when `css.inline` is set to `true` or an object with options.
|
|
15
|
-
*
|
|
16
|
-
* Options:
|
|
17
|
-
* - removeStyleTags: Remove style tags after inlining (default: false)
|
|
18
|
-
* - removeInlinedSelectors: Remove classes after they've been inlined (default: true)
|
|
19
|
-
* - preferUnitlessValues: Convert 0px, 0em, etc. to 0 (default: true)
|
|
20
|
-
* - safelist: Selectors that should not be removed after inlining
|
|
21
|
-
* - styleToAttribute: Map CSS properties to HTML attributes (e.g., background-color -> bgcolor)
|
|
22
|
-
* - applyWidthAttributes: Add width attributes based on inline CSS (default: true)
|
|
23
|
-
* - applyHeightAttributes: Add height attributes based on inline CSS (default: true)
|
|
24
|
-
* - widthElements: Elements that can receive width attributes (default: ['img', 'video'])
|
|
25
|
-
* - heightElements: Elements that can receive height attributes (default: ['img', 'video'])
|
|
26
|
-
* - excludedProperties: CSS properties to exclude from inlining
|
|
27
|
-
* - codeBlocks: Fenced code blocks to ignore (default: { EJS: { start: '<%', end: '%>' }, HBS: { start: '{{', end: '}}' } })
|
|
28
|
-
* - customCSS: Additional CSS to inline
|
|
15
|
+
* All Juice options are supported and passed through directly.
|
|
29
16
|
*/
|
|
30
17
|
function inlineCSS(dom, config = {}) {
|
|
31
18
|
const inline = config.inline;
|
|
32
19
|
if (!inline) return dom;
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
juice.
|
|
37
|
-
juice.
|
|
38
|
-
|
|
39
|
-
juice.heightElements = (options.heightElements ?? ["img", "video"]).map((i) => i.toUpperCase());
|
|
40
|
-
if (options.codeBlocks && typeof options.codeBlocks === "object") Object.entries(options.codeBlocks).forEach(([key, value]) => {
|
|
20
|
+
const { preferUnitlessValues = true, safelist, customCSS = "", styleToAttribute, excludedProperties, widthElements, heightElements, codeBlocks, ...juicePassthrough } = typeof inline === "object" ? inline : {};
|
|
21
|
+
juice.styleToAttribute = styleToAttribute ?? {};
|
|
22
|
+
juice.excludedProperties = ["--tw-shadow", ...excludedProperties ?? []];
|
|
23
|
+
juice.widthElements = (widthElements ?? ["img", "video"]).map((i) => i.toUpperCase());
|
|
24
|
+
juice.heightElements = (heightElements ?? ["img", "video"]).map((i) => i.toUpperCase());
|
|
25
|
+
if (codeBlocks && typeof codeBlocks === "object") Object.entries(codeBlocks).forEach(([key, value]) => {
|
|
41
26
|
if (value.start && value.end) juice.codeBlocks[key] = value;
|
|
42
27
|
});
|
|
43
28
|
walk(dom, (node) => {
|
|
@@ -45,31 +30,42 @@ function inlineCSS(dom, config = {}) {
|
|
|
45
30
|
if (el.name === "style" && el.attribs) {
|
|
46
31
|
if (el.attribs.embed && !("data-embed" in el.attribs)) el.attribs["data-embed"] = "";
|
|
47
32
|
if (el.attribs["data-embed"] && !("embed" in el.attribs)) el.attribs.embed = "";
|
|
33
|
+
if ("data-embed" in el.attribs) el.attribs["data-maizzle-embed"] = "";
|
|
48
34
|
}
|
|
49
35
|
});
|
|
50
36
|
const serialized = serialize(dom);
|
|
51
37
|
let inlinedHtml;
|
|
52
38
|
try {
|
|
53
|
-
|
|
54
|
-
removeStyleTags,
|
|
55
|
-
removeInlinedSelectors:
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
...
|
|
62
|
-
extraCss: customCSS
|
|
39
|
+
inlinedHtml = juice(serialized, {
|
|
40
|
+
removeStyleTags: juicePassthrough.removeStyleTags ?? false,
|
|
41
|
+
removeInlinedSelectors: juicePassthrough.removeInlinedSelectors ?? true,
|
|
42
|
+
applyWidthAttributes: juicePassthrough.applyWidthAttributes ?? true,
|
|
43
|
+
applyHeightAttributes: juicePassthrough.applyHeightAttributes ?? true,
|
|
44
|
+
preservedSelectors: safelist ?? [],
|
|
45
|
+
...customCSS ? { extraCss: customCSS } : {},
|
|
46
|
+
inlineDuplicateProperties: juicePassthrough.inlineDuplicateProperties ?? true,
|
|
47
|
+
...juicePassthrough
|
|
63
48
|
});
|
|
64
|
-
else inlinedHtml = juice(serialized, juiceOptions);
|
|
65
49
|
} catch {
|
|
66
50
|
return dom;
|
|
67
51
|
}
|
|
68
|
-
const preferUnitlessValues = options.preferUnitlessValues ?? true;
|
|
69
52
|
const result = parse(inlinedHtml);
|
|
70
|
-
|
|
53
|
+
walk(result, (node) => {
|
|
71
54
|
const el = node;
|
|
72
|
-
if (el.attribs?.style)
|
|
55
|
+
if (el.attribs?.style) {
|
|
56
|
+
let style = el.attribs.style.replace(/:\s*/g, ": ").replace(/;\s*/g, "; ").trimEnd();
|
|
57
|
+
if (!style.endsWith(";")) style += ";";
|
|
58
|
+
if (preferUnitlessValues) style = style.replace(/\b0(px|rem|em|%|vh|vw|vmin|vmax|in|cm|mm|pt|pc|ex|ch)\b/g, "0");
|
|
59
|
+
el.attribs.style = style;
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
walk(result, (node) => {
|
|
63
|
+
const el = node;
|
|
64
|
+
if (el.name === "style" && el.attribs && "data-maizzle-embed" in el.attribs) {
|
|
65
|
+
el.attribs["data-embed"] = "";
|
|
66
|
+
el.attribs.embed = "";
|
|
67
|
+
delete el.attribs["data-maizzle-embed"];
|
|
68
|
+
}
|
|
73
69
|
});
|
|
74
70
|
return result;
|
|
75
71
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inlineCSS.mjs","names":[],"sources":["../../src/transformers/inlineCSS.ts"],"sourcesContent":["import juice from 'juice'\nimport { walk, parse, serialize } from '../utils/ast/index.ts'\nimport type { ChildNode, Element } from 'domhandler'\nimport type { Options as JuiceOptions } from 'juice'\nimport type { CssConfig } from '../types/config.ts'\n\
|
|
1
|
+
{"version":3,"file":"inlineCSS.mjs","names":[],"sources":["../../src/transformers/inlineCSS.ts"],"sourcesContent":["import juice from 'juice'\nimport { walk, parse, serialize } from '../utils/ast/index.ts'\nimport type { ChildNode, Element } from 'domhandler'\nimport type { Options as JuiceOptions } from 'juice'\nimport type { CssConfig } from '../types/config.ts'\n\n/**\n * Inline CSS transformer.\n *\n * Inlines CSS from `<style>` tags into inline style attributes on HTML elements.\n * This is important for email client compatibility (especially Outlook on Windows).\n *\n * Enabled when `css.inline` is set to `true` or an object with options.\n * All Juice options are supported and passed through directly.\n */\nexport function inlineCSS(dom: ChildNode[], config: CssConfig = {}): ChildNode[] {\n const inline = config.inline\n\n // Disabled when inline is falsy or not an object/truthy\n if (!inline) {\n return dom\n }\n\n // Build options from config\n const options = typeof inline === 'object' ? inline : {}\n\n // Separate Maizzle-specific options from Juice options\n const {\n preferUnitlessValues = true,\n safelist,\n customCSS = '',\n styleToAttribute,\n excludedProperties,\n widthElements,\n heightElements,\n codeBlocks,\n ...juicePassthrough\n } = options\n\n // Configure Juice static properties\n juice.styleToAttribute = styleToAttribute ?? {}\n juice.excludedProperties = ['--tw-shadow', ...(excludedProperties ?? [])]\n juice.widthElements = (widthElements ?? ['img', 'video']).map(i => i.toUpperCase()) as unknown as HTMLElement[]\n juice.heightElements = (heightElements ?? ['img', 'video']).map(i => i.toUpperCase()) as unknown as HTMLElement[]\n\n // Add custom code blocks\n if (codeBlocks && typeof codeBlocks === 'object') {\n Object.entries(codeBlocks).forEach(([key, value]) => {\n if (value.start && value.end) {\n juice.codeBlocks[key] = value\n }\n })\n }\n\n // Handle style tags with embed attributes.\n // We add a marker attribute that persists through the pipeline,\n // then restore data-embed from it after Juice runs.\n walk(dom, (node) => {\n const el = node as Element\n if (el.name === 'style' && el.attribs) {\n // Sync data-embed ↔ embed\n if (el.attribs.embed && !('data-embed' in el.attribs)) {\n el.attribs['data-embed'] = ''\n }\n if (el.attribs['data-embed'] && !('embed' in el.attribs)) {\n el.attribs.embed = ''\n }\n\n // Add marker that persists through the pipeline\n if ('data-embed' in el.attribs) {\n el.attribs['data-maizzle-embed'] = ''\n }\n }\n })\n\n // Serialize for juice (juice requires a string)\n const serialized = serialize(dom)\n\n let inlinedHtml: string\n\n try {\n const juiceOptions: JuiceOptions = {\n removeStyleTags: juicePassthrough.removeStyleTags ?? false,\n removeInlinedSelectors: juicePassthrough.removeInlinedSelectors ?? true,\n applyWidthAttributes: juicePassthrough.applyWidthAttributes ?? true,\n applyHeightAttributes: juicePassthrough.applyHeightAttributes ?? true,\n preservedSelectors: safelist ?? [],\n ...customCSS ? { extraCss: customCSS } : {},\n inlineDuplicateProperties: juicePassthrough.inlineDuplicateProperties ?? true,\n ...juicePassthrough,\n }\n\n inlinedHtml = juice(serialized, juiceOptions)\n } catch {\n // If Juice fails, return the dom unchanged\n return dom\n }\n\n // Post-process for preferUnitlessValues\n const result = parse(inlinedHtml)\n\n walk(result, (node) => {\n const el = node as Element\n if (el.attribs?.style) {\n // Normalize style formatting: ensure spaces after : and ;\n let style = el.attribs.style\n .replace(/:\\s*/g, ': ')\n .replace(/;\\s*/g, '; ')\n .trimEnd()\n\n // Ensure trailing semicolon\n if (!style.endsWith(';')) {\n style += ';'\n }\n\n if (preferUnitlessValues) {\n style = style.replace(\n /\\b0(px|rem|em|%|vh|vw|vmin|vmax|in|cm|mm|pt|pc|ex|ch)\\b/g,\n '0'\n )\n }\n\n el.attribs.style = style\n }\n })\n\n // Restore data-embed from our marker, then remove the marker.\n // The purge step will handle final data-embed/embed removal.\n walk(result, (node) => {\n const el = node as Element\n if (el.name === 'style' && el.attribs && 'data-maizzle-embed' in el.attribs) {\n el.attribs['data-embed'] = ''\n el.attribs.embed = ''\n delete el.attribs['data-maizzle-embed']\n }\n })\n\n return result\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAeA,SAAgB,UAAU,KAAkB,SAAoB,EAAE,EAAe;CAC/E,MAAM,SAAS,OAAO;AAGtB,KAAI,CAAC,OACH,QAAO;CAOT,MAAM,EACJ,uBAAuB,MACvB,UACA,YAAY,IACZ,kBACA,oBACA,eACA,gBACA,YACA,GAAG,qBAZW,OAAO,WAAW,WAAW,SAAS,EAAE;AAgBxD,OAAM,mBAAmB,oBAAoB,EAAE;AAC/C,OAAM,qBAAqB,CAAC,eAAe,GAAI,sBAAsB,EAAE,CAAE;AACzE,OAAM,iBAAiB,iBAAiB,CAAC,OAAO,QAAQ,EAAE,KAAI,MAAK,EAAE,aAAa,CAAC;AACnF,OAAM,kBAAkB,kBAAkB,CAAC,OAAO,QAAQ,EAAE,KAAI,MAAK,EAAE,aAAa,CAAC;AAGrF,KAAI,cAAc,OAAO,eAAe,SACtC,QAAO,QAAQ,WAAW,CAAC,SAAS,CAAC,KAAK,WAAW;AACnD,MAAI,MAAM,SAAS,MAAM,IACvB,OAAM,WAAW,OAAO;GAE1B;AAMJ,MAAK,MAAM,SAAS;EAClB,MAAM,KAAK;AACX,MAAI,GAAG,SAAS,WAAW,GAAG,SAAS;AAErC,OAAI,GAAG,QAAQ,SAAS,EAAE,gBAAgB,GAAG,SAC3C,IAAG,QAAQ,gBAAgB;AAE7B,OAAI,GAAG,QAAQ,iBAAiB,EAAE,WAAW,GAAG,SAC9C,IAAG,QAAQ,QAAQ;AAIrB,OAAI,gBAAgB,GAAG,QACrB,IAAG,QAAQ,wBAAwB;;GAGvC;CAGF,MAAM,aAAa,UAAU,IAAI;CAEjC,IAAI;AAEJ,KAAI;AAYF,gBAAc,MAAM,YAXe;GACjC,iBAAiB,iBAAiB,mBAAmB;GACrD,wBAAwB,iBAAiB,0BAA0B;GACnE,sBAAsB,iBAAiB,wBAAwB;GAC/D,uBAAuB,iBAAiB,yBAAyB;GACjE,oBAAoB,YAAY,EAAE;GAClC,GAAG,YAAY,EAAE,UAAU,WAAW,GAAG,EAAE;GAC3C,2BAA2B,iBAAiB,6BAA6B;GACzE,GAAG;GACJ,CAE4C;SACvC;AAEN,SAAO;;CAIT,MAAM,SAAS,MAAM,YAAY;AAEjC,MAAK,SAAS,SAAS;EACrB,MAAM,KAAK;AACX,MAAI,GAAG,SAAS,OAAO;GAErB,IAAI,QAAQ,GAAG,QAAQ,MACpB,QAAQ,SAAS,KAAK,CACtB,QAAQ,SAAS,KAAK,CACtB,SAAS;AAGZ,OAAI,CAAC,MAAM,SAAS,IAAI,CACtB,UAAS;AAGX,OAAI,qBACF,SAAQ,MAAM,QACZ,4DACA,IACD;AAGH,MAAG,QAAQ,QAAQ;;GAErB;AAIF,MAAK,SAAS,SAAS;EACrB,MAAM,KAAK;AACX,MAAI,GAAG,SAAS,WAAW,GAAG,WAAW,wBAAwB,GAAG,SAAS;AAC3E,MAAG,QAAQ,gBAAgB;AAC3B,MAAG,QAAQ,QAAQ;AACnB,UAAO,GAAG,QAAQ;;GAEpB;AAEF,QAAO"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"purgeCSS.d.mts","names":[],"sources":["../../src/transformers/purgeCSS.ts"],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"purgeCSS.d.mts","names":[],"sources":["../../src/transformers/purgeCSS.ts"],"mappings":";;;;;;AAkDA;;;;;;;;;;;;;iBAAgB,QAAA,CAAS,GAAA,EAAK,SAAA,IAAa,MAAA,GAAQ,SAAA,GAAiB,SAAA"}
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { parse } from "../utils/ast/parser.mjs";
|
|
2
|
+
import { walk } from "../utils/ast/walker.mjs";
|
|
2
3
|
import { serialize } from "../utils/ast/serializer.mjs";
|
|
3
4
|
import "../utils/ast/index.mjs";
|
|
4
5
|
import { defu } from "defu";
|
|
6
|
+
import postcss from "postcss";
|
|
7
|
+
import safeParser from "postcss-safe-parser";
|
|
8
|
+
import { selectAll } from "css-select";
|
|
5
9
|
import { comb } from "email-comb";
|
|
6
10
|
|
|
7
11
|
//#region src/transformers/purgeCSS.ts
|
|
@@ -57,8 +61,70 @@ function purgeCSS(dom, config = {}) {
|
|
|
57
61
|
...restUserOptions,
|
|
58
62
|
whitelist: [...DEFAULT_SAFELIST, ...userSafelist]
|
|
59
63
|
}, DEFAULT_OPTIONS);
|
|
64
|
+
const safelist = [...DEFAULT_SAFELIST, ...userSafelist];
|
|
65
|
+
dom = deepPurge(dom, safelist);
|
|
60
66
|
const { result } = comb(serialize(dom), options);
|
|
61
|
-
|
|
67
|
+
let purgedDom = parse(result);
|
|
68
|
+
walk(purgedDom, (node) => {
|
|
69
|
+
const el = node;
|
|
70
|
+
if (el.name === "style" && el.attribs) {
|
|
71
|
+
delete el.attribs["data-embed"];
|
|
72
|
+
delete el.attribs.embed;
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
return purgedDom;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Deep purge: uses PostCSS to parse CSS in non-embedded style tags,
|
|
79
|
+
* then checks each selector against the DOM with css-select.
|
|
80
|
+
* Removes rules where no selector matches any element.
|
|
81
|
+
*/
|
|
82
|
+
function isSafelisted(selector, safelist) {
|
|
83
|
+
return safelist.some((pattern) => {
|
|
84
|
+
if (pattern.startsWith("*") && pattern.endsWith("*")) return selector.includes(pattern.slice(1, -1));
|
|
85
|
+
if (pattern.endsWith("*")) return selector.startsWith(pattern.slice(0, -1));
|
|
86
|
+
if (pattern.startsWith("*")) return selector.endsWith(pattern.slice(1));
|
|
87
|
+
return selector === pattern;
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
function deepPurge(dom, safelist) {
|
|
91
|
+
walk(dom, (node) => {
|
|
92
|
+
const el = node;
|
|
93
|
+
if (el.name !== "style" || !el.attribs) return;
|
|
94
|
+
if ("data-embed" in el.attribs) return;
|
|
95
|
+
const textNode = el.children?.find((c) => c.type === "text");
|
|
96
|
+
if (!textNode?.data?.trim()) return;
|
|
97
|
+
const root = postcss.parse(textNode.data, { parser: safeParser });
|
|
98
|
+
root.walkRules((rule) => {
|
|
99
|
+
if (rule.parent?.type === "atrule") return;
|
|
100
|
+
const selectors = rule.selectors ?? [rule.selector];
|
|
101
|
+
const matched = selectors.filter((sel) => {
|
|
102
|
+
if (isSafelisted(sel, safelist)) return true;
|
|
103
|
+
if (/::[\w-]/.test(sel)) return true;
|
|
104
|
+
if (/(?<!:):(?!not\b|is\b|where\b|has\b)[\w-]/.test(sel.replace(/\\./g, ""))) return true;
|
|
105
|
+
try {
|
|
106
|
+
return selectAll(sel, dom).length > 0;
|
|
107
|
+
} catch {
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
if (matched.length === 0) rule.remove();
|
|
112
|
+
else if (matched.length < selectors.length) rule.selectors = matched;
|
|
113
|
+
});
|
|
114
|
+
root.walkAtRules((atRule) => {
|
|
115
|
+
if (atRule.nodes?.length === 0) atRule.remove();
|
|
116
|
+
});
|
|
117
|
+
const purgedCss = root.toString();
|
|
118
|
+
if (purgedCss.trim()) textNode.data = purgedCss;
|
|
119
|
+
else {
|
|
120
|
+
const parent = el.parent;
|
|
121
|
+
if (parent && "children" in parent) {
|
|
122
|
+
const idx = parent.children.indexOf(el);
|
|
123
|
+
if (idx !== -1) parent.children.splice(idx, 1);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
return dom;
|
|
62
128
|
}
|
|
63
129
|
|
|
64
130
|
//#endregion
|