@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,118 +1,219 @@
|
|
|
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
|
-
tag: false,
|
|
27
|
-
content: ['']
|
|
28
|
-
}
|
|
29
|
-
}
|
|
1
|
+
import path from 'pathe'
|
|
2
|
+
import posthtml from 'posthtml'
|
|
3
|
+
import get from 'lodash-es/get.js'
|
|
4
|
+
import { defu as merge } from 'defu'
|
|
5
|
+
import { stripHtml } from 'string-strip-html'
|
|
6
|
+
import defaultConfig from '../posthtml/defaultConfig.js'
|
|
7
|
+
import { writeFile, lstat, mkdir } from 'node:fs/promises'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Removes HTML tags from a given HTML string based on
|
|
11
|
+
* a specified tag name or an array of tag names.
|
|
12
|
+
*
|
|
13
|
+
* @param {Object} options - The options object.
|
|
14
|
+
* @param {string|string[]} [options.tag='not-plaintext'] - The tag name or an array of tag names to remove from the HTML.
|
|
15
|
+
* @param {string} [options.html=''] - The HTML string from which to remove the tags.
|
|
16
|
+
* @param {Object} [options.config={}] - PostHTML options.
|
|
17
|
+
* @returns {string} - The HTML string with the specified tags removed.
|
|
18
|
+
*/
|
|
19
|
+
const removeTags = ({ tag = 'not-plaintext', html = '', config = {} }) => {
|
|
20
|
+
/**
|
|
21
|
+
* If the HTML string is empty, return it as is
|
|
22
|
+
*/
|
|
23
|
+
if (!html) {
|
|
24
|
+
return html
|
|
25
|
+
}
|
|
30
26
|
|
|
27
|
+
const posthtmlPlugin = () => tree => {
|
|
28
|
+
const process = node => {
|
|
29
|
+
if (!node.tag) {
|
|
31
30
|
return node
|
|
32
31
|
}
|
|
33
32
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
const posthtmlPlugin = () => tree => {
|
|
43
|
-
const process = node => {
|
|
44
|
-
if (node.tag === 'plaintext') {
|
|
45
|
-
return {
|
|
46
|
-
tag: false,
|
|
47
|
-
content: ['']
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
if (node.tag === 'not-plaintext') {
|
|
52
|
-
return {
|
|
53
|
-
tag: false,
|
|
54
|
-
content: tree.render(node.content)
|
|
55
|
-
}
|
|
33
|
+
/**
|
|
34
|
+
* If the tag is a string and it matches the node tag, remove it
|
|
35
|
+
*/
|
|
36
|
+
if (node.tag === tag) {
|
|
37
|
+
return {
|
|
38
|
+
tag: false,
|
|
39
|
+
content: ['']
|
|
56
40
|
}
|
|
57
|
-
|
|
58
|
-
return node
|
|
59
41
|
}
|
|
60
42
|
|
|
61
|
-
return
|
|
43
|
+
return node
|
|
62
44
|
}
|
|
63
45
|
|
|
64
|
-
return
|
|
65
|
-
}
|
|
66
|
-
generate: async (html, destination, config = {}) => {
|
|
67
|
-
const configDestinationPath = get(config, 'destination.path')
|
|
68
|
-
const extension = get(config, 'destination.extension', 'txt')
|
|
46
|
+
return tree.walk(process)
|
|
47
|
+
}
|
|
69
48
|
|
|
70
|
-
|
|
49
|
+
const posthtmlOptions = merge(defaultConfig, config)
|
|
71
50
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
enabled: true
|
|
75
|
-
},
|
|
76
|
-
stripTogetherWithTheirContents: ['script', 'style', 'xml'],
|
|
77
|
-
...config
|
|
78
|
-
}).result
|
|
51
|
+
return posthtml([posthtmlPlugin()]).process(html, { ...posthtmlOptions }).then(res => res.html)
|
|
52
|
+
}
|
|
79
53
|
|
|
80
|
-
|
|
54
|
+
/**
|
|
55
|
+
* Handles custom <plaintext> tags and replaces their content based on the tag name.
|
|
56
|
+
*
|
|
57
|
+
* @param {Object} options - The options object.
|
|
58
|
+
* @param {string} [options.html=''] - The HTML string containing custom tags to be processed.
|
|
59
|
+
* @param {Object} [options.config={}] - PostHTML options.
|
|
60
|
+
* @returns {string} - The modified HTML string after processing custom tags.
|
|
61
|
+
*/
|
|
62
|
+
export async function handlePlaintextTags(html = '', config = {}) {
|
|
63
|
+
/**
|
|
64
|
+
* If the HTML string is empty, return early
|
|
65
|
+
*/
|
|
66
|
+
if (!html) {
|
|
67
|
+
return html
|
|
68
|
+
}
|
|
81
69
|
|
|
82
|
-
|
|
83
|
-
|
|
70
|
+
const posthtmlPlugin = () => tree => {
|
|
71
|
+
const process = node => {
|
|
84
72
|
/**
|
|
85
|
-
*
|
|
86
|
-
* no matter how many templates there are.
|
|
87
|
-
*
|
|
88
|
-
* It will be based on the last-processed template.
|
|
73
|
+
* Remove <plaintext> tags and their content from the HTML
|
|
89
74
|
*/
|
|
90
|
-
if (
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
75
|
+
if (node.tag === 'plaintext') {
|
|
76
|
+
return {
|
|
77
|
+
tag: false,
|
|
78
|
+
content: ['']
|
|
79
|
+
}
|
|
94
80
|
}
|
|
95
81
|
|
|
96
82
|
/**
|
|
97
|
-
*
|
|
83
|
+
* Replace <not-plaintext> tags with their content
|
|
98
84
|
*/
|
|
99
|
-
|
|
85
|
+
if (node.tag === 'not-plaintext') {
|
|
86
|
+
return {
|
|
87
|
+
tag: false,
|
|
88
|
+
content: tree.render(node.content)
|
|
89
|
+
}
|
|
90
|
+
}
|
|
100
91
|
|
|
101
|
-
return
|
|
92
|
+
return node
|
|
102
93
|
}
|
|
103
94
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
95
|
+
return tree.walk(process)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const posthtmlOptions = merge(defaultConfig, config)
|
|
99
|
+
|
|
100
|
+
return posthtml([posthtmlPlugin()]).process(html, { ...posthtmlOptions }).then(res => res.html)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Generate a plaintext representation from the provided HTML.
|
|
105
|
+
*
|
|
106
|
+
* @param {Object} options - The options object.
|
|
107
|
+
* @param {string} [options.html=''] - The HTML string to convert to plaintext.
|
|
108
|
+
* @param {Object} [options.config={}] - Configuration object.
|
|
109
|
+
* @returns {Promise<string>|void} - The generated plaintext as a string.
|
|
110
|
+
*/
|
|
111
|
+
export async function generatePlaintext(html = '', config = {}) {
|
|
112
|
+
const { posthtml: posthtmlOptions, ...stripOptions } = config
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Remove <not-plaintext> tags and their content from the HTML.
|
|
116
|
+
* `config` is an object containing PostHTML options.
|
|
117
|
+
*/
|
|
118
|
+
html = await removeTags({ tag: 'not-plaintext', html, config: posthtmlOptions })
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Return the plaintext representation from the stripped HTML.
|
|
122
|
+
* The `dumpLinkHrefsNearby` option is enabled by default.
|
|
123
|
+
*/
|
|
124
|
+
return stripHtml(
|
|
125
|
+
html,
|
|
126
|
+
merge(
|
|
127
|
+
stripOptions,
|
|
128
|
+
{
|
|
129
|
+
dumpLinkHrefsNearby: {
|
|
130
|
+
enabled: true,
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
)
|
|
134
|
+
).result
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export async function writePlaintextFile(plaintext = '', templateConfig = {}) {
|
|
138
|
+
if (!plaintext) {
|
|
139
|
+
throw new Error('Missing plaintext content.')
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if (typeof plaintext !== 'string') {
|
|
143
|
+
throw new Error('Plaintext content must be a string.')
|
|
144
|
+
}
|
|
109
145
|
|
|
110
|
-
|
|
111
|
-
|
|
146
|
+
/**
|
|
147
|
+
* Get plaintext output path config, i.e `config.plaintext.destination.path`
|
|
148
|
+
*
|
|
149
|
+
* Fall back to template's build output path and extension, for example:
|
|
150
|
+
* `config.build.output.path`
|
|
151
|
+
*/
|
|
152
|
+
const plaintextConfig = get(templateConfig, 'plaintext')
|
|
153
|
+
let plaintextOutputPath = get(plaintextConfig, 'output.path', get(templateConfig, 'build.output.path'))
|
|
154
|
+
const plaintextExtension = get(plaintextConfig, 'output.extension', 'txt')
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* If `plaintext: true` (either from Front Matter or from config)
|
|
158
|
+
*/
|
|
159
|
+
if (plaintextConfig === true) {
|
|
160
|
+
// If the template has a `permalink` key set in the FM
|
|
161
|
+
if (typeof templateConfig.permalink === 'string') {
|
|
162
|
+
// Output plaintext at the `permalink` path
|
|
163
|
+
plaintextOutputPath = templateConfig.permalink
|
|
164
|
+
} else {
|
|
165
|
+
// Output plaintext at the same directory as the HTML file
|
|
166
|
+
plaintextOutputPath = path.join(
|
|
167
|
+
get(templateConfig, 'build.output.path'),
|
|
168
|
+
get(templateConfig, 'build.current.relativePath')
|
|
169
|
+
)
|
|
112
170
|
}
|
|
171
|
+
}
|
|
113
172
|
|
|
114
|
-
|
|
173
|
+
/**
|
|
174
|
+
* If `plaintext: path/to/file.ext` in the FM
|
|
175
|
+
* Can't work if set in config.js as file path, because it would be the same for all templates
|
|
176
|
+
* We check later if it's a dir path, won't work if it's a file path
|
|
177
|
+
*/
|
|
178
|
+
if (typeof plaintextConfig === 'string') {
|
|
179
|
+
plaintextOutputPath = plaintextConfig
|
|
115
180
|
}
|
|
116
|
-
}
|
|
117
181
|
|
|
118
|
-
|
|
182
|
+
// No need to handle if it's an object, since we already set it to that initially
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* If `plaintextOutputPath` is a file path, output file there
|
|
186
|
+
*/
|
|
187
|
+
if (path.extname(plaintextOutputPath)) {
|
|
188
|
+
// Ensure the target directory exists
|
|
189
|
+
await lstat(path.dirname(plaintextOutputPath)).catch(async () => {
|
|
190
|
+
await mkdir(path.dirname(plaintextOutputPath), { recursive: true })
|
|
191
|
+
})
|
|
192
|
+
|
|
193
|
+
// Ensure correct extension is used
|
|
194
|
+
plaintextOutputPath = path.join(
|
|
195
|
+
path.dirname(plaintextOutputPath),
|
|
196
|
+
path.basename(plaintextOutputPath, path.extname(plaintextOutputPath)) + '.' + plaintextExtension
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
return writeFile(plaintextOutputPath, plaintext)
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* If `plaintextOutputPath` is a directory path, output file there, using the template's name
|
|
204
|
+
*/
|
|
205
|
+
const templateFileName = get(templateConfig, 'build.current.path.name')
|
|
206
|
+
|
|
207
|
+
plaintextOutputPath = path.join(
|
|
208
|
+
plaintextOutputPath,
|
|
209
|
+
get(templateConfig, 'build.current.path.dir'),
|
|
210
|
+
templateFileName + '.' + plaintextExtension
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
// Ensure the target directory exists
|
|
214
|
+
await lstat(path.dirname(plaintextOutputPath)).catch(async () => {
|
|
215
|
+
await mkdir(path.dirname(plaintextOutputPath), { recursive: true })
|
|
216
|
+
})
|
|
217
|
+
|
|
218
|
+
return writeFile(plaintextOutputPath, plaintext)
|
|
219
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { parse } from 'pathe'
|
|
2
|
+
import posthtml from 'posthtml'
|
|
3
|
+
import { cwd } from 'node:process'
|
|
4
|
+
import { defu as merge } from 'defu'
|
|
5
|
+
import expressions from 'posthtml-expressions'
|
|
6
|
+
import { parseFrontMatter } from '../utils/node.js'
|
|
7
|
+
import { process as compilePostHTML } from '../posthtml/index.js'
|
|
8
|
+
import { run as useTransformers } from '../transformers/index.js'
|
|
9
|
+
|
|
10
|
+
export async function render(html = '', config = {}) {
|
|
11
|
+
if (typeof html !== 'string') {
|
|
12
|
+
throw new TypeError(`first argument must be a string, received ${html}`)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if (html.length === 0) {
|
|
16
|
+
throw new RangeError('received empty string')
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Parse front matter
|
|
21
|
+
*
|
|
22
|
+
* Parse expressions in front matter and add to config
|
|
23
|
+
* This could be handled by components() but plugins aren't working with it currently
|
|
24
|
+
*/
|
|
25
|
+
let { content, matter } = parseFrontMatter(html)
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Compute template config
|
|
29
|
+
*
|
|
30
|
+
* Merge it with front matter data and set the `cwd` for Tailwind.
|
|
31
|
+
*/
|
|
32
|
+
const { data: matterData } = await posthtml(
|
|
33
|
+
[
|
|
34
|
+
expressions({
|
|
35
|
+
strictMode: false,
|
|
36
|
+
missingLocal: '{local}',
|
|
37
|
+
locals: {
|
|
38
|
+
page: config
|
|
39
|
+
}
|
|
40
|
+
})
|
|
41
|
+
]
|
|
42
|
+
)
|
|
43
|
+
.process(matter)
|
|
44
|
+
.then(({ html }) => parseFrontMatter(`---${html}\n---`))
|
|
45
|
+
|
|
46
|
+
const templateConfig = merge(matterData, config)
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Used for PostCSS `from` to make `@config` work in Tailwind
|
|
50
|
+
*
|
|
51
|
+
* @todo use only when in Node environment
|
|
52
|
+
*/
|
|
53
|
+
templateConfig.cwd = parse(cwd()).base
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Run `beforeRender` event
|
|
57
|
+
*
|
|
58
|
+
* @param {Object} options
|
|
59
|
+
* @param {string} options.html - The HTML to be transformed
|
|
60
|
+
* @param {Object} options.config - The current template config
|
|
61
|
+
* @param {function} options.render - The render function
|
|
62
|
+
* @returns {string} - The transformed HTML, or the original one if nothing was returned
|
|
63
|
+
*/
|
|
64
|
+
if (typeof templateConfig.beforeRender === 'function') {
|
|
65
|
+
content = await templateConfig.beforeRender(({
|
|
66
|
+
html: content,
|
|
67
|
+
config: templateConfig,
|
|
68
|
+
render
|
|
69
|
+
})) ?? content
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Compile PostHTML
|
|
73
|
+
const compiled = await compilePostHTML(content, templateConfig)
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Run `afterRender` event
|
|
77
|
+
*
|
|
78
|
+
* @param {Object} options
|
|
79
|
+
* @param {string} options.html - The HTML to be transformed
|
|
80
|
+
* @param {Object} options.config - The current template config
|
|
81
|
+
* @param {function} options.render - The render function
|
|
82
|
+
* @returns {string} - The transformed HTML, or the original one if nothing was returned
|
|
83
|
+
*/
|
|
84
|
+
if (typeof templateConfig.afterRender === 'function') {
|
|
85
|
+
compiled.html = await templateConfig.afterRender(({
|
|
86
|
+
html: compiled.html,
|
|
87
|
+
config: templateConfig,
|
|
88
|
+
render
|
|
89
|
+
})) ?? compiled.html
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Run Transformers
|
|
93
|
+
/**
|
|
94
|
+
* Run Transformers
|
|
95
|
+
*
|
|
96
|
+
* Runs only if `useTransformers` is not explicitly disabled in the config.
|
|
97
|
+
*
|
|
98
|
+
* @param {string} html - The HTML to be transformed
|
|
99
|
+
* @param {Object} config - The current template config
|
|
100
|
+
* @returns {string} - The transformed HTML
|
|
101
|
+
*/
|
|
102
|
+
if (templateConfig.useTransformers !== false) {
|
|
103
|
+
compiled.html = await useTransformers(compiled.html, templateConfig).then(({ html }) => html)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Run `afterTransformers` event
|
|
107
|
+
/**
|
|
108
|
+
* Run `afterTransformers` event
|
|
109
|
+
*
|
|
110
|
+
* @param {Object} options
|
|
111
|
+
* @param {string} options.html - The HTML to be transformed
|
|
112
|
+
* @param {Object} options.config - The current template config
|
|
113
|
+
* @param {function} options.render - The render function
|
|
114
|
+
* @returns {string} - The transformed HTML, or the original one if nothing was returned
|
|
115
|
+
*/
|
|
116
|
+
if (typeof templateConfig.afterTransformers === 'function') {
|
|
117
|
+
compiled.html = await templateConfig.afterTransformers(({
|
|
118
|
+
html: compiled.html,
|
|
119
|
+
config: templateConfig,
|
|
120
|
+
render
|
|
121
|
+
})) ?? compiled.html
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return {
|
|
125
|
+
config: templateConfig,
|
|
126
|
+
html: compiled.html,
|
|
127
|
+
}
|
|
128
|
+
}
|
package/src/index.js
CHANGED
|
@@ -1,17 +1,49 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const toString = require('./functions/render')
|
|
5
|
-
const PostCSS = require('./generators/postcss')
|
|
6
|
-
const toPlaintext = require('./functions/plaintext')
|
|
7
|
-
const TailwindCSS = require('./generators/tailwindcss')
|
|
1
|
+
import serve from './server/index.js'
|
|
2
|
+
import build from './commands/build.js'
|
|
3
|
+
import { render } from './generators/render.js'
|
|
8
4
|
|
|
9
|
-
|
|
5
|
+
import { addAttributes } from './transformers/addAttributes.js'
|
|
6
|
+
import { attributeToStyle } from './transformers/attributeToStyle.js'
|
|
7
|
+
import { addBaseUrl } from './transformers/baseUrl.js'
|
|
8
|
+
import { comb } from './transformers/comb.js'
|
|
9
|
+
import { filters } from './transformers/filters/index.js'
|
|
10
|
+
import { inline } from './transformers/inline.js'
|
|
11
|
+
import { markdown } from './transformers/markdown.js'
|
|
12
|
+
import { minify } from './transformers/minify.js'
|
|
13
|
+
import { useMso } from './transformers/posthtmlMso.js'
|
|
14
|
+
import { prettify } from './transformers/prettify.js'
|
|
15
|
+
import { removeAttributes } from './transformers/removeAttributes.js'
|
|
16
|
+
import { replaceStrings } from './transformers/replaceStrings.js'
|
|
17
|
+
import { safeClassNames } from './transformers/safeClassNames.js'
|
|
18
|
+
import { shorthandCSS } from './transformers/shorthandCss.js'
|
|
19
|
+
import { sixHEX } from './transformers/sixHex.js'
|
|
20
|
+
import { addURLParams } from './transformers/urlParameters.js'
|
|
21
|
+
import { useAttributeSizes } from './transformers/useAttributeSizes.js'
|
|
22
|
+
import { preventWidows } from './transformers/preventWidows.js'
|
|
23
|
+
import { generatePlaintext } from './generators/plaintext.js'
|
|
24
|
+
|
|
25
|
+
export {
|
|
26
|
+
build,
|
|
10
27
|
serve,
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
28
|
+
render,
|
|
29
|
+
addAttributes,
|
|
30
|
+
attributeToStyle,
|
|
31
|
+
addBaseUrl,
|
|
32
|
+
comb as removeUnusedCSS,
|
|
33
|
+
comb as purgeCSS,
|
|
34
|
+
filters,
|
|
35
|
+
inline as inlineCSS,
|
|
36
|
+
markdown,
|
|
37
|
+
minify,
|
|
38
|
+
useMso,
|
|
39
|
+
prettify,
|
|
40
|
+
removeAttributes,
|
|
41
|
+
replaceStrings,
|
|
42
|
+
safeClassNames,
|
|
43
|
+
shorthandCSS,
|
|
44
|
+
sixHEX,
|
|
45
|
+
addURLParams,
|
|
46
|
+
useAttributeSizes,
|
|
47
|
+
preventWidows,
|
|
48
|
+
generatePlaintext,
|
|
17
49
|
}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
|
|
1
|
+
export default {
|
|
2
2
|
root: './',
|
|
3
3
|
folders: ['src/components', 'src/layouts', 'src/templates'],
|
|
4
4
|
fileExtension: 'html',
|
|
5
5
|
tag: 'component',
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
expressions: {
|
|
7
|
+
loopTags: ['each', 'for'],
|
|
8
|
+
missingLocal: '{local}',
|
|
9
|
+
strictMode: false,
|
|
10
|
+
},
|
|
9
11
|
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import get from 'lodash-es/get.js'
|
|
2
|
+
import { defu as merge } from 'defu'
|
|
3
|
+
|
|
4
|
+
// PostHTML
|
|
5
|
+
import posthtml from 'posthtml'
|
|
6
|
+
import components from 'posthtml-component'
|
|
7
|
+
import posthtmlPostcss from 'posthtml-postcss'
|
|
8
|
+
import defaultPosthtmlConfig from './defaultConfig.js'
|
|
9
|
+
import expandLinkTag from './plugins/expandLinkTag.js'
|
|
10
|
+
|
|
11
|
+
// PostCSS
|
|
12
|
+
import tailwindcss from 'tailwindcss'
|
|
13
|
+
import postcssImport from 'postcss-import'
|
|
14
|
+
import postcssSafeParser from 'postcss-safe-parser'
|
|
15
|
+
import customProperties from 'postcss-custom-properties'
|
|
16
|
+
|
|
17
|
+
import defaultComponentsConfig from './defaultComponentsConfig.js'
|
|
18
|
+
|
|
19
|
+
export async function process(html = '', config = {}) {
|
|
20
|
+
const postcssPlugin = posthtmlPostcss(
|
|
21
|
+
[
|
|
22
|
+
postcssImport(),
|
|
23
|
+
tailwindcss(get(config, 'css.tailwind', {})),
|
|
24
|
+
get(config, 'css.inline.resolveCSSVariables', true) && customProperties(),
|
|
25
|
+
...get(config, 'postcss.plugins', []),
|
|
26
|
+
],
|
|
27
|
+
merge(
|
|
28
|
+
get(config, 'postcss.options', {}),
|
|
29
|
+
{
|
|
30
|
+
from: config.cwd || './',
|
|
31
|
+
parser: postcssSafeParser
|
|
32
|
+
}
|
|
33
|
+
)
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
const posthtmlOptions = merge(get(config, 'posthtml.options', {}), defaultPosthtmlConfig)
|
|
37
|
+
|
|
38
|
+
const componentsUserOptions = get(config, 'components', {})
|
|
39
|
+
|
|
40
|
+
const expressionsOptions = merge(
|
|
41
|
+
get(config, 'build.expressions', get(config, 'posthtml.expressions', {})),
|
|
42
|
+
get(componentsUserOptions, 'expressions', {}),
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
const locals = merge(
|
|
46
|
+
get(config, 'locals', {}),
|
|
47
|
+
get(expressionsOptions, 'locals', {}),
|
|
48
|
+
{ page: config },
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
return posthtml([
|
|
52
|
+
...get(config, 'posthtml.plugins.before', []),
|
|
53
|
+
expandLinkTag,
|
|
54
|
+
postcssPlugin,
|
|
55
|
+
components(
|
|
56
|
+
merge({
|
|
57
|
+
expressions: {
|
|
58
|
+
locals,
|
|
59
|
+
}
|
|
60
|
+
}, defaultComponentsConfig)
|
|
61
|
+
),
|
|
62
|
+
expandLinkTag,
|
|
63
|
+
postcssPlugin,
|
|
64
|
+
...get(config, 'posthtml.plugins.after', get(config, 'posthtml.plugins', []))
|
|
65
|
+
])
|
|
66
|
+
.process(html, posthtmlOptions)
|
|
67
|
+
.then(result => ({
|
|
68
|
+
config,
|
|
69
|
+
html: result.html,
|
|
70
|
+
}))
|
|
71
|
+
.catch(error => {
|
|
72
|
+
throw error
|
|
73
|
+
})
|
|
74
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import fs from 'node:fs'
|
|
2
|
+
|
|
3
|
+
const targets = new Set(['expand', 'inline'])
|
|
4
|
+
|
|
5
|
+
// TODO: refactor to a Promise so we can use async readFile
|
|
6
|
+
const plugin = (() => tree => {
|
|
7
|
+
const process = node => {
|
|
8
|
+
/**
|
|
9
|
+
* Don't expand link tags that are not explicitly marked as such
|
|
10
|
+
*/
|
|
11
|
+
if (node.attrs && ![...targets].some(attr => attr in node.attrs)) {
|
|
12
|
+
for (const attr of targets) {
|
|
13
|
+
node.attrs[attr] = false
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return node
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (
|
|
20
|
+
node.tag === 'link'
|
|
21
|
+
&& node.attrs
|
|
22
|
+
&& node.attrs.href
|
|
23
|
+
&& node.attrs.rel === 'stylesheet'
|
|
24
|
+
) {
|
|
25
|
+
node.content = [fs.readFileSync(node.attrs.href, 'utf8')]
|
|
26
|
+
node.tag = 'style'
|
|
27
|
+
node.attrs = {}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return node
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return tree.walk(process)
|
|
34
|
+
})()
|
|
35
|
+
|
|
36
|
+
export default plugin
|