@maizzle/framework 6.0.0-rc.22 → 6.0.0-rc.24

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.
Files changed (222) hide show
  1. package/dist/build.d.ts.map +1 -1
  2. package/dist/build.js +22 -2
  3. package/dist/build.js.map +1 -1
  4. package/dist/components/Heading.vue +1 -1
  5. package/dist/components/Img.vue +60 -10
  6. package/dist/components/Link.vue +1 -1
  7. package/dist/components/Markdown.vue +48 -16
  8. package/dist/components/Preheader.vue +4 -2
  9. package/dist/components/Tailwind.vue +4 -2
  10. package/dist/components/Text.vue +1 -1
  11. package/dist/components/Vml.vue +354 -0
  12. package/dist/components/utils.d.ts.map +1 -1
  13. package/dist/components/utils.js.map +1 -1
  14. package/dist/composables/defineConfig.js.map +1 -1
  15. package/dist/composables/renderContext.d.ts +1 -0
  16. package/dist/composables/renderContext.d.ts.map +1 -1
  17. package/dist/composables/renderContext.js +1 -1
  18. package/dist/composables/renderContext.js.map +1 -1
  19. package/dist/composables/useBaseUrl.d.ts.map +1 -1
  20. package/dist/composables/useBaseUrl.js.map +1 -1
  21. package/dist/composables/useConfig.d.ts +7 -0
  22. package/dist/composables/useConfig.d.ts.map +1 -1
  23. package/dist/composables/useConfig.js +8 -1
  24. package/dist/composables/useConfig.js.map +1 -1
  25. package/dist/composables/useCurrentTemplate.d.ts.map +1 -1
  26. package/dist/composables/useCurrentTemplate.js +10 -3
  27. package/dist/composables/useCurrentTemplate.js.map +1 -1
  28. package/dist/composables/useDoctype.d.ts.map +1 -1
  29. package/dist/composables/useDoctype.js.map +1 -1
  30. package/dist/composables/useEvent.js.map +1 -1
  31. package/dist/composables/useFont.d.ts.map +1 -1
  32. package/dist/composables/useFont.js.map +1 -1
  33. package/dist/composables/useOutlookFallback.d.ts.map +1 -1
  34. package/dist/composables/useOutlookFallback.js.map +1 -1
  35. package/dist/composables/useOutputPath.d.ts +17 -0
  36. package/dist/composables/useOutputPath.d.ts.map +1 -0
  37. package/dist/composables/useOutputPath.js +23 -0
  38. package/dist/composables/useOutputPath.js.map +1 -0
  39. package/dist/composables/usePlaintext.d.ts.map +1 -1
  40. package/dist/composables/usePlaintext.js.map +1 -1
  41. package/dist/composables/usePreheader.d.ts.map +1 -1
  42. package/dist/composables/usePreheader.js.map +1 -1
  43. package/dist/composables/useTransformers.d.ts.map +1 -1
  44. package/dist/composables/useTransformers.js.map +1 -1
  45. package/dist/composables/useUrlQuery.d.ts.map +1 -1
  46. package/dist/composables/useUrlQuery.js.map +1 -1
  47. package/dist/config/defaults.d.ts.map +1 -1
  48. package/dist/config/defaults.js.map +1 -1
  49. package/dist/config/index.js +12 -0
  50. package/dist/config/index.js.map +1 -1
  51. package/dist/events/index.d.ts +5 -0
  52. package/dist/events/index.d.ts.map +1 -1
  53. package/dist/events/index.js +5 -0
  54. package/dist/events/index.js.map +1 -1
  55. package/dist/index.d.ts +2 -1
  56. package/dist/index.js +2 -1
  57. package/dist/plaintext.d.ts.map +1 -1
  58. package/dist/plaintext.js.map +1 -1
  59. package/dist/plugin.js.map +1 -1
  60. package/dist/plugins/postcss/mergeMediaQueries.d.ts.map +1 -1
  61. package/dist/plugins/postcss/mergeMediaQueries.js.map +1 -1
  62. package/dist/plugins/postcss/pruneVars.d.ts.map +1 -1
  63. package/dist/plugins/postcss/pruneVars.js.map +1 -1
  64. package/dist/plugins/postcss/quoteFontFamilies.d.ts.map +1 -1
  65. package/dist/plugins/postcss/quoteFontFamilies.js.map +1 -1
  66. package/dist/plugins/postcss/removeDeclarations.d.ts.map +1 -1
  67. package/dist/plugins/postcss/removeDeclarations.js.map +1 -1
  68. package/dist/plugins/postcss/resolveMaizzleImports.d.ts.map +1 -1
  69. package/dist/plugins/postcss/resolveMaizzleImports.js.map +1 -1
  70. package/dist/plugins/postcss/resolveProps.d.ts.map +1 -1
  71. package/dist/plugins/postcss/resolveProps.js +14 -0
  72. package/dist/plugins/postcss/resolveProps.js.map +1 -1
  73. package/dist/plugins/postcss/tailwindCleanup.d.ts.map +1 -1
  74. package/dist/plugins/postcss/tailwindCleanup.js.map +1 -1
  75. package/dist/prepare.d.ts.map +1 -1
  76. package/dist/prepare.js.map +1 -1
  77. package/dist/render/active.d.ts.map +1 -1
  78. package/dist/render/active.js.map +1 -1
  79. package/dist/render/createRenderer.d.ts +1 -0
  80. package/dist/render/createRenderer.d.ts.map +1 -1
  81. package/dist/render/createRenderer.js +105 -1
  82. package/dist/render/createRenderer.js.map +1 -1
  83. package/dist/render/index.d.ts.map +1 -1
  84. package/dist/render/index.js +7 -1
  85. package/dist/render/index.js.map +1 -1
  86. package/dist/render/injectFonts.js.map +1 -1
  87. package/dist/render/plugins/codeBlockExtract.d.ts.map +1 -1
  88. package/dist/render/plugins/codeBlockExtract.js +4 -0
  89. package/dist/render/plugins/codeBlockExtract.js.map +1 -1
  90. package/dist/render/plugins/markdownExtract.d.ts.map +1 -1
  91. package/dist/render/plugins/markdownExtract.js.map +1 -1
  92. package/dist/render/plugins/rawExtract.d.ts.map +1 -1
  93. package/dist/render/plugins/rawExtract.js.map +1 -1
  94. package/dist/render/plugins/rowSourceLocation.d.ts.map +1 -1
  95. package/dist/render/plugins/rowSourceLocation.js.map +1 -1
  96. package/dist/serve.d.ts.map +1 -1
  97. package/dist/serve.js +51 -18
  98. package/dist/serve.js.map +1 -1
  99. package/dist/server/compatibility.d.ts.map +1 -1
  100. package/dist/server/compatibility.js +48 -0
  101. package/dist/server/compatibility.js.map +1 -1
  102. package/dist/server/email.js.map +1 -1
  103. package/dist/server/linter.js +6 -0
  104. package/dist/server/linter.js.map +1 -1
  105. package/dist/server/sfc-utils.d.ts.map +1 -1
  106. package/dist/server/sfc-utils.js.map +1 -1
  107. package/dist/server/ui/App.vue +16 -16
  108. package/dist/server/ui/components/SidebarClose.vue +1 -1
  109. package/dist/server/ui/components/ui/checkbox/Checkbox.vue +1 -1
  110. package/dist/server/ui/components/ui/command/CommandInput.vue +2 -2
  111. package/dist/server/ui/components/ui/dialog/DialogContent.vue +1 -1
  112. package/dist/server/ui/components/ui/dialog/DialogScrollContent.vue +1 -1
  113. package/dist/server/ui/components/ui/dropdown-menu/DropdownMenuCheckboxItem.vue +1 -1
  114. package/dist/server/ui/components/ui/dropdown-menu/DropdownMenuRadioItem.vue +1 -1
  115. package/dist/server/ui/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue +1 -1
  116. package/dist/server/ui/components/ui/sheet/SheetContent.vue +1 -1
  117. package/dist/server/ui/components/ui/sidebar/SidebarTrigger.vue +1 -1
  118. package/dist/server/ui/components/ui/tags-input/TagsInputItemDelete.vue +1 -1
  119. package/dist/server/ui/lib/emulated-dark-mode.ts +25 -10
  120. package/dist/server/ui/main.css +25 -0
  121. package/dist/server/ui/pages/Home.vue +1 -1
  122. package/dist/server/ui/pages/Preview.vue +37 -19
  123. package/dist/tests/render/_helpers.js.map +1 -1
  124. package/dist/transformers/addAttributes.d.ts.map +1 -1
  125. package/dist/transformers/addAttributes.js.map +1 -1
  126. package/dist/transformers/attributeToStyle.d.ts.map +1 -1
  127. package/dist/transformers/attributeToStyle.js.map +1 -1
  128. package/dist/transformers/base.d.ts.map +1 -1
  129. package/dist/transformers/base.js +4 -0
  130. package/dist/transformers/base.js.map +1 -1
  131. package/dist/transformers/columnWidth.d.ts.map +1 -1
  132. package/dist/transformers/columnWidth.js.map +1 -1
  133. package/dist/transformers/entities.d.ts.map +1 -1
  134. package/dist/transformers/entities.js.map +1 -1
  135. package/dist/transformers/filters/defaults.d.ts.map +1 -1
  136. package/dist/transformers/filters/defaults.js.map +1 -1
  137. package/dist/transformers/filters/index.d.ts.map +1 -1
  138. package/dist/transformers/filters/index.js.map +1 -1
  139. package/dist/transformers/format.d.ts.map +1 -1
  140. package/dist/transformers/format.js.map +1 -1
  141. package/dist/transformers/index.d.ts.map +1 -1
  142. package/dist/transformers/index.js +26 -0
  143. package/dist/transformers/index.js.map +1 -1
  144. package/dist/transformers/inlineCss.d.ts.map +1 -1
  145. package/dist/transformers/inlineCss.js +25 -2
  146. package/dist/transformers/inlineCss.js.map +1 -1
  147. package/dist/transformers/inlineLink.d.ts.map +1 -1
  148. package/dist/transformers/inlineLink.js.map +1 -1
  149. package/dist/transformers/minify.d.ts.map +1 -1
  150. package/dist/transformers/minify.js.map +1 -1
  151. package/dist/transformers/minifyCodeInline.d.ts.map +1 -1
  152. package/dist/transformers/minifyCodeInline.js.map +1 -1
  153. package/dist/transformers/msoPlaceholders.d.ts.map +1 -1
  154. package/dist/transformers/msoPlaceholders.js.map +1 -1
  155. package/dist/transformers/purgeCss.d.ts.map +1 -1
  156. package/dist/transformers/purgeCss.js +29 -3
  157. package/dist/transformers/purgeCss.js.map +1 -1
  158. package/dist/transformers/removeAttributes.d.ts.map +1 -1
  159. package/dist/transformers/removeAttributes.js.map +1 -1
  160. package/dist/transformers/replaceStrings.d.ts.map +1 -1
  161. package/dist/transformers/replaceStrings.js.map +1 -1
  162. package/dist/transformers/safeSelectors.d.ts.map +1 -1
  163. package/dist/transformers/safeSelectors.js +13 -1
  164. package/dist/transformers/safeSelectors.js.map +1 -1
  165. package/dist/transformers/shorthandCss.d.ts.map +1 -1
  166. package/dist/transformers/shorthandCss.js.map +1 -1
  167. package/dist/transformers/sixHex.d.ts.map +1 -1
  168. package/dist/transformers/sixHex.js.map +1 -1
  169. package/dist/transformers/tailwindComponent.js +9 -0
  170. package/dist/transformers/tailwindComponent.js.map +1 -1
  171. package/dist/transformers/tailwindcss.d.ts.map +1 -1
  172. package/dist/transformers/tailwindcss.js +22 -0
  173. package/dist/transformers/tailwindcss.js.map +1 -1
  174. package/dist/transformers/urlQuery.d.ts.map +1 -1
  175. package/dist/transformers/urlQuery.js.map +1 -1
  176. package/dist/types/config.d.ts +4 -8
  177. package/dist/types/config.d.ts.map +1 -1
  178. package/dist/types/index.d.ts +1 -1
  179. package/dist/utils/ast/parser.d.ts.map +1 -1
  180. package/dist/utils/ast/parser.js.map +1 -1
  181. package/dist/utils/ast/serializer.d.ts.map +1 -1
  182. package/dist/utils/ast/serializer.js.map +1 -1
  183. package/dist/utils/ast/walker.d.ts.map +1 -1
  184. package/dist/utils/ast/walker.js.map +1 -1
  185. package/dist/utils/compileTailwindCss.d.ts.map +1 -1
  186. package/dist/utils/compileTailwindCss.js.map +1 -1
  187. package/dist/utils/componentSources.d.ts.map +1 -1
  188. package/dist/utils/componentSources.js.map +1 -1
  189. package/dist/utils/cssBox.d.ts.map +1 -1
  190. package/dist/utils/cssBox.js.map +1 -1
  191. package/dist/utils/decodeStyleEntities.d.ts.map +1 -1
  192. package/dist/utils/decodeStyleEntities.js.map +1 -1
  193. package/dist/utils/detect.d.ts.map +1 -1
  194. package/dist/utils/detect.js.map +1 -1
  195. package/dist/utils/output-markers.d.ts.map +1 -1
  196. package/dist/utils/output-markers.js.map +1 -1
  197. package/dist/utils/url.d.ts.map +1 -1
  198. package/dist/utils/url.js.map +1 -1
  199. package/dist/utils/watchPaths.js.map +1 -1
  200. package/node_modules/@clack/core/CHANGELOG.md +6 -0
  201. package/node_modules/@clack/core/dist/index.d.mts +1 -1
  202. package/node_modules/@clack/core/dist/index.mjs +8 -8
  203. package/node_modules/@clack/core/dist/index.mjs.map +1 -1
  204. package/node_modules/@clack/core/package.json +1 -1
  205. package/node_modules/@clack/prompts/CHANGELOG.md +13 -0
  206. package/node_modules/@clack/prompts/README.md +2 -2
  207. package/node_modules/@clack/prompts/dist/index.d.mts +98 -0
  208. package/node_modules/@clack/prompts/dist/index.mjs +122 -121
  209. package/node_modules/@clack/prompts/dist/index.mjs.map +1 -1
  210. package/node_modules/@clack/prompts/package.json +2 -2
  211. package/node_modules/fast-wrap-ansi/lib/main.js +0 -1
  212. package/node_modules/fast-wrap-ansi/package.json +10 -10
  213. package/node_modules/maizzle/dist/commands/make/config.mjs +7 -6
  214. package/node_modules/maizzle/dist/commands/new.mjs +15 -84
  215. package/node_modules/maizzle/package.json +2 -2
  216. package/node_modules/tinyexec/README.md +8 -0
  217. package/node_modules/tinyexec/dist/main.d.mts +16 -1
  218. package/node_modules/tinyexec/dist/main.mjs +163 -457
  219. package/node_modules/tinyexec/package.json +12 -14
  220. package/package.json +3 -4
  221. package/node_modules/fast-wrap-ansi/lib/main.js.map +0 -1
  222. package/node_modules/tinyexec/dist/LICENSES.txt +0 -83
