html-bundle 6.0.21 → 6.1.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/README.md CHANGED
@@ -63,6 +63,19 @@ Generate the config in the root and call it "bundle.config.js"
63
63
  **html-minifier-terser:** Your additional config<br>
64
64
  **critical:** Your additional config<br>
65
65
 
66
+ Example:
67
+
68
+ ```javascript
69
+ /** @type {import('html-bundle').Config} */
70
+ export default {
71
+ secure: true,
72
+ handler: "utils/staticFiles.js",
73
+ esbuild: {
74
+ external: ["images"],
75
+ },
76
+ };
77
+ ```
78
+
66
79
  ## Concept
67
80
 
68
81
  The bundler always globs all HTML, CSS and TS/JS files from the `src` (config) directory and processes them to the `build` (config) directory. PostCSS is being used for CSS files and inline styles, html-minifier-terser for HTML and esbuild to bundle, minify, etc. for inline and referenced TS/JS. Server-sent events and [hydro-js](https://github.com/Krutsch/hydro-js) are used for HMR. In order to trigger SPA Routers, the popstate event is being triggered after HMR Operations.
package/dist/bundle.mjs CHANGED
@@ -103,7 +103,10 @@ async function build(files, firstRun = true) {
103
103
  if (files.includes(file) || INLINE_BUNDLE_FILE.test(file)) {
104
104
  return;
105
105
  }
106
- await rebuild(file);
106
+ try {
107
+ await rebuild(file);
108
+ }
109
+ catch { }
107
110
  console.log(`⚡ added ${file} to the build`);
108
111
  });
109
112
  watcher.on("change", async (file) => {
@@ -123,11 +126,14 @@ async function build(files, firstRun = true) {
123
126
  const buildFile = getBuildPath(file)
124
127
  .replace(".ts", ".js")
125
128
  .replace(".jsx", ".js");
126
- await rm(buildFile);
127
- const bfDir = buildFile.split("/").slice(0, -1).join("/");
128
- const stats = await readdir(bfDir);
129
- if (!stats.length)
130
- await rm(bfDir);
129
+ try {
130
+ await rm(buildFile);
131
+ const bfDir = buildFile.split("/").slice(0, -1).join("/");
132
+ const stats = await readdir(bfDir);
133
+ if (!stats.length)
134
+ await rm(bfDir);
135
+ }
136
+ catch { }
131
137
  console.log(`⚡ deleted ${file} from the build`);
132
138
  });
133
139
  async function rebuild(file) {
@@ -162,6 +168,11 @@ async function build(files, firstRun = true) {
162
168
  await fileCopy(file);
163
169
  }
164
170
  }
171
+ else if (handlerFile) {
172
+ const { stdout } = await execFilePromise("node", [handlerFile, file]);
173
+ if (String(stdout))
174
+ console.log("📋 Logging Handler: ", String(stdout));
175
+ }
165
176
  serverSentEvents?.({ file, html });
166
177
  }
167
178
  }
@@ -177,7 +188,8 @@ async function minifyCSS(file, buildFile) {
177
188
  await writeFile(buildFile, result.css);
178
189
  }
179
190
  catch (err) {
180
- console.error(err);
191
+ // @ts-ignore
192
+ console.error(err?.reason);
181
193
  }
182
194
  }
