@maizzle/framework 6.0.0-rc.0 → 6.0.0-rc.10

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 (341) hide show
  1. package/bin/maizzle.mjs +1 -1
  2. package/dist/_virtual/_rolldown/runtime.mjs +32 -0
  3. package/dist/build.mjs +29 -9
  4. package/dist/build.mjs.map +1 -1
  5. package/dist/components/Body.vue +111 -0
  6. package/dist/components/Button.vue +68 -14
  7. package/dist/components/CodeBlock.vue +68 -0
  8. package/dist/components/CodeInline.vue +49 -0
  9. package/dist/components/Column.vue +86 -0
  10. package/dist/components/Container.vue +48 -0
  11. package/dist/components/Divider.vue +28 -0
  12. package/dist/components/Head.vue +30 -0
  13. package/dist/components/Heading.vue +28 -0
  14. package/dist/components/Html.vue +104 -0
  15. package/dist/components/Image.vue +70 -0
  16. package/dist/components/Layout.vue +93 -0
  17. package/dist/components/Link.vue +26 -0
  18. package/dist/components/Markdown.vue +89 -0
  19. package/dist/components/Outlook.vue +36 -0
  20. package/dist/components/Overlap.vue +80 -0
  21. package/dist/components/Preheader.vue +20 -0
  22. package/dist/components/Row.vue +91 -0
  23. package/dist/components/Section.vue +83 -0
  24. package/dist/components/Spacer.vue +50 -7
  25. package/dist/components/Text.vue +29 -0
  26. package/dist/components/Vml.vue +165 -13
  27. package/dist/composables/renderContext.d.mts +5 -0
  28. package/dist/composables/renderContext.d.mts.map +1 -1
  29. package/dist/composables/renderContext.mjs.map +1 -1
  30. package/dist/composables/usePreviewText.d.mts +24 -0
  31. package/dist/composables/usePreviewText.d.mts.map +1 -0
  32. package/dist/composables/usePreviewText.mjs +29 -0
  33. package/dist/composables/usePreviewText.mjs.map +1 -0
  34. package/dist/config/index.mjs +25 -1
  35. package/dist/config/index.mjs.map +1 -1
  36. package/dist/index.d.mts +4 -2
  37. package/dist/index.mjs +3 -1
  38. package/dist/node_modules/picomatch/index.mjs +13 -0
  39. package/dist/node_modules/picomatch/index.mjs.map +1 -0
  40. package/dist/node_modules/picomatch/lib/constants.mjs +174 -0
  41. package/dist/node_modules/picomatch/lib/constants.mjs.map +1 -0
  42. package/dist/node_modules/picomatch/lib/parse.mjs +1067 -0
  43. package/dist/node_modules/picomatch/lib/parse.mjs.map +1 -0
  44. package/dist/node_modules/picomatch/lib/picomatch.mjs +304 -0
  45. package/dist/node_modules/picomatch/lib/picomatch.mjs.map +1 -0
  46. package/dist/node_modules/picomatch/lib/scan.mjs +296 -0
  47. package/dist/node_modules/picomatch/lib/scan.mjs.map +1 -0
  48. package/dist/node_modules/picomatch/lib/utils.mjs +53 -0
  49. package/dist/node_modules/picomatch/lib/utils.mjs.map +1 -0
  50. package/dist/plugin.d.mts.map +1 -1
  51. package/dist/plugin.mjs +24 -7
  52. package/dist/plugin.mjs.map +1 -1
  53. package/dist/plugins/postcss/tailwindCleanup.d.mts.map +1 -1
  54. package/dist/plugins/postcss/tailwindCleanup.mjs +44 -13
  55. package/dist/plugins/postcss/tailwindCleanup.mjs.map +1 -1
  56. package/dist/render/createRenderer.d.mts +10 -3
  57. package/dist/render/createRenderer.d.mts.map +1 -1
  58. package/dist/render/createRenderer.mjs +147 -10
  59. package/dist/render/createRenderer.mjs.map +1 -1
  60. package/dist/render/index.mjs +9 -3
  61. package/dist/render/index.mjs.map +1 -1
  62. package/dist/serve.d.mts.map +1 -1
  63. package/dist/serve.mjs +159 -63
  64. package/dist/serve.mjs.map +1 -1
  65. package/dist/server/compatibility.d.mts +1 -2
  66. package/dist/server/compatibility.d.mts.map +1 -1
  67. package/dist/server/compatibility.mjs +30 -16
  68. package/dist/server/compatibility.mjs.map +1 -1
  69. package/dist/server/email.d.mts +17 -0
  70. package/dist/server/email.d.mts.map +1 -0
  71. package/dist/server/email.mjs +41 -0
  72. package/dist/server/email.mjs.map +1 -0
  73. package/dist/server/linter.d.mts +1 -2
  74. package/dist/server/linter.d.mts.map +1 -1
  75. package/dist/server/linter.mjs +60 -71
  76. package/dist/server/linter.mjs.map +1 -1
  77. package/dist/server/ui/App.vue +205 -69
  78. package/dist/server/ui/components/ui/checkbox/Checkbox.vue +35 -0
  79. package/dist/server/ui/components/ui/checkbox/index.ts +1 -0
  80. package/dist/server/ui/components/ui/command/CommandDialog.vue +1 -1
  81. package/dist/server/ui/components/ui/command/CommandInput.vue +19 -1
  82. package/dist/server/ui/components/ui/command/CommandItem.vue +1 -1
  83. package/dist/server/ui/components/ui/command/CommandList.vue +1 -1
  84. package/dist/server/ui/components/ui/command/CommandShortcut.vue +1 -1
  85. package/dist/server/ui/components/ui/dialog/DialogOverlay.vue +9 -1
  86. package/dist/server/ui/components/ui/dropdown-menu/DropdownMenuItem.vue +1 -1
  87. package/dist/server/ui/components/ui/scroll-area/ScrollBar.vue +1 -1
  88. package/dist/server/ui/components/ui/sheet/SheetContent.vue +1 -1
  89. package/dist/server/ui/components/ui/sheet/SheetOverlay.vue +9 -1
  90. package/dist/server/ui/components/ui/sidebar/Sidebar.vue +8 -1
  91. package/dist/server/ui/components/ui/sidebar/SidebarProvider.vue +1 -1
  92. package/dist/server/ui/components/ui/sidebar/SidebarTrigger.vue +5 -4
  93. package/dist/server/ui/components/ui/tags-input/TagsInput.vue +26 -0
  94. package/dist/server/ui/components/ui/tags-input/TagsInputInput.vue +17 -0
  95. package/dist/server/ui/components/ui/tags-input/TagsInputItem.vue +19 -0
  96. package/dist/server/ui/components/ui/tags-input/TagsInputItemDelete.vue +22 -0
  97. package/dist/server/ui/components/ui/tags-input/TagsInputItemText.vue +17 -0
  98. package/dist/server/ui/components/ui/tags-input/index.ts +5 -0
  99. package/dist/server/ui/components/ui/toggle/index.ts +3 -3
  100. package/dist/server/ui/components/ui/toggle-group/ToggleGroup.vue +1 -1
  101. package/dist/server/ui/components/ui/toggle-group/ToggleGroupItem.vue +2 -2
  102. package/dist/server/ui/main.css +20 -20
  103. package/dist/server/ui/pages/Home.vue +12 -5
  104. package/dist/server/ui/pages/Preview.vue +506 -216
  105. package/dist/transformers/entities.d.mts.map +1 -1
  106. package/dist/transformers/entities.mjs +3 -0
  107. package/dist/transformers/entities.mjs.map +1 -1
  108. package/dist/transformers/filters/defaults.d.mts +6 -0
  109. package/dist/transformers/filters/defaults.d.mts.map +1 -0
  110. package/dist/transformers/filters/defaults.mjs +78 -0
  111. package/dist/transformers/filters/defaults.mjs.map +1 -0
  112. package/dist/transformers/filters/index.d.mts +22 -0
  113. package/dist/transformers/filters/index.d.mts.map +1 -0
  114. package/dist/transformers/filters/index.mjs +67 -0
  115. package/dist/transformers/filters/index.mjs.map +1 -0
  116. package/dist/transformers/index.d.mts +11 -9
  117. package/dist/transformers/index.d.mts.map +1 -1
  118. package/dist/transformers/index.mjs +19 -11
  119. package/dist/transformers/index.mjs.map +1 -1
  120. package/dist/transformers/inlineCSS.d.mts +1 -14
  121. package/dist/transformers/inlineCSS.d.mts.map +1 -1
  122. package/dist/transformers/inlineCSS.mjs +25 -34
  123. package/dist/transformers/inlineCSS.mjs.map +1 -1
  124. package/dist/transformers/purgeCSS.d.mts.map +1 -1
  125. package/dist/transformers/purgeCSS.mjs +67 -1
  126. package/dist/transformers/purgeCSS.mjs.map +1 -1
  127. package/dist/transformers/sixHex.d.mts +16 -0
  128. package/dist/transformers/sixHex.d.mts.map +1 -0
  129. package/dist/transformers/sixHex.mjs +30 -0
  130. package/dist/transformers/sixHex.mjs.map +1 -0
  131. package/dist/transformers/tailwindcss.d.mts +6 -2
  132. package/dist/transformers/tailwindcss.d.mts.map +1 -1
  133. package/dist/transformers/tailwindcss.mjs +52 -28
  134. package/dist/transformers/tailwindcss.mjs.map +1 -1
  135. package/dist/types/config.d.mts +459 -17
  136. package/dist/types/config.d.mts.map +1 -1
  137. package/dist/types/index.d.mts +2 -2
  138. package/dist/utils/ast/serializer.d.mts +3 -2
  139. package/dist/utils/ast/serializer.d.mts.map +1 -1
  140. package/dist/utils/ast/serializer.mjs +24 -0
  141. package/dist/utils/ast/serializer.mjs.map +1 -1
  142. package/dist/utils/detect.d.mts +5 -0
  143. package/dist/utils/detect.d.mts.map +1 -0
  144. package/dist/utils/detect.mjs +11 -0
  145. package/dist/utils/detect.mjs.map +1 -0
  146. package/node_modules/@clack/core/CHANGELOG.md +87 -4
  147. package/node_modules/@clack/core/README.md +1 -1
  148. package/node_modules/@clack/core/dist/index.d.mts +186 -48
  149. package/node_modules/@clack/core/dist/index.mjs +10 -14
  150. package/node_modules/@clack/core/dist/index.mjs.map +1 -1
  151. package/node_modules/@clack/core/package.json +7 -9
  152. package/node_modules/@clack/prompts/CHANGELOG.md +171 -7
  153. package/node_modules/@clack/prompts/README.md +66 -3
  154. package/node_modules/@clack/prompts/dist/index.d.mts +302 -76
  155. package/node_modules/@clack/prompts/dist/index.mjs +134 -84
  156. package/node_modules/@clack/prompts/dist/index.mjs.map +1 -1
  157. package/node_modules/@clack/prompts/package.json +14 -10
  158. package/node_modules/citty/LICENSE +0 -15
  159. package/node_modules/citty/README.md +166 -69
  160. package/node_modules/citty/dist/index.d.mts +88 -56
  161. package/node_modules/citty/dist/index.mjs +399 -437
  162. package/node_modules/citty/package.json +28 -35
  163. package/node_modules/giget/README.md +59 -11
  164. package/node_modules/giget/dist/THIRD-PARTY-LICENSES.md +205 -0
  165. package/node_modules/giget/dist/_chunks/giget.mjs +508 -0
  166. package/node_modules/giget/dist/_chunks/libs/citty.mjs +269 -0
  167. package/node_modules/giget/dist/_chunks/libs/nypm.d.mts +1 -0
  168. package/node_modules/giget/dist/_chunks/libs/nypm.mjs +669 -0
  169. package/node_modules/giget/dist/_chunks/libs/tar.mjs +2931 -0
  170. package/node_modules/giget/dist/_chunks/rolldown-runtime.mjs +14 -0
  171. package/node_modules/giget/dist/cli.d.mts +1 -0
  172. package/node_modules/giget/dist/cli.mjs +89 -111
  173. package/node_modules/giget/dist/index.d.mts +46 -35
  174. package/node_modules/giget/dist/index.mjs +2 -22
  175. package/node_modules/giget/package.json +32 -45
  176. package/node_modules/maizzle/README.md +140 -0
  177. package/node_modules/maizzle/bin/maizzle.mjs +5 -0
  178. package/node_modules/maizzle/dist/commands/new.d.mts +7 -0
  179. package/node_modules/maizzle/dist/commands/new.mjs +278 -0
  180. package/node_modules/{@maizzle/cli → maizzle}/dist/index.d.mts +1 -1
  181. package/node_modules/maizzle/dist/index.mjs +44 -0
  182. package/node_modules/{commander → maizzle/node_modules/commander}/Readme.md +94 -67
  183. package/node_modules/{commander → maizzle/node_modules/commander}/lib/argument.js +5 -4
  184. package/node_modules/{commander → maizzle/node_modules/commander}/lib/command.js +154 -39
  185. package/node_modules/{commander → maizzle/node_modules/commander}/lib/help.js +77 -39
  186. package/node_modules/{commander → maizzle/node_modules/commander}/lib/option.js +16 -3
  187. package/node_modules/{commander → maizzle/node_modules/commander}/package-support.json +4 -1
  188. package/node_modules/{commander → maizzle/node_modules/commander}/package.json +8 -8
  189. package/node_modules/{commander → maizzle/node_modules/commander}/typings/index.d.ts +71 -3
  190. package/node_modules/{@maizzle/cli → maizzle}/package.json +13 -11
  191. package/node_modules/tinyexec/README.md +49 -3
  192. package/node_modules/tinyexec/dist/main.d.mts +25 -14
  193. package/node_modules/tinyexec/dist/main.mjs +148 -100
  194. package/node_modules/tinyexec/package.json +9 -8
  195. package/package.json +9 -4
  196. package/dist/server/ui/components/ui/resizable/ResizableHandle.vue +0 -30
  197. package/dist/server/ui/components/ui/resizable/ResizablePanel.vue +0 -21
  198. package/dist/server/ui/components/ui/resizable/ResizablePanelGroup.vue +0 -25
  199. package/dist/server/ui/components/ui/resizable/index.ts +0 -3
  200. package/node_modules/@clack/core/dist/index.cjs +0 -15
  201. package/node_modules/@clack/core/dist/index.cjs.map +0 -1
  202. package/node_modules/@clack/core/dist/index.d.cts +0 -211
  203. package/node_modules/@clack/core/dist/index.d.ts +0 -211
  204. package/node_modules/@clack/prompts/dist/index.cjs +0 -87
  205. package/node_modules/@clack/prompts/dist/index.cjs.map +0 -1
  206. package/node_modules/@clack/prompts/dist/index.d.cts +0 -165
  207. package/node_modules/@clack/prompts/dist/index.d.ts +0 -165
  208. package/node_modules/@maizzle/cli/README.md +0 -58
  209. package/node_modules/@maizzle/cli/dist/index.mjs +0 -42
  210. package/node_modules/citty/dist/index.cjs +0 -475
  211. package/node_modules/citty/dist/index.d.cts +0 -80
  212. package/node_modules/citty/dist/index.d.ts +0 -80
  213. package/node_modules/consola/LICENSE +0 -47
  214. package/node_modules/consola/README.md +0 -352
  215. package/node_modules/consola/basic.d.ts +0 -1
  216. package/node_modules/consola/browser.d.ts +0 -1
  217. package/node_modules/consola/core.d.ts +0 -1
  218. package/node_modules/consola/dist/basic.cjs +0 -32
  219. package/node_modules/consola/dist/basic.d.cts +0 -23
  220. package/node_modules/consola/dist/basic.d.mts +0 -21
  221. package/node_modules/consola/dist/basic.d.ts +0 -23
  222. package/node_modules/consola/dist/basic.mjs +0 -24
  223. package/node_modules/consola/dist/browser.cjs +0 -84
  224. package/node_modules/consola/dist/browser.d.cts +0 -23
  225. package/node_modules/consola/dist/browser.d.mts +0 -21
  226. package/node_modules/consola/dist/browser.d.ts +0 -23
  227. package/node_modules/consola/dist/browser.mjs +0 -76
  228. package/node_modules/consola/dist/chunks/prompt.cjs +0 -288
  229. package/node_modules/consola/dist/chunks/prompt.mjs +0 -280
  230. package/node_modules/consola/dist/core.cjs +0 -517
  231. package/node_modules/consola/dist/core.d.cts +0 -459
  232. package/node_modules/consola/dist/core.d.mts +0 -459
  233. package/node_modules/consola/dist/core.d.ts +0 -459
  234. package/node_modules/consola/dist/core.mjs +0 -512
  235. package/node_modules/consola/dist/index.cjs +0 -663
  236. package/node_modules/consola/dist/index.d.cts +0 -24
  237. package/node_modules/consola/dist/index.d.mts +0 -22
  238. package/node_modules/consola/dist/index.d.ts +0 -24
  239. package/node_modules/consola/dist/index.mjs +0 -651
  240. package/node_modules/consola/dist/shared/consola.DCGIlDNP.cjs +0 -75
  241. package/node_modules/consola/dist/shared/consola.DRwqZj3T.mjs +0 -72
  242. package/node_modules/consola/dist/shared/consola.DXBYu-KD.mjs +0 -288
  243. package/node_modules/consola/dist/shared/consola.DwRq1yyg.cjs +0 -312
  244. package/node_modules/consola/dist/utils.cjs +0 -64
  245. package/node_modules/consola/dist/utils.d.cts +0 -286
  246. package/node_modules/consola/dist/utils.d.mts +0 -286
  247. package/node_modules/consola/dist/utils.d.ts +0 -286
  248. package/node_modules/consola/dist/utils.mjs +0 -54
  249. package/node_modules/consola/lib/index.cjs +0 -10
  250. package/node_modules/consola/package.json +0 -136
  251. package/node_modules/consola/utils.d.ts +0 -1
  252. package/node_modules/create-maizzle/README.md +0 -86
  253. package/node_modules/create-maizzle/bin/create-maizzle.mjs +0 -4
  254. package/node_modules/create-maizzle/node_modules/@clack/core/CHANGELOG.md +0 -340
  255. package/node_modules/create-maizzle/node_modules/@clack/core/LICENSE +0 -9
  256. package/node_modules/create-maizzle/node_modules/@clack/core/README.md +0 -22
  257. package/node_modules/create-maizzle/node_modules/@clack/core/dist/index.d.mts +0 -349
  258. package/node_modules/create-maizzle/node_modules/@clack/core/dist/index.mjs +0 -11
  259. package/node_modules/create-maizzle/node_modules/@clack/core/dist/index.mjs.map +0 -1
  260. package/node_modules/create-maizzle/node_modules/@clack/core/package.json +0 -60
  261. package/node_modules/create-maizzle/node_modules/@clack/prompts/CHANGELOG.md +0 -576
  262. package/node_modules/create-maizzle/node_modules/@clack/prompts/LICENSE +0 -9
  263. package/node_modules/create-maizzle/node_modules/@clack/prompts/README.md +0 -270
  264. package/node_modules/create-maizzle/node_modules/@clack/prompts/dist/index.d.mts +0 -391
  265. package/node_modules/create-maizzle/node_modules/@clack/prompts/dist/index.mjs +0 -137
  266. package/node_modules/create-maizzle/node_modules/@clack/prompts/dist/index.mjs.map +0 -1
  267. package/node_modules/create-maizzle/node_modules/@clack/prompts/package.json +0 -65
  268. package/node_modules/create-maizzle/package.json +0 -47
  269. package/node_modules/create-maizzle/src/index.js +0 -242
  270. package/node_modules/defu/LICENSE +0 -21
  271. package/node_modules/defu/README.md +0 -171
  272. package/node_modules/defu/dist/defu.cjs +0 -77
  273. package/node_modules/defu/dist/defu.d.cts +0 -31
  274. package/node_modules/defu/dist/defu.d.mts +0 -29
  275. package/node_modules/defu/dist/defu.d.ts +0 -31
  276. package/node_modules/defu/dist/defu.mjs +0 -69
  277. package/node_modules/defu/lib/defu.cjs +0 -10
  278. package/node_modules/defu/lib/defu.d.cts +0 -12
  279. package/node_modules/defu/package.json +0 -48
  280. package/node_modules/giget/dist/shared/giget.OCaTp9b-.mjs +0 -468
  281. package/node_modules/node-fetch-native/LICENSE +0 -114
  282. package/node_modules/node-fetch-native/README.md +0 -225
  283. package/node_modules/node-fetch-native/dist/chunks/multipart-parser.cjs +0 -2
  284. package/node_modules/node-fetch-native/dist/chunks/multipart-parser.mjs +0 -2
  285. package/node_modules/node-fetch-native/dist/index.cjs +0 -1
  286. package/node_modules/node-fetch-native/dist/index.mjs +0 -1
  287. package/node_modules/node-fetch-native/dist/native.cjs +0 -1
  288. package/node_modules/node-fetch-native/dist/native.mjs +0 -1
  289. package/node_modules/node-fetch-native/dist/node.cjs +0 -19
  290. package/node_modules/node-fetch-native/dist/node.mjs +0 -19
  291. package/node_modules/node-fetch-native/dist/polyfill.cjs +0 -1
  292. package/node_modules/node-fetch-native/dist/polyfill.mjs +0 -1
  293. package/node_modules/node-fetch-native/dist/proxy-stub.cjs +0 -1
  294. package/node_modules/node-fetch-native/dist/proxy-stub.mjs +0 -1
  295. package/node_modules/node-fetch-native/dist/proxy.cjs +0 -58
  296. package/node_modules/node-fetch-native/dist/shared/node-fetch-native.DfbY2q-x.mjs +0 -1
  297. package/node_modules/node-fetch-native/dist/shared/node-fetch-native.DhEqb06g.cjs +0 -1
  298. package/node_modules/node-fetch-native/index.d.ts +0 -1
  299. package/node_modules/node-fetch-native/lib/empty.cjs +0 -0
  300. package/node_modules/node-fetch-native/lib/empty.mjs +0 -0
  301. package/node_modules/node-fetch-native/lib/index.cjs +0 -11
  302. package/node_modules/node-fetch-native/lib/index.d.cts +0 -10
  303. package/node_modules/node-fetch-native/lib/index.d.mts +0 -10
  304. package/node_modules/node-fetch-native/lib/index.d.ts +0 -10
  305. package/node_modules/node-fetch-native/lib/native.cjs +0 -11
  306. package/node_modules/node-fetch-native/lib/polyfill.d.cts +0 -1
  307. package/node_modules/node-fetch-native/lib/polyfill.d.mts +0 -1
  308. package/node_modules/node-fetch-native/lib/polyfill.d.ts +0 -1
  309. package/node_modules/node-fetch-native/lib/proxy.d.ts +0 -32
  310. package/node_modules/node-fetch-native/node.d.ts +0 -1
  311. package/node_modules/node-fetch-native/package.json +0 -138
  312. package/node_modules/node-fetch-native/polyfill.d.ts +0 -1
  313. package/node_modules/node-fetch-native/proxy.d.ts +0 -1
  314. package/node_modules/nypm/node_modules/citty/LICENSE +0 -21
  315. package/node_modules/nypm/node_modules/citty/README.md +0 -231
  316. package/node_modules/nypm/node_modules/citty/dist/index.d.mts +0 -112
  317. package/node_modules/nypm/node_modules/citty/dist/index.mjs +0 -425
  318. package/node_modules/nypm/node_modules/citty/package.json +0 -42
  319. /package/node_modules/{nypm/node_modules/citty → citty}/dist/THIRD-PARTY-LICENSES.md +0 -0
  320. /package/node_modules/{nypm/node_modules/citty → citty}/dist/_chunks/libs/scule.mjs +0 -0
  321. /package/node_modules/{@maizzle/cli → maizzle}/LICENSE +0 -0
  322. /package/node_modules/{@maizzle/cli → maizzle}/dist/commands/make/component.d.mts +0 -0
  323. /package/node_modules/{@maizzle/cli → maizzle}/dist/commands/make/component.mjs +0 -0
  324. /package/node_modules/{@maizzle/cli → maizzle}/dist/commands/make/config.d.mts +0 -0
  325. /package/node_modules/{@maizzle/cli → maizzle}/dist/commands/make/config.mjs +0 -0
  326. /package/node_modules/{@maizzle/cli → maizzle}/dist/commands/make/layout.d.mts +0 -0
  327. /package/node_modules/{@maizzle/cli → maizzle}/dist/commands/make/layout.mjs +0 -0
  328. /package/node_modules/{@maizzle/cli → maizzle}/dist/commands/make/scaffold.d.mts +0 -0
  329. /package/node_modules/{@maizzle/cli → maizzle}/dist/commands/make/scaffold.mjs +0 -0
  330. /package/node_modules/{@maizzle/cli → maizzle}/dist/commands/make/stubs/component.vue +0 -0
  331. /package/node_modules/{@maizzle/cli → maizzle}/dist/commands/make/stubs/config.ts +0 -0
  332. /package/node_modules/{@maizzle/cli → maizzle}/dist/commands/make/stubs/layout.vue +0 -0
  333. /package/node_modules/{@maizzle/cli → maizzle}/dist/commands/make/stubs/template.vue +0 -0
  334. /package/node_modules/{@maizzle/cli → maizzle}/dist/commands/make/template.d.mts +0 -0
  335. /package/node_modules/{@maizzle/cli → maizzle}/dist/commands/make/template.mjs +0 -0
  336. /package/node_modules/{commander → maizzle/node_modules/commander}/LICENSE +0 -0
  337. /package/node_modules/{commander → maizzle/node_modules/commander}/esm.mjs +0 -0
  338. /package/node_modules/{commander → maizzle/node_modules/commander}/index.js +0 -0
  339. /package/node_modules/{commander → maizzle/node_modules/commander}/lib/error.js +0 -0
  340. /package/node_modules/{commander → maizzle/node_modules/commander}/lib/suggestSimilar.js +0 -0
  341. /package/node_modules/{commander → maizzle/node_modules/commander}/typings/esm.d.mts +0 -0
