@depup/react-email 5.2.10-depup.0 → 6.9.0-depup.1

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 (404) hide show
  1. package/CHANGELOG.md +313 -0
  2. package/README.md +11 -10
  3. package/changes.json +21 -17
  4. package/dev/CHANGELOG.md +2 -0
  5. package/dev/index.js +1 -1
  6. package/dev/package.json +1 -1
  7. package/dist/_virtual/_rolldown/runtime.cjs +23 -0
  8. package/dist/cli/index.mjs +7801 -0
  9. package/dist/components/body/body.cjs +39 -0
  10. package/dist/components/body/body.d.cts +7 -0
  11. package/dist/components/body/body.d.mts +7 -0
  12. package/dist/components/body/body.mjs +37 -0
  13. package/dist/components/body/index.d.cts +1 -0
  14. package/dist/components/body/index.d.mts +1 -0
  15. package/dist/components/body/margin-properties.cjs +30 -0
  16. package/dist/components/body/margin-properties.mjs +29 -0
  17. package/dist/components/button/button.cjs +64 -0
  18. package/dist/components/button/button.d.cts +13 -0
  19. package/dist/components/button/button.d.mts +13 -0
  20. package/dist/components/button/button.mjs +62 -0
  21. package/dist/components/button/index.d.cts +1 -0
  22. package/dist/components/button/index.d.mts +1 -0
  23. package/dist/components/button/utils/parse-padding.cjs +90 -0
  24. package/dist/components/button/utils/parse-padding.mjs +90 -0
  25. package/dist/components/button/utils/px-to-pt.cjs +4 -0
  26. package/dist/components/button/utils/px-to-pt.mjs +4 -0
  27. package/dist/components/code-block/code-block.cjs +79 -0
  28. package/dist/components/code-block/code-block.d.cts +20 -0
  29. package/dist/components/code-block/code-block.d.mts +20 -0
  30. package/dist/components/code-block/code-block.mjs +77 -0
  31. package/dist/components/code-block/index.d.cts +3 -0
  32. package/dist/components/code-block/index.d.mts +3 -0
  33. package/dist/components/code-block/languages-available.d.cts +4 -0
  34. package/dist/components/code-block/languages-available.d.mts +4 -0
  35. package/dist/components/code-block/prism.cjs +14564 -0
  36. package/dist/components/code-block/prism.mjs +14562 -0
  37. package/dist/components/code-block/themes.cjs +2578 -0
  38. package/dist/components/code-block/themes.d.cts +4877 -0
  39. package/dist/components/code-block/themes.d.mts +4877 -0
  40. package/dist/components/code-block/themes.mjs +2541 -0
  41. package/dist/components/code-inline/code-inline.cjs +43 -0
  42. package/dist/components/code-inline/code-inline.d.cts +12 -0
  43. package/dist/components/code-inline/code-inline.d.mts +12 -0
  44. package/dist/components/code-inline/code-inline.mjs +41 -0
  45. package/dist/components/code-inline/index.d.cts +1 -0
  46. package/dist/components/code-inline/index.d.mts +1 -0
  47. package/dist/components/column/column.cjs +19 -0
  48. package/dist/components/column/column.d.cts +7 -0
  49. package/dist/components/column/column.d.mts +7 -0
  50. package/dist/components/column/column.mjs +17 -0
  51. package/dist/components/column/index.d.cts +1 -0
  52. package/dist/components/column/index.d.mts +1 -0
  53. package/dist/components/container/container.cjs +42 -0
  54. package/dist/components/container/container.d.cts +7 -0
  55. package/dist/components/container/container.d.mts +7 -0
  56. package/dist/components/container/container.mjs +40 -0
  57. package/dist/components/container/index.d.cts +1 -0
  58. package/dist/components/container/index.d.mts +1 -0
  59. package/dist/components/element-marker.cjs +8 -0
  60. package/dist/components/element-marker.mjs +7 -0
  61. package/dist/components/font/font.cjs +22 -0
  62. package/dist/components/font/font.d.cts +26 -0
  63. package/dist/components/font/font.d.mts +26 -0
  64. package/dist/components/font/font.mjs +21 -0
  65. package/dist/components/font/index.d.cts +1 -0
  66. package/dist/components/font/index.d.mts +1 -0
  67. package/dist/components/head/head.cjs +20 -0
  68. package/dist/components/head/head.d.cts +7 -0
  69. package/dist/components/head/head.d.mts +7 -0
  70. package/dist/components/head/head.mjs +18 -0
  71. package/dist/components/head/index.d.cts +1 -0
  72. package/dist/components/head/index.d.mts +1 -0
  73. package/dist/components/heading/heading.cjs +30 -0
  74. package/dist/components/heading/heading.d.cts +22 -0
  75. package/dist/components/heading/heading.d.mts +22 -0
  76. package/dist/components/heading/heading.mjs +28 -0
  77. package/dist/components/heading/index.d.cts +1 -0
  78. package/dist/components/heading/index.d.mts +1 -0
  79. package/dist/components/heading/utils/as.d.cts +16 -0
  80. package/dist/components/heading/utils/as.d.mts +16 -0
  81. package/dist/components/heading/utils/spaces.cjs +24 -0
  82. package/dist/components/heading/utils/spaces.d.cts +14 -0
  83. package/dist/components/heading/utils/spaces.d.mts +14 -0
  84. package/dist/components/heading/utils/spaces.mjs +24 -0
  85. package/dist/components/hr/hr.cjs +21 -0
  86. package/dist/components/hr/hr.d.cts +7 -0
  87. package/dist/components/hr/hr.d.mts +7 -0
  88. package/dist/components/hr/hr.mjs +19 -0
  89. package/dist/components/hr/index.d.cts +1 -0
  90. package/dist/components/hr/index.d.mts +1 -0
  91. package/dist/components/html/html.cjs +15 -0
  92. package/dist/components/html/html.d.cts +7 -0
  93. package/dist/components/html/html.d.mts +7 -0
  94. package/dist/components/html/html.mjs +13 -0
  95. package/dist/components/html/index.d.cts +1 -0
  96. package/dist/components/html/index.d.mts +1 -0
  97. package/dist/components/img/img.cjs +25 -0
  98. package/dist/components/img/img.d.cts +7 -0
  99. package/dist/components/img/img.d.mts +7 -0
  100. package/dist/components/img/img.mjs +23 -0
  101. package/dist/components/img/index.d.cts +1 -0
  102. package/dist/components/img/index.d.mts +1 -0
  103. package/dist/components/index.d.cts +24 -0
  104. package/dist/components/index.d.mts +24 -0
  105. package/dist/components/link/index.d.cts +1 -0
  106. package/dist/components/link/index.d.mts +1 -0
  107. package/dist/components/link/link.cjs +21 -0
  108. package/dist/components/link/link.d.cts +7 -0
  109. package/dist/components/link/link.d.mts +7 -0
  110. package/dist/components/link/link.mjs +19 -0
  111. package/dist/components/markdown/index.d.cts +1 -0
  112. package/dist/components/markdown/index.d.mts +1 -0
  113. package/dist/components/markdown/markdown.cjs +101 -0
  114. package/dist/components/markdown/markdown.d.cts +16 -0
  115. package/dist/components/markdown/markdown.d.mts +16 -0
  116. package/dist/components/markdown/markdown.mjs +99 -0
  117. package/dist/components/markdown/styles.cjs +92 -0
  118. package/dist/components/markdown/styles.d.cts +31 -0
  119. package/dist/components/markdown/styles.d.mts +31 -0
  120. package/dist/components/markdown/styles.mjs +92 -0
  121. package/dist/components/markdown/utils/parse-css-in-js-to-inline-css.cjs +60 -0
  122. package/dist/components/markdown/utils/parse-css-in-js-to-inline-css.mjs +60 -0
  123. package/dist/components/preview/index.d.cts +1 -0
  124. package/dist/components/preview/index.d.mts +1 -0
  125. package/dist/components/preview/preview.cjs +34 -0
  126. package/dist/components/preview/preview.d.cts +21 -0
  127. package/dist/components/preview/preview.d.mts +21 -0
  128. package/dist/components/preview/preview.mjs +31 -0
  129. package/dist/components/row/index.d.cts +1 -0
  130. package/dist/components/row/index.d.mts +1 -0
  131. package/dist/components/row/row.cjs +30 -0
  132. package/dist/components/row/row.d.cts +11 -0
  133. package/dist/components/row/row.d.mts +11 -0
  134. package/dist/components/row/row.mjs +28 -0
  135. package/dist/components/section/index.d.cts +1 -0
  136. package/dist/components/section/index.d.mts +1 -0
  137. package/dist/components/section/section.cjs +36 -0
  138. package/dist/components/section/section.d.cts +7 -0
  139. package/dist/components/section/section.d.mts +7 -0
  140. package/dist/components/section/section.mjs +34 -0
  141. package/dist/components/tailwind/hooks/use-suspended-promise.cjs +15 -0
  142. package/dist/components/tailwind/hooks/use-suspended-promise.mjs +15 -0
  143. package/dist/components/tailwind/index.d.cts +4 -0
  144. package/dist/components/tailwind/index.d.mts +4 -0
  145. package/dist/components/tailwind/inline-styles.cjs +11 -0
  146. package/dist/components/tailwind/inline-styles.d.cts +6 -0
  147. package/dist/components/tailwind/inline-styles.d.mts +6 -0
  148. package/dist/components/tailwind/inline-styles.mjs +11 -0
  149. package/dist/components/tailwind/sanitize-stylesheet.cjs +11 -0
  150. package/dist/components/tailwind/sanitize-stylesheet.d.cts +6 -0
  151. package/dist/components/tailwind/sanitize-stylesheet.d.mts +6 -0
  152. package/dist/components/tailwind/sanitize-stylesheet.mjs +11 -0
  153. package/dist/components/tailwind/tailwind.cjs +120 -0
  154. package/dist/components/tailwind/tailwind.d.cts +25 -0
  155. package/dist/components/tailwind/tailwind.d.mts +25 -0
  156. package/dist/components/tailwind/tailwind.mjs +117 -0
  157. package/dist/components/tailwind/utils/compatibility/get-react-property.cjs +10 -0
  158. package/dist/components/tailwind/utils/compatibility/get-react-property.mjs +10 -0
  159. package/dist/components/tailwind/utils/compatibility/sanitize-class-name.cjs +26 -0
  160. package/dist/components/tailwind/utils/compatibility/sanitize-class-name.mjs +26 -0
  161. package/dist/components/tailwind/utils/css/downlevel-for-email-clients.cjs +126 -0
  162. package/dist/components/tailwind/utils/css/downlevel-for-email-clients.mjs +125 -0
  163. package/dist/components/tailwind/utils/css/extract-rules-per-class.cjs +45 -0
  164. package/dist/components/tailwind/utils/css/extract-rules-per-class.mjs +44 -0
  165. package/dist/components/tailwind/utils/css/get-custom-properties.cjs +35 -0
  166. package/dist/components/tailwind/utils/css/get-custom-properties.mjs +34 -0
  167. package/dist/components/tailwind/utils/css/is-part-inlinable.cjs +10 -0
  168. package/dist/components/tailwind/utils/css/is-part-inlinable.mjs +9 -0
  169. package/dist/components/tailwind/utils/css/is-rule-inlinable.cjs +10 -0
  170. package/dist/components/tailwind/utils/css/is-rule-inlinable.mjs +9 -0
  171. package/dist/components/tailwind/utils/css/make-inline-styles-for.cjs +52 -0
  172. package/dist/components/tailwind/utils/css/make-inline-styles-for.mjs +51 -0
  173. package/dist/components/tailwind/utils/css/resolve-all-css-variables.cjs +89 -0
  174. package/dist/components/tailwind/utils/css/resolve-all-css-variables.mjs +88 -0
  175. package/dist/components/tailwind/utils/css/resolve-calc-expressions.cjs +92 -0
  176. package/dist/components/tailwind/utils/css/resolve-calc-expressions.mjs +91 -0
  177. package/dist/components/tailwind/utils/css/sanitize-declarations.cjs +310 -0
  178. package/dist/components/tailwind/utils/css/sanitize-declarations.mjs +309 -0
  179. package/dist/components/tailwind/utils/css/sanitize-non-inlinable-rules.cjs +46 -0
  180. package/dist/components/tailwind/utils/css/sanitize-non-inlinable-rules.mjs +45 -0
  181. package/dist/components/tailwind/utils/css/split-mixed-rule.cjs +41 -0
  182. package/dist/components/tailwind/utils/css/split-mixed-rule.mjs +40 -0
  183. package/dist/components/tailwind/utils/css/strip-empty-tailwind-vars.cjs +52 -0
  184. package/dist/components/tailwind/utils/css/strip-empty-tailwind-vars.mjs +51 -0
  185. package/dist/components/tailwind/utils/css/unwrap-value.cjs +7 -0
  186. package/dist/components/tailwind/utils/css/unwrap-value.mjs +7 -0
  187. package/dist/components/tailwind/utils/react/is-component.cjs +7 -0
  188. package/dist/components/tailwind/utils/react/is-component.mjs +7 -0
  189. package/dist/components/tailwind/utils/react/map-react-tree.cjs +32 -0
  190. package/dist/components/tailwind/utils/react/map-react-tree.mjs +30 -0
  191. package/dist/components/tailwind/utils/tailwindcss/clone-element-with-inlined-styles.cjs +37 -0
  192. package/dist/components/tailwind/utils/tailwindcss/clone-element-with-inlined-styles.mjs +35 -0
  193. package/dist/components/tailwind/utils/tailwindcss/setup-tailwind.cjs +77 -0
  194. package/dist/components/tailwind/utils/tailwindcss/setup-tailwind.d.cts +19 -0
  195. package/dist/components/tailwind/utils/tailwindcss/setup-tailwind.d.mts +19 -0
  196. package/dist/components/tailwind/utils/tailwindcss/setup-tailwind.mjs +76 -0
  197. package/dist/components/tailwind/utils/tailwindcss/tailwind-stylesheets/index.cjs +901 -0
  198. package/dist/components/tailwind/utils/tailwindcss/tailwind-stylesheets/index.mjs +901 -0
  199. package/dist/components/tailwind/utils/tailwindcss/tailwind-stylesheets/preflight.cjs +398 -0
  200. package/dist/components/tailwind/utils/tailwindcss/tailwind-stylesheets/preflight.mjs +398 -0
  201. package/dist/components/tailwind/utils/tailwindcss/tailwind-stylesheets/theme.cjs +467 -0
  202. package/dist/components/tailwind/utils/tailwindcss/tailwind-stylesheets/theme.mjs +467 -0
  203. package/dist/components/tailwind/utils/tailwindcss/tailwind-stylesheets/utilities.cjs +6 -0
  204. package/dist/components/tailwind/utils/tailwindcss/tailwind-stylesheets/utilities.mjs +6 -0
  205. package/dist/components/tailwind/utils/text/from-dash-case-to-camel-case.cjs +6 -0
  206. package/dist/components/tailwind/utils/text/from-dash-case-to-camel-case.mjs +6 -0
  207. package/dist/components/text/index.d.cts +1 -0
  208. package/dist/components/text/index.d.mts +1 -0
  209. package/dist/components/text/text.cjs +43 -0
  210. package/dist/components/text/text.d.cts +7 -0
  211. package/dist/components/text/text.d.mts +7 -0
  212. package/dist/components/text/text.mjs +41 -0
  213. package/dist/components/text/utils/compute-margins.cjs +62 -0
  214. package/dist/components/text/utils/compute-margins.mjs +62 -0
  215. package/dist/index.cjs +95 -0
  216. package/dist/index.d.cts +26 -0
  217. package/dist/index.d.mts +26 -0
  218. package/dist/index.mjs +25 -7326
  219. package/package.json +64 -32
  220. package/src/components/body/__snapshots__/body.spec.tsx.snap +23 -0
  221. package/src/components/body/body.spec.tsx +78 -0
  222. package/src/components/body/body.tsx +62 -0
  223. package/src/components/body/index.ts +1 -0
  224. package/src/components/body/margin-properties.ts +27 -0
  225. package/src/components/button/button.spec.tsx +53 -0
  226. package/src/components/button/button.tsx +114 -0
  227. package/src/components/button/index.ts +1 -0
  228. package/src/components/button/utils/parse-padding.ts +137 -0
  229. package/src/components/button/utils/px-to-pt.ts +4 -0
  230. package/src/components/button/utils/utils.spec.ts +153 -0
  231. package/src/components/code-block/code-block.tsx +136 -0
  232. package/src/components/code-block/index.ts +3 -0
  233. package/src/components/code-block/languages-available.ts +402 -0
  234. package/src/components/code-block/prism.ts +15618 -0
  235. package/src/components/code-block/themes.ts +4929 -0
  236. package/src/components/code-inline/code-inline.tsx +60 -0
  237. package/src/components/code-inline/index.ts +1 -0
  238. package/src/components/column/column.spec.tsx +28 -0
  239. package/src/components/column/column.tsx +17 -0
  240. package/src/components/column/index.ts +1 -0
  241. package/src/components/container/container.spec.tsx +33 -0
  242. package/src/components/container/container.tsx +59 -0
  243. package/src/components/container/index.ts +1 -0
  244. package/src/components/element-marker.ts +5 -0
  245. package/src/components/font/font.spec.tsx +63 -0
  246. package/src/components/font/font.tsx +76 -0
  247. package/src/components/font/index.ts +1 -0
  248. package/src/components/head/head.spec.tsx +34 -0
  249. package/src/components/head/head.tsx +15 -0
  250. package/src/components/head/index.ts +1 -0
  251. package/src/components/heading/heading.spec.tsx +32 -0
  252. package/src/components/heading/heading.tsx +31 -0
  253. package/src/components/heading/index.ts +1 -0
  254. package/src/components/heading/utils/as.ts +26 -0
  255. package/src/components/heading/utils/spaces.ts +64 -0
  256. package/src/components/heading/utils/utils.spec.ts +70 -0
  257. package/src/components/hr/hr.spec.tsx +22 -0
  258. package/src/components/hr/hr.tsx +23 -0
  259. package/src/components/hr/index.ts +1 -0
  260. package/src/components/html/html.spec.tsx +26 -0
  261. package/src/components/html/html.tsx +13 -0
  262. package/src/components/html/index.ts +1 -0
  263. package/src/components/img/img.spec.tsx +30 -0
  264. package/src/components/img/img.tsx +27 -0
  265. package/src/components/img/index.ts +1 -0
  266. package/src/components/index.ts +19 -0
  267. package/src/components/link/index.ts +1 -0
  268. package/src/components/link/link.spec.tsx +37 -0
  269. package/src/components/link/link.tsx +24 -0
  270. package/src/components/markdown/index.ts +1 -0
  271. package/src/components/markdown/markdown.spec.tsx +221 -0
  272. package/src/components/markdown/markdown.tsx +239 -0
  273. package/src/components/markdown/styles.ts +130 -0
  274. package/src/components/markdown/utils/parse-css-in-js-to-inline-css.spec.ts +42 -0
  275. package/src/components/markdown/utils/parse-css-in-js-to-inline-css.ts +73 -0
  276. package/src/components/preview/index.ts +1 -0
  277. package/src/components/preview/preview.spec.tsx +49 -0
  278. package/src/components/preview/preview.tsx +56 -0
  279. package/src/components/row/index.ts +1 -0
  280. package/src/components/row/row.spec.tsx +28 -0
  281. package/src/components/row/row.tsx +33 -0
  282. package/src/components/section/index.ts +1 -0
  283. package/src/components/section/section.spec.tsx +58 -0
  284. package/src/components/section/section.tsx +59 -0
  285. package/src/components/tailwind/e2e/integrations.spec.ts +44 -0
  286. package/src/components/tailwind/e2e/nextjs/README.md +9 -0
  287. package/src/components/tailwind/e2e/nextjs/emails/vercel-invite-user.tsx +151 -0
  288. package/src/components/tailwind/e2e/nextjs/next.config.mjs +6 -0
  289. package/src/components/tailwind/e2e/nextjs/package.json +24 -0
  290. package/src/components/tailwind/e2e/nextjs/src/app/favicon.ico +0 -0
  291. package/src/components/tailwind/e2e/nextjs/src/app/layout.tsx +23 -0
  292. package/src/components/tailwind/e2e/nextjs/src/app/page.tsx +7 -0
  293. package/src/components/tailwind/e2e/nextjs/tsconfig.json +27 -0
  294. package/src/components/tailwind/e2e/vite/README.md +9 -0
  295. package/src/components/tailwind/e2e/vite/emails/vercel-invite-user.tsx +151 -0
  296. package/src/components/tailwind/e2e/vite/index.html +13 -0
  297. package/src/components/tailwind/e2e/vite/package.json +25 -0
  298. package/src/components/tailwind/e2e/vite/public/vite.svg +1 -0
  299. package/src/components/tailwind/e2e/vite/src/App.tsx +10 -0
  300. package/src/components/tailwind/e2e/vite/src/main.tsx +9 -0
  301. package/src/components/tailwind/e2e/vite/src/vite-env.d.ts +1 -0
  302. package/src/components/tailwind/e2e/vite/tsconfig.json +25 -0
  303. package/src/components/tailwind/e2e/vite/tsconfig.node.json +11 -0
  304. package/src/components/tailwind/e2e/vite/vite.config.ts +7 -0
  305. package/src/components/tailwind/hooks/use-suspended-promise.ts +34 -0
  306. package/src/components/tailwind/hooks/use-suspensed-promise.spec.ts +263 -0
  307. package/src/components/tailwind/index.ts +4 -0
  308. package/src/components/tailwind/inline-styles.spec.ts +49 -0
  309. package/src/components/tailwind/inline-styles.ts +21 -0
  310. package/src/components/tailwind/sanitize-stylesheet.ts +10 -0
  311. package/src/components/tailwind/tailwind.spec.tsx +1390 -0
  312. package/src/components/tailwind/tailwind.tsx +178 -0
  313. package/src/components/tailwind/utils/__snapshots__/quick-safe-render-to-string.spec.tsx.snap +3 -0
  314. package/src/components/tailwind/utils/compatibility/escape-class-name.spec.ts +17 -0
  315. package/src/components/tailwind/utils/compatibility/escape-class-name.ts +18 -0
  316. package/src/components/tailwind/utils/compatibility/get-react-property.ts +15 -0
  317. package/src/components/tailwind/utils/compatibility/sanitize-class-name.spec.ts +7 -0
  318. package/src/components/tailwind/utils/compatibility/sanitize-class-name.ts +36 -0
  319. package/src/components/tailwind/utils/compatibility/unescape-class.ts +3 -0
  320. package/src/components/tailwind/utils/css/__snapshots__/extract-rules-matching-classes.spec.ts.snap +23 -0
  321. package/src/components/tailwind/utils/css/__snapshots__/remove-rule-duplicates-from-root.spec.ts.snap +3 -0
  322. package/src/components/tailwind/utils/css/__snapshots__/sanitize-non-inlinable-classes.spec.ts.snap +7 -0
  323. package/src/components/tailwind/utils/css/downlevel-for-email-clients.spec.ts +119 -0
  324. package/src/components/tailwind/utils/css/downlevel-for-email-clients.ts +244 -0
  325. package/src/components/tailwind/utils/css/extract-rules-per-class.spec.ts +232 -0
  326. package/src/components/tailwind/utils/css/extract-rules-per-class.ts +76 -0
  327. package/src/components/tailwind/utils/css/get-custom-properties.ts +49 -0
  328. package/src/components/tailwind/utils/css/is-part-inlinable.ts +15 -0
  329. package/src/components/tailwind/utils/css/is-rule-inlinable.ts +15 -0
  330. package/src/components/tailwind/utils/css/make-inline-styles-for.spec.ts +124 -0
  331. package/src/components/tailwind/utils/css/make-inline-styles-for.ts +73 -0
  332. package/src/components/tailwind/utils/css/resolve-all-css-variables.spec.ts +296 -0
  333. package/src/components/tailwind/utils/css/resolve-all-css-variables.ts +236 -0
  334. package/src/components/tailwind/utils/css/resolve-calc-expressions.spec.ts +36 -0
  335. package/src/components/tailwind/utils/css/resolve-calc-expressions.ts +147 -0
  336. package/src/components/tailwind/utils/css/sanitize-declarations.spec.ts +491 -0
  337. package/src/components/tailwind/utils/css/sanitize-declarations.ts +443 -0
  338. package/src/components/tailwind/utils/css/sanitize-non-inlinable-rules.spec.ts +72 -0
  339. package/src/components/tailwind/utils/css/sanitize-non-inlinable-rules.ts +48 -0
  340. package/src/components/tailwind/utils/css/split-mixed-rule.ts +68 -0
  341. package/src/components/tailwind/utils/css/strip-empty-tailwind-vars.spec.ts +128 -0
  342. package/src/components/tailwind/utils/css/strip-empty-tailwind-vars.ts +70 -0
  343. package/src/components/tailwind/utils/css/unwrap-value.ts +9 -0
  344. package/src/components/tailwind/utils/react/is-component.ts +12 -0
  345. package/src/components/tailwind/utils/react/map-react-tree.spec.tsx +58 -0
  346. package/src/components/tailwind/utils/react/map-react-tree.ts +58 -0
  347. package/src/components/tailwind/utils/tailwindcss/clone-element-with-inlined-styles.ts +61 -0
  348. package/src/components/tailwind/utils/tailwindcss/setup-tailwind.spec.ts +25 -0
  349. package/src/components/tailwind/utils/tailwindcss/setup-tailwind.ts +121 -0
  350. package/src/components/tailwind/utils/tailwindcss/tailwind-stylesheets/index.ts +900 -0
  351. package/src/components/tailwind/utils/tailwindcss/tailwind-stylesheets/preflight.ts +397 -0
  352. package/src/components/tailwind/utils/tailwindcss/tailwind-stylesheets/theme.ts +466 -0
  353. package/src/components/tailwind/utils/tailwindcss/tailwind-stylesheets/utilities.ts +5 -0
  354. package/src/components/tailwind/utils/text/from-dash-case-to-camel-case.ts +3 -0
  355. package/src/components/text/index.ts +1 -0
  356. package/src/components/text/text.spec.tsx +35 -0
  357. package/src/components/text/text.tsx +50 -0
  358. package/src/components/text/utils/compute-margins.spec.ts +67 -0
  359. package/src/components/text/utils/compute-margins.ts +102 -0
  360. package/src/index.ts +2 -110
  361. package/tsconfig.json +9 -4
  362. package/tsdown.config.ts +51 -6
  363. package/vitest.config.ts +1 -0
  364. package/vitest.e2e.config.ts +17 -0
  365. package/src/commands/build.ts +0 -269
  366. package/src/commands/dev.ts +0 -27
  367. package/src/commands/export.ts +0 -204
  368. package/src/commands/resend/reset.ts +0 -8
  369. package/src/commands/resend/setup.ts +0 -29
  370. package/src/commands/start.ts +0 -38
  371. package/src/utils/conf.ts +0 -9
  372. package/src/utils/esbuild/escape-string-for-regex.ts +0 -3
  373. package/src/utils/esbuild/renderring-utilities-exporter.ts +0 -63
  374. package/src/utils/get-emails-directory-metadata.spec.ts +0 -82
  375. package/src/utils/get-emails-directory-metadata.ts +0 -140
  376. package/src/utils/get-preview-server-location.ts +0 -50
  377. package/src/utils/index.ts +0 -2
  378. package/src/utils/packageJson.ts +0 -4
  379. package/src/utils/preview/get-env-variables-for-preview-app.ts +0 -20
  380. package/src/utils/preview/hot-reloading/create-dependency-graph.spec.ts +0 -226
  381. package/src/utils/preview/hot-reloading/create-dependency-graph.ts +0 -343
  382. package/src/utils/preview/hot-reloading/get-imported-modules.spec.ts +0 -151
  383. package/src/utils/preview/hot-reloading/get-imported-modules.ts +0 -49
  384. package/src/utils/preview/hot-reloading/resolve-path-aliases.spec.ts +0 -11
  385. package/src/utils/preview/hot-reloading/resolve-path-aliases.ts +0 -32
  386. package/src/utils/preview/hot-reloading/setup-hot-reloading.ts +0 -121
  387. package/src/utils/preview/hot-reloading/test/dependency-graph/inner/data-to-import.json +0 -1
  388. package/src/utils/preview/hot-reloading/test/dependency-graph/inner/file-a.ts +0 -5
  389. package/src/utils/preview/hot-reloading/test/dependency-graph/inner/file-b.ts +0 -5
  390. package/src/utils/preview/hot-reloading/test/dependency-graph/inner/general-importing-file.ts +0 -9
  391. package/src/utils/preview/hot-reloading/test/dependency-graph/inner/outer-dependency.ts +0 -3
  392. package/src/utils/preview/hot-reloading/test/dependency-graph/inner/path-aliases.ts +0 -1
  393. package/src/utils/preview/hot-reloading/test/dependency-graph/outer.ts +0 -5
  394. package/src/utils/preview/hot-reloading/test/some-file.ts +0 -0
  395. package/src/utils/preview/hot-reloading/test/tsconfig.json +0 -8
  396. package/src/utils/preview/index.ts +0 -2
  397. package/src/utils/preview/serve-static-file.ts +0 -51
  398. package/src/utils/preview/start-dev-server.ts +0 -252
  399. package/src/utils/register-spinner-autostopping.ts +0 -28
  400. package/src/utils/style-text.ts +0 -11
  401. package/src/utils/tree.spec.ts +0 -29
  402. package/src/utils/tree.ts +0 -76
  403. package/src/utils/types/hot-reload-change.ts +0 -6
  404. package/src/utils/types/hot-reload-event.ts +0 -3
