@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,354 @@
1
+ <script lang="ts">
2
+ import { computed, createStaticVNode } from 'vue'
3
+ import type { PropType } from 'vue'
4
+ import { normalizeToPixels } from './utils.ts'
5
+
6
+ export default {
7
+ name: 'Vml',
8
+ props: {
9
+ /**
10
+ * VML shape to render.
11
+ *
12
+ * - `rect` (default) — rectangle
13
+ * - `roundrect` — rectangle with rounded corners (`arcsize`)
14
+ * - `oval` — ellipse fitted to width/height
15
+ * - `line` — straight line between `from` and `to`
16
+ *
17
+ * @default 'rect'
18
+ */
19
+ shape: {
20
+ type: String as PropType<'rect' | 'roundrect' | 'oval' | 'line'>,
21
+ default: 'rect',
22
+ validator: (v: string) => ['rect', 'roundrect', 'oval', 'line'].includes(v),
23
+ },
24
+ /**
25
+ * Corner radius for `roundrect`, as a fraction of the shorter side.
26
+ *
27
+ * Range 0–1. Ignored for other shapes.
28
+ *
29
+ * @example '0.1'
30
+ */
31
+ arcsize: {
32
+ type: [String, Number],
33
+ },
34
+ /**
35
+ * Start coordinate for `shape="line"` as `"x,y"`.
36
+ *
37
+ * Required when `shape="line"`. Ignored otherwise.
38
+ *
39
+ * @example '0,0'
40
+ * @example '10pt,10pt'
41
+ */
42
+ from: {
43
+ type: String,
44
+ validator: (v: string) => /^[\d.]+(px|pt|%|em|rem)?,[\d.]+(px|pt|%|em|rem)?$/.test(v.replace(/\s/g, '')),
45
+ },
46
+ /**
47
+ * End coordinate for `shape="line"` as `"x,y"`.
48
+ *
49
+ * Required when `shape="line"`. Ignored otherwise.
50
+ *
51
+ * @example '600,0'
52
+ * @example '100%,0'
53
+ */
54
+ to: {
55
+ type: String,
56
+ validator: (v: string) => /^[\d.]+(px|pt|%|em|rem)?,[\d.]+(px|pt|%|em|rem)?$/.test(v.replace(/\s/g, '')),
57
+ },
58
+ /**
59
+ * Width of the shape. Ignored for `line`.
60
+ *
61
+ * Accepts a number (treated as pixels) or a string with units.
62
+ *
63
+ * @default '600px'
64
+ */
65
+ width: {
66
+ type: [String, Number],
67
+ default: '600px',
68
+ },
69
+ /**
70
+ * Height of the shape. Ignored for `line`.
71
+ *
72
+ * When not set, the shape auto-sizes to fit its content.
73
+ */
74
+ height: {
75
+ type: [String, Number],
76
+ default: null,
77
+ },
78
+ /**
79
+ * VML fill type.
80
+ *
81
+ * - `solid` — solid color fill (default in VML when omitted)
82
+ * - `gradient` — linear gradient
83
+ * - `gradientradial` — radial gradient
84
+ * - `tile` — repeat image to fill
85
+ * - `pattern` — tile at original size
86
+ * - `frame` — scale image to fill
87
+ *
88
+ * Only emitted on `<v:fill>` when set.
89
+ */
90
+ type: {
91
+ type: String as PropType<'solid' | 'gradient' | 'gradientradial' | 'tile' | 'pattern' | 'frame'>,
92
+ },
93
+ /**
94
+ * URL of a fill image.
95
+ *
96
+ * When set, a `<v:fill>` child is emitted with this `src`.
97
+ */
98
+ src: {
99
+ type: String,
100
+ },
101
+ /**
102
+ * Primary fill color on `<v:fill>` (start color for gradients).
103
+ *
104
+ * @example '#3b82f6'
105
+ */
106
+ color: {
107
+ type: String,
108
+ },
109
+ /**
110
+ * Secondary fill color for gradient fills.
111
+ *
112
+ * @example '#1d4ed8'
113
+ */
114
+ color2: {
115
+ type: String,
116
+ },
117
+ /**
118
+ * Gradient direction in degrees (0–360).
119
+ *
120
+ * @example 90
121
+ */
122
+ angle: {
123
+ type: [String, Number],
124
+ },
125
+ /**
126
+ * Gradient midpoint (0–100, percentage of distance from start).
127
+ *
128
+ * @example 50
129
+ */
130
+ focus: {
131
+ type: [String, Number],
132
+ },
133
+ /**
134
+ * Radial gradient focus size as `"x,y"` fractions.
135
+ *
136
+ * @example '0,0'
137
+ */
138
+ focussize: {
139
+ type: String,
140
+ validator: (v: string) => /^-?[\d.]+,-?[\d.]+$/.test(v.replace(/\s/g, '')),
141
+ },
142
+ /**
143
+ * Radial gradient focus position as `"x,y"` fractions.
144
+ *
145
+ * @example '0.5,0.5'
146
+ */
147
+ focusposition: {
148
+ type: String,
149
+ validator: (v: string) => /^-?[\d.]+,-?[\d.]+$/.test(v.replace(/\s/g, '')),
150
+ },
151
+ /**
152
+ * Comma-separated dimensions for the fill image.
153
+ *
154
+ * @example '300px,200px'
155
+ */
156
+ sizes: {
157
+ type: String,
158
+ validator: (v: string) => /^[\d.]+(px|%|em|rem)?(,[\d.]+(px|%|em|rem)?)+$/.test(v.replace(/\s/g, '')),
159
+ },
160
+ /**
161
+ * Fill origin offset as comma-separated fractional values.
162
+ *
163
+ * Overridden by `backgroundPosition` if both are set.
164
+ *
165
+ * @example '-0.5,-0.5'
166
+ */
167
+ origin: {
168
+ type: String,
169
+ validator: (v: string) => /^-?[\d.]+(,-?[\d.]+)+$/.test(v.replace(/\s/g, '')),
170
+ },
171
+ /**
172
+ * Fill position offset as comma-separated fractional values.
173
+ *
174
+ * Overridden by `backgroundPosition` if both are set.
175
+ *
176
+ * @example '0.5,0.5'
177
+ */
178
+ position: {
179
+ type: String,
180
+ validator: (v: string) => /^-?[\d.]+(,-?[\d.]+)+$/.test(v.replace(/\s/g, '')),
181
+ },
182
+ /**
183
+ * Convenience for image positioning. Maps to VML `origin` / `position`.
184
+ *
185
+ * First value is vertical (`top` | `center` | `bottom`).
186
+ * Second value is horizontal (`left` | `center` | `right`).
187
+ *
188
+ * @example 'center,center'
189
+ */
190
+ backgroundPosition: {
191
+ type: String as PropType<
192
+ | 'top,left' | 'top,center' | 'top,right'
193
+ | 'center,left' | 'center,center' | 'center,right'
194
+ | 'bottom,left' | 'bottom,center' | 'bottom,right'
195
+ >,
196
+ validator: (v: string) => /^(top|center|bottom),(left|center|right)$/.test(v.replace(/\s/g, '')),
197
+ },
198
+ /**
199
+ * Aspect ratio constraint for the fill image.
200
+ *
201
+ * - `atleast` — image at least as large as the shape
202
+ * - `atmost` — image at most as large as the shape
203
+ */
204
+ aspect: {
205
+ type: String as PropType<'atleast' | 'atmost'>,
206
+ },
207
+ /**
208
+ * Text box inset (padding) as `top,right,bottom,left`.
209
+ *
210
+ * @default '0,0,0,0'
211
+ */
212
+ inset: {
213
+ type: String,
214
+ default: '0,0,0,0',
215
+ },
216
+ /**
217
+ * Whether the shape has a visible border.
218
+ *
219
+ * @default false (true for `shape="line"`)
220
+ */
221
+ stroke: {
222
+ type: [Boolean, String],
223
+ default: null,
224
+ },
225
+ /**
226
+ * Border color. Setting this enables `stroke` automatically.
227
+ *
228
+ * @example '#000000'
229
+ */
230
+ strokecolor: {
231
+ type: String,
232
+ },
233
+ /**
234
+ * Whether the shape has a fill.
235
+ *
236
+ * @default true (false for `shape="line"`)
237
+ */
238
+ fill: {
239
+ type: [Boolean, String],
240
+ default: null,
241
+ },
242
+ /**
243
+ * Fallback fill color on the shape element itself.
244
+ *
245
+ * Rendered when no `<v:fill>` child is emitted or the fill image
246
+ * cannot be loaded.
247
+ *
248
+ * @example '#3b82f6'
249
+ */
250
+ fillcolor: {
251
+ type: String,
252
+ },
253
+ },
254
+ setup(props, { slots }) {
255
+ const backgroundPositionMap: Record<string, string> = {
256
+ 'top,left': '-0.5,-0.5',
257
+ 'top,center': '0,-0.5',
258
+ 'top,right': '0.5,-0.5',
259
+ 'center,left': '-0.5,0',
260
+ 'center,center': '0,0',
261
+ 'center,right': '0.5,0',
262
+ 'bottom,left': '-0.5,0.5',
263
+ 'bottom,center': '0,0.5',
264
+ 'bottom,right': '0.5,0.5',
265
+ }
266
+
267
+ const resolvedOrigin = computed(() => props.origin ?? (props.backgroundPosition ? backgroundPositionMap[props.backgroundPosition.replace(/\s/g, '')] : undefined))
268
+ const resolvedPosition = computed(() => props.position ?? (props.backgroundPosition ? backgroundPositionMap[props.backgroundPosition.replace(/\s/g, '')] : undefined))
269
+
270
+ const hasFillChild = computed(() => {
271
+ return props.type !== undefined
272
+ || props.src !== undefined
273
+ || props.color !== undefined
274
+ || props.color2 !== undefined
275
+ || props.angle !== undefined
276
+ || props.focus !== undefined
277
+ || props.focussize !== undefined
278
+ || props.focusposition !== undefined
279
+ || props.sizes !== undefined
280
+ || props.aspect !== undefined
281
+ || resolvedOrigin.value !== undefined
282
+ || resolvedPosition.value !== undefined
283
+ })
284
+
285
+ const before = computed(() => {
286
+ const isLine = props.shape === 'line'
287
+ const element = `v:${props.shape}`
288
+
289
+ const toBool = (v: boolean | string) => v === true || v === 'true' ? 'true' : 'false'
290
+
291
+ const defaultFill = isLine ? false : true
292
+ const defaultStroke = isLine ? true : false
293
+ const fillResolved = props.fill === null ? defaultFill : props.fill
294
+ const strokeResolved = props.stroke === null ? defaultStroke : props.stroke
295
+
296
+ const styleParts: string[] = []
297
+ if (!isLine) {
298
+ styleParts.push(`width: ${normalizeToPixels(props.width)}`)
299
+ if (props.height) styleParts.push(`height: ${normalizeToPixels(props.height)}`)
300
+ }
301
+
302
+ const shapeAttrs = [
303
+ `fill="${props.fillcolor ? 'true' : toBool(fillResolved)}"`,
304
+ `stroke="${props.strokecolor ? 'true' : toBool(strokeResolved)}"`,
305
+ styleParts.length ? `style="${styleParts.join('; ')};"` : '',
306
+ props.strokecolor ? `strokecolor="${props.strokecolor}"` : '',
307
+ props.fillcolor ? `fillcolor="${props.fillcolor}"` : '',
308
+ props.shape === 'roundrect' && props.arcsize !== undefined ? `arcsize="${props.arcsize}"` : '',
309
+ isLine && props.from ? `from="${props.from}"` : '',
310
+ isLine && props.to ? `to="${props.to}"` : '',
311
+ ].filter(Boolean).join(' ')
312
+
313
+ const fillAttrs = hasFillChild.value
314
+ ? [
315
+ props.type ? `type="${props.type}"` : '',
316
+ props.src ? `src="${props.src}"` : '',
317
+ props.color ? `color="${props.color}"` : '',
318
+ props.color2 ? `color2="${props.color2}"` : '',
319
+ props.angle !== undefined ? `angle="${props.angle}"` : '',
320
+ props.focus !== undefined ? `focus="${props.focus}"` : '',
321
+ props.focussize ? `focussize="${props.focussize}"` : '',
322
+ props.focusposition ? `focusposition="${props.focusposition}"` : '',
323
+ props.sizes ? `sizes="${props.sizes}"` : '',
324
+ props.aspect ? `aspect="${props.aspect}"` : '',
325
+ resolvedOrigin.value ? `origin="${resolvedOrigin.value}"` : '',
326
+ resolvedPosition.value ? `position="${resolvedPosition.value}"` : '',
327
+ ].filter(Boolean).join(' ')
328
+ : ''
329
+
330
+ const lines = [
331
+ `<!--[if mso]>`,
332
+ `<${element} xmlns:v="urn:schemas-microsoft-com:vml" ${shapeAttrs}>`,
333
+ ]
334
+ if (hasFillChild.value) {
335
+ lines.push(`<v:fill ${fillAttrs} />`)
336
+ }
337
+ lines.push(`<v:textbox inset="${props.inset}" style="mso-fit-shape-to-text: true">`)
338
+ lines.push(`<div><![endif]-->`)
339
+ return lines.join('')
340
+ })
341
+
342
+ const after = computed(() => {
343
+ const element = `v:${props.shape}`
344
+ return `<!--[if mso]></div></v:textbox></${element}><![endif]-->`
345
+ })
346
+
347
+ return () => [
348
+ createStaticVNode(before.value, 1),
349
+ slots.default?.(),
350
+ createStaticVNode(after.value, 1),
351
+ ]
352
+ },
353
+ }
354
+ </script>
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","names":[],"sources":["../../src/components/utils.ts"],"mappings":";iBAAgB,iBAAA,CAAkB,KAAA;AAAlC;;;;;AAiBA;;;AAjBA,iBAiBgB,MAAA,CAAO,MAAA;AAAA,iBAKP,eAAA,CAAgB,QAAA;AAAA,iBAQhB,eAAA,CAAgB,QAAA;AAAA,iBAIhB,gBAAA,CAAiB,QAAA;AAAA,iBAQjB,gBAAA,CAAiB,QAAA;;;AAZjC;;;;cAsBa,mBAAA;EAAA,eAGH,kBAAA;EAAA"}
1
+ {"version":3,"file":"utils.d.ts","names":[],"sources":["../../src/components/utils.ts"],"mappings":";iBAAgB,iBAAA,CAAkB,KAAsB;AAAxD;;;;AAAwD;AAiBxD;;;AAjBA,iBAiBgB,MAAA,CAAO,MAAc;AAAA,iBAKrB,eAAA,CAAgB,QAAgB;AAAA,iBAQhC,eAAA,CAAgB,QAAgB;AAAA,iBAIhC,gBAAA,CAAiB,QAAgB;AAAA,iBAQjC,gBAAA,CAAiB,QAAgB;;AApBD;AAQhD;;;;cAsBa,mBAAA;EAAA,eAGH,kBAAA;EAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","names":[],"sources":["../../src/components/utils.ts"],"sourcesContent":["export function normalizeToPixels(value: string | number): string {\n if (typeof value === 'number' || Number.isFinite(Number(value))) {\n return `${value}px`\n }\n return value\n}\n\nconst counters: Record<string, number> = {}\n\n/**\n * Module-scoped sequential ID generator. Used by components to mint\n * unique marker ids (e.g. `c1`, `c2`) for the post-render transformer.\n *\n * Must live here (not inside `<script setup>`) because Vue compiles\n * `<script setup>` into the component's `setup()` function — any\n * `let counter = 0` there resets per instance, causing id collisions.\n */\nexport function nextId(prefix: string): string {\n counters[prefix] = (counters[prefix] ?? 0) + 1\n return `${prefix}${counters[prefix]}`\n}\n\nexport function hasWidthUtility(classStr: string): boolean {\n return classStr.split(/\\s+/).some((c) => {\n const utility = c.split(':').pop() ?? ''\n const clean = utility.replace(/^!/, '')\n return /^(w-|max-w-|min-w-)/.test(clean)\n })\n}\n\nexport function hasWidthInStyle(styleStr: string): boolean {\n return /(?:^|;\\s*)(?:max-width|width)\\s*:/i.test(styleStr)\n}\n\nexport function hasHeightUtility(classStr: string): boolean {\n return classStr.split(/\\s+/).some((c) => {\n const utility = c.split(':').pop() ?? ''\n const clean = utility.replace(/^!/, '')\n return /^(h-|max-h-|min-h-)/.test(clean)\n })\n}\n\nexport function hasHeightInStyle(styleStr: string): boolean {\n return /(?:^|;\\s*)(?:max-height|height)\\s*:/i.test(styleStr)\n}\n\n/**\n * Shared prop for components that emit MSO/VML fallback markup. The\n * `null` default acts as the \"unset\" sentinel — `useOutlookFallback`\n * treats `null` as inherit-from-ancestor (root default `true`),\n * letting users override per-component without losing inheritance.\n */\nexport const outlookFallbackProp = {\n type: Boolean,\n default: null,\n} as const\n\n"],"mappings":";AAAA,SAAgB,kBAAkB,OAAgC;CAChE,IAAI,OAAO,UAAU,YAAY,OAAO,SAAS,OAAO,MAAM,CAAC,EAC7D,OAAO,GAAG,MAAM;CAElB,OAAO;;AAGT,MAAM,WAAmC,EAAE;;;;;;;;;AAU3C,SAAgB,OAAO,QAAwB;CAC7C,SAAS,WAAW,SAAS,WAAW,KAAK;CAC7C,OAAO,GAAG,SAAS,SAAS;;AAG9B,SAAgB,gBAAgB,UAA2B;CACzD,OAAO,SAAS,MAAM,MAAM,CAAC,MAAM,MAAM;EAEvC,MAAM,SADU,EAAE,MAAM,IAAI,CAAC,KAAK,IAAI,IAChB,QAAQ,MAAM,GAAG;EACvC,OAAO,sBAAsB,KAAK,MAAM;GACxC;;AAGJ,SAAgB,gBAAgB,UAA2B;CACzD,OAAO,qCAAqC,KAAK,SAAS;;AAG5D,SAAgB,iBAAiB,UAA2B;CAC1D,OAAO,SAAS,MAAM,MAAM,CAAC,MAAM,MAAM;EAEvC,MAAM,SADU,EAAE,MAAM,IAAI,CAAC,KAAK,IAAI,IAChB,QAAQ,MAAM,GAAG;EACvC,OAAO,sBAAsB,KAAK,MAAM;GACxC;;AAGJ,SAAgB,iBAAiB,UAA2B;CAC1D,OAAO,uCAAuC,KAAK,SAAS;;;;;;;;AAS9D,MAAa,sBAAsB;CACjC,MAAM;CACN,SAAS;CACV"}
1
+ {"version":3,"file":"utils.js","names":[],"sources":["../../src/components/utils.ts"],"sourcesContent":["export function normalizeToPixels(value: string | number): string {\n if (typeof value === 'number' || Number.isFinite(Number(value))) {\n return `${value}px`\n }\n return value\n}\n\nconst counters: Record<string, number> = {}\n\n/**\n * Module-scoped sequential ID generator. Used by components to mint\n * unique marker ids (e.g. `c1`, `c2`) for the post-render transformer.\n *\n * Must live here (not inside `<script setup>`) because Vue compiles\n * `<script setup>` into the component's `setup()` function — any\n * `let counter = 0` there resets per instance, causing id collisions.\n */\nexport function nextId(prefix: string): string {\n counters[prefix] = (counters[prefix] ?? 0) + 1\n return `${prefix}${counters[prefix]}`\n}\n\nexport function hasWidthUtility(classStr: string): boolean {\n return classStr.split(/\\s+/).some((c) => {\n const utility = c.split(':').pop() ?? ''\n const clean = utility.replace(/^!/, '')\n return /^(w-|max-w-|min-w-)/.test(clean)\n })\n}\n\nexport function hasWidthInStyle(styleStr: string): boolean {\n return /(?:^|;\\s*)(?:max-width|width)\\s*:/i.test(styleStr)\n}\n\nexport function hasHeightUtility(classStr: string): boolean {\n return classStr.split(/\\s+/).some((c) => {\n const utility = c.split(':').pop() ?? ''\n const clean = utility.replace(/^!/, '')\n return /^(h-|max-h-|min-h-)/.test(clean)\n })\n}\n\nexport function hasHeightInStyle(styleStr: string): boolean {\n return /(?:^|;\\s*)(?:max-height|height)\\s*:/i.test(styleStr)\n}\n\n/**\n * Shared prop for components that emit MSO/VML fallback markup. The\n * `null` default acts as the \"unset\" sentinel — `useOutlookFallback`\n * treats `null` as inherit-from-ancestor (root default `true`),\n * letting users override per-component without losing inheritance.\n */\nexport const outlookFallbackProp = {\n type: Boolean,\n default: null,\n} as const\n\n"],"mappings":";AAAA,SAAgB,kBAAkB,OAAgC;CAChE,IAAI,OAAO,UAAU,YAAY,OAAO,SAAS,OAAO,KAAK,CAAC,GAC5D,OAAO,GAAG,MAAM;CAElB,OAAO;AACT;AAEA,MAAM,WAAmC,CAAC;;;;;;;;;AAU1C,SAAgB,OAAO,QAAwB;CAC7C,SAAS,WAAW,SAAS,WAAW,KAAK;CAC7C,OAAO,GAAG,SAAS,SAAS;AAC9B;AAEA,SAAgB,gBAAgB,UAA2B;CACzD,OAAO,SAAS,MAAM,KAAK,EAAE,MAAM,MAAM;EAEvC,MAAM,SADU,EAAE,MAAM,GAAG,EAAE,IAAI,KAAK,IAChB,QAAQ,MAAM,EAAE;EACtC,OAAO,sBAAsB,KAAK,KAAK;CACzC,CAAC;AACH;AAEA,SAAgB,gBAAgB,UAA2B;CACzD,OAAO,qCAAqC,KAAK,QAAQ;AAC3D;AAEA,SAAgB,iBAAiB,UAA2B;CAC1D,OAAO,SAAS,MAAM,KAAK,EAAE,MAAM,MAAM;EAEvC,MAAM,SADU,EAAE,MAAM,GAAG,EAAE,IAAI,KAAK,IAChB,QAAQ,MAAM,EAAE;EACtC,OAAO,sBAAsB,KAAK,KAAK;CACzC,CAAC;AACH;AAEA,SAAgB,iBAAiB,UAA2B;CAC1D,OAAO,uCAAuC,KAAK,QAAQ;AAC7D;;;;;;;AAQA,MAAa,sBAAsB;CACjC,MAAM;CACN,SAAS;AACX"}
@@ -1 +1 @@
1
- {"version":3,"file":"defineConfig.js","names":[],"sources":["../../src/composables/defineConfig.ts"],"sourcesContent":["import { getCurrentInstance, inject, provide } from 'vue'\nimport { createDefu } from 'defu'\nimport { MaizzleConfigKey } from './useConfig.ts'\nimport { RenderContextKey } from './renderContext.ts'\nimport type { MaizzleConfig } from '../types/index.ts'\n\nconst merge = createDefu((obj, key, value) => {\n if (Array.isArray(obj[key])) {\n obj[key] = value\n return true\n }\n})\n\n/**\n * Define Maizzle config.\n *\n * In maizzle.config.ts: typed identity function, returns the config as-is\n * In Vue SFC `<script setup>`: merges with the global config and provides\n * the result to child components via `useConfig()`\n */\nexport function defineConfig(data: Partial<MaizzleConfig> = {}): MaizzleConfig {\n // Inside a Vue SFC — merge with global config and provide to children\n if (getCurrentInstance()) {\n const globalConfig = inject(MaizzleConfigKey, {} as MaizzleConfig)\n const merged = merge(data, globalConfig) as MaizzleConfig\n\n const ctx = inject(RenderContextKey)\n if (ctx) ctx.sfcConfig = merged\n\n provide(MaizzleConfigKey, merged)\n\n return merged\n }\n\n // Outside Vue (maizzle.config.ts) — just return the config\n return data as MaizzleConfig\n}\n"],"mappings":";;;;;AAMA,MAAM,QAAQ,YAAY,KAAK,KAAK,UAAU;CAC5C,IAAI,MAAM,QAAQ,IAAI,KAAK,EAAE;EAC3B,IAAI,OAAO;EACX,OAAO;;EAET;;;;;;;;AASF,SAAgB,aAAa,OAA+B,EAAE,EAAiB;CAE7E,IAAI,oBAAoB,EAAE;EAExB,MAAM,SAAS,MAAM,MADA,OAAO,kBAAkB,EAAE,CACT,CAAC;EAExC,MAAM,MAAM,OAAO,iBAAiB;EACpC,IAAI,KAAK,IAAI,YAAY;EAEzB,QAAQ,kBAAkB,OAAO;EAEjC,OAAO;;CAIT,OAAO"}
1
+ {"version":3,"file":"defineConfig.js","names":[],"sources":["../../src/composables/defineConfig.ts"],"sourcesContent":["import { getCurrentInstance, inject, provide } from 'vue'\nimport { createDefu } from 'defu'\nimport { MaizzleConfigKey } from './useConfig.ts'\nimport { RenderContextKey } from './renderContext.ts'\nimport type { MaizzleConfig } from '../types/index.ts'\n\nconst merge = createDefu((obj, key, value) => {\n if (Array.isArray(obj[key])) {\n obj[key] = value\n return true\n }\n})\n\n/**\n * Define Maizzle config.\n *\n * In maizzle.config.ts: typed identity function, returns the config as-is\n * In Vue SFC `<script setup>`: merges with the global config and provides\n * the result to child components via `useConfig()`\n */\nexport function defineConfig(data: Partial<MaizzleConfig> = {}): MaizzleConfig {\n // Inside a Vue SFC — merge with global config and provide to children\n if (getCurrentInstance()) {\n const globalConfig = inject(MaizzleConfigKey, {} as MaizzleConfig)\n const merged = merge(data, globalConfig) as MaizzleConfig\n\n const ctx = inject(RenderContextKey)\n if (ctx) ctx.sfcConfig = merged\n\n provide(MaizzleConfigKey, merged)\n\n return merged\n }\n\n // Outside Vue (maizzle.config.ts) — just return the config\n return data as MaizzleConfig\n}\n"],"mappings":";;;;;AAMA,MAAM,QAAQ,YAAY,KAAK,KAAK,UAAU;CAC5C,IAAI,MAAM,QAAQ,IAAI,IAAI,GAAG;EAC3B,IAAI,OAAO;EACX,OAAO;CACT;AACF,CAAC;;;;;;;;AASD,SAAgB,aAAa,OAA+B,CAAC,GAAkB;CAE7E,IAAI,mBAAmB,GAAG;EAExB,MAAM,SAAS,MAAM,MADA,OAAO,kBAAkB,CAAC,CACT,CAAC;EAEvC,MAAM,MAAM,OAAO,gBAAgB;EACnC,IAAI,KAAK,IAAI,YAAY;EAEzB,QAAQ,kBAAkB,MAAM;EAEhC,OAAO;CACT;CAGA,OAAO;AACT"}
@@ -27,6 +27,7 @@ interface RenderContext {
27
27
  handler: EventMap[EventName];
28
28
  }>;
