Converted @rollup/html to a standalone package (out of the original monorepo) and made it ESM-native
This commit is contained in:
133
src/index.ts
Normal file
133
src/index.ts
Normal file
@@ -0,0 +1,133 @@
|
||||
import { extname } from "node:path";
|
||||
|
||||
import type { Plugin, NormalizedOutputOptions, OutputBundle, EmittedAsset } from 'rollup';
|
||||
|
||||
import type { RollupHtmlOptions, RollupHtmlTemplateOptions } from '../types/index.d.ts';
|
||||
|
||||
const getFiles = (bundle: OutputBundle): RollupHtmlTemplateOptions['files'] => {
|
||||
const result = {} as ReturnType<typeof getFiles>;
|
||||
for (const file of Object.values(bundle)) {
|
||||
const { fileName } = file;
|
||||
const extension = extname(fileName).substring(1);
|
||||
|
||||
result[extension] = (result[extension] || []).concat(file);
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
export const makeHtmlAttributes = (attributes: Record<string, any>): string => {
|
||||
if (!attributes) {
|
||||
return '';
|
||||
}
|
||||
|
||||
const keys = Object.keys(attributes);
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
return keys.reduce((result, key) => (result += ` ${key}="${attributes[key]}"`), '');
|
||||
};
|
||||
|
||||
const defaultTemplate = async ({
|
||||
attributes,
|
||||
files,
|
||||
meta,
|
||||
publicPath,
|
||||
title
|
||||
}: RollupHtmlTemplateOptions) => {
|
||||
const scripts = (files.js || [])
|
||||
.map(({ fileName }) => {
|
||||
const attrs = makeHtmlAttributes(attributes.script);
|
||||
return `<script src="${publicPath}${fileName}"${attrs}></script>`;
|
||||
})
|
||||
.join('\n');
|
||||
|
||||
const links = (files.css || [])
|
||||
.map(({ fileName }) => {
|
||||
const attrs = makeHtmlAttributes(attributes.link);
|
||||
return `<link href="${publicPath}${fileName}" rel="stylesheet"${attrs}>`;
|
||||
})
|
||||
.join('\n');
|
||||
|
||||
const metas = meta
|
||||
.map((input) => {
|
||||
const attrs = makeHtmlAttributes(input);
|
||||
return `<meta${attrs}>`;
|
||||
})
|
||||
.join('\n');
|
||||
|
||||
return `
|
||||
<!doctype html>
|
||||
<html${makeHtmlAttributes(attributes.html)}>
|
||||
<head>
|
||||
${metas}
|
||||
<title>${title}</title>
|
||||
${links}
|
||||
</head>
|
||||
<body>
|
||||
${scripts}
|
||||
</body>
|
||||
</html>`;
|
||||
};
|
||||
|
||||
const supportedFormats = ['es', 'esm', 'iife', 'umd'];
|
||||
|
||||
const defaults = {
|
||||
attributes: {
|
||||
link: null,
|
||||
html: { lang: 'en' },
|
||||
script: null
|
||||
},
|
||||
fileName: 'index.html',
|
||||
meta: [{ charset: 'utf-8' }],
|
||||
publicPath: '',
|
||||
template: defaultTemplate,
|
||||
title: 'Rollup Bundle'
|
||||
};
|
||||
|
||||
export default function html(opts: RollupHtmlOptions = {}): Plugin {
|
||||
const { attributes, fileName, meta, publicPath, template, title } = Object.assign(
|
||||
{},
|
||||
defaults,
|
||||
opts
|
||||
);
|
||||
|
||||
return {
|
||||
name: 'html',
|
||||
|
||||
async generateBundle(output: NormalizedOutputOptions, bundle: OutputBundle) {
|
||||
if (!supportedFormats.includes(output.format) && !opts.template) {
|
||||
this.warn(
|
||||
`plugin-html: The output format '${
|
||||
output.format
|
||||
}' is not directly supported. A custom \`template\` is probably required. Supported formats include: ${supportedFormats.join(
|
||||
', '
|
||||
)}`
|
||||
);
|
||||
}
|
||||
|
||||
if (output.format === 'es') {
|
||||
attributes.script = Object.assign({}, attributes.script, {
|
||||
type: 'module'
|
||||
});
|
||||
}
|
||||
|
||||
const files = getFiles(bundle);
|
||||
const source = await template({
|
||||
attributes,
|
||||
bundle,
|
||||
files,
|
||||
meta,
|
||||
publicPath,
|
||||
title
|
||||
});
|
||||
|
||||
const htmlFile: EmittedAsset = {
|
||||
type: 'asset',
|
||||
source,
|
||||
name: 'Rollup HTML Asset',
|
||||
fileName
|
||||
};
|
||||
|
||||
this.emitFile(htmlFile);
|
||||
}
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user