@maizzle/framework 6.0.0-rc.15 → 6.0.0-rc.17

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 (250) hide show
  1. package/README.md +3 -3
  2. package/dist/{build.d.mts → build.d.ts} +2 -2
  3. package/dist/build.d.ts.map +1 -0
  4. package/dist/build.mjs +1 -1
  5. package/dist/build.mjs.map +1 -1
  6. package/dist/components/Body.vue +9 -2
  7. package/dist/components/Button.vue +13 -8
  8. package/dist/components/Column.vue +22 -8
  9. package/dist/components/Container.vue +9 -5
  10. package/dist/components/Html.vue +7 -2
  11. package/dist/components/Layout.vue +30 -15
  12. package/dist/components/Overlap.vue +8 -3
  13. package/dist/components/Raw.vue +28 -0
  14. package/dist/components/Row.vue +23 -11
  15. package/dist/components/Section.vue +9 -5
  16. package/dist/components/Spacer.vue +9 -4
  17. package/dist/components/Tailwind.vue +43 -0
  18. package/dist/components/{utils.d.mts → utils.d.ts} +12 -2
  19. package/dist/components/utils.d.ts.map +1 -0
  20. package/dist/components/utils.mjs +11 -1
  21. package/dist/components/utils.mjs.map +1 -1
  22. package/dist/components/utils.ts +12 -0
  23. package/dist/composables/{defineConfig.d.mts → defineConfig.d.ts} +2 -2
  24. package/dist/composables/defineConfig.d.ts.map +1 -0
  25. package/dist/composables/{renderContext.d.mts → renderContext.d.ts} +11 -5
  26. package/dist/composables/renderContext.d.ts.map +1 -0
  27. package/dist/composables/renderContext.mjs.map +1 -1
  28. package/dist/composables/{useConfig.d.mts → useConfig.d.ts} +2 -2
  29. package/dist/composables/useConfig.d.ts.map +1 -0
  30. package/dist/composables/{useDoctype.d.mts → useDoctype.d.ts} +1 -1
  31. package/dist/composables/useDoctype.d.ts.map +1 -0
  32. package/dist/composables/{useEvent.d.mts → useEvent.d.ts} +2 -2
  33. package/dist/composables/useEvent.d.ts.map +1 -0
  34. package/dist/composables/{useFont.d.mts → useFont.d.ts} +1 -1
  35. package/dist/composables/useFont.d.ts.map +1 -0
  36. package/dist/composables/useOutlookFallback.d.ts +21 -0
  37. package/dist/composables/useOutlookFallback.d.ts.map +1 -0
  38. package/dist/composables/useOutlookFallback.mjs +30 -0
  39. package/dist/composables/useOutlookFallback.mjs.map +1 -0
  40. package/dist/composables/{usePlaintext.d.mts → usePlaintext.d.ts} +1 -1
  41. package/dist/composables/usePlaintext.d.ts.map +1 -0
  42. package/dist/composables/{usePreheader.d.mts → usePreheader.d.ts} +1 -1
  43. package/dist/composables/usePreheader.d.ts.map +1 -0
  44. package/dist/config/{defaults.d.mts → defaults.d.ts} +2 -2
  45. package/dist/config/defaults.d.ts.map +1 -0
  46. package/dist/config/{index.d.mts → index.d.ts} +4 -4
  47. package/dist/config/index.d.ts.map +1 -0
  48. package/dist/events/{index.d.mts → index.d.ts} +2 -2
  49. package/dist/events/index.d.ts.map +1 -0
  50. package/dist/index.d.ts +34 -0
  51. package/dist/index.mjs +2 -1
  52. package/dist/{plaintext.d.mts → plaintext.d.ts} +1 -1
  53. package/dist/plaintext.d.ts.map +1 -0
  54. package/dist/{plugin.d.mts → plugin.d.ts} +2 -2
  55. package/dist/plugin.d.ts.map +1 -0
  56. package/dist/plugins/postcss/{mergeMediaQueries.d.mts → mergeMediaQueries.d.ts} +2 -2
  57. package/dist/plugins/postcss/mergeMediaQueries.d.ts.map +1 -0
  58. package/dist/plugins/postcss/{pruneVars.d.mts → pruneVars.d.ts} +1 -1
  59. package/dist/plugins/postcss/pruneVars.d.ts.map +1 -0
  60. package/dist/plugins/postcss/{quoteFontFamilies.d.mts → quoteFontFamilies.d.ts} +1 -1
  61. package/dist/plugins/postcss/quoteFontFamilies.d.ts.map +1 -0
  62. package/dist/plugins/postcss/{removeDeclarations.d.mts → removeDeclarations.d.ts} +1 -1
  63. package/dist/plugins/postcss/removeDeclarations.d.ts.map +1 -0
  64. package/dist/plugins/postcss/resolveMaizzleImports.d.ts +16 -0
  65. package/dist/plugins/postcss/resolveMaizzleImports.d.ts.map +1 -0
  66. package/dist/plugins/postcss/resolveMaizzleImports.mjs +40 -0
  67. package/dist/plugins/postcss/resolveMaizzleImports.mjs.map +1 -0
  68. package/dist/plugins/postcss/{resolveProps.d.mts → resolveProps.d.ts} +1 -1
  69. package/dist/plugins/postcss/resolveProps.d.ts.map +1 -0
  70. package/dist/plugins/postcss/{tailwindCleanup.d.mts → tailwindCleanup.d.ts} +2 -2
  71. package/dist/plugins/postcss/tailwindCleanup.d.ts.map +1 -0
  72. package/dist/{prepare.d.mts → prepare.d.ts} +1 -1
  73. package/dist/prepare.d.ts.map +1 -0
  74. package/dist/render/{createRenderer.d.mts → createRenderer.d.ts} +4 -3
  75. package/dist/render/createRenderer.d.ts.map +1 -0
  76. package/dist/render/createRenderer.mjs +9 -76
  77. package/dist/render/createRenderer.mjs.map +1 -1
  78. package/dist/render/index.d.ts +18 -0
  79. package/dist/render/index.d.ts.map +1 -0
  80. package/dist/render/index.mjs +13 -14
  81. package/dist/render/index.mjs.map +1 -1
  82. package/dist/render/{injectFonts.d.mts → injectFonts.d.ts} +2 -2
  83. package/dist/render/injectFonts.d.ts.map +1 -0
  84. package/dist/render/plugins/codeBlockExtract.d.ts +14 -0
  85. package/dist/render/plugins/codeBlockExtract.d.ts.map +1 -0
  86. package/dist/render/plugins/codeBlockExtract.mjs +34 -0
  87. package/dist/render/plugins/codeBlockExtract.mjs.map +1 -0
  88. package/dist/render/plugins/markdownExtract.d.ts +12 -0
  89. package/dist/render/plugins/markdownExtract.d.ts.map +1 -0
  90. package/dist/render/plugins/markdownExtract.mjs +50 -0
  91. package/dist/render/plugins/markdownExtract.mjs.map +1 -0
  92. package/dist/render/plugins/rawExtract.d.ts +14 -0
  93. package/dist/render/plugins/rawExtract.d.ts.map +1 -0
  94. package/dist/render/plugins/rawExtract.mjs +34 -0
  95. package/dist/render/plugins/rawExtract.mjs.map +1 -0
  96. package/dist/render/plugins/{rowSourceLocation.d.mts → rowSourceLocation.d.ts} +1 -1
  97. package/dist/render/plugins/rowSourceLocation.d.ts.map +1 -0
  98. package/dist/{serve.d.mts → serve.d.ts} +2 -2
  99. package/dist/serve.d.ts.map +1 -0
  100. package/dist/serve.mjs +15 -6
  101. package/dist/serve.mjs.map +1 -1
  102. package/dist/server/{compatibility.d.mts → compatibility.d.ts} +2 -2
  103. package/dist/server/compatibility.d.ts.map +1 -0
  104. package/dist/server/{email.d.mts → email.d.ts} +2 -2
  105. package/dist/server/email.d.ts.map +1 -0
  106. package/dist/server/{linter.d.mts → linter.d.ts} +2 -2
  107. package/dist/server/linter.d.ts.map +1 -0
  108. package/dist/server/{sfc-utils.d.mts → sfc-utils.d.ts} +1 -1
  109. package/dist/server/sfc-utils.d.ts.map +1 -0
  110. package/dist/server/ui/App.vue +47 -2
  111. package/dist/server/ui/pages/Preview.vue +110 -22
  112. package/dist/transformers/{addAttributes.d.mts → addAttributes.d.ts} +2 -2
  113. package/dist/transformers/addAttributes.d.ts.map +1 -0
  114. package/dist/transformers/{attributeToStyle.d.mts → attributeToStyle.d.ts} +2 -2
  115. package/dist/transformers/attributeToStyle.d.ts.map +1 -0
  116. package/dist/transformers/{base.d.mts → base.d.ts} +2 -2
  117. package/dist/transformers/base.d.ts.map +1 -0
  118. package/dist/transformers/{columnWidth.d.mts → columnWidth.d.ts} +10 -10
  119. package/dist/transformers/columnWidth.d.ts.map +1 -0
  120. package/dist/transformers/columnWidth.mjs +422 -41
  121. package/dist/transformers/columnWidth.mjs.map +1 -1
  122. package/dist/transformers/{entities.d.mts → entities.d.ts} +2 -2
  123. package/dist/transformers/entities.d.ts.map +1 -0
  124. package/dist/transformers/filters/{defaults.d.mts → defaults.d.ts} +1 -1
  125. package/dist/transformers/filters/defaults.d.ts.map +1 -0
  126. package/dist/transformers/filters/{index.d.mts → index.d.ts} +2 -2
  127. package/dist/transformers/filters/index.d.ts.map +1 -0
  128. package/dist/transformers/{format.d.mts → format.d.ts} +2 -2
  129. package/dist/transformers/format.d.ts.map +1 -0
  130. package/dist/transformers/{index.d.mts → index.d.ts} +4 -3
  131. package/dist/transformers/index.d.ts.map +1 -0
  132. package/dist/transformers/index.mjs +3 -1
  133. package/dist/transformers/index.mjs.map +1 -1
  134. package/dist/transformers/{inlineCSS.d.mts → inlineCSS.d.ts} +2 -2
  135. package/dist/transformers/inlineCSS.d.ts.map +1 -0
  136. package/dist/transformers/inlineCSS.mjs +7 -1
  137. package/dist/transformers/inlineCSS.mjs.map +1 -1
  138. package/dist/transformers/{inlineLink.d.mts → inlineLink.d.ts} +1 -1
  139. package/dist/transformers/inlineLink.d.ts.map +1 -0
  140. package/dist/transformers/{minify.d.mts → minify.d.ts} +2 -2
  141. package/dist/transformers/minify.d.ts.map +1 -0
  142. package/dist/transformers/{msoWidthFromClass.d.mts → msoWidthFromClass.d.ts} +1 -1
  143. package/dist/transformers/msoWidthFromClass.d.ts.map +1 -0
  144. package/dist/transformers/{purgeCSS.d.mts → purgeCSS.d.ts} +2 -2
  145. package/dist/transformers/purgeCSS.d.ts.map +1 -0
  146. package/dist/transformers/purgeCSS.mjs +44 -2
  147. package/dist/transformers/purgeCSS.mjs.map +1 -1
  148. package/dist/transformers/{removeAttributes.d.mts → removeAttributes.d.ts} +2 -2
  149. package/dist/transformers/removeAttributes.d.ts.map +1 -0
  150. package/dist/transformers/{replaceStrings.d.mts → replaceStrings.d.ts} +2 -2
  151. package/dist/transformers/replaceStrings.d.ts.map +1 -0
  152. package/dist/transformers/{safeClassNames.d.mts → safeClassNames.d.ts} +2 -2
  153. package/dist/transformers/safeClassNames.d.ts.map +1 -0
  154. package/dist/transformers/{shorthandCSS.d.mts → shorthandCSS.d.ts} +2 -2
  155. package/dist/transformers/shorthandCSS.d.ts.map +1 -0
  156. package/dist/transformers/{sixHex.d.mts → sixHex.d.ts} +2 -2
  157. package/dist/transformers/sixHex.d.ts.map +1 -0
  158. package/dist/transformers/tailwindComponent.d.ts +16 -0
  159. package/dist/transformers/tailwindComponent.d.ts.map +1 -0
  160. package/dist/transformers/tailwindComponent.mjs +93 -0
  161. package/dist/transformers/tailwindComponent.mjs.map +1 -0
  162. package/dist/transformers/{tailwindcss.d.mts → tailwindcss.d.ts} +2 -2
  163. package/dist/transformers/tailwindcss.d.ts.map +1 -0
  164. package/dist/transformers/tailwindcss.mjs +2 -54
  165. package/dist/transformers/tailwindcss.mjs.map +1 -1
  166. package/dist/transformers/{urlQuery.d.mts → urlQuery.d.ts} +2 -2
  167. package/dist/transformers/urlQuery.d.ts.map +1 -0
  168. package/dist/types/{config.d.mts → config.d.ts} +2 -2
  169. package/dist/types/config.d.ts.map +1 -0
  170. package/dist/types/{index.d.mts → index.d.ts} +1 -1
  171. package/dist/utils/ast/index.d.ts +4 -0
  172. package/dist/utils/ast/{parser.d.mts → parser.d.ts} +1 -1
  173. package/dist/utils/ast/parser.d.ts.map +1 -0
  174. package/dist/utils/ast/{serializer.d.mts → serializer.d.ts} +1 -1
  175. package/dist/utils/ast/serializer.d.ts.map +1 -0
  176. package/dist/utils/ast/{walker.d.mts → walker.d.ts} +1 -1
  177. package/dist/utils/ast/walker.d.ts.map +1 -0
  178. package/dist/utils/compileTailwindCss.d.ts +16 -0
  179. package/dist/utils/compileTailwindCss.d.ts.map +1 -0
  180. package/dist/utils/compileTailwindCss.mjs +55 -0
  181. package/dist/utils/compileTailwindCss.mjs.map +1 -0
  182. package/dist/utils/{decodeStyleEntities.d.mts → decodeStyleEntities.d.ts} +1 -1
  183. package/dist/utils/decodeStyleEntities.d.ts.map +1 -0
  184. package/dist/utils/{detect.d.mts → detect.d.ts} +1 -1
  185. package/dist/utils/detect.d.ts.map +1 -0
  186. package/dist/utils/{url.d.mts → url.d.ts} +1 -1
  187. package/dist/utils/url.d.ts.map +1 -0
  188. package/package.json +13 -6
  189. package/dist/build.d.mts.map +0 -1
  190. package/dist/components/utils.d.mts.map +0 -1
  191. package/dist/composables/defineConfig.d.mts.map +0 -1
  192. package/dist/composables/renderContext.d.mts.map +0 -1
  193. package/dist/composables/useConfig.d.mts.map +0 -1
  194. package/dist/composables/useDoctype.d.mts.map +0 -1
  195. package/dist/composables/useEvent.d.mts.map +0 -1
  196. package/dist/composables/useFont.d.mts.map +0 -1
  197. package/dist/composables/usePlaintext.d.mts.map +0 -1
  198. package/dist/composables/usePreheader.d.mts.map +0 -1
  199. package/dist/config/defaults.d.mts.map +0 -1
  200. package/dist/config/index.d.mts.map +0 -1
  201. package/dist/events/index.d.mts.map +0 -1
  202. package/dist/index.d.mts +0 -33
  203. package/dist/plaintext.d.mts.map +0 -1
  204. package/dist/plugin.d.mts.map +0 -1
  205. package/dist/plugins/postcss/mergeMediaQueries.d.mts.map +0 -1
  206. package/dist/plugins/postcss/pruneVars.d.mts.map +0 -1
  207. package/dist/plugins/postcss/quoteFontFamilies.d.mts.map +0 -1
  208. package/dist/plugins/postcss/removeDeclarations.d.mts.map +0 -1
  209. package/dist/plugins/postcss/resolveProps.d.mts.map +0 -1
  210. package/dist/plugins/postcss/tailwindCleanup.d.mts.map +0 -1
  211. package/dist/prepare.d.mts.map +0 -1
  212. package/dist/render/createRenderer.d.mts.map +0 -1
  213. package/dist/render/index.d.mts +0 -26
  214. package/dist/render/index.d.mts.map +0 -1
  215. package/dist/render/injectFonts.d.mts.map +0 -1
  216. package/dist/render/plugins/rowSourceLocation.d.mts.map +0 -1
  217. package/dist/serve.d.mts.map +0 -1
  218. package/dist/server/compatibility.d.mts.map +0 -1
  219. package/dist/server/email.d.mts.map +0 -1
  220. package/dist/server/linter.d.mts.map +0 -1
  221. package/dist/server/sfc-utils.d.mts.map +0 -1
  222. package/dist/transformers/addAttributes.d.mts.map +0 -1
  223. package/dist/transformers/attributeToStyle.d.mts.map +0 -1
  224. package/dist/transformers/base.d.mts.map +0 -1
  225. package/dist/transformers/columnWidth.d.mts.map +0 -1
  226. package/dist/transformers/entities.d.mts.map +0 -1
  227. package/dist/transformers/filters/defaults.d.mts.map +0 -1
  228. package/dist/transformers/filters/index.d.mts.map +0 -1
  229. package/dist/transformers/format.d.mts.map +0 -1
  230. package/dist/transformers/index.d.mts.map +0 -1
  231. package/dist/transformers/inlineCSS.d.mts.map +0 -1
  232. package/dist/transformers/inlineLink.d.mts.map +0 -1
  233. package/dist/transformers/minify.d.mts.map +0 -1
  234. package/dist/transformers/msoWidthFromClass.d.mts.map +0 -1
  235. package/dist/transformers/purgeCSS.d.mts.map +0 -1
  236. package/dist/transformers/removeAttributes.d.mts.map +0 -1
  237. package/dist/transformers/replaceStrings.d.mts.map +0 -1
  238. package/dist/transformers/safeClassNames.d.mts.map +0 -1
  239. package/dist/transformers/shorthandCSS.d.mts.map +0 -1
  240. package/dist/transformers/sixHex.d.mts.map +0 -1
  241. package/dist/transformers/tailwindcss.d.mts.map +0 -1
  242. package/dist/transformers/urlQuery.d.mts.map +0 -1
  243. package/dist/types/config.d.mts.map +0 -1
  244. package/dist/utils/ast/index.d.mts +0 -4
  245. package/dist/utils/ast/parser.d.mts.map +0 -1
  246. package/dist/utils/ast/serializer.d.mts.map +0 -1
  247. package/dist/utils/ast/walker.d.mts.map +0 -1
  248. package/dist/utils/decodeStyleEntities.d.mts.map +0 -1
  249. package/dist/utils/detect.d.mts.map +0 -1
  250. package/dist/utils/url.d.mts.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.d.ts","names":[],"sources":["../../src/transformers/base.ts"],"mappings":";;;;iBAwHgB,IAAA,CAAK,GAAA,EAAK,SAAA,IAAa,MAAA,GAAQ,SAAA,GAAiB,SAAA"}