29
29
  plaintext?: UsePlaintextOptions;
30
+ outputPath?: string;
30
31
  fonts?: FontRegistration[];
31
32
  tailwindBlocks?: TailwindBlock[];
32
33
  }
@@ -1 +1 @@
1
- {"version":3,"file":"renderContext.d.ts","names":[],"sources":["../../src/composables/renderContext.ts"],"mappings":";;;;;;UAKiB,gBAAA;EACf,MAAA;EACA,IAAA;EACA,WAAA;EACA,GAAA;AAAA;AAAA,UAGe,aAAA;EACf,EAAA;EANA;EAQA,GAAA;AAAA;AAAA,UAGe,aAAA;EACf,OAAA;EACA,SAAA;IAAc,IAAA;IAAc,WAAA;EAAA;EAC5B,SAAA,GAAY,aAAA;EACZ,gBAAA,EAAkB,KAAA;IAAQ,IAAA,EAAM,SAAA;IAAW,OAAA,EAAS,QAAA,CAAS,SAAA;EAAA;EAC7D,SAAA,GAAY,mBAAA;EACZ,KAAA,GAAQ,gBAAA;EACR,cAAA,GAAiB,aAAA;AAAA;AAAA,cAGN,gBAAA,EAAkB,YAAA,CAAa,aAAA"}
1
+ {"version":3,"file":"renderContext.d.ts","names":[],"sources":["../../src/composables/renderContext.ts"],"mappings":";;;;;;UAKiB,gBAAA;EACf,MAAA;EACA,IAAA;EACA,WAAA;EACA,GAAA;AAAA;AAAA,UAGe,aAAA;EACf,EAAA;EANA;EAQA,GAAG;AAAA;AAAA,UAGY,aAAA;EACf,OAAA;EACA,SAAA;IAAc,IAAA;IAAc,WAAA;EAAA;EAC5B,SAAA,GAAY,aAAA;EACZ,gBAAA,EAAkB,KAAA;IAAQ,IAAA,EAAM,SAAA;IAAW,OAAA,EAAS,QAAA,CAAS,SAAA;EAAA;EAC7D,SAAA,GAAY,mBAAA;EACZ,UAAA;EACA,KAAA,GAAQ,gBAAA;EACR,cAAA,GAAiB,aAAA;AAAA;AAAA,cAIN,gBAAA,EAAkB,YAAY,CAAC,aAAA"}
@@ -1,5 +1,5 @@
1
1
  //#region src/composables/renderContext.ts
