vite-plugin-singlefile-compression 2.3.3 → 2.4.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
@@ -6,7 +6,7 @@ The recipient can open it directly in the browser without manually unzipping the
6
6
 
7
7
  Using [DecompressionStream](https://developer.mozilla.org/en-US/docs/Web/API/DecompressionStream) + [base128-ascii](https://www.npmjs.com/package/base128-ascii).
8
8
 
9
- Preview: https://bddjr.github.io/vite-plugin-singlefile-compression/
9
+ Preview: https://bddjr.github.io/vite-plugin-singlefile-compression/#/
10
10
 
11
11
  ## Setup
12
12
 
@@ -65,6 +65,8 @@ Use Base128 to encode compressed script.
65
65
  If false, use Base64.
66
66
  https://www.npmjs.com/package/base128-ascii
67
67
 
68
+ This option is only valid when the `enableCompress` option is set to true.
69
+
68
70
  default: `true`
69
71
 
70
72
  type: `boolean`
@@ -75,6 +77,8 @@ Compress format.
75
77
 
76
78
  https://developer.mozilla.org/en-US/docs/Web/API/DecompressionStream/DecompressionStream
77
79
 
80
+ This option is only valid when the `enableCompress` option is set to true.
81
+
78
82
  default: `"deflate-raw"`
79
83
 
80
84
  type:
@@ -94,6 +98,8 @@ type:
94
98
 
95
99
  Custom compressor.
96
100
 
101
+ This option is only valid when the `enableCompress` option is set to true.
102
+
97
103
  type: `(buf: zlib.InputType) => (Buffer | Uint8Array | Promise<Buffer | Uint8Array>)`
98
104
 
99
105
  ### htmlMinifierTerser
@@ -124,7 +130,7 @@ type: `boolean`
124
130
 
125
131
  ### tryInlineHtmlPublicIcon
126
132
 
127
- Try inline html icon, if icon is in public dir.
133
+ Try inline html favicon, if icon is in public dir.
128
134
 
129
135
  default: `true`
130
136
 
@@ -132,12 +138,24 @@ type: `boolean`
132
138
 
133
139
  ### removeInlinedPublicIconFiles
134
140
 
135
- Remove inlined html icon files.
141
+ Remove inlined html favicon files.
136
142
 
137
143
  default: `true`
138
144
 
139
145
  type: `boolean`
140
146
 
147
+ ### enableCompressInlinedIcon
148
+
149
+ Enable compress inlined html favicon.
150
+
151
+ This option is only valid when the `enableCompress` option is set to true.
152
+
153
+ ⚠️ Not works on Safari (See [#20](https://github.com/bddjr/vite-plugin-singlefile-compression/issues/20))
154
+
155
+ default: `false`
156
+
157
+ type: `boolean`
158
+
141
159
  ### useImportMetaPolyfill
142
160
 
143
161
  Use import.meta polyfill.
@@ -149,24 +167,24 @@ type: `boolean`
149
167
 
150
168
  ## Effect
151
169
 
152
- Preview: https://bddjr.github.io/vite-plugin-singlefile-compression/
170
+ Preview: https://bddjr.github.io/vite-plugin-singlefile-compression/#/
153
171
 
154
172
  ```
155
173
  vite v8.0.8 building client environment for production...
156
174
  ✓ 43 modules transformed.
157
175
  rendering chunks (1)...
158
176
 
159
- vite-plugin-singlefile-compression 2.3.3 deflate-raw base128-ascii
177
+ vite-plugin-singlefile-compression 2.4.0 deflate-raw base128-ascii
160
178
 
161
179
  file:///D:/code/js/vite-plugin-singlefile-compression/test/dist/index.html
162
- 125.847 kB -> 51.312 kB
180
+ 126.497 kB -> 59.589 kB
163
181
 
164
182
  Finish.
165
183
 
166
184
  computing gzip size...
167
- dist/index.html 51.31 kB │ gzip: 44.73 kB
185
+ dist/index.html 59.58 kB │ gzip: 44.90 kB
168
186
 
169
- ✓ built in 285ms
187
+ ✓ built in 293ms
170
188
  ```
171
189
 
172
190
  ## Clone
package/dist/index.d.ts CHANGED
@@ -37,6 +37,9 @@ interface Options {
37
37
  * Use Base128 to encode compressed script.
38
38
  * If false, use Base64.
39
39
  * https://www.npmjs.com/package/base128-ascii
40
+ *
41
+ * This option is only valid when the `enableCompress` option is set to true.
42
+ *
40
43
  * @default true
41
44
  */
42
45
  useBase128?: boolean;
@@ -45,6 +48,8 @@ interface Options {
45
48
  *
46
49
  * https://developer.mozilla.org/en-US/docs/Web/API/DecompressionStream/DecompressionStream
47
50
  *
51
+ * This option is only valid when the `enableCompress` option is set to true.
52
+ *
48
53
  * @type {"deflate-raw" | "deflate" | "gzip" | "brotli" | "zstd" | "deflateRaw" | "gz" | "br" | "brotliCompress" | "zstandard" | "zst"}
49
54
  *
50
55
  * @default "deflate-raw"
@@ -52,6 +57,8 @@ interface Options {
52
57
  compressFormat?: CompressFormat | CompressFormatAlias;
53
58
  /**
54
59
  * Custom compressor.
60
+ *
61
+ * This option is only valid when the `enableCompress` option is set to true.
55
62
  */
56
63
  compressor?: Compressor;
57
64
  /**
@@ -70,15 +77,25 @@ interface Options {
70
77
  */
71
78
  removeInlinedAssetFiles?: boolean;
72
79
  /**
73
- * Try inline html icon, if icon is in public dir.
80
+ * Try inline html favicon, if icon is in public dir.
74
81
  * @default true
75
82
  */
76
83
  tryInlineHtmlPublicIcon?: boolean;
77
84
  /**
78
- * Remove inlined html icon files.
85
+ * Remove inlined html favicon files.
79
86
  * @default true
80
87
  */
81
88
  removeInlinedPublicIconFiles?: boolean;
89
+ /**
90
+ * Enable compress inlined html favicon.
91
+ *
92
+ * This option is only valid when the `enableCompress` option is set to true.
93
+ *
94
+ * ⚠️ Not works on Safari (See [#20](https://github.com/bddjr/vite-plugin-singlefile-compression/issues/20))
95
+ *
96
+ * @default false
97
+ */
98
+ enableCompressInlinedIcon?: boolean;
82
99
  /**
83
100
  * Use import.meta polyfill.
84
101
  * @default false
package/dist/index.js CHANGED
@@ -9,7 +9,7 @@ import zlib from "zlib";
9
9
  import svgToTinyDataUri from "mini-svg-data-uri";
10
10
  import { lookup } from "mrmime";
11
11
  //#region package.json
12
- var version = "2.3.3";
12
+ var version = "2.4.0";
13
13
  //#endregion
14
14
  //#region src/compress.ts
15
15
  const compressors = {
@@ -127,9 +127,10 @@ const defaultHtmlMinifierTerserOptions = {
127
127
  };
128
128
  function getInnerOptions(opt) {
129
129
  opt ||= {};
130
+ const enableCompress = opt.enableCompress ?? true;
130
131
  return {
131
132
  rename: opt.rename == null ? void 0 : String(opt.rename),
132
- enableCompress: opt.enableCompress ?? true,
133
+ enableCompress,
133
134
  useBase128: opt.useBase128 ?? true,
134
135
  compressFormat: opt.compressFormat ? compressFormatAlias.hasOwnProperty(opt.compressFormat) ? compressFormatAlias[opt.compressFormat] : String(opt.compressFormat) : "deflate-raw",
135
136
  compressor: typeof opt.compressor == "function" ? opt.compressor : void 0,
@@ -138,6 +139,7 @@ function getInnerOptions(opt) {
138
139
  removeInlinedAssetFiles: opt.removeInlinedAssetFiles ?? true,
139
140
  tryInlineHtmlPublicIcon: opt.tryInlineHtmlPublicIcon ?? true,
140
141
  removeInlinedPublicIconFiles: opt.removeInlinedPublicIconFiles ?? true,
142
+ enableCompressInlinedIcon: enableCompress && (opt.enableCompressInlinedIcon ?? false),
141
143
  useImportMetaPolyfill: opt.useImportMetaPolyfill ?? false
142
144
  };
143
145
  }
@@ -243,44 +245,62 @@ async function generateBundle(bundle, config, options) {
243
245
  }
244
246
  if (options.enableCompress) element.src = `data:${name}`;
245
247
  }
246
- if (options.tryInlineHtmlPublicIcon) {
247
- let needInline = true;
248
- let iconName = "favicon.ico";
249
- const element = document.querySelector(`link[rel=icon][href^="${config.base}"], link[rel="shortcut icon"][href^="${config.base}"]`);
250
- if (element) {
251
- iconName = cutPrefix(element.href, config.base);
252
- if (bundleAssetsNames.includes(iconName)) needInline = false;
253
- else {
254
- element.rel = "icon";
255
- element.href = "data:";
256
- }
248
+ let linkFavicon = document.querySelector(`link[rel=icon][href^="${config.base}"]`);
249
+ {
250
+ const link_shortcut_icon = document.querySelector(`link[rel="shortcut icon"][href^="${config.base}"]`);
251
+ if (link_shortcut_icon) if (linkFavicon) link_shortcut_icon.remove();
252
+ else {
253
+ link_shortcut_icon.rel = "icon";
254
+ linkFavicon = link_shortcut_icon;
257
255
  }
258
- if (needInline) try {
259
- if (!Object.prototype.hasOwnProperty.call(globalPublicFilesCache, iconName)) {
260
- let Path = path.join(config.build.outDir, iconName);
261
- if (fs.existsSync(Path)) globalRemoveDistFileNames.add(iconName);
262
- else Path = path.join(config.publicDir, iconName);
263
- const b = fs.readFileSync(Path);
264
- globalPublicFilesCache[iconName] = {
265
- dataURL: bufferToDataURL(iconName, b),
266
- size: b.length
267
- };
268
- }
269
- const { dataURL, size } = globalPublicFilesCache[iconName];
270
- oldSize += size;
271
- if (options.enableCompress) {
272
- newJSCode.push(template.icon(dataURL));
273
- if (!element) document.head.insertAdjacentHTML("beforeend", "<link rel=\"icon\" href=\"data:\">");
274
- } else if (element) element.href = dataURL;
275
- else {
276
- const e = document.head.appendChild(document.createElement("link"));
277
- e.rel = "icon";
278
- e.href = dataURL;
279
- }
280
- } catch (e) {
281
- if (element) console.error(e);
256
+ }
257
+ let faviconName = "favicon.ico";
258
+ let faviconIsDataURL = false;
259
+ if (linkFavicon) {
260
+ faviconName = linkFavicon.href;
261
+ faviconIsDataURL = /^data:/i.test(faviconName);
262
+ if (!faviconIsDataURL) faviconName = cutPrefix(faviconName, config.base);
263
+ }
264
+ function setFaviconDataURL(dataURL) {
265
+ if (options.enableCompressInlinedIcon) {
266
+ newJSCode.push(template.icon(dataURL));
267
+ if (linkFavicon) linkFavicon.href = "data:";
268
+ else document.head.insertAdjacentHTML("beforeend", "<link rel=\"icon\" href=\"data:\">");
269
+ } else if (linkFavicon) linkFavicon.href = dataURL;
270
+ else {
271
+ const e = document.head.appendChild(document.createElement("link"));
272
+ e.rel = "icon";
273
+ e.href = dataURL;
282
274
  }
283
275
  }
276
+ if (faviconIsDataURL) {
277
+ if (options.enableCompressInlinedIcon) {
278
+ newJSCode.push(template.icon(faviconName));
279
+ linkFavicon.href = "data:";
280
+ }
281
+ } else if (bundleAssetsNames.includes(faviconName)) {
282
+ const asset = bundle[faviconName];
283
+ if (asset) {
284
+ setFaviconDataURL(bufferToDataURL(faviconName, Buffer.from(asset.source)));
285
+ thisDel.add(faviconName);
286
+ }
287
+ } else if (options.tryInlineHtmlPublicIcon) try {
288
+ if (!Object.prototype.hasOwnProperty.call(globalPublicFilesCache, faviconName)) {
289
+ let Path = path.join(config.build.outDir, faviconName);
290
+ if (fs.existsSync(Path)) globalRemoveDistFileNames.add(faviconName);
291
+ else Path = path.join(config.publicDir, faviconName);
292
+ const b = fs.readFileSync(Path);
293
+ globalPublicFilesCache[faviconName] = {
294
+ dataURL: bufferToDataURL(faviconName, b),
295
+ size: b.length
296
+ };
297
+ }
298
+ const { dataURL, size } = globalPublicFilesCache[faviconName];
299
+ oldSize += size;
300
+ setFaviconDataURL(dataURL);
301
+ } catch (e) {
302
+ if (linkFavicon) console.error(e);
303
+ }
284
304
  htmlChunk.source = dom.serialize();
285
305
  if (options.htmlMinifierTerser) htmlChunk.source = await minify(htmlChunk.source, options.htmlMinifierTerser);
286
306
  function inlineHtmlAssets() {
@@ -296,10 +316,7 @@ async function generateBundle(bundle, config, options) {
296
316
  code = code.replace(/;?\n?$/, "");
297
317
  for (const name of bundleAssetsNames) {
298
318
  const assetName = name.slice(assetsDir.length);
299
- if (code.includes(assetName)) {
300
- globalDoNotDelete.add(name);
301
- delete assetsDataURL[assetName];
302
- }
319
+ if (code.includes(assetName)) globalDoNotDelete.add(name);
303
320
  }
304
321
  inlineHtmlAssets();
305
322
  if (options.useImportMetaPolyfill) newJSCode.push(template.importmeta(scriptName));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vite-plugin-singlefile-compression",
3
- "version": "2.3.3",
3
+ "version": "2.4.0",
4
4
  "author": "bddjr",
5
5
  "license": "MIT",
6
6
  "description": "Compress all assets and embeds them into dist/index.html, making it convenient to share as a single HTML file.",
@@ -14,7 +14,7 @@
14
14
  "build": "tsc && node build.js && tsc _dist/templateRaw.ts --ignoreConfig --noEmit && cd test && node --run build",
15
15
  "prepublishOnly": "node --run build"
16
16
  },
17
- "homepage": "https://bddjr.github.io/vite-plugin-singlefile-compression/",
17
+ "homepage": "https://bddjr.github.io/vite-plugin-singlefile-compression/#/",
18
18
  "repository": {
19
19
  "type": "git",
20
20
  "url": "git+https://github.com/bddjr/vite-plugin-singlefile-compression.git"
@@ -90,7 +90,7 @@
90
90
  },
91
91
  "dependencies": {
92
92
  "@types/html-minifier-terser": ">=7.0.2",
93
- "base128-ascii": ">=4.0.1",
93
+ "base128-ascii": ">=5.0.0",
94
94
  "html-minifier-terser": ">=7.2.0",
95
95
  "jsdom": ">=29.0.2",
96
96
  "mini-svg-data-uri": ">=1.4.4",