package/dist/serve.mjs CHANGED
@@ -1,9 +1,12 @@
1
+ import { __toESM } from "./_virtual/_rolldown/runtime.mjs";
1
2
  import { resolveConfig } from "./config/index.mjs";
2
3
  import { runTransformers } from "./transformers/index.mjs";
3
4
  import { createRenderer } from "./render/createRenderer.mjs";
4
5
  import { createPlaintext } from "./plaintext.mjs";
6
+ import { require_picomatch } from "./node_modules/picomatch/index.mjs";
5
7
  import { serveCompatibility } from "./server/compatibility.mjs";
6
8
  import { serveLint } from "./server/linter.mjs";
9
+ import { sendEmail } from "./server/email.mjs";
7
10
  import { createRequire } from "node:module";
8
11
  import { readFileSync } from "node:fs";
9
12
  import { basename, dirname, resolve } from "node:path";
@@ -15,10 +18,15 @@ import tailwindcss from "@tailwindcss/vite";
15
18
  import { createHighlighter } from "shiki";
16
19
 
17
20
  //#region src/serve.ts
21
+ var import_picomatch = /* @__PURE__ */ __toESM(require_picomatch(), 1);
18
22
  const devUIDir = resolve(dirname(fileURLToPath(import.meta.url)), "server/ui");