@@ -5,14 +5,14 @@ import { ChildNode } from "domhandler";
5
5
  * Resolve `__MAIZZLE_COLW_{id}__` and `__MAIZZLE_OH_{id}__` placeholders.
6
6
  *
7
7
  * COLW (column width) — emitted by `<Column>` and `<Overlap>`. Walks up to
8
- * the nearest ancestor marked with `data-maizzle-cw` (Container/Section/
9
- * Row/another Column already resolved) and divides by `data-maizzle-cw-count`.
10
- * If `data-maizzle-cw-self` is present, reads from the element's own inlined
11
- * `max-width`/`width`/`min-width` instead of walking up used by `<Overlap>`
12
- * when it has its own width class/inline style.
8
+ * the nearest ancestor marked `data-maizzle-cw` (Container, Section,
9
+ * Row, or another Column already resolved) and divides the source
10
+ * width by `data-maizzle-cw-count`. With `data-maizzle-cw-self`,
11
+ * reads from the element's own inlined max/width/min-width
12
+ * instead used by `<Overlap>` with its own width class.
13
13
  *
14
- * OH (overlap height) — emitted by `<Overlap>`. Reads `max-height`/`height`/
15
- * `min-height` from the element's own inlined style.
14
+ * OH (overlap height) — emitted by `<Overlap>`. Reads max-height, height,
15
+ * or min-height from the element's own inlined style.
16
16
  *
