@maizzle/framework 5.0.0-beta.9 → 5.0.1

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 (47) hide show
  1. package/package.json +32 -30
  2. package/src/commands/build.js +106 -30
  3. package/src/generators/plaintext.js +22 -18
  4. package/src/generators/render.js +16 -18
  5. package/src/index.js +3 -3
  6. package/src/posthtml/defaultComponentsConfig.js +10 -2
  7. package/src/posthtml/defaultConfig.js +13 -3
  8. package/src/posthtml/index.js +59 -14
  9. package/src/server/index.js +171 -98
  10. package/src/server/routes/hmr.js +14 -13
  11. package/src/server/routes/index.js +51 -13
  12. package/src/server/views/404.html +59 -0
  13. package/src/server/views/index.html +162 -14
  14. package/src/transformers/addAttributes.js +2 -3
  15. package/src/transformers/attributeToStyle.js +1 -3
  16. package/src/transformers/baseUrl.js +6 -6
  17. package/src/transformers/filters/index.js +1 -2
  18. package/src/transformers/index.js +57 -95
  19. package/src/transformers/inline.js +44 -48
  20. package/src/transformers/markdown.js +14 -7
  21. package/src/transformers/minify.js +4 -3
  22. package/src/transformers/posthtmlMso.js +1 -3
  23. package/src/transformers/prettify.js +4 -3
  24. package/src/transformers/preventWidows.js +15 -65
  25. package/src/transformers/{comb.js → purge.js} +9 -8
  26. package/src/transformers/removeAttributes.js +3 -4
  27. package/src/transformers/replaceStrings.js +7 -5
  28. package/src/transformers/safeClassNames.js +1 -2
  29. package/src/transformers/shorthandCss.js +1 -3
  30. package/src/transformers/sixHex.js +1 -3
  31. package/src/transformers/template.js +9 -9
  32. package/src/transformers/urlParameters.js +1 -3
  33. package/src/transformers/useAttributeSizes.js +1 -3
  34. package/src/utils/getConfigByFilePath.js +10 -0
  35. package/src/utils/node.js +0 -23
  36. package/src/utils/string.js +34 -12
  37. package/types/build.d.ts +51 -28
  38. package/types/config.d.ts +127 -64
  39. package/types/css/inline.d.ts +10 -26
  40. package/types/css/purge.d.ts +3 -3
  41. package/types/events.d.ts +153 -5
  42. package/types/index.d.ts +4 -3
  43. package/types/posthtml.d.ts +3 -3
  44. package/types/urlParameters.d.ts +1 -1
  45. package/types/widowWords.d.ts +16 -36
  46. package/types/components.d.ts +0 -195
  47. package/types/expressions.d.ts +0 -100
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@maizzle/framework",
3
- "version": "5.0.0-beta.9",
3
+ "version": "5.0.1",
4
4
  "description": "Maizzle is a framework that helps you quickly build HTML emails with Tailwind CSS.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -48,58 +48,60 @@
48
48
  "html-emails"
49
49
  ],
