@maizzle/framework 6.0.0-13 → 6.0.0-15
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/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## [6.0.0-14] - 2025-07-17
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- fix: replace css properties 9f37941
|
|
12
|
+
|
|
7
13
|
## [6.0.0-13] - 2025-07-17
|
|
8
14
|
|
|
9
15
|
### Added
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@maizzle/framework",
|
|
3
|
-
"version": "6.0.0-
|
|
3
|
+
"version": "6.0.0-15",
|
|
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",
|
|
@@ -71,6 +71,7 @@
|
|
|
71
71
|
"ora": "^8.1.0",
|
|
72
72
|
"pathe": "^2.0.0",
|
|
73
73
|
"postcss": "^8.4.49",
|
|
74
|
+
"postcss-calc": "^10.1.1",
|
|
74
75
|
"postcss-custom-properties": "^14.0.6",
|
|
75
76
|
"postcss-safe-parser": "^7.0.0",
|
|
76
77
|
"postcss-sort-media-queries": "^5.2.0",
|
|
@@ -65,6 +65,10 @@ async function processCss(css, config) {
|
|
|
65
65
|
* PostCSS pipeline. Plugins defined and added here
|
|
66
66
|
* will apply to all `<style>` tags in the HTML,
|
|
67
67
|
* unless marked to be excluded.
|
|
68
|
+
*
|
|
69
|
+
* @param {string} css CSS content to process
|
|
70
|
+
* @param {Object} config Maizzle configuration object
|
|
71
|
+
* @returns {Promise<string>} Processed CSS string
|
|
68
72
|
*/
|
|
69
73
|
let resolveCSSProps = get(config, 'css.resolveProps')
|
|
70
74
|
if (resolveCSSProps !== false) {
|
|
@@ -91,7 +95,7 @@ async function processCss(css, config) {
|
|
|
91
95
|
].filter(Boolean)).process(css, merge(
|
|
92
96
|
get(config, 'postcss.options', {}),
|
|
93
97
|
{
|
|
94
|
-
from: config
|
|
98
|
+
from: get(config, 'cwd', './'),
|
|
95
99
|
parser: postcssSafeParser
|
|
96
100
|
}
|
|
97
101
|
))
|
|
@@ -107,10 +111,10 @@ async function processCss(css, config) {
|
|
|
107
111
|
try {
|
|
108
112
|
const { code } = transform(
|
|
109
113
|
merge(
|
|
110
|
-
lightningCssOptions,
|
|
111
114
|
{
|
|
112
115
|
code: Buffer.from(result.css)
|
|
113
|
-
}
|
|
116
|
+
},
|
|
117
|
+
lightningCssOptions,
|
|
114
118
|
)
|
|
115
119
|
)
|
|
116
120
|
|
|
@@ -2,6 +2,7 @@ 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 postcssCalc from 'postcss-calc'
|
|
5
6
|
import * as cheerio from 'cheerio/slim'
|
|
6
7
|
import remove from 'lodash-es/remove.js'
|
|
7
8
|
import { render } from 'posthtml-render'
|
|
@@ -10,6 +11,7 @@ import { match } from 'posthtml/lib/api.js'
|
|
|
10
11
|
import safeParser from 'postcss-safe-parser'
|
|
11
12
|
import isObject from 'lodash-es/isObject.js'
|
|
12
13
|
import { parser as parse } from 'posthtml-parser'
|
|
14
|
+
import customProperties from 'postcss-custom-properties'
|
|
13
15
|
import { useAttributeSizes } from './useAttributeSizes.js'
|
|
14
16
|
import { getPosthtmlOptions } from '../posthtml/defaultConfig.js'
|
|
15
17
|
|
|
@@ -134,6 +136,7 @@ export async function inline(html = '', options = {}) {
|
|
|
134
136
|
|
|
135
137
|
const preservedAtRules = get(options, 'preservedAtRules', ['media'])
|
|
136
138
|
const selectors = new Set()
|
|
139
|
+
const rootSelectorCss = new Set()
|
|
137
140
|
|
|
138
141
|
inlined_tree.match({ tag: 'style' }, node => {
|
|
139
142
|
// If this is an embedded style tag, exit early
|
|
@@ -177,6 +180,10 @@ export async function inline(html = '', options = {}) {
|
|
|
177
180
|
// Create a set of selectors
|
|
178
181
|
const { selector } = rule
|
|
179
182
|
|
|
183
|
+
if (selector.includes(':root')) {
|
|
184
|
+
rootSelectorCss.add(rule.toString())
|
|
185
|
+
}
|
|
186
|
+
|
|
180
187
|
// Add the selector to the set as long as it's not a pseudo selector
|
|
181
188
|
if (!/.+[^\\\s]::?\w+/.test(selector)) {
|
|
182
189
|
selectors.add({
|
|
@@ -189,7 +196,6 @@ export async function inline(html = '', options = {}) {
|
|
|
189
196
|
options.safelist.add(selector)
|
|
190
197
|
}
|
|
191
198
|
|
|
192
|
-
|
|
193
199
|
if (options.removeInlinedSelectors) {
|
|
194
200
|
// Remove the rule in the <style> tag as long as it's not a preserved class
|
|
195
201
|
if (!options.safelist.has(selector) && !combinedRegex.test(selector)) {
|
|
@@ -288,6 +294,46 @@ export async function inline(html = '', options = {}) {
|
|
|
288
294
|
} catch { }
|
|
289
295
|
})
|
|
290
296
|
|
|
297
|
+
/**
|
|
298
|
+
* Find all elements with non-empty `style` attributes and
|
|
299
|
+
* process their values with PostCSS.
|
|
300
|
+
*
|
|
301
|
+
* We do this in order to compile CSS variables and calc()
|
|
302
|
+
* functions that may have been inlined by Juice.
|
|
303
|
+
*/
|
|
304
|
+
for (const el of $('[style]')) {
|
|
305
|
+
const styleAttr = $(el).attr('style')
|
|
306
|
+
if (!styleAttr || styleAttr.trim() === '') {
|
|
307
|
+
continue
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
const processedCss = postcss([
|
|
311
|
+
customProperties({ preserve: false }),
|
|
312
|
+
postcssCalc(),
|
|
313
|
+
{
|
|
314
|
+
postcssPlugin: 'remove-root-selectors',
|
|
315
|
+
Rule(rule) {
|
|
316
|
+
// Split comma-separated selectors and filter out :root
|
|
317
|
+
const selectors = rule.selector.split(',').map(s => s.trim());
|
|
318
|
+
const filteredSelectors = selectors.filter(s => !s.startsWith(':root'));
|
|
319
|
+
|
|
320
|
+
if (filteredSelectors.length === 0) {
|
|
321
|
+
// Remove the entire rule if all selectors were :root
|
|
322
|
+
rule.remove();
|
|
323
|
+
} else if (filteredSelectors.length < selectors.length) {
|
|
324
|
+
// Update the selector if some (but not all) were :root
|
|
325
|
+
rule.selector = filteredSelectors.join(', ');
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
]).process(`${[...rootSelectorCss].join('\n')} ${styleAttr}`, {
|
|
330
|
+
from: undefined,
|
|
331
|
+
parser: safeParser,
|
|
332
|
+
}).css
|
|
333
|
+
|
|
334
|
+
$(el).attr('style', processedCss.trim())
|
|
335
|
+
}
|
|
336
|
+
|
|
291
337
|
const optimized_tree = parse($.html(), posthtmlOptions)
|
|
292
338
|
optimized_tree.match = match
|
|
293
339
|
|
|
@@ -11,10 +11,6 @@ export default (maizzleConfig => tree => {
|
|
|
11
11
|
|
|
12
12
|
const replacements = get(maizzleConfig, 'css.replaceProperties', {})
|
|
13
13
|
|
|
14
|
-
if (Object.keys(replacements).length === 0) {
|
|
15
|
-
return node
|
|
16
|
-
}
|
|
17
|
-
|
|
18
14
|
const css = Array.isArray(node.content) ? node.content.join('') : node.content
|
|
19
15
|
|
|
20
16
|
postcss([
|
package/types/config.d.ts
CHANGED
|
@@ -242,6 +242,24 @@ export default interface Config {
|
|
|
242
242
|
* ```
|
|
243
243
|
*/
|
|
244
244
|
combineMediaQueries?: PostCSSSortMediaQueriesOptions;
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* `replaceCssProperties` Transformer.
|
|
248
|
+
*
|
|
249
|
+
* Define a mapping object of which CSS properties to replace with what strings.
|
|
250
|
+
*
|
|
251
|
+
* @default {'text-decoration-line': 'text-decoration'}
|
|
252
|
+
*
|
|
253
|
+
* @example
|
|
254
|
+
* ```
|
|
255
|
+
* export default {
|
|
256
|
+
* css: {
|
|
257
|
+
* replaceCssProperties: {
|
|
258
|
+
* 'text-decoration-line': 'text-decoration',
|
|
259
|
+
* 'margin': 'Margin',
|
|
260
|
+
* }
|
|
261
|
+
*/
|
|
262
|
+
replaceCssProperties?: Record<string, string>;
|
|
245
263
|
}
|
|
246
264
|
|
|
247
265
|
/**
|
package/types/css/inline.d.ts
CHANGED
|
@@ -215,4 +215,22 @@ export default interface InlineCSSConfig {
|
|
|
215
215
|
* ```
|
|
216
216
|
*/
|
|
217
217
|
safelist?: string[];
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Preserved CSS at-rules.
|
|
221
|
+
*
|
|
222
|
+
* These will not be removed as part of the CSS inlining process.
|
|
223
|
+
*
|
|
224
|
+
* @default ['media']
|
|
225
|
+
*
|
|
226
|
+
* @example
|
|
227
|
+
* ```
|
|
228
|
+
* export default {
|
|
229
|
+
* css: {
|
|
230
|
+
* preservedAtRules: ['media', 'supports'],
|
|
231
|
+
* }
|
|
232
|
+
* }
|
|
233
|
+
* ```
|
|
234
|
+
*/
|
|
235
|
+
preservedAtRules?: string[];
|
|
218
236
|
}
|