17
17
  * Resolution rules:
18
18
  * - Style placeholders for `min-width`: replaced when resolvable, otherwise
@@ -22,10 +22,10 @@ import { ChildNode } from "domhandler";
22
22
  * - Comment placeholders: same fallback chain.
23
23
  *
24
24
  * Resolved column widths are written back to `data-maizzle-cw` so nested
25
- * rows cascade. All `data-maizzle-cw*` and `data-maizzle-oh-*` attrs are
26
- * stripped at the end.
25
+ * rows cascade. All `data-maizzle-cw*` and `data-maizzle-oh-*` are
26
+ * stripped at the end of the second walk pass.
27
27
  */
28
28
  declare function columnWidth(dom: ChildNode[]): ChildNode[];
29
29
  //#endregion
30
30
  export { columnWidth };
31
- //# sourceMappingURL=columnWidth.d.mts.map
31
+ //# sourceMappingURL=columnWidth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"columnWidth.d.ts","names":[],"sources":["../../src/transformers/columnWidth.ts"],"mappings":";;;;;AAwTA;;;;;;;;;;;;;;;;;;;;;;iBAAgB,WAAA,CAAY,GAAA,EAAK,SAAA,KAAc,SAAA"}
@@ -1,14 +1,47 @@
1
1
  import { walk } from "../utils/ast/walker.mjs";
