@maizzle/framework 5.0.0-beta.33 → 5.0.0-beta.35

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@maizzle/framework",
3
- "version": "5.0.0-beta.33",
3
+ "version": "5.0.0-beta.35",
4
4
  "description": "Maizzle is a framework that helps you quickly build HTML emails with Tailwind CSS.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -48,7 +48,6 @@
48
48
  "html-emails"
49
49
  ],
50
50
  "dependencies": {
51
- "@csstools/css-calc": "^2.0.1",
52
51
  "@maizzle/cli": "next",
53
52
  "cheerio": "^1.0.0",
54
53
  "chokidar": "^3.6.0",
@@ -68,6 +67,7 @@
68
67
  "ora": "^8.1.0",
69
68
  "pathe": "^1.1.2",
70
69
  "postcss": "^8.4.49",
70
+ "postcss-calc": "^10.0.2",
71
71
  "postcss-css-variables": "^0.19.0",
72
72
  "postcss-import": "^16.1.0",
73
73
  "postcss-safe-parser": "^7.0.0",
@@ -13,6 +13,7 @@ import { getPosthtmlOptions } from './defaultConfig.js'
13
13
 
14
14
  // PostCSS
15
15
  import tailwindcss from 'tailwindcss'
16
+ import postcssCalc from 'postcss-calc'
16
17
  import postcssImport from 'postcss-import'
17
18
  import cssVariables from 'postcss-css-variables'
18
19
  import postcssSafeParser from 'postcss-safe-parser'
@@ -20,13 +21,21 @@ import postcssSafeParser from 'postcss-safe-parser'
20
21
  import defaultComponentsConfig from './defaultComponentsConfig.js'
21
22
 
22
23
  export async function process(html = '', config = {}) {
24
+ /**
25
+ * Configure PostCSS pipeline. Plugins defined and added here
26
+ * will apply to all `<style>` tags in the HTML.
27
+ */
23
28
  const resolveCSSProps = get(config, 'css.resolveProps')
29
+ const resolveCalc = get(config, 'css.resolveCalc') !== false
30
+ ? get(config, 'css.resolveCalc', { precision: 2 }) // it's true by default, use default precision 2
31
+ : false
24
32
 
25
33
  const postcssPlugin = posthtmlPostcss(
26
34
  [
27
35
  postcssImport(),
28
36
  tailwindcss(get(config, 'css.tailwind', {})),
29
37
  resolveCSSProps !== false && cssVariables(resolveCSSProps),
38
+ resolveCalc !== false && postcssCalc(resolveCalc),
30
39
  ...get(config, 'postcss.plugins', []),
31
40
  ],
32
41
  merge(
@@ -38,6 +47,10 @@ export async function process(html = '', config = {}) {
38
47
  )
39
48
  )
40
49
 
50
+ /**
51
+ * Define PostHTML options by merging user-provided ones
52
+ * on top of a default configuration.
53
+ */
41
54
  const posthtmlOptions = getPosthtmlOptions(get(config, 'posthtml.options', {}))
42
55
 
43
56
  const componentsUserOptions = get(config, 'components', {})
@@ -62,7 +62,7 @@ async function renderUpdatedFile(file, config) {
62
62
  spinner.start('Building...')
63
63
 
64
64
  /**
65
- * Add the current template path to the config
65
+ * Add current template path info to the config
66
66
  *
67
67
  * Can be used in events like `beforeRender` to determine
68
68
  * which template file is being rendered.
@@ -178,6 +178,11 @@ export default async (config = {}) => {
178
178
  // Set the file being viewed
179
179
  viewing = filePath
180
180
 
181
+ // Add current template path info to the config
182
+ config.build.current = {
183
+ path: path.parse(filePath),
184
+ }
185
+
181
186
  // Read the file
182
187
  const fileContent = await fs.readFile(filePath, 'utf8')
183
188
 
@@ -2,11 +2,9 @@ import juice from 'juice'
2
2
  import postcss from 'postcss'
3
3
  import get from 'lodash-es/get.js'
4
4
  import has from 'lodash-es/has.js'
5
- import { defu as merge } from 'defu'
6
5
  import * as cheerio from 'cheerio/slim'
7
6
  import remove from 'lodash-es/remove.js'
8
7
  import { render } from 'posthtml-render'
9
- import { calc } from '@csstools/css-calc'
10
8
  import isEmpty from 'lodash-es/isEmpty.js'
11
9
  import safeParser from 'postcss-safe-parser'
12
10
  import isObject from 'lodash-es/isObject.js'
@@ -30,9 +28,7 @@ export async function inline(html = '', options = {}) {
30
28
  const removeStyleTags = get(options, 'removeStyleTags', false)
31
29
  const css = get(options, 'customCSS', false)
32
30
 
33
- options.resolveCSSVariables = get(options, 'resolveCSSVariables', true)
34
31
  options.removeInlinedSelectors = get(options, 'removeInlinedSelectors', true)
35
- options.resolveCalc = get(options, 'resolveCalc', true)
36
32
  options.preferUnitlessValues = get(options, 'preferUnitlessValues', true)
37
33
  options.safelist = new Set([
38
34
  ...get(options, 'safelist', []),
@@ -147,37 +143,6 @@ export async function inline(html = '', options = {}) {
147
143
 
148
144
  // For each rule in the CSS block we're parsing
149
145
  root.walkRules(rule => {
150
- // Keep track of declarations in the rule
151
- const declarations = new Set()
152
-
153
- rule.walkDecls(decl => {
154
- // Resolve calc() values to static values
155
- if (options.resolveCalc) {
156
- decl.value = decl.value.includes('calc(') ? calc(decl.value, { precision: 2 }) : decl.value
157
- }
158
-
159
- declarations.add(decl)
160
- })
161
-
162
- /**
163
- * Remove duplicate declarations
164
- *
165
- * Only do so if the `resolveCSSVariables` option is enabled,
166
- * otherwise we'll end up removing all declarations that use CSS variables
167
- */
168
- if (options.resolveCSSVariables) {
169
- Array.from(declarations)
170
- /**
171
- * Consider only declarations with a value that includes any of the other declarations' property
172
- * So a decl like color(var(--text-color)) will be removed if there's a decl with a property of --text-color
173
- * */
174
- .filter(decl =>
175
- Array.from(declarations).some(otherDecl => decl.value.includes(otherDecl.prop))
176
- || decl.prop.startsWith('--')
177
- )
178
- .map(decl => decl.remove())
179
- }
180
-
181
146
  const { selector } = rule
182
147
 
183
148
  selectors.add({
@@ -186,7 +151,6 @@ export async function inline(html = '', options = {}) {
186
151
  })
187
152
 
188
153
  // Preserve pseudo selectors
189
- // TODO: revisit pseudos list
190
154
  if ([':hover', ':active', ':focus', ':visited', ':link', ':before', ':after'].some(i => selector.includes(i))) {
191
155
  options.safelist.add(selector)
192
156
  }
@@ -218,10 +182,6 @@ export async function inline(html = '', options = {}) {
218
182
  inlineStyles = styleAttr.split(';').reduce((acc, i) => {
219
183
  let { property, value } = parseCSSRule(i)
220
184
 
221
- if (value && options.resolveCalc) {
222
- value = value.includes('calc') ? calc(value, { precision: 2 }) : value
223
- }
224
-
225
185
  if (value && options.preferUnitlessValues) {
226
186
  value = value.replace(
227
187
  /\b0(px|rem|em|%|vh|vw|vmin|vmax|in|cm|mm|pt|pc|ex|ch)\b/g,
package/types/config.d.ts CHANGED
@@ -12,6 +12,7 @@ import type WidowWordsConfig from './widowWords';
12
12
  import type { CoreBeautifyOptions } from 'js-beautify';
13
13
  import type { BaseURLConfig } from 'posthtml-base-url';
14
14
  import type URLParametersConfig from './urlParameters';
15
+ import type { PostCssCalcOptions } from 'postcss-calc';
15
16
  import type { PostHTMLFetchConfig } from 'posthtml-fetch';
16
17
  import type { Config as TailwindConfig } from 'tailwindcss';
17
18
  import type { PostHTMLComponents } from 'posthtml-component';
@@ -41,7 +42,7 @@ export default interface Config {
41
42
  * }
42
43
  * ```
43
44
  */
44
- add?: Record<string, Record<string, string|number>>;
45
+ add?: Record<string, Record<string, string | number>>;
45
46
 
46
47
  /**
47
48
  * Remove attributes from elements.
@@ -110,6 +111,52 @@ export default interface Config {
110
111
  */
111
112
  purge?: PurgeCSSConfig;
112
113
 
114
+ /**
115
+ * Resolve CSS `calc()` expressions to their static values.
116
+ */
117
+ resolveCalc?: boolean | PostCssCalcOptions;
118
+
119
+ /**
120
+ * Resolve CSS custom properties to their static values.
121
+ */
122
+ resolveProps?: boolean | {
123
+ /**
124
+ * Whether to preserve custom properties in the output.
125
+ *
126
+ * @default false
127
+ */
128
+ preserve?: boolean | 'computed';
129
+ /**
130
+ * Define CSS variables that will be added to :root.
131
+ *
132
+ * @default {}
133
+ */
134
+ variables?: {
135
+ [key: string]: string | {
136
+ /**
137
+ * The value of the CSS variable.
138
+ */
139
+ value: string;
140
+ /**
141
+ * Whether the variable is !important.
142
+ */
143
+ isImportant?: boolean;
144
+ };
145
+ };
146
+ /**
147
+ * Whether to preserve variables injected via JS with the `variables` option.
148
+ *
149
+ * @default true
150
+ */
151
+ preserveInjectedVariables?: boolean;
152
+ /**
153
+ * Whether to preserve `@media` rules order.
154
+ *
155
+ * @default false
156
+ */
157
+ preserveAtRulesOrder?: boolean;
158
+ };
159
+
113
160
  /**
114
161
  * Normalize escaped character class names like `\:` or `\/` by replacing them
115
162
  * with email-safe alternatives.
@@ -129,40 +176,40 @@ export default interface Config {
129
176
  safe?: boolean | Record<string, string>;
130
177
 
131
178
  /**
132
- * Ensure that all your HEX colors inside `bgcolor` and `color` attributes are defined with six digits.
179
+ * Rewrite longhand CSS inside style attributes with shorthand syntax.
180
+ * Only works with `margin`, `padding` and `border`, and only when
181
+ * all sides are specified.
133
182
  *
134
- * @default true
183
+ * @default []
135
184
  *
136
185
  * @example
137
186
  * ```
138
187
  * export default {
139
188
  * css: {
140
- * sixHex: false,
189
+ * shorthand: {
190
+ * tags: ['td', 'div'],
191
+ * } // or shorthand: true
141
192
  * }
142
193
  * }
143
194
  * ```
144
195
  */
145
- sixHex?: boolean;
196
+ shorthand?: boolean | Record<string, string[]>;
146
197
 
147
198
  /**
148
- * Rewrite longhand CSS inside style attributes with shorthand syntax.
149
- * Only works with `margin`, `padding` and `border`, and only when
150
- * all sides are specified.
199
+ * Ensure that all your HEX colors inside `bgcolor` and `color` attributes are defined with six digits.
151
200
  *
152
- * @default []
201
+ * @default true
153
202
  *
154
203
  * @example
155
204
  * ```
156
205
  * export default {
157
206
  * css: {
158
- * shorthand: {
159
- * tags: ['td', 'div'],
160
- * } // or shorthand: true
207
+ * sixHex: false,
161
208
  * }
162
209
  * }
163
210
  * ```
164
211
  */
165
- shorthand?: boolean | Record<string, string[]>;
212
+ sixHex?: boolean;
166
213
 
167
214
  /**
168
215
  * Use a custom Tailwind CSS configuration object.
@@ -163,24 +163,6 @@ export default interface InlineCSSConfig {
163
163
  */
164
164
  customCSS?: string | false;
165
165
 
166
- /**
167
- * Resolve CSS variables and replace them with their values.
168
- *
169
- * @default true
170
- *
171
- * @example
172
- * ```
173
- * export default {
174
- * css: {
175
- * inline: {
176
- * resolveVariables: true
177
- * }
178
- * }
179
- * }
180
- * ```
181
- */
182
- resolveVariables?: boolean;
183
-
184
166
  /**
185
167
  * Remove inlined CSS selectors from the `<style>` tag.
186
168
  *
@@ -198,24 +180,6 @@ export default interface InlineCSSConfig {
198
180
  */
199
181
  removeInlinedSelectors?: boolean;
200
182
 
201
- /**
202
- * Resolve calc() expressions in CSS to their computed values.
203
- *
204
- * @default true
205
- *
206
- * @example
207
- * ```
208
- * export default {
209
- * css: {
210
- * inline: {
211
- * resolveCalc: true
212
- * }
213
- * }
214
- * }
215
- * ```
216
- */
217
- resolveCalc?: boolean;
218
-
219
183
  /**
220
184
  * Prefer unitless CSS values
221
185
  *