@maizzle/framework 5.0.0-beta.24 → 5.0.0-beta.26
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 +11 -11
- package/src/server/index.js +4 -4
- package/src/server/routes/index.js +1 -1
- package/src/server/views/index.html +25 -0
- package/src/transformers/index.js +25 -25
- package/src/transformers/inline.js +30 -3
- package/src/transformers/markdown.js +14 -5
- package/src/utils/string.js +10 -0
- package/types/index.d.ts +4 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@maizzle/framework",
|
|
3
|
-
"version": "5.0.0-beta.
|
|
3
|
+
"version": "5.0.0-beta.26",
|
|
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",
|
|
@@ -56,10 +56,10 @@
|
|
|
56
56
|
"color-shorthand-hex-to-six-digit": "^5.0.16",
|
|
57
57
|
"defu": "^6.1.4",
|
|
58
58
|
"email-comb": "^7.0.21",
|
|
59
|
-
"express": "^4.
|
|
59
|
+
"express": "^4.21.0",
|
|
60
60
|
"fast-glob": "^3.3.2",
|
|
61
61
|
"gray-matter": "^4.0.3",
|
|
62
|
-
"html-crush": "^6.0.
|
|
62
|
+
"html-crush": "^6.0.19",
|
|
63
63
|
"is-url-superb": "^6.1.0",
|
|
64
64
|
"istextorbinary": "^9.5.0",
|
|
65
65
|
"juice": "^11.0.0",
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
"morphdom": "^2.7.4",
|
|
68
68
|
"ora": "^8.1.0",
|
|
69
69
|
"pathe": "^1.1.2",
|
|
70
|
-
"postcss": "^8.4.
|
|
70
|
+
"postcss": "^8.4.47",
|
|
71
71
|
"postcss-custom-properties": "^14.0.1",
|
|
72
72
|
"postcss-import": "^16.1.0",
|
|
73
73
|
"postcss-safe-parser": "^7.0.0",
|
|
@@ -81,7 +81,7 @@
|
|
|
81
81
|
"posthtml-fetch": "^4.0.0",
|
|
82
82
|
"posthtml-markdownit": "^3.1.0",
|
|
83
83
|
"posthtml-mso": "^3.1.0",
|
|
84
|
-
"posthtml-parser": "^0.12.
|
|
84
|
+
"posthtml-parser": "^0.12.1",
|
|
85
85
|
"posthtml-postcss": "^1.0.2",
|
|
86
86
|
"posthtml-postcss-merge-longhand": "^3.1.2",
|
|
87
87
|
"posthtml-render": "^3.0.0",
|
|
@@ -90,16 +90,16 @@
|
|
|
90
90
|
"pretty": "^2.0.0",
|
|
91
91
|
"string-remove-widows": "^4.0.22",
|
|
92
92
|
"string-strip-html": "^13.4.8",
|
|
93
|
-
"tailwindcss": "^3.4.
|
|
94
|
-
"ws": "^8.
|
|
93
|
+
"tailwindcss": "^3.4.13",
|
|
94
|
+
"ws": "^8.18.0"
|
|
95
95
|
},
|
|
96
96
|
"devDependencies": {
|
|
97
|
-
"@biomejs/biome": "1.
|
|
97
|
+
"@biomejs/biome": "1.9.2",
|
|
98
98
|
"@types/js-beautify": "^1.14.3",
|
|
99
|
-
"@types/markdown-it": "^14.1.
|
|
100
|
-
"@vitest/coverage-v8": "^2.
|
|
99
|
+
"@types/markdown-it": "^14.1.2",
|
|
100
|
+
"@vitest/coverage-v8": "^2.1.1",
|
|
101
101
|
"supertest": "^7.0.0",
|
|
102
|
-
"vitest": "^2.
|
|
102
|
+
"vitest": "^2.1.1"
|
|
103
103
|
},
|
|
104
104
|
"engines": {
|
|
105
105
|
"node": ">=18.20"
|
package/src/server/index.js
CHANGED
|
@@ -63,7 +63,7 @@ async function renderUpdatedFile(file, config) {
|
|
|
63
63
|
|
|
64
64
|
// beforeCreate event
|
|
65
65
|
if (typeof config.beforeCreate === 'function') {
|
|
66
|
-
await config.beforeCreate(config)
|
|
66
|
+
await config.beforeCreate({ config })
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
// Read the file
|
|
@@ -164,11 +164,11 @@ export default async (config = {}) => {
|
|
|
164
164
|
app.get(routePattern, async (req, res, next) => {
|
|
165
165
|
// Run beforeCreate event
|
|
166
166
|
if (typeof config.beforeCreate === 'function') {
|
|
167
|
-
config.beforeCreate(config)
|
|
167
|
+
await config.beforeCreate({ config })
|
|
168
168
|
}
|
|
169
169
|
|
|
170
170
|
try {
|
|
171
|
-
const filePath = templatePaths.find(t => t.endsWith(req.url.slice(1)))
|
|
171
|
+
const filePath = templatePaths.find(t => t.endsWith(decodeURI(req.url.slice(1))))
|
|
172
172
|
|
|
173
173
|
// Set the file being viewed
|
|
174
174
|
viewing = filePath
|
|
@@ -288,7 +288,7 @@ export default async (config = {}) => {
|
|
|
288
288
|
|
|
289
289
|
// Run beforeCreate event
|
|
290
290
|
if (typeof config.beforeCreate === 'function') {
|
|
291
|
-
await config.beforeCreate(config)
|
|
291
|
+
await config.beforeCreate({ config })
|
|
292
292
|
}
|
|
293
293
|
|
|
294
294
|
// Read the file
|
|
@@ -79,6 +79,11 @@
|
|
|
79
79
|
border-left: 1px solid #64748B;
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
+
li.folder.nested > strong {
|
|
83
|
+
cursor: pointer;
|
|
84
|
+
display: block;
|
|
85
|
+
}
|
|
86
|
+
|
|
82
87
|
li.folder.root {
|
|
83
88
|
padding-top: 3rem;
|
|
84
89
|
border: none;
|
|
@@ -92,6 +97,15 @@
|
|
|
92
97
|
line-height: 2.25rem;
|
|
93
98
|
}
|
|
94
99
|
|
|
100
|
+
li.file.nested.collapsed {
|
|
101
|
+
display: none;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
li.file.nested.collapsed + .folder.nested {
|
|
105
|
+
padding-top: 0;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
|
|
95
109
|
li.file.nested a {
|
|
96
110
|
padding-bottom: 0.75rem;
|
|
97
111
|
margin-left: -1.5rem;
|
|
@@ -143,5 +157,16 @@
|
|
|
143
157
|
</ul>
|
|
144
158
|
|
|
145
159
|
<svg fill="none" stroke="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 993 483" class="insignia"><mask id="a" style="mask-type:alpha;" maskUnits="userSpaceOnUse" x="0" y="0" width="993" height="483"><path fill="#D9D9D9" d="M0 0h993v483H0z"></path></mask><g mask="url(#a)" stroke="#e2e8f0" stroke-miterlimit="10"><path d="M954.124 81.816c0-45.163-39.678-81.774-88.624-81.774-48.945 0-88.624 36.611-88.624 81.774v436.13c0 45.163 39.679 81.775 88.624 81.775 48.946 0 88.624-36.612 88.624-81.775V81.816ZM583.379 81.816c0-45.163-39.678-81.774-88.624-81.774-48.945 0-88.624 36.611-88.624 81.774v436.13c0 45.163 39.679 81.775 88.624 81.775 48.946 0 88.624-36.612 88.624-81.775V81.816Z"></path><path d="M935.39 132.185c30.161-35.57 23.362-86.965-15.187-114.795S825.954-4.165 795.794 31.404L425.713 467.848c-30.161 35.57-23.361 86.965 15.187 114.795 38.549 27.829 94.249 21.555 124.41-14.014l370.08-436.444ZM564.288 132.196c30.161-35.569 23.362-86.964-15.187-114.794S454.852-4.154 424.692 31.416L54.611 467.86c-30.16 35.569-23.361 86.965 15.187 114.794 38.549 27.83 94.249 21.556 124.41-14.013l370.08-436.445Z"></path></g></svg>
|
|
160
|
+
<script>
|
|
161
|
+
document.querySelectorAll('.folder.nested').forEach(folder => {
|
|
162
|
+
folder.addEventListener('click', function() {
|
|
163
|
+
let nextElement = this.nextElementSibling;
|
|
164
|
+
while (nextElement && nextElement.classList.contains('file') && nextElement.classList.contains('nested')) {
|
|
165
|
+
nextElement.classList.toggle('collapsed');
|
|
166
|
+
nextElement = nextElement.nextElementSibling;
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
</script>
|
|
146
171
|
</body>
|
|
147
172
|
</html>
|
|
@@ -124,16 +124,7 @@ export async function run(html = '', config = {}) {
|
|
|
124
124
|
}
|
|
125
125
|
|
|
126
126
|
/**
|
|
127
|
-
* 8.
|
|
128
|
-
*
|
|
129
|
-
* Remove unused CSS, uglify classes etc.
|
|
130
|
-
*/
|
|
131
|
-
if (get(config, 'css.purge')) {
|
|
132
|
-
posthtmlPlugins.push(comb(config.css.purge))
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* 9. Remove attributes
|
|
127
|
+
* 8. Remove attributes
|
|
137
128
|
*
|
|
138
129
|
* Remove attributes from HTML tags
|
|
139
130
|
* If `undefined`, removes empty `style` and `class` attributes
|
|
@@ -148,7 +139,7 @@ export async function run(html = '', config = {}) {
|
|
|
148
139
|
}
|
|
149
140
|
|
|
150
141
|
/**
|
|
151
|
-
*
|
|
142
|
+
* 9. Shorthand CSS
|
|
152
143
|
*
|
|
153
144
|
* Convert longhand CSS properties to shorthand in `style` attributes.
|
|
154
145
|
*/
|
|
@@ -159,7 +150,7 @@ export async function run(html = '', config = {}) {
|
|
|
159
150
|
}
|
|
160
151
|
|
|
161
152
|
/**
|
|
162
|
-
*
|
|
153
|
+
* 10. Add attributes
|
|
163
154
|
*
|
|
164
155
|
* Add attributes to HTML tags.
|
|
165
156
|
*/
|
|
@@ -170,7 +161,7 @@ export async function run(html = '', config = {}) {
|
|
|
170
161
|
}
|
|
171
162
|
|
|
172
163
|
/**
|
|
173
|
-
*
|
|
164
|
+
* 11. Base URL
|
|
174
165
|
*
|
|
175
166
|
* Add a base URL to relative paths.
|
|
176
167
|
*/
|
|
@@ -181,7 +172,7 @@ export async function run(html = '', config = {}) {
|
|
|
181
172
|
}
|
|
182
173
|
|
|
183
174
|
/**
|
|
184
|
-
*
|
|
175
|
+
* 12. URL parameters
|
|
185
176
|
*
|
|
186
177
|
* Add parameters to URLs.
|
|
187
178
|
*/
|
|
@@ -192,7 +183,7 @@ export async function run(html = '', config = {}) {
|
|
|
192
183
|
}
|
|
193
184
|
|
|
194
185
|
/**
|
|
195
|
-
*
|
|
186
|
+
* 13. Six-digit HEX
|
|
196
187
|
*
|
|
197
188
|
* Enabled by default, converts three-digit HEX colors to six-digit.
|
|
198
189
|
*/
|
|
@@ -203,7 +194,7 @@ export async function run(html = '', config = {}) {
|
|
|
203
194
|
}
|
|
204
195
|
|
|
205
196
|
/**
|
|
206
|
-
*
|
|
197
|
+
* 14. PostHTML MSO
|
|
207
198
|
*
|
|
208
199
|
* Enabled by default, simplifies writing MSO conditionals for Outlook.
|
|
209
200
|
*/
|
|
@@ -214,7 +205,23 @@ export async function run(html = '', config = {}) {
|
|
|
214
205
|
}
|
|
215
206
|
|
|
216
207
|
/**
|
|
217
|
-
*
|
|
208
|
+
* 15. Purge CSS
|
|
209
|
+
*
|
|
210
|
+
* Remove unused CSS, uglify classes etc.
|
|
211
|
+
*/
|
|
212
|
+
if (get(config, 'css.purge')) {
|
|
213
|
+
posthtmlPlugins.push(comb(config.css.purge))
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* 16. <template> tags
|
|
218
|
+
*
|
|
219
|
+
* Replace <template> tags with their content.
|
|
220
|
+
*/
|
|
221
|
+
posthtmlPlugins.push(templateTag())
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* 17. Prettify
|
|
218
225
|
*
|
|
219
226
|
* Pretty-print HTML using js-beautify.
|
|
220
227
|
*/
|
|
@@ -225,7 +232,7 @@ export async function run(html = '', config = {}) {
|
|
|
225
232
|
}
|
|
226
233
|
|
|
227
234
|
/**
|
|
228
|
-
*
|
|
235
|
+
* 18. Minify
|
|
229
236
|
*
|
|
230
237
|
* Minify HTML using html-crush.
|
|
231
238
|
*/
|
|
@@ -235,13 +242,6 @@ export async function run(html = '', config = {}) {
|
|
|
235
242
|
)
|
|
236
243
|
}
|
|
237
244
|
|
|
238
|
-
/**
|
|
239
|
-
* 18. <template> tags
|
|
240
|
-
*
|
|
241
|
-
* Replace <template> tags with their content.
|
|
242
|
-
*/
|
|
243
|
-
posthtmlPlugins.push(templateTag())
|
|
244
|
-
|
|
245
245
|
/**
|
|
246
246
|
* 19. Replace strings
|
|
247
247
|
*
|
|
@@ -55,9 +55,12 @@ export async function inline(html = '', options = {}) {
|
|
|
55
55
|
})
|
|
56
56
|
|
|
57
57
|
// Add a `data-embed` attribute to style tags that have the embed attribute
|
|
58
|
-
$('style[embed]').each((i, el) => {
|
|
58
|
+
$('style[embed]:not([data-embed])').each((i, el) => {
|
|
59
59
|
$(el).attr('data-embed', '')
|
|
60
60
|
})
|
|
61
|
+
$('style[data-embed]:not([embed])').each((i, el) => {
|
|
62
|
+
$(el).attr('embed', '')
|
|
63
|
+
})
|
|
61
64
|
|
|
62
65
|
/**
|
|
63
66
|
* Inline the CSS
|
|
@@ -103,7 +106,31 @@ export async function inline(html = '', options = {}) {
|
|
|
103
106
|
}
|
|
104
107
|
)
|
|
105
108
|
|
|
106
|
-
const preservedClasses = new Set(
|
|
109
|
+
const preservedClasses = new Set([
|
|
110
|
+
'.body', // Gmail
|
|
111
|
+
'.gmail', // Gmail
|
|
112
|
+
'.apple', // Apple Mail
|
|
113
|
+
'.ios', // Mail on iOS
|
|
114
|
+
'.ox-', // Open-Xchange
|
|
115
|
+
'.outlook', // Outlook.com
|
|
116
|
+
'[data-ogs', // Outlook.com
|
|
117
|
+
'.bloop_container', // Airmail
|
|
118
|
+
'.Singleton', // Apple Mail 10
|
|
119
|
+
'.unused', // Notes 8
|
|
120
|
+
'.moz-text-html', // Thunderbird
|
|
121
|
+
'.mail-detail-content', // Comcast, Libero webmail
|
|
122
|
+
'edo', // Edison (all)
|
|
123
|
+
'#msgBody', // Freenet uses #msgBody
|
|
124
|
+
'.lang' // Fenced code blocks
|
|
125
|
+
])
|
|
126
|
+
|
|
127
|
+
// Precompile a single regex to match any substring from the preservedClasses set
|
|
128
|
+
const combinedPattern = Array.from(preservedClasses)
|
|
129
|
+
.map(pattern => pattern.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&')) // Escape special regex chars
|
|
130
|
+
.join('|') // Combine all patterns into a single regex pattern with 'OR' (|)
|
|
131
|
+
|
|
132
|
+
const combinedRegex = new RegExp(combinedPattern)
|
|
133
|
+
|
|
107
134
|
const selectors = new Set()
|
|
108
135
|
|
|
109
136
|
// Preserve selectors in at rules
|
|
@@ -163,7 +190,7 @@ export async function inline(html = '', options = {}) {
|
|
|
163
190
|
|
|
164
191
|
if (options.removeInlinedSelectors) {
|
|
165
192
|
// Remove the rule in the <style> tag as long as it's not a preserved class
|
|
166
|
-
if (!preservedClasses.has(selector)) {
|
|
193
|
+
if (!preservedClasses.has(selector) && !combinedRegex.test(selector)) {
|
|
167
194
|
rule.remove()
|
|
168
195
|
}
|
|
169
196
|
|
|
@@ -3,17 +3,26 @@ import { defu as merge } from 'defu'
|
|
|
3
3
|
import md from 'posthtml-markdownit'
|
|
4
4
|
import posthtmlConfig from '../posthtml/defaultConfig.js'
|
|
5
5
|
|
|
6
|
-
export async function markdown(
|
|
6
|
+
export async function markdown(input = '', options = {}, posthtmlOptions = {}) {
|
|
7
7
|
/**
|
|
8
|
-
*
|
|
9
|
-
|
|
8
|
+
* If no input is provided, return an empty string.
|
|
9
|
+
*/
|
|
10
|
+
if (!input) {
|
|
11
|
+
return ''
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Automatically wrap in <md> tag, unless manual mode is enabled.
|
|
16
|
+
*
|
|
17
|
+
* With manual mode, user must wrap the input in a <md> tag.
|
|
18
|
+
*
|
|
10
19
|
* https://github.com/posthtml/posthtml-markdownit#usage
|
|
11
20
|
*/
|
|
12
|
-
|
|
21
|
+
input = options.manual ? input : `<md>${input}</md>`
|
|
13
22
|
|
|
14
23
|
return posthtml([
|
|
15
24
|
md(options)
|
|
16
25
|
])
|
|
17
|
-
.process(
|
|
26
|
+
.process(input, merge(posthtmlOptions, posthtmlConfig))
|
|
18
27
|
.then(result => result.html)
|
|
19
28
|
}
|
package/src/utils/string.js
CHANGED
|
@@ -194,3 +194,13 @@ export function parseCSSRule(rule) {
|
|
|
194
194
|
|
|
195
195
|
return { property, value }
|
|
196
196
|
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Normalize a string by removing extra whitespace.
|
|
200
|
+
*
|
|
201
|
+
* @param {String} str The string to clean
|
|
202
|
+
* @returns {String} The cleaned string
|
|
203
|
+
*/
|
|
204
|
+
export function cleanString(str) {
|
|
205
|
+
return str.replace(/\s+/g, ' ').trim()
|
|
206
|
+
}
|
package/types/index.d.ts
CHANGED
|
@@ -37,10 +37,11 @@ declare namespace MaizzleFramework {
|
|
|
37
37
|
*
|
|
38
38
|
* @param {string} input The Markdown string to compile.
|
|
39
39
|
* @param {MarkdownConfig} [options] A configuration object for the Markdown compiler.
|
|
40
|
-
* @
|
|
41
|
-
* @
|
|
40
|
+
* @param {PostHTMLConfig} [posthtmlOptions] A configuration object for PostHTML.
|
|
41
|
+
* @returns {Promise<string>} The compiled HTML string.
|
|
42
|
+
* @see https://maizzle.com/docs/markdown#api
|
|
42
43
|
*/
|
|
43
|
-
function markdown(input: string, options?: MarkdownConfig): string
|
|
44
|
+
function markdown(input: string, options?: MarkdownConfig, posthtmlOptions?: PostHTMLConfig): Promise<string>;
|
|
44
45
|
|
|
45
46
|
/**
|
|
46
47
|
* Prevent widow words inside a tag by adding a ` ` between its last two words.
|