183
195
  async function minifyCode() {
@@ -207,7 +219,7 @@ async function minifyCode() {
207
219
  let missingPkg = false;
208
220
  if (err?.errors) {
209
221
  for (const error of err.errors) {
210
- if (error.text?.startsWith("Could not resolve")) {
222
+ if (error.location && error.text?.startsWith("Could not resolve")) {
211
223
  missingPkg = true;
212
224
  const packageNameRegex = /(?<=").*(?=")/;
213
225
  const [pkgName] = error.text.match(packageNameRegex);
@@ -244,8 +256,9 @@ async function writeInlineScripts(file) {
244
256
  const script = scripts[index];
245
257
  const scriptTextNode = script.childNodes[0];
246
258
  const isReferencedScript = script.attrs.find((a) => a.name === "src");
259
+ const type = script.attrs.find((a) => a.name === "type");
247
260
  const scriptContent = scriptTextNode?.value;
248
- if (!scriptContent || isReferencedScript)
261
+ if (!scriptContent || isReferencedScript || type?.value === "importmap")
249
262
  continue;
250
263
  const jsFile = file.replace(".html", `-bundle-${index}.tsx`);
251
264
  inlineFiles.add(jsFile);
@@ -274,15 +287,21 @@ async function minifyHTML(file, buildFile) {
274
287
  const script = scripts[index];
275
288
  const scriptTextNode = script.childNodes[0];
276
289
  const isReferencedScript = script.attrs.find((a) => a.name === "src");
277
- if (!scriptTextNode?.value || isReferencedScript)
290
+ const type = script.attrs.find((a) => a.name === "type");
291
+ if (!scriptTextNode?.value ||
292
+ isReferencedScript ||
293
+ type?.value === "importmap")
278
294
  continue;
279
295
  // Use bundled file
280
296
  const buildInlineScript = buildFile.replace(".html", `-bundle-${index}.js`);
281
- const scriptContent = await readFile(buildInlineScript, {
282
- encoding: "utf-8",
283
- });
284
- await rm(buildInlineScript);
285
- scriptTextNode.value = scriptContent.replace(TEMPLATE_LITERAL_MINIFIER, " ");
297
+ try {
298
+ const scriptContent = await readFile(buildInlineScript, {
299
+ encoding: "utf-8",
300
+ });
301
+ await rm(buildInlineScript);
302
+ scriptTextNode.value = scriptContent.replace(TEMPLATE_LITERAL_MINIFIER, " ");
303
+ }
304
+ catch { }
286
305
  }
287
306
  // Minify Inline Style
288
307
  const styles = findElements(DOM, (e) => getTagName(e) === "style");
@@ -291,11 +310,17 @@ async function minifyHTML(file, buildFile) {
291
310
  const styleContent = node?.value;
292
311
  if (!styleContent)
293
312
  continue;
294
- const { css } = await CSSprocessor.process(styleContent, {
295
- ...options,
296
- from: undefined,
297
- });
298
- node.value = css;
313
+ try {
314
+ const { css } = await CSSprocessor.process(styleContent, {
315
+ ...options,
316
+ from: undefined,
317
+ });
318
+ node.value = css;
319
+ }
320
+ catch {
321
+ // @ts-ignore
322
+ console.error(err?.reason);
323
+ }
299
324
  }
300
325
  fileText = serialize(DOM);
301
326
  // Minify HTML
package/dist/utils.mjs CHANGED
@@ -71,9 +71,9 @@ async function getBundleConfig() {
71
71
  port: 5000,
72
72
  esbuild: {},
73
73
  "html-minifier-terser": {},
74
+ deletePrev: true,
74
75
  critical: {},
75
76
  isCritical: false,
76
- deletePrev: true,
77
77
  hmr: false,
78
78
  secure: false,
79
79
  handler: "",
package/package.json CHANGED
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "name": "html-bundle",
3
- "version": "6.0.21",
3
+ "version": "6.1.0",
4
4
  "description": "A very simple bundler for HTML SFC",
5
5
  "bin": "./dist/bundle.mjs",
6
+ "types": "./src/config.d.ts",
6
7
  "scripts": {
7
8
  "start": "tsc",
8
9
  "update": "npx npm-check-updates -u && npx typesync && npm i && npm outdated"
@@ -31,19 +32,19 @@
31
32
  },
32
33
  "bugs": "https://github.com/Krutsch/html-bundle/issues",
33
34
  "dependencies": {
34
- "@fastify/static": "^6.12.0",
35
+ "@fastify/static": "^7.0.0",
35
36
  "@web/parse5-utils": "^2.1.0",
36
37
  "await-spawn": "^4.0.2",
37
38
  "chokidar": "^3.5.3",
38
39
  "critters": "^0.0.20",
39
- "cssnano": "^6.0.2",
40
- "esbuild": "^0.19.11",
41
- "fastify": "^4.25.2",
40
+ "cssnano": "^6.0.3",
41
+ "esbuild": "^0.20.0",
42
+ "fastify": "^4.26.0",
42
43
  "glob": "^10.3.10",
43
44
  "html-minifier-terser": "^7.2.0",
44
45
  "hydro-js": "^1.5.14",
45
46
  "parse5": "^7.1.2",
46
- "postcss": "^8.4.32",
47
+ "postcss": "^8.4.34",
47
48
  "postcss-load-config": "^5.0.2"
48
49
  }
49
50
  }
package/src/bundle.mts CHANGED
@@ -138,7 +138,9 @@ async function build(files: string[], firstRun = true) {
138
138
  return;
139
139
  }
140
140
 
141
- await rebuild(file);
141
+ try {
142
+ await rebuild(file);
143
+ } catch {}
142
144
 
143
145
  console.log(`⚡ added ${file} to the build`);
144
146
  });
@@ -162,11 +164,13 @@ async function build(files: string[], firstRun = true) {
162
164
  const buildFile = getBuildPath(file)
163
165
  .replace(".ts", ".js")
164
166
  .replace(".jsx", ".js");
165
- await rm(buildFile);
166
167
 
167
- const bfDir = buildFile.split("/").slice(0, -1).join("/");
168
- const stats = await readdir(bfDir);
169
- if (!stats.length) await rm(bfDir);
168
+ try {
169
+ await rm(buildFile);
170
+ const bfDir = buildFile.split("/").slice(0, -1).join("/");
171
+ const stats = await readdir(bfDir);
172
+ if (!stats.length) await rm(bfDir);
173
+ } catch {}
170
174
 
171
175
  console.log(`⚡ deleted ${file} from the build`);
172
176
  });
@@ -200,6 +204,9 @@ async function build(files: string[], firstRun = true) {
200
204
  } else {
201
205
  await fileCopy(file);
202
206
  }
207
+ } else if (handlerFile) {
208
+ const { stdout } = await execFilePromise("node", [handlerFile, file]);
209
+ if (String(stdout)) console.log("📋 Logging Handler: ", String(stdout));
203
210
  }
204
211
 
205
212
  serverSentEvents?.({ file, html });
@@ -217,7 +224,8 @@ async function minifyCSS(file: string, buildFile: string) {
217
224
  });
218
225
  await writeFile(buildFile, result.css);
219
226
  } catch (err) {
220
- console.error(err);
227
+ // @ts-ignore
228
+ console.error(err?.reason);
221
229
  }
222
230
  }
