@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.
Files changed (80) hide show
  1. package/bin/maizzle +3 -1
  2. package/package.json +65 -58
  3. package/src/commands/build.js +244 -19
  4. package/src/commands/serve.js +2 -197
  5. package/src/generators/plaintext.js +192 -91
  6. package/src/generators/render.js +128 -0
  7. package/src/index.js +46 -14
  8. package/src/{generators/posthtml → posthtml}/defaultComponentsConfig.js +6 -4
  9. package/src/{generators/posthtml → posthtml}/defaultConfig.js +1 -1
  10. package/src/posthtml/index.js +74 -0
  11. package/src/posthtml/plugins/expandLinkTag.js +36 -0
  12. package/src/server/client.js +181 -0
  13. package/src/server/index.js +383 -0
  14. package/src/server/routes/hmr.js +24 -0
  15. package/src/server/routes/index.js +38 -0
  16. package/src/server/views/error.html +83 -0
  17. package/src/server/views/index.html +24 -0
  18. package/src/server/websockets.js +27 -0
  19. package/src/transformers/addAttributes.js +30 -0
  20. package/src/transformers/attributeToStyle.js +30 -36
  21. package/src/transformers/baseUrl.js +52 -23
  22. package/src/transformers/comb.js +51 -0
  23. package/src/transformers/core.js +20 -0
  24. package/src/transformers/filters/defaultFilters.js +90 -70
  25. package/src/transformers/filters/index.js +14 -78
  26. package/src/transformers/index.js +268 -63
  27. package/src/transformers/inline.js +240 -0
  28. package/src/transformers/markdown.js +13 -14
  29. package/src/transformers/minify.js +21 -16
  30. package/src/transformers/posthtmlMso.js +13 -8
  31. package/src/transformers/prettify.js +16 -15
  32. package/src/transformers/preventWidows.js +32 -26
  33. package/src/transformers/removeAttributes.js +17 -17
  34. package/src/transformers/replaceStrings.js +30 -9
  35. package/src/transformers/safeClassNames.js +24 -24
  36. package/src/transformers/shorthandCss.js +22 -0
  37. package/src/transformers/sixHex.js +15 -15
  38. package/src/transformers/urlParameters.js +18 -16
  39. package/src/transformers/useAttributeSizes.js +65 -0
  40. package/src/utils/getConfigByFilePath.js +124 -0
  41. package/src/utils/node.js +68 -0
  42. package/src/utils/string.js +117 -0
  43. package/types/build.d.ts +117 -57
  44. package/types/components.d.ts +130 -112
  45. package/types/config.d.ts +454 -242
  46. package/types/css/inline.d.ts +234 -0
  47. package/types/css/purge.d.ts +125 -0
  48. package/types/events.d.ts +5 -105
  49. package/types/index.d.ts +148 -116
  50. package/types/markdown.d.ts +20 -18
  51. package/types/minify.d.ts +122 -120
  52. package/types/plaintext.d.ts +46 -52
  53. package/types/posthtml.d.ts +103 -136
  54. package/types/render.d.ts +0 -117
  55. package/types/urlParameters.d.ts +21 -20
  56. package/types/widowWords.d.ts +9 -7
  57. package/src/functions/plaintext.js +0 -5
  58. package/src/functions/render.js +0 -5
  59. package/src/generators/config.js +0 -52
  60. package/src/generators/output/index.js +0 -4
  61. package/src/generators/output/to-disk.js +0 -254
  62. package/src/generators/output/to-string.js +0 -73
  63. package/src/generators/postcss.js +0 -23
  64. package/src/generators/posthtml/index.js +0 -75
  65. package/src/generators/tailwindcss.js +0 -157
  66. package/src/transformers/extraAttributes.js +0 -33
  67. package/src/transformers/inlineCss.js +0 -42
  68. package/src/transformers/removeInlineBackgroundColor.js +0 -56
  69. package/src/transformers/removeInlineSizes.js +0 -43
  70. package/src/transformers/removeInlinedSelectors.js +0 -100
  71. package/src/transformers/removeUnusedCss.js +0 -48
  72. package/src/transformers/shorthandInlineCSS.js +0 -26
  73. package/src/utils/helpers.js +0 -13
  74. package/types/baseUrl.d.ts +0 -79
  75. package/types/fetch.d.ts +0 -143
  76. package/types/inlineCss.d.ts +0 -207
  77. package/types/layouts.d.ts +0 -39
  78. package/types/removeUnusedCss.d.ts +0 -115
  79. package/types/tailwind.d.ts +0 -22
  80. package/types/templates.d.ts +0 -181