50
50
  "dependencies": {
51
- "@csstools/css-calc": "^1.2.4",
52
- "@maizzle/cli": "next",
53
- "cheerio": "^1.0.0-rc.12",
51
+ "@maizzle/cli": "^2.0.0",
52
+ "cheerio": "^1.0.0",
54
53
  "chokidar": "^3.6.0",
55
54
  "cli-table3": "^0.6.5",
56
55
  "color-shorthand-hex-to-six-digit": "^5.0.16",
57
56
  "defu": "^6.1.4",
58
57
  "email-comb": "^7.0.21",
59
- "express": "^4.19.2",
58
+ "express": "^4.21.0",
60
59
  "fast-glob": "^3.3.2",
61
60
  "gray-matter": "^4.0.3",
62
- "html-crush": "^6.0.18",
61
+ "html-crush": "^6.0.19",
63
62
  "is-url-superb": "^6.1.0",
64
63
  "istextorbinary": "^9.5.0",
65
- "juice": "^10.0.0",
64
+ "juice": "^11.0.0",
66
65
  "lodash-es": "^4.17.21",
67
66
  "morphdom": "^2.7.4",
68
- "ora": "^8.0.1",
69
- "pathe": "^1.1.2",
70
- "postcss": "^8.4.39",
71
- "postcss-custom-properties": "^13.3.12",
67
+ "ora": "^8.1.0",
68
+ "pathe": "^2.0.0",
69
+ "postcss": "^8.4.49",
70
+ "postcss-calc": "^10.0.2",
71
+ "postcss-css-variables": "^0.19.0",
72
72
  "postcss-import": "^16.1.0",
73
73
  "postcss-safe-parser": "^7.0.0",
74
74
  "posthtml": "^0.16.6",
75
- "posthtml-attrs-parser": "^1.1.0",
75
+ "posthtml-attrs-parser": "^1.1.1",
76
76
  "posthtml-base-url": "^3.1.4",
77
- "posthtml-component": "^1.1.0",
78
- "posthtml-content": "^2.0.1",
79
- "posthtml-extra-attributes": "^3.0.0",
80
- "posthtml-markdownit": "^3.0.1",
81
- "posthtml-mso": "^3.0.0",
82
- "posthtml-parser": "^0.12.0",
83
- "posthtml-postcss": "^1.0.0",
84
- "posthtml-postcss-merge-longhand": "^3.1.0",
77
+ "posthtml-component": "^2.1.0",
78
+ "posthtml-content": "^2.1.0",
79
+ "posthtml-expressions": "^1.11.4",
80
+ "posthtml-extra-attributes": "^3.1.0",
81
+ "posthtml-fetch": "^4.0.0",
82
+ "posthtml-markdownit": "^3.1.0",
83
+ "posthtml-mso": "^3.1.0",
84
+ "posthtml-parser": "^0.12.1",
85
+ "posthtml-postcss": "^1.0.2",
86
+ "posthtml-postcss-merge-longhand": "^3.1.2",
85
87
  "posthtml-render": "^3.0.0",
86
- "posthtml-safe-class-names": "^4.0.2",
87
- "posthtml-url-parameters": "^3.0.0",
88
+ "posthtml-safe-class-names": "^4.1.0",
89
+ "posthtml-url-parameters": "^3.1.0",
90
+ "posthtml-widows": "^1.0.0",
88
91
  "pretty": "^2.0.0",
89
- "string-remove-widows": "^4.0.22",
90
92
  "string-strip-html": "^13.4.8",
91
- "tailwindcss": "^3.4.5",
92
- "ws": "^8.17.0"
93
+ "tailwindcss": "^3.4.16",
94
+ "ws": "^8.18.0"
93
95
  },
94
96
  "devDependencies": {
95
- "@biomejs/biome": "1.8.3",
97
+ "@biomejs/biome": "1.9.2",
96
98
  "@types/js-beautify": "^1.14.3",
97
- "@types/markdown-it": "^14.1.1",
98
- "@vitest/coverage-v8": "^2.0.1",
99
+ "@types/markdown-it": "^14.1.2",
100
+ "@vitest/coverage-v8": "^3.0.4",
99
101
  "supertest": "^7.0.0",
100
- "vitest": "^2.0.1"
102
+ "vitest": "^3.0.3"
101
103
  },
102
104
  "engines": {
103
- "node": ">=18.0.0"
105
+ "node": ">=18.20"
104
106
  }
105
107
  }
@@ -1,9 +1,11 @@
1
1
  import {
2
2
  readFile,
3
3
  writeFile,
4
+ copyFile,
4
5
  lstat,
5
6
  mkdir,
6
- rm
7
+ rm,
8
+ cp,
7
9
  } from 'node:fs/promises'
8
10
  import path from 'pathe'
9
11
  import fg from 'fast-glob'
@@ -24,10 +26,7 @@ import {
24
26
  getFileExtensionsFromPattern,
25
27
  } from '../utils/string.js'
26
28
 