19
23
  const require = createRequire(import.meta.url);
20
- const frameworkNodeModules = resolve(dirname(require.resolve("vue/package.json")), "..");
21
- const vuePkgDir = dirname(require.resolve("vue/package.json"));
24
+ const pkg = (name) => {
25
+ const resolved = require.resolve(name);
26
+ const marker = `node_modules/${name}`;
27
+ const idx = resolved.lastIndexOf(marker);
28
+ return resolved.slice(0, idx + marker.length);
29
+ };
22
30
  /**
23
31
  * Start the Maizzle dev server.
24
32
  *
@@ -32,9 +40,12 @@ async function serve(options = {}) {
32
40
  const start = performance.now();
33
41
  let config = await resolveConfig(options.config);
34
42
  const port = config.server?.port ?? 3e3;
35
- const renderer = await createRenderer({
43
+ let renderer = await createRenderer({
36
44
  dts: true,
37
- markdown: config.markdown
45
+ markdown: config.markdown,
46
+ root: config.root,
47
+ componentDirs: [config.components?.source ?? []].flat(),
48
+ vite: config.vite
38
49
  });
39
50
  const server = await createServer({
40
51
  configFile: false,
@@ -52,40 +63,21 @@ async function serve(options = {}) {
52
63
  },
53
64
  {
54
65
  find: "vue",
55
- replacement: resolve(vuePkgDir, "dist/vue.runtime.esm-bundler.js")
66
+ replacement: resolve(pkg("vue"), "dist/vue.runtime.esm-bundler.js")
56
67
  },
57
- {
58
- find: "vue-router",
59
- replacement: resolve(frameworkNodeModules, "vue-router")
60
- },
61
- {
62
- find: "reka-ui",
63
- replacement: resolve(frameworkNodeModules, "reka-ui")
64
- },
65
- {
66
- find: "@vueuse/core",
67
- replacement: resolve(frameworkNodeModules, "@vueuse/core")
68
- },
69
- {
70
- find: "@vueuse/shared",
71
- replacement: resolve(frameworkNodeModules, "@vueuse/shared")
72
- },
73
- {
74
- find: "lucide-vue-next",
75
- replacement: resolve(frameworkNodeModules, "lucide-vue-next")
76
- },
77
- {
78
- find: "class-variance-authority",
79
- replacement: resolve(frameworkNodeModules, "class-variance-authority")
80
- },
81
- {
82
- find: "clsx",
83
- replacement: resolve(frameworkNodeModules, "clsx")
84
- },
85
- {
86
- find: "tailwind-merge",
87
- replacement: resolve(frameworkNodeModules, "tailwind-merge")
88
- }
68
+ ...[
69
+ "vue-router",
70
+ "reka-ui",
71
+ "@vueuse/core",
72
+ "@vueuse/shared",
73
+ "lucide-vue-next",
74
+ "class-variance-authority",
75
+ "clsx",
76
+ "tailwind-merge"
77
+ ].map((name) => ({
78
+ find: name,
79
+ replacement: pkg(name)
80
+ }))
89
81
  ]
90
82
  },
91
83
  cacheDir: resolve(devUIDir, ".vite"),
@@ -108,8 +100,19 @@ async function serve(options = {}) {
108
100
  host: options.host,
109
101
  fs: { allow: [
110
102
  process.cwd(),
103
+ config.root ?? process.cwd(),
111
104
  devUIDir,
112
- frameworkNodeModules
105
+ ...[
106
+ "vue",
107
+ "vue-router",
108
+ "reka-ui",
109
+ "@vueuse/core",
110
+ "@vueuse/shared",
111
+ "lucide-vue-next",
112
+ "class-variance-authority",
113
+ "clsx",
114
+ "tailwind-merge"
115
+ ].map(pkg)
113
116
  ] }
114
117
  },
115
118
  customLogger: customLogger()
@@ -143,26 +146,45 @@ function maizzleDevPlugin(config, renderer, configInput) {
143
146
  "maizzle.config.js",
144
147
  "maizzle.config.ts",
145
148
  "tailwind.config.js",
146
- "tailwind.config.ts"
149
+ "tailwind.config.ts",
150
+ "locales/**"
147
151
  ];
148
152
  const userWatchPaths = config.server?.watch ?? [];
149
153
  const watchPaths = [...defaultWatchPaths, ...userWatchPaths];
154
+ const isWatchedFile = (0, import_picomatch.default)(watchPaths);
150
155
  for (const watchPath of watchPaths) server.watcher.add(watchPath);
151
- server.watcher.on("add", (file) => {
152
- if (isTemplateFile(file)) server.ws.send({
153
- type: "custom",
154
- event: "maizzle:templates-changed"
155
- });
156
+ server.watcher.on("add", async (file) => {
157
+ if (isTemplateFile(file)) {
158
+ await renderer.invalidateAll();
159
+ server.ws.send({
160
+ type: "custom",
161
+ event: "maizzle:templates-changed"
162
+ });
163
+ }
156
164
  });
157
- server.watcher.on("unlink", (file) => {
158
- if (isTemplateFile(file)) server.ws.send({
159
- type: "custom",
160
- event: "maizzle:templates-changed"
161
- });
165
+ server.watcher.on("unlink", async (file) => {
166
+ if (isTemplateFile(file)) {
167
+ await renderer.invalidateAll();
168
+ server.ws.send({
169
+ type: "custom",
170
+ event: "maizzle:templates-changed"
171
+ });
172
+ }
162
173
  });
163
174
  server.watcher.on("change", async (file) => {
164
- if (watchPaths.some((p) => file.endsWith(p))) config = await resolveConfig(configInput);
165
- if (isTemplateFile(file) || watchPaths.some((p) => file.endsWith(p))) server.ws.send({
175
+ if (isWatchedFile(file)) {
176
+ config = await resolveConfig(configInput);
177
+ await renderer.close();
178
+ renderer = await createRenderer({
179
+ dts: true,
180
+ markdown: config.markdown,
181
+ root: config.root,
182
+ componentDirs: [config.components?.source ?? []].flat(),
183
+ vite: config.vite
184
+ });
185
+ }
186
+ await renderer.invalidateAll();
187
+ if (isTemplateFile(file) || isWatchedFile(file)) server.ws.send({
166
188
  type: "custom",
167
189
  event: "maizzle:template-updated",
168
190
  data: { file }
@@ -173,11 +195,13 @@ function maizzleDevPlugin(config, renderer, configInput) {
173
195
  if (url === "/__maizzle/templates") return serveTemplateList(config, res);
174
196
  if (url.startsWith("/__maizzle/render/")) return await serveRenderedTemplate(url, config, renderer, res);
175
197
  if (url.startsWith("/__maizzle/source/")) return await serveHighlightedSource(url, config, renderer, res);
176
- if (url.startsWith("/__maizzle/compatibility/")) return await serveCompatibility(url, config, res);
177
- if (url.startsWith("/__maizzle/lint/")) return await serveLint(url, config, res);
198
+ if (url === "/__maizzle/compatibility" && req.method === "POST") return await serveCompatibility(req, res);
199
+ if (url.startsWith("/__maizzle/lint/")) return serveLint(url, res);
178
200
  if (url.startsWith("/__maizzle/vue-source/")) return await serveVueSource(url, config, res);
179
201
  if (url.startsWith("/__maizzle/plaintext/")) return await servePlaintext(url, config, renderer, res);
180
202
  if (url.startsWith("/__maizzle/stats/")) return await serveStats(url, config, renderer, res);
203
+ if (url.startsWith("/__maizzle/email/") && req.method === "POST") return await serveEmailEndpoint(url, req, res, config, renderer);
204
+ if (url === "/__maizzle/email-config") return serveEmailConfig(config, res);
181
205
  next();
182
206
  });
183
207
  return () => {
@@ -226,12 +250,13 @@ async function serveRenderedTemplate(url, config, renderer, res) {
226
250
  }
227
251
  try {
228
252
  const absolutePath = resolve(match);
229
- await renderer.invalidate(absolutePath);
253
+ await renderer.invalidateAll();
230
254
  const rendered = await renderer.render(absolutePath, config);
231
255
  let html = rendered.html;
232
256
  const templateConfig = rendered.templateConfig;
233
- html = await runTransformers(html, templateConfig, absolutePath);
234
- html = `${rendered.doctype ?? templateConfig.doctype ?? "<!DOCTYPE html>"}\n${html}`;
257
+ const doctype = rendered.doctype ?? templateConfig.doctype ?? "<!DOCTYPE html>";
258
+ html = await runTransformers(html, templateConfig, absolutePath, doctype);
259
+ html = `${doctype}\n${html}`;
235
260
  res.setHeader("Content-Type", "text/html");
236
261
  res.end(html);
237
262
  } catch (error) {
@@ -257,12 +282,13 @@ async function serveHighlightedSource(url, config, renderer, res) {
257
282
  }
258
283
  try {
259
284
  const absolutePath = resolve(match);
260
- await renderer.invalidate(absolutePath);
285
+ await renderer.invalidateAll();
261
286
  const rendered = await renderer.render(absolutePath, config);
262
287
  let html = rendered.html;
263
288
  const templateConfig = rendered.templateConfig;
264
- html = await runTransformers(html, templateConfig, absolutePath);
265
- html = `${rendered.doctype ?? templateConfig.doctype ?? "<!DOCTYPE html>"}\n${html}`;
289
+ const doctype = rendered.doctype ?? templateConfig.doctype ?? "<!DOCTYPE html>";
290
+ html = await runTransformers(html, templateConfig, absolutePath, doctype);
291
+ html = `${doctype}\n${html}`;
266
292
  const highlighted = (await getHighlighter()).codeToHtml(html, {
267
293
  lang: "html",
268
294
  theme: "laserwave",
@@ -312,11 +338,12 @@ async function servePlaintext(url, config, renderer, res) {
312
338
  }
313
339
  try {
314
340
  const absolutePath = resolve(match);
315
- await renderer.invalidate(absolutePath);
341
+ await renderer.invalidateAll();
316
342
  const rendered = await renderer.render(absolutePath, config);
317
343
  let html = rendered.html;
318
344
  const templateConfig = rendered.templateConfig;
319
- html = await runTransformers(html, templateConfig, absolutePath);
345
+ const doctype = rendered.doctype ?? templateConfig.doctype ?? "<!DOCTYPE html>";
346
+ html = await runTransformers(html, templateConfig, absolutePath, doctype);
320
347
  const plaintext = createPlaintext(html);
321
348
  res.setHeader("Content-Type", "text/plain");
322
349
  res.end(plaintext);
@@ -356,11 +383,12 @@ async function serveStats(url, config, renderer, res) {
356
383
  }
357
384
  try {
358
385
  const absolutePath = resolve(match);
359
- await renderer.invalidate(absolutePath);
386
+ await renderer.invalidateAll();
360
387
  const rendered = await renderer.render(absolutePath, config);
361
388
  let html = rendered.html;
362
389
  const templateConfig = rendered.templateConfig;
363
- html = await runTransformers(html, templateConfig, absolutePath);
390
+ const doctype = rendered.doctype ?? templateConfig.doctype ?? "<!DOCTYPE html>";
391
+ html = await runTransformers(html, templateConfig, absolutePath, doctype);
364
392
  const sizeBytes = Buffer.byteLength(html, "utf-8");
365
393
  const totalImages = (html.match(/<img\b[^>]*>/gi) || []).length + (html.match(/url\s*\([^)]+\)/gi) || []).length;
366
394
  const links = (html.match(/<a\b[^>]*href\s*=/gi) || []).length;
@@ -378,6 +406,74 @@ async function serveStats(url, config, renderer, res) {
378
406
  res.end(JSON.stringify({ error: error.message }));
379
407
  }
380
408
  }
409
+ async function serveEmailEndpoint(url, req, res, config, renderer) {
410
+ const templateSlug = url.replace("/__maizzle/email/", "").replace(/\?.*$/, "");
411
+ const match = (await glob(config.content ?? ["emails/**/*.vue"])).find((t) => t.replace(/\.(vue|md)$/, "") === templateSlug);
412
+ if (!match) {
413
+ res.statusCode = 404;
414
+ res.end(JSON.stringify({
415
+ success: false,
416
+ message: "Template not found"
417
+ }));
418
+ return;
419
+ }
420
+ let body = "";
421
+ for await (const chunk of req) body += chunk;
422
+ let payload;
423
+ try {
424
+ payload = JSON.parse(body);
425
+ } catch {
426
+ res.statusCode = 400;
427
+ res.end(JSON.stringify({
428
+ success: false,
429
+ message: "Invalid JSON"
430
+ }));
431
+ return;
432
+ }
433
+ if (!payload.to?.length) {
434
+ res.statusCode = 400;
435
+ res.end(JSON.stringify({
436
+ success: false,
437
+ message: "Missing recipients"
438
+ }));
439
+ return;
440
+ }
441
+ try {
442
+ const absolutePath = resolve(match);
443
+ await renderer.invalidateAll();
444
+ const rendered = await renderer.render(absolutePath, config);
445
+ let html = rendered.html;
446
+ const templateConfig = rendered.templateConfig;
447
+ const doctype = rendered.doctype ?? templateConfig.doctype ?? "<!DOCTYPE html>";
448
+ html = await runTransformers(html, templateConfig, absolutePath, doctype);
449
+ html = `${doctype}\n${html}`;
450
+ const text = createPlaintext(html);
451
+ const result = await sendEmail({
452
+ to: payload.to,
453
+ subject: payload.subject,
454
+ html,
455
+ text
456
+ }, config, templateConfig);
457
+ res.setHeader("Content-Type", "application/json");
458
+ res.end(JSON.stringify(result));
459
+ } catch (error) {
460
+ res.statusCode = 500;
461
+ res.end(JSON.stringify({
462
+ success: false,
463
+ message: error.message
464
+ }));
465
+ }
466
+ }
467
+ function serveEmailConfig(config, res) {
468
+ const emailConfig = config.server?.email;
469
+ res.setHeader("Content-Type", "application/json");
470
+ res.end(JSON.stringify({
471
+ to: emailConfig?.to ? Array.isArray(emailConfig.to) ? emailConfig.to : [emailConfig.to] : [],
472
+ from: emailConfig?.from ?? "",
473
+ subject: emailConfig?.subject ?? "",
474
+ hasTransport: !!emailConfig?.transport
475
+ }));
476
+ }
381
477
  function printBanner(server, startupTime) {
382
478
  const info = server.config.logger.info;
383
479
  const time = startupTime ?? server._maizzleStartupTime;
@@ -1 +1 @@
1
- {"version":3,"file":"serve.mjs","names":[],"sources":["../src/serve.ts"],"sourcesContent":["import { readFileSync } from 'node:fs'\nimport { dirname, resolve, basename } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { createRequire } from 'node:module'\nimport { createServer, createLogger, type ViteDevServer } from 'vite'\nimport vue from '@vitejs/plugin-vue'\nimport tailwindcss from '@tailwindcss/vite'\nimport { glob } from 'tinyglobby'\nimport { createHighlighter, type Highlighter } from 'shiki'\nimport { createPlaintext } from './plaintext.ts'\nimport { resolveConfig } from './config/index.ts'\nimport { runTransformers } from './transformers/index.ts'\nimport { createRenderer, type Renderer } from './render/createRenderer.ts'\nimport { serveCompatibility } from './server/compatibility.ts'\nimport { serveLint } from './server/linter.ts'\nimport type { MaizzleConfig } from './types/index.ts'\n\nconst __dirname = dirname(fileURLToPath(import.meta.url))\nconst devUIDir = resolve(__dirname, 'server/ui')\n\nconst require = createRequire(import.meta.url)\nconst frameworkNodeModules = resolve(dirname(require.resolve('vue/package.json')), '..')\nconst vuePkgDir = dirname(require.resolve('vue/package.json'))\n\nexport interface ServeOptions {\n config?: Partial<MaizzleConfig> | string\n /** Expose the server on the network (e.g. --host) */\n host?: boolean | string\n /** When true, suppresses the banner/URL output (used by the Vite plugin, which prints its own) */\n silent?: boolean\n}\n\n/**\n * Start the Maizzle dev server.\n *\n * Creates two things:\n * 1. A Vite dev server for the dev UI (sidebar + preview, with Vue + Tailwind for the UI itself)\n * 2. A Renderer instance for SSR rendering email templates\n *\n * Template rendering goes through the Renderer, not the Vite dev server.\n */\nexport async function serve(options: ServeOptions = {}) {\n const start = performance.now()\n\n let config = await resolveConfig(options.config)\n const port = config.server?.port ?? 3000\n\n // Create a renderer for SSR rendering email templates (with dts for dev)\n const renderer = await createRenderer({ dts: true, markdown: config.markdown })\n\n const server = await createServer({\n configFile: false,\n plugins: [\n // Vue and Tailwind are only for the dev UI SPA, not for email templates\n vue(),\n tailwindcss(),\n maizzleDevPlugin(config, renderer, options.config),\n ],\n resolve: {\n dedupe: ['vue'],\n alias: [\n { find: '@', replacement: devUIDir },\n { find: 'vue', replacement: resolve(vuePkgDir, 'dist/vue.runtime.esm-bundler.js') },\n { find: 'vue-router', replacement: resolve(frameworkNodeModules, 'vue-router') },\n { find: 'reka-ui', replacement: resolve(frameworkNodeModules, 'reka-ui') },\n { find: '@vueuse/core', replacement: resolve(frameworkNodeModules, '@vueuse/core') },\n { find: '@vueuse/shared', replacement: resolve(frameworkNodeModules, '@vueuse/shared') },\n { find: 'lucide-vue-next', replacement: resolve(frameworkNodeModules, 'lucide-vue-next') },\n { find: 'class-variance-authority', replacement: resolve(frameworkNodeModules, 'class-variance-authority') },\n { find: 'clsx', replacement: resolve(frameworkNodeModules, 'clsx') },\n { find: 'tailwind-merge', replacement: resolve(frameworkNodeModules, 'tailwind-merge') },\n ],\n },\n cacheDir: resolve(devUIDir, '.vite'),\n optimizeDeps: {\n noDiscovery: true,\n include: [\n 'vue',\n 'vue-router',\n 'lucide-vue-next',\n '@vueuse/core',\n '@vueuse/shared',\n 'reka-ui',\n 'class-variance-authority',\n 'clsx',\n 'tailwind-merge',\n ],\n },\n server: {\n port,\n host: options.host,\n fs: {\n allow: [process.cwd(), devUIDir, frameworkNodeModules],\n },\n },\n customLogger: customLogger(),\n })\n\n // Store renderer ref on server for cleanup\n const originalClose = server.close.bind(server)\n server.close = async () => {\n await renderer.close()\n return originalClose()\n }\n\n await server.listen()\n\n const startupTime = Math.round(performance.now() - start)\n\n if (!options.silent) {\n printBanner(server, startupTime)\n }\n\n // Expose startup time so the plugin can print it later\n ; (server as any)._maizzleStartupTime = startupTime\n\n return server\n}\n\n/**\n * Internal Vite plugin that adds Maizzle middleware and file watching to the dev UI server.\n */\nfunction maizzleDevPlugin(\n config: MaizzleConfig,\n renderer: Renderer,\n configInput: Partial<MaizzleConfig> | string | undefined,\n) {\n return {\n name: 'maizzle:dev',\n enforce: 'pre' as const,\n\n hotUpdate: {\n order: 'pre' as const,\n handler({ file }: { file: string }) {\n // Prevent Tailwind/Vue from triggering a full reload for email template files.\n // Maizzle handles these via custom HMR events in the watcher below.\n if (isTemplateFile(file)) {\n return []\n }\n },\n },\n\n configureServer(server: ViteDevServer) {\n // File watching\n const defaultWatchPaths = [\n 'maizzle.config.js',\n 'maizzle.config.ts',\n 'tailwind.config.js',\n 'tailwind.config.ts',\n ]\n\n const userWatchPaths = config.server?.watch ?? []\n const watchPaths = [...defaultWatchPaths, ...userWatchPaths]\n\n for (const watchPath of watchPaths) {\n server.watcher.add(watchPath)\n }\n\n server.watcher.on('add', (file) => {\n if (isTemplateFile(file)) {\n server.ws.send({ type: 'custom', event: 'maizzle:templates-changed' })\n }\n })\n\n server.watcher.on('unlink', (file) => {\n if (isTemplateFile(file)) {\n server.ws.send({ type: 'custom', event: 'maizzle:templates-changed' })\n }\n })\n\n server.watcher.on('change', async (file) => {\n if (watchPaths.some(p => file.endsWith(p))) {\n config = await resolveConfig(configInput)\n }\n\n if (\n isTemplateFile(file)\n || watchPaths.some(p => file.endsWith(p))\n ) {\n server.ws.send({ type: 'custom', event: 'maizzle:template-updated', data: { file } })\n }\n })\n\n // API middleware (before Vite's middleware)\n server.middlewares.use(async (req: any, res: any, next: any) => {\n const url = req.url || '/'\n\n if (url === '/__maizzle/templates') {\n return serveTemplateList(config, res)\n }\n\n if (url.startsWith('/__maizzle/render/')) {\n return await serveRenderedTemplate(url, config, renderer, res)\n }\n\n if (url.startsWith('/__maizzle/source/')) {\n return await serveHighlightedSource(url, config, renderer, res)\n }\n\n if (url.startsWith('/__maizzle/compatibility/')) {\n return await serveCompatibility(url, config, res)\n }\n\n if (url.startsWith('/__maizzle/lint/')) {\n return await serveLint(url, config, res)\n }\n\n if (url.startsWith('/__maizzle/vue-source/')) {\n return await serveVueSource(url, config, res)\n }\n\n if (url.startsWith('/__maizzle/plaintext/')) {\n return await servePlaintext(url, config, renderer, res)\n }\n\n if (url.startsWith('/__maizzle/stats/')) {\n return await serveStats(url, config, renderer, res)\n }\n\n next()\n })\n\n // Dev UI fallback (after Vite's middleware)\n return () => {\n server.middlewares.use(async (req: any, res: any, next: any) => {\n if (isNavigationRequest(req)) {\n return await serveDevUI(server, res, req.url || '/')\n }\n\n next()\n })\n }\n },\n }\n}\n\nfunction isTemplateFile(file: string): boolean {\n return (file.endsWith('.vue') || file.endsWith('.md')) && !file.includes('server/ui')\n}\n\nfunction isNavigationRequest(req: any): boolean {\n const accept = req.headers?.accept || ''\n return req.method === 'GET' && accept.includes('text/html')\n}\n\nasync function serveDevUI(server: ViteDevServer, res: any, url: string) {\n let indexHtml = readFileSync(resolve(devUIDir, 'index.html'), 'utf-8')\n\n indexHtml = indexHtml.replace('./main.ts', `/@fs/${resolve(devUIDir, 'main.ts')}`)\n indexHtml = indexHtml.replace('./favicon.svg', `/@fs/${resolve(devUIDir, 'favicon.svg')}`)\n\n const transformed = await server.transformIndexHtml(url, indexHtml)\n\n res.setHeader('Content-Type', 'text/html')\n res.end(transformed)\n}\n\nasync function serveTemplateList(config: MaizzleConfig, res: any) {\n const contentPatterns = config.content ?? ['emails/**/*.vue']\n const templates = await glob(contentPatterns)\n\n const data = templates.map(t => ({\n name: basename(t).replace(/\\.(vue|md)$/, ''),\n path: t,\n href: '/' + t.replace(/\\.(vue|md)$/, ''),\n }))\n\n res.setHeader('Content-Type', 'application/json')\n res.end(JSON.stringify(data))\n}\n\n/**\n * SSR render a .vue template using the Renderer (not the dev UI server).\n */\nasync function serveRenderedTemplate(url: string, config: MaizzleConfig, renderer: Renderer, res: any) {\n const templateSlug = url.replace('/__maizzle/render/', '').replace(/\\?.*$/, '')\n\n const contentPatterns = config.content ?? ['emails/**/*.vue']\n const templates = await glob(contentPatterns)\n const match = templates.find(t => t.replace(/\\.(vue|md)$/, '') === templateSlug)\n\n if (!match) {\n res.statusCode = 404\n res.end('Template not found')\n return\n }\n\n try {\n const absolutePath = resolve(match)\n\n // Invalidate the module so changes are picked up\n await renderer.invalidate(absolutePath)\n\n const rendered = await renderer.render(absolutePath, config)\n let html = rendered.html\n\n const templateConfig = rendered.templateConfig\n\n html = await runTransformers(html, templateConfig, absolutePath)\n\n const doctype = rendered.doctype ?? templateConfig.doctype ?? '<!DOCTYPE html>'\n html = `${doctype}\\n${html}`\n\n res.setHeader('Content-Type', 'text/html')\n res.end(html)\n } catch (error: any) {\n res.statusCode = 500\n res.end(`<pre>${error.stack || error.message}</pre>`)\n }\n}\n\nlet highlighter: Highlighter | null = null\n\nasync function getHighlighter() {\n if (!highlighter) {\n highlighter = await createHighlighter({\n themes: ['laserwave'],\n langs: ['html', 'vue'],\n })\n }\n return highlighter\n}\n\nasync function serveHighlightedSource(url: string, config: MaizzleConfig, renderer: Renderer, res: any) {\n const templateSlug = url.replace('/__maizzle/source/', '').replace(/\\?.*$/, '')\n\n const contentPatterns = config.content ?? ['emails/**/*.vue']\n const templates = await glob(contentPatterns)\n const match = templates.find(t => t.replace(/\\.(vue|md)$/, '') === templateSlug)\n\n if (!match) {\n res.statusCode = 404\n res.end('Template not found')\n return\n }\n\n try {\n const absolutePath = resolve(match)\n\n await renderer.invalidate(absolutePath)\n\n const rendered = await renderer.render(absolutePath, config)\n let html = rendered.html\n\n const templateConfig = rendered.templateConfig\n html = await runTransformers(html, templateConfig, absolutePath)\n\n const doctype = rendered.doctype ?? templateConfig.doctype ?? '<!DOCTYPE html>'\n html = `${doctype}\\n${html}`\n\n const hl = await getHighlighter()\n const highlighted = hl.codeToHtml(html, {\n lang: 'html',\n theme: 'laserwave',\n transformers: [{\n line(node, line) {\n node.properties['data-line'] = line\n },\n }],\n })\n\n res.setHeader('Content-Type', 'text/html')\n res.end(highlighted)\n } catch (error: any) {\n res.statusCode = 500\n res.end(`<pre>${error.stack || error.message}</pre>`)\n }\n}\n\nasync function serveVueSource(url: string, config: MaizzleConfig, res: any) {\n const templateSlug = url.replace('/__maizzle/vue-source/', '').replace(/\\?.*$/, '')\n\n const contentPatterns = config.content ?? ['emails/**/*.vue']\n const templates = await glob(contentPatterns)\n const match = templates.find(t => t.replace(/\\.(vue|md)$/, '') === templateSlug)\n\n if (!match) {\n res.statusCode = 404\n res.end('Template not found')\n return\n }\n\n try {\n const source = readFileSync(resolve(match), 'utf-8')\n const lang = match.endsWith('.md') ? 'html' : 'vue'\n\n const hl = await getHighlighter()\n const highlighted = hl.codeToHtml(source, {\n lang,\n theme: 'laserwave',\n transformers: [{\n line(node, line) {\n node.properties['data-line'] = line\n },\n }],\n })\n\n res.setHeader('Content-Type', 'text/html')\n res.end(highlighted)\n } catch (error: any) {\n res.statusCode = 500\n res.end(`<pre>${error.stack || error.message}</pre>`)\n }\n}\n\nasync function servePlaintext(url: string, config: MaizzleConfig, renderer: Renderer, res: any) {\n const templateSlug = url.replace('/__maizzle/plaintext/', '').replace(/\\?.*$/, '')\n\n const contentPatterns = config.content ?? ['emails/**/*.vue']\n const templates = await glob(contentPatterns)\n const match = templates.find(t => t.replace(/\\.(vue|md)$/, '') === templateSlug)\n\n if (!match) {\n res.statusCode = 404\n res.end('Template not found')\n return\n }\n\n try {\n const absolutePath = resolve(match)\n await renderer.invalidate(absolutePath)\n\n const rendered = await renderer.render(absolutePath, config)\n let html = rendered.html\n const templateConfig = rendered.templateConfig\n html = await runTransformers(html, templateConfig, absolutePath)\n\n const plaintext = createPlaintext(html)\n\n res.setHeader('Content-Type', 'text/plain')\n res.end(plaintext)\n } catch (error: any) {\n res.statusCode = 500\n res.end(error.message)\n }\n}\n\nfunction humanFileSize(bytes: number, si = false, dp = 2) {\n const threshold = si ? 1000 : 1024\n\n if (Math.abs(bytes) < threshold) {\n return bytes + ' B'\n }\n\n const units = ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']\n let u = -1\n const r = 10 ** dp\n\n do {\n bytes /= threshold\n ++u\n } while (Math.round(Math.abs(bytes) * r) / r >= threshold && u < units.length - 1)\n\n return bytes.toFixed(dp) + ' ' + units[u]\n}\n\nasync function serveStats(url: string, config: MaizzleConfig, renderer: Renderer, res: any) {\n const templateSlug = url.replace('/__maizzle/stats/', '').replace(/\\?.*$/, '')\n\n const contentPatterns = config.content ?? ['emails/**/*.vue']\n const templates = await glob(contentPatterns)\n const match = templates.find(t => t.replace(/\\.(vue|md)$/, '') === templateSlug)\n\n if (!match) {\n res.statusCode = 404\n res.end(JSON.stringify({ error: 'Template not found' }))\n return\n }\n\n try {\n const absolutePath = resolve(match)\n await renderer.invalidate(absolutePath)\n\n const rendered = await renderer.render(absolutePath, config)\n let html = rendered.html\n const templateConfig = rendered.templateConfig\n html = await runTransformers(html, templateConfig, absolutePath)\n\n const sizeBytes = Buffer.byteLength(html, 'utf-8')\n\n // Count images: <img> tags and CSS background images\n const imgTags = (html.match(/<img\\b[^>]*>/gi) || []).length\n const bgImages = (html.match(/url\\s*\\([^)]+\\)/gi) || []).length\n const totalImages = imgTags + bgImages\n\n // Count links\n const links = (html.match(/<a\\b[^>]*href\\s*=/gi) || []).length\n\n res.setHeader('Content-Type', 'application/json')\n res.end(JSON.stringify({\n size: {\n bytes: sizeBytes,\n formatted: humanFileSize(sizeBytes),\n },\n images: totalImages,\n links,\n }))\n } catch (error: any) {\n res.statusCode = 500\n res.end(JSON.stringify({ error: error.message }))\n }\n}\n\nexport function printBanner(server: ViteDevServer, startupTime?: number) {\n const info = server.config.logger.info\n const time = startupTime ?? (server as any)._maizzleStartupTime\n\n info('')\n info(` \\x1b[32m\\x1b[1mMAIZZLE\\x1b[0m\\x1b[32m v6.0.0\\x1b[0m \\x1b[2mready in\\x1b[0m \\x1b[1m${time}\\x1b[0m ms`)\n info('')\n server.printUrls()\n info('')\n}\n\nfunction customLogger() {\n const logger = createLogger('info')\n const warn = logger.warn\n\n logger.warn = (message, options) => {\n if (typeof message === 'string' && message.includes('<tr> cannot be child of <table>')) {\n return\n }\n\n warn(message, options)\n }\n\n return logger\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"serve.mjs","names":[],"sources":["../src/serve.ts"],"sourcesContent":["import { readFileSync } from 'node:fs'\nimport { dirname, resolve, basename } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { createRequire } from 'node:module'\nimport { createServer, createLogger, type ViteDevServer } from 'vite'\nimport vue from '@vitejs/plugin-vue'\nimport tailwindcss from '@tailwindcss/vite'\nimport { glob } from 'tinyglobby'\nimport picomatch from 'picomatch'\nimport { createHighlighter, type Highlighter } from 'shiki'\nimport { createPlaintext } from './plaintext.ts'\nimport { resolveConfig } from './config/index.ts'\nimport { runTransformers } from './transformers/index.ts'\nimport { createRenderer, type Renderer } from './render/createRenderer.ts'\nimport { serveCompatibility } from './server/compatibility.ts'\nimport { serveLint } from './server/linter.ts'\nimport { sendEmail } from './server/email.ts'\nimport type { MaizzleConfig } from './types/index.ts'\n\nconst __dirname = dirname(fileURLToPath(import.meta.url))\nconst devUIDir = resolve(__dirname, 'server/ui')\n\nconst require = createRequire(import.meta.url)\nconst pkg = (name: string) => {\n const resolved = require.resolve(name)\n const marker = `node_modules/${name}`\n const idx = resolved.lastIndexOf(marker)\n\n return resolved.slice(0, idx + marker.length)\n}\n\nexport interface ServeOptions {\n config?: Partial<MaizzleConfig> | string\n /** Expose the server on the network (e.g. --host) */\n host?: boolean | string\n /** When true, suppresses the banner/URL output (used by the Vite plugin, which prints its own) */\n silent?: boolean\n}\n\n/**\n * Start the Maizzle dev server.\n *\n * Creates two things:\n * 1. A Vite dev server for the dev UI (sidebar + preview, with Vue + Tailwind for the UI itself)\n * 2. A Renderer instance for SSR rendering email templates\n *\n * Template rendering goes through the Renderer, not the Vite dev server.\n */\nexport async function serve(options: ServeOptions = {}) {\n const start = performance.now()\n\n let config = await resolveConfig(options.config)\n const port = config.server?.port ?? 3000\n\n // Create a renderer for SSR rendering email templates (with dts for dev)\n let renderer = await createRenderer({ dts: true, markdown: config.markdown, root: config.root, componentDirs: [config.components?.source ?? []].flat(), vite: config.vite })\n\n const server = await createServer({\n configFile: false,\n plugins: [\n // Vue and Tailwind are only for the dev UI SPA, not for email templates\n vue(),\n tailwindcss(),\n maizzleDevPlugin(config, renderer, options.config),\n ],\n resolve: {\n dedupe: ['vue'],\n alias: [\n { find: '@', replacement: devUIDir },\n { find: 'vue', replacement: resolve(pkg('vue'), 'dist/vue.runtime.esm-bundler.js') },\n ...['vue-router', 'reka-ui', '@vueuse/core', '@vueuse/shared', 'lucide-vue-next', 'class-variance-authority', 'clsx', 'tailwind-merge']\n .map(name => ({ find: name, replacement: pkg(name) })),\n ],\n },\n cacheDir: resolve(devUIDir, '.vite'),\n optimizeDeps: {\n noDiscovery: true,\n include: [\n 'vue',\n 'vue-router',\n 'lucide-vue-next',\n '@vueuse/core',\n '@vueuse/shared',\n 'reka-ui',\n 'class-variance-authority',\n 'clsx',\n 'tailwind-merge',\n ],\n },\n server: {\n port,\n host: options.host,\n fs: {\n allow: [process.cwd(), config.root ?? process.cwd(), devUIDir, ...['vue', 'vue-router', 'reka-ui', '@vueuse/core', '@vueuse/shared', 'lucide-vue-next', 'class-variance-authority', 'clsx', 'tailwind-merge'].map(pkg)],\n },\n },\n customLogger: customLogger(),\n })\n\n // Store renderer ref on server for cleanup\n const originalClose = server.close.bind(server)\n server.close = async () => {\n await renderer.close()\n return originalClose()\n }\n\n await server.listen()\n\n const startupTime = Math.round(performance.now() - start)\n\n if (!options.silent) {\n printBanner(server, startupTime)\n }\n\n // Expose startup time so the plugin can print it later\n ; (server as any)._maizzleStartupTime = startupTime\n\n return server\n}\n\n/**\n * Internal Vite plugin that adds Maizzle middleware and file watching to the dev UI server.\n */\nfunction maizzleDevPlugin(\n config: MaizzleConfig,\n renderer: Renderer,\n configInput: Partial<MaizzleConfig> | string | undefined,\n) {\n return {\n name: 'maizzle:dev',\n enforce: 'pre' as const,\n\n hotUpdate: {\n order: 'pre' as const,\n handler({ file }: { file: string }) {\n // Prevent Tailwind/Vue from triggering a full reload for email template files.\n // Maizzle handles these via custom HMR events in the watcher below.\n if (isTemplateFile(file)) {\n return []\n }\n },\n },\n\n configureServer(server: ViteDevServer) {\n // File watching\n const defaultWatchPaths = [\n 'maizzle.config.js',\n 'maizzle.config.ts',\n 'tailwind.config.js',\n 'tailwind.config.ts',\n 'locales/**',\n ]\n\n const userWatchPaths = config.server?.watch ?? []\n const watchPaths = [...defaultWatchPaths, ...userWatchPaths]\n const isWatchedFile = picomatch(watchPaths)\n\n for (const watchPath of watchPaths) {\n server.watcher.add(watchPath)\n }\n\n server.watcher.on('add', async (file) => {\n if (isTemplateFile(file)) {\n await renderer.invalidateAll()\n server.ws.send({ type: 'custom', event: 'maizzle:templates-changed' })\n }\n })\n\n server.watcher.on('unlink', async (file) => {\n if (isTemplateFile(file)) {\n await renderer.invalidateAll()\n server.ws.send({ type: 'custom', event: 'maizzle:templates-changed' })\n }\n })\n\n server.watcher.on('change', async (file) => {\n if (isWatchedFile(file)) {\n config = await resolveConfig(configInput)\n\n // Recreate the renderer so config changes (e.g. markdown.shikiTheme) take effect\n await renderer.close()\n renderer = await createRenderer({ dts: true, markdown: config.markdown, root: config.root, componentDirs: [config.components?.source ?? []].flat(), vite: config.vite })\n }\n\n // Invalidate all renderer modules so component and config changes\n // are picked up on the next render (Tailwind recompiles with fresh content)\n await renderer.invalidateAll()\n\n if (\n isTemplateFile(file)\n || isWatchedFile(file)\n ) {\n server.ws.send({ type: 'custom', event: 'maizzle:template-updated', data: { file } })\n }\n })\n\n // API middleware (before Vite's middleware)\n server.middlewares.use(async (req: any, res: any, next: any) => {\n const url = req.url || '/'\n\n if (url === '/__maizzle/templates') {\n return serveTemplateList(config, res)\n }\n\n if (url.startsWith('/__maizzle/render/')) {\n return await serveRenderedTemplate(url, config, renderer, res)\n }\n\n if (url.startsWith('/__maizzle/source/')) {\n return await serveHighlightedSource(url, config, renderer, res)\n }\n\n if (url === '/__maizzle/compatibility' && req.method === 'POST') {\n return await serveCompatibility(req, res)\n }\n\n if (url.startsWith('/__maizzle/lint/')) {\n return serveLint(url, res)\n }\n\n if (url.startsWith('/__maizzle/vue-source/')) {\n return await serveVueSource(url, config, res)\n }\n\n if (url.startsWith('/__maizzle/plaintext/')) {\n return await servePlaintext(url, config, renderer, res)\n }\n\n if (url.startsWith('/__maizzle/stats/')) {\n return await serveStats(url, config, renderer, res)\n }\n\n if (url.startsWith('/__maizzle/email/') && req.method === 'POST') {\n return await serveEmailEndpoint(url, req, res, config, renderer)\n }\n\n if (url === '/__maizzle/email-config') {\n return serveEmailConfig(config, res)\n }\n\n next()\n })\n\n // Dev UI fallback (after Vite's middleware)\n return () => {\n server.middlewares.use(async (req: any, res: any, next: any) => {\n if (isNavigationRequest(req)) {\n return await serveDevUI(server, res, req.url || '/')\n }\n\n next()\n })\n }\n },\n }\n}\n\nfunction isTemplateFile(file: string): boolean {\n return (file.endsWith('.vue') || file.endsWith('.md')) && !file.includes('server/ui')\n}\n\nfunction isNavigationRequest(req: any): boolean {\n const accept = req.headers?.accept || ''\n return req.method === 'GET' && accept.includes('text/html')\n}\n\nasync function serveDevUI(server: ViteDevServer, res: any, url: string) {\n let indexHtml = readFileSync(resolve(devUIDir, 'index.html'), 'utf-8')\n\n indexHtml = indexHtml.replace('./main.ts', `/@fs/${resolve(devUIDir, 'main.ts')}`)\n indexHtml = indexHtml.replace('./favicon.svg', `/@fs/${resolve(devUIDir, 'favicon.svg')}`)\n\n const transformed = await server.transformIndexHtml(url, indexHtml)\n\n res.setHeader('Content-Type', 'text/html')\n res.end(transformed)\n}\n\nasync function serveTemplateList(config: MaizzleConfig, res: any) {\n const contentPatterns = config.content ?? ['emails/**/*.vue']\n const templates = await glob(contentPatterns)\n\n const data = templates.map(t => ({\n name: basename(t).replace(/\\.(vue|md)$/, ''),\n path: t,\n href: '/' + t.replace(/\\.(vue|md)$/, ''),\n }))\n\n res.setHeader('Content-Type', 'application/json')\n res.end(JSON.stringify(data))\n}\n\n/**\n * SSR render a .vue template using the Renderer (not the dev UI server).\n */\nasync function serveRenderedTemplate(url: string, config: MaizzleConfig, renderer: Renderer, res: any) {\n const templateSlug = url.replace('/__maizzle/render/', '').replace(/\\?.*$/, '')\n\n const contentPatterns = config.content ?? ['emails/**/*.vue']\n const templates = await glob(contentPatterns)\n const match = templates.find(t => t.replace(/\\.(vue|md)$/, '') === templateSlug)\n\n if (!match) {\n res.statusCode = 404\n res.end('Template not found')\n return\n }\n\n try {\n const absolutePath = resolve(match)\n\n // Invalidate all modules so template + component changes are picked up\n await renderer.invalidateAll()\n\n const rendered = await renderer.render(absolutePath, config)\n let html = rendered.html\n\n const templateConfig = rendered.templateConfig\n const doctype = rendered.doctype ?? templateConfig.doctype ?? '<!DOCTYPE html>'\n\n html = await runTransformers(html, templateConfig, absolutePath, doctype)\n html = `${doctype}\\n${html}`\n\n res.setHeader('Content-Type', 'text/html')\n res.end(html)\n } catch (error: any) {\n res.statusCode = 500\n res.end(`<pre>${error.stack || error.message}</pre>`)\n }\n}\n\nlet highlighter: Highlighter | null = null\n\nasync function getHighlighter() {\n if (!highlighter) {\n highlighter = await createHighlighter({\n themes: ['laserwave'],\n langs: ['html', 'vue'],\n })\n }\n return highlighter\n}\n\nasync function serveHighlightedSource(url: string, config: MaizzleConfig, renderer: Renderer, res: any) {\n const templateSlug = url.replace('/__maizzle/source/', '').replace(/\\?.*$/, '')\n\n const contentPatterns = config.content ?? ['emails/**/*.vue']\n const templates = await glob(contentPatterns)\n const match = templates.find(t => t.replace(/\\.(vue|md)$/, '') === templateSlug)\n\n if (!match) {\n res.statusCode = 404\n res.end('Template not found')\n return\n }\n\n try {\n const absolutePath = resolve(match)\n\n await renderer.invalidateAll()\n\n const rendered = await renderer.render(absolutePath, config)\n let html = rendered.html\n\n const templateConfig = rendered.templateConfig\n const doctype = rendered.doctype ?? templateConfig.doctype ?? '<!DOCTYPE html>'\n html = await runTransformers(html, templateConfig, absolutePath, doctype)\n\n html = `${doctype}\\n${html}`\n\n const hl = await getHighlighter()\n const highlighted = hl.codeToHtml(html, {\n lang: 'html',\n theme: 'laserwave',\n transformers: [{\n line(node, line) {\n node.properties['data-line'] = line\n },\n }],\n })\n\n res.setHeader('Content-Type', 'text/html')\n res.end(highlighted)\n } catch (error: any) {\n res.statusCode = 500\n res.end(`<pre>${error.stack || error.message}</pre>`)\n }\n}\n\nasync function serveVueSource(url: string, config: MaizzleConfig, res: any) {\n const templateSlug = url.replace('/__maizzle/vue-source/', '').replace(/\\?.*$/, '')\n\n const contentPatterns = config.content ?? ['emails/**/*.vue']\n const templates = await glob(contentPatterns)\n const match = templates.find(t => t.replace(/\\.(vue|md)$/, '') === templateSlug)\n\n if (!match) {\n res.statusCode = 404\n res.end('Template not found')\n return\n }\n\n try {\n const source = readFileSync(resolve(match), 'utf-8')\n const lang = match.endsWith('.md') ? 'html' : 'vue'\n\n const hl = await getHighlighter()\n const highlighted = hl.codeToHtml(source, {\n lang,\n theme: 'laserwave',\n transformers: [{\n line(node, line) {\n node.properties['data-line'] = line\n },\n }],\n })\n\n res.setHeader('Content-Type', 'text/html')\n res.end(highlighted)\n } catch (error: any) {\n res.statusCode = 500\n res.end(`<pre>${error.stack || error.message}</pre>`)\n }\n}\n\nasync function servePlaintext(url: string, config: MaizzleConfig, renderer: Renderer, res: any) {\n const templateSlug = url.replace('/__maizzle/plaintext/', '').replace(/\\?.*$/, '')\n\n const contentPatterns = config.content ?? ['emails/**/*.vue']\n const templates = await glob(contentPatterns)\n const match = templates.find(t => t.replace(/\\.(vue|md)$/, '') === templateSlug)\n\n if (!match) {\n res.statusCode = 404\n res.end('Template not found')\n return\n }\n\n try {\n const absolutePath = resolve(match)\n await renderer.invalidateAll()\n\n const rendered = await renderer.render(absolutePath, config)\n let html = rendered.html\n const templateConfig = rendered.templateConfig\n const doctype = rendered.doctype ?? templateConfig.doctype ?? '<!DOCTYPE html>'\n html = await runTransformers(html, templateConfig, absolutePath, doctype)\n\n const plaintext = createPlaintext(html)\n\n res.setHeader('Content-Type', 'text/plain')\n res.end(plaintext)\n } catch (error: any) {\n res.statusCode = 500\n res.end(error.message)\n }\n}\n\nfunction humanFileSize(bytes: number, si = false, dp = 2) {\n const threshold = si ? 1000 : 1024\n\n if (Math.abs(bytes) < threshold) {\n return bytes + ' B'\n }\n\n const units = ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']\n let u = -1\n const r = 10 ** dp\n\n do {\n bytes /= threshold\n ++u\n } while (Math.round(Math.abs(bytes) * r) / r >= threshold && u < units.length - 1)\n\n return bytes.toFixed(dp) + ' ' + units[u]\n}\n\nasync function serveStats(url: string, config: MaizzleConfig, renderer: Renderer, res: any) {\n const templateSlug = url.replace('/__maizzle/stats/', '').replace(/\\?.*$/, '')\n\n const contentPatterns = config.content ?? ['emails/**/*.vue']\n const templates = await glob(contentPatterns)\n const match = templates.find(t => t.replace(/\\.(vue|md)$/, '') === templateSlug)\n\n if (!match) {\n res.statusCode = 404\n res.end(JSON.stringify({ error: 'Template not found' }))\n return\n }\n\n try {\n const absolutePath = resolve(match)\n await renderer.invalidateAll()\n\n const rendered = await renderer.render(absolutePath, config)\n let html = rendered.html\n const templateConfig = rendered.templateConfig\n const doctype = rendered.doctype ?? templateConfig.doctype ?? '<!DOCTYPE html>'\n html = await runTransformers(html, templateConfig, absolutePath, doctype)\n\n const sizeBytes = Buffer.byteLength(html, 'utf-8')\n\n // Count images: <img> tags and CSS background images\n const imgTags = (html.match(/<img\\b[^>]*>/gi) || []).length\n const bgImages = (html.match(/url\\s*\\([^)]+\\)/gi) || []).length\n const totalImages = imgTags + bgImages\n\n // Count links\n const links = (html.match(/<a\\b[^>]*href\\s*=/gi) || []).length\n\n res.setHeader('Content-Type', 'application/json')\n res.end(JSON.stringify({\n size: {\n bytes: sizeBytes,\n formatted: humanFileSize(sizeBytes),\n },\n images: totalImages,\n links,\n }))\n } catch (error: any) {\n res.statusCode = 500\n res.end(JSON.stringify({ error: error.message }))\n }\n}\n\nasync function serveEmailEndpoint(url: string, req: any, res: any, config: MaizzleConfig, renderer: Renderer) {\n const templateSlug = url.replace('/__maizzle/email/', '').replace(/\\?.*$/, '')\n\n const contentPatterns = config.content ?? ['emails/**/*.vue']\n const templates = await glob(contentPatterns)\n const match = templates.find(t => t.replace(/\\.(vue|md)$/, '') === templateSlug)\n\n if (!match) {\n res.statusCode = 404\n res.end(JSON.stringify({ success: false, message: 'Template not found' }))\n return\n }\n\n let body = ''\n for await (const chunk of req) body += chunk\n\n let payload: { to: string[]; subject: string }\n\n try {\n payload = JSON.parse(body)\n } catch {\n res.statusCode = 400\n res.end(JSON.stringify({ success: false, message: 'Invalid JSON' }))\n return\n }\n\n if (!payload.to?.length) {\n res.statusCode = 400\n res.end(JSON.stringify({ success: false, message: 'Missing recipients' }))\n return\n }\n\n try {\n const absolutePath = resolve(match)\n await renderer.invalidateAll()\n\n const rendered = await renderer.render(absolutePath, config)\n let html = rendered.html\n const templateConfig = rendered.templateConfig\n const doctype = rendered.doctype ?? templateConfig.doctype ?? '<!DOCTYPE html>'\n html = await runTransformers(html, templateConfig, absolutePath, doctype)\n html = `${doctype}\\n${html}`\n\n const text = createPlaintext(html)\n\n const result = await sendEmail(\n { to: payload.to, subject: payload.subject, html, text },\n config,\n templateConfig,\n )\n\n res.setHeader('Content-Type', 'application/json')\n res.end(JSON.stringify(result))\n } catch (error: any) {\n res.statusCode = 500\n res.end(JSON.stringify({ success: false, message: error.message }))\n }\n}\n\nfunction serveEmailConfig(config: MaizzleConfig, res: any) {\n const emailConfig = config.server?.email\n res.setHeader('Content-Type', 'application/json')\n res.end(JSON.stringify({\n to: emailConfig?.to ? (Array.isArray(emailConfig.to) ? emailConfig.to : [emailConfig.to]) : [],\n from: emailConfig?.from ?? '',\n subject: emailConfig?.subject ?? '',\n hasTransport: !!emailConfig?.transport,\n }))\n}\n\nexport function printBanner(server: ViteDevServer, startupTime?: number) {\n const info = server.config.logger.info\n const time = startupTime ?? (server as any)._maizzleStartupTime\n\n info('')\n info(` \\x1b[32m\\x1b[1mMAIZZLE\\x1b[0m\\x1b[32m v6.0.0\\x1b[0m \\x1b[2mready in\\x1b[0m \\x1b[1m${time}\\x1b[0m ms`)\n info('')\n server.printUrls()\n info('')\n}\n\nfunction customLogger() {\n const logger = createLogger('info')\n const warn = logger.warn\n\n logger.warn = (message, options) => {\n if (typeof message === 'string' && message.includes('<tr> cannot be child of <table>')) {\n return\n }\n\n warn(message, options)\n }\n\n return logger\n}\n"],"mappings":"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"}
@@ -1,6 +1,5 @@
1
- import { MaizzleConfig } from "../types/config.mjs";
2
1
  //#region src/server/compatibility.d.ts
3
- declare function serveCompatibility(url: string, config: MaizzleConfig, res: any): Promise<void>;
2
+ declare function serveCompatibility(req: any, res: any): Promise<void>;
4
3
  //#endregion
5
4
  export { serveCompatibility };
6
5
  //# sourceMappingURL=compatibility.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"compatibility.d.mts","names":[],"sources":["../../src/server/compatibility.ts"],"mappings":";;iBAMsB,kBAAA,CAAmB,GAAA,UAAa,MAAA,EAAQ,aAAA,EAAe,GAAA,QAAQ,OAAA"}
1
+ {"version":3,"file":"compatibility.d.mts","names":[],"sources":["../../src/server/compatibility.ts"],"mappings":";iBAEsB,kBAAA,CAAmB,GAAA,OAAU,GAAA,QAAQ,OAAA"}
@@ -1,21 +1,21 @@
1
- import { readFileSync } from "node:fs";
2
- import { resolve } from "node:path";
3
- import { glob } from "tinyglobby";
4
1
  import { caniemail, rawData } from "caniemail";
5
2
 
6
3
  //#region src/server/compatibility.ts
7
- async function serveCompatibility(url, config, res) {
8
- const templateSlug = url.replace("/__maizzle/compatibility/", "").replace(/\?.*$/, "");
9
- const match = (await glob(config.content ?? ["emails/**/*.vue"])).find((t) => t.replace(/\.(vue|md)$/, "") === templateSlug);
10
- if (!match) {
11
- res.statusCode = 404;
12
- res.end(JSON.stringify({
13
- errors: [],
14
- warnings: []
15
- }));
16
- return;
17
- }
4
+ async function serveCompatibility(req, res) {
18
5
  try {
6
+ const html = await new Promise((resolve, reject) => {
7
+ let body = "";
8
+ req.on("data", (chunk) => {
9
+ body += chunk;
10
+ });
11
+ req.on("end", () => resolve(body));
12
+ req.on("error", reject);
13
+ });
14
+ if (!html) {
15
+ res.setHeader("Content-Type", "application/json");
16
+ res.end(JSON.stringify([]));
17
+ return;
18
+ }
19
19
  const result = caniemail({
20
20
  clients: [
21
21
  "apple-mail.*",
@@ -23,10 +23,14 @@ async function serveCompatibility(url, config, res) {
23
23
  "outlook.*",
24
24
  "yahoo.*"
25
25
  ],
26
- html: readFileSync(resolve(match), "utf-8")
26
+ html
27
27
  });
28
28
  const urlMap = /* @__PURE__ */ new Map();
29
- for (const item of rawData.data) urlMap.set(item.title, item.url);
29
+ const categoryMap = /* @__PURE__ */ new Map();
30
+ for (const item of rawData.data) {
31
+ urlMap.set(item.title, item.url);
32
+ categoryMap.set(item.title, item.category);
33
+ }
30
34
  const issues = [];
31
35
  for (const [client, clientIssues] of result.issues.errors) for (const issue of clientIssues) issues.push({
32
36
  type: "error",
@@ -58,6 +62,7 @@ async function serveCompatibility(url, config, res) {
58
62
  } else grouped.set(key, {
59
63
  type: issue.type,
60
64
  title: issue.title,
65
+ category: categoryMap.get(issue.title) || "others",
61
66
  clients: [{
62
67
  name: clientName,
63
68
  notes: [...issue.notes]
@@ -66,7 +71,16 @@ async function serveCompatibility(url, config, res) {
66
71
  line: issue.line
67
72
  });
68
73
  }
74
+ const categoryOrder = [
75
+ "css",
76
+ "html",
77
+ "image",
78
+ "others"
79
+ ];
69
80
  const sortedIssues = [...grouped.values()].sort((a, b) => {
81
+ const catA = categoryOrder.indexOf(a.category);
82
+ const catB = categoryOrder.indexOf(b.category);
83
+ if (catA !== catB) return catA - catB;
70
84
  if (a.type !== b.type) return a.type === "error" ? -1 : 1;
71
85
  return a.title.localeCompare(b.title);
72
86
  });
@@ -1 +1 @@
1
- {"version":3,"file":"compatibility.mjs","names":[],"sources":["../../src/server/compatibility.ts"],"sourcesContent":["import { readFileSync } from 'node:fs'\nimport { resolve } from 'node:path'\nimport { glob } from 'tinyglobby'\nimport { caniemail, rawData } from 'caniemail'\nimport type { MaizzleConfig } from '../types/index.ts'\n\nexport async function serveCompatibility(url: string, config: MaizzleConfig, res: any) {\n const templateSlug = url.replace('/__maizzle/compatibility/', '').replace(/\\?.*$/, '')\n\n const contentPatterns = config.content ?? ['emails/**/*.vue']\n const templates = await glob(contentPatterns)\n const match = templates.find(t => t.replace(/\\.(vue|md)$/, '') === templateSlug)\n\n if (!match) {\n res.statusCode = 404\n res.end(JSON.stringify({ errors: [], warnings: [] }))\n return\n }\n\n try {\n const source = readFileSync(resolve(match), 'utf-8')\n\n const result = caniemail({\n clients: ['apple-mail.*', 'gmail.*', 'outlook.*', 'yahoo.*'],\n html: source,\n })\n\n // Build title -> caniemail URL lookup\n const urlMap = new Map<string, string>()\n for (const item of (rawData as any).data) {\n urlMap.set(item.title, item.url)\n }\n\n const issues: Array<{ type: 'error' | 'warning', client: string, title: string, notes: string[], line?: number }> = []\n\n for (const [client, clientIssues] of result.issues.errors) {\n for (const issue of clientIssues) {\n issues.push({\n type: 'error',\n client,\n title: issue.title,\n notes: issue.notes,\n line: issue.position?.start.line,\n })\n }\n }\n\n for (const [client, clientIssues] of result.issues.warnings) {\n for (const issue of clientIssues) {\n issues.push({\n type: 'warning',\n client,\n title: issue.title,\n notes: issue.notes,\n line: issue.position?.start.line,\n })\n }\n }\n\n // Group by feature title + type, keep per-client notes\n const grouped = new Map<string, {\n type: 'error' | 'warning'\n title: string\n clients: Array<{ name: string, notes: string[] }>\n url?: string\n line?: number\n }>()\n\n for (const issue of issues) {\n const key = `${issue.type}:${issue.title}`\n const existing = grouped.get(key)\n const clientName = issue.client\n .split('.')[0]\n .replace(/-/g, ' ')\n .replace(/\\b\\w/g, c => c.toUpperCase())\n\n if (existing) {\n const existingClient = existing.clients.find(c => c.name === clientName)\n if (existingClient) {\n for (const note of issue.notes) {\n if (!existingClient.notes.includes(note)) {\n existingClient.notes.push(note)\n }\n }\n } else {\n existing.clients.push({ name: clientName, notes: [...issue.notes] })\n }\n } else {\n grouped.set(key, {\n type: issue.type,\n title: issue.title,\n clients: [{ name: clientName, notes: [...issue.notes] }],\n url: urlMap.get(issue.title),\n line: issue.line,\n })\n }\n }\n\n // Sort: errors first, then warnings\n const sortedIssues = [...grouped.values()].sort((a, b) => {\n if (a.type !== b.type) return a.type === 'error' ? -1 : 1\n return a.title.localeCompare(b.title)\n })\n\n res.setHeader('Content-Type', 'application/json')\n res.end(JSON.stringify(sortedIssues))\n } catch (error: any) {\n res.statusCode = 500\n res.end(JSON.stringify({ error: error.message }))\n }\n}\n"],"mappings":";;;;;;AAMA,eAAsB,mBAAmB,KAAa,QAAuB,KAAU;CACrF,MAAM,eAAe,IAAI,QAAQ,6BAA6B,GAAG,CAAC,QAAQ,SAAS,GAAG;CAItF,MAAM,SADY,MAAM,KADA,OAAO,WAAW,CAAC,kBAAkB,CAChB,EACrB,MAAK,MAAK,EAAE,QAAQ,eAAe,GAAG,KAAK,aAAa;AAEhF,KAAI,CAAC,OAAO;AACV,MAAI,aAAa;AACjB,MAAI,IAAI,KAAK,UAAU;GAAE,QAAQ,EAAE;GAAE,UAAU,EAAE;GAAE,CAAC,CAAC;AACrD;;AAGF,KAAI;EAGF,MAAM,SAAS,UAAU;GACvB,SAAS;IAAC;IAAgB;IAAW;IAAa;IAAU;GAC5D,MAJa,aAAa,QAAQ,MAAM,EAAE,QAAQ;GAKnD,CAAC;EAGF,MAAM,yBAAS,IAAI,KAAqB;AACxC,OAAK,MAAM,QAAS,QAAgB,KAClC,QAAO,IAAI,KAAK,OAAO,KAAK,IAAI;EAGlC,MAAM,SAA8G,EAAE;AAEtH,OAAK,MAAM,CAAC,QAAQ,iBAAiB,OAAO,OAAO,OACjD,MAAK,MAAM,SAAS,aAClB,QAAO,KAAK;GACV,MAAM;GACN;GACA,OAAO,MAAM;GACb,OAAO,MAAM;GACb,MAAM,MAAM,UAAU,MAAM;GAC7B,CAAC;AAIN,OAAK,MAAM,CAAC,QAAQ,iBAAiB,OAAO,OAAO,SACjD,MAAK,MAAM,SAAS,aAClB,QAAO,KAAK;GACV,MAAM;GACN;GACA,OAAO,MAAM;GACb,OAAO,MAAM;GACb,MAAM,MAAM,UAAU,MAAM;GAC7B,CAAC;EAKN,MAAM,0BAAU,IAAI,KAMhB;AAEJ,OAAK,MAAM,SAAS,QAAQ;GAC1B,MAAM,MAAM,GAAG,MAAM,KAAK,GAAG,MAAM;GACnC,MAAM,WAAW,QAAQ,IAAI,IAAI;GACjC,MAAM,aAAa,MAAM,OACtB,MAAM,IAAI,CAAC,GACX,QAAQ,MAAM,IAAI,CAClB,QAAQ,UAAS,MAAK,EAAE,aAAa,CAAC;AAEzC,OAAI,UAAU;IACZ,MAAM,iBAAiB,SAAS,QAAQ,MAAK,MAAK,EAAE,SAAS,WAAW;AACxE,QAAI,gBACF;UAAK,MAAM,QAAQ,MAAM,MACvB,KAAI,CAAC,eAAe,MAAM,SAAS,KAAK,CACtC,gBAAe,MAAM,KAAK,KAAK;UAInC,UAAS,QAAQ,KAAK;KAAE,MAAM;KAAY,OAAO,CAAC,GAAG,MAAM,MAAM;KAAE,CAAC;SAGtE,SAAQ,IAAI,KAAK;IACf,MAAM,MAAM;IACZ,OAAO,MAAM;IACb,SAAS,CAAC;KAAE,MAAM;KAAY,OAAO,CAAC,GAAG,MAAM,MAAM;KAAE,CAAC;IACxD,KAAK,OAAO,IAAI,MAAM,MAAM;IAC5B,MAAM,MAAM;IACb,CAAC;;EAKN,MAAM,eAAe,CAAC,GAAG,QAAQ,QAAQ,CAAC,CAAC,MAAM,GAAG,MAAM;AACxD,OAAI,EAAE,SAAS,EAAE,KAAM,QAAO,EAAE,SAAS,UAAU,KAAK;AACxD,UAAO,EAAE,MAAM,cAAc,EAAE,MAAM;IACrC;AAEF,MAAI,UAAU,gBAAgB,mBAAmB;AACjD,MAAI,IAAI,KAAK,UAAU,aAAa,CAAC;UAC9B,OAAY;AACnB,MAAI,aAAa;AACjB,MAAI,IAAI,KAAK,UAAU,EAAE,OAAO,MAAM,SAAS,CAAC,CAAC"}
1
+ {"version":3,"file":"compatibility.mjs","names":[],"sources":["../../src/server/compatibility.ts"],"sourcesContent":["import { caniemail, rawData } from 'caniemail'\n\nexport async function serveCompatibility(req: any, res: any) {\n try {\n const html = await new Promise<string>((resolve, reject) => {\n let body = ''\n req.on('data', (chunk: string) => { body += chunk })\n req.on('end', () => resolve(body))\n req.on('error', reject)\n })\n\n if (!html) {\n res.setHeader('Content-Type', 'application/json')\n res.end(JSON.stringify([]))\n return\n }\n\n const result = caniemail({\n clients: ['apple-mail.*', 'gmail.*', 'outlook.*', 'yahoo.*'],\n html,\n })\n\n // Build title -> caniemail URL and category lookups\n const urlMap = new Map<string, string>()\n const categoryMap = new Map<string, string>()\n for (const item of (rawData as any).data) {\n urlMap.set(item.title, item.url)\n categoryMap.set(item.title, item.category)\n }\n\n const issues: Array<{ type: 'error' | 'warning', client: string, title: string, notes: string[], line?: number }> = []\n\n for (const [client, clientIssues] of result.issues.errors) {\n for (const issue of clientIssues) {\n issues.push({\n type: 'error',\n client,\n title: issue.title,\n notes: issue.notes,\n line: issue.position?.start.line,\n })\n }\n }\n\n for (const [client, clientIssues] of result.issues.warnings) {\n for (const issue of clientIssues) {\n issues.push({\n type: 'warning',\n client,\n title: issue.title,\n notes: issue.notes,\n line: issue.position?.start.line,\n })\n }\n }\n\n // Group by feature title + type, keep per-client notes\n const grouped = new Map<string, {\n type: 'error' | 'warning'\n title: string\n category: string\n clients: Array<{ name: string, notes: string[] }>\n url?: string\n line?: number\n }>()\n\n for (const issue of issues) {\n const key = `${issue.type}:${issue.title}`\n const existing = grouped.get(key)\n const clientName = issue.client\n .split('.')[0]\n .replace(/-/g, ' ')\n .replace(/\\b\\w/g, c => c.toUpperCase())\n\n if (existing) {\n const existingClient = existing.clients.find(c => c.name === clientName)\n if (existingClient) {\n for (const note of issue.notes) {\n if (!existingClient.notes.includes(note)) {\n existingClient.notes.push(note)\n }\n }\n } else {\n existing.clients.push({ name: clientName, notes: [...issue.notes] })\n }\n } else {\n grouped.set(key, {\n type: issue.type,\n title: issue.title,\n category: categoryMap.get(issue.title) || 'others',\n clients: [{ name: clientName, notes: [...issue.notes] }],\n url: urlMap.get(issue.title),\n line: issue.line,\n })\n }\n }\n\n // Sort: by category order, then errors first, then alphabetically\n const categoryOrder = ['css', 'html', 'image', 'others']\n const sortedIssues = [...grouped.values()].sort((a, b) => {\n const catA = categoryOrder.indexOf(a.category)\n const catB = categoryOrder.indexOf(b.category)\n if (catA !== catB) return catA - catB\n if (a.type !== b.type) return a.type === 'error' ? -1 : 1\n return a.title.localeCompare(b.title)\n })\n\n res.setHeader('Content-Type', 'application/json')\n res.end(JSON.stringify(sortedIssues))\n } catch (error: any) {\n res.statusCode = 500\n res.end(JSON.stringify({ error: error.message }))\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import { MaizzleConfig } from "../types/config.mjs";
2
+ //#region src/server/email.d.ts
3
+ interface SendEmailPayload {
4
+ to: string[];
5
+ subject: string;
6
+ html: string;
7
+ text?: string;
8
+ }
9
+ interface SendEmailResponse {
10
+ success: boolean;
11
+ message: string;
12
+ previewUrl?: string;
13
+ }
14
+ declare function sendEmail(payload: SendEmailPayload, config: MaizzleConfig, templateConfig: MaizzleConfig): Promise<SendEmailResponse>;
15
+ //#endregion
16
+ export { SendEmailPayload, sendEmail };
17
+ //# sourceMappingURL=email.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"email.d.mts","names":[],"sources":["../../src/server/email.ts"],"mappings":";;UAGiB,gBAAA;EACf,EAAA;EACA,OAAA;EACA,IAAA;EACA,IAAA;AAAA;AAAA,UAGQ,iBAAA;EACR,OAAA;EACA,OAAA;EACA,UAAA;AAAA;AAAA,iBAGoB,SAAA,CACpB,OAAA,EAAS,gBAAA,EACT,MAAA,EAAQ,aAAA,EACR,cAAA,EAAgB,aAAA,GACf,OAAA,CAAQ,iBAAA"}