feat: added initial sourcemapping attempt and use transform hook to parse and transform instead of load

This commit is contained in:
Miel Truyen 2023-11-25 22:44:31 +01:00
parent 980d33c48e
commit afd4a3c9ae
2 changed files with 39 additions and 16 deletions

View File

@ -11,9 +11,12 @@
# rollup-plugin-html-entry2
| :warning: WARNING |
|:-------------------------------------------------------------------|
|:----------------------------------------------------------------------------------------------------------------------|
| **Experimental-stage** plugin. Expect bugs and missing features... |
| :warning: WARNING |
| :------------------------------------------------------------------- |
| **Renaming** Name might change in the future. Consider rollup-plugin-html-bundler |
| (because we're basically transforming rollup into a tool for bundling html, might not even contain any JS in the end) |
A(nother) rollup plugin that tries to teach Rollup to start from an HTML entry, and the use of (multiple) HTML files in general.
The goal is to include assets referenced by the HTML file into the build-process as to copy/inline where appropriate and

View File

@ -23,6 +23,9 @@ import type {
import {createFilter} from '@rollup/pluginutils';
// parse5 package is used for parsing HTML.
import {parse as parseHtml, serialize as serializeHtml, DefaultTreeAdapterMap} from "parse5";
// magic-string to transform code and keeping a sourcemap aligned
import MagicString from "magic-string";
// nodejs imports (io, path)
import path, { extname, dirname } from "node:path";
@ -147,13 +150,19 @@ export default function html(opts: RollupHtmlOptions = {}): Plugin {
}
}
},
load: { // TODO, not in the mood to fix this. Load-result is getting cached and that gives us issues. Seperate load/transform behavior and adapt to use magic string for transformations?
load: {
// Something to figure out: its counter intuitive that rollup expects the load-callback to already return JS. It implies we already do transformations and can't really use rollup to further transform any of it. (i.e handlebars > intermediate-html > html would not be possible?)
async handler(id: string) {
if(virtualSources.has(id)) return virtualSources.get(id);
if(!filter(id)) return;
if (virtualSources.has(id)) return virtualSources.get(id);
if (!filter(id)) return;
}
},
transform: {
async handler(...args){
const [code, id] = args;
if (!filter(id)) return;
// Load
// parse
const htmlModule = htmlModules.get(id);
if(htmlModule) {
const contents = await readFile(id, {encoding: "utf-8"});
@ -162,7 +171,7 @@ export default function html(opts: RollupHtmlOptions = {}): Plugin {
id,
}) : contents;
// Parse document and store it (TODO: check for watch mode, we should check if it needs reparsing or not)
// Parse document and store it
const document = htmlModule.document = parseHtml(htmlSrc);
// Figure out which references to load from this HTML by iterating all nodes (looking for src or href attributes)
@ -244,13 +253,14 @@ export default function html(opts: RollupHtmlOptions = {}): Plugin {
} while (nodeQueue.length > 0);
}
let html = serializeHtml(htmlModule.document).replaceAll(/`/g,'\\\`').replaceAll(/\$\{/g,'\\${');
let htmlJS = new MagicString(serializeHtml(htmlModule.document));// TODO this is still a leak of AST, we're taking parse5 edited result and then transforming sourcemaps, this will only work when no edits were made
htmlJS.replaceAll(/`/g,'\\\`').replaceAll(/\$\{/g,'\\${');
const moduleImports = [];
for(const htmlImport of htmlImports){
if(htmlImport.type === 'default') {
const assetId: string = `asset${moduleImports.length}`;
moduleImports.push(`import ${assetId} from "${htmlImport.id}";`);// TODO: This is just the easy & safe solution. Would prefer to have recognizable names, and reeuse when something is the exact same resource..
html = html.replace(htmlImport.placeholder, `\${${assetId}}`);// TODO: Should we be worried about windows absolute URLs here?
htmlJS = htmlJS.replace(htmlImport.placeholder, `\${${assetId}}`);// TODO: Should we be worried about windows absolute URLs here?
// }else if(htmlImport.type === 'entryChunk' && htmlImport.referenceId){
// html = html.replace(htmlImport.placeholder, `\${import.meta.ROLLUP_FILE_URL_${htmlImport.referenceId}\}`);
}else{
@ -260,14 +270,24 @@ export default function html(opts: RollupHtmlOptions = {}): Plugin {
}
// TODO when importing html from .js this will not do. (
const htmlJSModule = [
htmlJS.prepend([
...moduleImports,
``,
`export const html = \`${html}\`;`,
`export const html = \``
].join('\n')).append([
`\`;`,
`export default html;`,
].join('\n');
].join('\n'));
const map = htmlJS.generateMap({
source: id,
file: `${id}.map`,
includeContent: true,
hires: 'boundary'
});
return {
code: htmlJSModule,
code: htmlJS.toString(),
map: map.toString(),
};
}
}