2
2
  import "../utils/ast/index.mjs";
3
+ import postcss from "postcss";
4
+ import safeParser from "postcss-safe-parser";
3
5
 
4
6
  //#region src/transformers/columnWidth.ts
5
- const RE_MAX_WIDTH = /(?:^|;\s*)max-width:\s*([^;]+)/i;
6
- const RE_WIDTH = /(?:^|;\s*)width:\s*([^;]+)/i;
7
- const RE_MIN_WIDTH = /(?:^|;\s*)min-width:\s*([^;]+)/i;
8
- const RE_MAX_HEIGHT = /(?:^|;\s*)max-height:\s*([^;]+)/i;
9
- const RE_HEIGHT = /(?:^|;\s*)height:\s*([^;]+)/i;
10
- const RE_MIN_HEIGHT = /(?:^|;\s*)min-height:\s*([^;]+)/i;
11
7
  const RE_PERCENT = /^[\d.]+%$/;
8
+ const NO_BORDER_STYLES = new Set(["none", "hidden"]);
9
+ /**
10
+ * Stringify decls into a `; `-joined inline-style attribute. PostCSS raws
11
+ * preserve the original source spacing, which mixes poorly with
12
+ * the fresh decls we inject — plain join keeps output uniform.
13
+ */
14
+ function serializeStyle(root) {
15
+ const parts = [];
16
+ root.walkDecls((d) => {
17
+ parts.push(`${d.prop}: ${d.value}${d.important ? " !important" : ""}`);
18
+ });
19
+ return parts.join("; ");
20
+ }
21
+ function firstDeclValue(root, prop) {
22
+ let found;
23
+ root.walkDecls(prop, (d) => {
24
+ found = d.value;
25
+ return false;
26
+ });
27
+ return found;
28
+ }
29
+ /**
30
+ * Find the user-set `min-width:` value on a column. Juice keeps both ours
31
+ * and the one inlined from a class like `min-w-1/3` — we skip any
32
+ * min-width whose value still contains our placeholder token,
33
+ * returning the first remaining user value, or null.
34
+ */
35
+ function findUserMinWidth(root) {
36
+ let userVal = null;
37
+ root.walkDecls("min-width", (d) => {
38
+ if (!d.value.includes("__MAIZZLE_COLW_")) {
39
+ userVal = d.value;
40
+ return false;
41
+ }
42
+ });
43
+ return userVal;
44
+ }
12
45
  function resolveLength(value) {
13
46
  const trimmed = value.trim();
14
47
  if (RE_PERCENT.test(trimmed)) return trimmed;
@@ -23,12 +56,176 @@ function resolveLength(value) {
23
56
  default: return null;
24
57
  }
25
58
  }
