From 44fff3490c1c1a13ae4ffe7ff42f54fcaa4d031c Mon Sep 17 00:00:00 2001
From: Mikhail Bashkirov
Date: Wed, 26 Nov 2025 13:09:11 +0100
Subject: [PATCH] feat(rollup-plugin-html): suport transform on input html
---
.changeset/light-comics-provide.md | 5 ++++
.../src/output/createHTMLOutput.ts | 12 +++++---
.../src/output/getOutputHTML.ts | 28 ++++++++++++++-----
.../src/rollupPluginHTML.ts | 28 ++++++++++++++-----
.../test/rollup-plugin-html.test.ts | 14 ++++++++--
.../test/src/output/getOutputHTML.test.ts | 4 +--
6 files changed, 69 insertions(+), 22 deletions(-)
create mode 100644 .changeset/light-comics-provide.md
diff --git a/.changeset/light-comics-provide.md b/.changeset/light-comics-provide.md
new file mode 100644
index 000000000..79f6bd1f7
--- /dev/null
+++ b/.changeset/light-comics-provide.md
@@ -0,0 +1,5 @@
+---
+'@web/rollup-plugin-html': minor
+---
+
+support transform on input html
diff --git a/packages/rollup-plugin-html/src/output/createHTMLOutput.ts b/packages/rollup-plugin-html/src/output/createHTMLOutput.ts
index cb2224267..4f3c1f646 100644
--- a/packages/rollup-plugin-html/src/output/createHTMLOutput.ts
+++ b/packages/rollup-plugin-html/src/output/createHTMLOutput.ts
@@ -15,7 +15,8 @@ export interface CreateHTMLAssetParams {
input: InputData;
emittedAssets: EmittedAssets;
generatedBundles: GeneratedBundle[];
- externalTransformHtmlFns: TransformHtmlFunction[];
+ inputExternalTransformHtmlFns: TransformHtmlFunction[];
+ outputExternalTransformHtmlFns: TransformHtmlFunction[];
pluginOptions: RollupPluginHTMLOptions;
defaultInjectDisabled: boolean;
serviceWorkerPath: string;
@@ -30,7 +31,8 @@ export async function createHTMLAsset(params: CreateHTMLAssetParams): Promise;
- externalTransformHtmlFns?: TransformHtmlFunction[];
+ inputExternalTransformHtmlFns?: TransformHtmlFunction[];
+ outputExternalTransformHtmlFns?: TransformHtmlFunction[];
defaultInjectDisabled: boolean;
serviceWorkerPath: string;
injectServiceWorker: boolean;
@@ -31,7 +32,8 @@ export async function getOutputHTML(params: GetOutputHTMLParams) {
const {
pluginOptions,
entrypointBundles,
- externalTransformHtmlFns,
+ inputExternalTransformHtmlFns,
+ outputExternalTransformHtmlFns,
input,
outputDir,
emittedAssets,
@@ -44,8 +46,20 @@ export async function getOutputHTML(params: GetOutputHTMLParams) {
const { default: defaultBundle, ...multiBundles } = entrypointBundles;
const { absoluteSocialMediaUrls = true, rootDir = process.cwd() } = pluginOptions;
+ let inputHtml = input.html;
+
+ // run transform functions on input HTML
+ const inputTransforms = [...(inputExternalTransformHtmlFns ?? [])];
+ for (const transform of inputTransforms) {
+ inputHtml = await transform(inputHtml, {
+ bundle: defaultBundle,
+ bundles: multiBundles,
+ htmlFileName: input.name,
+ });
+ }
+
// inject rollup output into HTML
- let document = parse(input.html);
+ let document = parse(inputHtml);
if (pluginOptions.extractAssets !== false) {
injectedUpdatedAssetPaths({
document,
@@ -75,17 +89,17 @@ export async function getOutputHTML(params: GetOutputHTMLParams) {
let outputHtml = serialize(document);
- const transforms = [...(externalTransformHtmlFns ?? [])];
+ const outputTransforms = [...(outputExternalTransformHtmlFns ?? [])];
if (pluginOptions.transformHtml) {
if (Array.isArray(pluginOptions.transformHtml)) {
- transforms.push(...pluginOptions.transformHtml);
+ outputTransforms.push(...pluginOptions.transformHtml);
} else {
- transforms.push(pluginOptions.transformHtml);
+ outputTransforms.push(pluginOptions.transformHtml);
}
}
// run transform functions on output HTML
- for (const transform of transforms) {
+ for (const transform of outputTransforms) {
outputHtml = await transform(outputHtml, {
bundle: defaultBundle,
bundles: multiBundles,
diff --git a/packages/rollup-plugin-html/src/rollupPluginHTML.ts b/packages/rollup-plugin-html/src/rollupPluginHTML.ts
index ffe1a0880..7b2806ec1 100644
--- a/packages/rollup-plugin-html/src/rollupPluginHTML.ts
+++ b/packages/rollup-plugin-html/src/rollupPluginHTML.ts
@@ -18,7 +18,10 @@ import { emitAssets } from './output/emitAssets.js';
export interface RollupPluginHtml extends Plugin {
api: {
getInputs(): InputData[];
- addHtmlTransformer(transformHtmlFunction: TransformHtmlFunction): void;
+ addHtmlTransformer(
+ transformHtmlFunction: TransformHtmlFunction,
+ transformStage?: 'input' | 'output',
+ ): void;
disableDefaultInject(): void;
addOutput(name: string): Plugin;
};
@@ -28,7 +31,8 @@ export function rollupPluginHTML(pluginOptions: RollupPluginHTMLOptions = {}): R
const multiOutputNames: string[] = [];
let inputs: InputData[] = [];
let generatedBundles: GeneratedBundle[] = [];
- let externalTransformHtmlFns: TransformHtmlFunction[] = [];
+ let inputExternalTransformHtmlFns: TransformHtmlFunction[] = [];
+ let outputExternalTransformHtmlFns: TransformHtmlFunction[] = [];
let defaultInjectDisabled = false;
let serviceWorkerPath = '';
let injectServiceWorker = false;
@@ -38,7 +42,8 @@ export function rollupPluginHTML(pluginOptions: RollupPluginHTMLOptions = {}): R
function reset() {
inputs = [];
generatedBundles = [];
- externalTransformHtmlFns = [];
+ inputExternalTransformHtmlFns = [];
+ outputExternalTransformHtmlFns = [];
}
return {
@@ -146,7 +151,8 @@ export function rollupPluginHTML(pluginOptions: RollupPluginHTMLOptions = {}): R
inputs,
emittedAssets,
generatedBundles,
- externalTransformHtmlFns,
+ inputExternalTransformHtmlFns,
+ outputExternalTransformHtmlFns,
pluginOptions,
defaultInjectDisabled,
serviceWorkerPath,
@@ -165,8 +171,15 @@ export function rollupPluginHTML(pluginOptions: RollupPluginHTMLOptions = {}): R
return inputs;
},
- addHtmlTransformer(transformHtmlFunction: TransformHtmlFunction) {
- externalTransformHtmlFns.push(transformHtmlFunction);
+ addHtmlTransformer(
+ transformHtmlFunction: TransformHtmlFunction,
+ transformStage: 'input' | 'output' = 'output',
+ ) {
+ if (transformStage === 'input') {
+ inputExternalTransformHtmlFns.push(transformHtmlFunction);
+ } else {
+ outputExternalTransformHtmlFns.push(transformHtmlFunction);
+ }
},
disableDefaultInject() {
@@ -205,7 +218,8 @@ export function rollupPluginHTML(pluginOptions: RollupPluginHTMLOptions = {}): R
inputs,
emittedAssets,
generatedBundles,
- externalTransformHtmlFns,
+ inputExternalTransformHtmlFns,
+ outputExternalTransformHtmlFns,
pluginOptions,
defaultInjectDisabled,
serviceWorkerPath,
diff --git a/packages/rollup-plugin-html/test/rollup-plugin-html.test.ts b/packages/rollup-plugin-html/test/rollup-plugin-html.test.ts
index 7ccd949b0..dfb0c2784 100644
--- a/packages/rollup-plugin-html/test/rollup-plugin-html.test.ts
+++ b/packages/rollup-plugin-html/test/rollup-plugin-html.test.ts
@@ -626,7 +626,16 @@ describe('rollup-plugin-html', () => {
return false;
});
plugin!.api.addHtmlTransformer((html: string) =>
- html.replace('
hello world
' +
+ '' +
'' +
'' +
- '', ''),
+ html.replace('', ''),
+ );
+ plugin!.api.addHtmlTransformer(
+ (html: string) =>
+ html.replace('', ''),
+ 'output',
+ );
+ plugin!.api.addHtmlTransformer(
+ (html: string) => html.replace('', ''),
+ 'input',
);
},
} as Plugin,
@@ -641,9 +650,10 @@ describe('rollup-plugin-html', () => {
expect(entryB).to.include("console.log('entrypoint-b.js');");
expect(stripNewlines(getAsset(output, 'index.html').source)).to.equal(
'