@maizzle/framework 4.2.1 → 4.2.3
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 +2 -3
- package/src/generators/plaintext.js +40 -6
- package/src/generators/posthtml/defaultConfig.js +3 -0
- package/src/generators/{posthtml.js → posthtml/index.js} +2 -1
- package/src/generators/tailwindcss.js +9 -2
- package/src/transformers/attributeToStyle.js +3 -2
- package/src/transformers/baseUrl.js +27 -26
- package/src/transformers/extraAttributes.js +3 -2
- package/src/transformers/filters/index.js +16 -5
- package/src/transformers/index.js +2 -2
- package/src/transformers/markdown.js +2 -1
- package/src/transformers/posthtmlMso.js +3 -2
- package/src/transformers/preventWidows.js +75 -7
- package/src/transformers/removeAttributes.js +48 -9
- package/src/transformers/removeInlineBackgroundColor.js +8 -4
- package/src/transformers/removeInlineSizes.js +8 -5
- package/src/transformers/removeInlinedSelectors.js +19 -5
- package/src/transformers/removeUnusedCss.js +12 -12
- package/src/transformers/replaceStrings.js +1 -1
- package/src/transformers/safeClassNames.js +7 -3
- package/src/transformers/shorthandInlineCSS.js +3 -2
- package/src/transformers/sixHex.js +13 -14
- package/src/transformers/urlParameters.js +3 -2
- package/src/utils/helpers.js +2 -1
- package/test/expected/transformers/base-url.html +1 -1
- package/test/fixtures/posthtml/component.html +2 -2
- package/test/stubs/breaking/bad.html +2 -2
- package/test/stubs/components/component.html +2 -2
- package/test/stubs/events/before-create.html +1 -1
- package/test/stubs/plaintext/plaintext.html +1 -1
- package/test/stubs/templates/1.html +1 -1
- package/test/stubs/templates/2.html +1 -0
- package/test/stubs/templates/2.test +1 -1
- package/test/test-posthtml.js +20 -31
- package/test/test-tailwindcss.js +6 -6
- package/test/test-todisk.js +14 -64
- package/test/test-tostring.js +20 -15
- package/test/test-transformers.js +113 -21
- package/test/expected/posthtml/fetch.html +0 -5
- package/test/fixtures/posthtml/fetch.html +0 -9
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@maizzle/framework",
|
|
3
|
-
"version": "4.2.
|
|
3
|
+
"version": "4.2.3",
|
|
4
4
|
"description": "Maizzle is a framework that helps you quickly build HTML emails with Tailwind CSS.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "src/index.js",
|
|
@@ -65,12 +65,11 @@
|
|
|
65
65
|
"posthtml-modules": "^0.9.0",
|
|
66
66
|
"posthtml-mso": "^1.0.4",
|
|
67
67
|
"posthtml-postcss-merge-longhand": "^1.0.2",
|
|
68
|
-
"posthtml-remove-attributes": "^1.0.0",
|
|
69
68
|
"posthtml-safe-class-names": "^1.0.8",
|
|
70
69
|
"posthtml-url-parameters": "^1.0.4",
|
|
71
70
|
"pretty": "^2.0.0",
|
|
72
|
-
"prevent-widows": "^1.0.2",
|
|
73
71
|
"query-string": "^7.1.0",
|
|
72
|
+
"string-remove-widows": "^2.1.0",
|
|
74
73
|
"string-strip-html": "^8.2.0",
|
|
75
74
|
"tailwindcss": "^3.1.0"
|
|
76
75
|
},
|
|
@@ -1,12 +1,44 @@
|
|
|
1
1
|
const path = require('path')
|
|
2
|
-
const {get} = require('lodash')
|
|
3
2
|
const posthtml = require('posthtml')
|
|
3
|
+
const {get, merge} = require('lodash')
|
|
4
4
|
const {stripHtml} = require('string-strip-html')
|
|
5
|
+
const defaultConfig = require('./posthtml/defaultConfig')
|
|
5
6
|
|
|
6
7
|
const self = {
|
|
7
|
-
|
|
8
|
+
removeCustomTags: (tag, html, config = {}) => {
|
|
8
9
|
const posthtmlOptions = get(config, 'build.posthtml.options', {})
|
|
9
10
|
|
|
11
|
+
const posthtmlPlugin = () => tree => {
|
|
12
|
+
const process = node => {
|
|
13
|
+
if (!node.tag) {
|
|
14
|
+
return node
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (node.tag === tag) {
|
|
18
|
+
return {
|
|
19
|
+
tag: false,
|
|
20
|
+
content: ['']
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (Array.isArray(tag) && tag.includes(node.tag)) {
|
|
25
|
+
return {
|
|
26
|
+
tag: false,
|
|
27
|
+
content: ['']
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return node
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return tree.walk(process)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return posthtml([posthtmlPlugin()]).process(html, {...posthtmlOptions, sync: true}).html
|
|
38
|
+
},
|
|
39
|
+
handleCustomTags: (html, config = {}) => {
|
|
40
|
+
const posthtmlOptions = merge(defaultConfig, get(config, 'build.posthtml.options', {}))
|
|
41
|
+
|
|
10
42
|
const posthtmlPlugin = () => tree => {
|
|
11
43
|
const process = node => {
|
|
12
44
|
if (node.tag === 'plaintext') {
|
|
@@ -31,16 +63,18 @@ const self = {
|
|
|
31
63
|
|
|
32
64
|
return posthtml([posthtmlPlugin()]).process(html, {...posthtmlOptions, sync: true}).html
|
|
33
65
|
},
|
|
34
|
-
generate: async (html, destination, config) => {
|
|
66
|
+
generate: async (html, destination, config = {}) => {
|
|
35
67
|
const configDestinationPath = get(config, 'destination.path')
|
|
36
68
|
const extension = get(config, 'destination.extension', 'txt')
|
|
37
69
|
|
|
38
|
-
const
|
|
70
|
+
const strippedHTML = self.removeCustomTags('not-plaintext', html, config)
|
|
71
|
+
|
|
72
|
+
const plaintext = stripHtml(strippedHTML, {
|
|
39
73
|
dumpLinkHrefsNearby: {
|
|
40
74
|
enabled: true
|
|
41
75
|
},
|
|
42
|
-
stripTogetherWithTheirContents: ['script', 'style', 'xml'
|
|
43
|
-
...
|
|
76
|
+
stripTogetherWithTheirContents: ['script', 'style', 'xml'],
|
|
77
|
+
...config
|
|
44
78
|
}).result
|
|
45
79
|
|
|
46
80
|
html = self.handleCustomTags(html, config)
|
|
@@ -4,6 +4,7 @@ const {get, merge} = require('lodash')
|
|
|
4
4
|
const fetch = require('posthtml-fetch')
|
|
5
5
|
const layouts = require('posthtml-extend')
|
|
6
6
|
const modules = require('posthtml-modules')
|
|
7
|
+
const defaultConfig = require('./defaultConfig')
|
|
7
8
|
const expressions = require('posthtml-expressions')
|
|
8
9
|
|
|
9
10
|
module.exports = async (html, config) => {
|
|
@@ -14,7 +15,7 @@ module.exports = async (html, config) => {
|
|
|
14
15
|
const modulesRoot = modulesOptions.root || './'
|
|
15
16
|
const modulesFrom = modulesOptions.from || `${modulesRoot}/fake`
|
|
16
17
|
|
|
17
|
-
const posthtmlOptions = get(config, 'build.posthtml.options', {})
|
|
18
|
+
const posthtmlOptions = merge(defaultConfig, get(config, 'build.posthtml.options', {}))
|
|
18
19
|
const posthtmlPlugins = get(config, 'build.posthtml.plugins', [])
|
|
19
20
|
|
|
20
21
|
const expressionsOptions = merge({strictMode: false}, get(config, 'build.posthtml.expressions', {}))
|
|
@@ -31,11 +31,19 @@ module.exports = {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
// Merge user's Tailwind config on top of a 'base' config
|
|
34
|
+
const layoutsRoot = get(maizzleConfig, 'build.layouts.root')
|
|
35
|
+
const componentsRoot = get(maizzleConfig, 'build.components.root')
|
|
36
|
+
|
|
34
37
|
const config = merge({
|
|
35
38
|
important: true,
|
|
36
39
|
content: {
|
|
37
40
|
files: [
|
|
38
|
-
'
|
|
41
|
+
typeof layoutsRoot === 'string' && layoutsRoot ?
|
|
42
|
+
`${layoutsRoot}/**/*.html`.replace(/\/\//g, '/') :
|
|
43
|
+
'./src/layouts/**/*.html',
|
|
44
|
+
typeof componentsRoot === 'string' && componentsRoot ?
|
|
45
|
+
`${componentsRoot}/**/*.html`.replace(/\/\//g, '/') :
|
|
46
|
+
'./src/components/**/*.html',
|
|
39
47
|
{raw: html, extension: 'html'}
|
|
40
48
|
]
|
|
41
49
|
}
|
|
@@ -46,7 +54,6 @@ module.exports = {
|
|
|
46
54
|
config.content = {
|
|
47
55
|
files: [
|
|
48
56
|
...config.content,
|
|
49
|
-
'./src/**/*.*',
|
|
50
57
|
{raw: html, extension: 'html'}
|
|
51
58
|
]
|
|
52
59
|
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
const posthtml = require('posthtml')
|
|
2
2
|
const parseAttrs = require('posthtml-attrs-parser')
|
|
3
|
-
const
|
|
3
|
+
const defaultConfig = require('../generators/posthtml/defaultConfig')
|
|
4
|
+
const {get, merge, forEach, intersection, keys, isEmpty} = require('lodash')
|
|
4
5
|
|
|
5
6
|
module.exports = async (html, config = {}, direct = false) => {
|
|
6
|
-
const posthtmlOptions = get(config, 'build.posthtml.options', {})
|
|
7
|
+
const posthtmlOptions = merge(defaultConfig, get(config, 'build.posthtml.options', {}))
|
|
7
8
|
const attributes = get(config, 'inlineCSS.attributeToStyle', false)
|
|
8
9
|
|
|
9
10
|
if (typeof attributes === 'boolean' && attributes) {
|
|
@@ -1,7 +1,33 @@
|
|
|
1
1
|
const posthtml = require('posthtml')
|
|
2
2
|
const isUrl = require('is-url-superb')
|
|
3
3
|
const baseUrl = require('posthtml-base-url')
|
|
4
|
-
const {get, isObject, isEmpty} = require('lodash')
|
|
4
|
+
const {get, merge, isObject, isEmpty} = require('lodash')
|
|
5
|
+
const defaultConfig = require('../generators/posthtml/defaultConfig')
|
|
6
|
+
|
|
7
|
+
module.exports = async (html, config = {}, direct = false) => {
|
|
8
|
+
const url = direct ? config : get(config, 'baseURL')
|
|
9
|
+
const posthtmlOptions = merge(defaultConfig, get(config, 'build.posthtml.options', {}))
|
|
10
|
+
|
|
11
|
+
// Handle `baseUrl` as a string
|
|
12
|
+
if (typeof url === 'string' && url.length > 0) {
|
|
13
|
+
html = rewriteVMLs(html, url)
|
|
14
|
+
|
|
15
|
+
return posthtml([
|
|
16
|
+
baseUrl({url, allTags: true, styleTag: true, inlineCss: true})
|
|
17
|
+
])
|
|
18
|
+
.process(html, posthtmlOptions)
|
|
19
|
+
.then(result => result.html)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Handle `baseUrl` as an object
|
|
23
|
+
if (isObject(url) && !isEmpty(url)) {
|
|
24
|
+
html = rewriteVMLs(html, url.url)
|
|
25
|
+
|
|
26
|
+
return posthtml([baseUrl(url)]).process(html, posthtmlOptions).then(result => result.html)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return html
|
|
30
|
+
}
|
|
5
31
|
|
|
6
32
|
/**
|
|
7
33
|
* VML backgrounds must be handled with regex because
|
|
@@ -42,28 +68,3 @@ const rewriteVMLs = (html, url) => {
|
|
|
42
68
|
|
|
43
69
|
return html
|
|
44
70
|
}
|
|
45
|
-
|
|
46
|
-
module.exports = async (html, config = {}, direct = false) => {
|
|
47
|
-
const url = direct ? config : get(config, 'baseURL')
|
|
48
|
-
const posthtmlOptions = get(config, 'build.posthtml.options', {})
|
|
49
|
-
|
|
50
|
-
// Handle `baseUrl` as a string
|
|
51
|
-
if (typeof url === 'string' && url.length > 0) {
|
|
52
|
-
html = rewriteVMLs(html, url)
|
|
53
|
-
|
|
54
|
-
return posthtml([
|
|
55
|
-
baseUrl({url, allTags: true, styleTag: true, inlineCss: true})
|
|
56
|
-
])
|
|
57
|
-
.process(html, posthtmlOptions)
|
|
58
|
-
.then(result => result.html)
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// Handle `baseUrl` as an object
|
|
62
|
-
if (isObject(url) && !isEmpty(url)) {
|
|
63
|
-
html = rewriteVMLs(html, url.url)
|
|
64
|
-
|
|
65
|
-
return posthtml([baseUrl(url)]).process(html, posthtmlOptions).then(result => result.html)
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
return html
|
|
69
|
-
}
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
const posthtml = require('posthtml')
|
|
2
|
-
const {get, isObject} = require('lodash')
|
|
2
|
+
const {get, merge, isObject} = require('lodash')
|
|
3
3
|
const addAttributes = require('posthtml-extra-attributes')
|
|
4
|
+
const defaultConfig = require('../generators/posthtml/defaultConfig')
|
|
4
5
|
|
|
5
6
|
module.exports = async (html, config = {}, direct = false) => {
|
|
6
7
|
if (get(config, 'extraAttributes') === false) {
|
|
7
8
|
return html
|
|
8
9
|
}
|
|
9
10
|
|
|
10
|
-
const posthtmlOptions = get(config, 'build.posthtml.options', {})
|
|
11
|
+
const posthtmlOptions = merge(defaultConfig, get(config, 'build.posthtml.options', {}))
|
|
11
12
|
|
|
12
13
|
let attributes = {
|
|
13
14
|
table: {
|
|
@@ -5,13 +5,14 @@ const PostCSS = require('../../generators/postcss')
|
|
|
5
5
|
const posthtmlContent = require('posthtml-content')
|
|
6
6
|
const Tailwind = require('../../generators/tailwindcss')
|
|
7
7
|
const safeClassNames = require('posthtml-safe-class-names')
|
|
8
|
+
const defaultConfig = require('../../generators/posthtml/defaultConfig')
|
|
8
9
|
|
|
9
10
|
module.exports = async (html, config = {}, direct = false) => {
|
|
10
11
|
const filters = direct ?
|
|
11
12
|
merge(defaultFilters, config) :
|
|
12
13
|
merge(defaultFilters, get(config, 'filters', {}))
|
|
13
14
|
|
|
14
|
-
const posthtmlOptions = get(config, 'build.posthtml.options', {})
|
|
15
|
+
const posthtmlOptions = merge(defaultConfig, get(config, 'build.posthtml.options', {}))
|
|
15
16
|
|
|
16
17
|
/**
|
|
17
18
|
* Compile CSS in <style {post|tailwind}css> tags
|
|
@@ -22,11 +23,21 @@ module.exports = async (html, config = {}, direct = false) => {
|
|
|
22
23
|
filters.postcss = css => PostCSS.process(css, maizzleConfig)
|
|
23
24
|
filters.tailwindcss = css => Tailwind.compile(css, html, tailwindConfig, maizzleConfig)
|
|
24
25
|
|
|
25
|
-
|
|
26
|
+
const posthtmlPlugins = [
|
|
26
27
|
styleDataEmbed(),
|
|
27
|
-
posthtmlContent(filters)
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
posthtmlContent(filters)
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
if (get(config, 'safeClassNames') !== false) {
|
|
32
|
+
posthtmlPlugins.push(safeClassNames({
|
|
33
|
+
replacements: {
|
|
34
|
+
'{': '{',
|
|
35
|
+
'}': '}'
|
|
36
|
+
}
|
|
37
|
+
}))
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return posthtml(posthtmlPlugins)
|
|
30
41
|
.process(html, posthtmlOptions)
|
|
31
42
|
.then(result => result.html)
|
|
32
43
|
}
|
|
@@ -49,10 +49,10 @@ exports.prettify = (html, config) => prettify(html, config, true)
|
|
|
49
49
|
exports.ensureSixHEX = (html, config) => ensureSixHEX(html, config)
|
|
50
50
|
exports.withFilters = (html, config) => filters(html, config, true)
|
|
51
51
|
exports.addURLParams = (html, config) => addURLParams(html, config, true)
|
|
52
|
-
exports.preventWidows = (html, config) => preventWidows(html, config
|
|
52
|
+
exports.preventWidows = (html, config) => preventWidows(html, config)
|
|
53
53
|
exports.replaceStrings = (html, config) => replaceStrings(html, config, true)
|
|
54
54
|
exports.safeClassNames = (html, config) => safeClassNames(html, config, true)
|
|
55
|
-
exports.removeUnusedCSS = (html, config) => removeUnusedCSS(html, config
|
|
55
|
+
exports.removeUnusedCSS = (html, config) => removeUnusedCSS(html, config)
|
|
56
56
|
exports.removeAttributes = (html, config) => removeAttributes(html, config, true)
|
|
57
57
|
exports.attributeToStyle = (html, config) => attributeToStyle(html, config, true)
|
|
58
58
|
exports.removeInlineSizes = (html, config) => removeInlineSizes(html, config, true)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const posthtml = require('posthtml')
|
|
2
2
|
const {get, merge} = require('lodash')
|
|
3
3
|
const markdown = require('posthtml-markdownit')
|
|
4
|
+
const defaultConfig = require('../generators/posthtml/defaultConfig')
|
|
4
5
|
|
|
5
6
|
module.exports = async (html, config = {}, direct = false) => {
|
|
6
7
|
if (get(config, 'markdown') === false) {
|
|
@@ -8,7 +9,7 @@ module.exports = async (html, config = {}, direct = false) => {
|
|
|
8
9
|
}
|
|
9
10
|
|
|
10
11
|
const userMarkdownOptions = direct ? config : get(config, 'markdown', {})
|
|
11
|
-
const posthtmlOptions = get(config, 'build.posthtml.options', {})
|
|
12
|
+
const posthtmlOptions = merge(defaultConfig, get(config, 'build.posthtml.options', {}))
|
|
12
13
|
const markdownOptions = merge({markdownit: {html: true}}, userMarkdownOptions)
|
|
13
14
|
|
|
14
15
|
return posthtml([
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
const {get} = require('lodash')
|
|
2
1
|
const posthtml = require('posthtml')
|
|
2
|
+
const {get, merge} = require('lodash')
|
|
3
3
|
const outlook = require('posthtml-mso')
|
|
4
|
+
const defaultConfig = require('../generators/posthtml/defaultConfig')
|
|
4
5
|
|
|
5
6
|
module.exports = async (html, config) => {
|
|
6
7
|
const outlookOptions = get(config, 'build.posthtml.outlook', {})
|
|
7
|
-
const posthtmlOptions = get(config, 'build.posthtml.options', {})
|
|
8
|
+
const posthtmlOptions = merge(defaultConfig, get(config, 'build.posthtml.options', {}))
|
|
8
9
|
|
|
9
10
|
return posthtml([outlook({...outlookOptions})]).process(html, posthtmlOptions).then(result => result.html)
|
|
10
11
|
}
|
|
@@ -1,13 +1,81 @@
|
|
|
1
|
-
const {get} = require('lodash')
|
|
2
1
|
const posthtml = require('posthtml')
|
|
3
|
-
const
|
|
2
|
+
const {get, merge, isEmpty} = require('lodash')
|
|
3
|
+
const {removeWidows} = require('string-remove-widows')
|
|
4
|
+
const defaultConfig = require('../generators/posthtml/defaultConfig')
|
|
4
5
|
|
|
5
|
-
module.exports = async (html, config = {}
|
|
6
|
-
|
|
6
|
+
module.exports = async (html, config = {}) => {
|
|
7
|
+
if (isEmpty(config)) {
|
|
8
|
+
return removeWidows(html).res
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const posthtmlOptions = merge(defaultConfig, get(config, 'build.posthtml.options', {}))
|
|
12
|
+
|
|
13
|
+
return posthtml([removeWidowsPlugin(config)]).process(html, posthtmlOptions).then(result => result.html)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const removeWidowsPlugin = options => tree => {
|
|
17
|
+
const {attrName = 'prevent-widows', ...removeWidowsOptions} = get(options, 'widowWords', options)
|
|
18
|
+
|
|
19
|
+
removeWidowsOptions.minWordCount = removeWidowsOptions.minWordCount || 3
|
|
20
|
+
|
|
21
|
+
// Ignore defaults
|
|
22
|
+
const mappings = [
|
|
23
|
+
// Jinja-like
|
|
24
|
+
{
|
|
25
|
+
heads: '{{',
|
|
26
|
+
tails: '}}'
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
heads: ['{% if', '{%- if'],
|
|
30
|
+
tails: ['{% endif', '{%- endif']
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
heads: ['{% for', '{%- for'],
|
|
34
|
+
tails: ['{% endfor', '{%- endfor']
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
heads: ['{%', '{%-'],
|
|
38
|
+
tails: ['%}', '-%}']
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
heads: '{#',
|
|
42
|
+
tails: '#}'
|
|
43
|
+
},
|
|
44
|
+
// ASP/Hexo-like
|
|
45
|
+
{
|
|
46
|
+
heads: ['<%', '<%=', '<%-'],
|
|
47
|
+
tails: ['%>', '=%>', '-%>']
|
|
48
|
+
},
|
|
49
|
+
// MSO comments
|
|
50
|
+
{
|
|
51
|
+
heads: '<!--[',
|
|
52
|
+
tails: ']>'
|
|
53
|
+
},
|
|
54
|
+
// <![endif]-->
|
|
55
|
+
{
|
|
56
|
+
heads: '<![',
|
|
57
|
+
tails: ']--><'
|
|
58
|
+
}
|
|
59
|
+
]
|
|
60
|
+
|
|
61
|
+
if (Array.isArray(removeWidowsOptions.ignore)) {
|
|
62
|
+
removeWidowsOptions.ignore.forEach(pair => mappings.push(pair))
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (typeof removeWidowsOptions.ignore !== 'string') {
|
|
66
|
+
removeWidowsOptions.ignore = mappings
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const process = node => {
|
|
70
|
+
if (node.attrs && Object.keys(node.attrs).includes(attrName)) {
|
|
71
|
+
const widowsRemovedString = removeWidows(tree.render(node.content), removeWidowsOptions).res
|
|
72
|
+
|
|
73
|
+
node.content = tree.render(tree.parser(widowsRemovedString))
|
|
74
|
+
node.attrs[attrName] = false
|
|
75
|
+
}
|
|
7
76
|
|
|
8
|
-
|
|
9
|
-
return preventWidows(html)
|
|
77
|
+
return node
|
|
10
78
|
}
|
|
11
79
|
|
|
12
|
-
return
|
|
80
|
+
return tree.walk(process)
|
|
13
81
|
}
|
|
@@ -1,17 +1,56 @@
|
|
|
1
|
-
const {get} = require('lodash')
|
|
2
1
|
const posthtml = require('posthtml')
|
|
3
|
-
const
|
|
2
|
+
const {get, merge} = require('lodash')
|
|
3
|
+
const defaultConfig = require('../generators/posthtml/defaultConfig')
|
|
4
4
|
|
|
5
5
|
module.exports = async (html, config = {}, direct = false) => {
|
|
6
6
|
const attributes = direct ? (Array.isArray(config) ? [...config] : []) : get(config, 'removeAttributes', [])
|
|
7
|
-
const posthtmlOptions = get(config, 'build.posthtml.options', {})
|
|
7
|
+
const posthtmlOptions = merge(defaultConfig, get(config, 'build.posthtml.options', {}))
|
|
8
8
|
|
|
9
|
-
attributes.push(
|
|
9
|
+
attributes.push('style', 'class')
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
})
|
|
11
|
+
html = await posthtml([
|
|
12
|
+
removeAttributes(attributes, posthtmlOptions)
|
|
13
|
+
]).process(html, posthtmlOptions).then(result => result.html)
|
|
15
14
|
|
|
16
|
-
return
|
|
15
|
+
return html
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Remove empty attributes with PostHTML
|
|
20
|
+
*
|
|
21
|
+
* Condition 1:
|
|
22
|
+
* `boolean` is for attributes without ="" (respects `recognizeNoValueAttribute` in PostHTML)
|
|
23
|
+
* `''` if the attribute included ="", i.e. style=""
|
|
24
|
+
*
|
|
25
|
+
* Condition 2: attribute value is a string and matches the one on the node
|
|
26
|
+
*
|
|
27
|
+
* Condition 3: same as 2, but for regular expressions
|
|
28
|
+
*/
|
|
29
|
+
const removeAttributes = (attributes = {}, posthtmlOptions = {}) => tree => {
|
|
30
|
+
const process = node => {
|
|
31
|
+
const normalizedAttrs = attributes.map(attribute => {
|
|
32
|
+
return {
|
|
33
|
+
name: get(attribute, 'name', typeof attribute === 'string' ? attribute : false),
|
|
34
|
+
value: get(attribute, 'value', get(posthtmlOptions, 'recognizeNoValueAttributes', true))
|
|
35
|
+
}
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
if (node.attrs) {
|
|
39
|
+
normalizedAttrs.forEach(attr => {
|
|
40
|
+
const targetAttrValue = get(node.attrs, attr.name)
|
|
41
|
+
|
|
42
|
+
if (
|
|
43
|
+
typeof targetAttrValue === 'boolean' || targetAttrValue === '' ||
|
|
44
|
+
(typeof attr.value === 'string' && node.attrs[attr.name] === attr.value) ||
|
|
45
|
+
(attr.value instanceof RegExp && attr.value.test(node.attrs[attr.name]))
|
|
46
|
+
) {
|
|
47
|
+
node.attrs[attr.name] = false
|
|
48
|
+
}
|
|
49
|
+
})
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return node
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return tree.walk(process)
|
|
17
56
|
}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
const posthtml = require('posthtml')
|
|
2
|
-
const {get, isEmpty} = require('lodash')
|
|
2
|
+
const {get, merge, isEmpty} = require('lodash')
|
|
3
3
|
const parseAttrs = require('posthtml-attrs-parser')
|
|
4
|
+
const {toStyleString} = require('../utils/helpers')
|
|
5
|
+
const defaultConfig = require('../generators/posthtml/defaultConfig')
|
|
4
6
|
|
|
5
7
|
module.exports = async (html, config = {}, direct = false) => {
|
|
6
|
-
const posthtmlOptions = get(config, 'build.posthtml.options', {})
|
|
8
|
+
const posthtmlOptions = merge(defaultConfig, get(config, 'build.posthtml.options', {}))
|
|
7
9
|
|
|
8
10
|
if (isEmpty(config)) {
|
|
9
11
|
return posthtml([removeInlineBGColor()]).process(html, posthtmlOptions).then(result => result.html)
|
|
@@ -40,9 +42,11 @@ const removeInlineBGColor = (options = {}) => tree => {
|
|
|
40
42
|
})
|
|
41
43
|
|
|
42
44
|
if (attrs.style && attrs.style['background-color']) {
|
|
43
|
-
attrs.bgcolor = attrs.style['background-color']
|
|
45
|
+
node.attrs.bgcolor = attrs.style['background-color']
|
|
46
|
+
|
|
44
47
|
delete attrs.style['background-color']
|
|
45
|
-
|
|
48
|
+
|
|
49
|
+
node.attrs.style = toStyleString(attrs.style)
|
|
46
50
|
}
|
|
47
51
|
|
|
48
52
|
return node
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
const posthtml = require('posthtml')
|
|
2
|
-
const {get, isEmpty} = require('lodash')
|
|
2
|
+
const {get, merge, isEmpty} = require('lodash')
|
|
3
3
|
const parseAttrs = require('posthtml-attrs-parser')
|
|
4
|
+
const {toStyleString} = require('../utils/helpers')
|
|
5
|
+
const defaultConfig = require('../generators/posthtml/defaultConfig')
|
|
4
6
|
|
|
5
7
|
module.exports = async (html, config = {}, direct = false) => {
|
|
6
8
|
const settings = direct ? config : get(config, 'inlineCSS.keepOnlyAttributeSizes', {})
|
|
7
9
|
|
|
8
10
|
if (!isEmpty(settings)) {
|
|
9
|
-
const posthtmlOptions = get(config, 'build.posthtml.options', {})
|
|
11
|
+
const posthtmlOptions = merge(defaultConfig, get(config, 'build.posthtml.options', {}))
|
|
12
|
+
|
|
10
13
|
return posthtml([removeInlineSizes(settings)]).process(html, posthtmlOptions).then(result => result.html)
|
|
11
14
|
}
|
|
12
15
|
|
|
@@ -26,14 +29,14 @@ const removeInlineSizes = (mappings = {}) => tree => {
|
|
|
26
29
|
}
|
|
27
30
|
|
|
28
31
|
tags.forEach(() => {
|
|
29
|
-
if (attrs.style) {
|
|
32
|
+
if (get(node, 'attrs.style')) {
|
|
30
33
|
delete attrs.style[attribute]
|
|
34
|
+
|
|
35
|
+
node.attrs.style = toStyleString(attrs.style)
|
|
31
36
|
}
|
|
32
37
|
})
|
|
33
38
|
})
|
|
34
39
|
|
|
35
|
-
node.attrs = attrs.compose()
|
|
36
|
-
|
|
37
40
|
return node
|
|
38
41
|
}
|
|
39
42
|
|
|
@@ -1,19 +1,21 @@
|
|
|
1
|
-
const {get, has, remove} = require('lodash')
|
|
2
1
|
const postcss = require('postcss')
|
|
3
2
|
const posthtml = require('posthtml')
|
|
3
|
+
const {get, merge, has, remove} = require('lodash')
|
|
4
4
|
const parseAttrs = require('posthtml-attrs-parser')
|
|
5
5
|
const matchHelper = require('posthtml-match-helper')
|
|
6
|
+
const defaultConfig = require('../generators/posthtml/defaultConfig')
|
|
6
7
|
|
|
7
8
|
module.exports = async (html, config = {}) => {
|
|
8
9
|
if (get(config, 'removeInlinedClasses') === false) {
|
|
9
10
|
return html
|
|
10
11
|
}
|
|
11
12
|
|
|
12
|
-
const posthtmlOptions = get(config, 'build.posthtml.options', {})
|
|
13
|
-
|
|
13
|
+
const posthtmlOptions = merge(defaultConfig, get(config, 'build.posthtml.options', {}))
|
|
14
|
+
|
|
15
|
+
return posthtml([plugin(posthtmlOptions)]).process(html, posthtmlOptions).then(result => result.html)
|
|
14
16
|
}
|
|
15
17
|
|
|
16
|
-
const plugin =
|
|
18
|
+
const plugin = posthtmlOptions => tree => {
|
|
17
19
|
const process = node => {
|
|
18
20
|
// For each style tag...
|
|
19
21
|
if (node.tag === 'style') {
|
|
@@ -57,12 +59,24 @@ const plugin = () => tree => {
|
|
|
57
59
|
|
|
58
60
|
n.attrs = parsedAttrs.compose()
|
|
59
61
|
|
|
62
|
+
// Fix issue with .compose() automatically quoting attributes with no values
|
|
63
|
+
Object.entries(n.attrs).forEach(([name, value]) => {
|
|
64
|
+
if (value === '' && get(posthtmlOptions, 'recognizeNoValueAttribute') === true) {
|
|
65
|
+
n.attrs[name] = true
|
|
66
|
+
}
|
|
67
|
+
})
|
|
68
|
+
|
|
60
69
|
return n
|
|
61
70
|
})
|
|
62
71
|
} catch {}
|
|
63
72
|
})
|
|
64
73
|
|
|
65
|
-
node.content = root.toString()
|
|
74
|
+
node.content = root.toString().trim()
|
|
75
|
+
|
|
76
|
+
// Remove <style> tag if it ends up empty after processing
|
|
77
|
+
if (node.content.length === 0) {
|
|
78
|
+
node.tag = false
|
|
79
|
+
}
|
|
66
80
|
}
|
|
67
81
|
|
|
68
82
|
return node
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
const {comb} = require('email-comb')
|
|
2
|
-
const {get,
|
|
2
|
+
const {get, merge} = require('lodash')
|
|
3
3
|
|
|
4
|
-
module.exports = async (html, config = {}
|
|
4
|
+
module.exports = async (html, config = {}) => {
|
|
5
5
|
if (get(config, 'removeUnusedCSS') === false) {
|
|
6
6
|
return html
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
const options = direct ? config : get(config, 'removeUnusedCSS', {})
|
|
10
|
-
|
|
11
9
|
const safelist = [
|
|
12
10
|
'*body*', // Gmail
|
|
13
11
|
'.gmail*', // Gmail
|
|
@@ -26,15 +24,17 @@ module.exports = async (html, config = {}, direct = false) => {
|
|
|
26
24
|
'.lang*' // Fenced code blocks
|
|
27
25
|
]
|
|
28
26
|
|
|
29
|
-
|
|
30
|
-
|
|
27
|
+
const defaultOptions = {
|
|
28
|
+
backend: [
|
|
29
|
+
{heads: '{{', tails: '}}'},
|
|
30
|
+
{heads: '{%', tails: '%}'}
|
|
31
|
+
],
|
|
32
|
+
whitelist: [...get(config, 'whitelist', []), ...safelist]
|
|
31
33
|
}
|
|
32
34
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
return comb(html, options).result
|
|
37
|
-
}
|
|
35
|
+
const options = typeof config === 'boolean' && config ?
|
|
36
|
+
defaultOptions :
|
|
37
|
+
merge(defaultOptions, get(config, 'removeUnusedCSS', config))
|
|
38
38
|
|
|
39
|
-
return html
|
|
39
|
+
return comb(html, options).result
|
|
40
40
|
}
|