59
+ function lengthToPx(value) {
60
+ const m = value.trim().match(/^([\d.]+)(px|rem|em|pt)?$/i);
61
+ if (!m) return null;
62
+ const n = parseFloat(m[1]);
63
+ switch ((m[2] || "px").toLowerCase()) {
64
+ case "px": return n;
65
+ case "rem":
66
+ case "em": return n * 16;
67
+ case "pt": return n * 1.333;
68
+ default: return null;
69
+ }
70
+ }
26
71
  function divideLength(value, divisor) {
27
72
  const m = value.match(/^([\d.]+)(px|%)$/);
28
73
  if (!m || divisor < 1) return null;
29
74
  const n = parseFloat(m[1]);
30
75
  return `${parseFloat((n / divisor).toFixed(2))}${m[2]}`;
31
76
  }
77
+ function subtractInsetPx(width, insetPx) {
78
+ if (insetPx <= 0) return width;
79
+ const m = width.match(/^([\d.]+)(px|%)$/);
80
+ if (!m) return width;
81
+ if (m[2] === "%") return width;
82
+ const n = parseFloat(m[1]) - insetPx;
83
+ return `${Math.max(0, Math.round(n))}px`;
84
+ }
85
+ /**
86
+ * Return the smaller of two px lengths. Clamps our count-based min-width
87
+ * down to the user's `max-width:` so the cap is never silently
88
+ * violated when our computed min would exceed the user's max.
89
+ */
90
+ function minPxLength(a, b) {
91
+ const am = a.match(/^([\d.]+)px$/);
92
+ const bm = b.match(/^([\d.]+)px$/);
93
+ if (!am || !bm) return a;
94
+ return parseFloat(am[1]) < parseFloat(bm[1]) ? a : b;
95
+ }
96
+ /**
97
+ * Expand a 1-4 token CSS shorthand (T R B L) into a left/right pair:
98
+ * 1: all sides
99
+ * 2: TB RL
100
+ * 3: T RL B
101
+ * 4: T R B L
102
+ */
103
+ function shorthandSides(value) {
104
+ const parts = value.trim().split(/\s+/);
105
+ switch (parts.length) {
106
+ case 1: return {
107
+ left: parts[0],
108
+ right: parts[0]
109
+ };
110
+ case 2:
111
+ case 3: return {
112
+ left: parts[1],
113
+ right: parts[1]
114
+ };
115
+ case 4: return {
116
+ left: parts[3],
117
+ right: parts[1]
118
+ };
119
+ default: return {};
120
+ }
121
+ }
122
+ /**
123
+ * Read horizontal padding (left + right) px from a parsed style root.
124
+ * Percentages are skipped — they'd need a known container width.
125
+ */
126
+ function horizontalPaddingPx(root) {
127
+ let left = null;
128
+ let right = null;
129
+ root.walkDecls((d) => {
130
+ switch (d.prop) {
131
+ case "padding": {
132
+ const { left: l, right: r } = shorthandSides(d.value);
133
+ if (l) left = lengthToPx(l);
134
+ if (r) right = lengthToPx(r);
135
+ break;
136
+ }
137
+ case "padding-left":
138
+ left = lengthToPx(d.value);
139
+ break;
140
+ case "padding-right":
141
+ right = lengthToPx(d.value);
142
+ break;
143
+ }
144
+ });
145
+ return (left ?? 0) + (right ?? 0);
146
+ }
147
+ /**
148
+ * Extract a px length from a CSS border shorthand (e.g. `1px solid red` → 1).
149
+ * Returns null when the value indicates no border — `none` or `hidden`.
150
+ * Defaults to 3px (CSS `medium`) when a visible style is set but
151
+ * no explicit width token is present in the shorthand value.
152
+ */
153
+ function shorthandBorderWidthPx(value) {
154
+ const tokens = value.trim().split(/\s+/);
155
+ if (tokens.some((t) => NO_BORDER_STYLES.has(t.toLowerCase()))) return null;
156
+ for (const t of tokens) {
157
+ const px = lengthToPx(t);
158
+ if (px != null) return px;
159
+ }
160
+ return 3;
161
+ }
162
+ /**
163
+ * Read horizontal border widths (left + right) px from a parsed style root.
164
+ * Per-side `border-style: none|hidden` overrides count as zero
165
+ * contribution. Returns total px or 0 when nothing resolves.
166
+ */
167
+ function horizontalBorderPx(root) {
168
+ let left = null;
169
+ let right = null;
170
+ let leftNone = false;
171
+ let rightNone = false;
172
+ root.walkDecls((d) => {
173
+ switch (d.prop) {
174
+ case "border": {
175
+ const w = shorthandBorderWidthPx(d.value);
176
+ if (w == null) leftNone = rightNone = true;
177
+ else {
178
+ left = right = w;
179
+ leftNone = rightNone = false;
180
+ }
181
+ break;
182
+ }
183
+ case "border-width": {
184
+ const { left: l, right: r } = shorthandSides(d.value);
185
+ if (l) left = lengthToPx(l) ?? left;
186
+ if (r) right = lengthToPx(r) ?? right;
187
+ break;
188
+ }
189
+ case "border-style": {
190
+ const { left: l, right: r } = shorthandSides(d.value);
191
+ if (l && NO_BORDER_STYLES.has(l.toLowerCase())) leftNone = true;
192
+ if (r && NO_BORDER_STYLES.has(r.toLowerCase())) rightNone = true;
193
+ break;
194
+ }
195
+ case "border-left": {
196
+ const w = shorthandBorderWidthPx(d.value);
197
+ if (w == null) leftNone = true;
198
+ else {
199
+ left = w;
200
+ leftNone = false;
201
+ }
202
+ break;
203
+ }
204
+ case "border-right": {
205
+ const w = shorthandBorderWidthPx(d.value);
206
+ if (w == null) rightNone = true;
207
+ else {
208
+ right = w;
209
+ rightNone = false;
210
+ }
211
+ break;
212
+ }
213
+ case "border-left-width":
214
+ left = lengthToPx(d.value) ?? left;
215
+ break;
216
+ case "border-right-width":
217
+ right = lengthToPx(d.value) ?? right;
218
+ break;
219
+ case "border-left-style":
220
+ if (NO_BORDER_STYLES.has(d.value.trim().toLowerCase())) leftNone = true;
221
+ break;
222
+ case "border-right-style":
223
+ if (NO_BORDER_STYLES.has(d.value.trim().toLowerCase())) rightNone = true;
224
+ break;
225
+ }
226
+ });
227
+ return (leftNone ? 0 : left ?? 0) + (rightNone ? 0 : right ?? 0);
228
+ }
32
229
  function depth(node) {
33
230
  let d = 0;
34
231
  let cur = node.parent;
@@ -38,36 +235,51 @@ function depth(node) {
38
235
  }
39
236
  return d;
40
237
  }
