@maizzle/framework 5.0.0-beta.2 → 5.0.0-beta.21
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 +24 -21
- package/src/commands/build.js +138 -70
- package/src/generators/plaintext.js +13 -14
- package/src/generators/render.js +8 -7
- package/src/posthtml/index.js +34 -5
- package/src/posthtml/plugins/envAttributes.js +32 -0
- package/src/posthtml/plugins/envTags.js +33 -0
- package/src/server/index.js +155 -92
- package/src/server/views/404.html +59 -0
- package/src/transformers/addAttributes.js +1 -1
- package/src/transformers/comb.js +1 -1
- package/src/transformers/core.js +12 -0
- package/src/transformers/index.js +32 -40
- package/src/transformers/inline.js +7 -5
- package/src/transformers/minify.js +2 -1
- package/src/transformers/replaceStrings.js +6 -2
- package/src/transformers/template.js +26 -0
- package/src/utils/string.js +79 -0
- package/types/build.d.ts +59 -24
- package/types/config.d.ts +54 -48
- package/types/css/purge.d.ts +1 -1
- package/types/events.d.ts +153 -5
- package/types/posthtml.d.ts +3 -3
- package/types/urlParameters.d.ts +1 -1
- package/types/components.d.ts +0 -195
- package/types/expressions.d.ts +0 -100
package/src/server/index.js
CHANGED
|
@@ -40,6 +40,71 @@ app.use(hmrRoute)
|
|
|
40
40
|
|
|
41
41
|
let viewing = ''
|
|
42
42
|
const spinner = ora()
|
|
43
|
+
let templatePaths = []
|
|
44
|
+
|
|
45
|
+
function getTemplateFolders(config) {
|
|
46
|
+
return Array.isArray(get(config, 'build.content'))
|
|
47
|
+
? config.build.content
|
|
48
|
+
: [config.build.content]
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async function getTemplatePaths(templateFolders) {
|
|
52
|
+
return await fg.glob([...new Set(templateFolders)])
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async function getUpdatedRoutes(app, config) {
|
|
56
|
+
return getTemplatePaths(getTemplateFolders(config))
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async function renderUpdatedFile(file, config) {
|
|
60
|
+
try {
|
|
61
|
+
const startTime = Date.now()
|
|
62
|
+
spinner.start('Building...')
|
|
63
|
+
|
|
64
|
+
// beforeCreate event
|
|
65
|
+
if (typeof config.beforeCreate === 'function') {
|
|
66
|
+
await config.beforeCreate(config)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Read the file
|
|
70
|
+
const fileContent = await fs.readFile(file, 'utf8')
|
|
71
|
+
|
|
72
|
+
// Set a `dev` flag on the config
|
|
73
|
+
config._dev = true
|
|
74
|
+
|
|
75
|
+
// Render the file with PostHTML
|
|
76
|
+
let { html } = await render(fileContent, config)
|
|
77
|
+
|
|
78
|
+
// Update console message
|
|
79
|
+
const shouldReportFileSize = get(config, 'server.reportFileSize', false)
|
|
80
|
+
|
|
81
|
+
spinner.succeed(
|
|
82
|
+
`Done in ${formatTime(Date.now() - startTime)}`
|
|
83
|
+
+ `${pico.gray(` [${path.relative(cwd(), file)}]`)}`
|
|
84
|
+
+ `${shouldReportFileSize ? ' · ' + getColorizedFileSize(html) : ''}`
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Inject HMR script
|
|
89
|
+
*/
|
|
90
|
+
html = injectScript(html, '<script src="/hmr.js"></script>')
|
|
91
|
+
|
|
92
|
+
// Notify connected websocket clients about the change
|
|
93
|
+
wss.clients.forEach(client => {
|
|
94
|
+
if (client.readyState === WebSocket.OPEN) {
|
|
95
|
+
client.send(JSON.stringify({
|
|
96
|
+
type: 'change',
|
|
97
|
+
content: html,
|
|
98
|
+
scrollSync: get(config, 'server.scrollSync', false),
|
|
99
|
+
hmr: get(config, 'server.hmr', true),
|
|
100
|
+
}))
|
|
101
|
+
}
|
|
102
|
+
})
|
|
103
|
+
} catch (error) {
|
|
104
|
+
spinner.fail('Failed to render template.')
|
|
105
|
+
throw error
|
|
106
|
+
}
|
|
107
|
+
}
|
|
43
108
|
|
|
44
109
|
export default async (config = {}) => {
|
|
45
110
|
// Read the Maizzle config file
|
|
@@ -47,7 +112,10 @@ export default async (config = {}) => {
|
|
|
47
112
|
|
|
48
113
|
/**
|
|
49
114
|
* Dev server settings
|
|
50
|
-
|
|
115
|
+
*/
|
|
116
|
+
spinner.spinner = get(config, 'server.spinner', 'circleHalves')
|
|
117
|
+
spinner.start('Starting server...')
|
|
118
|
+
|
|
51
119
|
const shouldScroll = get(config, 'server.scrollSync', false)
|
|
52
120
|
const useHmr = get(config, 'server.hmr', true)
|
|
53
121
|
|
|
@@ -62,16 +130,18 @@ export default async (config = {}) => {
|
|
|
62
130
|
*/
|
|
63
131
|
initWebSockets(wss, { scrollSync: shouldScroll, hmr: useHmr })
|
|
64
132
|
|
|
65
|
-
//
|
|
66
|
-
|
|
67
|
-
? config.build.content
|
|
68
|
-
: [config.build.content]
|
|
133
|
+
// Register routes
|
|
134
|
+
templatePaths = await getUpdatedRoutes(app, config)
|
|
69
135
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
136
|
+
/**
|
|
137
|
+
* Store template paths on the request object
|
|
138
|
+
*
|
|
139
|
+
* We use it in the index view to list all templates.
|
|
140
|
+
* */
|
|
73
141
|
app.request.templatePaths = templatePaths
|
|
74
142
|
|
|
143
|
+
// await updateRoutes(app, config)
|
|
144
|
+
|
|
75
145
|
/**
|
|
76
146
|
* Create route pattern
|
|
77
147
|
* Only allow files with the following extensions
|
|
@@ -83,7 +153,7 @@ export default async (config = {}) => {
|
|
|
83
153
|
)
|
|
84
154
|
].join('|')
|
|
85
155
|
|
|
86
|
-
const routePattern = Array.isArray(
|
|
156
|
+
const routePattern = Array.isArray(getTemplateFolders(config))
|
|
87
157
|
? `*/:file.(${extensions})`
|
|
88
158
|
: `:file.(${extensions})`
|
|
89
159
|
|
|
@@ -125,99 +195,82 @@ export default async (config = {}) => {
|
|
|
125
195
|
})
|
|
126
196
|
})
|
|
127
197
|
|
|
128
|
-
// Error-handling middleware
|
|
129
|
-
app.use(async (error, req, res, next) => { // eslint-disable-line
|
|
130
|
-
console.error(error)
|
|
131
|
-
|
|
132
|
-
const view = await fs.readFile(path.join(__dirname, 'views', 'error.html'), 'utf8')
|
|
133
|
-
const { html } = await render(view, {
|
|
134
|
-
method: req.method,
|
|
135
|
-
url: req.url,
|
|
136
|
-
error
|
|
137
|
-
})
|
|
138
|
-
|
|
139
|
-
res.status(500).send(html)
|
|
140
|
-
})
|
|
141
|
-
|
|
142
198
|
/**
|
|
143
199
|
* Components watcher
|
|
144
200
|
*
|
|
145
201
|
* Watches for changes in the configured Templates and Components paths
|
|
146
202
|
*/
|
|
203
|
+
let isWatcherReady = false
|
|
147
204
|
chokidar
|
|
148
|
-
.watch(
|
|
205
|
+
.watch(
|
|
206
|
+
[
|
|
207
|
+
...templatePaths,
|
|
208
|
+
...get(config, 'components.folders', defaultComponentsConfig.folders)
|
|
209
|
+
],
|
|
210
|
+
{
|
|
211
|
+
ignoreInitial: true,
|
|
212
|
+
awaitWriteFinish: {
|
|
213
|
+
stabilityThreshold: 150,
|
|
214
|
+
pollInterval: 25,
|
|
215
|
+
},
|
|
216
|
+
}
|
|
217
|
+
)
|
|
149
218
|
.on('change', async () => {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
return
|
|
219
|
+
if (viewing) {
|
|
220
|
+
await renderUpdatedFile(viewing, config)
|
|
153
221
|
}
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
// Update console message
|
|
174
|
-
const shouldReportFileSize = get(config, 'server.reportFileSize', false)
|
|
175
|
-
|
|
176
|
-
spinner.succeed(
|
|
177
|
-
`Done in ${formatTime(Date.now() - startTime)}`
|
|
178
|
-
+ `${pico.gray(` [${path.relative(cwd(), viewing)}]`)}`
|
|
179
|
-
+ `${ shouldReportFileSize ? ' · ' + getColorizedFileSize(html) : ''}`
|
|
180
|
-
)
|
|
181
|
-
|
|
182
|
-
/**
|
|
183
|
-
* Inject HMR script
|
|
184
|
-
*/
|
|
185
|
-
html = injectScript(html, '<script src="/hmr.js"></script>')
|
|
186
|
-
|
|
187
|
-
// Notify connected websocket clients about the change
|
|
188
|
-
wss.clients.forEach(client => {
|
|
189
|
-
if (client.readyState === WebSocket.OPEN) {
|
|
190
|
-
client.send(JSON.stringify({
|
|
191
|
-
type: 'change',
|
|
192
|
-
content: html,
|
|
193
|
-
scrollSync: get(config, 'server.scrollSync', false),
|
|
194
|
-
hmr: get(config, 'server.hmr', true),
|
|
195
|
-
}))
|
|
196
|
-
}
|
|
197
|
-
})
|
|
198
|
-
} catch (error) {
|
|
199
|
-
spinner.fail('Failed to render template.')
|
|
200
|
-
throw error
|
|
222
|
+
})
|
|
223
|
+
.on('ready', () => {
|
|
224
|
+
/**
|
|
225
|
+
* `add` fires immediately when the watcher is created,
|
|
226
|
+
* so we use this trick to detect new files added
|
|
227
|
+
* after it has started.
|
|
228
|
+
*/
|
|
229
|
+
isWatcherReady = true
|
|
230
|
+
})
|
|
231
|
+
.on('add', async () => {
|
|
232
|
+
if (isWatcherReady) {
|
|
233
|
+
templatePaths = await getUpdatedRoutes(app, config)
|
|
234
|
+
app.request.templatePaths = templatePaths
|
|
235
|
+
}
|
|
236
|
+
})
|
|
237
|
+
.on('unlink', async () => {
|
|
238
|
+
if (isWatcherReady) {
|
|
239
|
+
templatePaths = await getUpdatedRoutes(app, config)
|
|
240
|
+
app.request.templatePaths = templatePaths
|
|
201
241
|
}
|
|
202
242
|
})
|
|
203
243
|
|
|
204
244
|
/**
|
|
205
245
|
* Global watcher
|
|
206
246
|
*
|
|
207
|
-
* Watch for changes in the config
|
|
247
|
+
* Watch for changes in the config files, Tailwind CSS config, CSS files,
|
|
248
|
+
* configured static assets, and user-defined watch paths.
|
|
208
249
|
*/
|
|
209
250
|
const globalWatchedPaths = new Set([
|
|
210
|
-
'config*.js',
|
|
211
|
-
'maizzle.config*.js',
|
|
212
|
-
'tailwind*.config.js',
|
|
251
|
+
'config*.{js,cjs,ts}',
|
|
252
|
+
'maizzle.config*.{js,cjs,ts}',
|
|
253
|
+
'tailwind*.config.{js,ts}',
|
|
213
254
|
'**/*.css',
|
|
214
|
-
...get(config, '
|
|
255
|
+
...get(config, 'build.static.source', []),
|
|
256
|
+
...get(config, 'server.watch', []),
|
|
215
257
|
])
|
|
216
258
|
|
|
217
259
|
async function globalPathsHandler(file, eventType) {
|
|
260
|
+
// Update express.static to serve new files
|
|
261
|
+
if (eventType === 'add') {
|
|
262
|
+
app.use(express.static(path.dirname(file)))
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// Stop serving deleted files
|
|
266
|
+
if (eventType === 'unlink') {
|
|
267
|
+
app._router.stack = app._router.stack.filter(
|
|
268
|
+
layer => layer.regexp.source !== path.dirname(file).replace(/\\/g, '/')
|
|
269
|
+
)
|
|
270
|
+
}
|
|
271
|
+
|
|
218
272
|
// Not viewing a component in the browser, no need to rebuild
|
|
219
273
|
if (!viewing) {
|
|
220
|
-
spinner.info(`file ${eventType}: ${file}`)
|
|
221
274
|
return
|
|
222
275
|
}
|
|
223
276
|
|
|
@@ -254,7 +307,7 @@ export default async (config = {}) => {
|
|
|
254
307
|
spinner.succeed(
|
|
255
308
|
`Done in ${formatTime(Date.now() - startTime)}`
|
|
256
309
|
+ `${pico.gray(` [${path.relative(cwd(), filePath)}]`)}`
|
|
257
|
-
+ `${
|
|
310
|
+
+ `${shouldReportFileSize ? ' · ' + getColorizedFileSize(html) : ''}`
|
|
258
311
|
)
|
|
259
312
|
|
|
260
313
|
/**
|
|
@@ -274,7 +327,7 @@ export default async (config = {}) => {
|
|
|
274
327
|
}
|
|
275
328
|
})
|
|
276
329
|
} catch (error) {
|
|
277
|
-
spinner.fail(
|
|
330
|
+
spinner.fail(`Failed to render template: ${file}`)
|
|
278
331
|
throw error
|
|
279
332
|
}
|
|
280
333
|
}
|
|
@@ -286,6 +339,10 @@ export default async (config = {}) => {
|
|
|
286
339
|
get(config, 'build.output.path', 'build_production'),
|
|
287
340
|
],
|
|
288
341
|
ignoreInitial: true,
|
|
342
|
+
awaitWriteFinish: {
|
|
343
|
+
stabilityThreshold: 150,
|
|
344
|
+
pollInterval: 25,
|
|
345
|
+
},
|
|
289
346
|
})
|
|
290
347
|
.on('change', async file => await globalPathsHandler(file, 'change'))
|
|
291
348
|
.on('add', async file => await globalPathsHandler(file, 'add'))
|
|
@@ -293,25 +350,33 @@ export default async (config = {}) => {
|
|
|
293
350
|
|
|
294
351
|
/**
|
|
295
352
|
* Serve all folders in the cwd as static files
|
|
296
|
-
*
|
|
297
|
-
* TODO: change to include build.assets or build.static, which may be outside cwd
|
|
298
353
|
*/
|
|
299
354
|
const srcFoldersList = await fg.glob(
|
|
300
355
|
[
|
|
301
356
|
'**/*/',
|
|
302
357
|
...get(config, 'build.static.source', [])
|
|
303
358
|
], {
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
359
|
+
onlyFiles: false,
|
|
360
|
+
ignore: [
|
|
361
|
+
'node_modules',
|
|
362
|
+
get(config, 'build.output.path', 'build_*'),
|
|
363
|
+
]
|
|
364
|
+
})
|
|
310
365
|
|
|
311
366
|
srcFoldersList.forEach(folder => {
|
|
312
367
|
app.use(express.static(path.join(config.cwd, folder)))
|
|
313
368
|
})
|
|
314
369
|
|
|
370
|
+
// Error-handling middleware
|
|
371
|
+
app.use(async (req, res) => {
|
|
372
|
+
const view = await fs.readFile(path.join(__dirname, 'views', '404.html'), 'utf8')
|
|
373
|
+
const { html } = await render(view, {
|
|
374
|
+
url: req.url,
|
|
375
|
+
})
|
|
376
|
+
|
|
377
|
+
res.status(404).send(html)
|
|
378
|
+
})
|
|
379
|
+
|
|
315
380
|
/**
|
|
316
381
|
* Start the server
|
|
317
382
|
*/
|
|
@@ -321,8 +386,6 @@ export default async (config = {}) => {
|
|
|
321
386
|
|
|
322
387
|
function startServer(port) {
|
|
323
388
|
const serverStartTime = Date.now()
|
|
324
|
-
spinner.start('Starting server...')
|
|
325
|
-
|
|
326
389
|
const server = createServer(app)
|
|
327
390
|
|
|
328
391
|
/**
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>404 - Template not found</title>
|
|
7
|
+
<style>
|
|
8
|
+
html, body {
|
|
9
|
+
font-family: Helvetica, Arial, sans-serif;
|
|
10
|
+
margin: 0;
|
|
11
|
+
padding: 0;
|
|
12
|
+
box-sizing: border-box;
|
|
13
|
+
height: 100%;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.container {
|
|
17
|
+
box-sizing: border-box;
|
|
18
|
+
height: 100vh;
|
|
19
|
+
display: flex;
|
|
20
|
+
align-items: center;
|
|
21
|
+
justify-content: center;
|
|
22
|
+
position: relative;
|
|
23
|
+
z-index: 1;
|
|
24
|
+
padding: 24px;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.error-code {
|
|
28
|
+
font-size: 25rem;
|
|
29
|
+
font-weight: 700;
|
|
30
|
+
color: #f1f5f9;
|
|
31
|
+
position: fixed;
|
|
32
|
+
top: -1.5rem;
|
|
33
|
+
left: -3rem;
|
|
34
|
+
user-select: none;
|
|
35
|
+
}
|
|
36
|
+
</style>
|
|
37
|
+
</head>
|
|
38
|
+
<body>
|
|
39
|
+
<span class="error-code">404</span>
|
|
40
|
+
|
|
41
|
+
<div class="container">
|
|
42
|
+
<div style="text-align: center;">
|
|
43
|
+
<h1 style="font-size: 3rem; color: #0F172A; margin: 2.25rem 0">
|
|
44
|
+
Template Not Found
|
|
45
|
+
</h1>
|
|
46
|
+
<p style="margin: 0 0 2.25rem; font-size: 1.25rem; line-height: 1.5; color: #64748B;">
|
|
47
|
+
The Template you are looking for was not found:
|
|
48
|
+
</p>
|
|
49
|
+
<p style="margin: 1rem 0 0; font-size: 1rem; line-height: 1.5; font-weight: 600; color: #334155;">
|
|
50
|
+
{{ page.url }}
|
|
51
|
+
</p>
|
|
52
|
+
</div>
|
|
53
|
+
</div>
|
|
54
|
+
|
|
55
|
+
<div style="position: fixed; bottom: 0; right: 0; pointer-events: none; user-select: none;">
|
|
56
|
+
<svg width="883" height="536" fill="none" xmlns="http://www.w3.org/2000/svg"><mask id="a" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="1100" height="536"><path fill="#D9D9D9" d="M0 .955h1100V536H0z"/></mask><g mask="url(#a)" stroke="#94A3B8" stroke-miterlimit="10"><path d="M1056.93 92.587c0-50.03-43.95-90.587-98.168-90.587-54.22 0-98.174 40.557-98.174 90.587v483.125c0 50.029 43.954 90.586 98.174 90.586 54.218 0 98.168-40.557 98.168-90.586V92.587ZM646.241 92.587C646.241 42.556 602.287 2 548.067 2c-54.219 0-98.173 40.557-98.173 90.587v483.125c0 50.029 43.954 90.586 98.173 90.586 54.22 0 98.174-40.557 98.174-90.586V92.587Z"/><path d="M1036.18 148.383c33.41-39.402 25.88-96.336-16.82-127.164C976.657-9.61 914.955-2.66 881.544 36.742L471.586 520.215c-33.411 39.402-25.879 96.336 16.824 127.164 42.702 30.829 104.404 23.879 137.815-15.523l409.955-483.473ZM625.093 148.396c33.411-39.403 25.878-96.336-16.824-127.164C565.567-9.597 503.865-2.647 470.454 36.755L60.495 520.228c-33.41 39.402-25.878 96.336 16.825 127.164 42.702 30.829 104.404 23.879 137.815-15.523l409.958-483.473Z"/></g></svg>
|
|
57
|
+
</div>
|
|
58
|
+
</body>
|
|
59
|
+
</html>
|
package/src/transformers/comb.js
CHANGED
package/src/transformers/core.js
CHANGED
|
@@ -11,6 +11,18 @@ const posthtmlPlugin = (config = {}) => tree => {
|
|
|
11
11
|
node.content = ['']
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
/**
|
|
15
|
+
* Custom attributes to prevent inlining CSS from <style> tags
|
|
16
|
+
*/
|
|
17
|
+
if (
|
|
18
|
+
node.tag === 'style'
|
|
19
|
+
&& (node.attrs?.['no-inline'] || node.attrs?.embed)
|
|
20
|
+
) {
|
|
21
|
+
node.attrs['no-inline'] = false
|
|
22
|
+
node.attrs.embed = false
|
|
23
|
+
node.attrs['data-embed'] = true
|
|
24
|
+
}
|
|
25
|
+
|
|
14
26
|
return node
|
|
15
27
|
}
|
|
16
28
|
|
|
@@ -2,12 +2,14 @@ import posthtml from 'posthtml'
|
|
|
2
2
|
import get from 'lodash-es/get.js'
|
|
3
3
|
import { defu as merge } from 'defu'
|
|
4
4
|
|
|
5
|
+
import core from './core.js'
|
|
5
6
|
import comb from './comb.js'
|
|
6
7
|
import sixHex from './sixHex.js'
|
|
7
8
|
import minify from './minify.js'
|
|
8
9
|
import baseUrl from './baseUrl.js'
|
|
9
10
|
import inlineCSS from './inline.js'
|
|
10
11
|
import prettify from './prettify.js'
|
|
12
|
+
import templateTag from './template.js'
|
|
11
13
|
import filters from './filters/index.js'
|
|
12
14
|
import markdown from 'posthtml-markdownit'
|
|
13
15
|
import posthtmlMso from './posthtmlMso.js'
|
|
@@ -20,19 +22,17 @@ import replaceStrings from './replaceStrings.js'
|
|
|
20
22
|
import attributeToStyle from './attributeToStyle.js'
|
|
21
23
|
import removeAttributes from './removeAttributes.js'
|
|
22
24
|
|
|
23
|
-
import coreTransformers from './core.js'
|
|
24
|
-
|
|
25
25
|
import defaultPosthtmlConfig from '../posthtml/defaultConfig.js'
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
28
|
* Use Maizzle Transformers on an HTML string.
|
|
29
29
|
*
|
|
30
|
-
* Only Transformers that are enabled in the
|
|
30
|
+
* Only Transformers that are enabled in the passed
|
|
31
|
+
* `config` parameter will be used.
|
|
31
32
|
*
|
|
32
33
|
* @param {string} html The HTML content
|
|
33
34
|
* @param {object} config The Maizzle config object
|
|
34
|
-
* @returns {Promise<{
|
|
35
|
-
* A Promise resolving to an object containing the original HTML, modified HTML, and the config
|
|
35
|
+
* @returns {Promise<{ html: string }>} A Promise resolving to an object containing the modified HTML
|
|
36
36
|
*/
|
|
37
37
|
export async function run(html = '', config = {}) {
|
|
38
38
|
const posthtmlPlugins = []
|
|
@@ -45,27 +45,26 @@ export async function run(html = '', config = {}) {
|
|
|
45
45
|
/**
|
|
46
46
|
* 1. Core transformers
|
|
47
47
|
*
|
|
48
|
-
* Transformers that are always enabled
|
|
48
|
+
* Transformers that are always enabled.
|
|
49
49
|
*
|
|
50
50
|
*/
|
|
51
|
-
posthtmlPlugins.push(
|
|
51
|
+
posthtmlPlugins.push(core(config))
|
|
52
52
|
|
|
53
53
|
/**
|
|
54
54
|
* 2. Safe class names
|
|
55
55
|
*
|
|
56
56
|
* Rewrite Tailwind CSS class names to email-safe alternatives,
|
|
57
|
-
* unless explicitly disabled
|
|
57
|
+
* unless explicitly disabled.
|
|
58
58
|
*/
|
|
59
|
-
if (get(config, 'css.
|
|
59
|
+
if (get(config, 'css.safe') !== false) {
|
|
60
60
|
posthtmlPlugins.push(
|
|
61
|
-
safeClassNames(get(config, 'css.
|
|
61
|
+
safeClassNames(get(config, 'css.safe', {}))
|
|
62
62
|
)
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
/**
|
|
66
66
|
* 3. Filters
|
|
67
67
|
*
|
|
68
|
-
* Apply filters to HTML.
|
|
69
68
|
* Filters are always applied, unless explicitly disabled.
|
|
70
69
|
*/
|
|
71
70
|
if (get(config, 'filters') !== false) {
|
|
@@ -77,7 +76,7 @@ export async function run(html = '', config = {}) {
|
|
|
77
76
|
/**
|
|
78
77
|
* 4. Markdown
|
|
79
78
|
*
|
|
80
|
-
* Convert Markdown to HTML with
|
|
79
|
+
* Convert Markdown to HTML with markdown-it, unless explicitly disabled.
|
|
81
80
|
*/
|
|
82
81
|
if (get(config, 'markdown') !== false) {
|
|
83
82
|
posthtmlPlugins.push(
|
|
@@ -87,7 +86,9 @@ export async function run(html = '', config = {}) {
|
|
|
87
86
|
|
|
88
87
|
/**
|
|
89
88
|
* 5. Prevent widow words
|
|
90
|
-
*
|
|
89
|
+
*
|
|
90
|
+
* Enabled by default, will prevent widow words in elements
|
|
91
|
+
* wrapped with a `prevent-widows` attribute.
|
|
91
92
|
*/
|
|
92
93
|
if (get(config, 'widowWords') !== false) {
|
|
93
94
|
posthtmlPlugins.push(
|
|
@@ -109,7 +110,7 @@ export async function run(html = '', config = {}) {
|
|
|
109
110
|
/**
|
|
110
111
|
* 7. Inline CSS
|
|
111
112
|
*
|
|
112
|
-
* Inline CSS into HTML
|
|
113
|
+
* Inline CSS into HTML.
|
|
113
114
|
*/
|
|
114
115
|
if (get(config, 'css.inline')) {
|
|
115
116
|
posthtmlPlugins.push(inlineCSS(
|
|
@@ -149,7 +150,7 @@ export async function run(html = '', config = {}) {
|
|
|
149
150
|
/**
|
|
150
151
|
* 10. Shorthand CSS
|
|
151
152
|
*
|
|
152
|
-
* Convert longhand CSS properties to shorthand in `style` attributes
|
|
153
|
+
* Convert longhand CSS properties to shorthand in `style` attributes.
|
|
153
154
|
*/
|
|
154
155
|
if (get(config, 'css.shorthand')) {
|
|
155
156
|
posthtmlPlugins.push(
|
|
@@ -160,7 +161,7 @@ export async function run(html = '', config = {}) {
|
|
|
160
161
|
/**
|
|
161
162
|
* 11. Add attributes
|
|
162
163
|
*
|
|
163
|
-
* Add attributes to HTML tags
|
|
164
|
+
* Add attributes to HTML tags.
|
|
164
165
|
*/
|
|
165
166
|
if (get(config, 'attributes.add') !== false) {
|
|
166
167
|
posthtmlPlugins.push(
|
|
@@ -171,33 +172,18 @@ export async function run(html = '', config = {}) {
|
|
|
171
172
|
/**
|
|
172
173
|
* 12. Base URL
|
|
173
174
|
*
|
|
174
|
-
* Add a base URL to relative paths
|
|
175
|
+
* Add a base URL to relative paths.
|
|
175
176
|
*/
|
|
176
177
|
if (get(config, 'baseURL', get(config, 'baseUrl'))) {
|
|
177
178
|
posthtmlPlugins.push(
|
|
178
179
|
baseUrl(get(config, 'baseURL', get(config, 'baseUrl', {})))
|
|
179
180
|
)
|
|
180
|
-
} else {
|
|
181
|
-
/**
|
|
182
|
-
* Set baseURL to `build.static.destination` if it's not already set
|
|
183
|
-
*/
|
|
184
|
-
const destination = get(config, 'build.static.destination', '')
|
|
185
|
-
if (destination && !config._dev) {
|
|
186
|
-
posthtmlPlugins.push(
|
|
187
|
-
baseUrl({
|
|
188
|
-
url: destination,
|
|
189
|
-
allTags: true,
|
|
190
|
-
styleTag: true,
|
|
191
|
-
inlineCss: true,
|
|
192
|
-
})
|
|
193
|
-
)
|
|
194
|
-
}
|
|
195
181
|
}
|
|
196
182
|
|
|
197
183
|
/**
|
|
198
184
|
* 13. URL parameters
|
|
199
185
|
*
|
|
200
|
-
* Add parameters to URLs
|
|
186
|
+
* Add parameters to URLs.
|
|
201
187
|
*/
|
|
202
188
|
if (get(config, 'urlParameters')) {
|
|
203
189
|
posthtmlPlugins.push(
|
|
@@ -208,8 +194,7 @@ export async function run(html = '', config = {}) {
|
|
|
208
194
|
/**
|
|
209
195
|
* 14. Six-digit HEX
|
|
210
196
|
*
|
|
211
|
-
*
|
|
212
|
-
* Always runs, unless explicitly disabled
|
|
197
|
+
* Enabled by default, converts three-digit HEX colors to six-digit.
|
|
213
198
|
*/
|
|
214
199
|
if (get(config, 'css.sixHex') !== false) {
|
|
215
200
|
posthtmlPlugins.push(
|
|
@@ -220,7 +205,7 @@ export async function run(html = '', config = {}) {
|
|
|
220
205
|
/**
|
|
221
206
|
* 15. PostHTML MSO
|
|
222
207
|
*
|
|
223
|
-
*
|
|
208
|
+
* Enabled by default, simplifies writing MSO conditionals for Outlook.
|
|
224
209
|
*/
|
|
225
210
|
if (get(config, 'outlook') !== false) {
|
|
226
211
|
posthtmlPlugins.push(
|
|
@@ -231,7 +216,7 @@ export async function run(html = '', config = {}) {
|
|
|
231
216
|
/**
|
|
232
217
|
* 16. Prettify
|
|
233
218
|
*
|
|
234
|
-
* Pretty-print HTML using js-beautify
|
|
219
|
+
* Pretty-print HTML using js-beautify.
|
|
235
220
|
*/
|
|
236
221
|
if (get(config, 'prettify')) {
|
|
237
222
|
posthtmlPlugins.push(
|
|
@@ -242,7 +227,7 @@ export async function run(html = '', config = {}) {
|
|
|
242
227
|
/**
|
|
243
228
|
* 17. Minify
|
|
244
229
|
*
|
|
245
|
-
* Minify HTML using html-crush
|
|
230
|
+
* Minify HTML using html-crush.
|
|
246
231
|
*/
|
|
247
232
|
if (get(config, 'minify')) {
|
|
248
233
|
posthtmlPlugins.push(
|
|
@@ -251,9 +236,16 @@ export async function run(html = '', config = {}) {
|
|
|
251
236
|
}
|
|
252
237
|
|
|
253
238
|
/**
|
|
254
|
-
* 18.
|
|
239
|
+
* 18. <template> tags
|
|
240
|
+
*
|
|
241
|
+
* Replace <template> tags with their content.
|
|
242
|
+
*/
|
|
243
|
+
posthtmlPlugins.push(templateTag())
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* 19. Replace strings
|
|
255
247
|
*
|
|
256
|
-
* Replace strings through regular expressions
|
|
248
|
+
* Replace strings through regular expressions.
|
|
257
249
|
*/
|
|
258
250
|
if (get(config, 'replaceStrings')) {
|
|
259
251
|
posthtmlPlugins.push(
|