@maizzle/framework 5.0.0-beta.3 → 5.0.0-beta.31
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 +32 -30
- package/src/commands/build.js +146 -73
- package/src/generators/plaintext.js +26 -23
- package/src/generators/render.js +15 -14
- package/src/posthtml/defaultComponentsConfig.js +2 -2
- package/src/posthtml/defaultConfig.js +13 -3
- package/src/posthtml/index.js +38 -9
- package/src/posthtml/plugins/envAttributes.js +32 -0
- package/src/posthtml/plugins/envTags.js +33 -0
- package/src/server/index.js +159 -96
- package/src/server/routes/index.js +51 -13
- package/src/server/views/404.html +59 -0
- package/src/server/views/index.html +162 -14
- package/src/transformers/addAttributes.js +2 -3
- package/src/transformers/attributeToStyle.js +1 -3
- package/src/transformers/baseUrl.js +6 -6
- package/src/transformers/comb.js +7 -6
- package/src/transformers/core.js +12 -0
- package/src/transformers/filters/index.js +1 -2
- package/src/transformers/index.js +56 -67
- package/src/transformers/inline.js +53 -16
- package/src/transformers/markdown.js +14 -7
- package/src/transformers/minify.js +4 -3
- package/src/transformers/posthtmlMso.js +1 -3
- package/src/transformers/prettify.js +4 -3
- package/src/transformers/preventWidows.js +15 -65
- package/src/transformers/removeAttributes.js +3 -4
- package/src/transformers/replaceStrings.js +7 -5
- package/src/transformers/safeClassNames.js +1 -2
- package/src/transformers/shorthandCss.js +1 -3
- package/src/transformers/sixHex.js +1 -3
- package/src/transformers/template.js +26 -0
- package/src/transformers/urlParameters.js +1 -3
- package/src/transformers/useAttributeSizes.js +1 -3
- package/src/utils/string.js +89 -0
- package/types/build.d.ts +53 -24
- package/types/config.d.ts +60 -49
- package/types/css/inline.d.ts +20 -0
- package/types/css/purge.d.ts +3 -3
- package/types/events.d.ts +153 -5
- package/types/index.d.ts +4 -3
- package/types/posthtml.d.ts +3 -3
- package/types/urlParameters.d.ts +1 -1
- package/types/widowWords.d.ts +16 -36
- package/types/components.d.ts +0 -195
- package/types/expressions.d.ts +0 -100
|
@@ -2,18 +2,21 @@ import juice from 'juice'
|
|
|
2
2
|
import postcss from 'postcss'
|
|
3
3
|
import get from 'lodash-es/get.js'
|
|
4
4
|
import has from 'lodash-es/has.js'
|
|
5
|
+
import { defu as merge } from 'defu'
|
|
6
|
+
import * as cheerio from 'cheerio/slim'
|
|
5
7
|
import remove from 'lodash-es/remove.js'
|
|
6
8
|
import { render } from 'posthtml-render'
|
|
7
9
|
import { calc } from '@csstools/css-calc'
|
|
8
10
|
import isEmpty from 'lodash-es/isEmpty.js'
|
|
9
|
-
import * as cheerio from 'cheerio/lib/slim'
|
|
10
11
|
import safeParser from 'postcss-safe-parser'
|
|
11
12
|
import isObject from 'lodash-es/isObject.js'
|
|
12
13
|
import { parser as parse } from 'posthtml-parser'
|
|
14
|
+
import { parseCSSRule } from '../utils/string.js'
|
|
13
15
|
import { useAttributeSizes } from './useAttributeSizes.js'
|
|
16
|
+
import { getPosthtmlOptions } from '../posthtml/defaultConfig.js'
|
|
14
17
|
|
|
15
18
|
const posthtmlPlugin = (options = {}) => tree => {
|
|
16
|
-
return inline(render(tree), options).then(html => parse(html))
|
|
19
|
+
return inline(render(tree), options).then(html => parse(html, getPosthtmlOptions()))
|
|
17
20
|
}
|
|
18
21
|
|
|
19
22
|
export default posthtmlPlugin
|
|
@@ -31,6 +34,26 @@ export async function inline(html = '', options = {}) {
|
|
|
31
34
|
options.removeInlinedSelectors = get(options, 'removeInlinedSelectors', true)
|
|
32
35
|
options.resolveCalc = get(options, 'resolveCalc', true)
|
|
33
36
|
options.preferUnitlessValues = get(options, 'preferUnitlessValues', true)
|
|
37
|
+
options.safelist = new Set([
|
|
38
|
+
...get(options, 'safelist', []),
|
|
39
|
+
...[
|
|
40
|
+
'.body', // Gmail
|
|
41
|
+
'.gmail', // Gmail
|
|
42
|
+
'.apple', // Apple Mail
|
|
43
|
+
'.ios', // Mail on iOS
|
|
44
|
+
'.ox-', // Open-Xchange
|
|
45
|
+
'.outlook', // Outlook.com
|
|
46
|
+
'[data-ogs', // Outlook.com
|
|
47
|
+
'.bloop_container', // Airmail
|
|
48
|
+
'.Singleton', // Apple Mail 10
|
|
49
|
+
'.unused', // Notes 8
|
|
50
|
+
'.moz-text-html', // Thunderbird
|
|
51
|
+
'.mail-detail-content', // Comcast, Libero webmail
|
|
52
|
+
'edo', // Edison (all)
|
|
53
|
+
'#msgBody', // Freenet uses #msgBody
|
|
54
|
+
'.lang' // Fenced code blocks
|
|
55
|
+
],
|
|
56
|
+
])
|
|
34
57
|
|
|
35
58
|
juice.styleToAttribute = get(options, 'styleToAttribute', {})
|
|
36
59
|
juice.applyWidthAttributes = get(options, 'applyWidthAttributes', true)
|
|
@@ -45,12 +68,20 @@ export async function inline(html = '', options = {}) {
|
|
|
45
68
|
})
|
|
46
69
|
}
|
|
47
70
|
|
|
48
|
-
const $ = cheerio.load(html, {
|
|
71
|
+
const $ = cheerio.load(html, {
|
|
72
|
+
xml: {
|
|
73
|
+
decodeEntities: false,
|
|
74
|
+
xmlMode: false,
|
|
75
|
+
}
|
|
76
|
+
})
|
|
49
77
|
|
|
50
78
|
// Add a `data-embed` attribute to style tags that have the embed attribute
|
|
51
|
-
$('style[embed]').each((i, el) => {
|
|
79
|
+
$('style[embed]:not([data-embed])').each((i, el) => {
|
|
52
80
|
$(el).attr('data-embed', '')
|
|
53
81
|
})
|
|
82
|
+
$('style[data-embed]:not([embed])').each((i, el) => {
|
|
83
|
+
$(el).attr('embed', '')
|
|
84
|
+
})
|
|
54
85
|
|
|
55
86
|
/**
|
|
56
87
|
* Inline the CSS
|
|
@@ -96,14 +127,20 @@ export async function inline(html = '', options = {}) {
|
|
|
96
127
|
}
|
|
97
128
|
)
|
|
98
129
|
|
|
99
|
-
|
|
130
|
+
// Precompile a single regex to match any substring from the preservedClasses set
|
|
131
|
+
const combinedPattern = Array.from(options.safelist)
|
|
132
|
+
.map(pattern => pattern.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&')) // Escape special regex chars
|
|
133
|
+
.join('|') // Combine all patterns into a single regex pattern with 'OR' (|)
|
|
134
|
+
|
|
135
|
+
const combinedRegex = new RegExp(combinedPattern)
|
|
136
|
+
|
|
100
137
|
const selectors = new Set()
|
|
101
138
|
|
|
102
139
|
// Preserve selectors in at rules
|
|
103
140
|
root.walkAtRules(rule => {
|
|
104
141
|
if (['media', 'supports'].includes(rule.name)) {
|
|
105
142
|
rule.walkRules(rule => {
|
|
106
|
-
|
|
143
|
+
options.safelist.add(rule.selector)
|
|
107
144
|
})
|
|
108
145
|
}
|
|
109
146
|
})
|
|
@@ -116,7 +153,7 @@ export async function inline(html = '', options = {}) {
|
|
|
116
153
|
rule.walkDecls(decl => {
|
|
117
154
|
// Resolve calc() values to static values
|
|
118
155
|
if (options.resolveCalc) {
|
|
119
|
-
decl.value = decl.value.includes('calc(') ? calc(decl.value) : decl.value
|
|
156
|
+
decl.value = decl.value.includes('calc(') ? calc(decl.value, { precision: 2 }) : decl.value
|
|
120
157
|
}
|
|
121
158
|
|
|
122
159
|
declarations.add(decl)
|
|
@@ -130,10 +167,10 @@ export async function inline(html = '', options = {}) {
|
|
|
130
167
|
*/
|
|
131
168
|
if (options.resolveCSSVariables) {
|
|
132
169
|
Array.from(declarations)
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
170
|
+
/**
|
|
171
|
+
* Consider only declarations with a value that includes any of the other declarations' property
|
|
172
|
+
* So a decl like color(var(--text-color)) will be removed if there's a decl with a property of --text-color
|
|
173
|
+
* */
|
|
137
174
|
.filter(decl =>
|
|
138
175
|
Array.from(declarations).some(otherDecl => decl.value.includes(otherDecl.prop))
|
|
139
176
|
|| decl.prop.startsWith('--')
|
|
@@ -151,12 +188,12 @@ export async function inline(html = '', options = {}) {
|
|
|
151
188
|
// Preserve pseudo selectors
|
|
152
189
|
// TODO: revisit pseudos list
|
|
153
190
|
if ([':hover', ':active', ':focus', ':visited', ':link', ':before', ':after'].some(i => selector.includes(i))) {
|
|
154
|
-
|
|
191
|
+
options.safelist.add(selector)
|
|
155
192
|
}
|
|
156
193
|
|
|
157
194
|
if (options.removeInlinedSelectors) {
|
|
158
195
|
// Remove the rule in the <style> tag as long as it's not a preserved class
|
|
159
|
-
if (!
|
|
196
|
+
if (!options.safelist.has(selector) && !combinedRegex.test(selector)) {
|
|
160
197
|
rule.remove()
|
|
161
198
|
}
|
|
162
199
|
|
|
@@ -179,10 +216,10 @@ export async function inline(html = '', options = {}) {
|
|
|
179
216
|
|
|
180
217
|
if (styleAttr) {
|
|
181
218
|
inlineStyles = styleAttr.split(';').reduce((acc, i) => {
|
|
182
|
-
let
|
|
219
|
+
let { property, value } = parseCSSRule(i)
|
|
183
220
|
|
|
184
221
|
if (value && options.resolveCalc) {
|
|
185
|
-
value = value.includes('calc') ? calc(value) : value
|
|
222
|
+
value = value.includes('calc') ? calc(value, { precision: 2 }) : value
|
|
186
223
|
}
|
|
187
224
|
|
|
188
225
|
if (value && options.preferUnitlessValues) {
|
|
@@ -215,7 +252,7 @@ export async function inline(html = '', options = {}) {
|
|
|
215
252
|
// If the class has been inlined in the style attribute...
|
|
216
253
|
if (has(inlineStyles, prop)) {
|
|
217
254
|
// Try to remove the classes that have been inlined
|
|
218
|
-
if (![...
|
|
255
|
+
if (![...options.safelist].some(item => item.includes(name))) {
|
|
219
256
|
remove(classList, classToRemove => name.includes(classToRemove))
|
|
220
257
|
}
|
|
221
258
|
|
|
@@ -1,19 +1,26 @@
|
|
|
1
1
|
import posthtml from 'posthtml'
|
|
2
|
-
import { defu as merge } from 'defu'
|
|
3
2
|
import md from 'posthtml-markdownit'
|
|
4
|
-
import posthtmlConfig from '../posthtml/defaultConfig.js'
|
|
5
3
|
|
|
6
|
-
export async function markdown(
|
|
4
|
+
export async function markdown(input = '', options = {}, posthtmlOptions = {}) {
|
|
7
5
|
/**
|
|
8
|
-
*
|
|
9
|
-
|
|
6
|
+
* If no input is provided, return an empty string.
|
|
7
|
+
*/
|
|
8
|
+
if (!input) {
|
|
9
|
+
return ''
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Automatically wrap in <md> tag, unless manual mode is enabled.
|
|
14
|
+
*
|
|
15
|
+
* With manual mode, user must wrap the input in a <md> tag.
|
|
16
|
+
*
|
|
10
17
|
* https://github.com/posthtml/posthtml-markdownit#usage
|
|
11
18
|
*/
|
|
12
|
-
|
|
19
|
+
input = options.manual ? input : `<md>${input}</md>`
|
|
13
20
|
|
|
14
21
|
return posthtml([
|
|
15
22
|
md(options)
|
|
16
23
|
])
|
|
17
|
-
.process(
|
|
24
|
+
.process(input, posthtmlOptions)
|
|
18
25
|
.then(result => result.html)
|
|
19
26
|
}
|
|
@@ -3,16 +3,17 @@ import { crush } from 'html-crush'
|
|
|
3
3
|
import { defu as merge } from 'defu'
|
|
4
4
|
import { render } from 'posthtml-render'
|
|
5
5
|
import { parser as parse } from 'posthtml-parser'
|
|
6
|
-
import
|
|
6
|
+
import { getPosthtmlOptions } from '../posthtml/defaultConfig.js'
|
|
7
7
|
|
|
8
8
|
const posthtmlPlugin = (options = {}) => tree => {
|
|
9
9
|
options = merge(options, {
|
|
10
10
|
removeLineBreaks: true,
|
|
11
11
|
})
|
|
12
12
|
|
|
13
|
+
const posthtmlConfig = getPosthtmlOptions()
|
|
13
14
|
const { result: html } = crush(render(tree), options)
|
|
14
15
|
|
|
15
|
-
return parse(html)
|
|
16
|
+
return parse(html, posthtmlConfig)
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
export default posthtmlPlugin
|
|
@@ -21,6 +22,6 @@ export async function minify(html = '', options = {}, posthtmlOptions = {}) {
|
|
|
21
22
|
return posthtml([
|
|
22
23
|
posthtmlPlugin(options)
|
|
23
24
|
])
|
|
24
|
-
.process(html,
|
|
25
|
+
.process(html, posthtmlOptions)
|
|
25
26
|
.then(result => result.html)
|
|
26
27
|
}
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import posthtml from 'posthtml'
|
|
2
|
-
import { defu as merge } from 'defu'
|
|
3
2
|
import posthtmlMso from 'posthtml-mso'
|
|
4
|
-
import posthtmlConfig from '../posthtml/defaultConfig.js'
|
|
5
3
|
|
|
6
4
|
export default function posthtmlPlugin(options = {}) {
|
|
7
5
|
return posthtmlMso(options)
|
|
@@ -11,6 +9,6 @@ export async function useMso(html = '', options = {}, posthtmlOptions = {}) {
|
|
|
11
9
|
return posthtml([
|
|
12
10
|
posthtmlPlugin(options)
|
|
13
11
|
])
|
|
14
|
-
.process(html,
|
|
12
|
+
.process(html, posthtmlOptions)
|
|
15
13
|
.then(result => result.html)
|
|
16
14
|
}
|
|
@@ -2,7 +2,8 @@ import pretty from 'pretty'
|
|
|
2
2
|
import posthtml from 'posthtml'
|
|
3
3
|
import { defu as merge } from 'defu'
|
|
4
4
|
import { render } from 'posthtml-render'
|
|
5
|
-
import
|
|
5
|
+
import { parser as parse } from 'posthtml-parser'
|
|
6
|
+
import { getPosthtmlOptions } from '../posthtml/defaultConfig.js'
|
|
6
7
|
|
|
7
8
|
const posthtmlPlugin = (options = {}) => tree => {
|
|
8
9
|
const defaultConfig = {
|
|
@@ -14,7 +15,7 @@ const posthtmlPlugin = (options = {}) => tree => {
|
|
|
14
15
|
|
|
15
16
|
const config = merge(options, defaultConfig)
|
|
16
17
|
|
|
17
|
-
return pretty(render(tree), config)
|
|
18
|
+
return parse(pretty(render(tree), config), getPosthtmlOptions())
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
export default posthtmlPlugin
|
|
@@ -23,6 +24,6 @@ export async function prettify(html = '', options = {}, posthtmlOptions = {}) {
|
|
|
23
24
|
return posthtml([
|
|
24
25
|
posthtmlPlugin(options)
|
|
25
26
|
])
|
|
26
|
-
.process(html,
|
|
27
|
+
.process(html, posthtmlOptions)
|
|
27
28
|
.then(result => result.html)
|
|
28
29
|
}
|
|
@@ -1,87 +1,37 @@
|
|
|
1
1
|
import posthtml from 'posthtml'
|
|
2
|
+
import posthtmlWidows from 'posthtml-widows'
|
|
2
3
|
import { defu as merge } from 'defu'
|
|
3
|
-
import { removeWidows } from 'string-remove-widows'
|
|
4
|
-
import posthtmlConfig from '../posthtml/defaultConfig.js'
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
export default function posthtmlPlugin(options = {}) {
|
|
7
6
|
options = merge(options, {
|
|
8
|
-
|
|
9
|
-
attrName: 'prevent-widows'
|
|
7
|
+
minWords: 3
|
|
10
8
|
})
|
|
11
9
|
|
|
12
|
-
//
|
|
10
|
+
// Custom ignores
|
|
13
11
|
const mappings = [
|
|
14
|
-
// Jinja-like
|
|
15
|
-
{
|
|
16
|
-
heads: '{{',
|
|
17
|
-
tails: '}}'
|
|
18
|
-
},
|
|
19
|
-
{
|
|
20
|
-
heads: ['{% if', '{%- if'],
|
|
21
|
-
tails: ['{% endif', '{%- endif']
|
|
22
|
-
},
|
|
23
|
-
{
|
|
24
|
-
heads: ['{% for', '{%- for'],
|
|
25
|
-
tails: ['{% endfor', '{%- endfor']
|
|
26
|
-
},
|
|
27
|
-
{
|
|
28
|
-
heads: ['{%', '{%-'],
|
|
29
|
-
tails: ['%}', '-%}']
|
|
30
|
-
},
|
|
31
|
-
{
|
|
32
|
-
heads: '{#',
|
|
33
|
-
tails: '#}'
|
|
34
|
-
},
|
|
35
|
-
// ASP/Hexo-like
|
|
36
|
-
{
|
|
37
|
-
heads: ['<%', '<%=', '<%-'],
|
|
38
|
-
tails: ['%>', '=%>', '-%>']
|
|
39
|
-
},
|
|
40
12
|
// MSO comments
|
|
41
13
|
{
|
|
42
|
-
|
|
43
|
-
|
|
14
|
+
start: '<!--[',
|
|
15
|
+
end: ']>'
|
|
44
16
|
},
|
|
45
17
|
// <![endif]-->
|
|
46
18
|
{
|
|
47
|
-
|
|
48
|
-
|
|
19
|
+
start: '<![',
|
|
20
|
+
end: ']--><'
|
|
49
21
|
}
|
|
50
22
|
]
|
|
51
23
|
|
|
52
24
|
if (Array.isArray(options.ignore)) {
|
|
53
|
-
options.ignore
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
if (typeof options.ignore !== 'string') {
|
|
57
|
-
options.ignore = mappings
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const process = node => {
|
|
61
|
-
if (node.attrs && Object.keys(node.attrs).includes(options.attrName)) {
|
|
62
|
-
const widowsRemovedString = removeWidows(tree.render(node.content), options).res
|
|
63
|
-
node.content = tree.render(tree.parser(widowsRemovedString))
|
|
64
|
-
delete node.attrs[options.attrName]
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
return node
|
|
25
|
+
options.ignore = options.ignore.concat(mappings)
|
|
68
26
|
}
|
|
69
27
|
|
|
70
|
-
return
|
|
28
|
+
return posthtmlWidows(options)
|
|
71
29
|
}
|
|
72
30
|
|
|
73
|
-
export default posthtmlPlugin
|
|
74
|
-
|
|
75
31
|
export async function preventWidows(html = '', options = {}, posthtmlOptions = {}) {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
.process(html, merge(posthtmlOptions, posthtmlConfig))
|
|
82
|
-
.then(result => result.html)
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// Apply to all elements
|
|
86
|
-
return removeWidows(html, options).res
|
|
32
|
+
return posthtml([
|
|
33
|
+
posthtmlPlugin(options)
|
|
34
|
+
])
|
|
35
|
+
.process(html, posthtmlOptions)
|
|
36
|
+
.then(result => result.html)
|
|
87
37
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import posthtml from 'posthtml'
|
|
2
2
|
import get from 'lodash-es/get.js'
|
|
3
|
-
import {
|
|
4
|
-
import posthtmlConfig from '../posthtml/defaultConfig.js'
|
|
3
|
+
import { getPosthtmlOptions } from '../posthtml/defaultConfig.js'
|
|
5
4
|
|
|
6
5
|
/**
|
|
7
6
|
* Remove empty attributes with PostHTML
|
|
@@ -49,8 +48,8 @@ export default posthtmlPlugin
|
|
|
49
48
|
|
|
50
49
|
export async function removeAttributes(html = '', attributes = [], posthtmlOptions = {}) {
|
|
51
50
|
return posthtml([
|
|
52
|
-
posthtmlPlugin(attributes,
|
|
51
|
+
posthtmlPlugin(attributes, getPosthtmlOptions(posthtmlOptions))
|
|
53
52
|
])
|
|
54
|
-
.process(html,
|
|
53
|
+
.process(html, getPosthtmlOptions())
|
|
55
54
|
.then(result => result.html)
|
|
56
55
|
}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import posthtml from 'posthtml'
|
|
2
|
-
import { defu as merge } from 'defu'
|
|
3
2
|
import { render } from 'posthtml-render'
|
|
4
3
|
import isEmpty from 'lodash-es/isEmpty.js'
|
|
5
4
|
import { parser as parse } from 'posthtml-parser'
|
|
6
|
-
import
|
|
5
|
+
import { getPosthtmlOptions } from '../posthtml/defaultConfig.js'
|
|
7
6
|
|
|
8
7
|
const posthtmlPlugin = (replacements = {}) => tree => {
|
|
9
8
|
if (!isEmpty(replacements)) {
|
|
@@ -14,10 +13,13 @@ const posthtmlPlugin = (replacements = {}) => tree => {
|
|
|
14
13
|
render(tree).replace(patterns, matched => {
|
|
15
14
|
for (const [regex, replacement] of regexes) {
|
|
16
15
|
if (regex.test(matched)) {
|
|
17
|
-
return replacement
|
|
16
|
+
return matched.replace(regex, replacement)
|
|
18
17
|
}
|
|
19
18
|
}
|
|
20
|
-
|
|
19
|
+
|
|
20
|
+
return matched
|
|
21
|
+
}),
|
|
22
|
+
getPosthtmlOptions()
|
|
21
23
|
)
|
|
22
24
|
}
|
|
23
25
|
|
|
@@ -30,6 +32,6 @@ export async function replaceStrings(html = '', replacements = {}, posthtmlOptio
|
|
|
30
32
|
return posthtml([
|
|
31
33
|
posthtmlPlugin(replacements)
|
|
32
34
|
])
|
|
33
|
-
.process(html,
|
|
35
|
+
.process(html, posthtmlOptions)
|
|
34
36
|
.then(result => result.html)
|
|
35
37
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import posthtml from 'posthtml'
|
|
2
2
|
import { defu as merge } from 'defu'
|
|
3
|
-
import posthtmlConfig from '../posthtml/defaultConfig.js'
|
|
4
3
|
import posthtmlSafeClassNames from 'posthtml-safe-class-names'
|
|
5
4
|
|
|
6
5
|
export default function posthtmlPlugin(options = {}) {
|
|
@@ -24,6 +23,6 @@ export async function safeClassNames(html = '', options = {}, posthtmlOptions =
|
|
|
24
23
|
return posthtml([
|
|
25
24
|
posthtmlPlugin(options)
|
|
26
25
|
])
|
|
27
|
-
.process(html,
|
|
26
|
+
.process(html, posthtmlOptions)
|
|
28
27
|
.then(result => result.html)
|
|
29
28
|
}
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import posthtml from 'posthtml'
|
|
2
|
-
import { defu as merge } from 'defu'
|
|
3
|
-
import posthtmlConfig from '../posthtml/defaultConfig.js'
|
|
4
2
|
import posthtmlMergeLonghand from 'posthtml-postcss-merge-longhand'
|
|
5
3
|
|
|
6
4
|
export default function posthtmlPlugin(options = {}) {
|
|
@@ -17,6 +15,6 @@ export async function shorthandCSS(html = '', options = {}, posthtmlOptions = {}
|
|
|
17
15
|
return posthtml([
|
|
18
16
|
posthtmlPlugin(options)
|
|
19
17
|
])
|
|
20
|
-
.process(html,
|
|
18
|
+
.process(html, posthtmlOptions)
|
|
21
19
|
.then(result => result.html)
|
|
22
20
|
}
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import posthtml from 'posthtml'
|
|
2
|
-
import { defu as merge } from 'defu'
|
|
3
2
|
import { conv } from 'color-shorthand-hex-to-six-digit'
|
|
4
|
-
import posthtmlConfig from '../posthtml/defaultConfig.js'
|
|
5
3
|
|
|
6
4
|
const posthtmlPlugin = () => tree => {
|
|
7
5
|
const targets = new Set(['bgcolor', 'color'])
|
|
@@ -27,6 +25,6 @@ export async function sixHEX(html = '', posthtmlOptions = {}) {
|
|
|
27
25
|
return posthtml([
|
|
28
26
|
posthtmlPlugin()
|
|
29
27
|
])
|
|
30
|
-
.process(html,
|
|
28
|
+
.process(html, posthtmlOptions)
|
|
31
29
|
.then(result => result.html)
|
|
32
30
|
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
const posthtmlPlugin = () => tree => {
|
|
2
|
+
const process = node => {
|
|
3
|
+
// Return the original node if it doesn't have a tag
|
|
4
|
+
if (!node.tag) {
|
|
5
|
+
return node
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
if (node.tag === 'template') {
|
|
9
|
+
// Preserve <template> tags marked as such
|
|
10
|
+
if ('attrs' in node && 'preserve' in node.attrs) {
|
|
11
|
+
node.attrs.preserve = false
|
|
12
|
+
|
|
13
|
+
return node
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Remove the <template> tag
|
|
17
|
+
node.tag = false
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return node
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return tree.walk(process)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export default posthtmlPlugin
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import posthtml from 'posthtml'
|
|
2
2
|
import get from 'lodash-es/get.js'
|
|
3
|
-
import { defu as merge } from 'defu'
|
|
4
3
|
import urlParameters from 'posthtml-url-parameters'
|
|
5
|
-
import posthtmlConfig from '../posthtml/defaultConfig.js'
|
|
6
4
|
|
|
7
5
|
export default function posthtmlPlugin(options = {}) {
|
|
8
6
|
const { _options, ...parameters } = options
|
|
@@ -17,6 +15,6 @@ export async function addURLParams(html = '', options = {}, posthtmlOptions = {}
|
|
|
17
15
|
return posthtml([
|
|
18
16
|
posthtmlPlugin(options)
|
|
19
17
|
])
|
|
20
|
-
.process(html,
|
|
18
|
+
.process(html, posthtmlOptions)
|
|
21
19
|
.then(result => result.html)
|
|
22
20
|
}
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import postcss from 'postcss'
|
|
2
2
|
import posthtml from 'posthtml'
|
|
3
3
|
import get from 'lodash-es/get.js'
|
|
4
|
-
import { defu as merge } from 'defu'
|
|
5
|
-
import posthtmlConfig from '../posthtml/defaultConfig.js'
|
|
6
4
|
|
|
7
5
|
const posthtmlPlugin = (mappings = {}) => tree => {
|
|
8
6
|
if (!Object.keys(mappings).length) {
|
|
@@ -60,6 +58,6 @@ export async function useAttributeSizes(html = '', mappings = {}, posthtmlOption
|
|
|
60
58
|
return posthtml([
|
|
61
59
|
posthtmlPlugin(mappings)
|
|
62
60
|
])
|
|
63
|
-
.process(html,
|
|
61
|
+
.process(html, posthtmlOptions)
|
|
64
62
|
.then(result => result.html)
|
|
65
63
|
}
|
package/src/utils/string.js
CHANGED
|
@@ -115,3 +115,92 @@ export function humanFileSize(bytes, si=false, dp=2) {
|
|
|
115
115
|
|
|
116
116
|
return bytes.toFixed(dp) + ' ' + units[u]
|
|
117
117
|
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Get the root directories from a list of glob patterns.
|
|
121
|
+
*
|
|
122
|
+
* @param {array} patterns List of glob patterns.
|
|
123
|
+
* @returns {array} List of root directories.
|
|
124
|
+
*/
|
|
125
|
+
export function getRootDirectories(patterns = []) {
|
|
126
|
+
if (!Array.isArray(patterns)) {
|
|
127
|
+
return []
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (patterns.length === 0) {
|
|
131
|
+
return []
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return [...new Set(
|
|
135
|
+
patterns
|
|
136
|
+
.filter(pattern => !pattern.startsWith('!'))
|
|
137
|
+
.map(pattern => {
|
|
138
|
+
// If the pattern doesn't include wildcards, use it as is
|
|
139
|
+
if (!pattern.includes('*')) {
|
|
140
|
+
return pattern.replace(/\/$/, '') // Remove trailing slash if present
|
|
141
|
+
}
|
|
142
|
+
// For patterns with wildcards, get the part before the first wildcard
|
|
143
|
+
const parts = pattern.split(/[*{]/)[0].split('/')
|
|
144
|
+
return parts.slice(0, -1).join('/')
|
|
145
|
+
})
|
|
146
|
+
.filter(Boolean)
|
|
147
|
+
)]
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Get the file extensions from a glob pattern.
|
|
152
|
+
* @param {*} pattern
|
|
153
|
+
* @returns
|
|
154
|
+
*/
|
|
155
|
+
export function getFileExtensionsFromPattern(pattern) {
|
|
156
|
+
const starExtPattern = /\.([^\*\{\}]+)$/ // Matches .ext but not .* or .{ext}
|
|
157
|
+
const bracePattern = /\.{([^}]+)}$/ // Matches .{ext} or .{ext,ext}
|
|
158
|
+
const wildcardPattern = /\.\*$/ // Matches .*
|
|
159
|
+
|
|
160
|
+
if (wildcardPattern.test(pattern)) {
|
|
161
|
+
return ['html'] // We default to 'html' if the pattern is a wildcard
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const braceMatch = pattern.match(bracePattern);
|
|
165
|
+
if (braceMatch) {
|
|
166
|
+
return braceMatch[1].split(',') // Split and return extensions inside braces
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const starExtMatch = pattern.match(starExtPattern)
|
|
170
|
+
if (starExtMatch) {
|
|
171
|
+
return [starExtMatch[1]] // Return single extension
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return ['html'] // No recognizable extension pattern, default to 'html'
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export function parseCSSRule(rule) {
|
|
178
|
+
// Step 1: Trim the input string
|
|
179
|
+
rule = rule.trim()
|
|
180
|
+
|
|
181
|
+
// Step 2: Find the index of the first colon
|
|
182
|
+
const colonIndex = rule.indexOf(':')
|
|
183
|
+
|
|
184
|
+
// Step 3: Extract property and value parts
|
|
185
|
+
if (colonIndex === -1) {
|
|
186
|
+
return {
|
|
187
|
+
property: '',
|
|
188
|
+
value: ''
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const property = rule.slice(0, colonIndex).trim()
|
|
193
|
+
const value = rule.slice(colonIndex + 1).trim()
|
|
194
|
+
|
|
195
|
+
return { property, value }
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Normalize a string by removing extra whitespace.
|
|
200
|
+
*
|
|
201
|
+
* @param {String} str The string to clean
|
|
202
|
+
* @returns {String} The cleaned string
|
|
203
|
+
*/
|
|
204
|
+
export function cleanString(str) {
|
|
205
|
+
return str.replace(/\s+/g, ' ').trim()
|
|
206
|
+
}
|