@@ -0,0 +1,244 @@
1
+ /**
2
+ * Downlevels modern CSS features that email clients don't support,
3
+ * operating on a css-tree StyleSheet AST.
4
+ *
5
+ * 1. CSS Nesting: unnests @media rules from inside selectors
6
+ * `.sm_p-4{@media (min-width:40rem){padding:1rem!important}}`
7
+ * → `@media (min-width:40rem){.sm_p-4{padding:1rem!important}}`
8
+ *
9
+ * 2. Media Queries Level 4 range syntax → legacy min-width/max-width
10
+ * `(width>=40rem)` → `(min-width:40rem)`
11
+ *
12
+ * Gmail, Outlook, Yahoo, and most email clients don't support either feature.
13
+ * See: https://www.caniemail.com/features/css-at-media/
14
+ * https://www.caniemail.com/features/css-nesting/
15
+ */
16
+
17
+ import {
18
+ type Atrule,
19
+ type CssNode,
20
+ clone,
21
+ type Feature,
22
+ type FeatureRange,
23
+ List,
24
+ type ListItem,
25
+ type Rule,
26
+ type StyleSheet,
27
+ walk,
28
+ } from 'css-tree';
29
+
30
+ /**
31
+ * css-tree 3.x introduced new AST node types for query-related at-rules that
32
+ * `@types/css-tree` (still on 2.x at the time of writing) doesn't expose.
33
+ * Augmenting the module here lets the rest of this file work with strong
34
+ * types instead of scattering `as` casts everywhere.
35
+ *
36
+ * - `FeatureRange` is what the parser emits for Media Queries Level 4 range
37
+ * syntax: `(width >= 40rem)`.
38
+ * - `Feature` is the legacy form (`(min-width: 40rem)`) we construct as the
39
+ * downleveled output.
40
+ *
41
+ * Note: we cannot extend the `CssNode` union itself (it's a `type` alias, not
42
+ * an interface), so two narrow casts remain in this file:
43
+ * 1. Widening `node` inside `walk()` so we can narrow against
44
+ * `FeatureRange.type` (`CssNode` doesn't list `'FeatureRange'`).
45
+ * 2. Assigning a constructed `Feature` back to `ListItem<CssNode>.data`.
46
+ *
47
+ * Both are flagged inline and reference back to this block.
48
+ *
49
+ * See:
50
+ * https://github.com/csstree/csstree/blob/master/lib/syntax/node/FeatureRange.js
51
+ * https://github.com/csstree/csstree/blob/master/lib/syntax/node/Feature.js
52
+ */
53
+ declare module 'css-tree' {
54
+ interface FeatureRange extends CssNodeCommon {
55
+ type: 'FeatureRange';
56
+ kind: string;
57
+ left: CssNode;
58
+ leftComparison: string;
59
+ middle: CssNode;
60
+ rightComparison: string | null;
61
+ right: CssNode | null;
62
+ }
63
+
64
+ interface Feature extends CssNodeCommon {
65
+ type: 'Feature';
66
+ kind: string;
67
+ name: string;
68
+ value: CssNode | null;
69
+ }
70
+ }
71
+
72
+ /**
73
+ * Unnest @media at-rules from inside regular rules, and downlevel
74
+ * range media query syntax to legacy min-width/max-width.
75
+ *
76
+ * Mutates the stylesheet in place.
77
+ */
78
+ export function downlevelForEmailClients(styleSheet: StyleSheet): void {
79
+ unnestMediaQueries(styleSheet);
80
+ downlevelRangeMediaQueries(styleSheet);
81
+ }
82
+
83
+ // ---------------------------------------------------------------------------
84
+ // Unnesting
85
+ // ---------------------------------------------------------------------------
86
+
87
+ interface UnnestTransform {
88
+ parentRule: Rule;
89
+ parentItem: ListItem<CssNode>;
90
+ parentList: List<CssNode>;
91
+ nestedAtrules: Atrule[];
92
+ remainingChildren: CssNode[];
93
+ }
94
+
95
+ /**
96
+ * Walk the stylesheet and unnest any @media/@supports rules that are nested
97
+ * inside regular rules. For each, the parent Rule's selector wraps the
98
+ * at-rule's body.
99
+ *
100
+ * Before: `.sm_p-4 { @media (...) { padding: 1rem } }`
101
+ * After: `@media (...) { .sm_p-4 { padding: 1rem } }`
102
+ */
103
+ function unnestMediaQueries(styleSheet: StyleSheet): void {
104
+ const transforms: UnnestTransform[] = [];
105
+
106
+ walk(styleSheet, {
107
+ visit: 'Rule',
108
+ enter(rule, item, list) {
109
+ if (!rule.block || !item) return;
110
+
111
+ const nestedAtrules: Atrule[] = [];
112
+ const remainingChildren: CssNode[] = [];
113
+
114
+ rule.block.children.forEach((child) => {
115
+ if (
116
+ child.type === 'Atrule' &&
117
+ (child.name === 'media' || child.name === 'supports')
118
+ ) {
119
+ nestedAtrules.push(child);
120
+ } else {
121
+ remainingChildren.push(child);
122
+ }
123
+ });
124
+
125
+ if (nestedAtrules.length > 0) {
126
+ transforms.push({
127
+ parentRule: rule,
128
+ parentItem: item,
129
+ parentList: list,
130
+ nestedAtrules,
131
+ remainingChildren,
132
+ });
133
+ }
134
+ },
135
+ });
136
+
137
+ // Apply in reverse so list positions stay valid
138
+ for (let i = transforms.length - 1; i >= 0; i--) {
139
+ const {
140
+ parentRule,
141
+ parentItem,
142
+ parentList,
143
+ nestedAtrules,
144
+ remainingChildren,
145
+ } = transforms[i]!;
146
+
147
+ // Build replacement list: [modified parent rule (if any), unnested @media rules...]
148
+ const replacements = new List<CssNode>();
149
+
150
+ if (remainingChildren.length > 0) {
151
+ parentRule.block.children = new List<CssNode>().fromArray(
152
+ remainingChildren,
153
+ );
154
+ replacements.appendData(parentRule);
155
+ }
156
+
157
+ for (const atrule of nestedAtrules) {
158
+ const wrappedRule: Rule = {
159
+ type: 'Rule',
160
+ prelude: clone(parentRule.prelude) as Rule['prelude'],
161
+ block: {
162
+ type: 'Block',
163
+ children: atrule.block ? atrule.block.children : new List<CssNode>(),
164
+ },
165
+ };
166
+
167
+ const newAtrule: Atrule = {
168
+ type: 'Atrule',
169
+ name: atrule.name,
170
+ prelude: atrule.prelude,
171
+ block: {
172
+ type: 'Block',
173
+ children: new List<CssNode>().fromArray([wrappedRule]),
174
+ },
175
+ };
176
+
177
+ replacements.appendData(newAtrule);
178
+ }
179
+
180
+ // Replace the original rule with the entire list of new nodes
181
+ parentList.replace(parentItem, replacements);
182
+ }
183
+ }
184
+
185
+ // ---------------------------------------------------------------------------
186
+ // Range media query downleveling
187
+ // ---------------------------------------------------------------------------
188
+
189
+ /**
190
+ * Walk all nodes and downlevel range syntax (`FeatureRange`) inside @media
191
+ * preludes to legacy `Feature` nodes (`min-width` / `max-width`).
192
+ */
193
+ function downlevelRangeMediaQueries(styleSheet: StyleSheet): void {
194
+ const replacements: Array<{
195
+ item: ListItem<CssNode>;
196
+ replacement: Feature;
197
+ }> = [];
198
+
199
+ walk(styleSheet, {
200
+ enter(originalNode, item) {
201
+ // See module augmentation above: `CssNode` (from @types/css-tree 2.x)
202
+ // doesn't include `FeatureRange`, so widen here to enable narrowing.
203
+ const node = originalNode as CssNode | FeatureRange;
204
+ if (item && node.type === 'FeatureRange') {
205
+ const replacement = downlevelFeatureRange(node);
206
+ if (replacement) {
207
+ replacements.push({ item, replacement });
208
+ }
209
+ }
210
+ },
211
+ });
212
+
213
+ for (const { item, replacement } of replacements) {
214
+ // See module augmentation above: `Feature` is not part of the `CssNode`
215
+ // union, so a single cast is required when handing it back to the AST.
216
+ item.data = replacement as unknown as CssNode;
217
+ }
218
+ }
219
+
220
+ /**
221
+ * Convert a `FeatureRange` node to a `Feature` node (legacy min-/max- syntax).
222
+ *
223
+ * For `width >= 40rem`: left=Identifier("width"), leftComparison=">=", middle=Dimension("40","rem")
224
+ * Result: { type: "Feature", name: "min-width", value: Dimension("40","rem") }
225
+ */
226
+ function downlevelFeatureRange(range: FeatureRange): Feature | null {
227
+ if (range.left.type !== 'Identifier') return null;
228
+
229
+ let prefix: string;
230
+ if (range.leftComparison === '>=' || range.leftComparison === '>') {
231
+ prefix = 'min-';
232
+ } else if (range.leftComparison === '<=' || range.leftComparison === '<') {
233
+ prefix = 'max-';
234
+ } else {
235
+ return null;
236
+ }
237
+
238
+ return {
239
+ type: 'Feature',
240
+ kind: 'media',
241
+ name: `${prefix}${range.left.name}`,
242
+ value: range.middle,
243
+ };
244
+ }
@@ -0,0 +1,232 @@
1
+ import { generate, type Rule } from 'css-tree';
2
+ import { setupTailwind } from '../tailwindcss/setup-tailwind.js';
3
+ import { extractRulesPerClass } from './extract-rules-per-class.js';
4
+
5
+ describe('extractRulesPerClass()', async () => {
6
+ function convertToComparable(
7
+ map: Map<string, Rule[]>,
8
+ ): Record<string, string[]> {
9
+ return Object.fromEntries(
10
+ map
11
+ .entries()
12
+ .map(([k, rules]) => [k, rules.map((rule) => generate(rule))]),
13
+ );
14
+ }
15
+
16
+ it('works with just inlinable utilities', async () => {
17
+ const tailwind = await setupTailwind({});
18
+ const classes = ['text-center', 'bg-red-500'];
19
+ tailwind.addUtilities(classes);
20
+
21
+ const stylesheet = tailwind.getStyleSheet();
22
+
23
+ const { inlinable, nonInlinable } = extractRulesPerClass(
24
+ stylesheet,
25
+ classes,
26
+ );
27
+
28
+ expect(convertToComparable(inlinable)).toMatchInlineSnapshot(`
29
+ {
30
+ "bg-red-500": [
31
+ ".bg-red-500{background-color:var(--color-red-500)}",
32
+ ],
33
+ "text-center": [
34
+ ".text-center{text-align:center}",
35
+ ],
36
+ }
37
+ `);
38
+ expect(convertToComparable(nonInlinable)).toMatchInlineSnapshot('{}');
39
+ });
40
+
41
+ it('keeps every rule when a class is defined more than once', async () => {
42
+ const tailwind = await setupTailwind({
43
+ config: {
44
+ plugins: [
45
+ {
46
+ handler: (api) => {
47
+ api.addComponents({
48
+ '.box': { '@apply rounded-lg bg-white p-4': {} },
49
+ });
50
+ api.addComponents({
51
+ '.box': { '@apply bg-red-500': {} },
52
+ });
53
+ },
54
+ },
55
+ ],
56
+ },
57
+ });
58
+ const classes = ['box'];
59
+ tailwind.addUtilities(classes);
60
+
61
+ const stylesheet = tailwind.getStyleSheet();
62
+ const { inlinable } = extractRulesPerClass(stylesheet, classes);
63
+
64
+ expect(convertToComparable(inlinable)).toMatchInlineSnapshot(`
65
+ {
66
+ "box": [
67
+ ".box{border-radius:var(--radius-lg);background-color:var(--color-white);padding:calc(var(--spacing)*4)}",
68
+ ".box{background-color:var(--color-red-500)}",
69
+ ],
70
+ }
71
+ `);
72
+ });
73
+
74
+ it('handles non-inlinable utilities', async () => {
75
+ const tailwind = await setupTailwind({});
76
+ const classes = ['lg:w-1/2'];
77
+ tailwind.addUtilities(classes);
78
+
79
+ const stylesheet = tailwind.getStyleSheet();
80
+
81
+ const { inlinable, nonInlinable } = extractRulesPerClass(
82
+ stylesheet,
83
+ classes,
84
+ );
85
+
86
+ expect(convertToComparable(inlinable)).toMatchInlineSnapshot('{}');
87
+ expect(convertToComparable(nonInlinable)).toMatchInlineSnapshot(`
88
+ {
89
+ "lg:w-1/2": [
90
+ ".lg\\:w-1\\/2{@media (width>=64rem){width:calc(1/2*100%)}}",
91
+ ],
92
+ }
93
+ `);
94
+ });
95
+
96
+ it('handles a mix of inlinable and non-inlinable utilities', async () => {
97
+ const tailwind = await setupTailwind({});
98
+ const classes = [
99
+ 'text-center',
100
+ 'bg-red-500',
101
+ 'some-other-class', // should be ignored
102
+ 'w-full',
103
+ 'lg:w-1/2',
104
+ ];
105
+ tailwind.addUtilities(classes);
106
+
107
+ const stylesheet = tailwind.getStyleSheet();
108
+ const { inlinable, nonInlinable } = extractRulesPerClass(
109
+ stylesheet,
110
+ classes,
111
+ );
112
+ expect(convertToComparable(inlinable)).toMatchInlineSnapshot(`
113
+ {
114
+ "bg-red-500": [
115
+ ".bg-red-500{background-color:var(--color-red-500)}",
116
+ ],
117
+ "text-center": [
118
+ ".text-center{text-align:center}",
119
+ ],
120
+ "w-full": [
121
+ ".w-full{width:100%}",
122
+ ],
123
+ }
124
+ `);
125
+ expect(convertToComparable(nonInlinable)).toMatchInlineSnapshot(`
126
+ {
127
+ "lg:w-1/2": [
128
+ ".lg\\:w-1\\/2{@media (width>=64rem){width:calc(1/2*100%)}}",
129
+ ],
130
+ }
131
+ `);
132
+ });
133
+
134
+ it('splits mixed rules (base + media) into inlinable base and non-inlinable media', async () => {
135
+ const tailwind = await setupTailwind({
136
+ config: {
137
+ plugins: [
138
+ {
139
+ handler: (api) => {
140
+ api.addUtilities({
141
+ '.text-body': {
142
+ '@apply text-[green] sm:text-[darkgreen]': {},
143
+ },
144
+ });
145
+ },
146
+ },
147
+ ],
148
+ },
149
+ });
150
+ const classes = ['text-body'];
151
+ tailwind.addUtilities(classes);
152
+
153
+ const stylesheet = tailwind.getStyleSheet();
154
+ const { inlinable, nonInlinable } = extractRulesPerClass(
155
+ stylesheet,
156
+ classes,
157
+ );
158
+
159
+ expect(convertToComparable(inlinable)).toMatchInlineSnapshot(`
160
+ {
161
+ "text-body": [
162
+ ".text-body{color:green}",
163
+ ],
164
+ }
165
+ `);
166
+ expect(convertToComparable(nonInlinable)).toMatchInlineSnapshot(`
167
+ {
168
+ "text-body": [
169
+ ".text-body{@media (width>=40rem){color:darkgreen}}",
170
+ ],
171
+ }
172
+ `);
173
+ });
174
+
175
+ it('treats rules with pseudo-selectors as fully non-inlinable', async () => {
176
+ const tailwind = await setupTailwind({
177
+ config: {
178
+ plugins: [
179
+ {
180
+ handler: (api) => {
181
+ api.addUtilities({
182
+ '.btn:hover': {
183
+ color: 'red',
184
+ },
185
+ });
186
+ },
187
+ },
188
+ ],
189
+ },
190
+ });
191
+ const classes = ['btn'];
192
+ tailwind.addUtilities(classes);
193
+
194
+ const stylesheet = tailwind.getStyleSheet();
195
+ const { inlinable, nonInlinable } = extractRulesPerClass(
196
+ stylesheet,
197
+ classes,
198
+ );
199
+
200
+ expect(convertToComparable(inlinable)).toMatchInlineSnapshot('{}');
201
+ expect(convertToComparable(nonInlinable)).toMatchInlineSnapshot(`
202
+ {
203
+ "btn": [
204
+ ".btn{&:hover{color:red}}",
205
+ ],
206
+ }
207
+ `);
208
+ });
209
+
210
+ it('does not emit a bare nested rule for group/peer marker classes', async () => {
211
+ const tailwind = await setupTailwind({});
212
+ const classes = ['group', 'group-hover:underline'];
213
+ tailwind.addUtilities(classes);
214
+
215
+ const stylesheet = tailwind.getStyleSheet();
216
+ const { inlinable, nonInlinable } = extractRulesPerClass(
217
+ stylesheet,
218
+ classes,
219
+ );
220
+
221
+ // Only the real utility is keyed; the `group` marker must not produce a
222
+ // duplicate, parentless `&:is(...)` rule.
223
+ expect(Object.keys(convertToComparable(inlinable))).toEqual([]);
224
+ expect(convertToComparable(nonInlinable)).toMatchInlineSnapshot(`
225
+ {
226
+ "group-hover:underline": [
227
+ ".group-hover\\:underline{&:is(:where(.group):hover *){@media (hover:hover){text-decoration-line:underline}}}",
228
+ ],
229
+ }
230
+ `);
231
+ });
232
+ });
@@ -0,0 +1,76 @@
1
+ import { type CssNode, type Rule, string, walk } from 'css-tree';
2
+ import { isRuleInlinable } from './is-rule-inlinable.js';
3
+ import { splitMixedRule } from './split-mixed-rule.js';
4
+
5
+ export function extractRulesPerClass(root: CssNode, classes: string[]) {
6
+ const classSet = new Set(classes);
7
+
8
+ // A class can be defined by multiple rules (e.g. a preset and a child config
9
+ // override), so keep them all to merge instead of the last one clobbering.
10
+ const inlinableRules = new Map<string, Rule[]>();
11
+ const nonInlinableRules = new Map<string, Rule[]>();
12
+
13
+ const appendRule = (
14
+ map: Map<string, Rule[]>,
15
+ className: string,
16
+ rule: Rule,
17
+ ) => {
18
+ const existing = map.get(className);
19
+ if (existing) {
20
+ existing.push(rule);
21
+ } else {
22
+ map.set(className, [rule]);
23
+ }
24
+ };
25
+
26
+ walk(root, {
27
+ visit: 'Rule',
28
+ enter(rule) {
29
+ // A nested rule (e.g. group/peer's `&:is(:where(.group):hover *)`) belongs
30
+ // to its parent utility; processing it standalone emits a bare, parentless
31
+ // `&` rule into the <style> block, so skip it here.
32
+ const firstSelector =
33
+ rule.prelude.type === 'SelectorList'
34
+ ? rule.prelude.children.first
35
+ : null;
36
+ if (
37
+ firstSelector?.type === 'Selector' &&
38
+ firstSelector.children.first?.type === 'NestingSelector'
39
+ ) {
40
+ return;
41
+ }
42
+
43
+ // Only the prelude names the class that owns the rule; classes referenced
44
+ // inside the block (e.g. `.group` in `:where(.group)`) must not key it.
45
+ const selectorClasses: string[] = [];
46
+ walk(rule.prelude, {
47
+ visit: 'ClassSelector',
48
+ enter(classSelector) {
49
+ selectorClasses.push(string.decode(classSelector.name));
50
+ },
51
+ });
52
+ if (isRuleInlinable(rule)) {
53
+ for (const className of selectorClasses) {
54
+ if (classSet.has(className)) {
55
+ appendRule(inlinableRules, className, rule);
56
+ }
57
+ }
58
+ } else {
59
+ const { inlinablePart, nonInlinablePart } = splitMixedRule(rule);
60
+ for (const className of selectorClasses) {
61
+ if (!classSet.has(className)) continue;
62
+ if (inlinablePart) {
63
+ appendRule(inlinableRules, className, inlinablePart);
64
+ }
65
+ if (nonInlinablePart) {
66
+ appendRule(nonInlinableRules, className, nonInlinablePart);
67
+ }
68
+ }
69
+ }
70
+ },
71
+ });
72
+ return {
73
+ inlinable: inlinableRules,
74
+ nonInlinable: nonInlinableRules,
75
+ };
76
+ }
@@ -0,0 +1,49 @@
1
+ import { type CssNode, type Declaration, generate, walk } from 'css-tree';
2
+
3
+ export interface CustomProperty {
4
+ syntax?: Declaration;
5
+ inherits?: Declaration;
6
+ initialValue?: Declaration;
7
+ }
8
+
9
+ export type CustomProperties = Map<string, CustomProperty>;
10
+
11
+ export function getCustomProperties(node: CssNode) {
12
+ const customProperties = new Map<string, CustomProperty>();
13
+
14
+ walk(node, {
15
+ visit: 'Atrule',
16
+ enter(atrule) {
17
+ if (atrule.name === 'property' && atrule.prelude) {
18
+ const prelude = generate(atrule.prelude);
19
+ if (prelude.startsWith('--')) {
20
+ let syntax: Declaration | undefined;
21
+ let inherits: Declaration | undefined;
22
+ let initialValue: Declaration | undefined;
23
+ walk(atrule, {
24
+ visit: 'Declaration',
25
+ enter(declaration) {
26
+ if (declaration.property === 'syntax') {
27
+ syntax = declaration;
28
+ }
29
+ if (declaration.property === 'inherits') {
30
+ inherits = declaration;
31
+ }
32
+ if (declaration.property === 'initial-value') {
33
+ initialValue = declaration;
34
+ }
35
+ },
36
+ });
37
+
38
+ customProperties.set(prelude, {
39
+ syntax,
40
+ inherits,
41
+ initialValue,
42
+ });
43
+ }
44
+ }
45
+ },
46
+ });
47
+
48
+ return customProperties;
49
+ }
@@ -0,0 +1,15 @@
1
+ import { type CssNode, find } from 'css-tree';
2
+
3
+ export function isPartInlinable(part: CssNode): boolean {
4
+ const hasAtRuleInside = find(part, (node) => node.type === 'Atrule') !== null;
5
+
6
+ const hasPseudoSelector =
7
+ find(
8
+ part,
9
+ (node) =>
10
+ node.type === 'PseudoClassSelector' ||
11
+ node.type === 'PseudoElementSelector',
12
+ ) !== null;
13
+
14
+ return !hasAtRuleInside && !hasPseudoSelector;
15
+ }
@@ -0,0 +1,15 @@
1
+ import { find, type Rule } from 'css-tree';
2
+
3
+ export function isRuleInlinable(rule: Rule): boolean {
4
+ const hasAtRuleInside = find(rule, (node) => node.type === 'Atrule') !== null;
5
+
6
+ const hasPseudoSelector =
7
+ find(
8
+ rule,
9
+ (node) =>
10
+ node.type === 'PseudoClassSelector' ||
11
+ node.type === 'PseudoElementSelector',
12
+ ) !== null;
13
+
14
+ return !hasAtRuleInside && !hasPseudoSelector;
15
+ }