@auioc/rollup-plugin-html 1.1.0 → 1.3.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 +58 -11
- package/dist/index.cjs +49 -9
- package/dist/index.d.ts +24 -9
- package/dist/index.mjs +49 -9
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -32,17 +32,18 @@ export default {
|
|
|
32
32
|
|
|
33
33
|
## Options
|
|
34
34
|
|
|
35
|
-
| Option | Type
|
|
36
|
-
| ---------------------- |
|
|
37
|
-
| `template` | `string`
|
|
38
|
-
| `output` | `string`
|
|
39
|
-
| `injectStyle` | `boolean`
|
|
40
|
-
| `injectScript` | `boolean` \| `'module'`
|
|
41
|
-
| `external` | `{ style?: Asset[]; script?: Asset[] }`
|
|
42
|
-
| `styleTagPlaceholder` | `string`
|
|
43
|
-
| `scriptTagPlaceholder` | `string`
|
|
44
|
-
| `stripTag` | `string`
|
|
45
|
-
| `minify` | `boolean` \| `MinifierOptions`
|
|
35
|
+
| Option | Type | Default | Description |
|
|
36
|
+
| ---------------------- | ------------------------------------------------------------------ | -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
37
|
+
| `template` | `string` | | **Required**. Path to the template `.html` file, resolved relative to `process.cwd()`. |
|
|
38
|
+
| `output` | `string` | `'index.html'` | Output file name of the emitted HTML file. |
|
|
39
|
+
| `injectStyle` | `boolean` \| `((id: string) => boolean)` | `true` | Whether to inject styles.<br/>Pass a function to decide per-asset whether to inject it. The function receives the asset URL (for external assets) or the bundled file name. |
|
|
40
|
+
| `injectScript` | `boolean` \| `'module'` \| `((id: string) => boolean \| 'module')` | `true` | Whether to inject scripts.<br/>Use `'module'` to add `type="module"`.<br/>Pass a function to decide per-asset whether (and how) to inject it. The function receives the asset URL (for external assets) or the bundled file name. |
|
|
41
|
+
| `external` | `{ style?: Asset[]; script?: Asset[] }` | `{ }` | External assets to inject. Their tags are placed before the bundled ones. See [External Assets](#external-assets). |
|
|
42
|
+
| `styleTagPlaceholder` | `string` | `'<!-- inject:style -->'` | Placeholder comment replaced by CSS tags. |
|
|
43
|
+
| `scriptTagPlaceholder` | `string` | `'<!-- inject:script -->'` | Placeholder comment replaced by script tags. |
|
|
44
|
+
| `stripTag` | `string` | `'strip'` | Tag name used for strip comment blocks. |
|
|
45
|
+
| `minify` | `boolean` \| `MinifierOptions` | `false` | Minify the output HTML with [html-minifier-terser](https://www.npmjs.com/package/html-minifier-terser). Pass an object to forward html-minifier-terser options. |
|
|
46
|
+
| `cacheBusting` | `CacheBusting` (`boolean` \| `string` \| `Function`) | `false` | Append a query string to bundled asset URLs. See [Cache busting](#4-cache-busting). |
|
|
46
47
|
|
|
47
48
|
- Asset
|
|
48
49
|
|
|
@@ -56,6 +57,18 @@ export default {
|
|
|
56
57
|
};
|
|
57
58
|
```
|
|
58
59
|
|
|
60
|
+
- CacheBusting
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
type CacheBusting =
|
|
64
|
+
| boolean
|
|
65
|
+
| string
|
|
66
|
+
| ((
|
|
67
|
+
fileName: string,
|
|
68
|
+
content: string | Uint8Array
|
|
69
|
+
) => string | undefined | false);
|
|
70
|
+
```
|
|
71
|
+
|
|
59
72
|
## How It Works
|
|
60
73
|
|
|
61
74
|
### 1. Injection
|
|
@@ -162,6 +175,40 @@ html({
|
|
|
162
175
|
|
|
163
176
|
See [`html-minifier-terser` options](https://github.com/terser/html-minifier-terser#options-quick-reference) for the full list.
|
|
164
177
|
|
|
178
|
+
### 4. Cache busting
|
|
179
|
+
|
|
180
|
+
>**NOTE:** External assets injected through the `external` option are not affected.
|
|
181
|
+
|
|
182
|
+
Enable cache busting to append a query string to the URLs of bundled assets. The content hash is generated automatically:
|
|
183
|
+
|
|
184
|
+
```js
|
|
185
|
+
html({
|
|
186
|
+
template: 'src/index.html',
|
|
187
|
+
cacheBusting: true,
|
|
188
|
+
});
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
This produces tags such as `<script src="bundle.js?v=1a2b3c4d"></script>`.
|
|
192
|
+
|
|
193
|
+
You can also provide the query string yourself. The value is appended without the leading `?`:
|
|
194
|
+
|
|
195
|
+
```js
|
|
196
|
+
html({
|
|
197
|
+
template: 'src/index.html',
|
|
198
|
+
cacheBusting: 'v=1.2.3',
|
|
199
|
+
});
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
For per-asset control, pass a function receiving the asset file name and its content. Return an empty string to skip that asset:
|
|
203
|
+
|
|
204
|
+
```js
|
|
205
|
+
html({
|
|
206
|
+
template: 'src/index.html',
|
|
207
|
+
cacheBusting: (fileName, content) =>
|
|
208
|
+
fileName.endsWith('.js') ? `v=${content.length}` : 'v=1.2.3',
|
|
209
|
+
});
|
|
210
|
+
```
|
|
211
|
+
|
|
165
212
|
## License
|
|
166
213
|
|
|
167
214
|
Package `@auioc/rollup-plugin-html` is licensed under the **MIT License**.
|
package/dist/index.cjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* Package bundle (CJS) of @auioc/rollup-plugin-html
|
|
3
3
|
* https://github.com/auioc/rollup-plugins/tree/main/packages/html
|
|
4
|
-
* Generated at 2026-
|
|
5
|
-
* Version: v1.
|
|
4
|
+
* Generated at 2026-11-09T16:23:53.666Z
|
|
5
|
+
* Version: v1.3.0 - tag:html@v1.3.0@9873e315
|
|
6
6
|
* Copyright (C) 2026 AUIOC.ORG
|
|
7
7
|
* Copyright (C) 2022-2026 PCC-Studio
|
|
8
8
|
* Licensed under MIT
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
13
13
|
|
|
14
14
|
var htmlMinifierTerser = require('html-minifier-terser');
|
|
15
|
+
var node_crypto = require('node:crypto');
|
|
15
16
|
var fs = require('node:fs');
|
|
16
17
|
var Path = require('node:path');
|
|
17
18
|
|
|
@@ -20,6 +21,29 @@ const DEFAULT_TERSER_OPTIONS = {
|
|
|
20
21
|
collapseWhitespace: true,
|
|
21
22
|
removeComments: true,
|
|
22
23
|
};
|
|
24
|
+
function appendQuery(url, query) {
|
|
25
|
+
const hashIndex = url.indexOf('#');
|
|
26
|
+
const hash = hashIndex === -1 ? '' : url.slice(hashIndex);
|
|
27
|
+
const base = hashIndex === -1 ? url : url.slice(0, hashIndex);
|
|
28
|
+
const separator = base.includes('?') ? '&' : '?';
|
|
29
|
+
return `${base}${separator}${query}${hash}`;
|
|
30
|
+
}
|
|
31
|
+
function cacheBustingQuery(cacheBusting, fileName, content) {
|
|
32
|
+
if (typeof cacheBusting === 'string') {
|
|
33
|
+
return cacheBusting;
|
|
34
|
+
}
|
|
35
|
+
if (typeof cacheBusting === 'function') {
|
|
36
|
+
return cacheBusting(fileName, content) || '';
|
|
37
|
+
}
|
|
38
|
+
return `v=${node_crypto.createHash('sha256').update(content).digest('hex').slice(0, 8)}`;
|
|
39
|
+
}
|
|
40
|
+
function assetURL(fileName, content, cacheBusting) {
|
|
41
|
+
if (!cacheBusting) {
|
|
42
|
+
return fileName;
|
|
43
|
+
}
|
|
44
|
+
const query = cacheBustingQuery(cacheBusting, fileName, content);
|
|
45
|
+
return query ? appendQuery(fileName, query) : fileName;
|
|
46
|
+
}
|
|
23
47
|
function styleTag(asset) {
|
|
24
48
|
if (typeof asset === 'string') {
|
|
25
49
|
return `<link rel="stylesheet" href="${asset}">`;
|
|
@@ -41,7 +65,7 @@ function scriptTag(asset, module) {
|
|
|
41
65
|
return `<script ${module ? 'type="module" ' : ''}src="${asset.url}"${integrity}${crossorigin}></script>`;
|
|
42
66
|
}
|
|
43
67
|
function createHTML(options) {
|
|
44
|
-
const { template: templateFile, output = 'index.html', injectStyle = true, injectScript = true, styleTagPlaceholder = '<!-- inject:style -->', scriptTagPlaceholder = '<!-- inject:script -->', stripTag = 'strip', minify = false, } = options;
|
|
68
|
+
const { template: templateFile, output = 'index.html', injectStyle = true, injectScript = true, styleTagPlaceholder = '<!-- inject:style -->', scriptTagPlaceholder = '<!-- inject:script -->', stripTag = 'strip', minify = false, cacheBusting = false, } = options;
|
|
45
69
|
let template = '';
|
|
46
70
|
return {
|
|
47
71
|
name: NAME,
|
|
@@ -67,19 +91,24 @@ function createHTML(options) {
|
|
|
67
91
|
for (const [fileName, chunk] of Object.entries(bundle)) {
|
|
68
92
|
if (chunk.type === 'chunk' && fileName.endsWith('.js')) {
|
|
69
93
|
if (chunk.isEntry) {
|
|
70
|
-
jsFiles.push(fileName);
|
|
94
|
+
jsFiles.push(assetURL(fileName, chunk.code, cacheBusting));
|
|
71
95
|
}
|
|
72
96
|
}
|
|
73
97
|
else if (chunk.type === 'asset') {
|
|
74
98
|
if (fileName.endsWith('.css')) {
|
|
75
|
-
cssFiles.push(fileName);
|
|
99
|
+
cssFiles.push(assetURL(fileName, chunk.source, cacheBusting));
|
|
76
100
|
}
|
|
77
101
|
}
|
|
78
102
|
}
|
|
79
103
|
const external = options.external ?? { style: [], script: [] };
|
|
80
104
|
if (injectStyle) {
|
|
81
|
-
const
|
|
82
|
-
|
|
105
|
+
const predicate = typeof injectStyle === 'function'
|
|
106
|
+
? injectStyle
|
|
107
|
+
: () => true;
|
|
108
|
+
const externalTags = (external.style ?? [])
|
|
109
|
+
.filter((x) => predicate(typeof x === 'string' ? x : x.url))
|
|
110
|
+
.map(styleTag);
|
|
111
|
+
const bundledTags = cssFiles.filter(predicate).map(styleTag);
|
|
83
112
|
const tags = [...externalTags, ...bundledTags].join('\n');
|
|
84
113
|
if (tags) {
|
|
85
114
|
if (html.includes(styleTagPlaceholder)) {
|
|
@@ -94,10 +123,21 @@ function createHTML(options) {
|
|
|
94
123
|
}
|
|
95
124
|
}
|
|
96
125
|
if (injectScript) {
|
|
97
|
-
const
|
|
126
|
+
const predicate = typeof injectScript === 'function'
|
|
127
|
+
? injectScript
|
|
128
|
+
: () => injectScript;
|
|
129
|
+
const _toScriptTag = (asset) => {
|
|
130
|
+
const type = predicate(typeof asset === 'string' ? asset : asset.url);
|
|
131
|
+
if (type) {
|
|
132
|
+
return scriptTag(asset, type === 'module');
|
|
133
|
+
}
|
|
134
|
+
return undefined;
|
|
135
|
+
};
|
|
98
136
|
const externalTags = (external.script ?? []).map(_toScriptTag);
|
|
99
137
|
const bundledScriptTags = jsFiles.map(_toScriptTag);
|
|
100
|
-
const tags = [...externalTags, ...bundledScriptTags]
|
|
138
|
+
const tags = [...externalTags, ...bundledScriptTags]
|
|
139
|
+
.filter((x) => !!x)
|
|
140
|
+
.join('\n');
|
|
101
141
|
if (tags) {
|
|
102
142
|
if (html.includes(scriptTagPlaceholder)) {
|
|
103
143
|
html = html.replace(scriptTagPlaceholder, tags);
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* Type definitions of @auioc/rollup-plugin-html
|
|
3
3
|
* https://github.com/auioc/rollup-plugins/tree/main/packages/html
|
|
4
|
-
* Generated at 2026-
|
|
5
|
-
* Version: v1.
|
|
4
|
+
* Generated at 2026-11-09T16:23:53.666Z
|
|
5
|
+
* Version: v1.3.0 - tag:html@v1.3.0@9873e315
|
|
6
6
|
* Copyright (C) 2026 AUIOC.ORG
|
|
7
7
|
* Copyright (C) 2022-2026 PCC-Studio
|
|
8
8
|
* Licensed under MIT
|
|
@@ -15,6 +15,7 @@ type Asset = string | {
|
|
|
15
15
|
integrity?: string;
|
|
16
16
|
crossorigin?: 'anonymous' | 'use-credentials';
|
|
17
17
|
};
|
|
18
|
+
type CacheBusting = boolean | string | ((fileName: string, content: string | Uint8Array) => string | undefined | false);
|
|
18
19
|
interface Options {
|
|
19
20
|
/**
|
|
20
21
|
* Path of template `.html` file
|
|
@@ -27,19 +28,26 @@ interface Options {
|
|
|
27
28
|
output?: string;
|
|
28
29
|
/**
|
|
29
30
|
* Whether to inject bundled CSS files.
|
|
31
|
+
*
|
|
32
|
+
* Pass a function to decide per-asset whether to inject it.
|
|
33
|
+
* The function receives the asset URL (for external assets) or the
|
|
34
|
+
* bundled file name.
|
|
30
35
|
* @default true
|
|
31
36
|
*/
|
|
32
|
-
injectStyle?: boolean;
|
|
37
|
+
injectStyle?: boolean | ((id: string) => boolean);
|
|
33
38
|
/**
|
|
34
39
|
* Whether to inject bundled JS files.
|
|
40
|
+
*
|
|
35
41
|
* Use `'module'` to add `type="module"`.
|
|
42
|
+
*
|
|
43
|
+
* Pass a function to decide per-asset whether (and how) to inject it.
|
|
44
|
+
* The function receives the asset URL (for external assets) or the
|
|
45
|
+
* bundled file name, return `false` to skip injection,
|
|
46
|
+
* `'module'` to inject with `type="module"`, or `true` to inject a
|
|
47
|
+
* normal script tag.
|
|
36
48
|
* @default true
|
|
37
49
|
*/
|
|
38
|
-
injectScript?: boolean | 'module';
|
|
39
|
-
/**
|
|
40
|
-
* External assets to inject.
|
|
41
|
-
* @default {}
|
|
42
|
-
*/
|
|
50
|
+
injectScript?: boolean | 'module' | ((id: string) => boolean | 'module');
|
|
43
51
|
external?: {
|
|
44
52
|
style?: Asset[];
|
|
45
53
|
script?: Asset[];
|
|
@@ -67,8 +75,15 @@ interface Options {
|
|
|
67
75
|
* @default false
|
|
68
76
|
*/
|
|
69
77
|
minify?: boolean | Options$1;
|
|
78
|
+
/**
|
|
79
|
+
* Append a query string to bundled asset URLs to bust caches.
|
|
80
|
+
*
|
|
81
|
+
* External assets are not affected.
|
|
82
|
+
* @default false
|
|
83
|
+
*/
|
|
84
|
+
cacheBusting?: CacheBusting;
|
|
70
85
|
}
|
|
71
86
|
declare function createHTML(options: Options): Plugin;
|
|
72
87
|
|
|
73
88
|
export { createHTML as default };
|
|
74
|
-
export type { Asset, Options };
|
|
89
|
+
export type { Asset, CacheBusting, Options };
|
package/dist/index.mjs
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* Package bundle (ESM) of @auioc/rollup-plugin-html
|
|
3
3
|
* https://github.com/auioc/rollup-plugins/tree/main/packages/html
|
|
4
|
-
* Generated at 2026-
|
|
5
|
-
* Version: v1.
|
|
4
|
+
* Generated at 2026-11-09T16:23:53.666Z
|
|
5
|
+
* Version: v1.3.0 - tag:html@v1.3.0@9873e315
|
|
6
6
|
* Copyright (C) 2026 AUIOC.ORG
|
|
7
7
|
* Copyright (C) 2022-2026 PCC-Studio
|
|
8
8
|
* Licensed under MIT
|
|
9
9
|
*/
|
|
10
10
|
import { minify } from 'html-minifier-terser';
|
|
11
|
+
import { createHash } from 'node:crypto';
|
|
11
12
|
import fs from 'node:fs';
|
|
12
13
|
import Path from 'node:path';
|
|
13
14
|
|
|
@@ -16,6 +17,29 @@ const DEFAULT_TERSER_OPTIONS = {
|
|
|
16
17
|
collapseWhitespace: true,
|
|
17
18
|
removeComments: true,
|
|
18
19
|
};
|
|
20
|
+
function appendQuery(url, query) {
|
|
21
|
+
const hashIndex = url.indexOf('#');
|
|
22
|
+
const hash = hashIndex === -1 ? '' : url.slice(hashIndex);
|
|
23
|
+
const base = hashIndex === -1 ? url : url.slice(0, hashIndex);
|
|
24
|
+
const separator = base.includes('?') ? '&' : '?';
|
|
25
|
+
return `${base}${separator}${query}${hash}`;
|
|
26
|
+
}
|
|
27
|
+
function cacheBustingQuery(cacheBusting, fileName, content) {
|
|
28
|
+
if (typeof cacheBusting === 'string') {
|
|
29
|
+
return cacheBusting;
|
|
30
|
+
}
|
|
31
|
+
if (typeof cacheBusting === 'function') {
|
|
32
|
+
return cacheBusting(fileName, content) || '';
|
|
33
|
+
}
|
|
34
|
+
return `v=${createHash('sha256').update(content).digest('hex').slice(0, 8)}`;
|
|
35
|
+
}
|
|
36
|
+
function assetURL(fileName, content, cacheBusting) {
|
|
37
|
+
if (!cacheBusting) {
|
|
38
|
+
return fileName;
|
|
39
|
+
}
|
|
40
|
+
const query = cacheBustingQuery(cacheBusting, fileName, content);
|
|
41
|
+
return query ? appendQuery(fileName, query) : fileName;
|
|
42
|
+
}
|
|
19
43
|
function styleTag(asset) {
|
|
20
44
|
if (typeof asset === 'string') {
|
|
21
45
|
return `<link rel="stylesheet" href="${asset}">`;
|
|
@@ -37,7 +61,7 @@ function scriptTag(asset, module) {
|
|
|
37
61
|
return `<script ${module ? 'type="module" ' : ''}src="${asset.url}"${integrity}${crossorigin}></script>`;
|
|
38
62
|
}
|
|
39
63
|
function createHTML(options) {
|
|
40
|
-
const { template: templateFile, output = 'index.html', injectStyle = true, injectScript = true, styleTagPlaceholder = '<!-- inject:style -->', scriptTagPlaceholder = '<!-- inject:script -->', stripTag = 'strip', minify: minify$1 = false, } = options;
|
|
64
|
+
const { template: templateFile, output = 'index.html', injectStyle = true, injectScript = true, styleTagPlaceholder = '<!-- inject:style -->', scriptTagPlaceholder = '<!-- inject:script -->', stripTag = 'strip', minify: minify$1 = false, cacheBusting = false, } = options;
|
|
41
65
|
let template = '';
|
|
42
66
|
return {
|
|
43
67
|
name: NAME,
|
|
@@ -63,19 +87,24 @@ function createHTML(options) {
|
|
|
63
87
|
for (const [fileName, chunk] of Object.entries(bundle)) {
|
|
64
88
|
if (chunk.type === 'chunk' && fileName.endsWith('.js')) {
|
|
65
89
|
if (chunk.isEntry) {
|
|
66
|
-
jsFiles.push(fileName);
|
|
90
|
+
jsFiles.push(assetURL(fileName, chunk.code, cacheBusting));
|
|
67
91
|
}
|
|
68
92
|
}
|
|
69
93
|
else if (chunk.type === 'asset') {
|
|
70
94
|
if (fileName.endsWith('.css')) {
|
|
71
|
-
cssFiles.push(fileName);
|
|
95
|
+
cssFiles.push(assetURL(fileName, chunk.source, cacheBusting));
|
|
72
96
|
}
|
|
73
97
|
}
|
|
74
98
|
}
|
|
75
99
|
const external = options.external ?? { style: [], script: [] };
|
|
76
100
|
if (injectStyle) {
|
|
77
|
-
const
|
|
78
|
-
|
|
101
|
+
const predicate = typeof injectStyle === 'function'
|
|
102
|
+
? injectStyle
|
|
103
|
+
: () => true;
|
|
104
|
+
const externalTags = (external.style ?? [])
|
|
105
|
+
.filter((x) => predicate(typeof x === 'string' ? x : x.url))
|
|
106
|
+
.map(styleTag);
|
|
107
|
+
const bundledTags = cssFiles.filter(predicate).map(styleTag);
|
|
79
108
|
const tags = [...externalTags, ...bundledTags].join('\n');
|
|
80
109
|
if (tags) {
|
|
81
110
|
if (html.includes(styleTagPlaceholder)) {
|
|
@@ -90,10 +119,21 @@ function createHTML(options) {
|
|
|
90
119
|
}
|
|
91
120
|
}
|
|
92
121
|
if (injectScript) {
|
|
93
|
-
const
|
|
122
|
+
const predicate = typeof injectScript === 'function'
|
|
123
|
+
? injectScript
|
|
124
|
+
: () => injectScript;
|
|
125
|
+
const _toScriptTag = (asset) => {
|
|
126
|
+
const type = predicate(typeof asset === 'string' ? asset : asset.url);
|
|
127
|
+
if (type) {
|
|
128
|
+
return scriptTag(asset, type === 'module');
|
|
129
|
+
}
|
|
130
|
+
return undefined;
|
|
131
|
+
};
|
|
94
132
|
const externalTags = (external.script ?? []).map(_toScriptTag);
|
|
95
133
|
const bundledScriptTags = jsFiles.map(_toScriptTag);
|
|
96
|
-
const tags = [...externalTags, ...bundledScriptTags]
|
|
134
|
+
const tags = [...externalTags, ...bundledScriptTags]
|
|
135
|
+
.filter((x) => !!x)
|
|
136
|
+
.join('\n');
|
|
97
137
|
if (tags) {
|
|
98
138
|
if (html.includes(scriptTagPlaceholder)) {
|
|
99
139
|
html = html.replace(scriptTagPlaceholder, tags);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@auioc/rollup-plugin-html",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
},
|
|
22
22
|
"author": {
|
|
23
23
|
"name": "AUIOC",
|
|
24
|
-
"url": "https://
|
|
24
|
+
"url": "https://auioc.org"
|
|
25
25
|
},
|
|
26
26
|
"type": "module",
|
|
27
27
|
"main": "./dist/index.cjs",
|