@maizzle/framework 4.8.7 → 5.0.0-beta.0
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/bin/maizzle +3 -1
- package/package.json +65 -58
- package/src/commands/build.js +244 -19
- package/src/commands/serve.js +2 -197
- package/src/generators/plaintext.js +192 -91
- package/src/generators/render.js +128 -0
- package/src/index.js +46 -14
- package/src/{generators/posthtml → posthtml}/defaultComponentsConfig.js +6 -4
- package/src/{generators/posthtml → posthtml}/defaultConfig.js +1 -1
- package/src/posthtml/index.js +74 -0
- package/src/posthtml/plugins/expandLinkTag.js +36 -0
- package/src/server/client.js +181 -0
- package/src/server/index.js +383 -0
- package/src/server/routes/hmr.js +24 -0
- package/src/server/routes/index.js +38 -0
- package/src/server/views/error.html +83 -0
- package/src/server/views/index.html +24 -0
- package/src/server/websockets.js +27 -0
- package/src/transformers/addAttributes.js +30 -0
- package/src/transformers/attributeToStyle.js +30 -36
- package/src/transformers/baseUrl.js +52 -23
- package/src/transformers/comb.js +51 -0
- package/src/transformers/core.js +20 -0
- package/src/transformers/filters/defaultFilters.js +90 -70
- package/src/transformers/filters/index.js +14 -78
- package/src/transformers/index.js +268 -63
- package/src/transformers/inline.js +240 -0
- package/src/transformers/markdown.js +13 -14
- package/src/transformers/minify.js +21 -16
- package/src/transformers/posthtmlMso.js +13 -8
- package/src/transformers/prettify.js +16 -15
- package/src/transformers/preventWidows.js +32 -26
- package/src/transformers/removeAttributes.js +17 -17
- package/src/transformers/replaceStrings.js +30 -9
- package/src/transformers/safeClassNames.js +24 -24
- package/src/transformers/shorthandCss.js +22 -0
- package/src/transformers/sixHex.js +15 -15
- package/src/transformers/urlParameters.js +18 -16
- package/src/transformers/useAttributeSizes.js +65 -0
- package/src/utils/getConfigByFilePath.js +124 -0
- package/src/utils/node.js +68 -0
- package/src/utils/string.js +117 -0
- package/types/build.d.ts +117 -57
- package/types/components.d.ts +130 -112
- package/types/config.d.ts +454 -242
- package/types/css/inline.d.ts +234 -0
- package/types/css/purge.d.ts +125 -0
- package/types/events.d.ts +5 -105
- package/types/index.d.ts +148 -116
- package/types/markdown.d.ts +20 -18
- package/types/minify.d.ts +122 -120
- package/types/plaintext.d.ts +46 -52
- package/types/posthtml.d.ts +103 -136
- package/types/render.d.ts +0 -117
- package/types/urlParameters.d.ts +21 -20
- package/types/widowWords.d.ts +9 -7
- package/src/functions/plaintext.js +0 -5
- package/src/functions/render.js +0 -5
- package/src/generators/config.js +0 -52
- package/src/generators/output/index.js +0 -4
- package/src/generators/output/to-disk.js +0 -254
- package/src/generators/output/to-string.js +0 -73
- package/src/generators/postcss.js +0 -23
- package/src/generators/posthtml/index.js +0 -75
- package/src/generators/tailwindcss.js +0 -157
- package/src/transformers/extraAttributes.js +0 -33
- package/src/transformers/inlineCss.js +0 -42
- package/src/transformers/removeInlineBackgroundColor.js +0 -56
- package/src/transformers/removeInlineSizes.js +0 -43
- package/src/transformers/removeInlinedSelectors.js +0 -100
- package/src/transformers/removeUnusedCss.js +0 -48
- package/src/transformers/shorthandInlineCSS.js +0 -26
- package/src/utils/helpers.js +0 -13
- package/types/baseUrl.d.ts +0 -79
- package/types/fetch.d.ts +0 -143
- package/types/inlineCss.d.ts +0 -207
- package/types/layouts.d.ts +0 -39
- package/types/removeUnusedCss.d.ts +0 -115
- package/types/tailwind.d.ts +0 -22
- package/types/templates.d.ts +0 -181
|
@@ -1,64 +1,269 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
1
|
+
import posthtml from 'posthtml'
|
|
2
|
+
import get from 'lodash-es/get.js'
|
|
3
|
+
import { defu as merge } from 'defu'
|
|
4
|
+
|
|
5
|
+
import comb from './comb.js'
|
|
6
|
+
import sixHex from './sixHex.js'
|
|
7
|
+
import minify from './minify.js'
|
|
8
|
+
import baseUrl from './baseUrl.js'
|
|
9
|
+
import inlineCSS from './inline.js'
|
|
10
|
+
import prettify from './prettify.js'
|
|
11
|
+
import filters from './filters/index.js'
|
|
12
|
+
import markdown from 'posthtml-markdownit'
|
|
13
|
+
import posthtmlMso from './posthtmlMso.js'
|
|
14
|
+
import shorthandCss from './shorthandCss.js'
|
|
15
|
+
import preventWidows from './preventWidows.js'
|
|
16
|
+
import addAttributes from './addAttributes.js'
|
|
17
|
+
import urlParameters from './urlParameters.js'
|
|
18
|
+
import safeClassNames from './safeClassNames.js'
|
|
19
|
+
import replaceStrings from './replaceStrings.js'
|
|
20
|
+
import attributeToStyle from './attributeToStyle.js'
|
|
21
|
+
import removeAttributes from './removeAttributes.js'
|
|
22
|
+
|
|
23
|
+
import coreTransformers from './core.js'
|
|
24
|
+
|
|
25
|
+
import defaultPosthtmlConfig from '../posthtml/defaultConfig.js'
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Use Maizzle Transformers on an HTML string.
|
|
29
|
+
*
|
|
30
|
+
* Only Transformers that are enabled in the `config` will be used.
|
|
31
|
+
*
|
|
32
|
+
* @param {string} html The HTML content
|
|
33
|
+
* @param {object} config The Maizzle config object
|
|
34
|
+
* @returns {Promise<{ original: string, config: object, html: string }>}
|
|
35
|
+
* A Promise resolving to an object containing the original HTML, modified HTML, and the config
|
|
36
|
+
*/
|
|
37
|
+
export async function run(html = '', config = {}) {
|
|
38
|
+
const posthtmlPlugins = []
|
|
39
|
+
|
|
40
|
+
const posthtmlConfig = merge(
|
|
41
|
+
get(config, 'posthtml.options', {}),
|
|
42
|
+
defaultPosthtmlConfig
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* 1. Core transformers
|
|
47
|
+
*
|
|
48
|
+
* Transformers that are always enabled
|
|
49
|
+
*
|
|
50
|
+
*/
|
|
51
|
+
posthtmlPlugins.push(coreTransformers(config))
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* 2. Safe class names
|
|
55
|
+
*
|
|
56
|
+
* Rewrite Tailwind CSS class names to email-safe alternatives,
|
|
57
|
+
* unless explicitly disabled
|
|
58
|
+
*/
|
|
59
|
+
if (get(config, 'css.safeClassNames') !== false) {
|
|
60
|
+
posthtmlPlugins.push(
|
|
61
|
+
safeClassNames(get(config, 'css.safeClassNames', {}))
|
|
62
|
+
)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* 3. Filters
|
|
67
|
+
*
|
|
68
|
+
* Apply filters to HTML.
|
|
69
|
+
* Filters are always applied, unless explicitly disabled.
|
|
70
|
+
*/
|
|
71
|
+
if (get(config, 'filters') !== false) {
|
|
72
|
+
posthtmlPlugins.push(
|
|
73
|
+
filters(get(config, 'filters', {}))
|
|
74
|
+
)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* 4. Markdown
|
|
79
|
+
*
|
|
80
|
+
* Convert Markdown to HTML with Markdown-it, unless explicitly disabled
|
|
81
|
+
*/
|
|
82
|
+
if (get(config, 'markdown') !== false) {
|
|
83
|
+
posthtmlPlugins.push(
|
|
84
|
+
markdown(get(config, 'markdown', {}))
|
|
85
|
+
)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* 5. Prevent widow words
|
|
90
|
+
* Always runs, unless explicitly disabled
|
|
91
|
+
*/
|
|
92
|
+
if (get(config, 'widowWords') !== false) {
|
|
93
|
+
posthtmlPlugins.push(
|
|
94
|
+
preventWidows(get(config, 'widowWords', {}))
|
|
95
|
+
)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* 6. Attribute to `style`
|
|
100
|
+
*
|
|
101
|
+
* Duplicate HTML attributes to inline CSS.
|
|
102
|
+
*/
|
|
103
|
+
if (get(config, 'css.inline.attributeToStyle')) {
|
|
104
|
+
posthtmlPlugins.push(
|
|
105
|
+
attributeToStyle(get(config, 'css.inline.attributeToStyle', []))
|
|
106
|
+
)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* 7. Inline CSS
|
|
111
|
+
*
|
|
112
|
+
* Inline CSS into HTML
|
|
113
|
+
*/
|
|
114
|
+
if (get(config, 'css.inline')) {
|
|
115
|
+
posthtmlPlugins.push(inlineCSS(
|
|
116
|
+
merge(
|
|
117
|
+
get(config, 'css.inline', {}),
|
|
118
|
+
{
|
|
119
|
+
removeInlinedSelectors: true,
|
|
120
|
+
}
|
|
121
|
+
)
|
|
122
|
+
))
|
|
123
|
+
}
|
|
45
124
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
125
|
+
/**
|
|
126
|
+
* 8. Purge CSS
|
|
127
|
+
*
|
|
128
|
+
* Remove unused CSS, uglify classes etc.
|
|
129
|
+
*/
|
|
130
|
+
if (get(config, 'css.purge')) {
|
|
131
|
+
posthtmlPlugins.push(comb(config.css.purge))
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* 9. Remove attributes
|
|
136
|
+
*
|
|
137
|
+
* Remove attributes from HTML tags
|
|
138
|
+
* If `undefined`, removes empty `style` and `class` attributes
|
|
139
|
+
*/
|
|
140
|
+
if (get(config, 'attributes.remove') !== false) {
|
|
141
|
+
posthtmlPlugins.push(
|
|
142
|
+
removeAttributes(
|
|
143
|
+
get(config, 'attributes.remove', []),
|
|
144
|
+
posthtmlConfig
|
|
145
|
+
)
|
|
146
|
+
)
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* 10. Shorthand CSS
|
|
151
|
+
*
|
|
152
|
+
* Convert longhand CSS properties to shorthand in `style` attributes
|
|
153
|
+
*/
|
|
154
|
+
if (get(config, 'css.shorthand')) {
|
|
155
|
+
posthtmlPlugins.push(
|
|
156
|
+
shorthandCss(get(config, 'css.shorthand', {}))
|
|
157
|
+
)
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* 11. Add attributes
|
|
162
|
+
*
|
|
163
|
+
* Add attributes to HTML tags
|
|
164
|
+
*/
|
|
165
|
+
if (get(config, 'attributes.add') !== false) {
|
|
166
|
+
posthtmlPlugins.push(
|
|
167
|
+
addAttributes(get(config, 'attributes.add', {}))
|
|
168
|
+
)
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* 12. Base URL
|
|
173
|
+
*
|
|
174
|
+
* Add a base URL to relative paths
|
|
175
|
+
*/
|
|
176
|
+
if (get(config, 'baseURL', get(config, 'baseUrl'))) {
|
|
177
|
+
posthtmlPlugins.push(
|
|
178
|
+
baseUrl(get(config, 'baseURL', get(config, 'baseUrl', {})))
|
|
179
|
+
)
|
|
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
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* 13. URL parameters
|
|
199
|
+
*
|
|
200
|
+
* Add parameters to URLs
|
|
201
|
+
*/
|
|
202
|
+
if (get(config, 'urlParameters')) {
|
|
203
|
+
posthtmlPlugins.push(
|
|
204
|
+
urlParameters(get(config, 'urlParameters', {}))
|
|
205
|
+
)
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* 14. Six-digit HEX
|
|
210
|
+
*
|
|
211
|
+
* Convert three-digit HEX colors to six-digit
|
|
212
|
+
* Always runs, unless explicitly disabled
|
|
213
|
+
*/
|
|
214
|
+
if (get(config, 'css.sixHex') !== false) {
|
|
215
|
+
posthtmlPlugins.push(
|
|
216
|
+
sixHex()
|
|
217
|
+
)
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* 15. PostHTML MSO
|
|
222
|
+
*
|
|
223
|
+
* Simplify writing MSO conditionals for Outlook
|
|
224
|
+
*/
|
|
225
|
+
if (get(config, 'outlook') !== false) {
|
|
226
|
+
posthtmlPlugins.push(
|
|
227
|
+
posthtmlMso(get(config, 'outlook', {}))
|
|
228
|
+
)
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* 16. Prettify
|
|
233
|
+
*
|
|
234
|
+
* Pretty-print HTML using js-beautify
|
|
235
|
+
*/
|
|
236
|
+
if (get(config, 'prettify')) {
|
|
237
|
+
posthtmlPlugins.push(
|
|
238
|
+
prettify(get(config, 'prettify', {}))
|
|
239
|
+
)
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* 17. Minify
|
|
244
|
+
*
|
|
245
|
+
* Minify HTML using html-crush
|
|
246
|
+
*/
|
|
247
|
+
if (get(config, 'minify')) {
|
|
248
|
+
posthtmlPlugins.push(
|
|
249
|
+
minify(get(config, 'minify', {}))
|
|
250
|
+
)
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* 18. Replace strings
|
|
255
|
+
*
|
|
256
|
+
* Replace strings through regular expressions
|
|
257
|
+
*/
|
|
258
|
+
if (get(config, 'replaceStrings')) {
|
|
259
|
+
posthtmlPlugins.push(
|
|
260
|
+
replaceStrings(get(config, 'replaceStrings', {}))
|
|
261
|
+
)
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
return posthtml(posthtmlPlugins)
|
|
265
|
+
.process(html, posthtmlConfig)
|
|
266
|
+
.then(result => ({
|
|
267
|
+
html: result.html,
|
|
268
|
+
}))
|
|
269
|
+
}
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
import juice from 'juice'
|
|
2
|
+
import postcss from 'postcss'
|
|
3
|
+
import get from 'lodash-es/get.js'
|
|
4
|
+
import has from 'lodash-es/has.js'
|
|
5
|
+
import remove from 'lodash-es/remove.js'
|
|
6
|
+
import { render } from 'posthtml-render'
|
|
7
|
+
import { calc } from '@csstools/css-calc'
|
|
8
|
+
import isEmpty from 'lodash-es/isEmpty.js'
|
|
9
|
+
import * as cheerio from 'cheerio/lib/slim'
|
|
10
|
+
import safeParser from 'postcss-safe-parser'
|
|
11
|
+
import isObject from 'lodash-es/isObject.js'
|
|
12
|
+
import { parser as parse } from 'posthtml-parser'
|
|
13
|
+
import { useAttributeSizes } from './useAttributeSizes.js'
|
|
14
|
+
|
|
15
|
+
const posthtmlPlugin = (options = {}) => tree => {
|
|
16
|
+
return inline(render(tree), options).then(html => parse(html))
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export default posthtmlPlugin
|
|
20
|
+
|
|
21
|
+
export async function inline(html = '', options = {}) {
|
|
22
|
+
// Exit early if no HTML is passed
|
|
23
|
+
if (typeof html !== 'string' || html === '') {
|
|
24
|
+
return html
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const removeStyleTags = get(options, 'removeStyleTags', false)
|
|
28
|
+
const css = get(options, 'customCSS', false)
|
|
29
|
+
|
|
30
|
+
options.resolveCSSVariables = get(options, 'resolveCSSVariables', true)
|
|
31
|
+
options.removeInlinedSelectors = get(options, 'removeInlinedSelectors', true)
|
|
32
|
+
options.resolveCalc = get(options, 'resolveCalc', true)
|
|
33
|
+
options.preferUnitlessValues = get(options, 'preferUnitlessValues', true)
|
|
34
|
+
|
|
35
|
+
juice.styleToAttribute = get(options, 'styleToAttribute', {})
|
|
36
|
+
juice.applyWidthAttributes = get(options, 'applyWidthAttributes', true)
|
|
37
|
+
juice.applyHeightAttributes = get(options, 'applyHeightAttributes', true)
|
|
38
|
+
juice.excludedProperties.push(...get(options, 'excludedProperties', []))
|
|
39
|
+
juice.widthElements = get(options, 'widthElements', ['img', 'video']).map(i => i.toUpperCase())
|
|
40
|
+
juice.heightElements = get(options, 'heightElements', ['img', 'video']).map(i => i.toUpperCase())
|
|
41
|
+
|
|
42
|
+
if (isObject(options.codeBlocks) && !isEmpty(options.codeBlocks)) {
|
|
43
|
+
Object.entries(options.codeBlocks).forEach(([k, v]) => {
|
|
44
|
+
juice.codeBlocks[k] = v
|
|
45
|
+
})
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const $ = cheerio.load(html, { decodeEntities: false, _useHtmlParser2: true })
|
|
49
|
+
|
|
50
|
+
// Add a `data-embed` attribute to style tags that have the embed attribute
|
|
51
|
+
$('style[embed]').each((i, el) => {
|
|
52
|
+
$(el).attr('data-embed', '')
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Inline the CSS
|
|
57
|
+
*
|
|
58
|
+
* If customCSS is passed, inline that CSS specifically
|
|
59
|
+
* Otherwise, use Juice's default inlining
|
|
60
|
+
*/
|
|
61
|
+
$.root().html(
|
|
62
|
+
css
|
|
63
|
+
? juice.inlineContent($.html(), css, { removeStyleTags, ...options })
|
|
64
|
+
: juice($.html(), { removeStyleTags, ...options })
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Prefer attribute sizes
|
|
69
|
+
*
|
|
70
|
+
* Prefer HTML `width` and `height` attributes over inline CSS.
|
|
71
|
+
* Useful for retina images in MSO Outlook, where CSS sizes
|
|
72
|
+
* aren't respected and will render the image in its
|
|
73
|
+
* natural size.
|
|
74
|
+
*/
|
|
75
|
+
if (options.useAttributeSizes) {
|
|
76
|
+
$.root().html(
|
|
77
|
+
await useAttributeSizes(html, {
|
|
78
|
+
width: juice.widthElements,
|
|
79
|
+
height: juice.heightElements,
|
|
80
|
+
})
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Remove inlined selectors from the HTML
|
|
86
|
+
*/
|
|
87
|
+
// For each style tag
|
|
88
|
+
$('style:not([embed])').each((i, el) => {
|
|
89
|
+
// Parse the CSS
|
|
90
|
+
const { root } = postcss()
|
|
91
|
+
.process(
|
|
92
|
+
$(el).html(),
|
|
93
|
+
{
|
|
94
|
+
from: undefined,
|
|
95
|
+
parser: safeParser
|
|
96
|
+
}
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
const preservedClasses = new Set()
|
|
100
|
+
const selectors = new Set()
|
|
101
|
+
|
|
102
|
+
// Preserve selectors in at rules
|
|
103
|
+
root.walkAtRules(rule => {
|
|
104
|
+
if (['media', 'supports'].includes(rule.name)) {
|
|
105
|
+
rule.walkRules(rule => {
|
|
106
|
+
preservedClasses.add(rule.selector)
|
|
107
|
+
})
|
|
108
|
+
}
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
// For each rule in the CSS block we're parsing
|
|
112
|
+
root.walkRules(rule => {
|
|
113
|
+
// Keep track of declarations in the rule
|
|
114
|
+
const declarations = new Set()
|
|
115
|
+
|
|
116
|
+
rule.walkDecls(decl => {
|
|
117
|
+
// Resolve calc() values to static values
|
|
118
|
+
if (options.resolveCalc) {
|
|
119
|
+
decl.value = decl.value.includes('calc(') ? calc(decl.value) : decl.value
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
declarations.add(decl)
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Remove duplicate declarations
|
|
127
|
+
*
|
|
128
|
+
* Only do so if the `resolveCSSVariables` option is enabled,
|
|
129
|
+
* otherwise we'll end up removing all declarations that use CSS variables
|
|
130
|
+
*/
|
|
131
|
+
if (options.resolveCSSVariables) {
|
|
132
|
+
Array.from(declarations)
|
|
133
|
+
/**
|
|
134
|
+
* Consider only declarations with a value that includes any of the other declarations' property
|
|
135
|
+
* So a decl like color(var(--text-color)) will be removed if there's a decl with a property of --text-color
|
|
136
|
+
* */
|
|
137
|
+
.filter(decl =>
|
|
138
|
+
Array.from(declarations).some(otherDecl => decl.value.includes(otherDecl.prop))
|
|
139
|
+
|| decl.prop.startsWith('--')
|
|
140
|
+
)
|
|
141
|
+
.map(decl => decl.remove())
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const { selector } = rule
|
|
145
|
+
|
|
146
|
+
selectors.add({
|
|
147
|
+
name: selector,
|
|
148
|
+
prop: get(rule.nodes[0], 'prop')
|
|
149
|
+
})
|
|
150
|
+
|
|
151
|
+
// Preserve pseudo selectors
|
|
152
|
+
// TODO: revisit pseudos list
|
|
153
|
+
if ([':hover', ':active', ':focus', ':visited', ':link', ':before', ':after'].some(i => selector.includes(i))) {
|
|
154
|
+
preservedClasses.add(selector)
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (options.removeInlinedSelectors) {
|
|
158
|
+
// Remove the rule in the <style> tag as long as it's not a preserved class
|
|
159
|
+
if (!preservedClasses.has(selector)) {
|
|
160
|
+
rule.remove()
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Update the <style> tag contents
|
|
164
|
+
$(el).html(root.toString())
|
|
165
|
+
}
|
|
166
|
+
})
|
|
167
|
+
|
|
168
|
+
// Loop over selectors that we found in the <style> tags
|
|
169
|
+
selectors.forEach(({ name, prop }) => {
|
|
170
|
+
const elements = $(name).get()
|
|
171
|
+
|
|
172
|
+
// If the property is excluded from inlining, skip
|
|
173
|
+
if (!juice.excludedProperties.includes(prop)) {
|
|
174
|
+
// Find the selector in the HTML
|
|
175
|
+
elements.forEach((el) => {
|
|
176
|
+
// Get a `property|value` list from the inline style attribute
|
|
177
|
+
const styleAttr = $(el).attr('style')
|
|
178
|
+
let inlineStyles = {}
|
|
179
|
+
|
|
180
|
+
if (styleAttr) {
|
|
181
|
+
inlineStyles = styleAttr.split(';').reduce((acc, i) => {
|
|
182
|
+
let [property, value] = i.split(':').map(i => i.trim())
|
|
183
|
+
|
|
184
|
+
if (value && options.resolveCalc) {
|
|
185
|
+
value = value.includes('calc') ? calc(value) : value
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (value && options.preferUnitlessValues) {
|
|
189
|
+
value = value.replace(
|
|
190
|
+
/\b0(px|rem|em|%|vh|vw|vmin|vmax|in|cm|mm|pt|pc|ex|ch)\b/g,
|
|
191
|
+
'0'
|
|
192
|
+
)
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
if (property) {
|
|
196
|
+
acc[property] = value
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
return acc
|
|
200
|
+
}, {})
|
|
201
|
+
|
|
202
|
+
// Update the element's style attribute with the new value
|
|
203
|
+
$(el).attr(
|
|
204
|
+
'style',
|
|
205
|
+
Object.entries(inlineStyles).map(([property, value]) => `${property}: ${value}`).join('; ')
|
|
206
|
+
)
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Get the classes from the element's class attribute
|
|
210
|
+
const classes = $(el).attr('class')
|
|
211
|
+
|
|
212
|
+
if (options.removeInlinedSelectors && classes) {
|
|
213
|
+
const classList = classes.split(' ')
|
|
214
|
+
|
|
215
|
+
// If the class has been inlined in the style attribute...
|
|
216
|
+
if (has(inlineStyles, prop)) {
|
|
217
|
+
// Try to remove the classes that have been inlined
|
|
218
|
+
if (![...preservedClasses].some(item => item.endsWith(name) || item.startsWith(name))) {
|
|
219
|
+
remove(classList, classToRemove => name.includes(classToRemove))
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Update the class list on the element with the new classes
|
|
223
|
+
if (classList.length > 0) {
|
|
224
|
+
$(el).attr('class', classList.join(' '))
|
|
225
|
+
} else {
|
|
226
|
+
$(el).removeAttr('class')
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
})
|
|
231
|
+
}
|
|
232
|
+
})
|
|
233
|
+
})
|
|
234
|
+
|
|
235
|
+
$('style[embed]').each((i, el) => {
|
|
236
|
+
$(el).removeAttr('embed')
|
|
237
|
+
})
|
|
238
|
+
|
|
239
|
+
return $.html()
|
|
240
|
+
}
|
|
@@ -1,20 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import posthtml from 'posthtml'
|
|
2
|
+
import { defu as merge } from 'defu'
|
|
3
|
+
import md from 'posthtml-markdownit'
|
|
4
|
+
import posthtmlConfig from '../posthtml/defaultConfig.js'
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const markdownOptions = merge({markdownit: {html: true}}, userMarkdownOptions)
|
|
6
|
+
export async function markdown(html = '', options = {}, posthtmlOptions = {}) {
|
|
7
|
+
/**
|
|
8
|
+
* Automatically wrap in <md> tag, unless manual mode is enabled
|
|
9
|
+
* With manual mode, user must wrap the markdown content in a <md> tag
|
|
10
|
+
* https://github.com/posthtml/posthtml-markdownit#usage
|
|
11
|
+
*/
|
|
12
|
+
html = options.manual ? html : `<md>${html}</md>`
|
|
14
13
|
|
|
15
14
|
return posthtml([
|
|
16
|
-
|
|
15
|
+
md(options)
|
|
17
16
|
])
|
|
18
|
-
.process(html, posthtmlOptions)
|
|
17
|
+
.process(html, merge(posthtmlOptions, posthtmlConfig))
|
|
19
18
|
.then(result => result.html)
|
|
20
19
|
}
|
|
@@ -1,21 +1,26 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import posthtml from 'posthtml'
|
|
2
|
+
import { crush } from 'html-crush'
|
|
3
|
+
import { defu as merge } from 'defu'
|
|
4
|
+
import { render } from 'posthtml-render'
|
|
5
|
+
import { parser as parse } from 'posthtml-parser'
|
|
6
|
+
import posthtmlConfig from '../posthtml/defaultConfig.js'
|
|
3
7
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
return html
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
config = direct ? {
|
|
10
|
-
lineLengthLimit: 500,
|
|
11
|
-
removeIndentations: true,
|
|
8
|
+
const posthtmlPlugin = (options = {}) => tree => {
|
|
9
|
+
options = merge(options, {
|
|
12
10
|
removeLineBreaks: true,
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
const { result: html } = crush(render(tree), options)
|
|
14
|
+
|
|
15
|
+
return parse(html)
|
|
16
|
+
}
|
|
15
17
|
|
|
16
|
-
|
|
17
|
-
html = crush(html, {removeLineBreaks: true, ...config}).result
|
|
18
|
-
}
|
|
18
|
+
export default posthtmlPlugin
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
export async function minify(html = '', options = {}, posthtmlOptions = {}) {
|
|
21
|
+
return posthtml([
|
|
22
|
+
posthtmlPlugin(options)
|
|
23
|
+
])
|
|
24
|
+
.process(html, merge(posthtmlOptions, posthtmlConfig))
|
|
25
|
+
.then(result => result.html)
|
|
21
26
|
}
|
|
@@ -1,11 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import posthtml from 'posthtml'
|
|
2
|
+
import { defu as merge } from 'defu'
|
|
3
|
+
import posthtmlMso from 'posthtml-mso'
|
|
4
|
+
import posthtmlConfig from '../posthtml/defaultConfig.js'
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
export default function posthtmlPlugin(options = {}) {
|
|
7
|
+
return posthtmlMso(options)
|
|
8
|
+
}
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
export async function useMso(html = '', options = {}, posthtmlOptions = {}) {
|
|
11
|
+
return posthtml([
|
|
12
|
+
posthtmlPlugin(options)
|
|
13
|
+
])
|
|
14
|
+
.process(html, merge(posthtmlOptions, posthtmlConfig))
|
|
15
|
+
.then(result => result.html)
|
|
11
16
|
}
|