@@ -1,64 +1,269 @@
1
- const minify = require('./minify')
2
- const filters = require('./filters')
3
- const inline = require('./inlineCss')
4
- const markdown = require('./markdown')
5
- const prettify = require('./prettify')
6
- const ensureSixHEX = require('./sixHex')
7
- const applyBaseUrl = require('./baseUrl')
8
- const posthtmlMSO = require('./posthtmlMso')
9
- const addURLParams = require('./urlParameters')
10
- const preventWidows = require('./preventWidows')
11
- const replaceStrings = require('./replaceStrings')
12
- const safeClassNames = require('./safeClassNames')
13
- const removeUnusedCSS = require('./removeUnusedCss')
14
- const removeAttributes = require('./removeAttributes')
15
- const attributeToStyle = require('./attributeToStyle')
16
- const removeInlineSizes = require('./removeInlineSizes')
17
- const applyExtraAttributes = require('./extraAttributes')
18
- const shorthandInlineCSS = require('./shorthandInlineCSS')
19
- const removeInlinedClasses = require('./removeInlinedSelectors')
20
- const removeInlineBgColor = require('./removeInlineBackgroundColor')
21
-
22
- exports.process = async (html, config) => {
23
- html = await safeClassNames(html, config)
24
- html = await filters(html, config)
25
- html = await markdown(html, config)
26
- html = await preventWidows(html, config)
27
- html = await attributeToStyle(html, config)
28
- html = await inline(html, config)
29
- html = await removeUnusedCSS(html, config)
30
- html = await removeAttributes(html, config)
31
- html = await shorthandInlineCSS(html, config)
32
- html = await removeInlineSizes(html, config)
33
- html = await removeInlineBgColor(html, config)
34
- html = await applyExtraAttributes(html, config)
35
- html = await applyBaseUrl(html, config)
36
- html = await addURLParams(html, config)
37
- html = await ensureSixHEX(html, config)
38
- html = await posthtmlMSO(html, config)
39
- html = await prettify(html, config)
40
- html = await minify(html, config)
41
- html = await replaceStrings(html, config)
42
-
43
- return html
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
- exports.minify = (html, config) => minify(html, config, true)
47
- exports.inlineCSS = (html, config) => inline(html, config, true)
48
- exports.markdown = (html, config) => markdown(html, config, true)
49
- exports.prettify = (html, config) => prettify(html, config, true)
50
- exports.ensureSixHEX = (html, config) => ensureSixHEX(html, config)
51
- exports.withFilters = (html, config) => filters(html, config, true)
52
- exports.addURLParams = (html, config) => addURLParams(html, config, true)
53
- exports.preventWidows = (html, config) => preventWidows(html, config)
54
- exports.replaceStrings = (html, config) => replaceStrings(html, config, true)
55
- exports.safeClassNames = (html, config) => safeClassNames(html, config, true)
56
- exports.removeUnusedCSS = (html, config) => removeUnusedCSS(html, config, true)
57
- exports.removeAttributes = (html, config) => removeAttributes(html, config, true)
58
- exports.attributeToStyle = (html, config) => attributeToStyle(html, config, true)
59
- exports.removeInlineSizes = (html, config) => removeInlineSizes(html, config, true)
60
- exports.applyBaseUrl = (html, config) => applyBaseUrl(html, config, true)
61
- exports.removeInlinedClasses = (html, config) => removeInlinedClasses(html, config)
62
- exports.shorthandInlineCSS = (html, config) => shorthandInlineCSS(html, config, true)
63
- exports.removeInlineBgColor = (html, config) => removeInlineBgColor(html, config, true)
64
- exports.applyExtraAttributes = (html, config) => applyExtraAttributes(html, config, true)
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
- const posthtml = require('posthtml')
2
- const {get, merge} = require('lodash')
3
- const markdown = require('posthtml-markdownit')
4
- const defaultConfig = require('../generators/posthtml/defaultConfig')
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
- module.exports = async (html, config = {}, direct = false) => {
7
- if (get(config, 'markdown') === false) {
8
- return html
9
- }
10
-
11
- const userMarkdownOptions = direct ? config : get(config, 'markdown', {})
12
- const posthtmlOptions = merge(defaultConfig, get(config, 'build.posthtml.options', {}))
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
- markdown({...markdownOptions})
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
- const {crush} = require('html-crush')
2
- const {get, isEmpty} = require('lodash')
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
- module.exports = async (html, config = {}, direct = false) => {
5
- if (get(config, 'minify') === false) {
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
- ...config
14
- } : get(config, 'minify', {})
11
+ })
12
+
13
+ const { result: html } = crush(render(tree), options)
14
+
15
+ return parse(html)
16
+ }
15
17
 
16
- if (!isEmpty(config)) {
17
- html = crush(html, {removeLineBreaks: true, ...config}).result
18
- }
18
+ export default posthtmlPlugin
19
19
 
20
- return html
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
- const posthtml = require('posthtml')
2
- const {get, merge} = require('lodash')
3
- const outlook = require('posthtml-mso')
4
- const defaultConfig = require('../generators/posthtml/defaultConfig')
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
- module.exports = async (html, config) => {
7
- const outlookOptions = get(config, 'build.posthtml.outlook', {})
8
- const posthtmlOptions = merge(defaultConfig, get(config, 'build.posthtml.options', {}))
6
+ export default function posthtmlPlugin(options = {}) {
7
+ return posthtmlMso(options)
8
+ }
9
9
 
10
- return posthtml([outlook({...outlookOptions})]).process(html, posthtmlOptions).then(result => result.html)
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
  }