@@ -0,0 +1,23 @@
1
+ import { RenderContextKey } from "./renderContext.js";
2
+ import { inject } from "vue";
3
+ //#region src/composables/useOutputPath.ts
4
+ /**
5
+ * Override the output file path for the current template.
6
+ *
7
+ * The path is relative to the project root (cwd); it may be
8
+ * absolute or escape the output directory with `../`. If it
9
+ * has no extension, `output.extension` is appended.
10
+ *
11
+ * Usage in SFC <script setup>:
12
+ * ```ts
13
+ * useOutputPath('dist/promos/black-friday.html')
14
+ * ```
15
+ */
16
+ function useOutputPath(path) {
17
+ const ctx = inject(RenderContextKey);
18
+ if (ctx) ctx.outputPath = path;
19
+ }
20
+ //#endregion
21
+ export { useOutputPath };
22
+
23
+ //# sourceMappingURL=useOutputPath.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useOutputPath.js","names":[],"sources":["../../src/composables/useOutputPath.ts"],"sourcesContent":["import { inject } from 'vue'\nimport { RenderContextKey } from './renderContext.ts'\n\n/**\n * Override the output file path for the current template.\n *\n * The path is relative to the project root (cwd); it may be\n * absolute or escape the output directory with `../`. If it\n * has no extension, `output.extension` is appended.\n *\n * Usage in SFC <script setup>:\n * ```ts\n * useOutputPath('dist/promos/black-friday.html')\n * ```\n */\nexport function useOutputPath(path: string): void {\n const ctx = inject(RenderContextKey)\n if (ctx) ctx.outputPath = path\n}\n"],"mappings":";;;;;;;;;;;;;;;AAeA,SAAgB,cAAc,MAAoB;CAChD,MAAM,MAAM,OAAO,gBAAgB;CACnC,IAAI,KAAK,IAAI,aAAa;AAC5B"}
@@ -1 +1 @@
1
- {"version":3,"file":"usePlaintext.d.ts","names":[],"sources":["../../src/composables/usePlaintext.ts"],"mappings":";UAGiB,mBAAA;EACf,SAAA;EACA,WAAA;EACA,OAAA,GAAU,MAAA;AAAA;;;;;;;AAcZ;;;;;iBAAgB,YAAA,CAAa,OAAA,GAAU,mBAAA"}
1
+ {"version":3,"file":"usePlaintext.d.ts","names":[],"sources":["../../src/composables/usePlaintext.ts"],"mappings":";UAGiB,mBAAA;EACf,SAAA;EACA,WAAA;EACA,OAAA,GAAU,MAAM;AAAA;;;;;;AAAA;AAclB;;;;AAA0D;iBAA1C,YAAA,CAAa,OAA6B,GAAnB,mBAAmB"}
@@ -1 +1 @@
1
- {"version":3,"file":"usePlaintext.js","names":[],"sources":["../../src/composables/usePlaintext.ts"],"sourcesContent":["import { inject } from 'vue'\nimport { RenderContextKey } from './renderContext.ts'\n\nexport interface UsePlaintextOptions {\n extension?: string\n destination?: string\n options?: Record<string, unknown>\n}\n\n/**\n * Enable plaintext generation for the current email template.\n *\n * Usage in SFC <script setup>:\n * ```ts\n * usePlaintext()\n * usePlaintext({ extension: 'text' })\n * usePlaintext({ destination: '/custom/path' })\n * usePlaintext({ options: { ignoreTags: ['br'] } })\n * ```\n */\nexport function usePlaintext(options?: UsePlaintextOptions): void {\n const ctx = inject(RenderContextKey)\n if (ctx) ctx.plaintext = options ?? {}\n}\n"],"mappings":";;;;;;;;;;;;;;AAoBA,SAAgB,aAAa,SAAqC;CAChE,MAAM,MAAM,OAAO,iBAAiB;CACpC,IAAI,KAAK,IAAI,YAAY,WAAW,EAAE"}
1
+ {"version":3,"file":"usePlaintext.js","names":[],"sources":["../../src/composables/usePlaintext.ts"],"sourcesContent":["import { inject } from 'vue'\nimport { RenderContextKey } from './renderContext.ts'\n\nexport interface UsePlaintextOptions {\n extension?: string\n destination?: string\n options?: Record<string, unknown>\n}\n\n/**\n * Enable plaintext generation for the current email template.\n *\n * Usage in SFC <script setup>:\n * ```ts\n * usePlaintext()\n * usePlaintext({ extension: 'text' })\n * usePlaintext({ destination: '/custom/path' })\n * usePlaintext({ options: { ignoreTags: ['br'] } })\n * ```\n */\nexport function usePlaintext(options?: UsePlaintextOptions): void {\n const ctx = inject(RenderContextKey)\n if (ctx) ctx.plaintext = options ?? {}\n}\n"],"mappings":";;;;;;;;;;;;;;AAoBA,SAAgB,aAAa,SAAqC;CAChE,MAAM,MAAM,OAAO,gBAAgB;CACnC,IAAI,KAAK,IAAI,YAAY,WAAW,CAAC;AACvC"}
@@ -1 +1 @@
1
- {"version":3,"file":"usePreheader.d.ts","names":[],"sources":["../../src/composables/usePreheader.ts"],"mappings":";UAKiB,mBAAA;EAAA;;;;EAKf,MAAA;AAAA;;;;;;;;;;;;;;iBAgBc,YAAA,CAAa,IAAA,UAAc,OAAA,GAAU,mBAAA"}
1
+ {"version":3,"file":"usePreheader.d.ts","names":[],"sources":["../../src/composables/usePreheader.ts"],"mappings":";UAKiB,mBAAA;EAAA;;;;EAKf,MAAM;AAAA;;;;;;;;AAgBgE;;;;;;iBAAxD,YAAA,CAAa,IAAA,UAAc,OAAA,GAAU,mBAAmB"}
@@ -1 +1 @@
1
- {"version":3,"file":"usePreheader.js","names":[],"sources":["../../src/composables/usePreheader.ts"],"sourcesContent":["import { inject } from 'vue'\nimport { RenderContextKey } from './renderContext.ts'\n\nconst PREVIEW_LENGTH = 200\n\nexport interface UsePreheaderOptions {\n /**\n * Explicit number of filler sequences to render. When omitted, the count\n * is auto-derived to fill the 200-char inbox preview budget.\n */\n spaces?: number\n}\n\n/**\n * Set the preheader text for the current email template.\n *\n * Injects a hidden `<div>` at the start of `<body>` with the preheader text\n * followed by filler characters that prevent email clients from pulling\n * in body content after the preheader.\n *\n * Usage in SFC <script setup>:\n * ```ts\n * usePreheader('Thanks for signing up!')\n * usePreheader('Welcome!', { spaces: 50 })\n * ```\n */\nexport function usePreheader(text: string, options?: UsePreheaderOptions): void {\n const ctx = inject(RenderContextKey)\n if (ctx) {\n const fillerCount = options?.spaces !== undefined\n ? Math.max(0, options.spaces)\n : Math.max(0, PREVIEW_LENGTH - text.length)\n ctx.preheader = { text, fillerCount }\n }\n}\n"],"mappings":";;;AAGA,MAAM,iBAAiB;;;;;;;;;;;;;;AAuBvB,SAAgB,aAAa,MAAc,SAAqC;CAC9E,MAAM,MAAM,OAAO,iBAAiB;CACpC,IAAI,KAIF,IAAI,YAAY;EAAE;EAAM,aAHJ,SAAS,WAAW,KAAA,IACpC,KAAK,IAAI,GAAG,QAAQ,OAAO,GAC3B,KAAK,IAAI,GAAG,iBAAiB,KAAK,OAAO;EACR"}
1
+ {"version":3,"file":"usePreheader.js","names":[],"sources":["../../src/composables/usePreheader.ts"],"sourcesContent":["import { inject } from 'vue'\nimport { RenderContextKey } from './renderContext.ts'\n\nconst PREVIEW_LENGTH = 200\n\nexport interface UsePreheaderOptions {\n /**\n * Explicit number of filler sequences to render. When omitted, the count\n * is auto-derived to fill the 200-char inbox preview budget.\n */\n spaces?: number\n}\n\n/**\n * Set the preheader text for the current email template.\n *\n * Injects a hidden `<div>` at the start of `<body>` with the preheader text\n * followed by filler characters that prevent email clients from pulling\n * in body content after the preheader.\n *\n * Usage in SFC <script setup>:\n * ```ts\n * usePreheader('Thanks for signing up!')\n * usePreheader('Welcome!', { spaces: 50 })\n * ```\n */\nexport function usePreheader(text: string, options?: UsePreheaderOptions): void {\n const ctx = inject(RenderContextKey)\n if (ctx) {\n const fillerCount = options?.spaces !== undefined\n ? Math.max(0, options.spaces)\n : Math.max(0, PREVIEW_LENGTH - text.length)\n ctx.preheader = { text, fillerCount }\n }\n}\n"],"mappings":";;;AAGA,MAAM,iBAAiB;;;;;;;;;;;;;;AAuBvB,SAAgB,aAAa,MAAc,SAAqC;CAC9E,MAAM,MAAM,OAAO,gBAAgB;CACnC,IAAI,KAIF,IAAI,YAAY;EAAE;EAAM,aAHJ,SAAS,WAAW,KAAA,IACpC,KAAK,IAAI,GAAG,QAAQ,MAAM,IAC1B,KAAK,IAAI,GAAG,iBAAiB,KAAK,MAAM;CACR;AAExC"}
@@ -1 +1 @@
1
- {"version":3,"file":"useTransformers.d.ts","names":[],"sources":["../../src/composables/useTransformers.ts"],"mappings":";;;;;AAiCA;;;;;;;;;;;;;;;;;;;;;;;;;iBAAgB,eAAA,CAAgB,KAAA,aAAiB,kBAAA"}
1
+ {"version":3,"file":"useTransformers.d.ts","names":[],"sources":["../../src/composables/useTransformers.ts"],"mappings":";;;;;AAiCA;;;;AAA0E;;;;;;;;;;;;;;;;;;;;;iBAA1D,eAAA,CAAgB,KAA0C,aAAzB,kBAAyB"}
@@ -1 +1 @@
1
- {"version":3,"file":"useTransformers.js","names":[],"sources":["../../src/composables/useTransformers.ts"],"sourcesContent":["import { getCurrentInstance, inject, provide } from 'vue'\nimport { MaizzleConfigKey } from './useConfig.ts'\nimport { RenderContextKey } from './renderContext.ts'\nimport type { MaizzleConfig, TransformerToggles } from '../types/index.ts'\n\n/**\n * Toggle the transformer pipeline for the current template.\n *\n * - `useTransformers(false)` skips the entire pipeline (CSS inlining,\n * purging, shorthand, etc).\n * - `useTransformers(true)` (or no argument) keeps everything on.\n * - `useTransformers({ inlineCss: false, minify: false })` runs the\n * pipeline but skips the listed transformers.\n * - `useTransformers({ prettify: true, minify: true })` *enables*\n * transformers that would otherwise no-op (boolean-driven ones:\n * inlineCss, purgeCss, prettify, minify, shorthandCss, sixHex,\n * safeSelectors, entities). Same effect as setting their config\n * slice directly, scoped to one template.\n *\n * Data-driven transformers (filters, baseURL, urlQuery, addAttributes,\n * removeAttributes, replaceStrings, attributeToStyle) need actual\n * values in config — a bare `true` toggle for them is a no-op.\n *\n * Mirrors the `useTransformers` config flag, scoped to a single template\n * — no need to edit `maizzle.config.ts`.\n *\n * Usage in SFC <script setup>:\n * ```ts\n * useTransformers(false)\n * useTransformers({ inlineCss: false, minify: false })\n * useTransformers({ prettify: true })\n * ```\n */\nexport function useTransformers(value: boolean | TransformerToggles = true): void {\n if (!getCurrentInstance()) return\n\n const ctx = inject(RenderContextKey)\n if (!ctx) return\n\n const globalConfig = inject(MaizzleConfigKey, {} as MaizzleConfig)\n const merged: MaizzleConfig = {\n ...(ctx.sfcConfig ?? globalConfig),\n useTransformers: value,\n }\n\n ctx.sfcConfig = merged\n provide(MaizzleConfigKey, merged)\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiCA,SAAgB,gBAAgB,QAAsC,MAAY;CAChF,IAAI,CAAC,oBAAoB,EAAE;CAE3B,MAAM,MAAM,OAAO,iBAAiB;CACpC,IAAI,CAAC,KAAK;CAEV,MAAM,eAAe,OAAO,kBAAkB,EAAE,CAAkB;CAClE,MAAM,SAAwB;EAC5B,GAAI,IAAI,aAAa;EACrB,iBAAiB;EAClB;CAED,IAAI,YAAY;CAChB,QAAQ,kBAAkB,OAAO"}
1
+ {"version":3,"file":"useTransformers.js","names":[],"sources":["../../src/composables/useTransformers.ts"],"sourcesContent":["import { getCurrentInstance, inject, provide } from 'vue'\nimport { MaizzleConfigKey } from './useConfig.ts'\nimport { RenderContextKey } from './renderContext.ts'\nimport type { MaizzleConfig, TransformerToggles } from '../types/index.ts'\n\n/**\n * Toggle the transformer pipeline for the current template.\n *\n * - `useTransformers(false)` skips the entire pipeline (CSS inlining,\n * purging, shorthand, etc).\n * - `useTransformers(true)` (or no argument) keeps everything on.\n * - `useTransformers({ inlineCss: false, minify: false })` runs the\n * pipeline but skips the listed transformers.\n * - `useTransformers({ prettify: true, minify: true })` *enables*\n * transformers that would otherwise no-op (boolean-driven ones:\n * inlineCss, purgeCss, prettify, minify, shorthandCss, sixHex,\n * safeSelectors, entities). Same effect as setting their config\n * slice directly, scoped to one template.\n *\n * Data-driven transformers (filters, baseURL, urlQuery, addAttributes,\n * removeAttributes, replaceStrings, attributeToStyle) need actual\n * values in config — a bare `true` toggle for them is a no-op.\n *\n * Mirrors the `useTransformers` config flag, scoped to a single template\n * — no need to edit `maizzle.config.ts`.\n *\n * Usage in SFC <script setup>:\n * ```ts\n * useTransformers(false)\n * useTransformers({ inlineCss: false, minify: false })\n * useTransformers({ prettify: true })\n * ```\n */\nexport function useTransformers(value: boolean | TransformerToggles = true): void {\n if (!getCurrentInstance()) return\n\n const ctx = inject(RenderContextKey)\n if (!ctx) return\n\n const globalConfig = inject(MaizzleConfigKey, {} as MaizzleConfig)\n const merged: MaizzleConfig = {\n ...(ctx.sfcConfig ?? globalConfig),\n useTransformers: value,\n }\n\n ctx.sfcConfig = merged\n provide(MaizzleConfigKey, merged)\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiCA,SAAgB,gBAAgB,QAAsC,MAAY;CAChF,IAAI,CAAC,mBAAmB,GAAG;CAE3B,MAAM,MAAM,OAAO,gBAAgB;CACnC,IAAI,CAAC,KAAK;CAEV,MAAM,eAAe,OAAO,kBAAkB,CAAC,CAAkB;CACjE,MAAM,SAAwB;EAC5B,GAAI,IAAI,aAAa;EACrB,iBAAiB;CACnB;CAEA,IAAI,YAAY;CAChB,QAAQ,kBAAkB,MAAM;AAClC"}
@@ -1 +1 @@
1
- {"version":3,"file":"useUrlQuery.d.ts","names":[],"sources":["../../src/composables/useUrlQuery.ts"],"mappings":";;;;;AAkBA;;;;;;;;;;iBAAgB,WAAA,CAAY,KAAA,EAAO,QAAA"}
1
+ {"version":3,"file":"useUrlQuery.d.ts","names":[],"sources":["../../src/composables/useUrlQuery.ts"],"mappings":";;;;;AAkBA;;;;AAA2C;;;;;;iBAA3B,WAAA,CAAY,KAAe,EAAR,QAAQ"}
@@ -1 +1 @@
1
- {"version":3,"file":"useUrlQuery.js","names":["merge"],"sources":["../../src/composables/useUrlQuery.ts"],"sourcesContent":["import { inject } from 'vue'\nimport { defu as merge } from 'defu'\nimport { RenderContextKey } from './renderContext.ts'\nimport type { UrlQuery } from '../types/index.ts'\n\n/**\n * Append query parameters to URLs in the current email template — same\n * as `config.url.query`, scoped to one SFC. Common use: per-template\n * UTM parameters or campaign tracking.\n *\n * Usage in SFC <script setup>:\n * ```ts\n * useUrlQuery({ utm_source: 'maizzle', utm_campaign: 'newsletter' })\n * ```\n *\n * Pass `_options` alongside the params to tweak which tags/attributes\n * receive them (see `UrlQueryOptions`).\n */\nexport function useUrlQuery(value: UrlQuery): void {\n const ctx = inject(RenderContextKey)\n if (!ctx) return\n ctx.sfcConfig = merge({ url: { query: value } }, ctx.sfcConfig ?? {})\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAkBA,SAAgB,YAAY,OAAuB;CACjD,MAAM,MAAM,OAAO,iBAAiB;CACpC,IAAI,CAAC,KAAK;CACV,IAAI,YAAYA,OAAM,EAAE,KAAK,EAAE,OAAO,OAAO,EAAE,EAAE,IAAI,aAAa,EAAE,CAAC"}
1
+ {"version":3,"file":"useUrlQuery.js","names":["merge"],"sources":["../../src/composables/useUrlQuery.ts"],"sourcesContent":["import { inject } from 'vue'\nimport { defu as merge } from 'defu'\nimport { RenderContextKey } from './renderContext.ts'\nimport type { UrlQuery } from '../types/index.ts'\n\n/**\n * Append query parameters to URLs in the current email template — same\n * as `config.url.query`, scoped to one SFC. Common use: per-template\n * UTM parameters or campaign tracking.\n *\n * Usage in SFC <script setup>:\n * ```ts\n * useUrlQuery({ utm_source: 'maizzle', utm_campaign: 'newsletter' })\n * ```\n *\n * Pass `_options` alongside the params to tweak which tags/attributes\n * receive them (see `UrlQueryOptions`).\n */\nexport function useUrlQuery(value: UrlQuery): void {\n const ctx = inject(RenderContextKey)\n if (!ctx) return\n ctx.sfcConfig = merge({ url: { query: value } }, ctx.sfcConfig ?? {})\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAkBA,SAAgB,YAAY,OAAuB;CACjD,MAAM,MAAM,OAAO,gBAAgB;CACnC,IAAI,CAAC,KAAK;CACV,IAAI,YAAYA,OAAM,EAAE,KAAK,EAAE,OAAO,MAAM,EAAE,GAAG,IAAI,aAAa,CAAC,CAAC;AACtE"}
@@ -1 +1 @@
1
- {"version":3,"file":"defaults.d.ts","names":[],"sources":["../../src/config/defaults.ts"],"mappings":";;cAEa,QAAA,EAAU,aAAA"}
1
+ {"version":3,"file":"defaults.d.ts","names":[],"sources":["../../src/config/defaults.ts"],"mappings":";;cAEa,QAAA,EAAU,aA0BtB"}
@@ -1 +1 @@
1
- {"version":3,"file":"defaults.js","names":[],"sources":["../../src/config/defaults.ts"],"sourcesContent":["import type { MaizzleConfig } from '../types/index.ts'\n\nexport const defaults: MaizzleConfig = {\n content: ['emails/**/*.{vue,md}'],\n output: {\n path: 'dist',\n extension: 'html',\n },\n static: {\n source: ['public/**/*.*'],\n destination: 'public',\n },\n server: {\n port: 3000,\n watch: [],\n },\n css: {\n inline: true,\n purge: true,\n shorthand: true,\n safe: true,\n preferUnitless: true,\n },\n html: {\n decodeEntities: true,\n format: true,\n },\n useTransformers: true,\n}\n"],"mappings":";AAEA,MAAa,WAA0B;CACrC,SAAS,CAAC,uBAAuB;CACjC,QAAQ;EACN,MAAM;EACN,WAAW;EACZ;CACD,QAAQ;EACN,QAAQ,CAAC,gBAAgB;EACzB,aAAa;EACd;CACD,QAAQ;EACN,MAAM;EACN,OAAO,EAAE;EACV;CACD,KAAK;EACH,QAAQ;EACR,OAAO;EACP,WAAW;EACX,MAAM;EACN,gBAAgB;EACjB;CACD,MAAM;EACJ,gBAAgB;EAChB,QAAQ;EACT;CACD,iBAAiB;CAClB"}
1
+ {"version":3,"file":"defaults.js","names":[],"sources":["../../src/config/defaults.ts"],"sourcesContent":["import type { MaizzleConfig } from '../types/index.ts'\n\nexport const defaults: MaizzleConfig = {\n content: ['emails/**/*.{vue,md}'],\n output: {\n path: 'dist',\n extension: 'html',\n },\n static: {\n source: ['public/**/*.*'],\n destination: 'public',\n },\n server: {\n port: 3000,\n watch: [],\n },\n css: {\n inline: true,\n purge: true,\n shorthand: true,\n safe: true,\n preferUnitless: true,\n },\n html: {\n decodeEntities: true,\n format: true,\n },\n useTransformers: true,\n}\n"],"mappings":";AAEA,MAAa,WAA0B;CACrC,SAAS,CAAC,sBAAsB;CAChC,QAAQ;EACN,MAAM;EACN,WAAW;CACb;CACA,QAAQ;EACN,QAAQ,CAAC,eAAe;EACxB,aAAa;CACf;CACA,QAAQ;EACN,MAAM;EACN,OAAO,CAAC;CACV;CACA,KAAK;EACH,QAAQ;EACR,OAAO;EACP,WAAW;EACX,MAAM;EACN,gBAAgB;CAClB;CACA,MAAM;EACJ,gBAAgB;EAChB,QAAQ;CACV;CACA,iBAAiB;AACnB"}
@@ -34,6 +34,12 @@ async function resolveConfig(config, cwd = process.cwd()) {
34
34
  if (p.startsWith("/") || p.startsWith("!")) return p;
35
35
  return resolve(root, p).replace(/\\/g, "/");
36
36
  });
37
+ /**
38
+ * Resolve components.source paths relative to cwd (not root), since extra
39
+ * component dirs often live outside the root directory. String
40
+ * entries → resolve in-place. Object entries → resolve
41
+ * `path`, preserve `prefix`/`pathPrefix`.
42
+ */
37
43
  if (merged.components?.source) {
38
44
  const dirs = Array.isArray(merged.components.source) ? merged.components.source : [merged.components.source];
39
45
  merged.components.source = dirs.map((entry) => {
@@ -44,6 +50,12 @@ async function resolveConfig(config, cwd = process.cwd()) {
44
50
  };
45
51
  });
46
52
  }
53
+ /**
54
+ * Default css.base to root when root is explicitly set, so Tailwind resolves
55
+ * @source from the right directory. When root is not set, leave
56
+ * css.base undefined so Tailwind uses its own default (the
57
+ * template file's directory).
58
+ */
47
59
  if (hasExplicitRoot && !merged.css?.base) {
48
60
  if (!merged.css) merged.css = {};
49
61
  merged.css.base = root;
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/config/index.ts"],"sourcesContent":["import { existsSync } from 'node:fs'\nimport { resolve } from 'node:path'\nimport { createJiti } from 'jiti'\nimport { fileURLToPath } from 'node:url'\nimport { createDefu } from 'defu'\n\n// defu that replaces arrays: if user provides content: ['x'], it replaces the default, not appends\nconst merge = createDefu((obj, key, value) => {\n if (Array.isArray(obj[key])) {\n obj[key] = value\n return true\n }\n})\nimport { defaults } from './defaults.ts'\nimport type { MaizzleConfig } from '../types/index.ts'\n\nexport { defineConfig } from '../composables/defineConfig.ts'\nexport { defaults } from './defaults.ts'\n\nconst CONFIG_FILES = [\n 'maizzle.config.ts',\n 'maizzle.config.js',\n]\n\n/**\n * Resolve the Maizzle config.\n *\n * Always loads from the config file on disk (maizzle.config.{ts,js}),\n * then merges the programmatic config on top, then fills in defaults.\n */\nexport async function resolveConfig(\n config?: Partial<MaizzleConfig> | string,\n cwd: string = process.cwd(),\n): Promise<MaizzleConfig> {\n // If a string path was provided, load that specific file\n const fileConfig = await loadConfig(\n typeof config === 'string' ? config : undefined,\n cwd,\n )\n\n // Programmatic config (object) overrides file config, which overrides defaults\n const programmaticConfig = typeof config === 'object' && config !== null ? config : {}\n\n const merged = merge(programmaticConfig, fileConfig, defaults) as MaizzleConfig\n\n // Check if root was explicitly provided before resolving\n const hasExplicitRoot = !!(programmaticConfig.root ?? fileConfig.root)\n\n // Resolve root to an absolute path (defaults to cwd)\n const root = resolve(cwd, merged.root ?? '.')\n merged.root = root\n\n // Resolve content patterns relative to root\n if (merged.content) {\n merged.content = merged.content.map(p => {\n // Skip already-absolute or negated patterns\n if (p.startsWith('/') || p.startsWith('!')) return p\n return resolve(root, p).replace(/\\\\/g, '/')\n })\n }\n\n // Resolve static source patterns relative to root\n if (merged.static?.source) {\n merged.static.source = merged.static.source.map(p => {\n if (p.startsWith('/') || p.startsWith('!')) return p\n return resolve(root, p).replace(/\\\\/g, '/')\n })\n }\n\n // Resolve components.source paths relative to cwd (not root),\n // since extra component dirs often live outside the root directory.\n // String entries → resolve in-place. Object entries → resolve `path`,\n // preserve `prefix`/`pathPrefix`.\n if (merged.components?.source) {\n const dirs = Array.isArray(merged.components.source)\n ? merged.components.source\n : [merged.components.source]\n\n merged.components.source = dirs.map(entry => {\n if (typeof entry === 'string') {\n return entry.startsWith('/') ? entry : resolve(cwd, entry)\n }\n return {\n ...entry,\n path: entry.path.startsWith('/') ? entry.path : resolve(cwd, entry.path),\n }\n })\n }\n\n // Default css.base to root when root is explicitly set,\n // so Tailwind resolves @source from the right directory.\n // When root is not set, leave css.base undefined so Tailwind\n // uses its own default (the template file's directory).\n if (hasExplicitRoot && !merged.css?.base) {\n if (!merged.css) merged.css = {}\n merged.css.base = root\n }\n\n return merged\n}\n\nasync function loadConfig(\n configPath?: string,\n cwd: string = process.cwd(),\n): Promise<MaizzleConfig> {\n const jiti = createJiti(fileURLToPath(import.meta.url), { moduleCache: false })\n\n // If an explicit path was provided, use it directly\n if (configPath) {\n const absolutePath = resolve(cwd, configPath)\n\n if (!existsSync(absolutePath)) {\n throw new Error(`Config file not found: ${absolutePath}`)\n }\n\n const mod = await jiti.import(absolutePath) as any\n return mod.default ?? mod\n }\n\n // Otherwise scan cwd for known config file names\n for (const filename of CONFIG_FILES) {\n const filepath = resolve(cwd, filename)\n\n if (existsSync(filepath)) {\n const mod = await jiti.import(filepath) as any\n return mod.default ?? mod\n }\n }\n\n // No config file found, return empty (defaults will be applied by resolveConfig)\n return {}\n}\n"],"mappings":";;;;;;;;AAOA,MAAM,QAAQ,YAAY,KAAK,KAAK,UAAU;CAC5C,IAAI,MAAM,QAAQ,IAAI,KAAK,EAAE;EAC3B,IAAI,OAAO;EACX,OAAO;;EAET;AAOF,MAAM,eAAe,CACnB,qBACA,oBACD;;;;;;;AAQD,eAAsB,cACpB,QACA,MAAc,QAAQ,KAAK,EACH;CAExB,MAAM,aAAa,MAAM,WACvB,OAAO,WAAW,WAAW,SAAS,KAAA,GACtC,IACD;CAGD,MAAM,qBAAqB,OAAO,WAAW,YAAY,WAAW,OAAO,SAAS,EAAE;CAEtF,MAAM,SAAS,MAAM,oBAAoB,YAAY,SAAS;CAG9D,MAAM,kBAAkB,CAAC,EAAE,mBAAmB,QAAQ,WAAW;CAGjE,MAAM,OAAO,QAAQ,KAAK,OAAO,QAAQ,IAAI;CAC7C,OAAO,OAAO;CAGd,IAAI,OAAO,SACT,OAAO,UAAU,OAAO,QAAQ,KAAI,MAAK;EAEvC,IAAI,EAAE,WAAW,IAAI,IAAI,EAAE,WAAW,IAAI,EAAE,OAAO;EACnD,OAAO,QAAQ,MAAM,EAAE,CAAC,QAAQ,OAAO,IAAI;GAC3C;CAIJ,IAAI,OAAO,QAAQ,QACjB,OAAO,OAAO,SAAS,OAAO,OAAO,OAAO,KAAI,MAAK;EACnD,IAAI,EAAE,WAAW,IAAI,IAAI,EAAE,WAAW,IAAI,EAAE,OAAO;EACnD,OAAO,QAAQ,MAAM,EAAE,CAAC,QAAQ,OAAO,IAAI;GAC3C;CAOJ,IAAI,OAAO,YAAY,QAAQ;EAC7B,MAAM,OAAO,MAAM,QAAQ,OAAO,WAAW,OAAO,GAChD,OAAO,WAAW,SAClB,CAAC,OAAO,WAAW,OAAO;EAE9B,OAAO,WAAW,SAAS,KAAK,KAAI,UAAS;GAC3C,IAAI,OAAO,UAAU,UACnB,OAAO,MAAM,WAAW,IAAI,GAAG,QAAQ,QAAQ,KAAK,MAAM;GAE5D,OAAO;IACL,GAAG;IACH,MAAM,MAAM,KAAK,WAAW,IAAI,GAAG,MAAM,OAAO,QAAQ,KAAK,MAAM,KAAK;IACzE;IACD;;CAOJ,IAAI,mBAAmB,CAAC,OAAO,KAAK,MAAM;EACxC,IAAI,CAAC,OAAO,KAAK,OAAO,MAAM,EAAE;EAChC,OAAO,IAAI,OAAO;;CAGpB,OAAO;;AAGT,eAAe,WACb,YACA,MAAc,QAAQ,KAAK,EACH;CACxB,MAAM,OAAO,WAAW,cAAc,OAAO,KAAK,IAAI,EAAE,EAAE,aAAa,OAAO,CAAC;CAG/E,IAAI,YAAY;EACd,MAAM,eAAe,QAAQ,KAAK,WAAW;EAE7C,IAAI,CAAC,WAAW,aAAa,EAC3B,MAAM,IAAI,MAAM,0BAA0B,eAAe;EAG3D,MAAM,MAAM,MAAM,KAAK,OAAO,aAAa;EAC3C,OAAO,IAAI,WAAW;;CAIxB,KAAK,MAAM,YAAY,cAAc;EACnC,MAAM,WAAW,QAAQ,KAAK,SAAS;EAEvC,IAAI,WAAW,SAAS,EAAE;GACxB,MAAM,MAAM,MAAM,KAAK,OAAO,SAAS;GACvC,OAAO,IAAI,WAAW;;;CAK1B,OAAO,EAAE"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/config/index.ts"],"sourcesContent":["import { existsSync } from 'node:fs'\nimport { resolve } from 'node:path'\nimport { createJiti } from 'jiti'\nimport { fileURLToPath } from 'node:url'\nimport { createDefu } from 'defu'\n\n// defu that replaces arrays: if user provides content: ['x'], it replaces the default, not appends\nconst merge = createDefu((obj, key, value) => {\n if (Array.isArray(obj[key])) {\n obj[key] = value\n return true\n }\n})\nimport { defaults } from './defaults.ts'\nimport type { MaizzleConfig } from '../types/index.ts'\n\nexport { defineConfig } from '../composables/defineConfig.ts'\nexport { defaults } from './defaults.ts'\n\nconst CONFIG_FILES = [\n 'maizzle.config.ts',\n 'maizzle.config.js',\n]\n\n/**\n * Resolve the Maizzle config.\n *\n * Always loads from the config file on disk (maizzle.config.{ts,js}),\n * then merges the programmatic config on top, then fills in defaults.\n */\nexport async function resolveConfig(\n config?: Partial<MaizzleConfig> | string,\n cwd: string = process.cwd(),\n): Promise<MaizzleConfig> {\n // If a string path was provided, load that specific file\n const fileConfig = await loadConfig(\n typeof config === 'string' ? config : undefined,\n cwd,\n )\n\n // Programmatic config (object) overrides file config, which overrides defaults\n const programmaticConfig = typeof config === 'object' && config !== null ? config : {}\n\n const merged = merge(programmaticConfig, fileConfig, defaults) as MaizzleConfig\n\n // Check if root was explicitly provided before resolving\n const hasExplicitRoot = !!(programmaticConfig.root ?? fileConfig.root)\n\n // Resolve root to an absolute path (defaults to cwd)\n const root = resolve(cwd, merged.root ?? '.')\n merged.root = root\n\n // Resolve content patterns relative to root\n if (merged.content) {\n merged.content = merged.content.map(p => {\n // Skip already-absolute or negated patterns\n if (p.startsWith('/') || p.startsWith('!')) return p\n return resolve(root, p).replace(/\\\\/g, '/')\n })\n }\n\n // Resolve static source patterns relative to root\n if (merged.static?.source) {\n merged.static.source = merged.static.source.map(p => {\n if (p.startsWith('/') || p.startsWith('!')) return p\n return resolve(root, p).replace(/\\\\/g, '/')\n })\n }\n\n /**\n * Resolve components.source paths relative to cwd (not root), since extra\n * component dirs often live outside the root directory. String\n * entries → resolve in-place. Object entries → resolve\n * `path`, preserve `prefix`/`pathPrefix`.\n */\n if (merged.components?.source) {\n const dirs = Array.isArray(merged.components.source)\n ? merged.components.source\n : [merged.components.source]\n\n merged.components.source = dirs.map(entry => {\n if (typeof entry === 'string') {\n return entry.startsWith('/') ? entry : resolve(cwd, entry)\n }\n return {\n ...entry,\n path: entry.path.startsWith('/') ? entry.path : resolve(cwd, entry.path),\n }\n })\n }\n\n /**\n * Default css.base to root when root is explicitly set, so Tailwind resolves\n * @source from the right directory. When root is not set, leave\n * css.base undefined so Tailwind uses its own default (the\n * template file's directory).\n */\n if (hasExplicitRoot && !merged.css?.base) {\n if (!merged.css) merged.css = {}\n merged.css.base = root\n }\n\n return merged\n}\n\nasync function loadConfig(\n configPath?: string,\n cwd: string = process.cwd(),\n): Promise<MaizzleConfig> {\n const jiti = createJiti(fileURLToPath(import.meta.url), { moduleCache: false })\n\n // If an explicit path was provided, use it directly\n if (configPath) {\n const absolutePath = resolve(cwd, configPath)\n\n if (!existsSync(absolutePath)) {\n throw new Error(`Config file not found: ${absolutePath}`)\n }\n\n const mod = await jiti.import(absolutePath) as any\n return mod.default ?? mod\n }\n\n // Otherwise scan cwd for known config file names\n for (const filename of CONFIG_FILES) {\n const filepath = resolve(cwd, filename)\n\n if (existsSync(filepath)) {\n const mod = await jiti.import(filepath) as any\n return mod.default ?? mod\n }\n }\n\n // No config file found, return empty (defaults will be applied by resolveConfig)\n return {}\n}\n"],"mappings":";;;;;;;;AAOA,MAAM,QAAQ,YAAY,KAAK,KAAK,UAAU;CAC5C,IAAI,MAAM,QAAQ,IAAI,IAAI,GAAG;EAC3B,IAAI,OAAO;EACX,OAAO;CACT;AACF,CAAC;AAOD,MAAM,eAAe,CACnB,qBACA,mBACF;;;;;;;AAQA,eAAsB,cACpB,QACA,MAAc,QAAQ,IAAI,GACF;CAExB,MAAM,aAAa,MAAM,WACvB,OAAO,WAAW,WAAW,SAAS,KAAA,GACtC,GACF;CAGA,MAAM,qBAAqB,OAAO,WAAW,YAAY,WAAW,OAAO,SAAS,CAAC;CAErF,MAAM,SAAS,MAAM,oBAAoB,YAAY,QAAQ;CAG7D,MAAM,kBAAkB,CAAC,EAAE,mBAAmB,QAAQ,WAAW;CAGjE,MAAM,OAAO,QAAQ,KAAK,OAAO,QAAQ,GAAG;CAC5C,OAAO,OAAO;CAGd,IAAI,OAAO,SACT,OAAO,UAAU,OAAO,QAAQ,KAAI,MAAK;EAEvC,IAAI,EAAE,WAAW,GAAG,KAAK,EAAE,WAAW,GAAG,GAAG,OAAO;EACnD,OAAO,QAAQ,MAAM,CAAC,EAAE,QAAQ,OAAO,GAAG;CAC5C,CAAC;CAIH,IAAI,OAAO,QAAQ,QACjB,OAAO,OAAO,SAAS,OAAO,OAAO,OAAO,KAAI,MAAK;EACnD,IAAI,EAAE,WAAW,GAAG,KAAK,EAAE,WAAW,GAAG,GAAG,OAAO;EACnD,OAAO,QAAQ,MAAM,CAAC,EAAE,QAAQ,OAAO,GAAG;CAC5C,CAAC;;;;;;;CASH,IAAI,OAAO,YAAY,QAAQ;EAC7B,MAAM,OAAO,MAAM,QAAQ,OAAO,WAAW,MAAM,IAC/C,OAAO,WAAW,SAClB,CAAC,OAAO,WAAW,MAAM;EAE7B,OAAO,WAAW,SAAS,KAAK,KAAI,UAAS;GAC3C,IAAI,OAAO,UAAU,UACnB,OAAO,MAAM,WAAW,GAAG,IAAI,QAAQ,QAAQ,KAAK,KAAK;GAE3D,OAAO;IACL,GAAG;IACH,MAAM,MAAM,KAAK,WAAW,GAAG,IAAI,MAAM,OAAO,QAAQ,KAAK,MAAM,IAAI;GACzE;EACF,CAAC;CACH;;;;;;;CAQA,IAAI,mBAAmB,CAAC,OAAO,KAAK,MAAM;EACxC,IAAI,CAAC,OAAO,KAAK,OAAO,MAAM,CAAC;EAC/B,OAAO,IAAI,OAAO;CACpB;CAEA,OAAO;AACT;AAEA,eAAe,WACb,YACA,MAAc,QAAQ,IAAI,GACF;CACxB,MAAM,OAAO,WAAW,cAAc,OAAO,KAAK,GAAG,GAAG,EAAE,aAAa,MAAM,CAAC;CAG9E,IAAI,YAAY;EACd,MAAM,eAAe,QAAQ,KAAK,UAAU;EAE5C,IAAI,CAAC,WAAW,YAAY,GAC1B,MAAM,IAAI,MAAM,0BAA0B,cAAc;EAG1D,MAAM,MAAM,MAAM,KAAK,OAAO,YAAY;EAC1C,OAAO,IAAI,WAAW;CACxB;CAGA,KAAK,MAAM,YAAY,cAAc;EACnC,MAAM,WAAW,QAAQ,KAAK,QAAQ;EAEtC,IAAI,WAAW,QAAQ,GAAG;GACxB,MAAM,MAAM,MAAM,KAAK,OAAO,QAAQ;GACtC,OAAO,IAAI,WAAW;EACxB;CACF;CAGA,OAAO,CAAC;AACV"}
@@ -44,6 +44,11 @@ interface EventMap {
44
44
  */
45
45
  declare class EventManager {
46
46
  private handlers;
47
+ /**
48
+ * Snapshot of config-handler counts per event, captured at registerConfig().
49
+ * clearSfcHandlers() truncates each list back to this count, dropping
50
+ * any SFC-registered handlers that were appended after.
51
+ */
47
52
  private configHandlerCount;
48
53
  /**
49
54
  * Register handlers from the Maizzle config.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/events/index.ts"],"mappings":";;;;KAGY,SAAA;;;AAAZ;;;UAOiB,YAAA;EACf,MAAA;EACA,IAAA,EAAM,UAAA;AAAA;AAAA,UAGS,QAAA;EACf,YAAA,GAAe,MAAA;IAAU,MAAA,EAAQ,aAAA;EAAA,aAA2B,OAAA;EAC5D,YAAA,GAAe,MAAA;IAAU,MAAA,EAAQ,aAAA;IAAe,QAAA,EAAU,YAAA;EAAA,sBAAmC,OAAA;EAC7F,WAAA,GAAc,MAAA;IAAU,MAAA,EAAQ,aAAA;IAAe,QAAA,EAAU,YAAA;IAAc,IAAA;EAAA,sBAAmC,OAAA;EAC1G,cAAA,GAAiB,MAAA;IAAU,MAAA,EAAQ,aAAA;IAAe,QAAA,EAAU,YAAA;IAAc,IAAA;EAAA,sBAAmC,OAAA;EAC7G,UAAA,GAAa,MAAA;IAAU,KAAA;IAAiB,MAAA,EAAQ,aAAA;EAAA,aAA2B,OAAA;AAAA;;;;;;;;cAUhE,YAAA;EAAA,QACH,QAAA;EAAA,QAIA,kBAAA;EAlBwC;;;EAuBhD,cAAA,CAAe,MAAA,EAAQ,aAAA;EAtBvB;;;EAqCA,EAAA,WAAa,SAAA,CAAA,CAAW,IAAA,EAAM,CAAA,EAAG,OAAA,EAAS,QAAA,CAAS,CAAA;EArCM;;;EAgDnD,gBAAA,CAAiB,MAAA;IAAU,MAAA,EAAQ,aAAA;EAAA,IAAe,OAAA;EA/CrB;;;;EA2D7B,gBAAA,CAAiB,MAAA;IAAU,MAAA,EAAQ,aAAA;IAAe,QAAA,EAAU,YAAA;EAAA,IAAiB,OAAA;EA1D3C;;;EA2ElC,eAAA,CAAgB,MAAA;IAAU,MAAA,EAAQ,aAAA;IAAe,QAAA,EAAU,YAAA;IAAc,IAAA;EAAA,IAAiB,OAAA;EAjEzE;;;EAoFjB,kBAAA,CAAmB,MAAA;IAAU,MAAA,EAAQ,aAAA;IAAe,QAAA,EAAU,YAAA;IAAc,IAAA;EAAA,IAAiB,OAAA;EApC1D;;;EAuDnC,cAAA,CAAe,MAAA;IAAU,KAAA;IAAiB,MAAA,EAAQ,aAAA;EAAA,IAAe,OAAA;EAnBH;;;;;;;;EAmCpE,gBAAA,CAAiB,MAAA,GAAQ,SAAA;EA7GzB;;;EA2HA,KAAA,CAAA;AAAA"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/events/index.ts"],"mappings":";;;;KAGY,SAAA;;;AAAZ;;;UAOiB,YAAA;EACf,MAAA;EACA,IAAA,EAAM,UAAU;AAAA;AAAA,UAGD,QAAA;EACf,YAAA,GAAe,MAAA;IAAU,MAAA,EAAQ,aAAA;EAAA,aAA2B,OAAA;EAC5D,YAAA,GAAe,MAAA;IAAU,MAAA,EAAQ,aAAA;IAAe,QAAA,EAAU,YAAA;EAAA,sBAAmC,OAAA;EAC7F,WAAA,GAAc,MAAA;IAAU,MAAA,EAAQ,aAAA;IAAe,QAAA,EAAU,YAAA;IAAc,IAAA;EAAA,sBAAmC,OAAA;EAC1G,cAAA,GAAiB,MAAA;IAAU,MAAA,EAAQ,aAAA;IAAe,QAAA,EAAU,YAAA;IAAc,IAAA;EAAA,sBAAmC,OAAA;EAC7G,UAAA,GAAa,MAAA;IAAU,KAAA;IAAiB,MAAA,EAAQ,aAAA;EAAA,aAA2B,OAAA;AAAA;;;;;;;;cAUhE,YAAA;EAAA,QACH,QAAA;EAdyB;;;;;EAAA,QAoBzB,kBAAA;EAnBgB;;;EAwBxB,cAAA,CAAe,MAAA,EAAQ,aAAA;EAxBgD;;;EAuCvE,EAAA,WAAa,SAAA,CAAA,CAAW,IAAA,EAAM,CAAA,EAAG,OAAA,EAAS,QAAA,CAAS,CAAA;EAtCxB;;;EAiDrB,gBAAA,CAAiB,MAAA;IAAU,MAAA,EAAQ,aAAA;EAAA,IAAe,OAAA;EAjDqD;;;;EA6DvG,gBAAA,CAAiB,MAAA;IAAU,MAAA,EAAQ,aAAA;IAAe,QAAA,EAAU,YAAA;EAAA,IAAiB,OAAA;EA5DD;AAUpF;;EAmEQ,eAAA,CAAgB,MAAA;IAAU,MAAA,EAAQ,aAAA;IAAe,QAAA,EAAU,YAAA;IAAc,IAAA;EAAA,IAAiB,OAAA;EAxC7C;;;EA2D7C,kBAAA,CAAmB,MAAA;IAAU,MAAA,EAAQ,aAAA;IAAe,QAAA,EAAU,YAAA;IAAc,IAAA;EAAA,IAAiB,OAAA;EAnBH;;;EAsC1F,cAAA,CAAe,MAAA;IAAU,KAAA;IAAiB,MAAA,EAAQ,aAAA;EAAA,IAAe,OAAA;EAgBrC;;;;;;;;EAAlC,gBAAA,CAAiB,MAAA,GAAQ,SAAA;EA9FZ;;;EA4Gb,KAAA,CAAA;AAAA"}
@@ -8,6 +8,11 @@
8
8
  */
9
9
  var EventManager = class {
10
10
  handlers = /* @__PURE__ */ new Map();
11
+ /**
12
+ * Snapshot of config-handler counts per event, captured at registerConfig().
13
+ * clearSfcHandlers() truncates each list back to this count, dropping
14
+ * any SFC-registered handlers that were appended after.
15
+ */
11
16
  configHandlerCount = /* @__PURE__ */ new Map();
12
17
  /**
13
18
  * Register handlers from the Maizzle config.
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/events/index.ts"],"sourcesContent":["import type { ParsedPath } from 'node:path'\nimport type { MaizzleConfig } from '../types/index.ts'\n\nexport type EventName = 'beforeCreate' | 'beforeRender' | 'afterRender' | 'afterTransform' | 'afterBuild'\n\n/**\n * Info about the template currently being processed, passed to per-template\n * event handlers. `source` is the SFC file contents; `path` is the result of\n * `path.parse(absolutePath)` — `{ root, dir, base, ext, name }`.\n */\nexport interface TemplateInfo {\n source: string\n path: ParsedPath\n}\n\nexport interface EventMap {\n beforeCreate: (params: { config: MaizzleConfig }) => void | Promise<void>\n beforeRender: (params: { config: MaizzleConfig; template: TemplateInfo }) => string | void | Promise<string | void>\n afterRender: (params: { config: MaizzleConfig; template: TemplateInfo; html: string }) => string | void | Promise<string | void>\n afterTransform: (params: { config: MaizzleConfig; template: TemplateInfo; html: string }) => string | void | Promise<string | void>\n afterBuild: (params: { files: string[]; config: MaizzleConfig }) => void | Promise<void>\n}\n\n/**\n * Central event manager that collects handlers from config and useEvent() calls.\n *\n * Handlers are run in order: config handler first, then SFC handlers in registration order.\n * For events that return a value (beforeRender, afterRender, afterTransform),\n * the returned value replaces the corresponding input for the next handler.\n */\nexport class EventManager {\n private handlers = new Map<EventName, EventMap[EventName][]>()\n // Snapshot of config-handler counts per event, captured at registerConfig().\n // clearSfcHandlers() truncates each list back to this count, dropping any\n // SFC-registered handlers that were appended after.\n private configHandlerCount = new Map<EventName, number>()\n\n /**\n * Register handlers from the Maizzle config.\n */\n registerConfig(config: MaizzleConfig) {\n const eventNames: EventName[] = ['beforeCreate', 'beforeRender', 'afterRender', 'afterTransform', 'afterBuild']\n\n for (const name of eventNames) {\n const handler = config[name]\n if (typeof handler === 'function') {\n this.on(name, handler as EventMap[typeof name])\n }\n this.configHandlerCount.set(name, this.handlers.get(name)?.length ?? 0)\n }\n }\n\n /**\n * Register a handler for an event (used by useEvent composable).\n */\n on<K extends EventName>(name: K, handler: EventMap[K]) {\n if (!this.handlers.has(name)) {\n this.handlers.set(name, [])\n }\n\n this.handlers.get(name)!.push(handler)\n }\n\n /**\n * Fire beforeCreate — runs all handlers, config is mutated in place.\n */\n async fireBeforeCreate(params: { config: MaizzleConfig }) {\n const handlers = this.handlers.get('beforeCreate') ?? []\n\n for (const handler of handlers) {\n await (handler as EventMap['beforeCreate'])(params)\n }\n }\n\n /**\n * Fire beforeRender — if a handler returns a string, it replaces\n * `template.source` for subsequent handlers and the renderer.\n */\n async fireBeforeRender(params: { config: MaizzleConfig; template: TemplateInfo }): Promise<string> {\n const handlers = this.handlers.get('beforeRender') ?? []\n\n for (const handler of handlers) {\n const result = await (handler as EventMap['beforeRender'])(params)\n\n if (typeof result === 'string') {\n params.template.source = result\n }\n }\n\n return params.template.source\n }\n\n /**\n * Fire afterRender — if a handler returns a string, it replaces `html`.\n */\n async fireAfterRender(params: { config: MaizzleConfig; template: TemplateInfo; html: string }): Promise<string> {\n const handlers = this.handlers.get('afterRender') ?? []\n\n let { html } = params\n\n for (const handler of handlers) {\n const result = await (handler as EventMap['afterRender'])({ config: params.config, template: params.template, html })\n\n if (typeof result === 'string') {\n html = result\n }\n }\n\n return html\n }\n\n /**\n * Fire afterTransform — if a handler returns a string, it replaces `html`.\n */\n async fireAfterTransform(params: { config: MaizzleConfig; template: TemplateInfo; html: string }): Promise<string> {\n const handlers = this.handlers.get('afterTransform') ?? []\n\n let { html } = params\n\n for (const handler of handlers) {\n const result = await (handler as EventMap['afterTransform'])({ config: params.config, template: params.template, html })\n\n if (typeof result === 'string') {\n html = result\n }\n }\n\n return html\n }\n\n /**\n * Fire afterBuild — runs all handlers with the file list.\n */\n async fireAfterBuild(params: { files: string[]; config: MaizzleConfig }) {\n const handlers = this.handlers.get('afterBuild') ?? []\n\n for (const handler of handlers) {\n await (handler as EventMap['afterBuild'])(params)\n }\n }\n\n /**\n * Drop SFC-registered handlers, keep config-registered ones.\n *\n * Per default, only clears events whose scope is per-template\n * (`beforeRender`, `afterRender`, `afterTransform`). Build-scoped events\n * (`afterBuild`) accumulate across all templates and fire once at end of\n * build. Pass an explicit list to override.\n */\n clearSfcHandlers(events: EventName[] = ['beforeRender', 'afterRender', 'afterTransform']) {\n for (const name of events) {\n const handlers = this.handlers.get(name)\n if (!handlers) continue\n const keep = this.configHandlerCount.get(name) ?? 0\n if (handlers.length > keep) {\n this.handlers.set(name, handlers.slice(0, keep))\n }\n }\n }\n\n /**\n * Clear all handlers entirely.\n */\n clear() {\n this.handlers.clear()\n }\n}\n"],"mappings":";;;;;;;;AA8BA,IAAa,eAAb,MAA0B;CACxB,2BAAmB,IAAI,KAAuC;CAI9D,qCAA6B,IAAI,KAAwB;;;;CAKzD,eAAe,QAAuB;EAGpC,KAAK,MAAM,QAAQ;GAFc;GAAgB;GAAgB;GAAe;GAAkB;GAErE,EAAE;GAC7B,MAAM,UAAU,OAAO;GACvB,IAAI,OAAO,YAAY,YACrB,KAAK,GAAG,MAAM,QAAiC;GAEjD,KAAK,mBAAmB,IAAI,MAAM,KAAK,SAAS,IAAI,KAAK,EAAE,UAAU,EAAE;;;;;;CAO3E,GAAwB,MAAS,SAAsB;EACrD,IAAI,CAAC,KAAK,SAAS,IAAI,KAAK,EAC1B,KAAK,SAAS,IAAI,MAAM,EAAE,CAAC;EAG7B,KAAK,SAAS,IAAI,KAAK,CAAE,KAAK,QAAQ;;;;;CAMxC,MAAM,iBAAiB,QAAmC;EACxD,MAAM,WAAW,KAAK,SAAS,IAAI,eAAe,IAAI,EAAE;EAExD,KAAK,MAAM,WAAW,UACpB,MAAO,QAAqC,OAAO;;;;;;CAQvD,MAAM,iBAAiB,QAA4E;EACjG,MAAM,WAAW,KAAK,SAAS,IAAI,eAAe,IAAI,EAAE;EAExD,KAAK,MAAM,WAAW,UAAU;GAC9B,MAAM,SAAS,MAAO,QAAqC,OAAO;GAElE,IAAI,OAAO,WAAW,UACpB,OAAO,SAAS,SAAS;;EAI7B,OAAO,OAAO,SAAS;;;;;CAMzB,MAAM,gBAAgB,QAA0F;EAC9G,MAAM,WAAW,KAAK,SAAS,IAAI,cAAc,IAAI,EAAE;EAEvD,IAAI,EAAE,SAAS;EAEf,KAAK,MAAM,WAAW,UAAU;GAC9B,MAAM,SAAS,MAAO,QAAoC;IAAE,QAAQ,OAAO;IAAQ,UAAU,OAAO;IAAU;IAAM,CAAC;GAErH,IAAI,OAAO,WAAW,UACpB,OAAO;;EAIX,OAAO;;;;;CAMT,MAAM,mBAAmB,QAA0F;EACjH,MAAM,WAAW,KAAK,SAAS,IAAI,iBAAiB,IAAI,EAAE;EAE1D,IAAI,EAAE,SAAS;EAEf,KAAK,MAAM,WAAW,UAAU;GAC9B,MAAM,SAAS,MAAO,QAAuC;IAAE,QAAQ,OAAO;IAAQ,UAAU,OAAO;IAAU;IAAM,CAAC;GAExH,IAAI,OAAO,WAAW,UACpB,OAAO;;EAIX,OAAO;;;;;CAMT,MAAM,eAAe,QAAoD;EACvE,MAAM,WAAW,KAAK,SAAS,IAAI,aAAa,IAAI,EAAE;EAEtD,KAAK,MAAM,WAAW,UACpB,MAAO,QAAmC,OAAO;;;;;;;;;;CAYrD,iBAAiB,SAAsB;EAAC;EAAgB;EAAe;EAAiB,EAAE;EACxF,KAAK,MAAM,QAAQ,QAAQ;GACzB,MAAM,WAAW,KAAK,SAAS,IAAI,KAAK;GACxC,IAAI,CAAC,UAAU;GACf,MAAM,OAAO,KAAK,mBAAmB,IAAI,KAAK,IAAI;GAClD,IAAI,SAAS,SAAS,MACpB,KAAK,SAAS,IAAI,MAAM,SAAS,MAAM,GAAG,KAAK,CAAC;;;;;;CAQtD,QAAQ;EACN,KAAK,SAAS,OAAO"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/events/index.ts"],"sourcesContent":["import type { ParsedPath } from 'node:path'\nimport type { MaizzleConfig } from '../types/index.ts'\n\nexport type EventName = 'beforeCreate' | 'beforeRender' | 'afterRender' | 'afterTransform' | 'afterBuild'\n\n/**\n * Info about the template currently being processed, passed to per-template\n * event handlers. `source` is the SFC file contents; `path` is the result of\n * `path.parse(absolutePath)` — `{ root, dir, base, ext, name }`.\n */\nexport interface TemplateInfo {\n source: string\n path: ParsedPath\n}\n\nexport interface EventMap {\n beforeCreate: (params: { config: MaizzleConfig }) => void | Promise<void>\n beforeRender: (params: { config: MaizzleConfig; template: TemplateInfo }) => string | void | Promise<string | void>\n afterRender: (params: { config: MaizzleConfig; template: TemplateInfo; html: string }) => string | void | Promise<string | void>\n afterTransform: (params: { config: MaizzleConfig; template: TemplateInfo; html: string }) => string | void | Promise<string | void>\n afterBuild: (params: { files: string[]; config: MaizzleConfig }) => void | Promise<void>\n}\n\n/**\n * Central event manager that collects handlers from config and useEvent() calls.\n *\n * Handlers are run in order: config handler first, then SFC handlers in registration order.\n * For events that return a value (beforeRender, afterRender, afterTransform),\n * the returned value replaces the corresponding input for the next handler.\n */\nexport class EventManager {\n private handlers = new Map<EventName, EventMap[EventName][]>()\n /**\n * Snapshot of config-handler counts per event, captured at registerConfig().\n * clearSfcHandlers() truncates each list back to this count, dropping\n * any SFC-registered handlers that were appended after.\n */\n private configHandlerCount = new Map<EventName, number>()\n\n /**\n * Register handlers from the Maizzle config.\n */\n registerConfig(config: MaizzleConfig) {\n const eventNames: EventName[] = ['beforeCreate', 'beforeRender', 'afterRender', 'afterTransform', 'afterBuild']\n\n for (const name of eventNames) {\n const handler = config[name]\n if (typeof handler === 'function') {\n this.on(name, handler as EventMap[typeof name])\n }\n this.configHandlerCount.set(name, this.handlers.get(name)?.length ?? 0)\n }\n }\n\n /**\n * Register a handler for an event (used by useEvent composable).\n */\n on<K extends EventName>(name: K, handler: EventMap[K]) {\n if (!this.handlers.has(name)) {\n this.handlers.set(name, [])\n }\n\n this.handlers.get(name)!.push(handler)\n }\n\n /**\n * Fire beforeCreate — runs all handlers, config is mutated in place.\n */\n async fireBeforeCreate(params: { config: MaizzleConfig }) {\n const handlers = this.handlers.get('beforeCreate') ?? []\n\n for (const handler of handlers) {\n await (handler as EventMap['beforeCreate'])(params)\n }\n }\n\n /**\n * Fire beforeRender — if a handler returns a string, it replaces\n * `template.source` for subsequent handlers and the renderer.\n */\n async fireBeforeRender(params: { config: MaizzleConfig; template: TemplateInfo }): Promise<string> {\n const handlers = this.handlers.get('beforeRender') ?? []\n\n for (const handler of handlers) {\n const result = await (handler as EventMap['beforeRender'])(params)\n\n if (typeof result === 'string') {\n params.template.source = result\n }\n }\n\n return params.template.source\n }\n\n /**\n * Fire afterRender — if a handler returns a string, it replaces `html`.\n */\n async fireAfterRender(params: { config: MaizzleConfig; template: TemplateInfo; html: string }): Promise<string> {\n const handlers = this.handlers.get('afterRender') ?? []\n\n let { html } = params\n\n for (const handler of handlers) {\n const result = await (handler as EventMap['afterRender'])({ config: params.config, template: params.template, html })\n\n if (typeof result === 'string') {\n html = result\n }\n }\n\n return html\n }\n\n /**\n * Fire afterTransform — if a handler returns a string, it replaces `html`.\n */\n async fireAfterTransform(params: { config: MaizzleConfig; template: TemplateInfo; html: string }): Promise<string> {\n const handlers = this.handlers.get('afterTransform') ?? []\n\n let { html } = params\n\n for (const handler of handlers) {\n const result = await (handler as EventMap['afterTransform'])({ config: params.config, template: params.template, html })\n\n if (typeof result === 'string') {\n html = result\n }\n }\n\n return html\n }\n\n /**\n * Fire afterBuild — runs all handlers with the file list.\n */\n async fireAfterBuild(params: { files: string[]; config: MaizzleConfig }) {\n const handlers = this.handlers.get('afterBuild') ?? []\n\n for (const handler of handlers) {\n await (handler as EventMap['afterBuild'])(params)\n }\n }\n\n /**\n * Drop SFC-registered handlers, keep config-registered ones.\n *\n * Per default, only clears events whose scope is per-template\n * (`beforeRender`, `afterRender`, `afterTransform`). Build-scoped events\n * (`afterBuild`) accumulate across all templates and fire once at end of\n * build. Pass an explicit list to override.\n */\n clearSfcHandlers(events: EventName[] = ['beforeRender', 'afterRender', 'afterTransform']) {\n for (const name of events) {\n const handlers = this.handlers.get(name)\n if (!handlers) continue\n const keep = this.configHandlerCount.get(name) ?? 0\n if (handlers.length > keep) {\n this.handlers.set(name, handlers.slice(0, keep))\n }\n }\n }\n\n /**\n * Clear all handlers entirely.\n */\n clear() {\n this.handlers.clear()\n }\n}\n"],"mappings":";;;;;;;;AA8BA,IAAa,eAAb,MAA0B;CACxB,2BAAmB,IAAI,IAAsC;;;;;;CAM7D,qCAA6B,IAAI,IAAuB;;;;CAKxD,eAAe,QAAuB;EAGpC,KAAK,MAAM,QAAQ;GAFc;GAAgB;GAAgB;GAAe;GAAkB;EAEtE,GAAG;GAC7B,MAAM,UAAU,OAAO;GACvB,IAAI,OAAO,YAAY,YACrB,KAAK,GAAG,MAAM,OAAgC;GAEhD,KAAK,mBAAmB,IAAI,MAAM,KAAK,SAAS,IAAI,IAAI,GAAG,UAAU,CAAC;EACxE;CACF;;;;CAKA,GAAwB,MAAS,SAAsB;EACrD,IAAI,CAAC,KAAK,SAAS,IAAI,IAAI,GACzB,KAAK,SAAS,IAAI,MAAM,CAAC,CAAC;EAG5B,KAAK,SAAS,IAAI,IAAI,EAAG,KAAK,OAAO;CACvC;;;;CAKA,MAAM,iBAAiB,QAAmC;EACxD,MAAM,WAAW,KAAK,SAAS,IAAI,cAAc,KAAK,CAAC;EAEvD,KAAK,MAAM,WAAW,UACpB,MAAO,QAAqC,MAAM;CAEtD;;;;;CAMA,MAAM,iBAAiB,QAA4E;EACjG,MAAM,WAAW,KAAK,SAAS,IAAI,cAAc,KAAK,CAAC;EAEvD,KAAK,MAAM,WAAW,UAAU;GAC9B,MAAM,SAAS,MAAO,QAAqC,MAAM;GAEjE,IAAI,OAAO,WAAW,UACpB,OAAO,SAAS,SAAS;EAE7B;EAEA,OAAO,OAAO,SAAS;CACzB;;;;CAKA,MAAM,gBAAgB,QAA0F;EAC9G,MAAM,WAAW,KAAK,SAAS,IAAI,aAAa,KAAK,CAAC;EAEtD,IAAI,EAAE,SAAS;EAEf,KAAK,MAAM,WAAW,UAAU;GAC9B,MAAM,SAAS,MAAO,QAAoC;IAAE,QAAQ,OAAO;IAAQ,UAAU,OAAO;IAAU;GAAK,CAAC;GAEpH,IAAI,OAAO,WAAW,UACpB,OAAO;EAEX;EAEA,OAAO;CACT;;;;CAKA,MAAM,mBAAmB,QAA0F;EACjH,MAAM,WAAW,KAAK,SAAS,IAAI,gBAAgB,KAAK,CAAC;EAEzD,IAAI,EAAE,SAAS;EAEf,KAAK,MAAM,WAAW,UAAU;GAC9B,MAAM,SAAS,MAAO,QAAuC;IAAE,QAAQ,OAAO;IAAQ,UAAU,OAAO;IAAU;GAAK,CAAC;GAEvH,IAAI,OAAO,WAAW,UACpB,OAAO;EAEX;EAEA,OAAO;CACT;;;;CAKA,MAAM,eAAe,QAAoD;EACvE,MAAM,WAAW,KAAK,SAAS,IAAI,YAAY,KAAK,CAAC;EAErD,KAAK,MAAM,WAAW,UACpB,MAAO,QAAmC,MAAM;CAEpD;;;;;;;;;CAUA,iBAAiB,SAAsB;EAAC;EAAgB;EAAe;CAAgB,GAAG;EACxF,KAAK,MAAM,QAAQ,QAAQ;GACzB,MAAM,WAAW,KAAK,SAAS,IAAI,IAAI;GACvC,IAAI,CAAC,UAAU;GACf,MAAM,OAAO,KAAK,mBAAmB,IAAI,IAAI,KAAK;GAClD,IAAI,SAAS,SAAS,MACpB,KAAK,SAAS,IAAI,MAAM,SAAS,MAAM,GAAG,IAAI,CAAC;EAEnD;CACF;;;;CAKA,QAAQ;EACN,KAAK,SAAS,MAAM;CACtB;AACF"}
package/dist/index.d.ts CHANGED
@@ -9,6 +9,7 @@ import { useDoctype } from "./composables/useDoctype.js";
9
9
  import { useEvent } from "./composables/useEvent.js";
10
10
  import { useFont } from "./composables/useFont.js";
11
11
  import { useOutlookFallback } from "./composables/useOutlookFallback.js";
12
+ import { useOutputPath } from "./composables/useOutputPath.js";
12
13
  import { useTransformers } from "./composables/useTransformers.js";
13
14
  import { useUrlQuery } from "./composables/useUrlQuery.js";
14
15
  import { resolveConfig } from "./config/index.js";
@@ -36,4 +37,4 @@ import { replaceStrings } from "./transformers/replaceStrings.js";
36
37
  import { FormatOptions, format } from "./transformers/format.js";
37
38
  import { MinifyOptions, minify } from "./transformers/minify.js";
38
39
  import { useHead } from "@unhead/vue";
39
- export { type AttributesConfig, type BaseUrlOptions, type ComponentSource, type CreateRendererOptions, type CssConfig, type EntitiesConfig, type FilterFunction, type FiltersConfig, type FormatOptions, type HtmlConfig, type InlineCssOptions, type MaizzleConfig, type MinifyOptions, type NormalizedComponentSource, type PlaintextConfig, type PrepareOptions, type PurgeCssOptions, type RemoveAttributeOption, type RemoveAttributeRule, type RenderResult, type RenderedTemplate, type Renderer, type ShorthandCssOptions, type UrlConfig, type UrlQuery, type UrlQueryOptions, addAttributes, attributeToStyle, base, build, createPlaintext, createRenderer, defineConfig, entities, filters, format, inlineCss, inlineLink, maizzle, minify, normalizeComponentSources, prepare, purgeCss, removeAttributes, render, replaceStrings, resolveConfig, safeSelectors, serve, shorthandCss, sixHex, urlQuery, useBaseUrl, useConfig, useCurrentTemplate, useDoctype, useEvent, useFont, useHead, useOutlookFallback, usePlaintext, useTransformers, useUrlQuery };
40
+ export { type AttributesConfig, type BaseUrlOptions, type ComponentSource, type CreateRendererOptions, type CssConfig, type EntitiesConfig, type FilterFunction, type FiltersConfig, type FormatOptions, type HtmlConfig, type InlineCssOptions, type MaizzleConfig, type MinifyOptions, type NormalizedComponentSource, type PlaintextConfig, type PrepareOptions, type PurgeCssOptions, type RemoveAttributeOption, type RemoveAttributeRule, type RenderResult, type RenderedTemplate, type Renderer, type ShorthandCssOptions, type UrlConfig, type UrlQuery, type UrlQueryOptions, addAttributes, attributeToStyle, base, build, createPlaintext, createRenderer, defineConfig, entities, filters, format, inlineCss, inlineLink, maizzle, minify, normalizeComponentSources, prepare, purgeCss, removeAttributes, render, replaceStrings, resolveConfig, safeSelectors, serve, shorthandCss, sixHex, urlQuery, useBaseUrl, useConfig, useCurrentTemplate, useDoctype, useEvent, useFont, useHead, useOutlookFallback, useOutputPath, usePlaintext, useTransformers, useUrlQuery };
package/dist/index.js CHANGED
@@ -30,9 +30,10 @@ import { useDoctype } from "./composables/useDoctype.js";
30
30
  import { useEvent } from "./composables/useEvent.js";
31
31
  import { useFont } from "./composables/useFont.js";
32
32
  import { useOutlookFallback } from "./composables/useOutlookFallback.js";
33
+ import { useOutputPath } from "./composables/useOutputPath.js";
33
34
  import { usePlaintext } from "./composables/usePlaintext.js";
34
35
  import { useTransformers } from "./composables/useTransformers.js";
35
36
  import { useBaseUrl } from "./composables/useBaseUrl.js";
36
37
  import { useUrlQuery } from "./composables/useUrlQuery.js";
37
38
  import { useHead } from "@unhead/vue";
38
- export { addAttributes, attributeToStyle, base, build, createPlaintext, createRenderer, defineConfig, entities, filters, format, inlineCss, inlineLink, maizzle, minify, normalizeComponentSources, prepare, purgeCss, removeAttributes, render, replaceStrings, resolveConfig, safeSelectors, serve, shorthandCss, sixHex, urlQuery, useBaseUrl, useConfig, useCurrentTemplate, useDoctype, useEvent, useFont, useHead, useOutlookFallback, usePlaintext, useTransformers, useUrlQuery };
39
+ export { addAttributes, attributeToStyle, base, build, createPlaintext, createRenderer, defineConfig, entities, filters, format, inlineCss, inlineLink, maizzle, minify, normalizeComponentSources, prepare, purgeCss, removeAttributes, render, replaceStrings, resolveConfig, safeSelectors, serve, shorthandCss, sixHex, urlQuery, useBaseUrl, useConfig, useCurrentTemplate, useDoctype, useEvent, useFont, useHead, useOutlookFallback, useOutputPath, usePlaintext, useTransformers, useUrlQuery };
@@ -1 +1 @@
1
- {"version":3,"file":"plaintext.d.ts","names":[],"sources":["../src/plaintext.ts"],"mappings":";iBAUgB,eAAA,CAAgB,IAAA,UAAc,OAAA,GAAU,MAAA"}
1
+ {"version":3,"file":"plaintext.d.ts","names":[],"sources":["../src/plaintext.ts"],"mappings":";iBAUgB,eAAA,CAAgB,IAAA,UAAc,OAAA,GAAU,MAAM"}
@@ -1 +1 @@
1
- {"version":3,"file":"plaintext.js","names":[],"sources":["../src/plaintext.ts"],"sourcesContent":["import { stripHtml } from 'string-strip-html'\nimport defu from 'defu'\n\nconst defaults = {\n dumpLinkHrefsNearby: {\n enabled: true,\n putOnNewLine: true,\n },\n}\n\nexport function createPlaintext(html: string, options?: Record<string, unknown>): string {\n return stripHtml(html, defu(options, defaults)).result\n}\n"],"mappings":";;;AAGA,MAAM,WAAW,EACf,qBAAqB;CACnB,SAAS;CACT,cAAc;CACf,EACF;AAED,SAAgB,gBAAgB,MAAc,SAA2C;CACvF,OAAO,UAAU,MAAM,KAAK,SAAS,SAAS,CAAC,CAAC"}
1
+ {"version":3,"file":"plaintext.js","names":[],"sources":["../src/plaintext.ts"],"sourcesContent":["import { stripHtml } from 'string-strip-html'\nimport defu from 'defu'\n\nconst defaults = {\n dumpLinkHrefsNearby: {\n enabled: true,\n putOnNewLine: true,\n },\n}\n\nexport function createPlaintext(html: string, options?: Record<string, unknown>): string {\n return stripHtml(html, defu(options, defaults)).result\n}\n"],"mappings":";;;AAGA,MAAM,WAAW,EACf,qBAAqB;CACnB,SAAS;CACT,cAAc;AAChB,EACF;AAEA,SAAgB,gBAAgB,MAAc,SAA2C;CACvF,OAAO,UAAU,MAAM,KAAK,SAAS,QAAQ,CAAC,EAAE;AAClD"}
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.js","names":[],"sources":["../src/plugin.ts"],"sourcesContent":["import type { Plugin, ViteDevServer } from 'vite'\nimport type { MaizzleConfig } from './types/index.ts'\nimport { isLaravel } from './utils/detect.ts'\n\n/**\n * Maizzle Vite plugin for use inside an existing Vite project.\n *\n * - During `vite dev`: starts a separate Maizzle dev server on its own port\n * - During `vite build`: builds email templates alongside the host app\n *\n * Does NOT inject Vue, Tailwind, or any other plugins into the host's pipeline.\n * The host app manages its own stack. Maizzle runs in its own process.\n */\nexport function maizzle(configInput?: Partial<MaizzleConfig>): Plugin[] {\n let maizzleServer: ViteDevServer | null = null\n\n // Auto-configure defaults for Laravel projects\n if (isLaravel()) {\n const existing = configInput?.components?.source\n const laravelComponentDir = 'resources/js/components/email'\n\n if (!existing) {\n configInput = {\n ...configInput,\n components: {\n ...configInput?.components,\n source: [laravelComponentDir],\n },\n }\n }\n }\n\n return [{\n name: 'maizzle',\n\n async configureServer(hostServer) {\n // Close previous Maizzle server if the host restarts\n if (maizzleServer) {\n await maizzleServer.close()\n maizzleServer = null\n }\n\n const { serve } = await import('./serve.ts')\n maizzleServer = await serve({ config: configInput })\n\n // Clean up when the host server closes\n hostServer.httpServer?.on('close', () => {\n if (maizzleServer) {\n maizzleServer.close()\n maizzleServer = null\n }\n })\n },\n\n async closeBundle() {\n if (this.meta.watchMode) return\n\n const { build } = await import('./build.ts')\n await build(configInput)\n },\n\n async buildEnd() {\n if (maizzleServer) {\n await maizzleServer.close()\n maizzleServer = null\n }\n },\n }]\n}\n"],"mappings":";;;;;;;;;;;AAaA,SAAgB,QAAQ,aAAgD;CACtE,IAAI,gBAAsC;CAG1C,IAAI,WAAW,EAAE;EACf,MAAM,WAAW,aAAa,YAAY;EAC1C,MAAM,sBAAsB;EAE5B,IAAI,CAAC,UACH,cAAc;GACZ,GAAG;GACH,YAAY;IACV,GAAG,aAAa;IAChB,QAAQ,CAAC,oBAAoB;IAC9B;GACF;;CAIL,OAAO,CAAC;EACN,MAAM;EAEN,MAAM,gBAAgB,YAAY;GAEhC,IAAI,eAAe;IACjB,MAAM,cAAc,OAAO;IAC3B,gBAAgB;;GAGlB,MAAM,EAAE,UAAU,MAAM,OAAO;GAC/B,gBAAgB,MAAM,MAAM,EAAE,QAAQ,aAAa,CAAC;GAGpD,WAAW,YAAY,GAAG,eAAe;IACvC,IAAI,eAAe;KACjB,cAAc,OAAO;KACrB,gBAAgB;;KAElB;;EAGJ,MAAM,cAAc;GAClB,IAAI,KAAK,KAAK,WAAW;GAEzB,MAAM,EAAE,UAAU,MAAM,OAAO;GAC/B,MAAM,MAAM,YAAY;;EAG1B,MAAM,WAAW;GACf,IAAI,eAAe;IACjB,MAAM,cAAc,OAAO;IAC3B,gBAAgB;;;EAGrB,CAAC"}
1
+ {"version":3,"file":"plugin.js","names":[],"sources":["../src/plugin.ts"],"sourcesContent":["import type { Plugin, ViteDevServer } from 'vite'\nimport type { MaizzleConfig } from './types/index.ts'\nimport { isLaravel } from './utils/detect.ts'\n\n/**\n * Maizzle Vite plugin for use inside an existing Vite project.\n *\n * - During `vite dev`: starts a separate Maizzle dev server on its own port\n * - During `vite build`: builds email templates alongside the host app\n *\n * Does NOT inject Vue, Tailwind, or any other plugins into the host's pipeline.\n * The host app manages its own stack. Maizzle runs in its own process.\n */\nexport function maizzle(configInput?: Partial<MaizzleConfig>): Plugin[] {\n let maizzleServer: ViteDevServer | null = null\n\n // Auto-configure defaults for Laravel projects\n if (isLaravel()) {\n const existing = configInput?.components?.source\n const laravelComponentDir = 'resources/js/components/email'\n\n if (!existing) {\n configInput = {\n ...configInput,\n components: {\n ...configInput?.components,\n source: [laravelComponentDir],\n },\n }\n }\n }\n\n return [{\n name: 'maizzle',\n\n async configureServer(hostServer) {\n // Close previous Maizzle server if the host restarts\n if (maizzleServer) {\n await maizzleServer.close()\n maizzleServer = null\n }\n\n const { serve } = await import('./serve.ts')\n maizzleServer = await serve({ config: configInput })\n\n // Clean up when the host server closes\n hostServer.httpServer?.on('close', () => {\n if (maizzleServer) {\n maizzleServer.close()\n maizzleServer = null\n }\n })\n },\n\n async closeBundle() {\n if (this.meta.watchMode) return\n\n const { build } = await import('./build.ts')\n await build(configInput)\n },\n\n async buildEnd() {\n if (maizzleServer) {\n await maizzleServer.close()\n maizzleServer = null\n }\n },\n }]\n}\n"],"mappings":";;;;;;;;;;;AAaA,SAAgB,QAAQ,aAAgD;CACtE,IAAI,gBAAsC;CAG1C,IAAI,UAAU,GAAG;EACf,MAAM,WAAW,aAAa,YAAY;EAC1C,MAAM,sBAAsB;EAE5B,IAAI,CAAC,UACH,cAAc;GACZ,GAAG;GACH,YAAY;IACV,GAAG,aAAa;IAChB,QAAQ,CAAC,mBAAmB;GAC9B;EACF;CAEJ;CAEA,OAAO,CAAC;EACN,MAAM;EAEN,MAAM,gBAAgB,YAAY;GAEhC,IAAI,eAAe;IACjB,MAAM,cAAc,MAAM;IAC1B,gBAAgB;GAClB;GAEA,MAAM,EAAE,UAAU,MAAM,OAAO;GAC/B,gBAAgB,MAAM,MAAM,EAAE,QAAQ,YAAY,CAAC;GAGnD,WAAW,YAAY,GAAG,eAAe;IACvC,IAAI,eAAe;KACjB,cAAc,MAAM;KACpB,gBAAgB;IAClB;GACF,CAAC;EACH;EAEA,MAAM,cAAc;GAClB,IAAI,KAAK,KAAK,WAAW;GAEzB,MAAM,EAAE,UAAU,MAAM,OAAO;GAC/B,MAAM,MAAM,WAAW;EACzB;EAEA,MAAM,WAAW;GACf,IAAI,eAAe;IACjB,MAAM,cAAc,MAAM;IAC1B,gBAAgB;GAClB;EACF;CACF,CAAC;AACH"}
@@ -1 +1 @@
1
- {"version":3,"file":"mergeMediaQueries.d.ts","names":[],"sources":["../../../src/plugins/postcss/mergeMediaQueries.ts"],"mappings":";;;;;;AAcA;;;;;;;;iBAAgB,iBAAA,CAAkB,MAAA,EAAQ,aAAA,GAAgB,OAAA,CAAQ,MAAA"}
1
+ {"version":3,"file":"mergeMediaQueries.d.ts","names":[],"sources":["../../../src/plugins/postcss/mergeMediaQueries.ts"],"mappings":";;;;;;AAcA;;;;;;;;iBAAgB,iBAAA,CAAkB,MAAA,EAAQ,aAAA,GAAgB,OAAA,CAAQ,MAAM"}
@@ -1 +1 @@
1
- {"version":3,"file":"mergeMediaQueries.js","names":[],"sources":["../../../src/plugins/postcss/mergeMediaQueries.ts"],"sourcesContent":["import sortMediaQueries from 'postcss-sort-media-queries'\nimport type postcss from 'postcss'\nimport type { MaizzleConfig } from '../../types/config.ts'\n\n/**\n * Sorts and merges CSS media queries using postcss-sort-media-queries.\n *\n * Enabled by default. Opt out with css: { media: false }.\n *\n * Config examples:\n * css: { media: true } // merge, mobile-first sort (default)\n * css: { media: { sort: 'desktop-first' } } // merge, desktop-first sort\n * css: { media: false } // disabled\n */\nexport function mergeMediaQueries(config: MaizzleConfig): postcss.Plugin | null {\n const media = config.css?.media\n\n if (media === false) return null\n\n const options = typeof media === 'object' ? media : {}\n const sort = options.sort ?? 'mobile-first'\n\n return sortMediaQueries({ sort }) as postcss.Plugin\n}\n"],"mappings":";;;;;;;;;;;;AAcA,SAAgB,kBAAkB,QAA8C;CAC9E,MAAM,QAAQ,OAAO,KAAK;CAE1B,IAAI,UAAU,OAAO,OAAO;CAK5B,OAAO,iBAAiB,EAAE,OAHV,OAAO,UAAU,WAAW,QAAQ,EAAE,EACjC,QAAQ,gBAEG,CAAC"}
1
+ {"version":3,"file":"mergeMediaQueries.js","names":[],"sources":["../../../src/plugins/postcss/mergeMediaQueries.ts"],"sourcesContent":["import sortMediaQueries from 'postcss-sort-media-queries'\nimport type postcss from 'postcss'\nimport type { MaizzleConfig } from '../../types/config.ts'\n\n/**\n * Sorts and merges CSS media queries using postcss-sort-media-queries.\n *\n * Enabled by default. Opt out with css: { media: false }.\n *\n * Config examples:\n * css: { media: true } // merge, mobile-first sort (default)\n * css: { media: { sort: 'desktop-first' } } // merge, desktop-first sort\n * css: { media: false } // disabled\n */\nexport function mergeMediaQueries(config: MaizzleConfig): postcss.Plugin | null {\n const media = config.css?.media\n\n if (media === false) return null\n\n const options = typeof media === 'object' ? media : {}\n const sort = options.sort ?? 'mobile-first'\n\n return sortMediaQueries({ sort }) as postcss.Plugin\n}\n"],"mappings":";;;;;;;;;;;;AAcA,SAAgB,kBAAkB,QAA8C;CAC9E,MAAM,QAAQ,OAAO,KAAK;CAE1B,IAAI,UAAU,OAAO,OAAO;CAK5B,OAAO,iBAAiB,EAAE,OAHV,OAAO,UAAU,WAAW,QAAQ,CAAC,GAChC,QAAQ,eAEE,CAAC;AAClC"}
@@ -1 +1 @@
1
- {"version":3,"file":"pruneVars.d.ts","names":[],"sources":["../../../src/plugins/postcss/pruneVars.ts"],"mappings":";;;cAKyD,QAAA,QAYtC,MAAA;AAAA,cA2DN,OAAA"}
1
+ {"version":3,"file":"pruneVars.d.ts","names":[],"sources":["../../../src/plugins/postcss/pruneVars.ts"],"mappings":";;;cAKyD,QAAA,QAYtC,MAAM;AAAA,cA2DZ,OAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"pruneVars.js","names":[],"sources":["../../../src/plugins/postcss/pruneVars.ts"],"sourcesContent":["/**\n * postcss-prune-var\n * Removes unused CSS custom properties.\n */\n\nimport type { Declaration, Plugin, Root } from 'postcss';\n\nconst PLUGIN_NAME = 'postcss-prune-var';\n\nconst VAR_RE = /var\\(\\s*(--[^ ,);]+)/g;\n\ninterface VarRecord {\n uses: number;\n declarations: Set<Declaration>;\n dependencies: Set<string>;\n}\n\nexport default (): Plugin => {\n return {\n postcssPlugin: PLUGIN_NAME,\n\n Once(root: Root) {\n const records = new Map<string, VarRecord>();\n const usedVars = new Set<string>();\n\n const getRecord = (name: string): VarRecord => {\n let r = records.get(name);\n if (!r) {\n r = { uses: 0, declarations: new Set(), dependencies: new Set() };\n records.set(name, r);\n }\n return r;\n };\n\n const registerUse = (name: string, seen = new Set<string>()) => {\n const r = getRecord(name);\n r.uses++;\n seen.add(name);\n for (const dep of r.dependencies) {\n if (!seen.has(dep)) registerUse(dep, seen);\n }\n };\n\n // Build dependency graph\n root.walkDecls((decl) => {\n const isVar = decl.prop.startsWith('--');\n\n if (isVar) getRecord(decl.prop).declarations.add(decl);\n\n if (!decl.value.includes('var(')) return;\n\n let m;\n VAR_RE.lastIndex = 0;\n while ((m = VAR_RE.exec(decl.value))) {\n const ref = m[1].trim();\n if (isVar) {\n getRecord(decl.prop).dependencies.add(ref);\n } else {\n usedVars.add(ref);\n }\n }\n });\n\n // Propagate usage through the graph\n for (const v of usedVars) registerUse(v);\n\n // Remove declarations with zero uses\n for (const { uses, declarations } of records.values()) {\n if (uses === 0) {\n for (const decl of declarations) decl.remove();\n }\n }\n },\n };\n};\n\nexport const postcss = true;\n"],"mappings":";AAOA,MAAM,cAAc;AAEpB,MAAM,SAAS;AAQf,IAAA,0BAA6B;CAC3B,OAAO;EACL,eAAe;EAEf,KAAK,MAAY;GACf,MAAM,0BAAU,IAAI,KAAwB;GAC5C,MAAM,2BAAW,IAAI,KAAa;GAElC,MAAM,aAAa,SAA4B;IAC7C,IAAI,IAAI,QAAQ,IAAI,KAAK;IACzB,IAAI,CAAC,GAAG;KACN,IAAI;MAAE,MAAM;MAAG,8BAAc,IAAI,KAAK;MAAE,8BAAc,IAAI,KAAK;MAAE;KACjE,QAAQ,IAAI,MAAM,EAAE;;IAEtB,OAAO;;GAGT,MAAM,eAAe,MAAc,uBAAO,IAAI,KAAa,KAAK;IAC9D,MAAM,IAAI,UAAU,KAAK;IACzB,EAAE;IACF,KAAK,IAAI,KAAK;IACd,KAAK,MAAM,OAAO,EAAE,cAClB,IAAI,CAAC,KAAK,IAAI,IAAI,EAAE,YAAY,KAAK,KAAK;;GAK9C,KAAK,WAAW,SAAS;IACvB,MAAM,QAAQ,KAAK,KAAK,WAAW,KAAK;IAExC,IAAI,OAAO,UAAU,KAAK,KAAK,CAAC,aAAa,IAAI,KAAK;IAEtD,IAAI,CAAC,KAAK,MAAM,SAAS,OAAO,EAAE;IAElC,IAAI;IACJ,OAAO,YAAY;IACnB,OAAQ,IAAI,OAAO,KAAK,KAAK,MAAM,EAAG;KACpC,MAAM,MAAM,EAAE,GAAG,MAAM;KACvB,IAAI,OACF,UAAU,KAAK,KAAK,CAAC,aAAa,IAAI,IAAI;UAE1C,SAAS,IAAI,IAAI;;KAGrB;GAGF,KAAK,MAAM,KAAK,UAAU,YAAY,EAAE;GAGxC,KAAK,MAAM,EAAE,MAAM,kBAAkB,QAAQ,QAAQ,EACnD,IAAI,SAAS,GACX,KAAK,MAAM,QAAQ,cAAc,KAAK,QAAQ;;EAIrD;;AAGH,MAAa,UAAU"}
1
+ {"version":3,"file":"pruneVars.js","names":[],"sources":["../../../src/plugins/postcss/pruneVars.ts"],"sourcesContent":["/**\n * postcss-prune-var\n * Removes unused CSS custom properties.\n */\n\nimport type { Declaration, Plugin, Root } from 'postcss';\n\nconst PLUGIN_NAME = 'postcss-prune-var';\n\nconst VAR_RE = /var\\(\\s*(--[^ ,);]+)/g;\n\ninterface VarRecord {\n uses: number;\n declarations: Set<Declaration>;\n dependencies: Set<string>;\n}\n\nexport default (): Plugin => {\n return {\n postcssPlugin: PLUGIN_NAME,\n\n Once(root: Root) {\n const records = new Map<string, VarRecord>();\n const usedVars = new Set<string>();\n\n const getRecord = (name: string): VarRecord => {\n let r = records.get(name);\n if (!r) {\n r = { uses: 0, declarations: new Set(), dependencies: new Set() };\n records.set(name, r);\n }\n return r;\n };\n\n const registerUse = (name: string, seen = new Set<string>()) => {\n const r = getRecord(name);\n r.uses++;\n seen.add(name);\n for (const dep of r.dependencies) {\n if (!seen.has(dep)) registerUse(dep, seen);\n }\n };\n\n // Build dependency graph\n root.walkDecls((decl) => {\n const isVar = decl.prop.startsWith('--');\n\n if (isVar) getRecord(decl.prop).declarations.add(decl);\n\n if (!decl.value.includes('var(')) return;\n\n let m;\n VAR_RE.lastIndex = 0;\n while ((m = VAR_RE.exec(decl.value))) {\n const ref = m[1].trim();\n if (isVar) {\n getRecord(decl.prop).dependencies.add(ref);\n } else {\n usedVars.add(ref);\n }\n }\n });\n\n // Propagate usage through the graph\n for (const v of usedVars) registerUse(v);\n\n // Remove declarations with zero uses\n for (const { uses, declarations } of records.values()) {\n if (uses === 0) {\n for (const decl of declarations) decl.remove();\n }\n }\n },\n };\n};\n\nexport const postcss = true;\n"],"mappings":";AAOA,MAAM,cAAc;AAEpB,MAAM,SAAS;AAQf,IAAA,0BAA6B;CAC3B,OAAO;EACL,eAAe;EAEf,KAAK,MAAY;GACf,MAAM,0BAAU,IAAI,IAAuB;GAC3C,MAAM,2BAAW,IAAI,IAAY;GAEjC,MAAM,aAAa,SAA4B;IAC7C,IAAI,IAAI,QAAQ,IAAI,IAAI;IACxB,IAAI,CAAC,GAAG;KACN,IAAI;MAAE,MAAM;MAAG,8BAAc,IAAI,IAAI;MAAG,8BAAc,IAAI,IAAI;KAAE;KAChE,QAAQ,IAAI,MAAM,CAAC;IACrB;IACA,OAAO;GACT;GAEA,MAAM,eAAe,MAAc,uBAAO,IAAI,IAAY,MAAM;IAC9D,MAAM,IAAI,UAAU,IAAI;IACxB,EAAE;IACF,KAAK,IAAI,IAAI;IACb,KAAK,MAAM,OAAO,EAAE,cAClB,IAAI,CAAC,KAAK,IAAI,GAAG,GAAG,YAAY,KAAK,IAAI;GAE7C;GAGA,KAAK,WAAW,SAAS;IACvB,MAAM,QAAQ,KAAK,KAAK,WAAW,IAAI;IAEvC,IAAI,OAAO,UAAU,KAAK,IAAI,EAAE,aAAa,IAAI,IAAI;IAErD,IAAI,CAAC,KAAK,MAAM,SAAS,MAAM,GAAG;IAElC,IAAI;IACJ,OAAO,YAAY;IACnB,OAAQ,IAAI,OAAO,KAAK,KAAK,KAAK,GAAI;KACpC,MAAM,MAAM,EAAE,GAAG,KAAK;KACtB,IAAI,OACF,UAAU,KAAK,IAAI,EAAE,aAAa,IAAI,GAAG;UAEzC,SAAS,IAAI,GAAG;IAEpB;GACF,CAAC;GAGD,KAAK,MAAM,KAAK,UAAU,YAAY,CAAC;GAGvC,KAAK,MAAM,EAAE,MAAM,kBAAkB,QAAQ,OAAO,GAClD,IAAI,SAAS,GACX,KAAK,MAAM,QAAQ,cAAc,KAAK,OAAO;EAGnD;CACF;AACF;AAEA,MAAa,UAAU"}
@@ -1 +1 @@
1
- {"version":3,"file":"quoteFontFamilies.d.ts","names":[],"sources":["../../../src/plugins/postcss/quoteFontFamilies.ts"],"mappings":";;;;;AA+CA;;;iBAAgB,iBAAA,CAAA,GAAqB,MAAA;AAAA,cA6BxB,OAAA"}
1
+ {"version":3,"file":"quoteFontFamilies.d.ts","names":[],"sources":["../../../src/plugins/postcss/quoteFontFamilies.ts"],"mappings":";;;;;AA+CA;;;iBAAgB,iBAAA,CAAA,GAAqB,MAAM;AAAA,cA6B9B,OAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"quoteFontFamilies.js","names":[],"sources":["../../../src/plugins/postcss/quoteFontFamilies.ts"],"sourcesContent":["import type { Plugin } from 'postcss'\n\nconst GENERIC_KEYWORDS = new Set([\n 'serif', 'sans-serif', 'monospace', 'cursive', 'fantasy',\n 'system-ui', 'ui-serif', 'ui-sans-serif', 'ui-monospace', 'ui-rounded',\n 'emoji', 'math', 'fangsong',\n 'inherit', 'initial', 'unset', 'revert', 'revert-layer',\n])\n\n/**\n * Split a font-family value on top-level commas only, preserving quoted\n * strings and parenthesised groups like `var(...)`.\n */\nfunction splitFamilies(value: string): string[] {\n const parts: string[] = []\n let depth = 0\n let quote: string | null = null\n let start = 0\n\n for (let i = 0; i < value.length; i++) {\n const ch = value[i]\n if (quote) {\n if (ch === '\\\\') { i++; continue }\n if (ch === quote) quote = null\n continue\n }\n if (ch === '\"' || ch === \"'\") {\n quote = ch\n continue\n }\n if (ch === '(') depth++\n else if (ch === ')') depth--\n else if (ch === ',' && depth === 0) {\n parts.push(value.slice(start, i).trim())\n start = i + 1\n }\n }\n\n parts.push(value.slice(start).trim())\n return parts.filter(Boolean)\n}\n\n/**\n * Re-quote multi-word font-family identifiers that lightningcss \"optimised\"\n * by removing quotes. CSS allows space-separated identifiers as a family\n * name, but Google Fonts (and most style guides) prescribe quoted form.\n */\nexport function quoteFontFamilies(): Plugin {\n return {\n postcssPlugin: 'quote-font-families',\n Declaration: {\n 'font-family': (decl) => {\n const value = decl.value\n if (!value || !/\\s/.test(value)) return\n\n const families = splitFamilies(value)\n let changed = false\n\n const fixed = families.map((token) => {\n if (token.startsWith('\"') || token.startsWith(\"'\")) return token\n if (token.startsWith('var(')) return token\n if (!token.includes(' ')) return token\n if (GENERIC_KEYWORDS.has(token.toLowerCase())) return token\n\n changed = true\n return `\"${token}\"`\n })\n\n if (changed) {\n decl.value = fixed.join(', ')\n }\n },\n },\n }\n}\n\nexport const postcss = true\n"],"mappings":";AAEA,MAAM,mBAAmB,IAAI,IAAI;CAC/B;CAAS;CAAc;CAAa;CAAW;CAC/C;CAAa;CAAY;CAAiB;CAAgB;CAC1D;CAAS;CAAQ;CACjB;CAAW;CAAW;CAAS;CAAU;CAC1C,CAAC;;;;;AAMF,SAAS,cAAc,OAAyB;CAC9C,MAAM,QAAkB,EAAE;CAC1B,IAAI,QAAQ;CACZ,IAAI,QAAuB;CAC3B,IAAI,QAAQ;CAEZ,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;EACrC,MAAM,KAAK,MAAM;EACjB,IAAI,OAAO;GACT,IAAI,OAAO,MAAM;IAAE;IAAK;;GACxB,IAAI,OAAO,OAAO,QAAQ;GAC1B;;EAEF,IAAI,OAAO,QAAO,OAAO,KAAK;GAC5B,QAAQ;GACR;;EAEF,IAAI,OAAO,KAAK;OACX,IAAI,OAAO,KAAK;OAChB,IAAI,OAAO,OAAO,UAAU,GAAG;GAClC,MAAM,KAAK,MAAM,MAAM,OAAO,EAAE,CAAC,MAAM,CAAC;GACxC,QAAQ,IAAI;;;CAIhB,MAAM,KAAK,MAAM,MAAM,MAAM,CAAC,MAAM,CAAC;CACrC,OAAO,MAAM,OAAO,QAAQ;;;;;;;AAQ9B,SAAgB,oBAA4B;CAC1C,OAAO;EACL,eAAe;EACf,aAAa,EACX,gBAAgB,SAAS;GACvB,MAAM,QAAQ,KAAK;GACnB,IAAI,CAAC,SAAS,CAAC,KAAK,KAAK,MAAM,EAAE;GAEjC,MAAM,WAAW,cAAc,MAAM;GACrC,IAAI,UAAU;GAEd,MAAM,QAAQ,SAAS,KAAK,UAAU;IACpC,IAAI,MAAM,WAAW,KAAI,IAAI,MAAM,WAAW,IAAI,EAAE,OAAO;IAC3D,IAAI,MAAM,WAAW,OAAO,EAAE,OAAO;IACrC,IAAI,CAAC,MAAM,SAAS,IAAI,EAAE,OAAO;IACjC,IAAI,iBAAiB,IAAI,MAAM,aAAa,CAAC,EAAE,OAAO;IAEtD,UAAU;IACV,OAAO,IAAI,MAAM;KACjB;GAEF,IAAI,SACF,KAAK,QAAQ,MAAM,KAAK,KAAK;KAGlC;EACF;;AAGH,MAAa,UAAU"}
1
+ {"version":3,"file":"quoteFontFamilies.js","names":[],"sources":["../../../src/plugins/postcss/quoteFontFamilies.ts"],"sourcesContent":["import type { Plugin } from 'postcss'\n\nconst GENERIC_KEYWORDS = new Set([\n 'serif', 'sans-serif', 'monospace', 'cursive', 'fantasy',\n 'system-ui', 'ui-serif', 'ui-sans-serif', 'ui-monospace', 'ui-rounded',\n 'emoji', 'math', 'fangsong',\n 'inherit', 'initial', 'unset', 'revert', 'revert-layer',\n])\n\n/**\n * Split a font-family value on top-level commas only, preserving quoted\n * strings and parenthesised groups like `var(...)`.\n */\nfunction splitFamilies(value: string): string[] {\n const parts: string[] = []\n let depth = 0\n let quote: string | null = null\n let start = 0\n\n for (let i = 0; i < value.length; i++) {\n const ch = value[i]\n if (quote) {\n if (ch === '\\\\') { i++; continue }\n if (ch === quote) quote = null\n continue\n }\n if (ch === '\"' || ch === \"'\") {\n quote = ch\n continue\n }\n if (ch === '(') depth++\n else if (ch === ')') depth--\n else if (ch === ',' && depth === 0) {\n parts.push(value.slice(start, i).trim())\n start = i + 1\n }\n }\n\n parts.push(value.slice(start).trim())\n return parts.filter(Boolean)\n}\n\n/**\n * Re-quote multi-word font-family identifiers that lightningcss \"optimised\"\n * by removing quotes. CSS allows space-separated identifiers as a family\n * name, but Google Fonts (and most style guides) prescribe quoted form.\n */\nexport function quoteFontFamilies(): Plugin {\n return {\n postcssPlugin: 'quote-font-families',\n Declaration: {\n 'font-family': (decl) => {\n const value = decl.value\n if (!value || !/\\s/.test(value)) return\n\n const families = splitFamilies(value)\n let changed = false\n\n const fixed = families.map((token) => {\n if (token.startsWith('\"') || token.startsWith(\"'\")) return token\n if (token.startsWith('var(')) return token\n if (!token.includes(' ')) return token\n if (GENERIC_KEYWORDS.has(token.toLowerCase())) return token\n\n changed = true\n return `\"${token}\"`\n })\n\n if (changed) {\n decl.value = fixed.join(', ')\n }\n },\n },\n }\n}\n\nexport const postcss = true\n"],"mappings":";AAEA,MAAM,mBAAmB,IAAI,IAAI;CAC/B;CAAS;CAAc;CAAa;CAAW;CAC/C;CAAa;CAAY;CAAiB;CAAgB;CAC1D;CAAS;CAAQ;CACjB;CAAW;CAAW;CAAS;CAAU;AAC3C,CAAC;;;;;AAMD,SAAS,cAAc,OAAyB;CAC9C,MAAM,QAAkB,CAAC;CACzB,IAAI,QAAQ;CACZ,IAAI,QAAuB;CAC3B,IAAI,QAAQ;CAEZ,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;EACrC,MAAM,KAAK,MAAM;EACjB,IAAI,OAAO;GACT,IAAI,OAAO,MAAM;IAAE;IAAK;GAAS;GACjC,IAAI,OAAO,OAAO,QAAQ;GAC1B;EACF;EACA,IAAI,OAAO,QAAO,OAAO,KAAK;GAC5B,QAAQ;GACR;EACF;EACA,IAAI,OAAO,KAAK;OACX,IAAI,OAAO,KAAK;OAChB,IAAI,OAAO,OAAO,UAAU,GAAG;GAClC,MAAM,KAAK,MAAM,MAAM,OAAO,CAAC,EAAE,KAAK,CAAC;GACvC,QAAQ,IAAI;EACd;CACF;CAEA,MAAM,KAAK,MAAM,MAAM,KAAK,EAAE,KAAK,CAAC;CACpC,OAAO,MAAM,OAAO,OAAO;AAC7B;;;;;;AAOA,SAAgB,oBAA4B;CAC1C,OAAO;EACL,eAAe;EACf,aAAa,EACX,gBAAgB,SAAS;GACvB,MAAM,QAAQ,KAAK;GACnB,IAAI,CAAC,SAAS,CAAC,KAAK,KAAK,KAAK,GAAG;GAEjC,MAAM,WAAW,cAAc,KAAK;GACpC,IAAI,UAAU;GAEd,MAAM,QAAQ,SAAS,KAAK,UAAU;IACpC,IAAI,MAAM,WAAW,IAAG,KAAK,MAAM,WAAW,GAAG,GAAG,OAAO;IAC3D,IAAI,MAAM,WAAW,MAAM,GAAG,OAAO;IACrC,IAAI,CAAC,MAAM,SAAS,GAAG,GAAG,OAAO;IACjC,IAAI,iBAAiB,IAAI,MAAM,YAAY,CAAC,GAAG,OAAO;IAEtD,UAAU;IACV,OAAO,IAAI,MAAM;GACnB,CAAC;GAED,IAAI,SACF,KAAK,QAAQ,MAAM,KAAK,IAAI;EAEhC,EACF;CACF;AACF;AAEA,MAAa,UAAU"}
@@ -1 +1 @@
1
- {"version":3,"file":"removeDeclarations.d.ts","names":[],"sources":["../../../src/plugins/postcss/removeDeclarations.ts"],"mappings":";;;KA0BY,WAAA,6BAIR,MAAA;AAAA,UAEa,yBAAA;EACf,MAAA,EAAQ,MAAA,SAAe,WAAA;AAAA;AAAA,cACxB,QAAA,GAQe,OAAA,EAAS,yBAAA,KAA4B,MAAA;AAAA,cAyDxC,OAAA"}
1
+ {"version":3,"file":"removeDeclarations.d.ts","names":[],"sources":["../../../src/plugins/postcss/removeDeclarations.ts"],"mappings":";;;KA0BY,WAAA,6BAIR,MAAM;AAAA,UAEO,yBAAA;EACf,MAAA,EAAQ,MAAM,SAAS,WAAA;AAAA;AAAA,cACxB,QAAA,GAQe,OAAA,EAAS,yBAAA,KAA4B,MAAM;AAAA,cAyD9C,OAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"removeDeclarations.js","names":[],"sources":["../../../src/plugins/postcss/removeDeclarations.ts"],"sourcesContent":["/**\n * postcss-remove-declarations\n *\n * Removes CSS declarations (or whole rules) based on a selector map.\n *\n * The `remove` option maps a selector string to one of:\n *\n * - `\"*\"` — remove the entire rule\n * - `string` — remove the single named property\n * - `string[]` — remove every listed property\n * - `Record<string, string>` — remove a property only when its value matches.\n * Append `!important` to the value to restrict the match\n * to non-important declarations only.\n *\n * Example:\n * removeDeclarations({\n * remove: {\n * ':root': '*',\n * '.foo': ['color', 'margin'],\n * '.bar': { color: 'red' },\n * }\n * })\n */\n\nimport type { Plugin, Root } from 'postcss'\n\nexport type RemoveValue =\n | '*'\n | string\n | string[]\n | Record<string, string>\n\nexport interface RemoveDeclarationsOptions {\n remove: Record<string, RemoveValue>\n}\n\nconst IMPORTANT = '!important'\n\nfunction normalizeSelector(selector: string): string {\n return selector.replace(/(\\r\\n|\\n|\\r)/gm, '')\n}\n\nexport default (options: RemoveDeclarationsOptions): Plugin => {\n return {\n postcssPlugin: 'postcss-remove-declarations',\n\n Once(root: Root) {\n const remove = options.remove ?? {}\n\n root.walkRules((rule) => {\n let toRemove = remove[normalizeSelector(rule.selector)]\n\n if (!toRemove) return\n\n // Remove the entire rule\n if (toRemove === '*') {\n rule.remove()\n return\n }\n\n // Normalise a bare string into an array\n if (typeof toRemove === 'string') {\n toRemove = [toRemove]\n }\n\n if (Array.isArray(toRemove)) {\n const props = toRemove as string[]\n rule.walkDecls((decl) => {\n if (props.includes(decl.prop)) decl.remove()\n })\n } else if (typeof toRemove === 'object') {\n // Object: match both property and value\n const map = toRemove as Record<string, string>\n rule.walkDecls((decl) => {\n if (!(decl.prop in map)) return\n\n let expected = map[decl.prop]\n const requireNonImportant = expected.endsWith(IMPORTANT)\n\n if (requireNonImportant) {\n expected = expected.slice(0, -IMPORTANT.length).trim()\n }\n\n if (decl.value !== expected) return\n if (decl.important && requireNonImportant) return\n\n decl.remove()\n })\n }\n\n // Remove the rule if all declarations were removed\n if (rule.nodes?.length === 0) {\n rule.remove()\n }\n })\n },\n }\n}\n\nexport const postcss = true\n"],"mappings":";AAoCA,MAAM,YAAY;AAElB,SAAS,kBAAkB,UAA0B;CACnD,OAAO,SAAS,QAAQ,kBAAkB,GAAG;;AAG/C,IAAA,8BAAgB,YAA+C;CAC7D,OAAO;EACL,eAAe;EAEf,KAAK,MAAY;GACf,MAAM,SAAS,QAAQ,UAAU,EAAE;GAEnC,KAAK,WAAW,SAAS;IACvB,IAAI,WAAW,OAAO,kBAAkB,KAAK,SAAS;IAEtD,IAAI,CAAC,UAAU;IAGf,IAAI,aAAa,KAAK;KACpB,KAAK,QAAQ;KACb;;IAIF,IAAI,OAAO,aAAa,UACtB,WAAW,CAAC,SAAS;IAGvB,IAAI,MAAM,QAAQ,SAAS,EAAE;KAC3B,MAAM,QAAQ;KACd,KAAK,WAAW,SAAS;MACvB,IAAI,MAAM,SAAS,KAAK,KAAK,EAAE,KAAK,QAAQ;OAC5C;WACG,IAAI,OAAO,aAAa,UAAU;KAEvC,MAAM,MAAM;KACZ,KAAK,WAAW,SAAS;MACvB,IAAI,EAAE,KAAK,QAAQ,MAAM;MAEzB,IAAI,WAAW,IAAI,KAAK;MACxB,MAAM,sBAAsB,SAAS,SAAS,UAAU;MAExD,IAAI,qBACF,WAAW,SAAS,MAAM,GAAG,IAAkB,CAAC,MAAM;MAGxD,IAAI,KAAK,UAAU,UAAU;MAC7B,IAAI,KAAK,aAAa,qBAAqB;MAE3C,KAAK,QAAQ;OACb;;IAIJ,IAAI,KAAK,OAAO,WAAW,GACzB,KAAK,QAAQ;KAEf;;EAEL;;AAGH,MAAa,UAAU"}
1
+ {"version":3,"file":"removeDeclarations.js","names":[],"sources":["../../../src/plugins/postcss/removeDeclarations.ts"],"sourcesContent":["/**\n * postcss-remove-declarations\n *\n * Removes CSS declarations (or whole rules) based on a selector map.\n *\n * The `remove` option maps a selector string to one of:\n *\n * - `\"*\"` — remove the entire rule\n * - `string` — remove the single named property\n * - `string[]` — remove every listed property\n * - `Record<string, string>` — remove a property only when its value matches.\n * Append `!important` to the value to restrict the match\n * to non-important declarations only.\n *\n * Example:\n * removeDeclarations({\n * remove: {\n * ':root': '*',\n * '.foo': ['color', 'margin'],\n * '.bar': { color: 'red' },\n * }\n * })\n */\n\nimport type { Plugin, Root } from 'postcss'\n\nexport type RemoveValue =\n | '*'\n | string\n | string[]\n | Record<string, string>\n\nexport interface RemoveDeclarationsOptions {\n remove: Record<string, RemoveValue>\n}\n\nconst IMPORTANT = '!important'\n\nfunction normalizeSelector(selector: string): string {\n return selector.replace(/(\\r\\n|\\n|\\r)/gm, '')\n}\n\nexport default (options: RemoveDeclarationsOptions): Plugin => {\n return {\n postcssPlugin: 'postcss-remove-declarations',\n\n Once(root: Root) {\n const remove = options.remove ?? {}\n\n root.walkRules((rule) => {\n let toRemove = remove[normalizeSelector(rule.selector)]\n\n if (!toRemove) return\n\n // Remove the entire rule\n if (toRemove === '*') {\n rule.remove()\n return\n }\n\n // Normalise a bare string into an array\n if (typeof toRemove === 'string') {\n toRemove = [toRemove]\n }\n\n if (Array.isArray(toRemove)) {\n const props = toRemove as string[]\n rule.walkDecls((decl) => {\n if (props.includes(decl.prop)) decl.remove()\n })\n } else if (typeof toRemove === 'object') {\n // Object: match both property and value\n const map = toRemove as Record<string, string>\n rule.walkDecls((decl) => {\n if (!(decl.prop in map)) return\n\n let expected = map[decl.prop]\n const requireNonImportant = expected.endsWith(IMPORTANT)\n\n if (requireNonImportant) {\n expected = expected.slice(0, -IMPORTANT.length).trim()\n }\n\n if (decl.value !== expected) return\n if (decl.important && requireNonImportant) return\n\n decl.remove()\n })\n }\n\n // Remove the rule if all declarations were removed\n if (rule.nodes?.length === 0) {\n rule.remove()\n }\n })\n },\n }\n}\n\nexport const postcss = true\n"],"mappings":";AAoCA,MAAM,YAAY;AAElB,SAAS,kBAAkB,UAA0B;CACnD,OAAO,SAAS,QAAQ,kBAAkB,EAAE;AAC9C;AAEA,IAAA,8BAAgB,YAA+C;CAC7D,OAAO;EACL,eAAe;EAEf,KAAK,MAAY;GACf,MAAM,SAAS,QAAQ,UAAU,CAAC;GAElC,KAAK,WAAW,SAAS;IACvB,IAAI,WAAW,OAAO,kBAAkB,KAAK,QAAQ;IAErD,IAAI,CAAC,UAAU;IAGf,IAAI,aAAa,KAAK;KACpB,KAAK,OAAO;KACZ;IACF;IAGA,IAAI,OAAO,aAAa,UACtB,WAAW,CAAC,QAAQ;IAGtB,IAAI,MAAM,QAAQ,QAAQ,GAAG;KAC3B,MAAM,QAAQ;KACd,KAAK,WAAW,SAAS;MACvB,IAAI,MAAM,SAAS,KAAK,IAAI,GAAG,KAAK,OAAO;KAC7C,CAAC;IACH,OAAO,IAAI,OAAO,aAAa,UAAU;KAEvC,MAAM,MAAM;KACZ,KAAK,WAAW,SAAS;MACvB,IAAI,EAAE,KAAK,QAAQ,MAAM;MAEzB,IAAI,WAAW,IAAI,KAAK;MACxB,MAAM,sBAAsB,SAAS,SAAS,SAAS;MAEvD,IAAI,qBACF,WAAW,SAAS,MAAM,GAAG,GAAiB,EAAE,KAAK;MAGvD,IAAI,KAAK,UAAU,UAAU;MAC7B,IAAI,KAAK,aAAa,qBAAqB;MAE3C,KAAK,OAAO;KACd,CAAC;IACH;IAGA,IAAI,KAAK,OAAO,WAAW,GACzB,KAAK,OAAO;GAEhB,CAAC;EACH;CACF;AACF;AAEA,MAAa,UAAU"}
@@ -1 +1 @@
1
- {"version":3,"file":"resolveMaizzleImports.d.ts","names":[],"sources":["../../../src/plugins/postcss/resolveMaizzleImports.ts"],"mappings":";;;;;AAiBA;;;;;;;iBAAgB,qBAAA,CAAsB,QAAA,YAAmC,MAAA"}
1
+ {"version":3,"file":"resolveMaizzleImports.d.ts","names":[],"sources":["../../../src/plugins/postcss/resolveMaizzleImports.ts"],"mappings":";;;;;AAiBA;;;;AAA+E;;;iBAA/D,qBAAA,CAAsB,QAAA,YAAmC,MAAM"}
@@ -1 +1 @@
1
- {"version":3,"file":"resolveMaizzleImports.js","names":[],"sources":["../../../src/plugins/postcss/resolveMaizzleImports.ts"],"sourcesContent":["import { createRequire } from 'node:module'\nimport type { Plugin } from 'postcss'\n\nconst PKG = '@maizzle/tailwindcss'\nconst SUBPATH_RE = new RegExp(`^${PKG}(?:/|$)`)\n\nconst requireFromFramework = createRequire(import.meta.url)\n\n/**\n * Rewrite `@import \"@maizzle/tailwindcss\"` (and subpaths like\n * `@maizzle/tailwindcss/mso`) to absolute file paths so postcss/Tailwind\n * can resolve them regardless of where the user's template lives or how\n * their package manager hoists dependencies.\n *\n * Resolution order: prefer the user's project copy (so explicit installs\n * win), then fall back to the copy bundled with the framework.\n */\nexport function resolveMaizzleImports(userRoot: string = process.cwd()): Plugin {\n const requireFromUser = createRequire(`${userRoot}/_maizzle.js`)\n\n function resolve(spec: string): string | undefined {\n try { return requireFromUser.resolve(spec) } catch {}\n try { return requireFromFramework.resolve(spec) } catch {}\n return undefined\n }\n\n return {\n postcssPlugin: 'maizzle:resolve-tw-imports',\n AtRule: {\n import(rule) {\n const m = rule.params.match(/^\\s*[\"']([^\"']+)[\"']/)\n if (!m) return\n const spec = m[1]\n if (!SUBPATH_RE.test(spec)) return\n\n const abs = resolve(spec)\n if (abs) rule.params = rule.params.replace(m[0], `\"${abs}\"`)\n },\n },\n }\n}\n"],"mappings":";;AAIA,MAAM,aAAa,IAAI,OAAO,+BAAiB;AAE/C,MAAM,uBAAuB,cAAc,OAAO,KAAK,IAAI;;;;;;;;;;AAW3D,SAAgB,sBAAsB,WAAmB,QAAQ,KAAK,EAAU;CAC9E,MAAM,kBAAkB,cAAc,GAAG,SAAS,cAAc;CAEhE,SAAS,QAAQ,MAAkC;EACjD,IAAI;GAAE,OAAO,gBAAgB,QAAQ,KAAK;UAAS;EACnD,IAAI;GAAE,OAAO,qBAAqB,QAAQ,KAAK;UAAS;;CAI1D,OAAO;EACL,eAAe;EACf,QAAQ,EACN,OAAO,MAAM;GACX,MAAM,IAAI,KAAK,OAAO,MAAM,uBAAuB;GACnD,IAAI,CAAC,GAAG;GACR,MAAM,OAAO,EAAE;GACf,IAAI,CAAC,WAAW,KAAK,KAAK,EAAE;GAE5B,MAAM,MAAM,QAAQ,KAAK;GACzB,IAAI,KAAK,KAAK,SAAS,KAAK,OAAO,QAAQ,EAAE,IAAI,IAAI,IAAI,GAAG;KAE/D;EACF"}
1
+ {"version":3,"file":"resolveMaizzleImports.js","names":[],"sources":["../../../src/plugins/postcss/resolveMaizzleImports.ts"],"sourcesContent":["import { createRequire } from 'node:module'\nimport type { Plugin } from 'postcss'\n\nconst PKG = '@maizzle/tailwindcss'\nconst SUBPATH_RE = new RegExp(`^${PKG}(?:/|$)`)\n\nconst requireFromFramework = createRequire(import.meta.url)\n\n/**\n * Rewrite `@import \"@maizzle/tailwindcss\"` (and subpaths like\n * `@maizzle/tailwindcss/mso`) to absolute file paths so postcss/Tailwind\n * can resolve them regardless of where the user's template lives or how\n * their package manager hoists dependencies.\n *\n * Resolution order: prefer the user's project copy (so explicit installs\n * win), then fall back to the copy bundled with the framework.\n */\nexport function resolveMaizzleImports(userRoot: string = process.cwd()): Plugin {\n const requireFromUser = createRequire(`${userRoot}/_maizzle.js`)\n\n function resolve(spec: string): string | undefined {\n try { return requireFromUser.resolve(spec) } catch {}\n try { return requireFromFramework.resolve(spec) } catch {}\n return undefined\n }\n\n return {\n postcssPlugin: 'maizzle:resolve-tw-imports',\n AtRule: {\n import(rule) {\n const m = rule.params.match(/^\\s*[\"']([^\"']+)[\"']/)\n if (!m) return\n const spec = m[1]\n if (!SUBPATH_RE.test(spec)) return\n\n const abs = resolve(spec)\n if (abs) rule.params = rule.params.replace(m[0], `\"${abs}\"`)\n },\n },\n }\n}\n"],"mappings":";;AAIA,MAAM,aAAa,IAAI,OAAO,8BAAgB;AAE9C,MAAM,uBAAuB,cAAc,OAAO,KAAK,GAAG;;;;;;;;;;AAW1D,SAAgB,sBAAsB,WAAmB,QAAQ,IAAI,GAAW;CAC9E,MAAM,kBAAkB,cAAc,GAAG,SAAS,aAAa;CAE/D,SAAS,QAAQ,MAAkC;EACjD,IAAI;GAAE,OAAO,gBAAgB,QAAQ,IAAI;EAAE,QAAQ,CAAC;EACpD,IAAI;GAAE,OAAO,qBAAqB,QAAQ,IAAI;EAAE,QAAQ,CAAC;CAE3D;CAEA,OAAO;EACL,eAAe;EACf,QAAQ,EACN,OAAO,MAAM;GACX,MAAM,IAAI,KAAK,OAAO,MAAM,sBAAsB;GAClD,IAAI,CAAC,GAAG;GACR,MAAM,OAAO,EAAE;GACf,IAAI,CAAC,WAAW,KAAK,IAAI,GAAG;GAE5B,MAAM,MAAM,QAAQ,IAAI;GACxB,IAAI,KAAK,KAAK,SAAS,KAAK,OAAO,QAAQ,EAAE,IAAI,IAAI,IAAI,EAAE;EAC7D,EACF;CACF;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"resolveProps.d.ts","names":[],"sources":["../../../src/plugins/postcss/resolveProps.ts"],"mappings":";;;cAiByD,QAAA,QA6FtC,MAAA;AAAA,cA8IN,OAAA"}
1
+ {"version":3,"file":"resolveProps.d.ts","names":[],"sources":["../../../src/plugins/postcss/resolveProps.ts"],"mappings":";;;cAiByD,QAAA,QA+FtC,MAAM;AAAA,cAqJZ,OAAA"}
@@ -70,9 +70,18 @@ var resolveProps_default = () => {
70
70
  propertyDefaults.set(name, decl.value);
71
71
  });
72
72
  });
73
+ /**
74
+ * Pass 1: collect :root vars (top-level and inside @layer). Skip
75
+ * :root inside @media — those are for dark mode and should
76
+ * stay.
77
+ */
73
78
  const rootVars = /* @__PURE__ */ new Map();
74
79
  root.walkRules((rule) => {
75
80
  if (!isRootRule(rule)) return;
81
+ /**
82
+ * Allow :root at top level or inside @layer (Tailwind theme vars).
83
+ * Skip :root inside @media or other non-layer at-rules.
84
+ */
76
85
  if (rule.parent?.type !== "root" && !isInLayer(rule)) return;
77
86
  rule.each((node) => {
78
87
  if (node.type === "decl" && node.prop.startsWith("--")) rootVars.set(node.prop, node.value);
@@ -94,6 +103,11 @@ var resolveProps_default = () => {
94
103
  }
95
104
  }
96
105
  root.walkRules((rule) => {
106
+ /**
107
+ * Skip :root inside @media — those vars are for dark mode etc. and
108
+ * must stay in the <style> tag as-is. Allow :root at top
109
+ * level and inside @layer (processed in pass 3).
110
+ */
97
111
  if (isRootRule(rule)) {
98
112
  if (rule.parent?.type !== "root" && !isInLayer(rule)) return;
99
113
  }
@@ -1 +1 @@
1
- {"version":3,"file":"resolveProps.js","names":[],"sources":["../../../src/plugins/postcss/resolveProps.ts"],"sourcesContent":["/**\n * postcss-resolve-props\n *\n * Resolves CSS custom properties (var() references) and removes\n * the consumed declarations, producing flat CSS for email inlining.\n *\n * Resolution order per var():\n * 1. Local declaration in the same rule\n * 2. :root declaration (top-level only, not inside @media)\n * 3. @property initial-value (Tailwind v4 composable defaults)\n * 4. Fallback value from the var() itself\n *\n * Handles nested var() in both values and fallbacks.\n * Replaces postcss-custom-properties with correct support for\n * local var declarations (Tailwind composable pattern, user CSS).\n */\n\nimport type { AtRule, Plugin, Root, Rule } from 'postcss'\n\n/** Check if a rule's selector includes :root */\nfunction isRootRule(rule: Rule): boolean {\n const sel = rule.selector\n return sel === ':root' || sel.includes(':root')\n}\n\n/** Check if a rule is inside @layer (not @media or other at-rules) */\nfunction isInLayer(rule: Rule): boolean {\n return rule.parent?.type === 'atrule' && (rule.parent as any).name === 'layer'\n}\n\n/**\n * Parse the first var() call in a string by counting parens.\n * Returns null if no var() found.\n */\nfunction findVar(value: string, startFrom = 0): {\n start: number\n end: number\n name: string\n fallback: string | undefined\n} | null {\n const idx = value.indexOf('var(', startFrom)\n if (idx === -1) return null\n\n let depth = 1\n let i = idx + 4\n let commaIdx = -1\n\n while (i < value.length && depth > 0) {\n const ch = value.charCodeAt(i)\n if (ch === 40 /* ( */) depth++\n else if (ch === 41 /* ) */) {\n if (--depth === 0) break\n } else if (ch === 44 /* , */ && depth === 1 && commaIdx === -1) {\n commaIdx = i\n }\n i++\n }\n\n if (depth !== 0) return null\n\n const name = commaIdx === -1\n ? value.slice(idx + 4, i).trim()\n : value.slice(idx + 4, commaIdx).trim()\n\n const fallback = commaIdx === -1\n ? undefined\n : value.slice(commaIdx + 1, i)\n\n return { start: idx, end: i + 1, name, fallback }\n}\n\n/**\n * Resolve all var() references in a value string.\n * Iterates until no resolvable var() remain.\n */\nfunction resolveValue(\n value: string,\n localVars: Map<string, string>,\n rootVars: Map<string, string>,\n propertyDefaults?: Map<string, string>,\n): string {\n let result = value\n let safety = 10\n\n while (safety-- > 0) {\n const v = findVar(result)\n if (!v) break\n\n const resolved = localVars.get(v.name) ?? rootVars.get(v.name) ?? propertyDefaults?.get(v.name)\n\n if (resolved !== undefined) {\n result = result.slice(0, v.start) + resolved + result.slice(v.end)\n } else if (v.fallback !== undefined) {\n result = result.slice(0, v.start) + v.fallback.trim() + result.slice(v.end)\n } else {\n // Unresolvable with no fallback — skip past it to avoid infinite loop\n // Try to find another var() after this one\n const next = findVar(result, v.end)\n if (!next) break\n\n // Process the rest of the string from after this var()\n const tail = resolveValue(result.slice(v.end), localVars, rootVars, propertyDefaults)\n result = result.slice(0, v.end) + tail\n break\n }\n }\n\n return result\n}\n\nexport default (): Plugin => {\n return {\n postcssPlugin: 'postcss-resolve-props',\n\n Once(root: Root) {\n // Pass 0: collect @property initial-value defaults (Tailwind v4 composable pattern)\n const propertyDefaults = new Map<string, string>()\n\n root.walkAtRules('property', (rule: AtRule) => {\n const name = rule.params.trim()\n if (!name.startsWith('--')) return\n\n rule.walkDecls('initial-value', (decl) => {\n propertyDefaults.set(name, decl.value)\n })\n })\n\n // Pass 1: collect :root vars (top-level and inside @layer)\n // Skip :root inside @media — those are for dark mode and should stay.\n const rootVars = new Map<string, string>()\n\n root.walkRules((rule) => {\n if (!isRootRule(rule)) return\n\n // Allow :root at top level or inside @layer (Tailwind theme vars)\n // Skip :root inside @media or other non-layer at-rules\n if (rule.parent?.type !== 'root' && !isInLayer(rule)) return\n\n rule.each((node) => {\n if (node.type === 'decl' && node.prop.startsWith('--')) {\n rootVars.set(node.prop, node.value)\n }\n })\n })\n\n // Resolve :root vars referencing other :root vars\n if (rootVars.size > 0) {\n let changed = true\n let iterations = 5\n\n while (changed && iterations-- > 0) {\n changed = false\n for (const [name, value] of rootVars) {\n if (!value.includes('var(')) continue\n const resolved = resolveValue(value, rootVars, rootVars, propertyDefaults)\n if (resolved !== value) {\n rootVars.set(name, resolved)\n changed = true\n }\n }\n }\n }\n\n // Pass 2: resolve var() in all rules\n root.walkRules((rule) => {\n // Skip :root inside @media — those vars are for dark mode etc.\n // and must stay in the <style> tag as-is.\n // Allow :root at top level and inside @layer (processed in pass 3).\n if (isRootRule(rule)) {\n if (rule.parent?.type !== 'root' && !isInLayer(rule)) return\n }\n\n // Collect local --* declarations (walk into nested @media etc.)\n const localVars = new Map<string, string>()\n const localDecls: Declaration[] = []\n let hasVarRefs = false\n\n rule.walk((node) => {\n if (node.type !== 'decl') return\n\n if (node.prop.startsWith('--')) {\n localDecls.push(node)\n } else if (node.value.includes('var(')) {\n hasVarRefs = true\n }\n })\n\n // Skip rules with no var() references and no local vars to clean up\n if (!hasVarRefs && localDecls.length === 0) return\n\n // Build local vars map — resolve values that reference other locals or :root\n for (const decl of localDecls) {\n const value = decl.value.includes('var(')\n ? resolveValue(decl.value, localVars, rootVars, propertyDefaults)\n : decl.value\n\n localVars.set(decl.prop, value)\n }\n\n // Resolve var() in non-custom-property declarations (walk into nested @media etc.)\n if (hasVarRefs) {\n rule.walk((node) => {\n if (node.type !== 'decl') return\n if (node.prop.startsWith('--')) return\n if (!node.value.includes('var(')) return\n\n const resolved = resolveValue(node.value, localVars, rootVars, propertyDefaults)\n\n if (resolved !== node.value) {\n // Clean up: collapse whitespace, trim\n const cleaned = resolved.replace(/ +/g, ' ').trim()\n\n if (cleaned) {\n node.value = cleaned\n } else {\n // Value resolved to empty — remove the declaration\n node.remove()\n }\n }\n })\n }\n\n // Remove local --* declarations (consumed or no longer needed)\n for (const decl of localDecls) {\n decl.remove()\n }\n })\n\n // Remove @property rules (not supported in email clients)\n root.walkAtRules('property', (rule) => {\n rule.remove()\n })\n\n // Pass 3: clean up :root (same scope as pass 1)\n root.walkRules((rule) => {\n if (!isRootRule(rule)) return\n if (rule.parent?.type !== 'root' && !isInLayer(rule)) return\n\n rule.each((node) => {\n if (node.type === 'decl' && node.prop.startsWith('--')) {\n node.remove()\n }\n })\n\n if (rule.nodes?.length === 0) {\n rule.remove()\n }\n })\n },\n }\n}\n\nexport const postcss = true\n"],"mappings":"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"}
1
+ {"version":3,"file":"resolveProps.js","names":[],"sources":["../../../src/plugins/postcss/resolveProps.ts"],"sourcesContent":["/**\n * postcss-resolve-props\n *\n * Resolves CSS custom properties (var() references) and removes\n * the consumed declarations, producing flat CSS for email inlining.\n *\n * Resolution order per var():\n * 1. Local declaration in the same rule\n * 2. :root declaration (top-level only, not inside @media)\n * 3. @property initial-value (Tailwind v4 composable defaults)\n * 4. Fallback value from the var() itself\n *\n * Handles nested var() in both values and fallbacks.\n * Replaces postcss-custom-properties with correct support for\n * local var declarations (Tailwind composable pattern, user CSS).\n */\n\nimport type { AtRule, Plugin, Root, Rule } from 'postcss'\n\n/** Check if a rule's selector includes :root */\nfunction isRootRule(rule: Rule): boolean {\n const sel = rule.selector\n return sel === ':root' || sel.includes(':root')\n}\n\n/** Check if a rule is inside @layer (not @media or other at-rules) */\nfunction isInLayer(rule: Rule): boolean {\n return rule.parent?.type === 'atrule' && (rule.parent as any).name === 'layer'\n}\n\n/**\n * Parse the first var() call in a string by counting parens.\n * Returns null if no var() found.\n */\nfunction findVar(value: string, startFrom = 0): {\n start: number\n end: number\n name: string\n fallback: string | undefined\n} | null {\n const idx = value.indexOf('var(', startFrom)\n if (idx === -1) return null\n\n let depth = 1\n let i = idx + 4\n let commaIdx = -1\n\n while (i < value.length && depth > 0) {\n const ch = value.charCodeAt(i)\n if (ch === 40 /* ( */) depth++\n else if (ch === 41 /* ) */) {\n if (--depth === 0) break\n } else if (ch === 44 /* , */ && depth === 1 && commaIdx === -1) {\n commaIdx = i\n }\n i++\n }\n\n if (depth !== 0) return null\n\n const name = commaIdx === -1\n ? value.slice(idx + 4, i).trim()\n : value.slice(idx + 4, commaIdx).trim()\n\n const fallback = commaIdx === -1\n ? undefined\n : value.slice(commaIdx + 1, i)\n\n return { start: idx, end: i + 1, name, fallback }\n}\n\n/**\n * Resolve all var() references in a value string.\n * Iterates until no resolvable var() remain.\n */\nfunction resolveValue(\n value: string,\n localVars: Map<string, string>,\n rootVars: Map<string, string>,\n propertyDefaults?: Map<string, string>,\n): string {\n let result = value\n let safety = 10\n\n while (safety-- > 0) {\n const v = findVar(result)\n if (!v) break\n\n const resolved = localVars.get(v.name) ?? rootVars.get(v.name) ?? propertyDefaults?.get(v.name)\n\n if (resolved !== undefined) {\n result = result.slice(0, v.start) + resolved + result.slice(v.end)\n } else if (v.fallback !== undefined) {\n result = result.slice(0, v.start) + v.fallback.trim() + result.slice(v.end)\n } else {\n /**\n * Unresolvable with no fallback — skip past it to avoid infinite loop.\n * Try to find another var() after this one.\n */\n const next = findVar(result, v.end)\n if (!next) break\n\n // Process the rest of the string from after this var()\n const tail = resolveValue(result.slice(v.end), localVars, rootVars, propertyDefaults)\n result = result.slice(0, v.end) + tail\n break\n }\n }\n\n return result\n}\n\nexport default (): Plugin => {\n return {\n postcssPlugin: 'postcss-resolve-props',\n\n Once(root: Root) {\n // Pass 0: collect @property initial-value defaults (Tailwind v4 composable pattern)\n const propertyDefaults = new Map<string, string>()\n\n root.walkAtRules('property', (rule: AtRule) => {\n const name = rule.params.trim()\n if (!name.startsWith('--')) return\n\n rule.walkDecls('initial-value', (decl) => {\n propertyDefaults.set(name, decl.value)\n })\n })\n\n /**\n * Pass 1: collect :root vars (top-level and inside @layer). Skip\n * :root inside @media — those are for dark mode and should\n * stay.\n */\n const rootVars = new Map<string, string>()\n\n root.walkRules((rule) => {\n if (!isRootRule(rule)) return\n\n /**\n * Allow :root at top level or inside @layer (Tailwind theme vars).\n * Skip :root inside @media or other non-layer at-rules.\n */\n if (rule.parent?.type !== 'root' && !isInLayer(rule)) return\n\n rule.each((node) => {\n if (node.type === 'decl' && node.prop.startsWith('--')) {\n rootVars.set(node.prop, node.value)\n }\n })\n })\n\n // Resolve :root vars referencing other :root vars\n if (rootVars.size > 0) {\n let changed = true\n let iterations = 5\n\n while (changed && iterations-- > 0) {\n changed = false\n for (const [name, value] of rootVars) {\n if (!value.includes('var(')) continue\n const resolved = resolveValue(value, rootVars, rootVars, propertyDefaults)\n if (resolved !== value) {\n rootVars.set(name, resolved)\n changed = true\n }\n }\n }\n }\n\n // Pass 2: resolve var() in all rules\n root.walkRules((rule) => {\n /**\n * Skip :root inside @media — those vars are for dark mode etc. and\n * must stay in the <style> tag as-is. Allow :root at top\n * level and inside @layer (processed in pass 3).\n */\n if (isRootRule(rule)) {\n if (rule.parent?.type !== 'root' && !isInLayer(rule)) return\n }\n\n // Collect local --* declarations (walk into nested @media etc.)\n const localVars = new Map<string, string>()\n const localDecls: Declaration[] = []\n let hasVarRefs = false\n\n rule.walk((node) => {\n if (node.type !== 'decl') return\n\n if (node.prop.startsWith('--')) {\n localDecls.push(node)\n } else if (node.value.includes('var(')) {\n hasVarRefs = true\n }\n })\n\n // Skip rules with no var() references and no local vars to clean up\n if (!hasVarRefs && localDecls.length === 0) return\n\n // Build local vars map — resolve values that reference other locals or :root\n for (const decl of localDecls) {\n const value = decl.value.includes('var(')\n ? resolveValue(decl.value, localVars, rootVars, propertyDefaults)\n : decl.value\n\n localVars.set(decl.prop, value)\n }\n\n // Resolve var() in non-custom-property declarations (walk into nested @media etc.)\n if (hasVarRefs) {\n rule.walk((node) => {\n if (node.type !== 'decl') return\n if (node.prop.startsWith('--')) return\n if (!node.value.includes('var(')) return\n\n const resolved = resolveValue(node.value, localVars, rootVars, propertyDefaults)\n\n if (resolved !== node.value) {\n // Clean up: collapse whitespace, trim\n const cleaned = resolved.replace(/ +/g, ' ').trim()\n\n if (cleaned) {\n node.value = cleaned\n } else {\n // Value resolved to empty — remove the declaration\n node.remove()\n }\n }\n })\n }\n\n // Remove local --* declarations (consumed or no longer needed)\n for (const decl of localDecls) {\n decl.remove()\n }\n })\n\n // Remove @property rules (not supported in email clients)\n root.walkAtRules('property', (rule) => {\n rule.remove()\n })\n\n // Pass 3: clean up :root (same scope as pass 1)\n root.walkRules((rule) => {\n if (!isRootRule(rule)) return\n if (rule.parent?.type !== 'root' && !isInLayer(rule)) return\n\n rule.each((node) => {\n if (node.type === 'decl' && node.prop.startsWith('--')) {\n node.remove()\n }\n })\n\n if (rule.nodes?.length === 0) {\n rule.remove()\n }\n })\n },\n }\n}\n\nexport const postcss = true\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"tailwindCleanup.d.ts","names":[],"sources":["../../../src/plugins/postcss/tailwindCleanup.ts"],"mappings":";;;;;;AA0CA;;;;;;;;iBAAgB,eAAA,CAAgB,MAAA,EAAQ,aAAA,GAAgB,OAAA,CAAQ,MAAA"}
1
+ {"version":3,"file":"tailwindCleanup.d.ts","names":[],"sources":["../../../src/plugins/postcss/tailwindCleanup.ts"],"mappings":";;;;;;AA0CA;;;;;;;;iBAAgB,eAAA,CAAgB,MAAA,EAAQ,aAAA,GAAgB,OAAA,CAAQ,MAAM"}
@@ -1 +1 @@
1
- {"version":3,"file":"tailwindCleanup.js","names":[],"sources":["../../../src/plugins/postcss/tailwindCleanup.ts"],"sourcesContent":["import postcss from 'postcss'\nimport type { MaizzleConfig } from '../../types/config.ts'\n\nconst DEFAULT_SELECTORS = [':host', ':lang']\nconst DEFAULT_AT_RULES = ['layer', 'property']\n\n/**\n * Split a selector list on top-level commas only.\n *\n * Commas inside parenthesised groups like `:not(:is(:lang(ae), :lang(ar)))`\n * are not treated as selector separators.\n */\nfunction splitSelector(selector: string): string[] {\n const parts: string[] = []\n let depth = 0\n let start = 0\n\n for (let i = 0; i < selector.length; i++) {\n const ch = selector[i]\n if (ch === '(') depth++\n else if (ch === ')') depth--\n else if (ch === ',' && depth === 0) {\n parts.push(selector.slice(start, i).trim())\n start = i + 1\n }\n }\n\n parts.push(selector.slice(start).trim())\n\n return parts.filter(Boolean)\n}\n\n/**\n * Removes CSS rules whose every comma-separated selector part starts with\n * one of the configured prefixes (e.g. ':host', ':lang'). Rules with mixed\n * selectors have the unwanted parts stripped.\n *\n * Also removes entire at-rules by name (e.g. '@layer', '@property').\n *\n * Intended to clean up Tailwind's compiled output after lightningcss has\n * flattened all modern CSS syntax.\n */\nexport function tailwindCleanup(config: MaizzleConfig): postcss.Plugin[] {\n const selectors: string[] = config.postcss?.removeSelectors ?? DEFAULT_SELECTORS\n const atRules: string[] = config.postcss?.removeAtRules ?? DEFAULT_AT_RULES\n\n return [\n {\n postcssPlugin: 'tailwind-cleanup-selectors',\n Rule(rule) {\n const parts = splitSelector(rule.selector)\n const kept = parts.filter(p => !selectors.some(s => p === s || p.includes(`${s}(`)))\n if (kept.length === 0) {\n rule.remove()\n } else if (kept.length < parts.length) {\n rule.selector = kept.join(', ')\n }\n },\n },\n {\n postcssPlugin: 'tailwind-cleanup-at-rules',\n AtRule(rule) {\n if (!atRules.includes(rule.name)) return\n\n if (rule.nodes?.length) {\n // Unwrap: keep children, remove the at-rule wrapper\n rule.replaceWith(rule.nodes)\n } else {\n rule.remove()\n }\n },\n },\n {\n postcssPlugin: 'tailwind-cleanup-text-decoration',\n Declaration(decl) {\n if (decl.prop === 'text-decoration-line') {\n decl.prop = 'text-decoration'\n }\n },\n },\n ]\n}\n"],"mappings":";AAGA,MAAM,oBAAoB,CAAC,SAAS,QAAQ;AAC5C,MAAM,mBAAmB,CAAC,SAAS,WAAW;;;;;;;AAQ9C,SAAS,cAAc,UAA4B;CACjD,MAAM,QAAkB,EAAE;CAC1B,IAAI,QAAQ;CACZ,IAAI,QAAQ;CAEZ,KAAK,IAAI,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;EACxC,MAAM,KAAK,SAAS;EACpB,IAAI,OAAO,KAAK;OACX,IAAI,OAAO,KAAK;OAChB,IAAI,OAAO,OAAO,UAAU,GAAG;GAClC,MAAM,KAAK,SAAS,MAAM,OAAO,EAAE,CAAC,MAAM,CAAC;GAC3C,QAAQ,IAAI;;;CAIhB,MAAM,KAAK,SAAS,MAAM,MAAM,CAAC,MAAM,CAAC;CAExC,OAAO,MAAM,OAAO,QAAQ;;;;;;;;;;;;AAa9B,SAAgB,gBAAgB,QAAyC;CACvE,MAAM,YAAsB,OAAO,SAAS,mBAAmB;CAC/D,MAAM,UAAoB,OAAO,SAAS,iBAAiB;CAE3D,OAAO;EACL;GACE,eAAe;GACf,KAAK,MAAM;IACT,MAAM,QAAQ,cAAc,KAAK,SAAS;IAC1C,MAAM,OAAO,MAAM,QAAO,MAAK,CAAC,UAAU,MAAK,MAAK,MAAM,KAAK,EAAE,SAAS,GAAG,EAAE,GAAG,CAAC,CAAC;IACpF,IAAI,KAAK,WAAW,GAClB,KAAK,QAAQ;SACR,IAAI,KAAK,SAAS,MAAM,QAC7B,KAAK,WAAW,KAAK,KAAK,KAAK;;GAGpC;EACD;GACE,eAAe;GACf,OAAO,MAAM;IACX,IAAI,CAAC,QAAQ,SAAS,KAAK,KAAK,EAAE;IAElC,IAAI,KAAK,OAAO,QAEd,KAAK,YAAY,KAAK,MAAM;SAE5B,KAAK,QAAQ;;GAGlB;EACD;GACE,eAAe;GACf,YAAY,MAAM;IAChB,IAAI,KAAK,SAAS,wBAChB,KAAK,OAAO;;GAGjB;EACF"}
1
+ {"version":3,"file":"tailwindCleanup.js","names":[],"sources":["../../../src/plugins/postcss/tailwindCleanup.ts"],"sourcesContent":["import postcss from 'postcss'\nimport type { MaizzleConfig } from '../../types/config.ts'\n\nconst DEFAULT_SELECTORS = [':host', ':lang']\nconst DEFAULT_AT_RULES = ['layer', 'property']\n\n/**\n * Split a selector list on top-level commas only.\n *\n * Commas inside parenthesised groups like `:not(:is(:lang(ae), :lang(ar)))`\n * are not treated as selector separators.\n */\nfunction splitSelector(selector: string): string[] {\n const parts: string[] = []\n let depth = 0\n let start = 0\n\n for (let i = 0; i < selector.length; i++) {\n const ch = selector[i]\n if (ch === '(') depth++\n else if (ch === ')') depth--\n else if (ch === ',' && depth === 0) {\n parts.push(selector.slice(start, i).trim())\n start = i + 1\n }\n }\n\n parts.push(selector.slice(start).trim())\n\n return parts.filter(Boolean)\n}\n\n/**\n * Removes CSS rules whose every comma-separated selector part starts with\n * one of the configured prefixes (e.g. ':host', ':lang'). Rules with mixed\n * selectors have the unwanted parts stripped.\n *\n * Also removes entire at-rules by name (e.g. '@layer', '@property').\n *\n * Intended to clean up Tailwind's compiled output after lightningcss has\n * flattened all modern CSS syntax.\n */\nexport function tailwindCleanup(config: MaizzleConfig): postcss.Plugin[] {\n const selectors: string[] = config.postcss?.removeSelectors ?? DEFAULT_SELECTORS\n const atRules: string[] = config.postcss?.removeAtRules ?? DEFAULT_AT_RULES\n\n return [\n {\n postcssPlugin: 'tailwind-cleanup-selectors',\n Rule(rule) {\n const parts = splitSelector(rule.selector)\n const kept = parts.filter(p => !selectors.some(s => p === s || p.includes(`${s}(`)))\n if (kept.length === 0) {\n rule.remove()\n } else if (kept.length < parts.length) {\n rule.selector = kept.join(', ')\n }\n },\n },\n {\n postcssPlugin: 'tailwind-cleanup-at-rules',\n AtRule(rule) {\n if (!atRules.includes(rule.name)) return\n\n if (rule.nodes?.length) {\n // Unwrap: keep children, remove the at-rule wrapper\n rule.replaceWith(rule.nodes)\n } else {\n rule.remove()\n }\n },\n },\n {\n postcssPlugin: 'tailwind-cleanup-text-decoration',\n Declaration(decl) {\n if (decl.prop === 'text-decoration-line') {\n decl.prop = 'text-decoration'\n }\n },\n },\n ]\n}\n"],"mappings":";AAGA,MAAM,oBAAoB,CAAC,SAAS,OAAO;AAC3C,MAAM,mBAAmB,CAAC,SAAS,UAAU;;;;;;;AAQ7C,SAAS,cAAc,UAA4B;CACjD,MAAM,QAAkB,CAAC;CACzB,IAAI,QAAQ;CACZ,IAAI,QAAQ;CAEZ,KAAK,IAAI,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;EACxC,MAAM,KAAK,SAAS;EACpB,IAAI,OAAO,KAAK;OACX,IAAI,OAAO,KAAK;OAChB,IAAI,OAAO,OAAO,UAAU,GAAG;GAClC,MAAM,KAAK,SAAS,MAAM,OAAO,CAAC,EAAE,KAAK,CAAC;GAC1C,QAAQ,IAAI;EACd;CACF;CAEA,MAAM,KAAK,SAAS,MAAM,KAAK,EAAE,KAAK,CAAC;CAEvC,OAAO,MAAM,OAAO,OAAO;AAC7B;;;;;;;;;;;AAYA,SAAgB,gBAAgB,QAAyC;CACvE,MAAM,YAAsB,OAAO,SAAS,mBAAmB;CAC/D,MAAM,UAAoB,OAAO,SAAS,iBAAiB;CAE3D,OAAO;EACL;GACE,eAAe;GACf,KAAK,MAAM;IACT,MAAM,QAAQ,cAAc,KAAK,QAAQ;IACzC,MAAM,OAAO,MAAM,QAAO,MAAK,CAAC,UAAU,MAAK,MAAK,MAAM,KAAK,EAAE,SAAS,GAAG,EAAE,EAAE,CAAC,CAAC;IACnF,IAAI,KAAK,WAAW,GAClB,KAAK,OAAO;SACP,IAAI,KAAK,SAAS,MAAM,QAC7B,KAAK,WAAW,KAAK,KAAK,IAAI;GAElC;EACF;EACA;GACE,eAAe;GACf,OAAO,MAAM;IACX,IAAI,CAAC,QAAQ,SAAS,KAAK,IAAI,GAAG;IAElC,IAAI,KAAK,OAAO,QAEd,KAAK,YAAY,KAAK,KAAK;SAE3B,KAAK,OAAO;GAEhB;EACF;EACA;GACE,eAAe;GACf,YAAY,MAAM;IAChB,IAAI,KAAK,SAAS,wBAChB,KAAK,OAAO;GAEhB;EACF;CACF;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"prepare.d.ts","names":[],"sources":["../src/prepare.ts"],"mappings":";UAOiB,cAAA;EAAA;EAEf,MAAA;AAAA;;;AAWF;;;;;;iBAAsB,OAAA,CAAQ,OAAA,GAAS,cAAA,GAAsB,OAAA"}
1
+ {"version":3,"file":"prepare.d.ts","names":[],"sources":["../src/prepare.ts"],"mappings":";UAOiB,cAAA;EAAA;EAEf,MAAM;AAAA;;AAAA;AAWR;;;;;;iBAAsB,OAAA,CAAQ,OAAA,GAAS,cAAA,GAAsB,OAAO"}