41
- function readWidthSource(el) {
238
+ function readWidthFromRoot(root) {
239
+ const raw = firstDeclValue(root, "max-width") ?? firstDeclValue(root, "width") ?? firstDeclValue(root, "min-width");
240
+ return raw ? resolveLength(raw) : null;
241
+ }
242
+ function readHeightFromRoot(root) {
243
+ const raw = firstDeclValue(root, "max-height") ?? firstDeclValue(root, "height") ?? firstDeclValue(root, "min-height");
244
+ return raw ? resolveLength(raw) : null;
245
+ }
246
+ function readWidthSource(el, root) {
42
247
  const explicit = el.attribs?.["data-maizzle-cw"];
43
248
  if (explicit) {
44
249
  const r = resolveLength(explicit);
45
250
  if (r) return r;
46
251
  }
47
- return readWidthFromStyle(el);
252
+ return root ? readWidthFromRoot(root) : null;
48
253
  }
49
- function readWidthFromStyle(el) {
50
- const style = el.attribs?.style ?? "";
51
- const raw = style.match(RE_MAX_WIDTH)?.[1] ?? style.match(RE_WIDTH)?.[1] ?? style.match(RE_MIN_WIDTH)?.[1];
52
- return raw ? resolveLength(raw) : null;
53
- }
54
- function readHeightFromStyle(el) {
55
- const style = el.attribs?.style ?? "";
56
- const raw = style.match(RE_MAX_HEIGHT)?.[1] ?? style.match(RE_HEIGHT)?.[1] ?? style.match(RE_MIN_HEIGHT)?.[1];
57
- return raw ? resolveLength(raw) : null;
254
+ /**
255
+ * Convert a user-supplied length to absolute px against the column's source
256
+ * width (post-inset). Percentages multiply against the source while
257
+ * absolute units pass through `resolveLength`. Returns null when
258
+ * the value or source can't be expressed in px.
259
+ */
260
+ function userValueToPx(rawValue, sourcePx) {
261
+ const trimmed = rawValue.trim();
262
+ if (trimmed.match(/^([\d.]+)(px|rem|em|pt)$/i)) return resolveLength(trimmed);
263
+ const pctMatch = trimmed.match(/^([\d.]+)%$/);
264
+ if (!pctMatch || !sourcePx) return null;
265
+ const sourceMatch = sourcePx.match(/^([\d.]+)px$/);
266
+ if (!sourceMatch) return null;
267
+ const pct = parseFloat(pctMatch[1]);
268
+ const src = parseFloat(sourceMatch[1]);
269
+ return `${Math.round(pct / 100 * src)}px`;
58
270
  }
59
271
  /**
60
272
  * Resolve `__MAIZZLE_COLW_{id}__` and `__MAIZZLE_OH_{id}__` placeholders.
61
273
  *
62
274
  * COLW (column width) — emitted by `<Column>` and `<Overlap>`. Walks up to
63
- * the nearest ancestor marked with `data-maizzle-cw` (Container/Section/
64
- * Row/another Column already resolved) and divides by `data-maizzle-cw-count`.
65
- * If `data-maizzle-cw-self` is present, reads from the element's own inlined
66
- * `max-width`/`width`/`min-width` instead of walking up used by `<Overlap>`
67
- * when it has its own width class/inline style.
275
+ * the nearest ancestor marked `data-maizzle-cw` (Container, Section,
276
+ * Row, or another Column already resolved) and divides the source
277
+ * width by `data-maizzle-cw-count`. With `data-maizzle-cw-self`,
278
+ * reads from the element's own inlined max/width/min-width
279
+ * instead used by `<Overlap>` with its own width class.
68
280
  *
69
- * OH (overlap height) — emitted by `<Overlap>`. Reads `max-height`/`height`/
70
- * `min-height` from the element's own inlined style.
281
+ * OH (overlap height) — emitted by `<Overlap>`. Reads max-height, height,
282
+ * or min-height from the element's own inlined style.
71
283
  *
72
284
  * Resolution rules:
73
285
  * - Style placeholders for `min-width`: replaced when resolvable, otherwise
@@ -77,10 +289,25 @@ function readHeightFromStyle(el) {
77
289
  * - Comment placeholders: same fallback chain.
78
290
  *
79
291
  * Resolved column widths are written back to `data-maizzle-cw` so nested
80
- * rows cascade. All `data-maizzle-cw*` and `data-maizzle-oh-*` attrs are
81
- * stripped at the end.
292
+ * rows cascade. All `data-maizzle-cw*` and `data-maizzle-oh-*` are
293
+ * stripped at the end of the second walk pass.
82
294
  */
83
295
  function columnWidth(dom) {
296
+ /**
297
+ * Cache parsed style ASTs for this columnWidth invocation. The walk-up
298
+ * loop visits the same Section/Container once per column of a Row,
299
+ * so without caching each column re-parses every ancestor's style.
300
+ * Cache is function-local — no cross-build leak via the WeakMap.
301
+ */
302
+ const styleCache = /* @__PURE__ */ new WeakMap();
303
+ const parseElStyle = (el) => {
304
+ const cached = styleCache.get(el);
305
+ if (cached) return cached;
306
+ const style = el.attribs?.style ?? "";
307
+ const root = style ? safeParser(style) : postcss.root();
308
+ styleCache.set(el, root);
309
+ return root;
310
+ };
84
311
  const columns = [];
85
312
  const heightTargets = [];
86
313
  walk(dom, (node) => {
@@ -107,32 +334,141 @@ function columnWidth(dom) {
107
334
  columns.sort((a, b) => a.d - b.d);
108
335
  const widthResolutions = /* @__PURE__ */ new Map();
109
336
  const widthFallbacks = /* @__PURE__ */ new Map();
337
+ /**
338
+ * Column ids whose absolute user `width:` was promoted to `min-width:`
339
+ * — the original `width:` declaration must be stripped from the
340
+ * column's style (otherwise it'd compete with the min-width).
341
+ */
342
+ const stripWidth = /* @__PURE__ */ new Set();
343
+ /**
344
+ * Column ids where the user wrote a percentage `width:` (e.g. `w-1/2`) —
345
+ * explicit opt-out of px-based stacking. Keep the user's `width: X%`
346
+ * and drop our `min-width:` placeholder so the column stays at
347
+ * that percentage of its parent forever and never stacks.
348
+ */
349
+ const dropMinWidth = /* @__PURE__ */ new Set();
350
+ /**
351
+ * Column ids where the user wrote their own `min-width:` (via `min-w-1/3`).
352
+ * Juice inlines theirs after ours, so two `min-width:` decls land in
353
+ * the style — we strip the user's after using its value as the
354
+ * column's resolution, leaving our placeholder as last word.
355
+ */
356
+ const stripUserMinWidth = /* @__PURE__ */ new Set();
357
+ /**
358
+ * Column ids where the user already supplied a `max-width:` of their own.
359
+ * Our default `max-width: 100%` would just be shadowed by it via
360
+ * last-wins and bloat the style — so we skip emitting it.
361
+ */
362
+ const userHasMaxWidth = /* @__PURE__ */ new Set();
110
363
  for (const { id, count } of columns) widthFallbacks.set(id, `${Math.round(100 / Math.max(count, 1))}%`);
111
364
  for (const { el, id, count, self } of columns) {
365
+ const ownRoot = parseElStyle(el);
112
366
  let sourceWidth = null;
113
- if (self) sourceWidth = readWidthFromStyle(el);
114
- else {
367
+ let accumulatedInsetPx = 0;
368
+ if (self) {
369
+ sourceWidth = readWidthFromRoot(ownRoot);
370
+ accumulatedInsetPx = horizontalPaddingPx(ownRoot) + horizontalBorderPx(ownRoot);
371
+ } else {
372
+ /**
373
+ * Walk up through every ancestor with attribs, accumulating horizontal
374
+ * padding+border along the way (including the source). Stop at the
375
+ * first `data-maizzle-cw` ancestor whose width is resolvable.
376
+ * Markers without a resolvable width (Row emitted empty after
377
+ * Tailwind dropped a bogus class) shouldn't shadow a real
378
+ * width on a higher ancestor like `<Container>`.
379
+ *
380
+ * With CSS content-box this is technically generous toward the
381
+ * source's own padding/border, but matches user expectations
382
+ * when they put `px-9` or `border-2` on a wrapper.
383
+ */
115
384
  let cur = el.parent;
116
385
  while (cur) {
117
386
  const parentEl = cur;
118
- if (parentEl.attribs && "data-maizzle-cw" in parentEl.attribs) {
119
- sourceWidth = readWidthSource(parentEl);
120
- break;
387
+ if (parentEl.attribs) {
388
+ let pRoot = null;
389
+ if (parentEl.attribs.style) {
390
+ pRoot = parseElStyle(parentEl);
391
+ accumulatedInsetPx += horizontalPaddingPx(pRoot) + horizontalBorderPx(pRoot);
392
+ }
393
+ if ("data-maizzle-cw" in parentEl.attribs) {
394
+ const w = readWidthSource(parentEl, pRoot);
395
+ if (w) {
396
+ sourceWidth = w;
397
+ break;
398
+ }
399
+ }
121
400
  }
122
401
  cur = cur.parent ?? null;
123
402
  }
124
403
  }
125
- if (sourceWidth) {
126
- const div = divideLength(sourceWidth, count);
127
- if (div) {
128
- widthResolutions.set(id, div);
129
- el.attribs["data-maizzle-cw"] = div;
404
+ const adjusted = sourceWidth ? subtractInsetPx(sourceWidth, accumulatedInsetPx) : null;
405
+ const countBased = adjusted ? divideLength(adjusted, count) : null;
406
+ /**
407
+ * Four user-override paths, decided by which CSS property the user
408
+ * actually wrote:
409
+ *
410
+ * - `min-width: X` → user's value wins. Convert to px against
411
+ * the source (if %), use as the column's
412
+ * resolution, and strip the user's min-width
413
+ * declaration so our placeholder substitution
414
+ * remains the last `min-width:` in style.
415
+ * - `width: X%` → opt-out of px stacking. Keep `width:` in
416
+ * style, drop our `min-width:` placeholder.
417
+ * Cols stay at X% of parent forever, never stack.
418
+ * - `width: Xpx` (or rem/em/pt) → fixed pixel column. Promote to
419
+ * `min-width:`, strip the original `width:` so
420
+ * it doesn't compete.
421
+ * - `max-width: X` → CSS cap. Keep the `max-width:` declaration;
422
+ * clamp our count-based min-width *down* to
423
+ * the user's max-width when our min would
424
+ * otherwise violate it.
425
+ */
426
+ const userMinRaw = findUserMinWidth(ownRoot);
427
+ const widthRaw = firstDeclValue(ownRoot, "width");
428
+ const maxRaw = firstDeclValue(ownRoot, "max-width");
429
+ if (userMinRaw) {
430
+ const minPx = userValueToPx(userMinRaw, adjusted) ?? resolveLength(userMinRaw);
431
+ if (minPx) {
432
+ widthResolutions.set(id, minPx);
433
+ el.attribs["data-maizzle-cw"] = minPx;
434
+ stripUserMinWidth.add(id);
435
+ continue;
130
436
  }
131
437
  }
438
+ if (widthRaw) {
439
+ const widthVal = resolveLength(widthRaw);
440
+ if (widthVal?.endsWith("%")) {
441
+ widthResolutions.set(id, widthVal);
442
+ el.attribs["data-maizzle-cw"] = widthVal;
443
+ dropMinWidth.add(id);
444
+ continue;
445
+ }
446
+ if (widthVal) {
447
+ widthResolutions.set(id, widthVal);
448
+ el.attribs["data-maizzle-cw"] = widthVal;
449
+ stripWidth.add(id);
450
+ continue;
451
+ }
452
+ }
453
+ if (maxRaw && countBased) {
454
+ const maxPx = userValueToPx(maxRaw, adjusted);
455
+ if (maxPx) {
456
+ const cappedMin = countBased.endsWith("px") ? minPxLength(countBased, maxPx) : maxPx;
457
+ widthResolutions.set(id, cappedMin);
458
+ el.attribs["data-maizzle-cw"] = cappedMin;
459
+ userHasMaxWidth.add(id);
460
+ continue;
461
+ }
462
+ }
463
+ if (countBased) {
464
+ widthResolutions.set(id, countBased);
465
+ el.attribs["data-maizzle-cw"] = countBased;
466
+ }
132
467
  }
133
468
  const heightResolutions = /* @__PURE__ */ new Map();
134
469
  for (const { el, id } of heightTargets) {
135
- const h = readHeightFromStyle(el);
470
+ if (!el.attribs?.style) continue;
471
+ const h = readHeightFromRoot(parseElStyle(el));
136
472
  if (h) heightResolutions.set(id, h);
137
473
  }
138
474
  walk(dom, (node) => {
@@ -146,10 +482,55 @@ function columnWidth(dom) {
146
482
  if (!el.attribs) return;
147
483
  const style = el.attribs.style;
148
484
  if (style && (style.includes("__MAIZZLE_COLW_") || style.includes("__MAIZZLE_OH_"))) {
149
- let next = style.replace(/(?:^|;\s*)min-width:\s*__MAIZZLE_COLW_([^_]+)__\s*;?/g, (_m, mid) => widthResolutions.has(mid) ? `; min-width: ${widthResolutions.get(mid)}` : "");
150
- next = next.replace(/__MAIZZLE_COLW_([^_]+)__/g, (_m, mid) => widthResolutions.get(mid) ?? widthFallbacks.get(mid) ?? "100%").replace(/__MAIZZLE_OH_([^_]+)__/g, (_m, hid) => heightResolutions.get(hid) ?? "100%");
151
- next = next.replace(/^;\s*/, "").replace(/;\s*$/, "").trim();
152
- if (next) el.attribs.style = next;
485
+ const root = parseElStyle(el);
486
+ const cwId = el.attribs["data-maizzle-cw-id"];
487
+ /**
488
+ * Strip user dups BEFORE substitution — last-wins CSS would
489
+ * otherwise shadow our resolved values in the output.
490
+ */
491
+ if (cwId && stripUserMinWidth.has(cwId)) root.walkDecls("min-width", (d) => {
492
+ if (!d.value.includes("__MAIZZLE_COLW_")) d.remove();
493
+ });
494
+ if (cwId && stripWidth.has(cwId)) root.walkDecls("width", (d) => {
495
+ d.remove();
496
+ });
497
+ /**
498
+ * Substitute the column's `min-width:` placeholder with `width: <res>;
499
+ * max-width: 100%`. Width gives the same stacking trigger as
500
+ * min-width — inline-block wraps when children sum > parent
501
+ * — and the `max-width: 100%` clamp keeps the column from
502
+ * overflowing the viewport once it drops to its own row on
503
+ * mobile. Skip the clamp when the user supplied their own.
504
+ *
505
+ * Other placeholders (Overlap td `width`, comment markers,
506
+ * OH height) get a plain value substitution.
507
+ */
508
+ root.walkDecls((d) => {
509
+ if (d.prop === "min-width") {
510
+ const m = d.value.match(/^__MAIZZLE_COLW_([^_]+)__$/);
511
+ if (m) {
512
+ const mid = m[1];
513
+ if (dropMinWidth.has(mid) || !widthResolutions.has(mid)) {
514
+ d.remove();
515
+ return;
516
+ }
517
+ const resolved = widthResolutions.get(mid);
518
+ const repl = [postcss.decl({
519
+ prop: "width",
520
+ value: resolved
521
+ })];
522
+ if (!userHasMaxWidth.has(mid)) repl.push(postcss.decl({
523
+ prop: "max-width",
524
+ value: "100%"
525
+ }));
526
+ d.replaceWith(...repl);
527
+ return;
528
+ }
529
+ }
530
+ if (d.value.includes("__MAIZZLE_COLW_") || d.value.includes("__MAIZZLE_OH_")) d.value = d.value.replace(/__MAIZZLE_COLW_([^_]+)__/g, (_m, mid) => widthResolutions.get(mid) ?? widthFallbacks.get(mid) ?? "100%").replace(/__MAIZZLE_OH_([^_]+)__/g, (_m, hid) => heightResolutions.get(hid) ?? "100%");
531
+ });
532
+ const out = serializeStyle(root);
533
+ if (out) el.attribs.style = out;
153
534
  else delete el.attribs.style;
154
535
  }
155
536
  delete el.attribs["data-maizzle-cw"];