vite-plugin-singlefile-compression 2.0.14 → 2.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/LICENSE.txt CHANGED
@@ -1,5 +1,5 @@
1
1
  The MIT License (MIT)
2
- Copyright © 2024 bddjr
2
+ Copyright © 2026 bddjr
3
3
 
4
4
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5
5
 
package/README.md CHANGED
@@ -9,30 +9,28 @@ Using [DecompressionStream](https://developer.mozilla.org/docs/Web/API/Decompres
9
9
  ## Setup
10
10
 
11
11
  ```
12
- npm i vite-plugin-singlefile-compression -D
12
+ npm i vite-plugin-singlefile-compression@latest -D
13
13
  ```
14
14
 
15
- Then modify `vite.config.ts`, see [test/vite.config.ts](test/vite.config.ts)
15
+ Then modify `vite.config.ts`, like [test/vite.config.ts](test/vite.config.ts)
16
16
 
17
- ```ts
18
- // Import singleFileCompression
19
- import singleFileCompression from 'vite-plugin-singlefile-compression'
20
-
21
- export default defineConfig({
22
- plugins: [
23
- vue(),
24
- vueDevTools(),
25
- // Add singleFileCompression
26
- singleFileCompression(),
27
- ],
17
+ ```diff
18
+ + import singleFileCompression from 'vite-plugin-singlefile-compression'
19
+
20
+ export default defineConfig({
21
+ plugins: [
22
+ vue(),
23
+ vueDevTools(),
24
+ + singleFileCompression(),
25
+ ],
28
26
  ```
29
27
 
30
- Then modify [src/router/index.ts](test/src/router/index.ts#L5)
28
+ Then use hash history, like [test/src/router/index.ts](test/src/router/index.ts#L5)
31
29
 
32
- ```ts
33
- const router = createRouter({
34
- // Use Hash History
35
- history: createWebHashHistory(),
30
+ ```diff
31
+ const router = createRouter({
32
+ - history: createWebHistory(),
33
+ + history: createWebHashHistory(),
36
34
  ```
37
35
 
38
36
  ## Options
@@ -49,6 +47,36 @@ More info see [src/options.ts](src/options.ts)
49
47
 
50
48
  ```ts
51
49
  export interface Options {
50
+ /**
51
+ * Enable compress.
52
+ * @default true
53
+ */
54
+ enableCompress?: boolean
55
+
56
+ /**
57
+ * Use Base128 to encode compressed script.
58
+ * If false, use Base64.
59
+ * https://www.npmjs.com/package/base128-ascii
60
+ * @default true
61
+ */
62
+ useBase128?: boolean
63
+
64
+ /**
65
+ * Compress format.
66
+ *
67
+ * https://developer.mozilla.org/en-US/docs/Web/API/DecompressionStream/DecompressionStream
68
+ *
69
+ * @type {"deflate-raw" | "deflate" | "gzip" | "brotli" | "zstd" | "deflateRaw" | "gz" | "br" | "brotliCompress" | "zstandard" | "zst"}
70
+ *
71
+ * @default "deflate-raw"
72
+ */
73
+ compressFormat?: CompressFormat | CompressFormatAlias
74
+
75
+ /**
76
+ * Custom compressor.
77
+ */
78
+ compressor?: Compressor
79
+
52
80
  /**
53
81
  * Rename index.html
54
82
  */
@@ -58,7 +86,7 @@ export interface Options {
58
86
  * https://github.com/terser/html-minifier-terser?tab=readme-ov-file#options-quick-reference
59
87
  * @default defaultHtmlMinifierTerserOptions
60
88
  */
61
- htmlMinifierTerser?: htmlMinifierOptions | boolean
89
+ htmlMinifierTerser?: HtmlMinifierOptions | boolean
62
90
 
63
91
  /**
64
92
  * Try inline html used assets, if inlined or not used in JS.
@@ -84,27 +112,6 @@ export interface Options {
84
112
  */
85
113
  removeInlinedPublicIconFiles?: boolean
86
114
 
87
- /**
88
- * Use Base128 to encode gzipped script.
89
- * If false, use Base64.
90
- * https://www.npmjs.com/package/base128-ascii
91
- * @default true
92
- */
93
- useBase128?: boolean
94
-
95
- /**
96
- * Compress format.
97
- * https://developer.mozilla.org/en-US/docs/Web/API/DecompressionStream/DecompressionStream
98
- * @type "deflate-raw" | "deflate" | "gzip" | "brotli" | "zstd"
99
- * @default "deflate-raw"
100
- */
101
- compressFormat?: compressFormat
102
-
103
- /**
104
- * Custom compressor.
105
- */
106
- compressor?: compressor
107
-
108
115
  /**
109
116
  * Use import.meta polyfill.
110
117
  * @default true
@@ -115,23 +122,24 @@ export interface Options {
115
122
 
116
123
  ## Effect
117
124
 
118
- https://bddjr.github.io/vite-plugin-singlefile-compression/
125
+ Preview: https://bddjr.github.io/vite-plugin-singlefile-compression/
119
126
 
120
127
  ```
121
128
  vite v8.0.0 building client environment for production...
122
- 41 modules transformed.
123
- rendering chunks (1)...
129
+ 315 modules transformed.
130
+
124
131
 
125
- vite-plugin-singlefile-compression 2.0.14 building...
132
+ vite-plugin-singlefile-compression 2.1.0 deflate-raw
126
133
 
127
134
  file:///D:/code/js/vite-plugin-singlefile-compression/test/dist/index.html
128
- 106.506 kB -> 47.487 kB
135
+ 1085.847 kB -> 455.561 kB
129
136
 
130
137
  Finish.
131
138
 
132
- dist/index.html 47.48 kB
139
+ computing gzip size...
140
+ dist/index.html 455.56 kB │ gzip: 397.49 kB
133
141
 
134
- ✓ built in 296ms
142
+ ✓ built in 416ms
135
143
  ```
136
144
 
137
145
  ![](effect.jpg)
package/dist/index.d.ts CHANGED
@@ -1,4 +1,93 @@
1
+ import { Options as HtmlMinifierOptions } from "html-minifier-terser";
2
+ import zlib from "zlib";
1
3
  import { PluginOption } from "vite";
2
- import { Options } from "./options.js";
3
- export declare function singleFileCompression(opt?: Options): PluginOption;
4
- export default singleFileCompression;
4
+
5
+ //#region _dist/compress.d.ts
6
+ declare const compressors: {
7
+ "deflate-raw"(buf: zlib.InputType): Buffer;
8
+ deflate(buf: zlib.InputType): Buffer;
9
+ gzip(buf: zlib.InputType): Buffer;
10
+ brotli: typeof zlib.brotliCompressSync;
11
+ zstd: (buf: zlib.InputType) => NonSharedBuffer;
12
+ };
13
+ declare const compressFormatAlias: Readonly<{
14
+ deflateRaw: "deflate-raw";
15
+ gz: "gzip";
16
+ br: "brotli";
17
+ brotliCompress: "brotli";
18
+ zstandard: "zstd";
19
+ zst: "zstd";
20
+ }>;
21
+ type Compressor = ((buf: zlib.InputType) => (Buffer | Uint8Array));
22
+ type CompressFormat = keyof typeof compressors;
23
+ type CompressFormatAlias = keyof typeof compressFormatAlias;
24
+ //#endregion
25
+ //#region _dist/options.d.ts
26
+ interface Options {
27
+ /**
28
+ * Enable compress.
29
+ * @default true
30
+ */
31
+ enableCompress?: boolean;
32
+ /**
33
+ * Use Base128 to encode compressed script.
34
+ * If false, use Base64.
35
+ * https://www.npmjs.com/package/base128-ascii
36
+ * @default true
37
+ */
38
+ useBase128?: boolean;
39
+ /**
40
+ * Compress format.
41
+ *
42
+ * https://developer.mozilla.org/en-US/docs/Web/API/DecompressionStream/DecompressionStream
43
+ *
44
+ * @type {"deflate-raw" | "deflate" | "gzip" | "brotli" | "zstd" | "deflateRaw" | "gz" | "br" | "brotliCompress" | "zstandard" | "zst"}
45
+ *
46
+ * @default "deflate-raw"
47
+ */
48
+ compressFormat?: CompressFormat | CompressFormatAlias;
49
+ /**
50
+ * Custom compressor.
51
+ */
52
+ compressor?: Compressor;
53
+ /**
54
+ * Rename index.html
55
+ */
56
+ rename?: string;
57
+ /**
58
+ * https://github.com/terser/html-minifier-terser?tab=readme-ov-file#options-quick-reference
59
+ * @default defaultHtmlMinifierTerserOptions
60
+ */
61
+ htmlMinifierTerser?: HtmlMinifierOptions | boolean;
62
+ /**
63
+ * Try inline html used assets, if inlined or not used in JS.
64
+ * @default true
65
+ */
66
+ tryInlineHtmlAssets?: boolean;
67
+ /**
68
+ * Remove inlined asset files.
69
+ * @default true
70
+ */
71
+ removeInlinedAssetFiles?: boolean;
72
+ /**
73
+ * Try inline html icon, if icon is in public dir.
74
+ * @default true
75
+ */
76
+ tryInlineHtmlPublicIcon?: boolean;
77
+ /**
78
+ * Remove inlined html icon files.
79
+ * @default true
80
+ */
81
+ removeInlinedPublicIconFiles?: boolean;
82
+ /**
83
+ * Use import.meta polyfill.
84
+ * @default true
85
+ */
86
+ useImportMetaPolyfill?: boolean;
87
+ }
88
+ declare const defaultHtmlMinifierTerserOptions: HtmlMinifierOptions;
89
+ //#endregion
90
+ //#region _dist/index.d.ts
91
+ declare function singleFileCompression(opt?: Options): PluginOption;
92
+ //#endregion
93
+ export { CompressFormat, CompressFormatAlias, Compressor, HtmlMinifierOptions, Options, singleFileCompression as default, singleFileCompression, defaultHtmlMinifierTerserOptions };
package/dist/index.js CHANGED
@@ -1,253 +1,317 @@
1
1
  import pc from "picocolors";
2
- import { minify as htmlMinify } from 'html-minifier-terser';
3
- import { JSDOM } from 'jsdom';
4
- import path from 'path';
5
- import fs from 'fs';
2
+ import { minify } from "html-minifier-terser";
3
+ import { JSDOM } from "jsdom";
4
+ import path from "path";
5
+ import fs from "fs";
6
6
  import { pathToFileURL } from "url";
7
- import { version } from './getVersion.js';
8
- import { template } from './getTemplate.js';
9
- import { bufferToDataURL } from "./dataurl.js";
10
- import { kB } from "./kB.js";
11
- import { getInnerOptions } from "./options.js";
12
- import { cutPrefix } from "./cutPrefix.js";
13
- export function singleFileCompression(opt) {
14
- let conf;
15
- return {
16
- name: "singleFileCompression",
17
- enforce: "post",
18
- config: setConfig,
19
- configResolved(c) { conf = c; },
20
- generateBundle: (_, bundle) => generateBundle(bundle, conf, getInnerOptions(opt)),
21
- };
7
+ import base128 from "base128-ascii";
8
+ import zlib from "zlib";
9
+ import svgToTinyDataUri from "mini-svg-data-uri";
10
+ import mime from "mime";
11
+ //#region _dist/getVersion.js
12
+ var version = "2.1.0";
13
+ //#endregion
14
+ //#region _dist/compress.js
15
+ const compressors = {
16
+ "deflate-raw"(buf) {
17
+ return zlib.deflateRawSync(buf, { level: zlib.constants.Z_BEST_COMPRESSION });
18
+ },
19
+ deflate(buf) {
20
+ return zlib.deflateSync(buf, { level: zlib.constants.Z_BEST_COMPRESSION });
21
+ },
22
+ gzip(buf) {
23
+ return zlib.gzipSync(buf, { level: zlib.constants.Z_BEST_COMPRESSION });
24
+ },
25
+ brotli: zlib.brotliCompressSync,
26
+ zstd: zlib.zstdCompressSync && ((buf) => zlib.zstdCompressSync(buf, { params: { [zlib.constants.ZSTD_c_compressionLevel]: 19 } }))
27
+ };
28
+ const compressFormatAlias = Object.freeze({
29
+ deflateRaw: "deflate-raw",
30
+ gz: "gzip",
31
+ br: "brotli",
32
+ brotliCompress: "brotli",
33
+ zstandard: "zstd",
34
+ zst: "zstd"
35
+ });
36
+ function switchCompressor(format) {
37
+ if (compressors.hasOwnProperty(format)) {
38
+ const f = compressors[format];
39
+ if (f) return f;
40
+ throw Error(`Could not get compressor: Please upgrade node.js or set your compressor function.`);
41
+ }
42
+ {
43
+ const _format = format.replace(/-([a-zA-Z])/g, (m, a) => a.toUpperCase());
44
+ for (const funcName of [_format + "CompressSync", _format + "Sync"]) if (Object.prototype.hasOwnProperty.call(zlib, funcName)) {
45
+ const f = zlib[funcName];
46
+ if (typeof f == "function") return f;
47
+ }
48
+ }
49
+ throw Error(`Could not get compressor: Unknown compress format '${format}', please set your compressor function.`);
22
50
  }
23
- export default singleFileCompression;
24
- function setConfig(config, env) {
25
- config.base ??= './';
26
- const build = config.build ??= {};
27
- build.cssCodeSplit ??= false;
28
- build.assetsInlineLimit ??= () => true;
29
- build.chunkSizeWarningLimit ??= Number.MAX_SAFE_INTEGER;
30
- build.modulePreload ??= { polyfill: false };
31
- build.reportCompressedSize ??= false;
32
- if (this.meta.rolldownVersion) {
33
- // Vite 8
34
- const rolldownOptions = build.rolldownOptions ?? build.rollupOptions ?? (build.rolldownOptions = {});
35
- for (const output of [rolldownOptions.output ??= {}].flat(1)) {
36
- output.codeSplitting ??= false;
37
- }
38
- }
39
- else {
40
- // Vite oldest
41
- const rollupOptions = (build.rollupOptions ??= {});
42
- for (const output of [rollupOptions.output ??= {}].flat(1)) {
43
- output.inlineDynamicImports ??= true;
44
- }
45
- }
51
+ function compress(format, buf, useBase128, compressor) {
52
+ if (typeof compressor != "function") compressor = switchCompressor(format);
53
+ const outBuf = compressor(buf);
54
+ if (useBase128) return base128.encode(outBuf).toJSTemplateLiterals();
55
+ if (Buffer.isBuffer(outBuf)) return outBuf.toString("base64");
56
+ if (typeof outBuf.toBase64 == "function") return outBuf.toBase64();
57
+ return Buffer.from(outBuf).toString("base64");
58
+ }
59
+ //#endregion
60
+ //#region _dist/templateRaw.js
61
+ var raw = {
62
+ "assets": "{let e={\"\":\"\"};for(let o in e)for(let s of document.querySelectorAll(`[src=\"data:${o}\"]`))s.src=e[o]}",
63
+ "base128": "var a=\"<script>\",i=a.length,r=new Uint8Array(Math.floor(i/8*7)),c=0,o=0,e,t=()=>(e=a.charCodeAt(c++))>127?e=0:e;for(;c<i;)r[o++]=t()<<1|t()>>6,r[o++]=e<<2|t()>>5,r[o++]=e<<3|t()>>4,r[o++]=e<<4|t()>>3,r[o++]=e<<5|t()>>2,r[o++]=e<<6|t()>>1,r[o++]=e<<7|t();new Response(new Blob([r]).stream().pipeThrough(new DecompressionStream(\"<format>\")),{headers:{\"Content-Type\":\"text/javascript\"}}).blob().then(n=>(import(n=URL.createObjectURL(n)),URL.revokeObjectURL(n)))",
64
+ "base64": "fetch(\"data:;base64,<script>\").then(e=>new Response(e.body.pipeThrough(new DecompressionStream(\"<format>\")),{headers:{\"Content-Type\":\"text/javascript\"}}).blob()).then(e=>(import(e=URL.createObjectURL(e)),URL.revokeObjectURL(e)))",
65
+ "css": "document.head.appendChild(document.createElement(\"style\")).innerHTML=\"<style>\"",
66
+ "icon": "document.querySelector(\"link[rel=icon]\").href=\"<icon>\"",
67
+ "importmeta": "{let e=import.meta,r=e.resolve,l=e.url=new URL(\"<path>\",location).href;e.resolve=function(t){return/^\\.{0,2}\\//.test(t)?new URL(t,l).href:r.apply(this,arguments)}}"
68
+ };
69
+ //#endregion
70
+ //#region _dist/getTemplate.js
71
+ function split2(str, separator) {
72
+ const s = str.split(separator);
73
+ if (s.length !== 2) throw Error("s.length!==2");
74
+ return s;
75
+ }
76
+ const files = {
77
+ base64: raw.base64,
78
+ base128: raw.base128,
79
+ assets: split2(raw.assets, "{\"\":\"\"}"),
80
+ css: split2(raw.css, "\"<style>\""),
81
+ icon: split2(raw.icon, "\"<icon>\""),
82
+ importmeta: split2(raw.importmeta, "\"<path>\"")
83
+ };
84
+ const template = {
85
+ base(script, format, useBase128, compressor) {
86
+ script = compress(format, script, useBase128, compressor);
87
+ if (useBase128) return files.base128.replace("<format>", format).split("\"<script>\"", 2).join(script);
88
+ return files.base64.replace("<format>", format).split("<script>", 2).join(script);
89
+ },
90
+ assets(assetsJSON) {
91
+ return files.assets.join(assetsJSON);
92
+ },
93
+ css(cssSource) {
94
+ return files.css.join(JSON.stringify(cssSource));
95
+ },
96
+ icon(dataURL) {
97
+ return files.icon.join(JSON.stringify(dataURL));
98
+ },
99
+ importmeta(p) {
100
+ return files.importmeta.join(JSON.stringify(p));
101
+ }
102
+ };
103
+ //#endregion
104
+ //#region _dist/dataurl.js
105
+ function bufferToDataURL(name, b) {
106
+ return /\.svg$/i.test(name) ? svgToTinyDataUri(b.toString()) : `data:${mime.getType(name)};base64,${b.toString("base64")}`;
107
+ }
108
+ //#endregion
109
+ //#region _dist/kB.js
110
+ function kB(size) {
111
+ return `${size / 1e3} kB`;
112
+ }
113
+ //#endregion
114
+ //#region _dist/options.js
115
+ const defaultHtmlMinifierTerserOptions = {
116
+ removeAttributeQuotes: true,
117
+ removeComments: true,
118
+ collapseWhitespace: true,
119
+ removeOptionalTags: true,
120
+ removeRedundantAttributes: true,
121
+ minifyJS: false
122
+ };
123
+ function getInnerOptions(opt) {
124
+ opt ||= {};
125
+ return {
126
+ enableCompress: opt.enableCompress ?? true,
127
+ rename: opt.rename == null ? void 0 : String(opt.rename),
128
+ htmlMinifierTerser: opt.htmlMinifierTerser == null || opt.htmlMinifierTerser === true ? defaultHtmlMinifierTerserOptions : opt.htmlMinifierTerser,
129
+ tryInlineHtmlAssets: opt.tryInlineHtmlAssets ?? true,
130
+ removeInlinedAssetFiles: opt.removeInlinedAssetFiles ?? true,
131
+ tryInlineHtmlPublicIcon: opt.tryInlineHtmlPublicIcon ?? true,
132
+ removeInlinedPublicIconFiles: opt.removeInlinedPublicIconFiles ?? true,
133
+ useBase128: opt.useBase128 ?? true,
134
+ compressFormat: opt.compressFormat ? compressFormatAlias.hasOwnProperty(opt.compressFormat) ? compressFormatAlias[opt.compressFormat] : String(opt.compressFormat) : "deflate-raw",
135
+ compressor: typeof opt.compressor == "function" ? opt.compressor : void 0,
136
+ useImportMetaPolyfill: opt.useImportMetaPolyfill ?? true
137
+ };
138
+ }
139
+ //#endregion
140
+ //#region _dist/cutPrefix.js
141
+ function cutPrefix(str, prefix) {
142
+ return str.startsWith(prefix) ? str.slice(prefix.length) : str;
143
+ }
144
+ //#endregion
145
+ //#region _dist/index.js
146
+ function singleFileCompression(opt) {
147
+ let conf;
148
+ const innerOptions = getInnerOptions(opt);
149
+ return {
150
+ name: "singleFileCompression",
151
+ enforce: "post",
152
+ config(...args) {
153
+ return setConfig.call(this, innerOptions, ...args);
154
+ },
155
+ configResolved(c) {
156
+ conf = c;
157
+ },
158
+ generateBundle(outputOptions, bundle) {
159
+ return generateBundle(bundle, conf, innerOptions);
160
+ }
161
+ };
162
+ }
163
+ function setConfig(opt, config, env) {
164
+ config.base ??= "./";
165
+ const build = config.build ??= {};
166
+ build.cssCodeSplit ??= false;
167
+ build.assetsInlineLimit ??= () => true;
168
+ build.modulePreload ?? build.polyfillModulePreload ?? (build.modulePreload = { polyfill: false });
169
+ if (this.meta.rolldownVersion) {
170
+ const rolldownOptions = build.rolldownOptions ?? build.rollupOptions ?? (build.rolldownOptions = {});
171
+ for (const output of [rolldownOptions.output ??= {}].flat(1)) output.codeSplitting ?? output.inlineDynamicImports ?? (output.codeSplitting = false);
172
+ } else {
173
+ const rollupOptions = build.rollupOptions ??= {};
174
+ for (const output of [rollupOptions.output ??= {}].flat(1)) output.inlineDynamicImports ??= true;
175
+ }
46
176
  }
47
177
  async function generateBundle(bundle, config, options) {
48
- console.log(pc.reset('\n\n') + pc.cyan('vite-plugin-singlefile-compression ' + version) + pc.green(' building...'));
49
- // rename
50
- if (options.rename
51
- && options.rename !== "index.html"
52
- && ("index.html" in bundle)
53
- && !(options.rename in bundle)) {
54
- bundle[options.rename] = bundle["index.html"];
55
- bundle[options.rename].fileName = options.rename;
56
- delete bundle["index.html"];
57
- }
58
- const distURL = pathToFileURL(config.build.outDir).href + '/',
59
- /** "assets/" */
60
- assetsDir = path.posix.join(config.build.assetsDir, '/'),
61
- /** "./assets/" */
62
- assetsDirWithBase = config.base + assetsDir,
63
- /** '[href^="./assets/"]' */
64
- assetsHrefSelector = `[href^="${assetsDirWithBase}"]`,
65
- /** '[src^="./assets/"]' */
66
- assetsSrcSelector = `[src^="${assetsDirWithBase}"]`, fakeScript = `_vitePluginSinglefileCompression(${Date.now()})`, globalDelete = new Set(), globalDoNotDelete = new Set(), globalRemoveDistFileNames = new Set(), globalAssetsDataURL = {}, globalPublicFilesCache = {},
67
- /** format: ["assets/index-XXXXXXXX.js"] */
68
- bundleAssetsNames = [],
69
- /** format: ["index.html"] */
70
- bundleHTMLNames = [];
71
- for (const name of Object.keys(bundle)) {
72
- if (name.startsWith(assetsDir))
73
- bundleAssetsNames.push(name);
74
- else if (name.endsWith('.html'))
75
- bundleHTMLNames.push(name);
76
- }
77
- for (const htmlFileName of bundleHTMLNames) {
78
- console.log("\n " + pc.underline(pc.cyan(distURL) + pc.greenBright(bundle[htmlFileName].fileName)));
79
- // init
80
- const htmlChunk = bundle[htmlFileName], oldHTML = htmlChunk.source, dom = new JSDOM(oldHTML), document = dom.window.document, thisDel = new Set(), newJSCode = [], scriptElement = document.querySelector(`script[type=module]${assetsSrcSelector}`), scriptName = scriptElement ? cutPrefix(scriptElement.src, config.base) : '';
81
- let oldSize = oldHTML.length;
82
- // fill fake script
83
- if (scriptElement) {
84
- scriptElement.remove();
85
- scriptElement.removeAttribute('src');
86
- scriptElement.innerHTML = fakeScript;
87
- document.body.appendChild(scriptElement);
88
- }
89
- else {
90
- document.body.insertAdjacentHTML('beforeend', `<script type="module">${fakeScript}</script>`);
91
- }
92
- // get css tag
93
- let allCSS = '';
94
- for (const element of document.querySelectorAll(`link[rel=stylesheet]${assetsHrefSelector}`)) {
95
- const name = cutPrefix(element.href, config.base);
96
- thisDel.add(name);
97
- const css = bundle[name];
98
- const cssSource = css.source;
99
- if (cssSource) {
100
- oldSize += cssSource.length;
101
- // do not delete not inlined asset
102
- for (const name of bundleAssetsNames) {
103
- if (cssSource.includes(name.slice(assetsDir.length)))
104
- globalDoNotDelete.add(name);
105
- }
106
- // add script for load css
107
- allCSS += cssSource.replace(/\n$/, '');
108
- }
109
- // remove tag
110
- element.remove();
111
- }
112
- newJSCode.push(template.css(allCSS));
113
- // inline html assets
114
- const assetsDataURL = {};
115
- if (options.tryInlineHtmlAssets) {
116
- for (const element of document.querySelectorAll(assetsSrcSelector)) {
117
- const name = cutPrefix(element.src, assetsDirWithBase);
118
- if (name.endsWith('.js'))
119
- continue;
120
- if (!Object.prototype.hasOwnProperty.call(assetsDataURL, name)) {
121
- const bundleName = assetsDir + name;
122
- const a = bundle[bundleName];
123
- if (!a)
124
- continue;
125
- thisDel.add(bundleName);
126
- oldSize += a.source.length;
127
- if (!Object.prototype.hasOwnProperty.call(globalAssetsDataURL, name))
128
- globalAssetsDataURL[name] = bufferToDataURL(name, Buffer.from(
129
- //@ts-ignore
130
- a.source));
131
- assetsDataURL[name] = globalAssetsDataURL[name];
132
- }
133
- element.src = `data:${name}`;
134
- }
135
- }
136
- // inline html icon
137
- if (options.tryInlineHtmlPublicIcon) {
138
- let needInline = true;
139
- let iconName = 'favicon.ico';
140
- // replace tag
141
- const element = document.querySelector(`link[rel=icon][href^="${config.base}"], link[rel="shortcut icon"][href^="${config.base}"]`);
142
- if (element) {
143
- iconName = cutPrefix(element.href, config.base);
144
- if (bundleAssetsNames.includes(iconName)) {
145
- needInline = false;
146
- }
147
- else {
148
- element.rel = 'icon';
149
- element.href = 'data:';
150
- }
151
- }
152
- if (needInline) {
153
- // inline
154
- try {
155
- if (!Object.prototype.hasOwnProperty.call(globalPublicFilesCache, iconName)) {
156
- // dist/favicon.ico
157
- let Path = path.join(config.build.outDir, iconName);
158
- if (fs.existsSync(Path)) {
159
- globalRemoveDistFileNames.add(iconName);
160
- }
161
- else {
162
- // public/favicon.ico
163
- Path = path.join(config.publicDir, iconName);
164
- }
165
- // read
166
- const b = fs.readFileSync(Path);
167
- globalPublicFilesCache[iconName] = {
168
- dataURL: bufferToDataURL(iconName, b),
169
- size: b.length
170
- };
171
- }
172
- const { dataURL, size } = globalPublicFilesCache[iconName];
173
- oldSize += size;
174
- newJSCode.push(template.icon(dataURL));
175
- if (!element) {
176
- // add link icon tag
177
- document.head.insertAdjacentHTML('beforeend', '<link rel="icon" href="data:">');
178
- }
179
- }
180
- catch (e) {
181
- if (element)
182
- console.error(e);
183
- }
184
- }
185
- }
186
- // generate html
187
- htmlChunk.source = dom.serialize();
188
- // minify html
189
- if (options.htmlMinifierTerser)
190
- htmlChunk.source = await htmlMinify(htmlChunk.source, options.htmlMinifierTerser);
191
- // fill script
192
- function inlineHtmlAssets() {
193
- if (options.tryInlineHtmlAssets) {
194
- // add script for load html assets
195
- const assetsJSON = JSON.stringify(assetsDataURL);
196
- if (assetsJSON !== '{}')
197
- newJSCode.push(template.assets(assetsJSON));
198
- }
199
- }
200
- if (scriptElement) {
201
- thisDel.add(scriptName);
202
- let { code } = bundle[scriptName];
203
- oldSize += code.length;
204
- code = code.replace(/;?\n?$/, '');
205
- // do not delete not inlined asset
206
- for (const name of bundleAssetsNames) {
207
- const assetName = name.slice(assetsDir.length);
208
- if (code.includes(assetName)) {
209
- globalDoNotDelete.add(name);
210
- delete assetsDataURL[assetName];
211
- }
212
- }
213
- inlineHtmlAssets();
214
- if (options.useImportMetaPolyfill)
215
- newJSCode.push(template.importmeta(scriptName));
216
- // 此 polyfill 仅在以下选项的值为 true 时需要。
217
- // config.build.rollupOptions.output.inlineDynamicImports
218
- if (code.includes("__VITE_PRELOAD__"))
219
- newJSCode.push("var __VITE_PRELOAD__");
220
- newJSCode.push(code);
221
- }
222
- else {
223
- inlineHtmlAssets();
224
- }
225
- htmlChunk.source = htmlChunk.source.split(fakeScript, 2).join(template.base(newJSCode.join(';'), options.compressFormat, options.useBase128, options.compressor));
226
- // log
227
- console.log(" " + pc.gray(kB(oldSize) + " -> ") + pc.cyanBright(kB(htmlChunk.source.length)) + '\n');
228
- // delete assets
229
- for (const name of thisDel) {
230
- globalDelete.add(name);
231
- }
232
- }
233
- if (options.removeInlinedAssetFiles) {
234
- // delete inlined assets
235
- for (const name of globalDelete) {
236
- // do not delete not inlined asset
237
- if (!globalDoNotDelete.has(name))
238
- delete bundle[name];
239
- }
240
- }
241
- if (options.removeInlinedPublicIconFiles) {
242
- // delete inlined public files
243
- for (const name of globalRemoveDistFileNames) {
244
- try {
245
- fs.unlinkSync(path.join(config.build.outDir, name));
246
- }
247
- catch (e) {
248
- console.error(e);
249
- }
250
- }
251
- }
252
- console.log(pc.green('Finish.') + pc.reset('\n'));
178
+ console.log(pc.reset("\n\n") + pc.cyan("vite-plugin-singlefile-compression " + version) + " " + (options.enableCompress ? pc.green(options.compressFormat) : pc.red("disable compress")));
179
+ if (options.rename && options.rename != "index.html" && Object.prototype.hasOwnProperty.call(bundle, "index.html") && !Object.prototype.hasOwnProperty.call(bundle, options.rename)) {
180
+ bundle[options.rename] = bundle["index.html"];
181
+ bundle[options.rename].fileName = options.rename;
182
+ delete bundle["index.html"];
183
+ }
184
+ const distURL = pathToFileURL(config.build.outDir).href + "/", assetsDir = path.posix.join(config.build.assetsDir, "/"), assetsDirWithBase = config.base + assetsDir, assetsHrefSelector = `[href^="${assetsDirWithBase}"]`, assetsSrcSelector = `[src^="${assetsDirWithBase}"]`, fakeScript = `_vitePluginSinglefileCompression(${Date.now()})`, globalDelete = /* @__PURE__ */ new Set(), globalDoNotDelete = /* @__PURE__ */ new Set(), globalRemoveDistFileNames = /* @__PURE__ */ new Set(), globalAssetsDataURL = {}, globalPublicFilesCache = {}, bundleAssetsNames = [], bundleHTMLNames = [];
185
+ for (const name in bundle) if (name.startsWith(assetsDir)) bundleAssetsNames.push(name);
186
+ else if (/\.html$/i.test(name)) bundleHTMLNames.push(name);
187
+ for (const htmlFileName of bundleHTMLNames) {
188
+ console.log("\n " + pc.underline(pc.cyan(distURL) + pc.greenBright(bundle[htmlFileName].fileName)));
189
+ const htmlChunk = bundle[htmlFileName], oldHTML = htmlChunk.source, dom = new JSDOM(oldHTML), document = dom.window.document, thisDel = /* @__PURE__ */ new Set(), newJSCode = [], scriptElement = document.querySelector(`script[type=module]${assetsSrcSelector}`), scriptName = scriptElement ? cutPrefix(scriptElement.src, config.base) : "";
190
+ let oldSize = oldHTML.length;
191
+ if (scriptElement) {
192
+ scriptElement.remove();
193
+ scriptElement.removeAttribute("src");
194
+ scriptElement.removeAttribute("crossorigin");
195
+ scriptElement.innerHTML = fakeScript;
196
+ document.body.appendChild(scriptElement);
197
+ } else document.body.insertAdjacentHTML("beforeend", `<script type="module">${fakeScript}<\/script>`);
198
+ let allCSS = "";
199
+ const linkStylesheet = document.querySelectorAll(`link[rel=stylesheet]${assetsHrefSelector}`);
200
+ for (const element of linkStylesheet) {
201
+ const name = cutPrefix(element.href, config.base);
202
+ thisDel.add(name);
203
+ const cssSource = bundle[name].source;
204
+ if (cssSource) {
205
+ oldSize += cssSource.length;
206
+ for (const name of bundleAssetsNames) if (cssSource.includes(name.slice(assetsDir.length))) globalDoNotDelete.add(name);
207
+ allCSS += cssSource.replace(/(\/\*[^*]*\*\/)?\s*$/, "");
208
+ }
209
+ if (options.enableCompress) element.remove();
210
+ }
211
+ if (allCSS) if (options.enableCompress) newJSCode.push(template.css(allCSS));
212
+ else {
213
+ const e = document.createElement("style");
214
+ e.innerHTML = allCSS;
215
+ linkStylesheet[0].before(e);
216
+ for (const e of linkStylesheet) e.remove();
217
+ }
218
+ const assetsDataURL = {};
219
+ if (options.tryInlineHtmlAssets) for (const element of document.querySelectorAll(assetsSrcSelector)) {
220
+ const name = cutPrefix(element.src, assetsDirWithBase);
221
+ if (/\.js$/i.test(name)) continue;
222
+ if (!options.enableCompress || !Object.prototype.hasOwnProperty.call(assetsDataURL, name)) {
223
+ const bundleName = assetsDir + name;
224
+ const a = bundle[bundleName];
225
+ if (!a) continue;
226
+ thisDel.add(bundleName);
227
+ oldSize += a.source.length;
228
+ let dataURL;
229
+ if (Object.prototype.hasOwnProperty.call(globalAssetsDataURL, name)) dataURL = globalAssetsDataURL[name];
230
+ else globalAssetsDataURL[name] = dataURL = bufferToDataURL(name, Buffer.from(a.source));
231
+ if (options.enableCompress) assetsDataURL[name] = dataURL;
232
+ else element.src = dataURL;
233
+ }
234
+ if (options.enableCompress) element.src = `data:${name}`;
235
+ }
236
+ if (options.tryInlineHtmlPublicIcon) {
237
+ let needInline = true;
238
+ let iconName = "favicon.ico";
239
+ const element = document.querySelector(`link[rel=icon][href^="${config.base}"], link[rel="shortcut icon"][href^="${config.base}"]`);
240
+ if (element) {
241
+ iconName = cutPrefix(element.href, config.base);
242
+ if (bundleAssetsNames.includes(iconName)) needInline = false;
243
+ else {
244
+ element.rel = "icon";
245
+ element.href = "data:";
246
+ }
247
+ }
248
+ if (needInline) try {
249
+ if (!Object.prototype.hasOwnProperty.call(globalPublicFilesCache, iconName)) {
250
+ let Path = path.join(config.build.outDir, iconName);
251
+ if (fs.existsSync(Path)) globalRemoveDistFileNames.add(iconName);
252
+ else Path = path.join(config.publicDir, iconName);
253
+ const b = fs.readFileSync(Path);
254
+ globalPublicFilesCache[iconName] = {
255
+ dataURL: bufferToDataURL(iconName, b),
256
+ size: b.length
257
+ };
258
+ }
259
+ const { dataURL, size } = globalPublicFilesCache[iconName];
260
+ oldSize += size;
261
+ if (options.enableCompress) {
262
+ newJSCode.push(template.icon(dataURL));
263
+ if (!element) document.head.insertAdjacentHTML("beforeend", "<link rel=\"icon\" href=\"data:\">");
264
+ } else if (element) element.href = dataURL;
265
+ else {
266
+ const e = document.head.appendChild(document.createElement("link"));
267
+ e.rel = "icon";
268
+ e.href = dataURL;
269
+ }
270
+ } catch (e) {
271
+ if (element) console.error(e);
272
+ }
273
+ }
274
+ htmlChunk.source = dom.serialize();
275
+ if (options.htmlMinifierTerser) htmlChunk.source = await minify(htmlChunk.source, options.htmlMinifierTerser);
276
+ function inlineHtmlAssets() {
277
+ if (options.tryInlineHtmlAssets) {
278
+ const assetsJSON = JSON.stringify(assetsDataURL);
279
+ if (assetsJSON !== "{}") newJSCode.push(template.assets(assetsJSON));
280
+ }
281
+ }
282
+ if (scriptElement) {
283
+ thisDel.add(scriptName);
284
+ let { code } = bundle[scriptName];
285
+ oldSize += code.length;
286
+ code = code.replace(/;?\n?$/, "");
287
+ for (const name of bundleAssetsNames) {
288
+ const assetName = name.slice(assetsDir.length);
289
+ if (code.includes(assetName)) {
290
+ globalDoNotDelete.add(name);
291
+ delete assetsDataURL[assetName];
292
+ }
293
+ }
294
+ inlineHtmlAssets();
295
+ if (options.useImportMetaPolyfill) newJSCode.push(template.importmeta(scriptName));
296
+ if (/\b__VITE_PRELOAD__\b/.test(code)) newJSCode.push("var __VITE_PRELOAD__");
297
+ newJSCode.push(code);
298
+ } else inlineHtmlAssets();
299
+ let outputScript = newJSCode.join(";");
300
+ if (options.enableCompress) outputScript = template.base(outputScript, options.compressFormat, options.useBase128, options.compressor);
301
+ else outputScript = outputScript.replaceAll("<\/script", "<\\/script");
302
+ htmlChunk.source = htmlChunk.source.split(fakeScript, 2).join(outputScript);
303
+ console.log(" " + pc.gray(kB(oldSize) + " -> ") + pc.cyanBright(kB(htmlChunk.source.length)) + "\n");
304
+ for (const name of thisDel) globalDelete.add(name);
305
+ }
306
+ if (options.removeInlinedAssetFiles) {
307
+ for (const name of globalDelete) if (!globalDoNotDelete.has(name)) delete bundle[name];
308
+ }
309
+ if (options.removeInlinedPublicIconFiles) for (const name of globalRemoveDistFileNames) try {
310
+ fs.unlinkSync(path.join(config.build.outDir, name));
311
+ } catch (e) {
312
+ console.error(e);
313
+ }
314
+ console.log(pc.green("Finish.") + pc.reset("\n"));
253
315
  }
316
+ //#endregion
317
+ export { singleFileCompression as default, singleFileCompression, defaultHtmlMinifierTerserOptions };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vite-plugin-singlefile-compression",
3
- "version": "2.0.14",
3
+ "version": "2.1.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.",
@@ -11,7 +11,7 @@
11
11
  ],
12
12
  "type": "module",
13
13
  "scripts": {
14
- "build": "rimraf dist && tsc && node build.js && es-check es2021 --checkFeatures --module dist/**/*.js && cd test && node --run build",
14
+ "build": "rimraf dist _dist && tsc && node build.js && cd test && node --run build",
15
15
  "prepublishOnly": "node --run build"
16
16
  },
17
17
  "repository": {
@@ -57,13 +57,14 @@
57
57
  },
58
58
  "devDependencies": {
59
59
  "@types/jsdom": ">=28.0.0",
60
- "@types/node": ">=25.5.0",
61
- "es-check": ">=9.6.2",
62
- "esbuild": ">=0.27.4",
60
+ "@types/node": "^22.19.15",
61
+ "esbuild": "^0.27.4",
62
+ "marked": "^17.0.4",
63
63
  "rimraf": ">=6.1.3",
64
64
  "rolldown": ">=1.0.0-rc.9",
65
+ "rolldown-plugin-dts": "^0.22.5",
65
66
  "rollup": ">=4.59.0",
66
67
  "typescript": ">=5.9.3",
67
68
  "vite": ">=8.0.0"
68
69
  }
69
- }
70
+ }
@@ -1,12 +0,0 @@
1
- import zlib from 'zlib';
2
- declare const compressors: {
3
- "deflate-raw"(buf: zlib.InputType): Buffer;
4
- deflate(buf: zlib.InputType): Buffer;
5
- gzip(buf: zlib.InputType): Buffer;
6
- brotli: typeof zlib.brotliCompressSync;
7
- zstd: (buf: zlib.InputType) => NonSharedBuffer;
8
- };
9
- export type compressor = ((buf: zlib.InputType) => (Buffer | Uint8Array));
10
- export type compressFormat = keyof typeof compressors;
11
- export declare function compress(format: compressFormat, buf: zlib.InputType, useBase128: boolean, compressor: compressor | undefined): any;
12
- export {};
package/dist/compress.js DELETED
@@ -1,54 +0,0 @@
1
- import base128 from "base128-ascii";
2
- import zlib from 'zlib';
3
- const compressors = {
4
- "deflate-raw"(buf) {
5
- return zlib.deflateRawSync(buf, {
6
- level: zlib.constants.Z_BEST_COMPRESSION,
7
- });
8
- },
9
- deflate(buf) {
10
- return zlib.deflateSync(buf, {
11
- level: zlib.constants.Z_BEST_COMPRESSION,
12
- });
13
- },
14
- gzip(buf) {
15
- return zlib.gzipSync(buf, {
16
- level: zlib.constants.Z_BEST_COMPRESSION,
17
- });
18
- },
19
- brotli: zlib.brotliCompressSync,
20
- zstd: zlib.zstdCompressSync && function (buf) {
21
- return zlib.zstdCompressSync(buf, {
22
- params: {
23
- [zlib.constants.ZSTD_c_compressionLevel]: 19
24
- }
25
- });
26
- },
27
- };
28
- function switchCompressor(format) {
29
- if (Object.prototype.hasOwnProperty.call(compressors, format)) {
30
- const f = compressors[format];
31
- if (f)
32
- return f;
33
- throw Error(`Could not get compressor: Please upgrade node.js or set your compressor function.`);
34
- }
35
- let funcName = format + 'CompressSync';
36
- if (Object.prototype.hasOwnProperty.call(zlib, funcName)) {
37
- const f = zlib[funcName];
38
- if (typeof f == 'function')
39
- return f;
40
- }
41
- throw Error(`Could not get compressor: Unknown compress format '${format}', please set your compressor function.`);
42
- }
43
- export function compress(format, buf, useBase128, compressor) {
44
- if (typeof compressor != 'function')
45
- compressor = switchCompressor(format);
46
- const outBuf = compressor(buf);
47
- if (useBase128)
48
- return base128.encode(outBuf).toJSTemplateLiterals();
49
- if (outBuf instanceof Buffer)
50
- return outBuf.toString('base64');
51
- if (typeof outBuf.toBase64 == 'function') // Uint8Array Node25
52
- return outBuf.toBase64();
53
- return Buffer.from(outBuf).toString('base64');
54
- }
@@ -1 +0,0 @@
1
- export declare function cutPrefix(str: string, prefix: string): string;
package/dist/cutPrefix.js DELETED
@@ -1,5 +0,0 @@
1
- export function cutPrefix(str, prefix) {
2
- return str.startsWith(prefix)
3
- ? str.slice(prefix.length)
4
- : str;
5
- }
package/dist/dataurl.d.ts DELETED
@@ -1 +0,0 @@
1
- export declare function bufferToDataURL(name: string, b: Buffer): string;
package/dist/dataurl.js DELETED
@@ -1,7 +0,0 @@
1
- import svgToTinyDataUri from "mini-svg-data-uri";
2
- import mime from 'mime';
3
- export function bufferToDataURL(name, b) {
4
- return name.endsWith('.svg')
5
- ? svgToTinyDataUri(b.toString())
6
- : `data:${mime.getType(name)};base64,${b.toString('base64')}`;
7
- }
@@ -1,8 +0,0 @@
1
- import { compressFormat, compressor } from './compress.js';
2
- export declare const template: {
3
- base(script: string, format: compressFormat, useBase128: boolean, compressor: compressor | undefined): string;
4
- assets(assetsJSON: string): string;
5
- css(cssSource: string): string;
6
- icon(dataURL: string): string;
7
- importmeta(p: string): string;
8
- };
@@ -1,45 +0,0 @@
1
- import fs from 'fs';
2
- import { fileURLToPath } from 'url';
3
- import { compress } from './compress.js';
4
- function r(name) {
5
- return fs.readFileSync(fileURLToPath(new URL(`./template/${name}.js`, import.meta.url))).toString();
6
- }
7
- function rt(name, template) {
8
- const s = r(name).split(template);
9
- if (s.length !== 2)
10
- throw Error("s.length!==2");
11
- return s;
12
- }
13
- const files = {
14
- base64: r('base64'),
15
- base128: r('base128'),
16
- assets: rt('assets', '{"":""}'),
17
- css: rt('css', '"<style>"'),
18
- icon: rt('icon', '"<icon>"'),
19
- importmeta: rt('importmeta', '"<path>"'),
20
- };
21
- export const template = {
22
- base(script, format, useBase128, compressor) {
23
- script = compress(format, script, useBase128, compressor);
24
- if (useBase128) {
25
- return files.base128
26
- .replace("<format>", format)
27
- .split('"<script>"', 2).join(script);
28
- }
29
- return files.base64
30
- .replace("<format>", format)
31
- .split("<script>", 2).join(script);
32
- },
33
- assets(assetsJSON) {
34
- return files.assets.join(assetsJSON);
35
- },
36
- css(cssSource) {
37
- return files.css.join(JSON.stringify(cssSource));
38
- },
39
- icon(dataURL) {
40
- return files.icon.join(JSON.stringify(dataURL));
41
- },
42
- importmeta(p) {
43
- return files.importmeta.join(JSON.stringify(p));
44
- },
45
- };
@@ -1 +0,0 @@
1
- export declare const version: string;
@@ -1,3 +0,0 @@
1
- import fs from 'fs';
2
- import { fileURLToPath } from 'url';
3
- export const version = JSON.parse(fs.readFileSync(fileURLToPath(new URL("../package.json", import.meta.url))).toString()).version;
package/dist/kB.d.ts DELETED
@@ -1 +0,0 @@
1
- export declare function kB(size: number): string;
package/dist/kB.js DELETED
@@ -1,3 +0,0 @@
1
- export function kB(size) {
2
- return `${size / 1000} kB`;
3
- }
package/dist/options.d.ts DELETED
@@ -1,70 +0,0 @@
1
- import { Options as htmlMinifierOptions } from 'html-minifier-terser';
2
- import { compressFormat, compressor } from './compress.js';
3
- export interface Options {
4
- /**
5
- * Rename index.html
6
- */
7
- rename?: string;
8
- /**
9
- * https://github.com/terser/html-minifier-terser?tab=readme-ov-file#options-quick-reference
10
- * @default defaultHtmlMinifierTerserOptions
11
- */
12
- htmlMinifierTerser?: htmlMinifierOptions | boolean;
13
- /**
14
- * Try inline html used assets, if inlined or not used in JS.
15
- * @default true
16
- */
17
- tryInlineHtmlAssets?: boolean;
18
- /**
19
- * Remove inlined asset files.
20
- * @default true
21
- */
22
- removeInlinedAssetFiles?: boolean;
23
- /**
24
- * Try inline html icon, if icon is in public dir.
25
- * @default true
26
- */
27
- tryInlineHtmlPublicIcon?: boolean;
28
- /**
29
- * Remove inlined html icon files.
30
- * @default true
31
- */
32
- removeInlinedPublicIconFiles?: boolean;
33
- /**
34
- * Use Base128 to encode gzipped script.
35
- * If false, use Base64.
36
- * https://www.npmjs.com/package/base128-ascii
37
- * @default true
38
- */
39
- useBase128?: boolean;
40
- /**
41
- * Compress format.
42
- * https://developer.mozilla.org/en-US/docs/Web/API/DecompressionStream/DecompressionStream
43
- * @type "deflate-raw" | "deflate" | "gzip" | "brotli" | "zstd"
44
- * @default "deflate-raw"
45
- */
46
- compressFormat?: compressFormat;
47
- /**
48
- * Custom compressor.
49
- */
50
- compressor?: compressor;
51
- /**
52
- * Use import.meta polyfill.
53
- * @default true
54
- */
55
- useImportMetaPolyfill?: boolean;
56
- }
57
- export declare const defaultHtmlMinifierTerserOptions: htmlMinifierOptions;
58
- export interface innerOptions {
59
- rename?: string;
60
- htmlMinifierTerser: htmlMinifierOptions | false;
61
- tryInlineHtmlAssets: boolean;
62
- removeInlinedAssetFiles: boolean;
63
- tryInlineHtmlPublicIcon: boolean;
64
- removeInlinedPublicIconFiles: boolean;
65
- useBase128: boolean;
66
- compressFormat: compressFormat;
67
- compressor?: compressor;
68
- useImportMetaPolyfill: boolean;
69
- }
70
- export declare function getInnerOptions(opt?: Options): innerOptions;
package/dist/options.js DELETED
@@ -1,25 +0,0 @@
1
- export const defaultHtmlMinifierTerserOptions = {
2
- removeAttributeQuotes: true,
3
- removeComments: true,
4
- collapseWhitespace: true,
5
- removeOptionalTags: true,
6
- removeRedundantAttributes: true,
7
- minifyJS: false,
8
- };
9
- export function getInnerOptions(opt) {
10
- opt ||= {};
11
- return {
12
- rename: opt.rename && opt.rename.replace(/(\.(html?)?)?$/, '.html'),
13
- htmlMinifierTerser: opt.htmlMinifierTerser == null || opt.htmlMinifierTerser === true
14
- ? defaultHtmlMinifierTerserOptions
15
- : opt.htmlMinifierTerser,
16
- tryInlineHtmlAssets: opt.tryInlineHtmlAssets ?? true,
17
- removeInlinedAssetFiles: opt.removeInlinedAssetFiles ?? true,
18
- tryInlineHtmlPublicIcon: opt.tryInlineHtmlPublicIcon ?? true,
19
- removeInlinedPublicIconFiles: opt.removeInlinedPublicIconFiles ?? true,
20
- useBase128: opt.useBase128 ?? true,
21
- compressFormat: opt.compressFormat || "deflate-raw",
22
- compressor: typeof opt.compressor == 'function' ? opt.compressor : undefined,
23
- useImportMetaPolyfill: opt.useImportMetaPolyfill ?? true,
24
- };
25
- }
@@ -1 +0,0 @@
1
- {let e={"":""};for(let o in e)for(let s of document.querySelectorAll(`[src="data:${o}"]`))s.src=e[o]}
@@ -1 +0,0 @@
1
- var a="<script>",i=a.length,r=new Uint8Array(Math.floor(i/8*7)),c=0,o=0,e,t=()=>(e=a.charCodeAt(c++))>127?e=0:e;for(;c<i;)r[o++]=t()<<1|t()>>6,r[o++]=e<<2|t()>>5,r[o++]=e<<3|t()>>4,r[o++]=e<<4|t()>>3,r[o++]=e<<5|t()>>2,r[o++]=e<<6|t()>>1,r[o++]=e<<7|t();new Response(new Blob([r]).stream().pipeThrough(new DecompressionStream("<format>")),{headers:{"Content-Type":"text/javascript"}}).blob().then(n=>import(n=URL.createObjectURL(n)).finally(h=>URL.revokeObjectURL(n)))
@@ -1 +0,0 @@
1
- fetch("data:;base64,<script>").then(e=>new Response(e.body.pipeThrough(new DecompressionStream("<format>")),{headers:{"Content-Type":"text/javascript"}}).blob()).then(e=>import(e=URL.createObjectURL(e)).finally(t=>URL.revokeObjectURL(e)))
@@ -1 +0,0 @@
1
- document.head.appendChild(document.createElement("style")).innerHTML="<style>"
@@ -1 +0,0 @@
1
- document.querySelector("link[rel=icon]").href="<icon>"
@@ -1 +0,0 @@
1
- {let e=import.meta,r=e.resolve,l=e.url=new URL("<path>",location).href;e.resolve=function(t){return/^\.{0,2}\//.test(t)?new URL(t,l).href:r.apply(this,arguments)}}