diff --git a/src/index.ts b/src/index.ts index 3a3ac8f..0147fbb 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,4 @@ -import path, { extname } from "node:path"; + import type { Plugin, @@ -19,17 +19,21 @@ import type { LoadReference, BodyReference, AttributeReference, LoadFunction } from '../types/index.d.ts'; +// createFilter function is a utility that constructs a filter function from include/exclude patterns. import {createFilter} from '@rollup/pluginutils'; +// parse5 package is used for parsing HTML. import {parse as parseHtml, serialize as serializeHtml, DefaultTreeAdapterMap} from "parse5"; -import {readFile} from "node:fs/promises" +// nodejs imports (io, path) +import path, { extname, dirname } from "node:path"; +import {readFile} from "node:fs/promises" +import posix from "node:path/posix"; +import crypto from "node:crypto"; + +// utilities import {makeLoader, makeInlineId} from "./loader.js"; import {HtmlImport, HtmlModule} from "./html-module.js"; -import {dirname} from "node:path"; -import posix from "node:path/posix"; - -import crypto from "node:crypto"; const defaults: RollupHtmlOptions = { transform: (source: string)=>source,// NO-OP @@ -44,6 +48,12 @@ const defaults: RollupHtmlOptions = { const modulePrefix = `// `; const moduleSuffix = `// `; +/** + * Creates a Rollup plugin that transforms HTML files. + * + * @param {RollupHtmlOptions} opts - The options for the plugin. + * @returns {Plugin} - The Rollup plugin. + */ export default function html(opts: RollupHtmlOptions = {}): Plugin { const { publicPath, @@ -70,14 +80,35 @@ export default function html(opts: RollupHtmlOptions = {}): Plugin { let entryNames = new Map(); const pluginName = 'html2'; + /** + * Short summary: + * Intercepts the loading of the html files and parses it with parse5. + * The parsed result is iterated to check for external references that need to be including in the rollup build (via for example @rollup/plugin-url). + * To satisfy rollup a JS version of the html file is returned, optionally including a few imports left for rollup to resolve + * When the result is generated the rollup result for the html file and any of its inlined assets are stripped from the output. + * and replaced with the html file. + * + * Caveats: + * - to get the resulting html content file we're parsing the evaluating the result JS module and take its default export + * [warn] other plugins such as CJS transformer and hot-reload can severely screw this up. + * - sourcemaps won't work yet (to add support we'd need to rewrite using magic-string?) + * - to fix the naming of resulting html files, and behave properly when files are entryPoints or not... we're fighting rollup alot + * + * + * Rework by testing a stripped down version with JS imports? + * - the logic in load should be moved to a transform, properly use rollups ability to specify the plugin should run 'pre' other hooks and see if that allows us to intercept before a commonjs or some other tool horribly transpiles our code + * - we might need to know which output is being used to properly extract the html back from the result? (in case of not being included in a JS file) + */ return { name: pluginName,// TODO: Need a better name, original plugin was just named `html` and might still make sense to use in conjunction with this one + // Track html entrypoints buildStart(options){ entryNames = new Map(Object.entries(typeof(options.input)==='object'?options.input:{[options.input]:[options.input]}) .map(([k,v])=>[v,k]) ); }, + resolveId: { async handler(specifier: string, importer: string | undefined, diff --git a/src/loader.ts b/src/loader.ts index 5075b61..f5a5ec6 100644 --- a/src/loader.ts +++ b/src/loader.ts @@ -46,6 +46,12 @@ export function makeInlineId(sourceId: string, node: DefaultTreeAdapterMap['chil return [sourceId, [makeHtmlPath(node), 'js'].join('.')].join('.'); } +/** + * Creates a loader function that maps node types and attributes to load operations. + * + * @param mappings - An array of NodeMapping objects specifying how to map and load different nodes. + * @returns A LoadNodeCallback function that can be used to load nodes based on the mappings. + */ export function makeLoader(mappings: NodeMapping[] = defaultMapping){ const fn : LoadNodeCallback = async function ({node, sourceId}, load){ for(const mapping of mappings){ diff --git a/test/multi-entry/snapshots/test.js.snap b/test/multi-entry/snapshots/test.js.snap index c12e1c9..234d8de 100644 Binary files a/test/multi-entry/snapshots/test.js.snap and b/test/multi-entry/snapshots/test.js.snap differ diff --git a/test/templating/snapshots/test.js.snap b/test/templating/snapshots/test.js.snap index 107f938..c58d00f 100644 Binary files a/test/templating/snapshots/test.js.snap and b/test/templating/snapshots/test.js.snap differ