@maizzle/framework 6.0.0-3 → 6.0.0-4
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,20 @@ 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-3] - 2025-07-14
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- added support for skipping CSS compilation on individual `<style>` tags by adding any of the following attributes: `raw`, `plain`, `as-is`, `uncompiled`, `unprocessed`
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
|
|
15
|
+
- refactored CSS compilation into a custom PostHTML plugin
|
|
16
|
+
|
|
17
|
+
### Removed
|
|
18
|
+
|
|
19
|
+
- removed `posthtml-postcss` dependency
|
|
20
|
+
|
|
7
21
|
## [6.0.0-2] - 2025-07-11
|
|
8
22
|
|
|
9
23
|
### Fixed
|
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-4",
|
|
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",
|
|
@@ -86,7 +86,6 @@
|
|
|
86
86
|
"posthtml-markdownit": "^3.1.0",
|
|
87
87
|
"posthtml-mso": "^3.1.0",
|
|
88
88
|
"posthtml-parser": "^0.12.1",
|
|
89
|
-
"posthtml-postcss": "^1.0.2",
|
|
90
89
|
"posthtml-postcss-merge-longhand": "^3.1.2",
|
|
91
90
|
"posthtml-render": "^3.0.0",
|
|
92
91
|
"posthtml-safe-class-names": "^4.1.0",
|
package/src/posthtml/index.js
CHANGED
|
@@ -6,51 +6,16 @@ import posthtml from 'posthtml'
|
|
|
6
6
|
import posthtmlFetch from 'posthtml-fetch'
|
|
7
7
|
import envTags from './plugins/envTags.js'
|
|
8
8
|
import components from 'posthtml-component'
|
|
9
|
-
import posthtmlPostcss from 'posthtml-postcss'
|
|
10
9
|
import expandLinkTag from './plugins/expandLinkTag.js'
|
|
11
10
|
import envAttributes from './plugins/envAttributes.js'
|
|
12
11
|
import { getPosthtmlOptions } from './defaultConfig.js'
|
|
13
|
-
import lowerCssSyntax from './plugins/lowerCssSyntax.js'
|
|
14
12
|
import combineMediaQueries from './plugins/combineMediaQueries.js'
|
|
13
|
+
import defaultComponentsConfig from './defaultComponentsConfig.js'
|
|
15
14
|
|
|
16
15
|
// PostCSS
|
|
17
|
-
import
|
|
18
|
-
import postcssCalc from 'postcss-calc'
|
|
19
|
-
import cssVariables from 'postcss-css-variables'
|
|
20
|
-
import postcssSafeParser from 'postcss-safe-parser'
|
|
21
|
-
import removeDuplicateSelectors from './plugins/postcss/removeDuplicateSelectors.js'
|
|
22
|
-
import cleanupTailwindArtifacts from './plugins/postcss/cleanupTailwindArtifacts.js'
|
|
23
|
-
|
|
24
|
-
import defaultComponentsConfig from './defaultComponentsConfig.js'
|
|
16
|
+
import compileCss from './plugins/postcss/compileCss.js'
|
|
25
17
|
|
|
26
18
|
export async function process(html = '', config = {}) {
|
|
27
|
-
/**
|
|
28
|
-
* Configure PostCSS pipeline. Plugins defined and added here
|
|
29
|
-
* will apply to all `<style>` tags in the HTML.
|
|
30
|
-
*/
|
|
31
|
-
const resolveCSSProps = get(config, 'css.resolveProps')
|
|
32
|
-
const resolveCalc = get(config, 'css.resolveCalc') !== false
|
|
33
|
-
? get(config, 'css.resolveCalc', { precision: 2 }) // it's true by default, use default precision 2
|
|
34
|
-
: false
|
|
35
|
-
|
|
36
|
-
const postcssPlugin = posthtmlPostcss(
|
|
37
|
-
[
|
|
38
|
-
tailwindcss(get(config, 'css.tailwind', {})),
|
|
39
|
-
resolveCSSProps !== false && cssVariables(resolveCSSProps),
|
|
40
|
-
resolveCalc !== false && postcssCalc(resolveCalc),
|
|
41
|
-
removeDuplicateSelectors(),
|
|
42
|
-
cleanupTailwindArtifacts(get(config, 'css.cleanup', {})),
|
|
43
|
-
...get(config, 'postcss.plugins', []),
|
|
44
|
-
],
|
|
45
|
-
merge(
|
|
46
|
-
get(config, 'postcss.options', {}),
|
|
47
|
-
{
|
|
48
|
-
from: config.cwd || './',
|
|
49
|
-
parser: postcssSafeParser
|
|
50
|
-
}
|
|
51
|
-
)
|
|
52
|
-
)
|
|
53
|
-
|
|
54
19
|
/**
|
|
55
20
|
* Define PostHTML options by merging user-provided ones
|
|
56
21
|
* on top of a default configuration.
|
|
@@ -106,18 +71,15 @@ export async function process(html = '', config = {}) {
|
|
|
106
71
|
|
|
107
72
|
return posthtml([
|
|
108
73
|
...beforePlugins,
|
|
109
|
-
envTags(config.env),
|
|
110
|
-
envAttributes(config.env),
|
|
111
|
-
expandLinkTag(),
|
|
112
|
-
postcssPlugin,
|
|
113
74
|
fetchPlugin,
|
|
114
75
|
components(componentsConfig),
|
|
76
|
+
fetchPlugin,
|
|
115
77
|
expandLinkTag(),
|
|
116
|
-
postcssPlugin,
|
|
117
78
|
envTags(config.env),
|
|
118
79
|
envAttributes(config.env),
|
|
119
|
-
|
|
120
|
-
get(config, 'css.combineMediaQueries') !== false
|
|
80
|
+
compileCss(config),
|
|
81
|
+
get(config, 'css.combineMediaQueries') !== false
|
|
82
|
+
&& combineMediaQueries(get(config, 'css.combineMediaQueries', { sort: 'mobile-first' })),
|
|
121
83
|
...get(
|
|
122
84
|
config,
|
|
123
85
|
'posthtml.plugins.after',
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import postcss from 'postcss'
|
|
2
|
+
import get from 'lodash-es/get.js'
|
|
3
|
+
import { defu as merge } from 'defu'
|
|
4
|
+
import postcssCalc from 'postcss-calc'
|
|
5
|
+
import { transform } from 'lightningcss'
|
|
6
|
+
import tailwindcss from '@tailwindcss/postcss'
|
|
7
|
+
import cssVariables from 'postcss-css-variables'
|
|
8
|
+
import postcssSafeParser from 'postcss-safe-parser'
|
|
9
|
+
import removeDuplicateSelectors from './removeDuplicateSelectors.js'
|
|
10
|
+
import cleanupTailwindArtifacts from './cleanupTailwindArtifacts.js'
|
|
11
|
+
|
|
12
|
+
const validAttributeNames = new Set([
|
|
13
|
+
'raw',
|
|
14
|
+
'plain',
|
|
15
|
+
'as-is',
|
|
16
|
+
'uncompiled',
|
|
17
|
+
'unprocessed',
|
|
18
|
+
])
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* PostHTML plugin to process Tailwind CSS within style tags.
|
|
22
|
+
*
|
|
23
|
+
* This plugin processes CSS content in `<style>` tags and
|
|
24
|
+
* compiles it with PostCSS. `<style>` tags marked as
|
|
25
|
+
* `no-process` will be skipped.
|
|
26
|
+
*/
|
|
27
|
+
export default function compile(config = {}) {
|
|
28
|
+
return tree => {
|
|
29
|
+
return new Promise((resolve, reject) => {
|
|
30
|
+
const stylePromises = []
|
|
31
|
+
|
|
32
|
+
tree.walk(node => {
|
|
33
|
+
if (node.tag === 'style' && node.content) {
|
|
34
|
+
if (node.attrs && Object.keys(node.attrs).some(attr => validAttributeNames.has(attr))) {
|
|
35
|
+
// Remove the attribute
|
|
36
|
+
for (const attr of Object.keys(node.attrs)) {
|
|
37
|
+
if (validAttributeNames.has(attr)) {
|
|
38
|
+
delete node.attrs[attr]
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return node
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const css = Array.isArray(node.content)
|
|
46
|
+
? node.content.join('')
|
|
47
|
+
: node.content
|
|
48
|
+
|
|
49
|
+
const promise = processCss(css, config)
|
|
50
|
+
.then(processedCss => {
|
|
51
|
+
node.content = [processedCss]
|
|
52
|
+
})
|
|
53
|
+
.catch(error => {
|
|
54
|
+
console.warn('Error processing CSS in style tag:', error.message)
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
stylePromises.push(promise)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return node
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
Promise.all(stylePromises)
|
|
64
|
+
.then(() => resolve(tree))
|
|
65
|
+
.catch(reject)
|
|
66
|
+
})
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async function processCss(css, config) {
|
|
71
|
+
/**
|
|
72
|
+
* PostCSS pipeline. Plugins defined and added here
|
|
73
|
+
* will apply to all `<style>` tags in the HTML,
|
|
74
|
+
* unless marked to be excluded.
|
|
75
|
+
*/
|
|
76
|
+
const resolveCSSProps = get(config, 'css.resolveProps')
|
|
77
|
+
const resolveCalc = get(config, 'css.resolveCalc') !== false
|
|
78
|
+
? get(config, 'css.resolveCalc', { precision: 2 })
|
|
79
|
+
: false
|
|
80
|
+
|
|
81
|
+
const lightningCssOptions = merge(
|
|
82
|
+
get(config, 'css.lightning', {}),
|
|
83
|
+
{
|
|
84
|
+
targets: {
|
|
85
|
+
ie: 1,
|
|
86
|
+
},
|
|
87
|
+
}
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
try {
|
|
91
|
+
const processor = postcss([
|
|
92
|
+
tailwindcss(get(config, 'css.tailwind', {})),
|
|
93
|
+
resolveCSSProps !== false && cssVariables(resolveCSSProps),
|
|
94
|
+
resolveCalc !== false && postcssCalc(resolveCalc),
|
|
95
|
+
removeDuplicateSelectors(),
|
|
96
|
+
cleanupTailwindArtifacts(get(config, 'css.cleanup', {})),
|
|
97
|
+
...get(config, 'postcss.plugins', []),
|
|
98
|
+
].filter(Boolean))
|
|
99
|
+
|
|
100
|
+
const result = await processor.process(css, merge(
|
|
101
|
+
get(config, 'postcss.options', {}),
|
|
102
|
+
{
|
|
103
|
+
from: config.cwd || './',
|
|
104
|
+
parser: postcssSafeParser
|
|
105
|
+
}
|
|
106
|
+
))
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Lightning CSS processing
|
|
110
|
+
*
|
|
111
|
+
* We use this to lower the modern Tailwind CSS 4 syntax
|
|
112
|
+
* to be more email-friendly.
|
|
113
|
+
*/
|
|
114
|
+
|
|
115
|
+
if (result.css?.trim()) {
|
|
116
|
+
try {
|
|
117
|
+
const { code } = transform(
|
|
118
|
+
merge(
|
|
119
|
+
lightningCssOptions,
|
|
120
|
+
{
|
|
121
|
+
code: Buffer.from(result.css)
|
|
122
|
+
}
|
|
123
|
+
)
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
return code.toString()
|
|
127
|
+
} catch (error) {
|
|
128
|
+
console.warn('Failed to lower syntax with Lightning CSS:', error.message)
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return result.css
|
|
133
|
+
} catch (error) {
|
|
134
|
+
console.warn('Error compiling CSS:', error.message)
|
|
135
|
+
return css
|
|
136
|
+
}
|
|
137
|
+
}
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { defu as merge } from 'defu'
|
|
2
|
-
import { transform } from 'lightningcss'
|
|
3
|
-
|
|
4
|
-
const plugin = (options = {}) => tree => {
|
|
5
|
-
options = merge(options, {
|
|
6
|
-
targets: options.targets ? {} : {
|
|
7
|
-
ie: 1,
|
|
8
|
-
},
|
|
9
|
-
})
|
|
10
|
-
|
|
11
|
-
const process = node => {
|
|
12
|
-
// Check if this is a style tag with content
|
|
13
|
-
if (node.tag === 'style' && node.content && Array.isArray(node.content)) {
|
|
14
|
-
// Get the CSS content from the style tag
|
|
15
|
-
const cssContent = node.content.join('')
|
|
16
|
-
|
|
17
|
-
if (cssContent.trim()) {
|
|
18
|
-
try {
|
|
19
|
-
const { code } = transform(
|
|
20
|
-
merge(
|
|
21
|
-
options,
|
|
22
|
-
{
|
|
23
|
-
code: Buffer.from(cssContent)
|
|
24
|
-
}
|
|
25
|
-
)
|
|
26
|
-
)
|
|
27
|
-
|
|
28
|
-
// Replace the content with processed CSS
|
|
29
|
-
node.content = [code.toString()]
|
|
30
|
-
} catch (error) {
|
|
31
|
-
// If processing fails, leave the content unchanged
|
|
32
|
-
console.warn('Failed to process media queries:', error.message)
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
return node
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
return tree.walk(process)
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export default plugin
|