@roots/entrypoints-webpack-plugin
Version:
Manifest with assets grouped by entrypoint
111 lines (110 loc) • 3.42 kB
JavaScript
import { __decorate } from "tslib";
import { Buffer } from 'node:buffer';
import { bind } from 'helpful-decorators';
import Webpack from 'webpack';
/**
* Emits inline html for each entrypoint
*/
export class HtmlEmitter {
compilation;
assets;
entrypoints;
publicPath;
/**
* Class constructor
*
* @param compilation - webpack compilation
* @param assets - webpack compilation assets
* @param entrypoints - {@link Entrypoints}
* @param publicPath - asset publicPath
*/
constructor(compilation, assets, entrypoints, publicPath) {
this.compilation = compilation;
this.assets = assets;
this.entrypoints = entrypoints;
this.publicPath = publicPath;
}
/**
* Reduce entrypoint entrypoints to markup
*
* @returns void
* @decorator bind - {@link bind}
*/
emit() {
;
[...this.entrypoints.entries()].map(([name, entrypoint]) => {
this.compilation.emitAsset(`${name}.html`, new Webpack.sources.RawSource([...entrypoint.entries()].reduce((html, [extension, files]) => {
if ([`js`, `mjs`].includes(extension))
return [...files].reduce(this.scriptReducer, html);
if (extension === `css`)
return [...files].reduce(this.styleReducer, html);
return html;
}, ``)));
});
}
/**
* Get compiled asset file contents
*
* @param ident - asset module name
* @returns - asset file contents
*/
getCompiledAsset(ident) {
const raw = this.assets[ident.replace(this.publicPath, ``)]?.source();
return raw instanceof Buffer ? raw.toString() : raw;
}
/**
* Reduce a js filename to markup
*/
makeScript(attributeRecords, inner = ``) {
inner = inner ? `\n\t${inner}\n` : ``;
const attributes = attributeRecords
? Object.entries(attributeRecords)
.filter(([_, v]) => v !== undefined)
.map(([k, v]) => {
// html5 specification allows for omitting value for boolean attributes
if (v === true)
return k;
return `${k}=${v}`;
})
.filter(Boolean)
.join(` `)
: ``;
return `<script ${attributes}>${inner}</script>`;
}
/**
* Reduce a script from entry item to markup
*/
scriptReducer(acc, src) {
const attributes = {
async: true,
defer: true,
src: !src.includes(`runtime`) ? src : undefined,
type: src.endsWith(`.mjs`) ? `module` : undefined,
};
return [
acc,
this.makeScript(attributes, src.includes(`runtime`) ? this.getCompiledAsset(src) : undefined),
].join(`\n`);
}
/**
* Reduce a stylesheet from entry item to markup
*/
styleReducer(acc, href) {
return [acc, `<link rel=stylesheet href=${href} />`].join(`\n`);
}
}
__decorate([
bind
], HtmlEmitter.prototype, "emit", null);
__decorate([
bind
], HtmlEmitter.prototype, "getCompiledAsset", null);
__decorate([
bind
], HtmlEmitter.prototype, "makeScript", null);
__decorate([
bind
], HtmlEmitter.prototype, "scriptReducer", null);
__decorate([
bind
], HtmlEmitter.prototype, "styleReducer", null);