27
- import {
28
- getColorizedFileSize,
29
- copyDirectory,
30
- } from '../utils/node.js'
29
+ import { getColorizedFileSize } from '../utils/node.js'
31
30
 
32
31
  import {
33
32
  generatePlaintext,
@@ -37,7 +36,26 @@ import {
37
36
 
38
37
  import { readFileConfig } from '../utils/getConfigByFilePath.js'
39
38
 
40
- import { transformers } from '../transformers/index.js'
39
+ /**
40
+ * Ensures that a directory exists, creating it if needed.
41
+ *
42
+ * @param {string} filePath - The path to the file to check.
43
+ */
44
+ async function ensureDirectoryExistence(filePath) {
45
+ const dirname = path.dirname(filePath)
46
+ await mkdir(dirname, { recursive: true })
47
+ }
48
+
49
+ /**
50
+ * Copy a file from source to target.
51
+ *
52
+ * @param {string} source - The source file path.
53
+ * @param {string} target - The target file path.
54
+ */
55
+ async function copyFileAsync(source, target) {
56
+ await ensureDirectoryExistence(target)
57
+ await copyFile(source, target)
58
+ }
41
59
 
42
60
  /**
43
61
  * Compile templates and output to the build directory.
@@ -52,7 +70,10 @@ export default async (config = {}) => {
52
70
  try {
53
71
  const startTime = Date.now()
54
72
 
55
- // Compute config
73
+ /**
74
+ * Read the config file for this environment,
75
+ * merging it with the default config.
76
+ */
56
77
  config = await readFileConfig(config).catch(() => { throw new Error('Could not compute config') })
57
78
 
58
79
  /**
@@ -84,17 +105,10 @@ export default async (config = {}) => {
84
105
  })
85
106
 
86
107
  /**
87
- * Determine paths to handle
88
- *
89
- * 1. Resolve globs in `build.content` to folders that should be copied over to `build.output.path`
90
- * 2. Check that templates to be built, actually exist
108
+ * Check that templates to be built, actually exist
91
109
  */
92
- const contentPaths = get(config, 'build.content', 'src/templates/**/*.html')
93
-
94
- // 1. Resolve globs in `build.content` to folders that should be copied over to `build.output.path`
95
- const rootDirs = await getRootDirectories(contentPaths)
110
+ const contentPaths = get(config, 'build.content', ['src/templates/**/*.html'])
96
111
 
97
- // 2. Check that templates to be built, actually exist
98
112
  const templateFolders = Array.isArray(contentPaths) ? contentPaths : [contentPaths]
99
113
  const templatePaths = await fg.glob([...new Set(templateFolders)])
100
114
 
@@ -108,8 +122,48 @@ export default async (config = {}) => {
108
122
  *
109
123
  * Copies each `build.content` path to the `build.output.path` directory.
110
124
  */
111
- for await (const rootDir of rootDirs) {
112
- await copyDirectory(rootDir, buildOutputPath)
125
+ let from = get(config, 'build.output.from', ['src/templates', 'src'])
126
+
127
+ const globPathsToCopy = contentPaths.map(glob => {
128
+ // Keep negated paths as they are
129
+ if (glob.startsWith('!')) {
130
+ return glob
131
+ }
132
+
133
+ // Keep single-file sources as they are
134
+ if (!/\*/.test(glob)) {
135
+ return glob
136
+ }
137
+
138
+ // Update non-negated paths to target all files, avoiding duplication
139
+ return glob.replace(/\/\*\*\/\*\.\{.*?\}$|\/\*\*\/\*\.[^/]*$|\/*\.[^/]*$/, '/**/*')
140
+ })
141
+
142
+ try {
143
+ from = Array.isArray(from) ? from : [from]
144
+
145
+ /**
146
+ * Copy files from source to destination
147
+ *
148
+ * The array/set conversion is to remove duplicates
149
+ */
150
+ for (const file of await fg(Array.from(new Set(globPathsToCopy)))) {
151
+ let relativePath
152
+ for (const dir of from) {
153
+ if (file.startsWith(dir)) {
154
+ relativePath = path.relative(dir, file)
155
+ break
156
+ }
157
+ }
158
+ if (!relativePath) {
159
+ relativePath = path.relative('.', file)
160
+ }
161
+
162
+ const targetPath = path.join(buildOutputPath, relativePath)
163
+ await copyFileAsync(file, targetPath)
164
+ }
165
+ } catch (error) {
166
+ console.error('Error while processing pattern:', error)
113
167
  }
114
168
 
115
169
  /**
@@ -121,13 +175,15 @@ export default async (config = {}) => {
121
175
  const outputExtensions = new Set()
122
176
 
123
177
  for (const pattern of contentPaths) {
124
- outputExtensions.add(...getFileExtensionsFromPattern(pattern))
178
+ getFileExtensionsFromPattern(pattern).map(ext => outputExtensions.add(ext))
125
179
  }
126
180
 
127
181
  /**
128
182
  * Create a list of templates to compile
129
183
  */
130
- const extensions = outputExtensions.size > 1 ? `{${[...outputExtensions].join(',')}}` : 'html'
184
+ const extensions = outputExtensions.size > 1
185
+ ? `{${[...outputExtensions].join(',')}}`
186
+ : [...outputExtensions][0] || 'html'
131
187
 
132
188
  const templatesToCompile = await fg.glob(
133
189
  path.join(
@@ -154,7 +210,26 @@ export default async (config = {}) => {
154
210
 
155
211
  const html = await readFile(templatePath, 'utf8')
156
212
 
157
- const rendered = await render(html, config)
213
+ /**
214
+ * Render the markup.
215
+ *
216
+ * Merging a custom `components` object to make sure that file extensions from both
217
+ * `build.content` * and * `components.fileExtension` are used when scanning for
218
+ * component files.
219
+ */
220
+ const userComponentFileExtensions = get(config, 'components.fileExtension', ['html'])
221
+
222
+ const rendered = await render(html, merge(
223
+ {
224
+ components: {
225
+ fileExtension: [
226
+ ...outputExtensions,
227
+ ...(new Set([].concat(userComponentFileExtensions))),
228
+ ],
229
+ }
230
+ },
231
+ config
232
+ ))
158
233
 
159
234
  /**
160
235
  * Generate plaintext
@@ -167,12 +242,14 @@ export default async (config = {}) => {
167
242
  if (Boolean(plaintextConfig) || !isEmpty(plaintextConfig)) {
168
243
  const posthtmlOptions = get(rendered.config, 'posthtml.options', {})
169
244
 
170
- const plaintext = await generatePlaintext(rendered.html, merge(plaintextConfig, posthtmlOptions))
245
+ await writePlaintextFile(
246
+ await generatePlaintext(rendered.html, merge(plaintextConfig, posthtmlOptions)),
247
+ rendered.config
248
+ ).catch(error => {
249
+ throw new Error(`Error writing plaintext file: ${error}`)
250
+ })
251
+
171
252
  rendered.html = await handlePlaintextTags(rendered.html, posthtmlOptions)
172
- await writePlaintextFile(plaintext, rendered.config)
173
- .catch(error => {
174
- throw new Error(`Error writing plaintext file: ${error}`)
175
- })
176
253
  }
177
254
 
178
255
  /**
@@ -225,10 +302,10 @@ export default async (config = {}) => {
225
302
  * TODO: support an array of objects with source and destination,
226
303
  * i.e. static: [{ source: 'src/assets', destination: 'assets' }, ...]
227
304
  */
228
- const staticSourcePaths = await fg.glob([...new Set(get(config, 'build.static.source', []))])
305
+ const staticSourcePaths = getRootDirectories([...new Set(get(config, 'build.static.source', []))])
229
306
 
230
- for await (const rootDir of getRootDirectories(staticSourcePaths)) {
231
- await copyDirectory(rootDir, path.join(buildOutputPath, get(config, 'build.static.destination')))
307
+ for await (const rootDir of staticSourcePaths) {
308
+ await cp(rootDir, path.join(buildOutputPath, get(config, 'build.static.destination')), { recursive: true })
232
309
  }
233
310
 
234
311
  const allOutputFiles = await fg.glob(path.join(buildOutputPath, '**/*'))
@@ -240,7 +317,6 @@ export default async (config = {}) => {
240
317
  await config.afterBuild({
241
318
  config,
242
319
  files: allOutputFiles,
243
- transform: transformers,
244
320
  })
245
321
  }
246
322
 
@@ -3,8 +3,8 @@ import posthtml from 'posthtml'
3
3
  import get from 'lodash-es/get.js'
4
4
  import { defu as merge } from 'defu'
5
5
  import { stripHtml } from 'string-strip-html'
6
- import defaultConfig from '../posthtml/defaultConfig.js'
7
6
  import { writeFile, lstat, mkdir } from 'node:fs/promises'
7
+ import { getPosthtmlOptions } from '../posthtml/defaultConfig.js'
8
8
 
9
9
  /**
10
10
  * Removes HTML tags from a given HTML string based on
@@ -46,7 +46,7 @@ const removeTags = ({ tag = 'not-plaintext', html = '', config = {} }) => {
46
46
  return tree.walk(process)
47
47
  }
48
48
 
49
- const posthtmlOptions = merge(defaultConfig, config)
49
+ const posthtmlOptions = merge(config, getPosthtmlOptions())
50
50
 
51
51
  return posthtml([posthtmlPlugin()]).process(html, { ...posthtmlOptions }).then(res => res.html)
52
52
  }
@@ -95,7 +95,7 @@ export async function handlePlaintextTags(html = '', config = {}) {
95
95
  return tree.walk(process)
96
96
  }
97
97
 
98
- const posthtmlOptions = merge(defaultConfig, config)
98
+ const posthtmlOptions = merge(config, getPosthtmlOptions())
99
99
 
100
100
  return posthtml([posthtmlPlugin()]).process(html, { ...posthtmlOptions }).then(res => res.html)
101
101
  }
@@ -154,17 +154,11 @@ export async function writePlaintextFile(plaintext = '', config = {}) {
154
154
  const plaintextExtension = get(plaintextConfig, 'output.extension', 'txt')
155
155
 
156
156
  /**
157
- * If `plaintext: true` (either from Front Matter or from config)
157
+ * If `plaintext: true` (either from Front Matter or from config),
158
+ * output plaintext file in the same location as the HTML file.
158
159
  */
159
160
  if (plaintextConfig === true) {
160
- // If the template has a `permalink` key set in the FM
161
- if (typeof config.permalink === 'string') {
162
- // Output plaintext at the `permalink` path
163
- plaintextOutputPath = config.permalink
164
- } else {
165
- // Output plaintext at the same directory as the HTML file
166
- plaintextOutputPath = get(config, 'build.output.path')
167
- }
161
+ plaintextOutputPath = get(config, 'build.output.path')
168
162
  }
169
163
 
170
164
  /**
@@ -179,12 +173,22 @@ export async function writePlaintextFile(plaintext = '', config = {}) {
179
173
  // No need to handle if it's an object, since we already set it to that initially
180
174
 
181
175
  /**
182
- * If `plaintextOutputPath` is a file path, output file there
176
+ * If the template has a `permalink` key set in the FM, always output plaintext file there
177
+ */
178
+ if (typeof config.permalink === 'string') {
179
+ plaintextOutputPath = config.permalink
180
+ }
181
+
182
+ /**
183
+ * If `plaintextOutputPath` is a file path, output file there.
184
+ *
185
+ * The file will be output relative to the project root, and the extension
186
+ * doesn't matter, it will be replaced with `plaintextExtension`.
183
187
  */
184
188
  if (path.extname(plaintextOutputPath)) {
185
189
  // Ensure the target directory exists
186
190
  await lstat(plaintextOutputPath).catch(async () => {
187
- await mkdir(plaintextOutputPath, { recursive: true })
191
+ await mkdir(path.dirname(plaintextOutputPath), { recursive: true })
188
192
  })
189
193
 
190
194
  // Ensure correct extension is used
@@ -193,19 +197,19 @@ export async function writePlaintextFile(plaintext = '', config = {}) {
193
197
  path.basename(plaintextOutputPath, path.extname(plaintextOutputPath)) + '.' + plaintextExtension
194
198
  )
195
199
 
196
- console.log('plaintextOutputPath', plaintextOutputPath);
197
-
198
200
  return writeFile(plaintextOutputPath, plaintext)
199
201
  }
200
202
 
201
203
  /**
202
- * If `plaintextOutputPath` is a directory path, output file there, using the template's name
204
+ * If `plaintextOutputPath` is a directory path, output file there using the Template's name.
205
+ *
206
+ * The file will be output relative to the `build.output.path` directory.
203
207
  */
204
208
  const templateFileName = get(config, 'build.current.path.name')
205
209
 
206
210
  plaintextOutputPath = path.join(
207
- path.dirname(plaintextOutputPath),
208
211
  get(config, 'build.current.path.dir'),
212
+ plaintextOutputPath,
209
213
  templateFileName + '.' + plaintextExtension
210
214
  )
211
215
 
@@ -4,8 +4,9 @@ import { cwd } from 'node:process'
4
4
  import { defu as merge } from 'defu'
5
5
  import expressions from 'posthtml-expressions'
6
6
  import { parseFrontMatter } from '../utils/node.js'
7
+ import { getPosthtmlOptions } from '../posthtml/defaultConfig.js'
7
8
  import { process as compilePostHTML } from '../posthtml/index.js'
8
- import { run as useTransformers, transformers } from '../transformers/index.js'
9
+ import { run as useTransformers } from '../transformers/index.js'
9
10
 
10
11
  export async function render(html = '', config = {}) {
11
12
  if (typeof html !== 'string') {
@@ -40,7 +41,7 @@ export async function render(html = '', config = {}) {
40
41
  })
41
42
  ]
42
43
  )
43
- .process(matter)
44
+ .process(matter, getPosthtmlOptions())
44
45
  .then(({ html }) => parseFrontMatter(`---${html}\n---`))
45
46
 
46
47
  const templateConfig = merge(matterData, config)
@@ -57,20 +58,21 @@ export async function render(html = '', config = {}) {
57
58
  *
58
59
  * @param {Object} options
59
60
  * @param {string} options.html - The HTML to be transformed
61
+ * @param {Object} options.matter - The front matter data
60
62
  * @param {Object} options.config - The current template config
61
- * @param {function} options.render - The render function
62
63
  * @returns {string} - The transformed HTML, or the original one if nothing was returned
63
64
  */
64
65
  if (typeof templateConfig.beforeRender === 'function') {
65
66
  content = await templateConfig.beforeRender(({
66
67
  html: content,
68
+ matter: matterData,
67
69
  config: templateConfig,
68
- posthtml: compilePostHTML,
69
- transform: transformers,
70
70
  })) ?? content
71
71
  }
72
72
 
73
- // Compile PostHTML
73
+ /**
74
+ * Compile PostHTML
75
+ */
74
76
  const compiled = await compilePostHTML(content, templateConfig)
75
77
 
76
78
  /**
@@ -78,20 +80,18 @@ export async function render(html = '', config = {}) {
78
80
  *
79
81
  * @param {Object} options
80
82
  * @param {string} options.html - The HTML to be transformed
83
+ * @param {Object} options.matter - The front matter data
81
84
  * @param {Object} options.config - The current template config
82
- * @param {function} options.render - The render function
83
85
  * @returns {string} - The transformed HTML, or the original one if nothing was returned
84
86
  */
85
87
  if (typeof templateConfig.afterRender === 'function') {
86
88
  compiled.html = await templateConfig.afterRender(({
87
89
  html: compiled.html,
88
- config: templateConfig,
89
- posthtml: compilePostHTML,
90
- transform: transformers,
90
+ matter: matterData,
91
+ config: compiled.config,
91
92
  })) ?? compiled.html
92
93
  }
93
94
 
94
- // Run Transformers
95
95
  /**
96
96
  * Run Transformers
97
97
  *
@@ -102,30 +102,28 @@ export async function render(html = '', config = {}) {
102
102
  * @returns {string} - The transformed HTML
103
103
  */
104
104
  if (templateConfig.useTransformers !== false) {
105
- compiled.html = await useTransformers(compiled.html, templateConfig).then(({ html }) => html)
105
+ compiled.html = await useTransformers(compiled.html, compiled.config).then(({ html }) => html)
106
106
  }
107
107
 
108
- // Run `afterTransformers` event
109
108
  /**
110
109
  * Run `afterTransformers` event
111
110
  *
112
111
  * @param {Object} options
113
112
  * @param {string} options.html - The HTML to be transformed
113
+ * @param {Object} options.matter - The front matter data
114
114
  * @param {Object} options.config - The current template config
115
- * @param {function} options.render - The render function
116
115
  * @returns {string} - The transformed HTML, or the original one if nothing was returned
117
116
  */
118
117
  if (typeof templateConfig.afterTransformers === 'function') {
119
118
  compiled.html = await templateConfig.afterTransformers(({
120
119
  html: compiled.html,
121
- config: templateConfig,
122
- posthtml: compilePostHTML,
123
- transform: transformers,
120
+ matter: matterData,
121
+ config: compiled.config,
124
122
  })) ?? compiled.html
125
123
  }
126
124
 
127
125
  return {
128
- config: templateConfig,
126
+ config: compiled.config,
129
127
  html: compiled.html,
130
128
  }
131
129
  }
package/src/index.js CHANGED
@@ -5,7 +5,7 @@ import { render } from './generators/render.js'
5
5
  import { addAttributes } from './transformers/addAttributes.js'
6
6
  import { attributeToStyle } from './transformers/attributeToStyle.js'
7
7
  import { addBaseUrl } from './transformers/baseUrl.js'
8
- import { comb } from './transformers/comb.js'
8
+ import { purge } from './transformers/purge.js'
9
9
  import { filters } from './transformers/filters/index.js'
10
10
  import { inline } from './transformers/inline.js'
11
11
  import { markdown } from './transformers/markdown.js'
@@ -29,8 +29,8 @@ export {
29
29
  addAttributes,
30
30
  attributeToStyle,
31
31
  addBaseUrl,
32
- comb as removeUnusedCSS,
33
- comb as purgeCSS,
32
+ purge as removeUnusedCSS,
33
+ purge as purgeCSS,
34
34
  filters,
35
35
  inline as inlineCSS,
36
36
  markdown,
@@ -1,8 +1,16 @@
1
1
  export default {
2
2
  root: './',
3
- folders: ['src/components', 'src/layouts', 'src/templates'],
4
- fileExtension: 'html',
5
3
  tag: 'component',
4
+ fileExtension: ['html'],
5
+ folders: [
6
+ 'layouts',
7
+ 'emails',
8
+ 'templates',
9
+ 'components',
10
+ 'src/layouts',
11
+ 'src/templates',
12
+ 'src/components'
13
+ ],
6
14
  expressions: {
7
15
  loopTags: ['each', 'for'],
8
16
  missingLocal: '{local}',
@@ -1,4 +1,14 @@
1
- export default {
2
- recognizeNoValueAttribute: true,
3
- recognizeSelfClosing: true
1
+ import { defu as merge } from 'defu'
2
+
3
+ export function getPosthtmlOptions(userConfigOptions = {}) {
4
+ return merge(
5
+ userConfigOptions,
6
+ {
7
+ recognizeNoValueAttribute: true,
8
+ recognizeSelfClosing: true,
9
+ directives: [
10
+ { name: '?php', start: '<', end: '>' },
11
+ ],
12
+ }
13
+ )
4
14
  }