@maizzle/framework 6.0.0-rc.8 → 6.0.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 +3 -3
- package/bin/maizzle.mjs +1 -1
- package/dist/build.d.ts +38 -0
- package/dist/build.d.ts.map +1 -0
- package/dist/build.js +234 -0
- package/dist/build.js.map +1 -0
- package/dist/components/Body.vue +32 -3
- package/dist/components/Button.vue +91 -62
- package/dist/components/CodeBlock.vue +6 -4
- package/dist/components/CodeInline.vue +77 -6
- package/dist/components/Column.vue +67 -31
- package/dist/components/Container.vue +73 -12
- package/dist/components/Font.vue +96 -0
- package/dist/components/Head.vue +1 -1
- package/dist/components/Heading.vue +1 -1
- package/dist/components/Hr.vue +33 -0
- package/dist/components/Html.vue +36 -3
- package/dist/components/Img.vue +332 -0
- package/dist/components/Layout.vue +71 -21
- package/dist/components/Link.vue +1 -1
- package/dist/components/Markdown.vue +56 -23
- package/dist/components/MarkdownLayout.vue +39 -0
- package/dist/components/NotPlaintext.vue +14 -0
- package/dist/components/Outlook.vue +38 -11
- package/dist/components/OutlookBg.vue +241 -0
- package/dist/components/Plaintext.vue +14 -0
- package/dist/components/Preheader.vue +35 -10
- package/dist/components/QrCode.vue +157 -0
- package/dist/components/Raw.vue +28 -0
- package/dist/components/Row.vue +115 -22
- package/dist/components/Section.vue +65 -26
- package/dist/components/Spacer.vue +35 -29
- package/dist/components/Tailwind.vue +45 -0
- package/dist/components/Text.vue +3 -3
- package/dist/components/Vml.vue +207 -94
- package/dist/components/utils.d.ts +53 -0
- package/dist/components/utils.d.ts.map +1 -0
- package/dist/components/utils.js +80 -0
- package/dist/components/utils.js.map +1 -0
- package/dist/components/utils.ts +102 -0
- package/dist/composables/defineConfig.d.ts +13 -0
- package/dist/composables/defineConfig.d.ts.map +1 -0
- package/dist/composables/{defineConfig.mjs → defineConfig.js} +7 -9
- package/dist/composables/defineConfig.js.map +1 -0
- package/dist/composables/renderContext.d.ts +37 -0
- package/dist/composables/renderContext.d.ts.map +1 -0
- package/dist/composables/renderContext.js +6 -0
- package/dist/composables/renderContext.js.map +1 -0
- package/dist/composables/useBaseUrl.d.ts +19 -0
- package/dist/composables/useBaseUrl.d.ts.map +1 -0
- package/dist/composables/useBaseUrl.js +26 -0
- package/dist/composables/useBaseUrl.js.map +1 -0
- package/dist/composables/useConfig.d.ts +16 -0
- package/dist/composables/useConfig.d.ts.map +1 -0
- package/dist/composables/useConfig.js +19 -0
- package/dist/composables/useConfig.js.map +1 -0
- package/dist/composables/useCurrentTemplate.d.ts +31 -0
- package/dist/composables/useCurrentTemplate.d.ts.map +1 -0
- package/dist/composables/useCurrentTemplate.js +42 -0
- package/dist/composables/useCurrentTemplate.js.map +1 -0
- package/dist/composables/{useDoctype.d.mts → useDoctype.d.ts} +1 -1
- package/dist/composables/useDoctype.d.ts.map +1 -0
- package/dist/composables/{useDoctype.mjs → useDoctype.js} +3 -4
- package/dist/composables/useDoctype.js.map +1 -0
- package/dist/composables/{useEvent.d.mts → useEvent.d.ts} +3 -3
- package/dist/composables/useEvent.d.ts.map +1 -0
- package/dist/composables/{useEvent.mjs → useEvent.js} +4 -5
- package/dist/composables/useEvent.js.map +1 -0
- package/dist/composables/useFont.d.ts +50 -0
- package/dist/composables/useFont.d.ts.map +1 -0
- package/dist/composables/useFont.js +92 -0
- package/dist/composables/useFont.js.map +1 -0
- package/dist/composables/useOutlookFallback.d.ts +21 -0
- package/dist/composables/useOutlookFallback.d.ts.map +1 -0
- package/dist/composables/useOutlookFallback.js +29 -0
- package/dist/composables/useOutlookFallback.js.map +1 -0
- package/dist/composables/useOutputPath.d.ts +17 -0
- package/dist/composables/useOutputPath.d.ts.map +1 -0
- package/dist/composables/useOutputPath.js +23 -0
- package/dist/composables/useOutputPath.js.map +1 -0
- package/dist/composables/{usePlaintext.d.mts → usePlaintext.d.ts} +3 -1
- package/dist/composables/usePlaintext.d.ts.map +1 -0
- package/dist/composables/{usePlaintext.mjs → usePlaintext.js} +4 -4
- package/dist/composables/usePlaintext.js.map +1 -0
- package/dist/composables/usePreheader.d.ts +25 -0
- package/dist/composables/usePreheader.d.ts.map +1 -0
- package/dist/composables/usePreheader.js +28 -0
- package/dist/composables/usePreheader.js.map +1 -0
- package/dist/composables/useTransformers.d.ts +34 -0
- package/dist/composables/useTransformers.d.ts.map +1 -0
- package/dist/composables/useTransformers.js +48 -0
- package/dist/composables/useTransformers.js.map +1 -0
- package/dist/composables/useUrlQuery.d.ts +19 -0
- package/dist/composables/useUrlQuery.d.ts.map +1 -0
- package/dist/composables/useUrlQuery.js +26 -0
- package/dist/composables/useUrlQuery.js.map +1 -0
- package/dist/config/{defaults.d.mts → defaults.d.ts} +2 -2
- package/dist/config/defaults.d.ts.map +1 -0
- package/dist/config/{defaults.mjs → defaults.js} +10 -6
- package/dist/config/defaults.js.map +1 -0
- package/dist/config/index.d.ts +24 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/{index.mjs → index.js} +45 -14
- package/dist/config/index.js.map +1 -0
- package/dist/events/{index.d.mts → index.d.ts} +35 -12
- package/dist/events/index.d.ts.map +1 -0
- package/dist/events/{index.mjs → index.js} +31 -13
- package/dist/events/index.js.map +1 -0
- package/dist/index.d.ts +41 -0
- package/dist/index.js +40 -0
- package/dist/{plaintext.d.mts → plaintext.d.ts} +1 -1
- package/dist/plaintext.d.ts.map +1 -0
- package/dist/{plaintext.mjs → plaintext.js} +4 -5
- package/dist/plaintext.js.map +1 -0
- package/dist/{plugin.d.mts → plugin.d.ts} +2 -2
- package/dist/plugin.d.ts.map +1 -0
- package/dist/{plugin.mjs → plugin.js} +16 -13
- package/dist/plugin.js.map +1 -0
- package/dist/plugins/postcss/{mergeMediaQueries.d.mts → mergeMediaQueries.d.ts} +2 -2
- package/dist/plugins/postcss/mergeMediaQueries.d.ts.map +1 -0
- package/dist/plugins/postcss/{mergeMediaQueries.mjs → mergeMediaQueries.js} +2 -3
- package/dist/plugins/postcss/mergeMediaQueries.js.map +1 -0
- package/dist/plugins/postcss/{pruneVars.d.mts → pruneVars.d.ts} +1 -1
- package/dist/plugins/postcss/pruneVars.d.ts.map +1 -0
- package/dist/plugins/postcss/{pruneVars.mjs → pruneVars.js} +2 -2
- package/dist/plugins/postcss/pruneVars.js.map +1 -0
- package/dist/plugins/postcss/quoteFontFamilies.d.ts +13 -0
- package/dist/plugins/postcss/quoteFontFamilies.d.ts.map +1 -0
- package/dist/plugins/postcss/quoteFontFamilies.js +84 -0
- package/dist/plugins/postcss/quoteFontFamilies.js.map +1 -0
- package/dist/plugins/postcss/{removeDeclarations.d.mts → removeDeclarations.d.ts} +1 -1
- package/dist/plugins/postcss/removeDeclarations.d.ts.map +1 -0
- package/dist/plugins/postcss/{removeDeclarations.mjs → removeDeclarations.js} +2 -2
- package/dist/plugins/postcss/removeDeclarations.js.map +1 -0
- package/dist/plugins/postcss/resolveMaizzleImports.d.ts +16 -0
- package/dist/plugins/postcss/resolveMaizzleImports.d.ts.map +1 -0
- package/dist/plugins/postcss/resolveMaizzleImports.js +39 -0
- package/dist/plugins/postcss/resolveMaizzleImports.js.map +1 -0
- package/dist/plugins/postcss/resolveProps.d.ts +8 -0
- package/dist/plugins/postcss/resolveProps.d.ts.map +1 -0
- package/dist/plugins/postcss/resolveProps.js +155 -0
- package/dist/plugins/postcss/resolveProps.js.map +1 -0
- package/dist/plugins/postcss/{tailwindCleanup.d.mts → tailwindCleanup.d.ts} +2 -2
- package/dist/plugins/postcss/tailwindCleanup.d.ts.map +1 -0
- package/dist/plugins/postcss/{tailwindCleanup.mjs → tailwindCleanup.js} +29 -5
- package/dist/plugins/postcss/tailwindCleanup.js.map +1 -0
- package/dist/prepare.d.ts +17 -0
- package/dist/prepare.d.ts.map +1 -0
- package/dist/prepare.js +44 -0
- package/dist/prepare.js.map +1 -0
- package/dist/render/active.d.ts +8 -0
- package/dist/render/active.d.ts.map +1 -0
- package/dist/render/active.js +12 -0
- package/dist/render/active.js.map +1 -0
- package/dist/render/buildTemplate.d.ts +49 -0
- package/dist/render/buildTemplate.d.ts.map +1 -0
- package/dist/render/buildTemplate.js +141 -0
- package/dist/render/buildTemplate.js.map +1 -0
- package/dist/render/{createRenderer.d.mts → createRenderer.d.ts} +17 -6
- package/dist/render/createRenderer.d.ts.map +1 -0
- package/dist/render/createRenderer.js +468 -0
- package/dist/render/createRenderer.js.map +1 -0
- package/dist/render/index.d.ts +18 -0
- package/dist/render/index.d.ts.map +1 -0
- package/dist/render/index.js +59 -0
- package/dist/render/index.js.map +1 -0
- package/dist/render/injectFonts.d.ts +15 -0
- package/dist/render/injectFonts.d.ts.map +1 -0
- package/dist/render/injectFonts.js +45 -0
- package/dist/render/injectFonts.js.map +1 -0
- package/dist/render/parallel/buildWorker.d.ts +31 -0
- package/dist/render/parallel/buildWorker.d.ts.map +1 -0
- package/dist/render/parallel/buildWorker.js +66 -0
- package/dist/render/parallel/buildWorker.js.map +1 -0
- package/dist/render/parallel/worker.mjs +28 -0
- package/dist/render/plugins/codeBlockExtract.d.ts +14 -0
- package/dist/render/plugins/codeBlockExtract.d.ts.map +1 -0
- package/dist/render/plugins/codeBlockExtract.js +38 -0
- package/dist/render/plugins/codeBlockExtract.js.map +1 -0
- package/dist/render/plugins/markdownExtract.d.ts +12 -0
- package/dist/render/plugins/markdownExtract.d.ts.map +1 -0
- package/dist/render/plugins/markdownExtract.js +49 -0
- package/dist/render/plugins/markdownExtract.js.map +1 -0
- package/dist/render/plugins/rawExtract.d.ts +14 -0
- package/dist/render/plugins/rawExtract.d.ts.map +1 -0
- package/dist/render/plugins/rawExtract.js +34 -0
- package/dist/render/plugins/rawExtract.js.map +1 -0
- package/dist/render/plugins/rowSourceLocation.d.ts +18 -0
- package/dist/render/plugins/rowSourceLocation.d.ts.map +1 -0
- package/dist/render/plugins/rowSourceLocation.js +45 -0
- package/dist/render/plugins/rowSourceLocation.js.map +1 -0
- package/dist/{serve.d.mts → serve.d.ts} +5 -3
- package/dist/serve.d.ts.map +1 -0
- package/dist/{serve.mjs → serve.js} +207 -106
- package/dist/serve.js.map +1 -0
- package/dist/server/compatibility.d.ts +59 -0
- package/dist/server/compatibility.d.ts.map +1 -0
- package/dist/server/compatibility.js +959 -0
- package/dist/server/compatibility.js.map +1 -0
- package/dist/server/{email.d.mts → email.d.ts} +2 -2
- package/dist/server/email.d.ts.map +1 -0
- package/dist/server/{email.mjs → email.js} +2 -3
- package/dist/server/email.js.map +1 -0
- package/dist/server/linter.d.ts +20 -0
- package/dist/server/linter.d.ts.map +1 -0
- package/dist/server/linter.js +345 -0
- package/dist/server/linter.js.map +1 -0
- package/dist/server/sfc-utils.d.ts +21 -0
- package/dist/server/sfc-utils.d.ts.map +1 -0
- package/dist/server/sfc-utils.js +198 -0
- package/dist/server/sfc-utils.js.map +1 -0
- package/dist/server/ui/.vite/deps/@lucide_vue.js +44967 -0
- package/dist/server/ui/.vite/deps/@lucide_vue.js.map +1 -0
- package/dist/server/ui/.vite/deps/@vueuse_core.js +8155 -0
- package/dist/server/ui/.vite/deps/@vueuse_core.js.map +1 -0
- package/dist/server/ui/.vite/deps/@vueuse_shared.js +1859 -0
- package/dist/server/ui/.vite/deps/@vueuse_shared.js.map +1 -0
- package/dist/server/ui/.vite/deps/_metadata.json +78 -0
- package/dist/server/ui/.vite/deps/chunk-EAsCxrDo.js +14 -0
- package/dist/server/ui/.vite/deps/class-variance-authority.js +57 -0
- package/dist/server/ui/.vite/deps/class-variance-authority.js.map +1 -0
- package/dist/server/ui/.vite/deps/clsx.js +18 -0
- package/dist/server/ui/.vite/deps/clsx.js.map +1 -0
- package/dist/server/ui/.vite/deps/culori.js +4312 -0
- package/dist/server/ui/.vite/deps/culori.js.map +1 -0
- package/dist/server/ui/.vite/deps/package.json +3 -0
- package/dist/server/ui/.vite/deps/reka-ui.js +44464 -0
- package/dist/server/ui/.vite/deps/reka-ui.js.map +1 -0
- package/dist/server/ui/.vite/deps/tailwind-merge.js +3458 -0
- package/dist/server/ui/.vite/deps/tailwind-merge.js.map +1 -0
- package/dist/server/ui/.vite/deps/vue-router.js +6383 -0
- package/dist/server/ui/.vite/deps/vue-router.js.map +1 -0
- package/dist/server/ui/.vite/deps/vue.js +2 -0
- package/dist/server/ui/.vite/deps/vue.runtime.esm-bundler-DaqjATE_.js +8785 -0
- package/dist/server/ui/.vite/deps/vue.runtime.esm-bundler-DaqjATE_.js.map +1 -0
- package/dist/server/ui/App.vue +106 -66
- package/dist/server/ui/components/SidebarClose.vue +12 -0
- package/dist/server/ui/components/ui/checkbox/Checkbox.vue +1 -1
- package/dist/server/ui/components/ui/command/Command.vue +5 -1
- package/dist/server/ui/components/ui/command/CommandInput.vue +2 -2
- package/dist/server/ui/components/ui/dialog/DialogContent.vue +1 -1
- package/dist/server/ui/components/ui/dialog/DialogScrollContent.vue +1 -1
- package/dist/server/ui/components/ui/dropdown-menu/DropdownMenuCheckboxItem.vue +1 -1
- package/dist/server/ui/components/ui/dropdown-menu/DropdownMenuRadioItem.vue +1 -1
- package/dist/server/ui/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue +1 -1
- package/dist/server/ui/components/ui/input/Input.vue +1 -1
- package/dist/server/ui/components/ui/sheet/SheetContent.vue +1 -1
- package/dist/server/ui/components/ui/sidebar/SidebarTrigger.vue +2 -2
- package/dist/server/ui/components/ui/tags-input/TagsInputInput.vue +1 -1
- package/dist/server/ui/components/ui/tags-input/TagsInputItemDelete.vue +1 -1
- package/dist/server/ui/lib/emulated-dark-mode.ts +146 -0
- package/dist/server/ui/main.css +25 -0
- package/dist/server/ui/pages/Home.vue +1 -1
- package/dist/server/ui/pages/Preview.vue +377 -186
- package/dist/server/ui/vite-env.d.ts +1 -0
- package/dist/tests/render/_helpers.d.ts +6 -0
- package/dist/tests/render/_helpers.d.ts.map +1 -0
- package/dist/tests/render/_helpers.js +16 -0
- package/dist/tests/render/_helpers.js.map +1 -0
- package/dist/transformers/addAttributes.d.ts +42 -0
- package/dist/transformers/addAttributes.d.ts.map +1 -0
- package/dist/transformers/{addAttributes.mjs → addAttributes.js} +40 -24
- package/dist/transformers/addAttributes.js.map +1 -0
- package/dist/transformers/attributeToStyle.d.ts +38 -0
- package/dist/transformers/attributeToStyle.d.ts.map +1 -0
- package/dist/transformers/attributeToStyle.js +94 -0
- package/dist/transformers/attributeToStyle.js.map +1 -0
- package/dist/transformers/base.d.ts +71 -0
- package/dist/transformers/base.d.ts.map +1 -0
- package/dist/transformers/{base.mjs → base.js} +65 -40
- package/dist/transformers/base.js.map +1 -0
- package/dist/transformers/columnWidth.d.ts +31 -0
- package/dist/transformers/columnWidth.d.ts.map +1 -0
- package/dist/transformers/columnWidth.js +527 -0
- package/dist/transformers/columnWidth.js.map +1 -0
- package/dist/transformers/entities.d.ts +37 -0
- package/dist/transformers/entities.d.ts.map +1 -0
- package/dist/transformers/entities.js +74 -0
- package/dist/transformers/entities.js.map +1 -0
- package/dist/transformers/filters/{defaults.d.mts → defaults.d.ts} +1 -1
- package/dist/transformers/filters/defaults.d.ts.map +1 -0
- package/dist/transformers/filters/{defaults.mjs → defaults.js} +2 -2
- package/dist/transformers/filters/defaults.js.map +1 -0
- package/dist/transformers/filters/index.d.ts +43 -0
- package/dist/transformers/filters/index.d.ts.map +1 -0
- package/dist/transformers/filters/index.js +89 -0
- package/dist/transformers/filters/index.js.map +1 -0
- package/dist/transformers/format.d.ts +22 -0
- package/dist/transformers/format.d.ts.map +1 -0
- package/dist/transformers/format.js +30 -0
- package/dist/transformers/format.js.map +1 -0
- package/dist/transformers/imgWidth.d.ts +20 -0
- package/dist/transformers/imgWidth.d.ts.map +1 -0
- package/dist/transformers/imgWidth.js +76 -0
- package/dist/transformers/imgWidth.js.map +1 -0
- package/dist/transformers/{index.d.mts → index.d.ts} +14 -12
- package/dist/transformers/index.d.ts.map +1 -0
- package/dist/transformers/index.js +163 -0
- package/dist/transformers/index.js.map +1 -0
- package/dist/transformers/inlineCss.d.ts +85 -0
- package/dist/transformers/inlineCss.d.ts.map +1 -0
- package/dist/transformers/inlineCss.js +112 -0
- package/dist/transformers/inlineCss.js.map +1 -0
- package/dist/transformers/inlineLink.d.ts +35 -0
- package/dist/transformers/inlineLink.d.ts.map +1 -0
- package/dist/transformers/{inlineLink.mjs → inlineLink.js} +35 -11
- package/dist/transformers/inlineLink.js.map +1 -0
- package/dist/transformers/minify.d.ts +21 -0
- package/dist/transformers/minify.d.ts.map +1 -0
- package/dist/transformers/minify.js +25 -0
- package/dist/transformers/minify.js.map +1 -0
- package/dist/transformers/minifyCodeInline.d.ts +29 -0
- package/dist/transformers/minifyCodeInline.d.ts.map +1 -0
- package/dist/transformers/minifyCodeInline.js +36 -0
- package/dist/transformers/minifyCodeInline.js.map +1 -0
- package/dist/transformers/msoPlaceholders.d.ts +33 -0
- package/dist/transformers/msoPlaceholders.d.ts.map +1 -0
- package/dist/transformers/msoPlaceholders.js +114 -0
- package/dist/transformers/msoPlaceholders.js.map +1 -0
- package/dist/transformers/purgeCss.d.ts +43 -0
- package/dist/transformers/purgeCss.d.ts.map +1 -0
- package/dist/transformers/purgeCss.js +207 -0
- package/dist/transformers/purgeCss.js.map +1 -0
- package/dist/transformers/removeAttributes.d.ts +54 -0
- package/dist/transformers/removeAttributes.d.ts.map +1 -0
- package/dist/transformers/removeAttributes.js +72 -0
- package/dist/transformers/removeAttributes.js.map +1 -0
- package/dist/transformers/{replaceStrings.d.mts → replaceStrings.d.ts} +2 -2
- package/dist/transformers/replaceStrings.d.ts.map +1 -0
- package/dist/transformers/{replaceStrings.mjs → replaceStrings.js} +2 -2
- package/dist/transformers/replaceStrings.js.map +1 -0
- package/dist/transformers/safeSelectors.d.ts +37 -0
- package/dist/transformers/safeSelectors.d.ts.map +1 -0
- package/dist/transformers/{safeClassNames.mjs → safeSelectors.js} +40 -10
- package/dist/transformers/safeSelectors.js.map +1 -0
- package/dist/transformers/shorthandCss.d.ts +47 -0
- package/dist/transformers/shorthandCss.d.ts.map +1 -0
- package/dist/transformers/shorthandCss.js +92 -0
- package/dist/transformers/shorthandCss.js.map +1 -0
- package/dist/transformers/sixHex.d.ts +25 -0
- package/dist/transformers/sixHex.d.ts.map +1 -0
- package/dist/transformers/sixHex.js +42 -0
- package/dist/transformers/sixHex.js.map +1 -0
- package/dist/transformers/tailwindComponent.d.ts +16 -0
- package/dist/transformers/tailwindComponent.d.ts.map +1 -0
- package/dist/transformers/tailwindComponent.js +101 -0
- package/dist/transformers/tailwindComponent.js.map +1 -0
- package/dist/transformers/{tailwindcss.d.mts → tailwindcss.d.ts} +2 -2
- package/dist/transformers/tailwindcss.d.ts.map +1 -0
- package/dist/transformers/{tailwindcss.mjs → tailwindcss.js} +33 -74
- package/dist/transformers/tailwindcss.js.map +1 -0
- package/dist/transformers/urlQuery.d.ts +36 -0
- package/dist/transformers/urlQuery.d.ts.map +1 -0
- package/dist/transformers/urlQuery.js +77 -0
- package/dist/transformers/urlQuery.js.map +1 -0
- package/dist/types/{config.d.mts → config.d.ts} +270 -40
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +1 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.js +1 -0
- package/dist/utils/ast/index.d.ts +4 -0
- package/dist/utils/ast/index.js +4 -0
- package/dist/utils/ast/{parser.d.mts → parser.d.ts} +1 -1
- package/dist/utils/ast/parser.d.ts.map +1 -0
- package/dist/utils/ast/{parser.mjs → parser.js} +2 -3
- package/dist/utils/ast/parser.js.map +1 -0
- package/dist/utils/ast/{serializer.d.mts → serializer.d.ts} +1 -1
- package/dist/utils/ast/serializer.d.ts.map +1 -0
- package/dist/utils/ast/serializer.js +46 -0
- package/dist/utils/ast/serializer.js.map +1 -0
- package/dist/utils/ast/{walker.d.mts → walker.d.ts} +1 -1
- package/dist/utils/ast/walker.d.ts.map +1 -0
- package/dist/utils/ast/{walker.mjs → walker.js} +2 -2
- package/dist/utils/ast/walker.js.map +1 -0
- package/dist/utils/cloneConfig.d.ts +13 -0
- package/dist/utils/cloneConfig.d.ts.map +1 -0
- package/dist/utils/cloneConfig.js +21 -0
- package/dist/utils/cloneConfig.js.map +1 -0
- package/dist/utils/compileTailwindCss.d.ts +16 -0
- package/dist/utils/compileTailwindCss.d.ts.map +1 -0
- package/dist/utils/compileTailwindCss.js +55 -0
- package/dist/utils/compileTailwindCss.js.map +1 -0
- package/dist/utils/componentSources.d.ts +50 -0
- package/dist/utils/componentSources.d.ts.map +1 -0
- package/dist/utils/componentSources.js +50 -0
- package/dist/utils/componentSources.js.map +1 -0
- package/dist/utils/cssBox.d.ts +42 -0
- package/dist/utils/cssBox.d.ts.map +1 -0
- package/dist/utils/cssBox.js +151 -0
- package/dist/utils/cssBox.js.map +1 -0
- package/dist/utils/decodeStyleEntities.d.ts +15 -0
- package/dist/utils/decodeStyleEntities.d.ts.map +1 -0
- package/dist/utils/decodeStyleEntities.js +18 -0
- package/dist/utils/decodeStyleEntities.js.map +1 -0
- package/dist/utils/{detect.d.mts → detect.d.ts} +1 -1
- package/dist/utils/detect.d.ts.map +1 -0
- package/dist/utils/{detect.mjs → detect.js} +2 -3
- package/dist/utils/detect.js.map +1 -0
- package/dist/utils/output-markers.d.ts +29 -0
- package/dist/utils/output-markers.d.ts.map +1 -0
- package/dist/utils/output-markers.js +68 -0
- package/dist/utils/output-markers.js.map +1 -0
- package/dist/utils/{url.d.mts → url.d.ts} +1 -1
- package/dist/utils/url.d.ts.map +1 -0
- package/dist/utils/{url.mjs → url.js} +2 -3
- package/dist/utils/url.js.map +1 -0
- package/dist/utils/watchPaths.d.ts +11 -0
- package/dist/utils/watchPaths.d.ts.map +1 -0
- package/dist/utils/watchPaths.js +19 -0
- package/dist/utils/watchPaths.js.map +1 -0
- package/node_modules/@clack/core/CHANGELOG.md +44 -0
- package/node_modules/@clack/core/dist/index.d.mts +125 -5
- package/node_modules/@clack/core/dist/index.mjs +972 -11
- package/node_modules/@clack/core/package.json +6 -2
- package/node_modules/@clack/prompts/CHANGELOG.md +70 -0
- package/node_modules/@clack/prompts/README.md +129 -3
- package/node_modules/@clack/prompts/dist/index.d.mts +567 -33
- package/node_modules/@clack/prompts/dist/index.mjs +1378 -133
- package/node_modules/@clack/prompts/package.json +7 -4
- package/node_modules/fast-string-truncated-width/dist/index.js +36 -96
- package/node_modules/fast-string-truncated-width/dist/types.d.ts +0 -3
- package/node_modules/fast-string-truncated-width/dist/utils.d.ts +3 -3
- package/node_modules/fast-string-truncated-width/dist/utils.js +14 -9
- package/node_modules/fast-string-truncated-width/package.json +1 -1
- package/node_modules/fast-string-truncated-width/readme.md +2 -3
- package/node_modules/fast-string-width/package.json +2 -2
- package/node_modules/fast-string-width/readme.md +0 -3
- package/node_modules/fast-wrap-ansi/lib/main.js +4 -2
- package/node_modules/fast-wrap-ansi/package.json +11 -11
- package/node_modules/maizzle/README.md +24 -0
- package/node_modules/maizzle/dist/commands/make/component.mjs +1 -1
- package/node_modules/maizzle/dist/commands/make/config.mjs +8 -7
- package/node_modules/maizzle/dist/commands/make/layout.mjs +3 -3
- package/node_modules/maizzle/dist/commands/make/scaffold.mjs +1 -1
- package/node_modules/maizzle/dist/commands/make/stubs/Layout.vue +146 -0
- package/node_modules/maizzle/dist/commands/make/stubs/component.vue +2 -4
- package/node_modules/maizzle/dist/commands/make/stubs/config.ts +1 -5
- package/node_modules/maizzle/dist/commands/make/template.mjs +1 -1
- package/node_modules/maizzle/dist/commands/new.mjs +46 -135
- package/node_modules/maizzle/dist/index.d.mts +1 -0
- package/node_modules/maizzle/dist/index.mjs +30 -7
- package/node_modules/maizzle/package.json +5 -4
- package/node_modules/nypm/dist/cli.mjs +28 -5
- package/node_modules/nypm/dist/index.d.mts +0 -8
- package/node_modules/nypm/dist/index.mjs +27 -4
- package/node_modules/nypm/package.json +12 -12
- package/node_modules/tinyexec/README.md +9 -1
- package/node_modules/tinyexec/dist/main.d.mts +22 -7
- package/node_modules/tinyexec/dist/main.mjs +189 -491
- package/node_modules/tinyexec/package.json +14 -16
- package/package.json +38 -30
- package/dist/build.d.mts +0 -19
- package/dist/build.d.mts.map +0 -1
- package/dist/build.mjs +0 -140
- package/dist/build.mjs.map +0 -1
- package/dist/components/Divider.vue +0 -133
- package/dist/components/Image.vue +0 -70
- package/dist/components/Overlap.vue +0 -80
- package/dist/components/utils.d.mts +0 -5
- package/dist/components/utils.d.mts.map +0 -1
- package/dist/components/utils.mjs +0 -9
- package/dist/components/utils.mjs.map +0 -1
- package/dist/composables/defineConfig.d.mts +0 -14
- package/dist/composables/defineConfig.d.mts.map +0 -1
- package/dist/composables/defineConfig.mjs.map +0 -1
- package/dist/composables/renderContext.d.mts +0 -24
- package/dist/composables/renderContext.d.mts.map +0 -1
- package/dist/composables/renderContext.mjs +0 -6
- package/dist/composables/renderContext.mjs.map +0 -1
- package/dist/composables/useConfig.d.mts +0 -9
- package/dist/composables/useConfig.d.mts.map +0 -1
- package/dist/composables/useConfig.mjs +0 -13
- package/dist/composables/useConfig.mjs.map +0 -1
- package/dist/composables/useDoctype.d.mts.map +0 -1
- package/dist/composables/useDoctype.mjs.map +0 -1
- package/dist/composables/useEvent.d.mts.map +0 -1
- package/dist/composables/useEvent.mjs.map +0 -1
- package/dist/composables/usePlaintext.d.mts.map +0 -1
- package/dist/composables/usePlaintext.mjs.map +0 -1
- package/dist/composables/usePreviewText.d.mts +0 -24
- package/dist/composables/usePreviewText.d.mts.map +0 -1
- package/dist/composables/usePreviewText.mjs +0 -29
- package/dist/composables/usePreviewText.mjs.map +0 -1
- package/dist/config/defaults.d.mts.map +0 -1
- package/dist/config/defaults.mjs.map +0 -1
- package/dist/config/index.d.mts +0 -15
- package/dist/config/index.d.mts.map +0 -1
- package/dist/config/index.mjs.map +0 -1
- package/dist/events/index.d.mts.map +0 -1
- package/dist/events/index.mjs.map +0 -1
- package/dist/index.d.mts +0 -30
- package/dist/index.mjs +0 -30
- package/dist/plaintext.d.mts.map +0 -1
- package/dist/plaintext.mjs.map +0 -1
- package/dist/plugin.d.mts.map +0 -1
- package/dist/plugin.mjs.map +0 -1
- package/dist/plugins/postcss/mergeMediaQueries.d.mts.map +0 -1
- package/dist/plugins/postcss/mergeMediaQueries.mjs.map +0 -1
- package/dist/plugins/postcss/pruneVars.d.mts.map +0 -1
- package/dist/plugins/postcss/pruneVars.mjs.map +0 -1
- package/dist/plugins/postcss/removeDeclarations.d.mts.map +0 -1
- package/dist/plugins/postcss/removeDeclarations.mjs.map +0 -1
- package/dist/plugins/postcss/tailwindCleanup.d.mts.map +0 -1
- package/dist/plugins/postcss/tailwindCleanup.mjs.map +0 -1
- package/dist/render/createRenderer.d.mts.map +0 -1
- package/dist/render/createRenderer.mjs +0 -279
- package/dist/render/createRenderer.mjs.map +0 -1
- package/dist/render/index.d.mts +0 -26
- package/dist/render/index.d.mts.map +0 -1
- package/dist/render/index.mjs +0 -45
- package/dist/render/index.mjs.map +0 -1
- package/dist/serve.d.mts.map +0 -1
- package/dist/serve.mjs.map +0 -1
- package/dist/server/compatibility.d.mts +0 -5
- package/dist/server/compatibility.d.mts.map +0 -1
- package/dist/server/compatibility.mjs +0 -97
- package/dist/server/compatibility.mjs.map +0 -1
- package/dist/server/email.d.mts.map +0 -1
- package/dist/server/email.mjs.map +0 -1
- package/dist/server/linter.d.mts +0 -5
- package/dist/server/linter.d.mts.map +0 -1
- package/dist/server/linter.mjs +0 -189
- package/dist/server/linter.mjs.map +0 -1
- package/dist/transformers/addAttributes.d.mts +0 -32
- package/dist/transformers/addAttributes.d.mts.map +0 -1
- package/dist/transformers/addAttributes.mjs.map +0 -1
- package/dist/transformers/attributeToStyle.d.mts +0 -25
- package/dist/transformers/attributeToStyle.d.mts.map +0 -1
- package/dist/transformers/attributeToStyle.mjs +0 -80
- package/dist/transformers/attributeToStyle.mjs.map +0 -1
- package/dist/transformers/base.d.mts +0 -8
- package/dist/transformers/base.d.mts.map +0 -1
- package/dist/transformers/base.mjs.map +0 -1
- package/dist/transformers/entities.d.mts +0 -8
- package/dist/transformers/entities.d.mts.map +0 -1
- package/dist/transformers/entities.mjs +0 -41
- package/dist/transformers/entities.mjs.map +0 -1
- package/dist/transformers/filters/defaults.d.mts.map +0 -1
- package/dist/transformers/filters/defaults.mjs.map +0 -1
- package/dist/transformers/filters/index.d.mts +0 -22
- package/dist/transformers/filters/index.d.mts.map +0 -1
- package/dist/transformers/filters/index.mjs +0 -67
- package/dist/transformers/filters/index.mjs.map +0 -1
- package/dist/transformers/format.d.mts +0 -15
- package/dist/transformers/format.d.mts.map +0 -1
- package/dist/transformers/format.mjs +0 -26
- package/dist/transformers/format.mjs.map +0 -1
- package/dist/transformers/index.d.mts.map +0 -1
- package/dist/transformers/index.mjs +0 -78
- package/dist/transformers/index.mjs.map +0 -1
- package/dist/transformers/inlineCSS.d.mts +0 -17
- package/dist/transformers/inlineCSS.d.mts.map +0 -1
- package/dist/transformers/inlineCSS.mjs +0 -70
- package/dist/transformers/inlineCSS.mjs.map +0 -1
- package/dist/transformers/inlineLink.d.mts +0 -14
- package/dist/transformers/inlineLink.d.mts.map +0 -1
- package/dist/transformers/inlineLink.mjs.map +0 -1
- package/dist/transformers/minify.d.mts +0 -17
- package/dist/transformers/minify.d.mts.map +0 -1
- package/dist/transformers/minify.mjs +0 -24
- package/dist/transformers/minify.mjs.map +0 -1
- package/dist/transformers/purgeCSS.d.mts +0 -23
- package/dist/transformers/purgeCSS.d.mts.map +0 -1
- package/dist/transformers/purgeCSS.mjs +0 -132
- package/dist/transformers/purgeCSS.mjs.map +0 -1
- package/dist/transformers/removeAttributes.d.mts +0 -31
- package/dist/transformers/removeAttributes.d.mts.map +0 -1
- package/dist/transformers/removeAttributes.mjs +0 -63
- package/dist/transformers/removeAttributes.mjs.map +0 -1
- package/dist/transformers/replaceStrings.d.mts.map +0 -1
- package/dist/transformers/replaceStrings.mjs.map +0 -1
- package/dist/transformers/safeClassNames.d.mts +0 -22
- package/dist/transformers/safeClassNames.d.mts.map +0 -1
- package/dist/transformers/safeClassNames.mjs.map +0 -1
- package/dist/transformers/shorthandCSS.d.mts +0 -24
- package/dist/transformers/shorthandCSS.d.mts.map +0 -1
- package/dist/transformers/shorthandCSS.mjs +0 -48
- package/dist/transformers/shorthandCSS.mjs.map +0 -1
- package/dist/transformers/tailwindcss.d.mts.map +0 -1
- package/dist/transformers/tailwindcss.mjs.map +0 -1
- package/dist/transformers/urlQuery.d.mts +0 -24
- package/dist/transformers/urlQuery.d.mts.map +0 -1
- package/dist/transformers/urlQuery.mjs +0 -65
- package/dist/transformers/urlQuery.mjs.map +0 -1
- package/dist/types/config.d.mts.map +0 -1
- package/dist/types/config.mjs +0 -1
- package/dist/types/index.d.mts +0 -2
- package/dist/types/index.mjs +0 -1
- package/dist/utils/ast/index.d.mts +0 -4
- package/dist/utils/ast/index.mjs +0 -5
- package/dist/utils/ast/parser.d.mts.map +0 -1
- package/dist/utils/ast/parser.mjs.map +0 -1
- package/dist/utils/ast/serializer.d.mts.map +0 -1
- package/dist/utils/ast/serializer.mjs +0 -37
- package/dist/utils/ast/serializer.mjs.map +0 -1
- package/dist/utils/ast/walker.d.mts.map +0 -1
- package/dist/utils/ast/walker.mjs.map +0 -1
- package/dist/utils/detect.d.mts.map +0 -1
- package/dist/utils/detect.mjs.map +0 -1
- package/dist/utils/url.d.mts.map +0 -1
- package/dist/utils/url.mjs.map +0 -1
- package/node_modules/@clack/core/dist/index.mjs.map +0 -1
- package/node_modules/@clack/prompts/dist/index.mjs.map +0 -1
- package/node_modules/fast-wrap-ansi/lib/main.js.map +0 -1
- package/node_modules/maizzle/dist/commands/make/stubs/layout.vue +0 -39
- package/node_modules/tinyexec/dist/LICENSES.txt +0 -83
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { ref, computed, watch, nextTick, onMounted, onUnmounted } from 'vue'
|
|
3
3
|
import { useRoute } from 'vue-router'
|
|
4
|
-
import { ChevronUp, ChevronDown, Check
|
|
4
|
+
import { ChevronUp, ChevronDown, Check } from '@lucide/vue'
|
|
5
5
|
import {
|
|
6
6
|
DropdownMenu,
|
|
7
7
|
DropdownMenuContent,
|
|
@@ -20,9 +20,9 @@ import {
|
|
|
20
20
|
TagsInputItemDelete,
|
|
21
21
|
TagsInputItemText,
|
|
22
22
|
} from '@/components/ui/tags-input'
|
|
23
|
-
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'
|
|
24
23
|
|
|
25
24
|
import stripesUrl from '../stripes.svg'
|
|
25
|
+
import { applyColorInversion, undoColorInversion } from '@/lib/emulated-dark-mode'
|
|
26
26
|
|
|
27
27
|
interface Device {
|
|
28
28
|
name: string
|
|
@@ -43,6 +43,7 @@ const props = defineProps<{
|
|
|
43
43
|
}>()
|
|
44
44
|
|
|
45
45
|
const viewMode = defineModel<'preview' | 'source'>('viewMode', { default: 'preview' })
|
|
46
|
+
const darkMode = defineModel<boolean>('darkMode', { default: false })
|
|
46
47
|
|
|
47
48
|
const route = useRoute()
|
|
48
49
|
const srcdoc = ref('')
|
|
@@ -52,26 +53,61 @@ const plaintextContent = ref('')
|
|
|
52
53
|
const sourceView = ref<'compiled' | 'vue' | 'plaintext'>('compiled')
|
|
53
54
|
const copied = ref(false)
|
|
54
55
|
|
|
56
|
+
/**
|
|
57
|
+
* Source views (Compiled HTML, Vue source, Plaintext) refresh lazily. On a
|
|
58
|
+
* save we only refetch the view currently on screen and bump
|
|
59
|
+
* `sourcesGeneration` to mark the others stale. Switching to a stale view
|
|
60
|
+
* keeps its previous content visible while a background refetch replaces it
|
|
61
|
+
* in place — so panels never flash empty. Each fetch stamps the generation
|
|
62
|
+
* it was initiated at so a save mid-fetch correctly leaves the view stale.
|
|
63
|
+
*/
|
|
64
|
+
const sourcesGeneration = ref(0)
|
|
65
|
+
const compiledGen = ref(-1)
|
|
66
|
+
const vueGen = ref(-1)
|
|
67
|
+
const plaintextGen = ref(-1)
|
|
68
|
+
|
|
69
|
+
function refreshSourceView(view: 'compiled' | 'vue' | 'plaintext') {
|
|
70
|
+
if (view === 'compiled' && (!sourceHtml.value || compiledGen.value < sourcesGeneration.value)) fetchSource()
|
|
71
|
+
if (view === 'vue' && (!vueSourceHtml.value || vueGen.value < sourcesGeneration.value)) fetchVueSource()
|
|
72
|
+
if (view === 'plaintext' && (!plaintextContent.value || plaintextGen.value < sourcesGeneration.value)) fetchPlaintext()
|
|
73
|
+
}
|
|
74
|
+
|
|
55
75
|
const iframeEl = ref<HTMLIFrameElement>()
|
|
56
76
|
const compiledSourceEl = ref<HTMLElement>()
|
|
57
77
|
const vueSourceEl = ref<HTMLElement>()
|
|
78
|
+
const plaintextEl = ref<HTMLElement>()
|
|
58
79
|
const containerEl = ref<HTMLElement>()
|
|
59
80
|
const wrapperEl = ref<HTMLElement>()
|
|
60
81
|
|
|
61
82
|
const panelWidth = defineModel<number>('panelWidth', { default: 0 })
|
|
62
83
|
const panelHeight = defineModel<number>('panelHeight', { default: 0 })
|
|
84
|
+
/**
|
|
85
|
+
* Container's available area, exposed to the toolbar so size inputs can
|
|
86
|
+
* clamp typed values without paying a layout-recalc cost on
|
|
87
|
+
* every drag tick. Kept in sync via a ResizeObserver.
|
|
88
|
+
*/
|
|
89
|
+
const maxIframeWidth = defineModel<number>('maxIframeWidth', { default: 0 })
|
|
90
|
+
const maxIframeHeight = defineModel<number>('maxIframeHeight', { default: 0 })
|
|
63
91
|
const isDragging = defineModel<boolean>('isDragging', { default: false })
|
|
64
92
|
const isFullSize = defineModel<boolean>('isFullSize', { default: true })
|
|
65
93
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
94
|
+
/**
|
|
95
|
+
* Custom resizable: width/height of the iframe wrapper (null = fill the
|
|
96
|
+
* container). Exposed as v-models so the toolbar's size indicator
|
|
97
|
+
* can drive these too, alongside the drag handles.
|
|
98
|
+
*/
|
|
99
|
+
const iframeWidth = defineModel<number | null>('iframeWidth', { default: null })
|
|
100
|
+
const iframeHeight = defineModel<number | null>('iframeHeight', { default: null })
|
|
69
101
|
const iframeContentHeight = ref<number | null>(null)
|
|
70
102
|
|
|
71
103
|
function copySource() {
|
|
72
104
|
let text: string
|
|
73
105
|
if (sourceView.value === 'compiled') {
|
|
74
|
-
|
|
106
|
+
/**
|
|
107
|
+
* `renderedHtml` holds the raw compiled HTML (srcdoc is only populated
|
|
108
|
+
* for the initial iframe load; subsequent renders use doc.write).
|
|
109
|
+
*/
|
|
110
|
+
text = renderedHtml || srcdoc.value
|
|
75
111
|
} else if (sourceView.value === 'plaintext') {
|
|
76
112
|
text = plaintextContent.value
|
|
77
113
|
} else {
|
|
@@ -80,28 +116,59 @@ function copySource() {
|
|
|
80
116
|
text = el.textContent || ''
|
|
81
117
|
}
|
|
82
118
|
|
|
83
|
-
|
|
84
|
-
const item = new ClipboardItem({ 'text/plain': blob })
|
|
85
|
-
navigator.clipboard.write([item]).then(() => {
|
|
119
|
+
navigator.clipboard.writeText(text).then(() => {
|
|
86
120
|
copied.value = true
|
|
87
121
|
setTimeout(() => { copied.value = false }, 2000)
|
|
122
|
+
}).catch((err) => {
|
|
123
|
+
console.error('Copy failed:', err)
|
|
88
124
|
})
|
|
89
125
|
}
|
|
90
126
|
|
|
91
|
-
interface
|
|
92
|
-
|
|
127
|
+
interface CheckIssue {
|
|
128
|
+
kind: 'compat' | 'lint'
|
|
129
|
+
slug?: string
|
|
93
130
|
title: string
|
|
94
|
-
category: string
|
|
95
|
-
clients: Array<{ name: string, notes: string[] }>
|
|
96
131
|
url?: string
|
|
132
|
+
category: string
|
|
97
133
|
line?: number
|
|
134
|
+
file: string
|
|
135
|
+
// compat-only
|
|
136
|
+
supportLevel?: 'unsupported' | 'mitigated' | 'unknown'
|
|
137
|
+
supportLabel?: string
|
|
138
|
+
affectedClients?: string[]
|
|
139
|
+
// lint-only
|
|
140
|
+
severity?: 'error' | 'warning'
|
|
141
|
+
message?: string
|
|
98
142
|
}
|
|
99
143
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
144
|
+
function supportPrefix(issue: CheckIssue): string {
|
|
145
|
+
if (issue.supportLevel === 'unsupported') return 'Not supported in'
|
|
146
|
+
if (issue.supportLevel === 'mitigated') return 'Partial support in'
|
|
147
|
+
return 'Support unknown in'
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Split a message on backtick-delimited code spans. Returns alternating
|
|
152
|
+
* { text } and { code } segments so the template can render <code> inline
|
|
153
|
+
* without needing v-html.
|
|
154
|
+
*/
|
|
155
|
+
function messageSegments(raw: string | undefined): Array<{ code: boolean, text: string }> {
|
|
156
|
+
if (!raw) return []
|
|
157
|
+
const out: Array<{ code: boolean, text: string }> = []
|
|
158
|
+
const parts = raw.split('`')
|
|
159
|
+
for (let i = 0; i < parts.length; i++) {
|
|
160
|
+
if (parts[i]) out.push({ code: i % 2 === 1, text: parts[i] })
|
|
161
|
+
}
|
|
162
|
+
return out
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function issueColorClass(issue: CheckIssue): string {
|
|
166
|
+
if (issue.kind === 'lint') {
|
|
167
|
+
return issue.severity === 'error' ? 'text-rose-600' : 'text-amber-600'
|
|
168
|
+
}
|
|
169
|
+
if (issue.supportLevel === 'unsupported') return 'text-rose-600'
|
|
170
|
+
if (issue.supportLevel === 'mitigated') return 'text-amber-600'
|
|
171
|
+
return 'text-gray-500 dark:text-gray-400'
|
|
105
172
|
}
|
|
106
173
|
|
|
107
174
|
interface TemplateStats {
|
|
@@ -110,10 +177,18 @@ interface TemplateStats {
|
|
|
110
177
|
links: number
|
|
111
178
|
}
|
|
112
179
|
|
|
113
|
-
const compatibilityIssues = ref<
|
|
180
|
+
const compatibilityIssues = ref<CheckIssue[]>([])
|
|
114
181
|
const compatibilityLoading = ref(false)
|
|
115
182
|
const compatibilityError = ref('')
|
|
116
183
|
const compatibilityCategory = ref('')
|
|
184
|
+
/**
|
|
185
|
+
* Injected by serveDevUI into index.html — synchronous, available before
|
|
186
|
+
* any HTTP calls, so the Checks tab never flashes in when disabled.
|
|
187
|
+
*/
|
|
188
|
+
const checksConfig = (window as any).__MAIZZLE_CONFIG__?.checks
|
|
189
|
+
const compatibilityDisabled = ref(checksConfig === false)
|
|
190
|
+
const expandedIssueKeys = ref(new Set<string>())
|
|
191
|
+
const issueKey = (issue: CheckIssue, i: number): string => `${issue.file}|${issue.line ?? 0}|${issue.slug ?? issue.title}|${i}`
|
|
117
192
|
const compatibilityCategories = ['css', 'html', 'image', 'others'] as const
|
|
118
193
|
const activeCompatibilityCategories = computed(() =>
|
|
119
194
|
compatibilityCategories.filter(cat => compatibilityIssues.value.some(i => i.category === cat))
|
|
@@ -122,8 +197,6 @@ const filteredCompatibilityIssues = computed(() => {
|
|
|
122
197
|
if (!compatibilityCategory.value) return compatibilityIssues.value
|
|
123
198
|
return compatibilityIssues.value.filter(i => i.category === compatibilityCategory.value)
|
|
124
199
|
})
|
|
125
|
-
const lintIssues = ref<LintIssue[]>([])
|
|
126
|
-
const lintLoading = ref(false)
|
|
127
200
|
const stats = ref<TemplateStats | null>(null)
|
|
128
201
|
const statsLoading = ref(false)
|
|
129
202
|
|
|
@@ -187,7 +260,11 @@ function updateIframeContentHeight() {
|
|
|
187
260
|
|
|
188
261
|
// Temporarily collapse to measure true content height
|
|
189
262
|
iframe.style.height = '0'
|
|
190
|
-
|
|
263
|
+
const contentHeight = doc.documentElement.scrollHeight
|
|
264
|
+
// Fill the preview viewport when the email is shorter than it; grow past it
|
|
265
|
+
// (and let the ScrollArea scroll) when the email is taller.
|
|
266
|
+
const availableHeight = viewport?.clientHeight ?? 0
|
|
267
|
+
iframeContentHeight.value = Math.max(contentHeight, availableHeight)
|
|
191
268
|
iframe.style.height = `${iframeContentHeight.value}px`
|
|
192
269
|
|
|
193
270
|
// Restore scroll position
|
|
@@ -196,6 +273,19 @@ function updateIframeContentHeight() {
|
|
|
196
273
|
}
|
|
197
274
|
}
|
|
198
275
|
|
|
276
|
+
function onIframeLoad() {
|
|
277
|
+
updateIframeContentHeight()
|
|
278
|
+
const iframe = iframeEl.value
|
|
279
|
+
if (darkMode.value && iframe) applyColorInversion(iframe)
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
watch(darkMode, (on) => {
|
|
283
|
+
const iframe = iframeEl.value
|
|
284
|
+
if (!iframe) return
|
|
285
|
+
if (on) applyColorInversion(iframe)
|
|
286
|
+
else undoColorInversion(iframe)
|
|
287
|
+
})
|
|
288
|
+
|
|
199
289
|
async function fetchTemplate() {
|
|
200
290
|
const res = await fetch(`/__maizzle/render/${route.params.template}`)
|
|
201
291
|
renderedHtml = await res.text()
|
|
@@ -203,14 +293,17 @@ async function fetchTemplate() {
|
|
|
203
293
|
const iframe = iframeEl.value
|
|
204
294
|
const doc = iframe?.contentDocument
|
|
205
295
|
|
|
206
|
-
|
|
207
|
-
|
|
296
|
+
/**
|
|
297
|
+
* Write directly into the iframe document to avoid a full reload,
|
|
298
|
+
* which preserves scroll position natively.
|
|
299
|
+
*/
|
|
208
300
|
if (doc) {
|
|
209
301
|
doc.open()
|
|
210
302
|
doc.write(renderedHtml)
|
|
211
303
|
doc.close()
|
|
212
304
|
// Hide iframe body overflow — scrolling is handled by the outer ScrollArea
|
|
213
305
|
if (doc.body) doc.body.style.overflow = 'hidden'
|
|
306
|
+
if (darkMode.value && iframe) applyColorInversion(iframe)
|
|
214
307
|
await nextTick()
|
|
215
308
|
updateIframeContentHeight()
|
|
216
309
|
} else {
|
|
@@ -219,19 +312,58 @@ async function fetchTemplate() {
|
|
|
219
312
|
}
|
|
220
313
|
}
|
|
221
314
|
|
|
315
|
+
const sourceLoading = ref(false)
|
|
316
|
+
const vueSourceLoading = ref(false)
|
|
317
|
+
const plaintextLoading = ref(false)
|
|
318
|
+
|
|
222
319
|
async function fetchSource() {
|
|
223
|
-
|
|
224
|
-
|
|
320
|
+
if (sourceLoading.value) return
|
|
321
|
+
sourceLoading.value = true
|
|
322
|
+
const gen = sourcesGeneration.value
|
|
323
|
+
try {
|
|
324
|
+
const res = await fetch(`/__maizzle/source/${route.params.template}`)
|
|
325
|
+
sourceHtml.value = await res.text()
|
|
326
|
+
compiledGen.value = gen
|
|
327
|
+
} finally {
|
|
328
|
+
sourceLoading.value = false
|
|
329
|
+
}
|
|
225
330
|
}
|
|
226
331
|
|
|
227
332
|
async function fetchVueSource() {
|
|
228
|
-
|
|
229
|
-
|
|
333
|
+
if (vueSourceLoading.value) return
|
|
334
|
+
vueSourceLoading.value = true
|
|
335
|
+
const gen = sourcesGeneration.value
|
|
336
|
+
try {
|
|
337
|
+
const res = await fetch(`/__maizzle/vue-source/${route.params.template}`)
|
|
338
|
+
vueSourceHtml.value = await res.text()
|
|
339
|
+
vueGen.value = gen
|
|
340
|
+
} finally {
|
|
341
|
+
vueSourceLoading.value = false
|
|
342
|
+
}
|
|
230
343
|
}
|
|
231
344
|
|
|
232
345
|
async function fetchPlaintext() {
|
|
233
|
-
|
|
234
|
-
|
|
346
|
+
if (plaintextLoading.value) return
|
|
347
|
+
plaintextLoading.value = true
|
|
348
|
+
const gen = sourcesGeneration.value
|
|
349
|
+
try {
|
|
350
|
+
const res = await fetch(`/__maizzle/plaintext/${route.params.template}`)
|
|
351
|
+
plaintextContent.value = await res.text()
|
|
352
|
+
plaintextGen.value = gen
|
|
353
|
+
} finally {
|
|
354
|
+
plaintextLoading.value = false
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* Warm the three source views in the background so switching from the
|
|
360
|
+
* preview is instant. Single-flight guards above prevent duplication
|
|
361
|
+
* with any in-flight fetch from a view-switch watcher.
|
|
362
|
+
*/
|
|
363
|
+
function prefetchSources() {
|
|
364
|
+
if (!sourceHtml.value) fetchSource()
|
|
365
|
+
if (!vueSourceHtml.value) fetchVueSource()
|
|
366
|
+
if (!plaintextContent.value) fetchPlaintext()
|
|
235
367
|
}
|
|
236
368
|
|
|
237
369
|
async function fetchStats() {
|
|
@@ -247,22 +379,33 @@ async function fetchStats() {
|
|
|
247
379
|
}
|
|
248
380
|
|
|
249
381
|
async function fetchCompatibility() {
|
|
382
|
+
if (compatibilityDisabled.value) return
|
|
383
|
+
const template = props.templates?.find(t => t.href === '/' + route.params.template)
|
|
384
|
+
if (!template) return
|
|
385
|
+
|
|
250
386
|
compatibilityLoading.value = true
|
|
251
387
|
compatibilityError.value = ''
|
|
252
388
|
try {
|
|
253
|
-
const res = await fetch(
|
|
254
|
-
method: 'POST',
|
|
255
|
-
body: renderedHtml,
|
|
256
|
-
})
|
|
389
|
+
const res = await fetch(`/__maizzle/compatibility/${template.path}`)
|
|
257
390
|
const data = await res.json()
|
|
258
|
-
if (data?.error) {
|
|
391
|
+
if (!Array.isArray(data) && data?.error) {
|
|
259
392
|
compatibilityError.value = data.error
|
|
260
393
|
compatibilityIssues.value = []
|
|
261
394
|
} else {
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
395
|
+
const issues: CheckIssue[] = Array.isArray(data) ? data : []
|
|
396
|
+
compatibilityIssues.value = issues
|
|
397
|
+
/**
|
|
398
|
+
* Keep the current category if it still has issues; otherwise fall
|
|
399
|
+
* back to the first category that does. Prevents a "refresh"
|
|
400
|
+
* during edits from snapping back to CSS when the user is
|
|
401
|
+
* on HTML/Image.
|
|
402
|
+
*/
|
|
403
|
+
const current = compatibilityCategory.value
|
|
404
|
+
const currentStillActive = current && issues.some((i) => i.category === current)
|
|
405
|
+
if (!currentStillActive) {
|
|
406
|
+
const firstCat = compatibilityCategories.find(cat => issues.some((i) => i.category === cat))
|
|
407
|
+
compatibilityCategory.value = firstCat || ''
|
|
408
|
+
}
|
|
266
409
|
}
|
|
267
410
|
} catch {
|
|
268
411
|
compatibilityIssues.value = []
|
|
@@ -271,19 +414,21 @@ async function fetchCompatibility() {
|
|
|
271
414
|
}
|
|
272
415
|
}
|
|
273
416
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
417
|
+
/** Check if an issue is from the currently viewed template file */
|
|
418
|
+
function isCurrentFile(issue: { file: string }): boolean {
|
|
419
|
+
const template = props.templates?.find(t => t.href === '/' + route.params.template)
|
|
420
|
+
if (!template) return true
|
|
421
|
+
return issue.file.endsWith(template.path)
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
/** Get a short display name for a component file path */
|
|
425
|
+
function componentName(filePath: string): string {
|
|
426
|
+
const parts = filePath.replace(/\\/g, '/').split('/')
|
|
427
|
+
return parts[parts.length - 1]?.replace(/\.vue$/, '') ?? filePath
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
function openInEditor(file: string, line: number) {
|
|
431
|
+
fetch(`/__open-in-editor?file=${encodeURIComponent(file + ':' + line)}`)
|
|
287
432
|
}
|
|
288
433
|
|
|
289
434
|
watch(() => route.params.template, () => {
|
|
@@ -292,76 +437,98 @@ watch(() => route.params.template, () => {
|
|
|
292
437
|
plaintextContent.value = ''
|
|
293
438
|
compatibilityIssues.value = []
|
|
294
439
|
compatibilityError.value = ''
|
|
295
|
-
lintIssues.value = []
|
|
296
440
|
stats.value = null
|
|
297
441
|
emailResult.value = null
|
|
298
442
|
sourceView.value = 'compiled'
|
|
299
|
-
fetchTemplate().then(
|
|
300
|
-
|
|
443
|
+
fetchTemplate().then(prefetchSources)
|
|
444
|
+
fetchCompatibility()
|
|
301
445
|
fetchStats()
|
|
302
446
|
fetchEmailConfig()
|
|
303
447
|
if (viewMode.value === 'source') fetchSource()
|
|
304
448
|
}, { immediate: true })
|
|
305
449
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
if (sourceView.value === 'plaintext' && !plaintextContent.value) fetchPlaintext()
|
|
450
|
+
// Templates list loads async from App.vue — re-trigger once available
|
|
451
|
+
watch(() => props.templates, (templates) => {
|
|
452
|
+
if (templates?.length && !compatibilityIssues.value.length && !compatibilityLoading.value) {
|
|
453
|
+
fetchCompatibility()
|
|
311
454
|
}
|
|
312
455
|
})
|
|
313
456
|
|
|
314
|
-
watch(
|
|
315
|
-
if (
|
|
316
|
-
if (view === 'compiled' && !sourceHtml.value) fetchSource()
|
|
317
|
-
if (view === 'plaintext' && !plaintextContent.value) fetchPlaintext()
|
|
457
|
+
watch(viewMode, (mode) => {
|
|
458
|
+
if (mode === 'source') refreshSourceView(sourceView.value)
|
|
318
459
|
})
|
|
319
460
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
fetchLint()
|
|
324
|
-
fetchStats()
|
|
325
|
-
|
|
326
|
-
// Always clear all source views so they re-fetch when switched to
|
|
327
|
-
sourceHtml.value = ''
|
|
328
|
-
vueSourceHtml.value = ''
|
|
329
|
-
plaintextContent.value = ''
|
|
461
|
+
watch(sourceView, (view) => {
|
|
462
|
+
refreshSourceView(view)
|
|
463
|
+
})
|
|
330
464
|
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
465
|
+
/**
|
|
466
|
+
* Preserve scrollTop across in-place content updates (HMR refetch).
|
|
467
|
+
* Vue's default `flush: 'pre'` runs the watcher BEFORE the DOM is
|
|
468
|
+
* updated — so we read the current scrollTop, then restore it on the
|
|
469
|
+
* next tick after the new content has rendered. Skip the case where
|
|
470
|
+
* the value transitions from empty (first paint / route change) so a
|
|
471
|
+
* fresh template doesn't snap to a stale offset.
|
|
472
|
+
*/
|
|
473
|
+
function viewportFor(el: HTMLElement | undefined): HTMLElement | null {
|
|
474
|
+
return (el?.closest('[data-slot="scroll-area-viewport"]') as HTMLElement | null) ?? null
|
|
338
475
|
}
|
|
339
476
|
|
|
340
|
-
|
|
341
|
-
async
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
await fetchVueSource()
|
|
477
|
+
function preserveScroll(getEl: () => HTMLElement | undefined) {
|
|
478
|
+
return async (newVal: string, oldVal: string) => {
|
|
479
|
+
if (!oldVal || !newVal) return
|
|
480
|
+
const vp = viewportFor(getEl())
|
|
481
|
+
if (!vp) return
|
|
482
|
+
const top = vp.scrollTop
|
|
483
|
+
await nextTick()
|
|
484
|
+
vp.scrollTop = top
|
|
349
485
|
}
|
|
486
|
+
}
|
|
350
487
|
|
|
351
|
-
|
|
488
|
+
watch(sourceHtml, preserveScroll(() => compiledSourceEl.value))
|
|
489
|
+
watch(vueSourceHtml, preserveScroll(() => vueSourceEl.value))
|
|
490
|
+
watch(plaintextContent, preserveScroll(() => plaintextEl.value))
|
|
352
491
|
|
|
353
|
-
|
|
354
|
-
|
|
492
|
+
if ((import.meta as any).hot) {
|
|
493
|
+
;(import.meta as any).hot.on('maizzle:template-updated', () => {
|
|
494
|
+
fetchCompatibility()
|
|
495
|
+
fetchStats()
|
|
355
496
|
|
|
356
|
-
|
|
357
|
-
|
|
497
|
+
/**
|
|
498
|
+
* Refetch in place — don't clear the previous values first. v-html
|
|
499
|
+
* replaces the highlighted block atomically when the new content
|
|
500
|
+
* arrives, and the ScrollArea viewport keeps its scrollTop as
|
|
501
|
+
* long as the new content's height is similar. Plaintext
|
|
502
|
+
* interpolation updates a single text node, so scroll
|
|
503
|
+
* is naturally preserved.
|
|
504
|
+
*
|
|
505
|
+
* Only the preview iframe and the currently-visible source view
|
|
506
|
+
* refresh eagerly; hidden source views are marked stale (via the
|
|
507
|
+
* generation bump) and refresh on next switch, keeping their old
|
|
508
|
+
* content on screen until then so panels never flash empty.
|
|
509
|
+
*/
|
|
510
|
+
fetchTemplate()
|
|
511
|
+
sourcesGeneration.value++
|
|
512
|
+
if (viewMode.value === 'source') refreshSourceView(sourceView.value)
|
|
513
|
+
})
|
|
358
514
|
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
515
|
+
/**
|
|
516
|
+
* Keep the UI in sync with live config edits. Payload is the same shape
|
|
517
|
+
* as the initial `window.__MAIZZLE_CONFIG__` inject — we replace it
|
|
518
|
+
* and derive per-feature flags from there.
|
|
519
|
+
*/
|
|
520
|
+
;(import.meta as any).hot.on('maizzle:config-updated', (data: Record<string, unknown>) => {
|
|
521
|
+
;(window as any).__MAIZZLE_CONFIG__ = data
|
|
522
|
+
const wasDisabled = compatibilityDisabled.value
|
|
523
|
+
const nowDisabled = data?.checks === false
|
|
524
|
+
compatibilityDisabled.value = nowDisabled
|
|
525
|
+
if (nowDisabled) {
|
|
526
|
+
compatibilityIssues.value = []
|
|
527
|
+
if (activeTab.value === 'compatibility') activeTab.value = 'stats'
|
|
528
|
+
} else if (wasDisabled) {
|
|
529
|
+
fetchCompatibility()
|
|
530
|
+
}
|
|
531
|
+
})
|
|
365
532
|
}
|
|
366
533
|
|
|
367
534
|
async function goToCompiledLine(line: number) {
|
|
@@ -412,6 +579,8 @@ function onEdgeDrag(e: MouseEvent | TouchEvent, edge: Edge) {
|
|
|
412
579
|
const isHorizontal = edge === 'left' || edge === 'right'
|
|
413
580
|
const sign = (edge === 'left' || edge === 'top') ? -1 : 1
|
|
414
581
|
|
|
582
|
+
document.documentElement.style.cursor = isHorizontal ? 'ew-resize' : 'ns-resize'
|
|
583
|
+
|
|
415
584
|
const onMove = (ev: MouseEvent | TouchEvent) => {
|
|
416
585
|
const point = ev.type === 'touchmove' ? (ev as TouchEvent).touches[0] : (ev as MouseEvent)
|
|
417
586
|
if (isHorizontal) {
|
|
@@ -426,6 +595,7 @@ function onEdgeDrag(e: MouseEvent | TouchEvent, edge: Edge) {
|
|
|
426
595
|
|
|
427
596
|
const onUp = () => {
|
|
428
597
|
isDragging.value = false
|
|
598
|
+
document.documentElement.style.cursor = ''
|
|
429
599
|
updateFullSize()
|
|
430
600
|
document.removeEventListener('mousemove', onMove)
|
|
431
601
|
document.removeEventListener('mouseup', onUp)
|
|
@@ -448,6 +618,7 @@ function updateFullSize() {
|
|
|
448
618
|
&& (iframeHeight.value === null || iframeHeight.value >= rect.height - gutter - 2)
|
|
449
619
|
}
|
|
450
620
|
|
|
621
|
+
|
|
451
622
|
function applyDeviceSize(device: Device | null | undefined) {
|
|
452
623
|
if (!device) {
|
|
453
624
|
iframeWidth.value = null
|
|
@@ -484,6 +655,7 @@ watch(viewMode, async (mode) => {
|
|
|
484
655
|
})
|
|
485
656
|
|
|
486
657
|
let observer: ResizeObserver | null = null
|
|
658
|
+
let containerObserver: ResizeObserver | null = null
|
|
487
659
|
|
|
488
660
|
function forwardIframeKeys(iframe: HTMLIFrameElement) {
|
|
489
661
|
try {
|
|
@@ -498,6 +670,7 @@ function forwardIframeKeys(iframe: HTMLIFrameElement) {
|
|
|
498
670
|
metaKey: e.metaKey,
|
|
499
671
|
shiftKey: e.shiftKey,
|
|
500
672
|
altKey: e.altKey,
|
|
673
|
+
bubbles: true,
|
|
501
674
|
}))
|
|
502
675
|
})
|
|
503
676
|
} catch {}
|
|
@@ -519,6 +692,21 @@ onMounted(() => {
|
|
|
519
692
|
observer.observe(wrapper)
|
|
520
693
|
}
|
|
521
694
|
|
|
695
|
+
const container = containerEl.value
|
|
696
|
+
if (container) {
|
|
697
|
+
const gutter = 40
|
|
698
|
+
const rect = container.getBoundingClientRect()
|
|
699
|
+
maxIframeWidth.value = Math.max(0, Math.round(rect.width - gutter))
|
|
700
|
+
maxIframeHeight.value = Math.max(0, Math.round(rect.height - gutter))
|
|
701
|
+
containerObserver = new ResizeObserver((entries) => {
|
|
702
|
+
for (const entry of entries) {
|
|
703
|
+
maxIframeWidth.value = Math.max(0, Math.round(entry.contentRect.width - gutter))
|
|
704
|
+
maxIframeHeight.value = Math.max(0, Math.round(entry.contentRect.height - gutter))
|
|
705
|
+
}
|
|
706
|
+
})
|
|
707
|
+
containerObserver.observe(container)
|
|
708
|
+
}
|
|
709
|
+
|
|
522
710
|
const el = iframeEl.value
|
|
523
711
|
if (el) {
|
|
524
712
|
el.addEventListener('load', () => forwardIframeKeys(el))
|
|
@@ -527,17 +715,20 @@ onMounted(() => {
|
|
|
527
715
|
|
|
528
716
|
onUnmounted(() => {
|
|
529
717
|
observer?.disconnect()
|
|
718
|
+
containerObserver?.disconnect()
|
|
530
719
|
})
|
|
531
720
|
|
|
532
721
|
const bottomPanelOpen = ref(false)
|
|
533
722
|
const tabsPanelHeight = ref(40)
|
|
534
723
|
const activeTab = ref<string | undefined>(undefined)
|
|
535
724
|
|
|
725
|
+
const defaultTab = () => compatibilityDisabled.value ? 'stats' : 'compatibility'
|
|
726
|
+
|
|
536
727
|
function toggleBottomPanel() {
|
|
537
728
|
bottomPanelOpen.value = !bottomPanelOpen.value
|
|
538
729
|
if (bottomPanelOpen.value) {
|
|
539
730
|
tabsPanelHeight.value = 300
|
|
540
|
-
if (!activeTab.value) activeTab.value =
|
|
731
|
+
if (!activeTab.value) activeTab.value = defaultTab()
|
|
541
732
|
} else {
|
|
542
733
|
tabsPanelHeight.value = 40
|
|
543
734
|
activeTab.value = undefined
|
|
@@ -560,35 +751,39 @@ function onTabClick(tab: string) {
|
|
|
560
751
|
|
|
561
752
|
const tabsDragging = ref(false)
|
|
562
753
|
|
|
563
|
-
function onTabsDragStart(e: MouseEvent) {
|
|
754
|
+
function onTabsDragStart(e: MouseEvent | TouchEvent) {
|
|
564
755
|
e.preventDefault()
|
|
565
756
|
tabsDragging.value = true
|
|
566
|
-
const
|
|
757
|
+
const isTouch = e.type === 'touchstart'
|
|
758
|
+
const startY = isTouch ? (e as TouchEvent).touches[0].clientY : (e as MouseEvent).clientY
|
|
567
759
|
const startHeight = tabsPanelHeight.value
|
|
568
760
|
|
|
569
761
|
const rootEl = containerEl.value?.closest('.relative.h-full') as HTMLElement | null
|
|
570
762
|
const maxHeight = rootEl ? rootEl.getBoundingClientRect().height : Infinity
|
|
571
763
|
|
|
572
|
-
const
|
|
573
|
-
const
|
|
764
|
+
const onMove = (e: MouseEvent | TouchEvent) => {
|
|
765
|
+
const clientY = e.type === 'touchmove' ? (e as TouchEvent).touches[0].clientY : (e as MouseEvent).clientY
|
|
766
|
+
const newHeight = Math.max(40, Math.min(maxHeight, startHeight + startY - clientY))
|
|
574
767
|
tabsPanelHeight.value = newHeight
|
|
575
768
|
bottomPanelOpen.value = newHeight > 40
|
|
576
769
|
|
|
577
770
|
if (!bottomPanelOpen.value) {
|
|
578
771
|
activeTab.value = undefined
|
|
579
772
|
} else if (!activeTab.value) {
|
|
580
|
-
activeTab.value =
|
|
773
|
+
activeTab.value = defaultTab()
|
|
581
774
|
}
|
|
582
775
|
}
|
|
583
776
|
|
|
584
|
-
const
|
|
777
|
+
const onEnd = () => {
|
|
585
778
|
tabsDragging.value = false
|
|
586
|
-
document.removeEventListener('mousemove',
|
|
587
|
-
document.removeEventListener('mouseup',
|
|
779
|
+
document.removeEventListener('mousemove', onMove)
|
|
780
|
+
document.removeEventListener('mouseup', onEnd)
|
|
781
|
+
document.removeEventListener('touchmove', onMove)
|
|
782
|
+
document.removeEventListener('touchend', onEnd)
|
|
588
783
|
}
|
|
589
784
|
|
|
590
|
-
document.addEventListener('mousemove',
|
|
591
|
-
document.addEventListener('mouseup',
|
|
785
|
+
document.addEventListener(isTouch ? 'touchmove' : 'mousemove', onMove)
|
|
786
|
+
document.addEventListener(isTouch ? 'touchend' : 'mouseup', onEnd)
|
|
592
787
|
}
|
|
593
788
|
|
|
594
789
|
const stripeBg = {
|
|
@@ -651,6 +846,7 @@ const stripeBg = {
|
|
|
651
846
|
</ScrollArea>
|
|
652
847
|
<ScrollArea v-show="sourceView === 'plaintext'" class="h-full [&_[data-slot=scroll-area-viewport]>div]:flex [&_[data-slot=scroll-area-viewport]>div]:flex-col [&_[data-slot=scroll-area-viewport]>div]:min-h-full">
|
|
653
848
|
<pre
|
|
849
|
+
ref="plaintextEl"
|
|
654
850
|
class="p-6 pt-14 text-sm leading-6 flex-1 text-gray-300 bg-[#27212e] dark:bg-gray-950 whitespace-pre-wrap break-words"
|
|
655
851
|
>{{ plaintextContent }}</pre>
|
|
656
852
|
</ScrollArea>
|
|
@@ -697,7 +893,7 @@ const stripeBg = {
|
|
|
697
893
|
<iframe
|
|
698
894
|
ref="iframeEl"
|
|
699
895
|
:srcdoc="srcdoc"
|
|
700
|
-
@load="
|
|
896
|
+
@load="onIframeLoad"
|
|
701
897
|
class="w-full border-0 bg-white dark:bg-gray-950"
|
|
702
898
|
:style="{ height: iframeContentHeight ? `${iframeContentHeight}px` : '100%' }"
|
|
703
899
|
/>
|
|
@@ -719,20 +915,18 @@ const stripeBg = {
|
|
|
719
915
|
<div
|
|
720
916
|
class="relative h-0 cursor-row-resize before:absolute before:top-0 before:left-0 before:right-0 before:h-3.25 before:content-['']"
|
|
721
917
|
@mousedown="onTabsDragStart"
|
|
918
|
+
@touchstart.prevent="onTabsDragStart"
|
|
722
919
|
/>
|
|
723
920
|
<Tabs :model-value="activeTab" class="flex flex-col min-h-0 h-full">
|
|
724
921
|
<div class="flex items-center justify-between min-h-10 pl-2 pr-3 shrink-0" :class="bottomPanelOpen ? 'border-b' : ''">
|
|
725
922
|
<TabsList class="h-full bg-transparent! rounded-none! p-0 gap-1">
|
|
726
|
-
<TabsTrigger value="compatibility" class="text-xs font-normal px-3 h-full rounded-none! border-0! shadow-none! border-b! border-transparent select-none data-[state=active]:border-gray-400 data-[state=active]:dark:border-gray-600 data-[state=active]:bg-transparent data-[state=inactive]:bg-transparent" @click="onTabClick('compatibility')">
|
|
727
|
-
|
|
728
|
-
</TabsTrigger>
|
|
729
|
-
<TabsTrigger value="lint" class="text-xs font-normal px-3 h-full rounded-none! border-0! shadow-none! border-b! border-transparent select-none data-[state=active]:border-gray-400 data-[state=active]:dark:border-gray-600 data-[state=active]:bg-transparent data-[state=inactive]:bg-transparent" @click="onTabClick('lint')">
|
|
730
|
-
Linter
|
|
923
|
+
<TabsTrigger v-if="!compatibilityDisabled" value="compatibility" class="text-xs font-normal px-3 h-full rounded-none! border-0! shadow-none! border-b! border-transparent select-none data-[state=active]:border-gray-400 data-[state=active]:dark:border-gray-600 data-[state=active]:bg-transparent data-[state=inactive]:bg-transparent dark:bg-transparent! dark:hover:bg-transparent!" @click="onTabClick('compatibility')">
|
|
924
|
+
Checks
|
|
731
925
|
</TabsTrigger>
|
|
732
|
-
<TabsTrigger value="stats" class="text-xs font-normal px-3 h-full rounded-none! border-0! shadow-none! border-b! border-transparent select-none data-[state=active]:border-gray-400 data-[state=active]:dark:border-gray-600 data-[state=active]:bg-transparent data-[state=inactive]:bg-transparent" @click="onTabClick('stats')">
|
|
926
|
+
<TabsTrigger value="stats" class="text-xs font-normal px-3 h-full rounded-none! border-0! shadow-none! border-b! border-transparent select-none data-[state=active]:border-gray-400 data-[state=active]:dark:border-gray-600 data-[state=active]:bg-transparent data-[state=inactive]:bg-transparent dark:bg-transparent! dark:hover:bg-transparent!" @click="onTabClick('stats')">
|
|
733
927
|
Stats
|
|
734
928
|
</TabsTrigger>
|
|
735
|
-
<TabsTrigger value="test" class="text-xs font-normal px-3 h-full rounded-none! border-0! shadow-none! border-b! border-transparent select-none data-[state=active]:border-gray-400 data-[state=active]:dark:border-gray-600 data-[state=active]:bg-transparent data-[state=inactive]:bg-transparent" @click="onTabClick('test')">
|
|
929
|
+
<TabsTrigger value="test" class="text-xs font-normal px-3 h-full rounded-none! border-0! shadow-none! border-b! border-transparent select-none data-[state=active]:border-gray-400 data-[state=active]:dark:border-gray-600 data-[state=active]:bg-transparent data-[state=inactive]:bg-transparent dark:bg-transparent! dark:hover:bg-transparent!" @click="onTabClick('test')">
|
|
736
930
|
Test
|
|
737
931
|
</TabsTrigger>
|
|
738
932
|
</TabsList>
|
|
@@ -746,7 +940,7 @@ const stripeBg = {
|
|
|
746
940
|
<button
|
|
747
941
|
v-for="cat in activeCompatibilityCategories"
|
|
748
942
|
:key="cat"
|
|
749
|
-
class="px-2 py-0.5 text-[11px] rounded-full cursor-
|
|
943
|
+
class="px-2 py-0.5 text-[11px] rounded-full cursor-default transition-colors"
|
|
750
944
|
:class="compatibilityCategory === cat
|
|
751
945
|
? 'bg-gray-900 text-white dark:bg-gray-600 dark:text-gray-100'
|
|
752
946
|
: 'text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-white/10'"
|
|
@@ -757,48 +951,45 @@ const stripeBg = {
|
|
|
757
951
|
</button>
|
|
758
952
|
</div>
|
|
759
953
|
<ScrollArea class="h-full flex-1 min-h-0 pl-5">
|
|
760
|
-
<p v-if="compatibilityLoading" class="pr-4 py-3 text-xs text-gray-500 dark:text-gray-400">
|
|
954
|
+
<p v-if="compatibilityLoading" class="pr-4 py-3 text-xs text-gray-500 dark:text-gray-400">Running checks...</p>
|
|
761
955
|
<p v-else-if="compatibilityError" class="pr-4 py-3 text-xs text-red-500 dark:text-red-400">{{ compatibilityError }}</p>
|
|
762
|
-
<p v-else-if="compatibilityIssues.length === 0" class="pr-4 py-3 text-xs text-gray-500 dark:text-gray-400">No
|
|
956
|
+
<p v-else-if="compatibilityIssues.length === 0" class="pr-4 py-3 text-xs text-gray-500 dark:text-gray-400">No issues found.</p>
|
|
763
957
|
<ul v-else class="text-xs divide-y">
|
|
764
958
|
<li
|
|
765
959
|
v-for="(issue, i) in filteredCompatibilityIssues"
|
|
766
960
|
:key="i"
|
|
767
|
-
class="pr-4 py-
|
|
768
|
-
>
|
|
769
|
-
<div class="flex items-center gap-2">
|
|
770
|
-
<a v-if="issue.url" :href="issue.url" target="_blank" rel="noopener" class="font-medium hover:underline shrink-0" :class="issue.type === 'error' ? 'text-red-600' : 'text-amber-600'">
|
|
771
|
-
{{ issue.title }}
|
|
772
|
-
</a>
|
|
773
|
-
<span v-else class="font-medium shrink-0" :class="issue.type === 'error' ? 'text-red-600' : 'text-amber-600'">
|
|
774
|
-
{{ issue.title }}
|
|
775
|
-
</span>
|
|
776
|
-
<span class="text-gray-400 dark:text-gray-600 shrink-0">·</span>
|
|
777
|
-
<span class="text-gray-500 dark:text-gray-400 truncate">{{ issue.type === 'error' ? 'Not supported' : 'Partial support' }} in {{ issue.clients.map((c: any) => c.name).join(', ') }}</span>
|
|
778
|
-
<button v-if="issue.line" class="text-gray-500 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 cursor-pointer tabular-nums shrink-0 ml-auto" @click="goToCompiledLine(issue.line!)">L{{ issue.line }}</button>
|
|
779
|
-
</div>
|
|
780
|
-
</li>
|
|
781
|
-
</ul>
|
|
782
|
-
</ScrollArea>
|
|
783
|
-
</TabsContent>
|
|
784
|
-
<TabsContent value="lint" class="mt-0 h-full">
|
|
785
|
-
<ScrollArea class="h-full pl-5">
|
|
786
|
-
<p v-if="lintLoading" class="pr-4 py-3 text-xs text-gray-500 dark:text-gray-400">Linting...</p>
|
|
787
|
-
<p v-else-if="lintIssues.length === 0" class="pr-4 py-3 text-xs text-gray-500 dark:text-gray-400">No issues found.</p>
|
|
788
|
-
<ul v-else class="text-xs divide-y">
|
|
789
|
-
<li
|
|
790
|
-
v-for="(issue, i) in lintIssues"
|
|
791
|
-
:key="i"
|
|
792
|
-
class="pr-4 py-2 hover:bg-gray-50 dark:hover:bg-white/5"
|
|
961
|
+
class="pr-4 py-2"
|
|
793
962
|
>
|
|
794
|
-
<div class="flex items-
|
|
963
|
+
<div class="flex items-center justify-between gap-4">
|
|
795
964
|
<div>
|
|
796
|
-
<
|
|
965
|
+
<a v-if="issue.url" :href="issue.url" target="_blank" rel="noopener" class="font-medium hover:underline" :class="issueColorClass(issue)">
|
|
966
|
+
{{ issue.title }}
|
|
967
|
+
</a>
|
|
968
|
+
<span v-else class="font-medium" :class="issueColorClass(issue)">
|
|
797
969
|
{{ issue.title }}
|
|
798
970
|
</span>
|
|
799
|
-
<div class="text-gray-500 dark:text-gray-400 mt-0.5">
|
|
971
|
+
<div class="text-gray-500 dark:text-gray-400 mt-0.5">
|
|
972
|
+
<template v-if="issue.kind === 'lint'">
|
|
973
|
+
<template v-for="(seg, j) in messageSegments(issue.message)" :key="j">
|
|
974
|
+
<code v-if="seg.code" class="px-1 py-0.5 rounded bg-gray-100 dark:bg-white/10 font-mono text-[11px]">{{ seg.text }}</code>
|
|
975
|
+
<template v-else>{{ seg.text }}</template>
|
|
976
|
+
</template>
|
|
977
|
+
</template>
|
|
978
|
+
<template v-else>
|
|
979
|
+
{{ supportPrefix(issue) }}
|
|
980
|
+
<template v-if="(issue.affectedClients?.length ?? 0) <= 4 || expandedIssueKeys.has(issueKey(issue, i))">
|
|
981
|
+
{{ (issue.affectedClients ?? []).join(', ') }}
|
|
982
|
+
</template>
|
|
983
|
+
<template v-else>
|
|
984
|
+
{{ issue.affectedClients!.slice(0, 4).join(', ') }}
|
|
985
|
+
<button class="underline cursor-pointer hover:text-gray-700 dark:hover:text-gray-200" @click="expandedIssueKeys.add(issueKey(issue, i)); expandedIssueKeys = new Set(expandedIssueKeys)">
|
|
986
|
+
+ {{ issue.affectedClients!.length - 4 }} others
|
|
987
|
+
</button>
|
|
988
|
+
</template>
|
|
989
|
+
</template>
|
|
990
|
+
</div>
|
|
800
991
|
</div>
|
|
801
|
-
<button v-if="issue.line" class="text-gray-500 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 cursor-pointer tabular-nums shrink-0" @click="
|
|
992
|
+
<button v-if="issue.line" class="text-gray-500 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 cursor-pointer tabular-nums shrink-0" @click="openInEditor(issue.file, issue.line!)">{{ isCurrentFile(issue) ? `L${issue.line}` : `${componentName(issue.file)}:${issue.line}` }}</button>
|
|
802
993
|
</div>
|
|
803
994
|
</li>
|
|
804
995
|
</ul>
|
|
@@ -808,35 +999,35 @@ const stripeBg = {
|
|
|
808
999
|
<ScrollArea class="h-full pl-5">
|
|
809
1000
|
<p v-if="statsLoading" class="pr-4 py-3 text-xs text-gray-500 dark:text-gray-400">Loading stats...</p>
|
|
810
1001
|
<p v-else-if="!stats" class="pr-4 py-3 text-xs text-gray-500 dark:text-gray-400">No stats available.</p>
|
|
811
|
-
<
|
|
812
|
-
<
|
|
813
|
-
<
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
</
|
|
825
|
-
<
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
</
|
|
839
|
-
</
|
|
1002
|
+
<ul v-else class="text-xs divide-y divide-gray-200 dark:divide-white/10">
|
|
1003
|
+
<li class="pr-4 py-2">
|
|
1004
|
+
<div class="flex items-center justify-between gap-4">
|
|
1005
|
+
<div>
|
|
1006
|
+
<span class="font-medium" :class="stats.size.bytes > 102400 ? 'text-red-600' : stats.size.bytes > 51200 ? 'text-amber-600' : 'text-gray-900 dark:text-gray-300'">Size</span>
|
|
1007
|
+
<div class="text-gray-500 dark:text-gray-400 mt-0.5">Compiled HTML size. Gmail clips emails larger than ~100KB.</div>
|
|
1008
|
+
</div>
|
|
1009
|
+
<span class="font-medium tabular-nums shrink-0" :class="stats.size.bytes > 102400 ? 'text-red-600' : stats.size.bytes > 51200 ? 'text-amber-600' : 'text-gray-900 dark:text-gray-300'">{{ stats.size.formatted }}</span>
|
|
1010
|
+
</div>
|
|
1011
|
+
</li>
|
|
1012
|
+
<li class="pr-4 py-2">
|
|
1013
|
+
<div class="flex items-center justify-between gap-4">
|
|
1014
|
+
<div>
|
|
1015
|
+
<span class="font-medium text-gray-900 dark:text-gray-300">Images</span>
|
|
1016
|
+
<div class="text-gray-500 dark:text-gray-400 mt-0.5">Total from <img> tags and CSS background images.</div>
|
|
1017
|
+
</div>
|
|
1018
|
+
<span class="font-medium tabular-nums shrink-0">{{ stats.images }}</span>
|
|
1019
|
+
</div>
|
|
1020
|
+
</li>
|
|
1021
|
+
<li class="pr-4 py-2">
|
|
1022
|
+
<div class="flex items-center justify-between gap-4">
|
|
1023
|
+
<div>
|
|
1024
|
+
<span class="font-medium text-gray-900 dark:text-gray-300">Links</span>
|
|
1025
|
+
<div class="text-gray-500 dark:text-gray-400 mt-0.5">Total <a> tags with an href attribute.</div>
|
|
1026
|
+
</div>
|
|
1027
|
+
<span class="font-medium tabular-nums shrink-0">{{ stats.links }}</span>
|
|
1028
|
+
</div>
|
|
1029
|
+
</li>
|
|
1030
|
+
</ul>
|
|
840
1031
|
</ScrollArea>
|
|
841
1032
|
</TabsContent>
|
|
842
1033
|
<TabsContent value="test" class="mt-0 h-full">
|
|
@@ -844,19 +1035,19 @@ const stripeBg = {
|
|
|
844
1035
|
<div class="pr-4 py-3 max-w-md">
|
|
845
1036
|
<div class="space-y-2">
|
|
846
1037
|
<div class="flex items-center gap-2">
|
|
847
|
-
<label class="text-xs text-gray-500 dark:text-gray-400 w-12 shrink-0">To</label>
|
|
1038
|
+
<label for="email-to" class="text-xs text-gray-500 dark:text-gray-400 w-12 shrink-0 cursor-pointer">To</label>
|
|
848
1039
|
<TagsInput v-model="emailTo" delimiter=" " add-on-paste add-on-blur class="flex-1 min-h-7 gap-1 px-2 py-1">
|
|
849
1040
|
<TagsInputItem v-for="item in emailTo" :key="item" :value="item" class="h-5 text-xs rounded">
|
|
850
1041
|
<TagsInputItemText class="px-1.5 py-0 text-xs" />
|
|
851
1042
|
<TagsInputItemDelete class="size-3.5" />
|
|
852
1043
|
</TagsInputItem>
|
|
853
|
-
<TagsInputInput class="text-xs min-h-5 px-0.5" placeholder="Add emails..." />
|
|
1044
|
+
<TagsInputInput id="email-to" class="text-xs min-h-5 px-0.5" placeholder="Add emails..." />
|
|
854
1045
|
</TagsInput>
|
|
855
1046
|
</div>
|
|
856
1047
|
<div class="flex items-center gap-2">
|
|
857
|
-
<label class="text-xs text-gray-500 dark:text-gray-400 w-12 shrink-0">Subject</label>
|
|
1048
|
+
<label for="email-subject" class="text-xs text-gray-500 dark:text-gray-400 w-12 shrink-0 cursor-pointer">Subject</label>
|
|
858
1049
|
<div class="flex-1 flex items-center gap-3">
|
|
859
|
-
<Input v-model="emailSubject" :placeholder="String(route.params.template)" class="flex-1 h-7 text-xs! px-2" />
|
|
1050
|
+
<Input id="email-subject" v-model="emailSubject" :placeholder="String(route.params.template)" class="flex-1 h-7 text-xs! px-2" />
|
|
860
1051
|
<label class="flex items-center gap-1.5 cursor-pointer select-none shrink-0">
|
|
861
1052
|
<Checkbox v-model="emailPreventThreading" :default-checked="true" class="size-3.5" />
|
|
862
1053
|
<span class="text-xs text-gray-500 dark:text-gray-400">Prevent threading</span>
|