UNPKG

@roots/entrypoints-webpack-plugin

Version:

Manifest with assets grouped by entrypoint

111 lines (110 loc) 3.42 kB
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);