2
- const RenderContextKey = Symbol("RenderContext");
2
+ const RenderContextKey = Symbol.for("maizzle.renderContext");
3
3
  //#endregion
4
4
  export { RenderContextKey };
5
5
 
@@ -1 +1 @@
1
- {"version":3,"file":"renderContext.js","names":[],"sources":["../../src/composables/renderContext.ts"],"sourcesContent":["import type { InjectionKey } from 'vue'\nimport type { MaizzleConfig } from '../types/index.ts'\nimport type { EventName, EventMap } from '../events/index.ts'\nimport type { UsePlaintextOptions } from './usePlaintext.ts'\n\nexport interface FontRegistration {\n family: string\n slug: string\n declaration: string\n url: string\n}\n\nexport interface TailwindBlock {\n id: string\n /** Optional raw CSS from the component's `#config` slot. */\n css?: string\n}\n\nexport interface RenderContext {\n doctype?: string\n preheader?: { text: string; fillerCount: number }\n sfcConfig?: MaizzleConfig\n sfcEventHandlers: Array<{ name: EventName; handler: EventMap[EventName] }>\n plaintext?: UsePlaintextOptions\n fonts?: FontRegistration[]\n tailwindBlocks?: TailwindBlock[]\n}\n\nexport const RenderContextKey: InjectionKey<RenderContext> = Symbol('RenderContext')\n"],"mappings":";AA4BA,MAAa,mBAAgD,OAAO,gBAAgB"}
1
+ {"version":3,"file":"renderContext.js","names":[],"sources":["../../src/composables/renderContext.ts"],"sourcesContent":["import type { InjectionKey } from 'vue'\nimport type { MaizzleConfig } from '../types/index.ts'\nimport type { EventName, EventMap } from '../events/index.ts'\nimport type { UsePlaintextOptions } from './usePlaintext.ts'\n\nexport interface FontRegistration {\n family: string\n slug: string\n declaration: string\n url: string\n}\n\nexport interface TailwindBlock {\n id: string\n /** Optional raw CSS from the component's `#config` slot. */\n css?: string\n}\n\nexport interface RenderContext {\n doctype?: string\n preheader?: { text: string; fillerCount: number }\n sfcConfig?: MaizzleConfig\n sfcEventHandlers: Array<{ name: EventName; handler: EventMap[EventName] }>\n plaintext?: UsePlaintextOptions\n outputPath?: string\n fonts?: FontRegistration[]\n tailwindBlocks?: TailwindBlock[]\n}\n\n// Global symbol registry — same rationale as MaizzleConfigKey in useConfig.ts.\nexport const RenderContextKey: InjectionKey<RenderContext> = Symbol.for('maizzle.renderContext')\n"],"mappings":";AA8BA,MAAa,mBAAgD,OAAO,IAAI,uBAAuB"}
@@ -1 +1 @@
1
- {"version":3,"file":"useBaseUrl.d.ts","names":[],"sources":["../../src/composables/useBaseUrl.ts"],"mappings":";;;;;AAkBA;;;;;;;;;;iBAAgB,UAAA,CAAW,KAAA,EAAO,SAAA"}
1
+ {"version":3,"file":"useBaseUrl.d.ts","names":[],"sources":["../../src/composables/useBaseUrl.ts"],"mappings":";;;;;AAkBA;;;;AAAmD;;;;;;iBAAnC,UAAA,CAAW,KAAwB,EAAjB,SAAS"}
@@ -1 +1 @@
1
- {"version":3,"file":"useBaseUrl.js","names":["merge"],"sources":["../../src/composables/useBaseUrl.ts"],"sourcesContent":["import { inject } from 'vue'\nimport { defu as merge } from 'defu'\nimport { RenderContextKey } from './renderContext.ts'\nimport type { UrlConfig } from '../types/index.ts'\n\n/**\n * Set the base URL for the current email template — same as\n * `config.url.base`, scoped to one SFC.\n *\n * Pass a string to prepend to all default tags/attributes, or an object\n * for fine-grained control (which tags/attributes, style tags, etc.).\n *\n * Usage in SFC <script setup>:\n * ```ts\n * useBaseUrl('https://cdn.example.com/emails/')\n * useBaseUrl({ url: 'https://cdn.example.com/', styleTag: true })\n * ```\n */\nexport function useBaseUrl(value: UrlConfig['base']): void {\n const ctx = inject(RenderContextKey)\n if (!ctx) return\n ctx.sfcConfig = merge({ url: { base: value } }, ctx.sfcConfig ?? {})\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAkBA,SAAgB,WAAW,OAAgC;CACzD,MAAM,MAAM,OAAO,iBAAiB;CACpC,IAAI,CAAC,KAAK;CACV,IAAI,YAAYA,OAAM,EAAE,KAAK,EAAE,MAAM,OAAO,EAAE,EAAE,IAAI,aAAa,EAAE,CAAC"}
1
+ {"version":3,"file":"useBaseUrl.js","names":["merge"],"sources":["../../src/composables/useBaseUrl.ts"],"sourcesContent":["import { inject } from 'vue'\nimport { defu as merge } from 'defu'\nimport { RenderContextKey } from './renderContext.ts'\nimport type { UrlConfig } from '../types/index.ts'\n\n/**\n * Set the base URL for the current email template — same as\n * `config.url.base`, scoped to one SFC.\n *\n * Pass a string to prepend to all default tags/attributes, or an object\n * for fine-grained control (which tags/attributes, style tags, etc.).\n *\n * Usage in SFC <script setup>:\n * ```ts\n * useBaseUrl('https://cdn.example.com/emails/')\n * useBaseUrl({ url: 'https://cdn.example.com/', styleTag: true })\n * ```\n */\nexport function useBaseUrl(value: UrlConfig['base']): void {\n const ctx = inject(RenderContextKey)\n if (!ctx) return\n ctx.sfcConfig = merge({ url: { base: value } }, ctx.sfcConfig ?? {})\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAkBA,SAAgB,WAAW,OAAgC;CACzD,MAAM,MAAM,OAAO,gBAAgB;CACnC,IAAI,CAAC,KAAK;CACV,IAAI,YAAYA,OAAM,EAAE,KAAK,EAAE,MAAM,MAAM,EAAE,GAAG,IAAI,aAAa,CAAC,CAAC;AACrE"}
@@ -2,6 +2,13 @@ import { MaizzleConfig } from "../types/config.js";
2
2
  import { InjectionKey } from "vue";
3
3
 
4
4
  //#region src/composables/useConfig.d.ts
5
+ /**
6
+ * Use the global symbol registry so the key is identical across every
7
+ * module instance. In dev, `render()` (Node) and the SFC's auto-imported
8
+ * composables can resolve to two separate instances of this module; a plain
9
+ * `Symbol()` would differ between them, so `app.provide()` and the SFC's
10
+ * `inject()` would miss each other and `useConfig()` would throw.
11
+ */
5
12
  declare const MaizzleConfigKey: InjectionKey<MaizzleConfig>;
6
13
  declare function useConfig(): MaizzleConfig;
7
14
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"useConfig.d.ts","names":[],"sources":["../../src/composables/useConfig.ts"],"mappings":";;;;cAIa,gBAAA,EAAkB,YAAA,CAAa,aAAA;AAAA,iBAE5B,SAAA,CAAA,GAAa,aAAA"}
1
+ {"version":3,"file":"useConfig.d.ts","names":[],"sources":["../../src/composables/useConfig.ts"],"mappings":";;;;;;;AAWA;;;;cAAa,gBAAA,EAAkB,YAAY,CAAC,aAAA;AAAA,iBAE5B,SAAA,CAAA,GAAa,aAAa"}
@@ -1,6 +1,13 @@
1
1
  import { inject } from "vue";
2
2
  //#region src/composables/useConfig.ts
3
- const MaizzleConfigKey = Symbol("MaizzleConfig");
3
+ /**
4
+ * Use the global symbol registry so the key is identical across every
5
+ * module instance. In dev, `render()` (Node) and the SFC's auto-imported
6
+ * composables can resolve to two separate instances of this module; a plain
7
+ * `Symbol()` would differ between them, so `app.provide()` and the SFC's
8
+ * `inject()` would miss each other and `useConfig()` would throw.
9
+ */
10
+ const MaizzleConfigKey = Symbol.for("maizzle.config");
4
11
  function useConfig() {
5
12
  const config = inject(MaizzleConfigKey);
6
13
  if (!config) throw new Error("useConfig() requires the Maizzle plugin to provide config. Make sure you are using it inside a Maizzle template.");
@@ -1 +1 @@
1
- {"version":3,"file":"useConfig.js","names":[],"sources":["../../src/composables/useConfig.ts"],"sourcesContent":["import { inject } from 'vue'\nimport type { InjectionKey } from 'vue'\nimport type { MaizzleConfig } from '../types/index.ts'\n\nexport const MaizzleConfigKey: InjectionKey<MaizzleConfig> = Symbol('MaizzleConfig')\n\nexport function useConfig(): MaizzleConfig {\n const config = inject(MaizzleConfigKey)\n\n if (!config) {\n throw new Error('useConfig() requires the Maizzle plugin to provide config. Make sure you are using it inside a Maizzle template.')\n }\n\n return config\n}\n"],"mappings":";;AAIA,MAAa,mBAAgD,OAAO,gBAAgB;AAEpF,SAAgB,YAA2B;CACzC,MAAM,SAAS,OAAO,iBAAiB;CAEvC,IAAI,CAAC,QACH,MAAM,IAAI,MAAM,mHAAmH;CAGrI,OAAO"}
1
+ {"version":3,"file":"useConfig.js","names":[],"sources":["../../src/composables/useConfig.ts"],"sourcesContent":["import { inject } from 'vue'\nimport type { InjectionKey } from 'vue'\nimport type { MaizzleConfig } from '../types/index.ts'\n\n/**\n * Use the global symbol registry so the key is identical across every\n * module instance. In dev, `render()` (Node) and the SFC's auto-imported\n * composables can resolve to two separate instances of this module; a plain\n * `Symbol()` would differ between them, so `app.provide()` and the SFC's\n * `inject()` would miss each other and `useConfig()` would throw.\n */\nexport const MaizzleConfigKey: InjectionKey<MaizzleConfig> = Symbol.for('maizzle.config')\n\nexport function useConfig(): MaizzleConfig {\n const config = inject(MaizzleConfigKey)\n\n if (!config) {\n throw new Error('useConfig() requires the Maizzle plugin to provide config. Make sure you are using it inside a Maizzle template.')\n }\n\n return config\n}\n"],"mappings":";;;;;;;;;AAWA,MAAa,mBAAgD,OAAO,IAAI,gBAAgB;AAExF,SAAgB,YAA2B;CACzC,MAAM,SAAS,OAAO,gBAAgB;CAEtC,IAAI,CAAC,QACH,MAAM,IAAI,MAAM,kHAAkH;CAGpI,OAAO;AACT"}
@@ -1 +1 @@
1
- {"version":3,"file":"useCurrentTemplate.d.ts","names":[],"sources":["../../src/composables/useCurrentTemplate.ts"],"mappings":";;;;;AAQA;;iBAAgB,mBAAA,CAAoB,MAAA,EAAQ,UAAA;;;AAuB5C;;;;;;;;;;;;;;;;;iBAAgB,kBAAA,CAAA,GAAsB,UAAA"}
1
+ {"version":3,"file":"useCurrentTemplate.d.ts","names":[],"sources":["../../src/composables/useCurrentTemplate.ts"],"mappings":";;;;;AAmBA;;iBAAgB,mBAAA,CAAoB,MAA8B,EAAtB,UAAU;;AAAY;AAuBlE;;;;AAAgD;;;;;;;;;;;;;iBAAhC,kBAAA,CAAA,GAAsB,UAAU"}
@@ -1,11 +1,18 @@
1
1
  //#region src/composables/useCurrentTemplate.ts
2
- let current;
2
+ /**
3
+ * Stored on globalThis so the Vite SSR module graph (which loads this file
4
+ * when a user SFC auto-imports useCurrentTemplate) and the Node import
5
+ * graph (used by build.ts / serve.ts) share the same value. Two
6
+ * module instances would otherwise hold independent `let`
7
+ * bindings.
8
+ */
9
+ const KEY = Symbol.for("maizzle.currentTemplate");
3
10
  /**
4
11
  * Internal — set by the build loop before each template iteration and
5
12
  * cleared in `finally`. Not exported from the package entrypoint.
6
13
  */
7
14
  function _setCurrentTemplate(parsed) {
8
- current = parsed;
15
+ globalThis[KEY] = parsed;
9
16
  }
10
17
  /**
11
18
  * Returns the parsed path of the template currently being processed,
@@ -27,7 +34,7 @@ function _setCurrentTemplate(parsed) {
27
34
  * ```
28
35
  */
29
36
  function useCurrentTemplate() {
30
- return current;
37
+ return globalThis[KEY];
31
38
  }
32
39
  //#endregion
33
40
  export { _setCurrentTemplate, useCurrentTemplate };
@@ -1 +1 @@
1
- {"version":3,"file":"useCurrentTemplate.js","names":[],"sources":["../../src/composables/useCurrentTemplate.ts"],"sourcesContent":["import type { ParsedPath } from 'node:path'\n\nlet current: ParsedPath | undefined\n\n/**\n * Internal — set by the build loop before each template iteration and\n * cleared in `finally`. Not exported from the package entrypoint.\n */\nexport function _setCurrentTemplate(parsed: ParsedPath | undefined): void {\n current = parsed\n}\n\n/**\n * Returns the parsed path of the template currently being processed,\n * or `undefined` when called outside the per-template scope (e.g. from\n * `beforeCreate` / `afterBuild`, or outside a build entirely).\n *\n * Usage in an SFC `<script setup>`:\n * ```ts\n * const file = useCurrentTemplate()\n * console.log(file?.name) // 'welcome'\n * ```\n *\n * Usage in an event handler:\n * ```ts\n * beforeRender() {\n * const file = useCurrentTemplate()\n * // file?.dir, file?.name, file?.ext, file?.base, file?.root\n * }\n * ```\n */\nexport function useCurrentTemplate(): ParsedPath | undefined {\n return current\n}\n"],"mappings":";AAEA,IAAI;;;;;AAMJ,SAAgB,oBAAoB,QAAsC;CACxE,UAAU;;;;;;;;;;;;;;;;;;;;;AAsBZ,SAAgB,qBAA6C;CAC3D,OAAO"}
1
+ {"version":3,"file":"useCurrentTemplate.js","names":[],"sources":["../../src/composables/useCurrentTemplate.ts"],"sourcesContent":["import type { ParsedPath } from 'node:path'\n\n/**\n * Stored on globalThis so the Vite SSR module graph (which loads this file\n * when a user SFC auto-imports useCurrentTemplate) and the Node import\n * graph (used by build.ts / serve.ts) share the same value. Two\n * module instances would otherwise hold independent `let`\n * bindings.\n */\nconst KEY = Symbol.for('maizzle.currentTemplate')\n\ninterface GlobalWithCurrentTemplate {\n [KEY]?: ParsedPath\n}\n\n/**\n * Internal — set by the build loop before each template iteration and\n * cleared in `finally`. Not exported from the package entrypoint.\n */\nexport function _setCurrentTemplate(parsed: ParsedPath | undefined): void {\n (globalThis as GlobalWithCurrentTemplate)[KEY] = parsed\n}\n\n/**\n * Returns the parsed path of the template currently being processed,\n * or `undefined` when called outside the per-template scope (e.g. from\n * `beforeCreate` / `afterBuild`, or outside a build entirely).\n *\n * Usage in an SFC `<script setup>`:\n * ```ts\n * const file = useCurrentTemplate()\n * console.log(file?.name) // 'welcome'\n * ```\n *\n * Usage in an event handler:\n * ```ts\n * beforeRender() {\n * const file = useCurrentTemplate()\n * // file?.dir, file?.name, file?.ext, file?.base, file?.root\n * }\n * ```\n */\nexport function useCurrentTemplate(): ParsedPath | undefined {\n return (globalThis as GlobalWithCurrentTemplate)[KEY]\n}\n"],"mappings":";;;;;;;;AASA,MAAM,MAAM,OAAO,IAAI,yBAAyB;;;;;AAUhD,SAAgB,oBAAoB,QAAsC;CACxE,WAA0C,OAAO;AACnD;;;;;;;;;;;;;;;;;;;;AAqBA,SAAgB,qBAA6C;CAC3D,OAAQ,WAAyC;AACnD"}
@@ -1 +1 @@
1
- {"version":3,"file":"useDoctype.d.ts","names":[],"sources":["../../src/composables/useDoctype.ts"],"mappings":";;AAWA;;;;;;;iBAAgB,UAAA,CAAW,OAAA"}
1
+ {"version":3,"file":"useDoctype.d.ts","names":[],"sources":["../../src/composables/useDoctype.ts"],"mappings":";;AAWA;;;;AAA0C;;;iBAA1B,UAAA,CAAW,OAAe"}
@@ -1 +1 @@
1
- {"version":3,"file":"useDoctype.js","names":[],"sources":["../../src/composables/useDoctype.ts"],"sourcesContent":["import { inject } from 'vue'\nimport { RenderContextKey } from './renderContext.ts'\n\n/**\n * Set the doctype for the current email template.\n *\n * Usage in SFC <script setup>:\n * ```ts\n * useDoctype('<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">')\n * ```\n */\nexport function useDoctype(doctype: string): void {\n const ctx = inject(RenderContextKey)\n if (ctx) ctx.doctype = doctype\n}\n"],"mappings":";;;;;;;;;;;AAWA,SAAgB,WAAW,SAAuB;CAChD,MAAM,MAAM,OAAO,iBAAiB;CACpC,IAAI,KAAK,IAAI,UAAU"}
1
+ {"version":3,"file":"useDoctype.js","names":[],"sources":["../../src/composables/useDoctype.ts"],"sourcesContent":["import { inject } from 'vue'\nimport { RenderContextKey } from './renderContext.ts'\n\n/**\n * Set the doctype for the current email template.\n *\n * Usage in SFC <script setup>:\n * ```ts\n * useDoctype('<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">')\n * ```\n */\nexport function useDoctype(doctype: string): void {\n const ctx = inject(RenderContextKey)\n if (ctx) ctx.doctype = doctype\n}\n"],"mappings":";;;;;;;;;;;AAWA,SAAgB,WAAW,SAAuB;CAChD,MAAM,MAAM,OAAO,gBAAgB;CACnC,IAAI,KAAK,IAAI,UAAU;AACzB"}
@@ -1 +1 @@
1
- {"version":3,"file":"useEvent.js","names":[],"sources":["../../src/composables/useEvent.ts"],"sourcesContent":["import { inject } from 'vue'\nimport { RenderContextKey } from './renderContext.ts'\nimport type { EventName, EventMap } from '../events/index.ts'\n\n/**\n * Register an event handler from within an SFC's <script setup>.\n *\n * Usage:\n * ```ts\n * useEvent('beforeRender', ({ config, template }) => {\n * return template.source.replace('foo', 'bar')\n * })\n * ```\n */\nexport function useEvent<K extends EventName>(name: K, handler: EventMap[K]) {\n const ctx = inject(RenderContextKey)\n if (ctx) ctx.sfcEventHandlers.push({ name, handler })\n}\n"],"mappings":";;;;;;;;;;;;;AAcA,SAAgB,SAA8B,MAAS,SAAsB;CAC3E,MAAM,MAAM,OAAO,iBAAiB;CACpC,IAAI,KAAK,IAAI,iBAAiB,KAAK;EAAE;EAAM;EAAS,CAAC"}
1
+ {"version":3,"file":"useEvent.js","names":[],"sources":["../../src/composables/useEvent.ts"],"sourcesContent":["import { inject } from 'vue'\nimport { RenderContextKey } from './renderContext.ts'\nimport type { EventName, EventMap } from '../events/index.ts'\n\n/**\n * Register an event handler from within an SFC's <script setup>.\n *\n * Usage:\n * ```ts\n * useEvent('beforeRender', ({ config, template }) => {\n * return template.source.replace('foo', 'bar')\n * })\n * ```\n */\nexport function useEvent<K extends EventName>(name: K, handler: EventMap[K]) {\n const ctx = inject(RenderContextKey)\n if (ctx) ctx.sfcEventHandlers.push({ name, handler })\n}\n"],"mappings":";;;;;;;;;;;;;AAcA,SAAgB,SAA8B,MAAS,SAAsB;CAC3E,MAAM,MAAM,OAAO,gBAAgB;CACnC,IAAI,KAAK,IAAI,iBAAiB,KAAK;EAAE;EAAM;CAAQ,CAAC;AACtD"}
@@ -1 +1 @@
1
- {"version":3,"file":"useFont.d.ts","names":[],"sources":["../../src/composables/useFont.ts"],"mappings":";KA8CY,YAAA;AAAA,UAEK,cAAA;EAFO;;;;AAExB;;EAOE,MAAA;EAoBc;EAlBd,QAAA;EAAA;;;;;EAMA,QAAA,GAAW,YAAA;EAYX;;;;AA+CF;EArDE,GAAA;;EAEA,OAAA;EAmD6C;EAjD7C,OAAA;;EAEA,MAAA,GAAS,KAAA;AAAA;;;;;;;;;;;;;;;;iBA+CK,OAAA,CAAQ,OAAA,EAAS,cAAA"}
1
+ {"version":3,"file":"useFont.d.ts","names":[],"sources":["../../src/composables/useFont.ts"],"mappings":";KA8CY,YAAA;AAAA,UAEK,cAAA;EAFO;;;AAAA;AAExB;;EAOE,MAAA;EAoBc;EAlBd,QAAA;EAAA;;;;;EAMA,QAAA,GAAW,YAAA;EAYX;;;AAAc;AA+ChB;EArDE,GAAA;;EAEA,OAAA;EAmD6C;EAjD7C,OAAA;;EAEA,MAAA,GAAS,KAAK;AAAA;;;;;;;;;;;;;;;;iBA+CA,OAAA,CAAQ,OAAuB,EAAd,cAAc"}
@@ -1 +1 @@
1
- {"version":3,"file":"useFont.js","names":[],"sources":["../../src/composables/useFont.ts"],"sourcesContent":["import { inject } from 'vue'\nimport { RenderContextKey } from './renderContext.ts'\n\ntype FontCategory = 'sans' | 'serif' | 'mono' | 'display' | 'handwriting'\n\nconst FAMILY_CATEGORIES: Record<string, FontCategory> = {\n // Sans-serif\n 'Roboto': 'sans',\n 'Open Sans': 'sans',\n 'Inter': 'sans',\n 'Lato': 'sans',\n 'Montserrat': 'sans',\n // Serif\n 'Merriweather': 'serif',\n 'Playfair Display': 'serif',\n 'Lora': 'serif',\n 'PT Serif': 'serif',\n 'Noto Serif': 'serif',\n // Display\n 'Oswald': 'display',\n 'Bebas Neue': 'display',\n 'Anton': 'display',\n 'Lobster': 'display',\n 'Pacifico': 'display',\n // Handwriting\n 'Dancing Script': 'handwriting',\n 'Caveat': 'handwriting',\n 'Shadows Into Light': 'handwriting',\n 'Satisfy': 'handwriting',\n 'Great Vibes': 'handwriting',\n // Monospace\n 'Roboto Mono': 'mono',\n 'Source Code Pro': 'mono',\n 'JetBrains Mono': 'mono',\n 'Fira Code': 'mono',\n 'Inconsolata': 'mono',\n}\n\nconst DEFAULT_FALLBACKS: Record<FontCategory, string> = {\n sans: 'ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", sans-serif',\n serif: 'ui-serif, Georgia, Cambria, \"Times New Roman\", Times, serif',\n mono: 'ui-monospace, Menlo, Consolas, monospace',\n display: 'Impact, \"Arial Black\", system-ui, sans-serif',\n handwriting: '\"Segoe Script\", \"Brush Script MT\", cursive',\n}\n\nexport type FontProvider = 'google' | 'bunny'\n\nexport interface UseFontOptions {\n /**\n * A single font family name, e.g. `\"Roboto\"` or `\"Open Sans\"`.\n *\n * For fallback fonts, use the `fallback` option instead of a\n * comma-separated list here.\n */\n family: string\n /** CSS fallback list appended to the `font-family` declaration. */\n fallback?: string\n /**\n * Font provider used to build the stylesheet URL when `url` is omitted.\n * Bunny Fonts is a drop-in, privacy-friendly Google Fonts mirror.\n * @default 'google'\n */\n provider?: FontProvider\n /**\n * Stylesheet URL. When provided, used as-is for the `<link href>`.\n * When omitted, a URL is built from `provider`, `family`, `weights`,\n * `display` and `styles`.\n */\n url?: string\n /** Font weights to load. Ignored when `url` is provided. */\n weights?: number[]\n /** `font-display` value. Ignored when `url` is provided. */\n display?: 'auto' | 'block' | 'swap' | 'fallback' | 'optional'\n /** Font styles to load. Ignored when `url` is provided. */\n styles?: Array<'normal' | 'italic'>\n}\n\nconst PROVIDER_BASE_URL: Record<FontProvider, string> = {\n google: 'https://fonts.googleapis.com/css2',\n bunny: 'https://fonts.bunny.net/css2',\n}\n\nfunction slugify(family: string): string {\n return family\n .trim()\n .toLowerCase()\n .replace(/\\s+/g, '-')\n .replace(/[^a-z0-9-]/g, '')\n}\n\nfunction buildProviderUrl(opts: Required<Omit<UseFontOptions, 'url' | 'fallback'>>): string {\n const familyParam = opts.family.trim().replace(/\\s+/g, '+')\n const weights = [...opts.weights].sort((a, b) => a - b)\n const hasItalic = opts.styles.includes('italic')\n const hasNormal = opts.styles.includes('normal')\n\n const axis = hasItalic\n ? `:ital,wght@${weights.flatMap(w => [\n ...(hasNormal ? [`0,${w}`] : []),\n `1,${w}`,\n ]).join(';')}`\n : `:wght@${weights.join(';')}`\n\n return `${PROVIDER_BASE_URL[opts.provider]}?family=${familyParam}${axis}&display=${opts.display}`\n}\n\n/**\n * Register a font for the current email template.\n *\n * Builds a Google Fonts stylesheet URL from `family`/`weights`/`display`/`styles`\n * (or uses `url` as-is). The renderer injects a `<link>` tag into `<head>`\n * and merges `--font-{slug}` declarations into the template's existing\n * `@import \"tailwindcss\"` style block so a `font-{slug}` utility class\n * is generated. If no Tailwind import is found, falls back to a `:root`\n * declaration so the CSS variable is still available.\n *\n * Usage in SFC <script setup>:\n * ```ts\n * useFont({ family: 'Roboto', fallback: 'Verdana, sans-serif', weights: [400, 600] })\n * ```\n */\nexport function useFont(options: UseFontOptions): void {\n const ctx = inject(RenderContextKey)\n if (!ctx) return\n\n ctx.fonts = ctx.fonts ?? []\n if (ctx.fonts.some(f => f.family === options.family)) return\n\n const url = options.url ?? buildProviderUrl({\n family: options.family,\n provider: options.provider ?? 'google',\n weights: options.weights ?? [400],\n display: options.display ?? 'swap',\n styles: options.styles ?? ['normal'],\n })\n\n const fallback = options.fallback\n ?? DEFAULT_FALLBACKS[FAMILY_CATEGORIES[options.family] ?? 'sans']\n const quoted = /\\s/.test(options.family) ? `\"${options.family}\"` : options.family\n const declaration = `${quoted}, ${fallback}`\n\n ctx.fonts.push({\n family: options.family,\n slug: slugify(options.family),\n declaration,\n url,\n })\n}\n"],"mappings":";;;AAKA,MAAM,oBAAkD;CAEtD,UAAU;CACV,aAAa;CACb,SAAS;CACT,QAAQ;CACR,cAAc;CAEd,gBAAgB;CAChB,oBAAoB;CACpB,QAAQ;CACR,YAAY;CACZ,cAAc;CAEd,UAAU;CACV,cAAc;CACd,SAAS;CACT,WAAW;CACX,YAAY;CAEZ,kBAAkB;CAClB,UAAU;CACV,sBAAsB;CACtB,WAAW;CACX,eAAe;CAEf,eAAe;CACf,mBAAmB;CACnB,kBAAkB;CAClB,aAAa;CACb,eAAe;CAChB;AAED,MAAM,oBAAkD;CACtD,MAAM;CACN,OAAO;CACP,MAAM;CACN,SAAS;CACT,aAAa;CACd;AAkCD,MAAM,oBAAkD;CACtD,QAAQ;CACR,OAAO;CACR;AAED,SAAS,QAAQ,QAAwB;CACvC,OAAO,OACJ,MAAM,CACN,aAAa,CACb,QAAQ,QAAQ,IAAI,CACpB,QAAQ,eAAe,GAAG;;AAG/B,SAAS,iBAAiB,MAAkE;CAC1F,MAAM,cAAc,KAAK,OAAO,MAAM,CAAC,QAAQ,QAAQ,IAAI;CAC3D,MAAM,UAAU,CAAC,GAAG,KAAK,QAAQ,CAAC,MAAM,GAAG,MAAM,IAAI,EAAE;CACvD,MAAM,YAAY,KAAK,OAAO,SAAS,SAAS;CAChD,MAAM,YAAY,KAAK,OAAO,SAAS,SAAS;CAEhD,MAAM,OAAO,YACT,cAAc,QAAQ,SAAQ,MAAK,CACjC,GAAI,YAAY,CAAC,KAAK,IAAI,GAAG,EAAE,EAC/B,KAAK,IACN,CAAC,CAAC,KAAK,IAAI,KACZ,SAAS,QAAQ,KAAK,IAAI;CAE9B,OAAO,GAAG,kBAAkB,KAAK,UAAU,UAAU,cAAc,KAAK,WAAW,KAAK;;;;;;;;;;;;;;;;;AAkB1F,SAAgB,QAAQ,SAA+B;CACrD,MAAM,MAAM,OAAO,iBAAiB;CACpC,IAAI,CAAC,KAAK;CAEV,IAAI,QAAQ,IAAI,SAAS,EAAE;CAC3B,IAAI,IAAI,MAAM,MAAK,MAAK,EAAE,WAAW,QAAQ,OAAO,EAAE;CAEtD,MAAM,MAAM,QAAQ,OAAO,iBAAiB;EAC1C,QAAQ,QAAQ;EAChB,UAAU,QAAQ,YAAY;EAC9B,SAAS,QAAQ,WAAW,CAAC,IAAI;EACjC,SAAS,QAAQ,WAAW;EAC5B,QAAQ,QAAQ,UAAU,CAAC,SAAS;EACrC,CAAC;CAEF,MAAM,WAAW,QAAQ,YACpB,kBAAkB,kBAAkB,QAAQ,WAAW;CAE5D,MAAM,cAAc,GADL,KAAK,KAAK,QAAQ,OAAO,GAAG,IAAI,QAAQ,OAAO,KAAK,QAAQ,OAC7C,IAAI;CAElC,IAAI,MAAM,KAAK;EACb,QAAQ,QAAQ;EAChB,MAAM,QAAQ,QAAQ,OAAO;EAC7B;EACA;EACD,CAAC"}
1
+ {"version":3,"file":"useFont.js","names":[],"sources":["../../src/composables/useFont.ts"],"sourcesContent":["import { inject } from 'vue'\nimport { RenderContextKey } from './renderContext.ts'\n\ntype FontCategory = 'sans' | 'serif' | 'mono' | 'display' | 'handwriting'\n\nconst FAMILY_CATEGORIES: Record<string, FontCategory> = {\n // Sans-serif\n 'Roboto': 'sans',\n 'Open Sans': 'sans',\n 'Inter': 'sans',\n 'Lato': 'sans',\n 'Montserrat': 'sans',\n // Serif\n 'Merriweather': 'serif',\n 'Playfair Display': 'serif',\n 'Lora': 'serif',\n 'PT Serif': 'serif',\n 'Noto Serif': 'serif',\n // Display\n 'Oswald': 'display',\n 'Bebas Neue': 'display',\n 'Anton': 'display',\n 'Lobster': 'display',\n 'Pacifico': 'display',\n // Handwriting\n 'Dancing Script': 'handwriting',\n 'Caveat': 'handwriting',\n 'Shadows Into Light': 'handwriting',\n 'Satisfy': 'handwriting',\n 'Great Vibes': 'handwriting',\n // Monospace\n 'Roboto Mono': 'mono',\n 'Source Code Pro': 'mono',\n 'JetBrains Mono': 'mono',\n 'Fira Code': 'mono',\n 'Inconsolata': 'mono',\n}\n\nconst DEFAULT_FALLBACKS: Record<FontCategory, string> = {\n sans: 'ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", sans-serif',\n serif: 'ui-serif, Georgia, Cambria, \"Times New Roman\", Times, serif',\n mono: 'ui-monospace, Menlo, Consolas, monospace',\n display: 'Impact, \"Arial Black\", system-ui, sans-serif',\n handwriting: '\"Segoe Script\", \"Brush Script MT\", cursive',\n}\n\nexport type FontProvider = 'google' | 'bunny'\n\nexport interface UseFontOptions {\n /**\n * A single font family name, e.g. `\"Roboto\"` or `\"Open Sans\"`.\n *\n * For fallback fonts, use the `fallback` option instead of a\n * comma-separated list here.\n */\n family: string\n /** CSS fallback list appended to the `font-family` declaration. */\n fallback?: string\n /**\n * Font provider used to build the stylesheet URL when `url` is omitted.\n * Bunny Fonts is a drop-in, privacy-friendly Google Fonts mirror.\n * @default 'google'\n */\n provider?: FontProvider\n /**\n * Stylesheet URL. When provided, used as-is for the `<link href>`.\n * When omitted, a URL is built from `provider`, `family`, `weights`,\n * `display` and `styles`.\n */\n url?: string\n /** Font weights to load. Ignored when `url` is provided. */\n weights?: number[]\n /** `font-display` value. Ignored when `url` is provided. */\n display?: 'auto' | 'block' | 'swap' | 'fallback' | 'optional'\n /** Font styles to load. Ignored when `url` is provided. */\n styles?: Array<'normal' | 'italic'>\n}\n\nconst PROVIDER_BASE_URL: Record<FontProvider, string> = {\n google: 'https://fonts.googleapis.com/css2',\n bunny: 'https://fonts.bunny.net/css2',\n}\n\nfunction slugify(family: string): string {\n return family\n .trim()\n .toLowerCase()\n .replace(/\\s+/g, '-')\n .replace(/[^a-z0-9-]/g, '')\n}\n\nfunction buildProviderUrl(opts: Required<Omit<UseFontOptions, 'url' | 'fallback'>>): string {\n const familyParam = opts.family.trim().replace(/\\s+/g, '+')\n const weights = [...opts.weights].sort((a, b) => a - b)\n const hasItalic = opts.styles.includes('italic')\n const hasNormal = opts.styles.includes('normal')\n\n const axis = hasItalic\n ? `:ital,wght@${weights.flatMap(w => [\n ...(hasNormal ? [`0,${w}`] : []),\n `1,${w}`,\n ]).join(';')}`\n : `:wght@${weights.join(';')}`\n\n return `${PROVIDER_BASE_URL[opts.provider]}?family=${familyParam}${axis}&display=${opts.display}`\n}\n\n/**\n * Register a font for the current email template.\n *\n * Builds a Google Fonts stylesheet URL from `family`/`weights`/`display`/`styles`\n * (or uses `url` as-is). The renderer injects a `<link>` tag into `<head>`\n * and merges `--font-{slug}` declarations into the template's existing\n * `@import \"tailwindcss\"` style block so a `font-{slug}` utility class\n * is generated. If no Tailwind import is found, falls back to a `:root`\n * declaration so the CSS variable is still available.\n *\n * Usage in SFC <script setup>:\n * ```ts\n * useFont({ family: 'Roboto', fallback: 'Verdana, sans-serif', weights: [400, 600] })\n * ```\n */\nexport function useFont(options: UseFontOptions): void {\n const ctx = inject(RenderContextKey)\n if (!ctx) return\n\n ctx.fonts = ctx.fonts ?? []\n if (ctx.fonts.some(f => f.family === options.family)) return\n\n const url = options.url ?? buildProviderUrl({\n family: options.family,\n provider: options.provider ?? 'google',\n weights: options.weights ?? [400],\n display: options.display ?? 'swap',\n styles: options.styles ?? ['normal'],\n })\n\n const fallback = options.fallback\n ?? DEFAULT_FALLBACKS[FAMILY_CATEGORIES[options.family] ?? 'sans']\n const quoted = /\\s/.test(options.family) ? `\"${options.family}\"` : options.family\n const declaration = `${quoted}, ${fallback}`\n\n ctx.fonts.push({\n family: options.family,\n slug: slugify(options.family),\n declaration,\n url,\n })\n}\n"],"mappings":";;;AAKA,MAAM,oBAAkD;CAEtD,UAAU;CACV,aAAa;CACb,SAAS;CACT,QAAQ;CACR,cAAc;CAEd,gBAAgB;CAChB,oBAAoB;CACpB,QAAQ;CACR,YAAY;CACZ,cAAc;CAEd,UAAU;CACV,cAAc;CACd,SAAS;CACT,WAAW;CACX,YAAY;CAEZ,kBAAkB;CAClB,UAAU;CACV,sBAAsB;CACtB,WAAW;CACX,eAAe;CAEf,eAAe;CACf,mBAAmB;CACnB,kBAAkB;CAClB,aAAa;CACb,eAAe;AACjB;AAEA,MAAM,oBAAkD;CACtD,MAAM;CACN,OAAO;CACP,MAAM;CACN,SAAS;CACT,aAAa;AACf;AAkCA,MAAM,oBAAkD;CACtD,QAAQ;CACR,OAAO;AACT;AAEA,SAAS,QAAQ,QAAwB;CACvC,OAAO,OACJ,KAAK,EACL,YAAY,EACZ,QAAQ,QAAQ,GAAG,EACnB,QAAQ,eAAe,EAAE;AAC9B;AAEA,SAAS,iBAAiB,MAAkE;CAC1F,MAAM,cAAc,KAAK,OAAO,KAAK,EAAE,QAAQ,QAAQ,GAAG;CAC1D,MAAM,UAAU,CAAC,GAAG,KAAK,OAAO,EAAE,MAAM,GAAG,MAAM,IAAI,CAAC;CACtD,MAAM,YAAY,KAAK,OAAO,SAAS,QAAQ;CAC/C,MAAM,YAAY,KAAK,OAAO,SAAS,QAAQ;CAE/C,MAAM,OAAO,YACT,cAAc,QAAQ,SAAQ,MAAK,CACjC,GAAI,YAAY,CAAC,KAAK,GAAG,IAAI,CAAC,GAC9B,KAAK,GACP,CAAC,EAAE,KAAK,GAAG,MACX,SAAS,QAAQ,KAAK,GAAG;CAE7B,OAAO,GAAG,kBAAkB,KAAK,UAAU,UAAU,cAAc,KAAK,WAAW,KAAK;AAC1F;;;;;;;;;;;;;;;;AAiBA,SAAgB,QAAQ,SAA+B;CACrD,MAAM,MAAM,OAAO,gBAAgB;CACnC,IAAI,CAAC,KAAK;CAEV,IAAI,QAAQ,IAAI,SAAS,CAAC;CAC1B,IAAI,IAAI,MAAM,MAAK,MAAK,EAAE,WAAW,QAAQ,MAAM,GAAG;CAEtD,MAAM,MAAM,QAAQ,OAAO,iBAAiB;EAC1C,QAAQ,QAAQ;EAChB,UAAU,QAAQ,YAAY;EAC9B,SAAS,QAAQ,WAAW,CAAC,GAAG;EAChC,SAAS,QAAQ,WAAW;EAC5B,QAAQ,QAAQ,UAAU,CAAC,QAAQ;CACrC,CAAC;CAED,MAAM,WAAW,QAAQ,YACpB,kBAAkB,kBAAkB,QAAQ,WAAW;CAE5D,MAAM,cAAc,GADL,KAAK,KAAK,QAAQ,MAAM,IAAI,IAAI,QAAQ,OAAO,KAAK,QAAQ,OAC7C,IAAI;CAElC,IAAI,MAAM,KAAK;EACb,QAAQ,QAAQ;EAChB,MAAM,QAAQ,QAAQ,MAAM;EAC5B;EACA;CACF,CAAC;AACH"}
@@ -1 +1 @@
1
- {"version":3,"file":"useOutlookFallback.d.ts","names":[],"sources":["../../src/composables/useOutlookFallback.ts"],"mappings":";;AAoBA;;;;;;;;;;;;;;;iBAAgB,kBAAA,CAAmB,KAAA"}
1
+ {"version":3,"file":"useOutlookFallback.d.ts","names":[],"sources":["../../src/composables/useOutlookFallback.ts"],"mappings":";;AAoBA;;;;AAAyD;;;;;;;;;;;iBAAzC,kBAAA,CAAmB,KAAsB"}
@@ -1 +1 @@
1
- {"version":3,"file":"useOutlookFallback.js","names":[],"sources":["../../src/composables/useOutlookFallback.ts"],"sourcesContent":["import { inject, provide, type InjectionKey } from 'vue'\n\nconst OutlookFallbackKey: InjectionKey<boolean> = Symbol('OutlookFallback')\n\n/**\n * Toggle whether descendants emit Outlook (MSO) and VML fallback markup.\n *\n * Call once in a Layout/template's `<script setup>` to disable for the\n * whole tree:\n * `useOutlookFallback(false)`\n *\n * Components inheriting `false` skip MSO ghost tables, VML rectangles,\n * `xmlns:v`/`xmlns:o`, mso-specific CSS, and Button's `<Outlook>`\n * spacers. Each MSO-aware component still accepts an `outlook-fallback`\n * prop that overrides inheritance for its subtree.\n *\n * @param value Pass `true`/`false` to set; omit to just read the\n * inherited value (defaults to `true` at the root).\n * @returns The resolved boolean for the current component.\n */\nexport function useOutlookFallback(value?: boolean | null): boolean {\n const inherited = inject(OutlookFallbackKey, true)\n const enabled = value == null ? inherited : value\n provide(OutlookFallbackKey, enabled)\n return enabled\n}\n"],"mappings":";;AAEA,MAAM,qBAA4C,OAAO,kBAAkB;;;;;;;;;;;;;;;;;AAkB3E,SAAgB,mBAAmB,OAAiC;CAClE,MAAM,YAAY,OAAO,oBAAoB,KAAK;CAClD,MAAM,UAAU,SAAS,OAAO,YAAY;CAC5C,QAAQ,oBAAoB,QAAQ;CACpC,OAAO"}
1
+ {"version":3,"file":"useOutlookFallback.js","names":[],"sources":["../../src/composables/useOutlookFallback.ts"],"sourcesContent":["import { inject, provide, type InjectionKey } from 'vue'\n\nconst OutlookFallbackKey: InjectionKey<boolean> = Symbol('OutlookFallback')\n\n/**\n * Toggle whether descendants emit Outlook (MSO) and VML fallback markup.\n *\n * Call once in a Layout/template's `<script setup>` to disable for the\n * whole tree:\n * `useOutlookFallback(false)`\n *\n * Components inheriting `false` skip MSO ghost tables, VML rectangles,\n * `xmlns:v`/`xmlns:o`, mso-specific CSS, and Button's `<Outlook>`\n * spacers. Each MSO-aware component still accepts an `outlook-fallback`\n * prop that overrides inheritance for its subtree.\n *\n * @param value Pass `true`/`false` to set; omit to just read the\n * inherited value (defaults to `true` at the root).\n * @returns The resolved boolean for the current component.\n */\nexport function useOutlookFallback(value?: boolean | null): boolean {\n const inherited = inject(OutlookFallbackKey, true)\n const enabled = value == null ? inherited : value\n provide(OutlookFallbackKey, enabled)\n return enabled\n}\n"],"mappings":";;AAEA,MAAM,qBAA4C,OAAO,iBAAiB;;;;;;;;;;;;;;;;;AAkB1E,SAAgB,mBAAmB,OAAiC;CAClE,MAAM,YAAY,OAAO,oBAAoB,IAAI;CACjD,MAAM,UAAU,SAAS,OAAO,YAAY;CAC5C,QAAQ,oBAAoB,OAAO;CACnC,OAAO;AACT"}
@@ -0,0 +1,17 @@
1
+ //#region src/composables/useOutputPath.d.ts
2
+ /**
3
+ * Override the output file path for the current template.
4
+ *
5
+ * The path is relative to the project root (cwd); it may be
6
+ * absolute or escape the output directory with `../`. If it
7
+ * has no extension, `output.extension` is appended.
8
+ *
9
+ * Usage in SFC <script setup>:
10
+ * ```ts
11
+ * useOutputPath('dist/promos/black-friday.html')
12
+ * ```
13
+ */
14
+ declare function useOutputPath(path: string): void;
15
+ //#endregion
16
+ export { useOutputPath };
17
+ //# sourceMappingURL=useOutputPath.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useOutputPath.d.ts","names":[],"sources":["../../src/composables/useOutputPath.ts"],"mappings":";;AAeA;;;;AAA0C;;;;;;;iBAA1B,aAAA,CAAc,IAAY"}