223
231
 
@@ -248,7 +256,7 @@ async function minifyCode(): Promise<unknown> {
248
256
  let missingPkg = false;
249
257
  if (err?.errors) {
250
258
  for (const error of err.errors) {
251
- if (error.text?.startsWith("Could not resolve")) {
259
+ if (error.location && error.text?.startsWith("Could not resolve")) {
252
260
  missingPkg = true;
253
261
  const packageNameRegex = /(?<=").*(?=")/;
254
262
  const [pkgName] = error.text.match(packageNameRegex);
@@ -293,8 +301,10 @@ async function writeInlineScripts(file: string) {
293
301
  const isReferencedScript = script.attrs.find(
294
302
  (a: { name: string }) => a.name === "src"
295
303
  );
304
+ const type = script.attrs.find((a: { name: string }) => a.name === "type");
296
305
  const scriptContent = scriptTextNode?.value;
297
- if (!scriptContent || isReferencedScript) continue;
306
+ if (!scriptContent || isReferencedScript || type?.value === "importmap")
307
+ continue;
298
308
 
299
309
  const jsFile = file.replace(".html", `-bundle-${index}.tsx`);
300
310
  inlineFiles.add(jsFile);
@@ -327,19 +337,27 @@ async function minifyHTML(file: string, buildFile: string) {
327
337
  const isReferencedScript = script.attrs.find(
328
338
  (a: { name: string }) => a.name === "src"
329
339
  );
330
- if (!scriptTextNode?.value || isReferencedScript) continue;
340
+ const type = script.attrs.find((a: { name: string }) => a.name === "type");
341
+ if (
342
+ !scriptTextNode?.value ||
343
+ isReferencedScript ||
344
+ type?.value === "importmap"
345
+ )
346
+ continue;
331
347
 
332
348
  // Use bundled file
333
349
  const buildInlineScript = buildFile.replace(".html", `-bundle-${index}.js`);
334
350
 
335
- const scriptContent = await readFile(buildInlineScript, {
336
- encoding: "utf-8",
337
- });
338
- await rm(buildInlineScript);
339
- scriptTextNode.value = scriptContent.replace(
340
- TEMPLATE_LITERAL_MINIFIER,
341
- " "
342
- );
351
+ try {
352
+ const scriptContent = await readFile(buildInlineScript, {
353
+ encoding: "utf-8",
354
+ });
355
+ await rm(buildInlineScript);
356
+ scriptTextNode.value = scriptContent.replace(
357
+ TEMPLATE_LITERAL_MINIFIER,
358
+ " "
359
+ );
360
+ } catch {}
343
361
  }
344
362
 
345
363
  // Minify Inline Style
@@ -349,11 +367,16 @@ async function minifyHTML(file: string, buildFile: string) {
349
367
  const styleContent = node?.value;
350
368
  if (!styleContent) continue;
351
369
 
352
- const { css } = await CSSprocessor.process(styleContent, {
353
- ...options,
354
- from: undefined,
355
- });
356
- node.value = css;
370
+ try {
371
+ const { css } = await CSSprocessor.process(styleContent, {
372
+ ...options,
373
+ from: undefined,
374
+ });
375
+ node.value = css;
376
+ } catch {
377
+ // @ts-ignore
378
+ console.error(err?.reason);
379
+ }
357
380
  }
358
381
 
359
382
  fileText = serialize(DOM);
@@ -0,0 +1,13 @@
1
+ export type Config = {
2
+ build: string;
3
+ src: string;
4
+ port: number;
5
+ secure: boolean;
6
+ esbuild?: BuildOptions;
7
+ "html-minifier-terser"?: HTMLOptions;
8
+ critical?: Options;
9
+ deletePrev?: boolean;
10
+ isCritical?: boolean;
11
+ hmr?: boolean;
12
+ handler?: string;
13
+ };
package/src/utils.mts CHANGED
@@ -16,6 +16,7 @@ import {
16
16
  findElement,
17
17
  appendChild,
18
18
  } from "@web/parse5-utils";
19
+ import { Config } from "./config";
19
20
 
20
21
  export const bundleConfig = await getBundleConfig();
21
22
 
@@ -89,19 +90,6 @@ export async function getPostCSSConfig() {
89
90
  }
90
91
  }
91
92
 
92
- export type Config = {
93
- build: string;
94
- src: string;
95
- port: number;
96
- secure: boolean;
97
- esbuild?: BuildOptions;
98
- "html-minifier-terser"?: HTMLOptions;
99
- critical?: Options;
100
- deletePrev?: boolean;
101
- isCritical?: boolean;
102
- hmr?: boolean;
103
- handler?: string;
104
- };
105
93
  async function getBundleConfig(): Promise<Config> {
106
94
  const base = {
107
95
  build: "build",