vite-plugin-singlefile-compression 2.0.13 → 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 +1 -1
- package/README.md +57 -48
- package/dist/index.d.ts +92 -3
- package/dist/index.js +311 -239
- package/package.json +23 -17
- package/browser.min.js +0 -1
- package/dist/compress.d.ts +0 -12
- package/dist/compress.js +0 -54
- package/dist/cutPrefix.d.ts +0 -1
- package/dist/cutPrefix.js +0 -5
- package/dist/dataurl.d.ts +0 -1
- package/dist/dataurl.js +0 -7
- package/dist/getTemplate.d.ts +0 -8
- package/dist/getTemplate.js +0 -45
- package/dist/getVersion.d.ts +0 -1
- package/dist/getVersion.js +0 -3
- package/dist/kB.d.ts +0 -1
- package/dist/kB.js +0 -3
- package/dist/options.d.ts +0 -70
- package/dist/options.js +0 -25
- package/dist/template/assets.js +0 -1
- package/dist/template/base128.js +0 -1
- package/dist/template/base64.js +0 -1
- package/dist/template/css.js +0 -1
- package/dist/template/icon.js +0 -1
- package/dist/template/importmeta.js +0 -1
package/LICENSE.txt
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
The MIT License (MIT)
|
|
2
|
-
Copyright ©
|
|
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`,
|
|
15
|
+
Then modify `vite.config.ts`, like [test/vite.config.ts](test/vite.config.ts)
|
|
16
16
|
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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
|
|
28
|
+
Then use hash history, like [test/src/router/index.ts](test/src/router/index.ts#L5)
|
|
31
29
|
|
|
32
|
-
```
|
|
33
|
-
const router = createRouter({
|
|
34
|
-
|
|
35
|
-
|
|
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?:
|
|
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,22 +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
|
-
vite
|
|
122
|
-
✓
|
|
123
|
-
rendering chunks (1)...
|
|
128
|
+
vite v8.0.0 building client environment for production...
|
|
129
|
+
✓ 315 modules transformed.
|
|
124
130
|
|
|
125
|
-
|
|
131
|
+
|
|
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
|
-
|
|
135
|
+
1085.847 kB -> 455.561 kB
|
|
129
136
|
|
|
130
137
|
Finish.
|
|
131
138
|
|
|
132
|
-
|
|
133
|
-
|
|
139
|
+
computing gzip size...
|
|
140
|
+
dist/index.html 455.56 kB │ gzip: 397.49 kB
|
|
141
|
+
|
|
142
|
+
✓ built in 416ms
|
|
134
143
|
```
|
|
135
144
|
|
|
136
145
|

|
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
|
-
|
|
3
|
-
|
|
4
|
-
|
|
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,245 +1,317 @@
|
|
|
1
1
|
import pc from "picocolors";
|
|
2
|
-
import { minify
|
|
3
|
-
import { JSDOM } from
|
|
4
|
-
import path from
|
|
5
|
-
import fs from
|
|
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
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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
|
+
}
|
|
38
176
|
}
|
|
39
177
|
async function generateBundle(bundle, config, options) {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
}
|
|
178
|
-
// generate html
|
|
179
|
-
htmlChunk.source = dom.serialize();
|
|
180
|
-
// minify html
|
|
181
|
-
if (options.htmlMinifierTerser)
|
|
182
|
-
htmlChunk.source = await htmlMinify(htmlChunk.source, options.htmlMinifierTerser);
|
|
183
|
-
// fill script
|
|
184
|
-
function inlineHtmlAssets() {
|
|
185
|
-
if (options.tryInlineHtmlAssets) {
|
|
186
|
-
// add script for load html assets
|
|
187
|
-
const assetsJSON = JSON.stringify(assetsDataURL);
|
|
188
|
-
if (assetsJSON !== '{}')
|
|
189
|
-
newJSCode.push(template.assets(assetsJSON));
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
if (scriptElement) {
|
|
193
|
-
thisDel.add(scriptName);
|
|
194
|
-
let { code } = bundle[scriptName];
|
|
195
|
-
oldSize += code.length;
|
|
196
|
-
code = code.replace(/;?\n?$/, '');
|
|
197
|
-
// do not delete not inlined asset
|
|
198
|
-
for (const name of bundleAssetsNames) {
|
|
199
|
-
const assetName = name.slice(assetsDir.length);
|
|
200
|
-
if (code.includes(assetName)) {
|
|
201
|
-
globalDoNotDelete.add(name);
|
|
202
|
-
delete assetsDataURL[assetName];
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
inlineHtmlAssets();
|
|
206
|
-
if (options.useImportMetaPolyfill)
|
|
207
|
-
newJSCode.push(template.importmeta(scriptName));
|
|
208
|
-
// 此 polyfill 仅在以下选项的值为 true 时需要。
|
|
209
|
-
// config.build.rollupOptions.output.inlineDynamicImports
|
|
210
|
-
if (code.includes("__VITE_PRELOAD__"))
|
|
211
|
-
newJSCode.push("var __VITE_PRELOAD__");
|
|
212
|
-
newJSCode.push(code);
|
|
213
|
-
}
|
|
214
|
-
else {
|
|
215
|
-
inlineHtmlAssets();
|
|
216
|
-
}
|
|
217
|
-
htmlChunk.source = htmlChunk.source.split(fakeScript, 2).join(template.base(newJSCode.join(';'), options.compressFormat, options.useBase128, options.compressor));
|
|
218
|
-
// log
|
|
219
|
-
console.log(" " + pc.gray(kB(oldSize) + " -> ") + pc.cyanBright(kB(htmlChunk.source.length)) + '\n');
|
|
220
|
-
// delete assets
|
|
221
|
-
for (const name of thisDel) {
|
|
222
|
-
globalDelete.add(name);
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
if (options.removeInlinedAssetFiles) {
|
|
226
|
-
// delete inlined assets
|
|
227
|
-
for (const name of globalDelete) {
|
|
228
|
-
// do not delete not inlined asset
|
|
229
|
-
if (!globalDoNotDelete.has(name))
|
|
230
|
-
delete bundle[name];
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
if (options.removeInlinedPublicIconFiles) {
|
|
234
|
-
// delete inlined public files
|
|
235
|
-
for (const name of globalRemoveDistFileNames) {
|
|
236
|
-
try {
|
|
237
|
-
fs.unlinkSync(path.join(config.build.outDir, name));
|
|
238
|
-
}
|
|
239
|
-
catch (e) {
|
|
240
|
-
console.error(e);
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
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"));
|
|
245
315
|
}
|
|
316
|
+
//#endregion
|
|
317
|
+
export { singleFileCompression as default, singleFileCompression, defaultHtmlMinifierTerserOptions };
|
package/package.json
CHANGED
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vite-plugin-singlefile-compression",
|
|
3
|
-
"version": "2.0
|
|
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.",
|
|
7
7
|
"main": "./dist/index.js",
|
|
8
8
|
"types": "./dist/index.d.ts",
|
|
9
|
-
"browser": "./browser.min.js",
|
|
10
9
|
"files": [
|
|
11
|
-
"dist"
|
|
12
|
-
"./browser.min.js"
|
|
10
|
+
"dist"
|
|
13
11
|
],
|
|
14
12
|
"type": "module",
|
|
15
13
|
"scripts": {
|
|
16
|
-
"build": "rimraf dist && tsc && node build.js &&
|
|
14
|
+
"build": "rimraf dist _dist && tsc && node build.js && cd test && node --run build",
|
|
17
15
|
"prepublishOnly": "node --run build"
|
|
18
16
|
},
|
|
19
17
|
"repository": {
|
|
@@ -40,25 +38,33 @@
|
|
|
40
38
|
"js",
|
|
41
39
|
"javascript",
|
|
42
40
|
"css",
|
|
43
|
-
"class"
|
|
41
|
+
"class",
|
|
42
|
+
"rolldown",
|
|
43
|
+
"rolldown-vite",
|
|
44
|
+
"rollup",
|
|
45
|
+
"vite-plugin-singlefile",
|
|
46
|
+
"vite-plugin-compression",
|
|
47
|
+
"vite-plugin-compression2"
|
|
44
48
|
],
|
|
45
49
|
"dependencies": {
|
|
46
50
|
"@types/html-minifier-terser": ">=7.0.2",
|
|
47
|
-
"base128-ascii": ">=2.1.
|
|
51
|
+
"base128-ascii": ">=2.1.11",
|
|
48
52
|
"html-minifier-terser": ">=7.2.0",
|
|
49
|
-
"jsdom": ">=
|
|
50
|
-
"mime": ">=4.0
|
|
53
|
+
"jsdom": ">=28.1.0",
|
|
54
|
+
"mime": ">=4.1.0",
|
|
51
55
|
"mini-svg-data-uri": ">=1.4.4",
|
|
52
56
|
"picocolors": ">=1.1.1"
|
|
53
57
|
},
|
|
54
58
|
"devDependencies": {
|
|
55
|
-
"@types/jsdom": ">=
|
|
56
|
-
"@types/node": "
|
|
57
|
-
"
|
|
58
|
-
"
|
|
59
|
-
"rimraf": ">=6.
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
"
|
|
59
|
+
"@types/jsdom": ">=28.0.0",
|
|
60
|
+
"@types/node": "^22.19.15",
|
|
61
|
+
"esbuild": "^0.27.4",
|
|
62
|
+
"marked": "^17.0.4",
|
|
63
|
+
"rimraf": ">=6.1.3",
|
|
64
|
+
"rolldown": ">=1.0.0-rc.9",
|
|
65
|
+
"rolldown-plugin-dts": "^0.22.5",
|
|
66
|
+
"rollup": ">=4.59.0",
|
|
67
|
+
"typescript": ">=5.9.3",
|
|
68
|
+
"vite": ">=8.0.0"
|
|
63
69
|
}
|
|
64
70
|
}
|
package/browser.min.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
throw Error("This npm package does not support running in the web browser.")
|
package/dist/compress.d.ts
DELETED
|
@@ -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
|
-
}
|
package/dist/cutPrefix.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function cutPrefix(str: string, prefix: string): string;
|
package/dist/cutPrefix.js
DELETED
package/dist/dataurl.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function bufferToDataURL(name: string, b: Buffer): string;
|
package/dist/dataurl.js
DELETED
package/dist/getTemplate.d.ts
DELETED
|
@@ -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
|
-
};
|
package/dist/getTemplate.js
DELETED
|
@@ -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
|
-
};
|
package/dist/getVersion.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const version: string;
|
package/dist/getVersion.js
DELETED
package/dist/kB.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function kB(size: number): string;
|
package/dist/kB.js
DELETED
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
|
-
}
|
package/dist/template/assets.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{let e={"":""};for(let o in e)for(let s of document.querySelectorAll(`[src="data:${o}"]`))s.src=e[o]}
|
package/dist/template/base128.js
DELETED
|
@@ -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)))
|
package/dist/template/base64.js
DELETED
|
@@ -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)))
|
package/dist/template/css.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
document.head.appendChild(document.createElement("style")).innerHTML="<style>"
|
package/dist/template/icon.js
DELETED
|
@@ -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)}}
|