diff --git a/CHANGELOG.md b/CHANGELOG.md index b837f03..4bf7a80 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ # Remove me: TODO: This started as a fork of, but is now something different entirely. Changelog is no longer relevant (neither is the [README.md](README.md)) +rollup-plugin-css was used in the initial tests, but it hasnt been update in **7** years. Remove this # @rollup/plugin-html ChangeLog diff --git a/package.json b/package.json index 2d5a756..82c93f7 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "ci:coverage": "nyc pnpm test && nyc report --reporter=text-lcov > coverage.lcov", "ci:lint": "pnpm build && pnpm lint-staged", "ci:test": "pnpm test -- --verbose", - "dev-test": "ava --match='handlebars*'" + "dev-test": "ava --match='handlebars*' --update-snapshots" }, "files": [ "dist", @@ -94,7 +94,8 @@ "js": true }, "nodeArguments": [ - "--loader=ts-node/esm" + "--loader=ts-node/esm", + "--experimental-vm-modules" ] } } diff --git a/src/index.ts b/src/index.ts index 2171a4b..1586014 100644 --- a/src/index.ts +++ b/src/index.ts @@ -7,7 +7,9 @@ import type { OutputAsset, NormalizedOutputOptions, // ModuleInfo, - ResolvedId, PreRenderedChunk + ResolvedId, + PreRenderedChunk, + RenderedChunk, } from 'rollup'; import type { @@ -18,6 +20,7 @@ import type { } from '../types/index.d.ts'; import {createFilter} from '@rollup/pluginutils'; import {parse as parseHtml, serialize as serializeHtml, DefaultTreeAdapterMap} from "parse5"; +// import {Script, SourceTextModule, createContext} from "node:vm"; const getFiles = (bundle: OutputBundle): Record => { const result = {} as ReturnType; @@ -88,6 +91,7 @@ type HtmlModule = { // TODO might want to impose an own unique id, in case this changes after multiple builds id: string, resolved: HtmlImport[]; + document: DefaultTreeAdapterMap['document'], } export default function html(opts: RollupHtmlOptions = {}): Plugin { @@ -139,18 +143,19 @@ export default function html(opts: RollupHtmlOptions = {}): Plugin { async handler(code: string, id: string){ if(!filter(id)) return; - const handled : HtmlModule = { - id, - resolved: [], - }; - handledHtmls.set(id, handled); - - const htmlSrc = transform? await transform(code, { + const htmlSrc = transform? await transform(code, { id, }) : code; const document = parseHtml(htmlSrc); + const handled : HtmlModule = { + id, + resolved: [], + document, + }; + handledHtmls.set(id, handled); + // Figure out which references to load from this HTML by iterating all nodes (looking for src or href attributes) let loadResults : { reference: LoadReference, node: DefaultTreeAdapterMap['element'] }[] = []; if(document.childNodes){ @@ -199,7 +204,7 @@ export default function html(opts: RollupHtmlOptions = {}): Plugin { if(resolvedId){ const rollupResolved = await this.resolve(resolvedId, id, { skipSelf: true, - isEntry: true, // TODO: for href/src tags, this is probably the right option. For anything that is to be inlined into the HTML... probably no + isEntry: true, // TODO: for href/src tags, this is probably the right option. For anything that is to be inlined into the HTML... probably not }); // TODO: should we check if this is refused for resolving here. i.e. external? const htmlImport: HtmlImport = { @@ -216,6 +221,7 @@ export default function html(opts: RollupHtmlOptions = {}): Plugin { index, }; if(htmlImport.referenceId) { + // only used when importing from javascript reference.set(`\${import.meta.ROLLUP_FILE_URL_${htmlImport.referenceId}\}`); } handled.resolved.push(htmlImport); @@ -227,8 +233,7 @@ export default function html(opts: RollupHtmlOptions = {}): Plugin { // Transform to JS const serialized = serializeHtml(document); const jsModule = [ - //...resolveResults.map(x=>`import * as dep${x.index} from "${x.id}";`), - // ...handled.resolved.map(x=>`import("${x.id}");`),// Inject as a dynamic import. We need to remove these before outputting // todo better solution to mark the ids as dependencies of this bundle... + // This will only make sense when importing from javascript `export const html = \`${serialized.replaceAll(/`/g,'\\\`')}\`;`, `export default html;` ].join('\n'); @@ -236,39 +241,24 @@ export default function html(opts: RollupHtmlOptions = {}): Plugin { return {code: jsModule}; } }, - async generateBundle(output: NormalizedOutputOptions, bundle: OutputBundle) { - const files = getFiles(bundle); - console.log("must output?!", output, bundle, files); + async renderChunk( + code: string, + chunk: RenderedChunk, + options: NormalizedOutputOptions, + meta: { chunks: Record } + ){ + const htmlModule = chunk.facadeModuleId ? handledHtmls.get(chunk.facadeModuleId!) : null; + if(htmlModule){ + let html = ''; + for(const htmlImport of htmlModule.resolved){ + if(htmlImport.referenceId) { + const fileName = this.getFileName(htmlImport.referenceId); + htmlImport.reference.set(fileName); + } + } + html = serializeHtml(htmlModule.document);// This might contain temporary hashes, but it should be alright + return {code: html}; + } }, - - // async generateBundle(output: NormalizedOutputOptions, bundle: OutputBundle) { - // if (!supportedFormats.includes(output.format) && !opts.transform) { - // 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 htmlFile: EmittedAsset = { - // type: 'asset', - // source, - // name: 'Rollup HTML Asset', - // fileName - // }; - // - // this.emitFile(htmlFile); - // } }; } diff --git a/test/hbs/fixtures/index.hbs b/test/hbs/fixtures/index.hbs index 075ab39..d7ba232 100644 --- a/test/hbs/fixtures/index.hbs +++ b/test/hbs/fixtures/index.hbs @@ -1,6 +1,8 @@ - - - - + + + + + + diff --git a/test/hbs/snapshots/test.js.md b/test/hbs/snapshots/test.js.md index cd3ad1b..3344211 100644 --- a/test/hbs/snapshots/test.js.md +++ b/test/hbs/snapshots/test.js.md @@ -10,29 +10,65 @@ Generated by [AVA](https://avajs.dev). [ { - code: `(function (factory) {␊ - typeof define === 'function' && define.amd ? define(factory) :␊ - factory();␊ - })((function () { 'use strict';␊ - ␊=-u + code: `␊ + ␊ + ␊ + ␊ + ␊ + ␊ ␊ - ␊ - }));␊ + ␊ + //# sourceMappingURL=index.html.map␊ `, - fileName: 'batman.js', - map: null, + fileName: 'index.html', + map: SourceMap { + file: 'index.html', + mappings: '', + names: [], + sources: [], + sourcesContent: [], + version: 3, + }, + source: undefined, + }, + { + code: `const notSoIifi = ()=>{␊ + return \`I'm "annoying" ${"in case we need to test \\\`string\\\` escaping.''"}\`;␊ + };␊ + console.log(notSoIifi());␊ + ␊ + export { notSoIifi };␊ + //# sourceMappingURL=batman-f8ac73ff.js.map␊ + `, + fileName: 'batman-f8ac73ff.js', + map: SourceMap { + file: 'batman-f8ac73ff.js', + mappings: 'AAAY,MAAC,SAAS,GAAG,IAAI;AAC7B,IAAI,OAAO,CAAC,eAAe,EAAE,gDAAgD,CAAC,CAAC,CAAC;AAChF,EAAC;AACD,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC;;;;', + names: [], + sources: [ + '../batman.js', + ], + sourcesContent: [ + `export const notSoIifi = ()=>{␊ + return \`I'm "annoying" ${"in case we need to test \\\`string\\\` escaping.''"}\`;␊ + }␊ + console.log(notSoIifi());␊ + `, + ], + version: 3, + }, source: undefined, }, { code: undefined, - fileName: 'index.html', + fileName: 'batman-f8ac73ff.js.map', map: undefined, - source: `␊ - ␊ - ␊ - ␊ - ␊ - ␊ - `, + source: '{"version":3,"file":"batman-f8ac73ff.js","sources":["../batman.js"],"sourcesContent":["export const notSoIifi = ()=>{\\n return `I\'m \\"annoying\\" ${\\"in case we need to test \\\\`string\\\\` escaping.\'\'\\"}`;\\n}\\nconsole.log(notSoIifi());\\n"],"names":[],"mappings":"AAAY,MAAC,SAAS,GAAG,IAAI;AAC7B,IAAI,OAAO,CAAC,eAAe,EAAE,gDAAgD,CAAC,CAAC,CAAC;AAChF,EAAC;AACD,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC;;;;"}', + }, + { + code: undefined, + fileName: 'index.html.map', + map: undefined, + source: '{"version":3,"file":"index.html","sources":[],"sourcesContent":[],"names":[],"mappings":""}', }, ] diff --git a/test/hbs/snapshots/test.js.snap b/test/hbs/snapshots/test.js.snap index f57403c..342d38e 100644 Binary files a/test/hbs/snapshots/test.js.snap and b/test/hbs/snapshots/test.js.snap differ diff --git a/test/hbs/test.js b/test/hbs/test.js index 41428bf..553e862 100644 --- a/test/hbs/test.js +++ b/test/hbs/test.js @@ -8,7 +8,11 @@ import { getCode } from "../util/test.js"; import html from "../../src/index.ts"; import handlebars from "handlebars"; -const output = { dir: 'output', format: 'es' }; +const output = { + dir: 'output', // Output all files + format: 'es', // iifi and cjs should be added to tests + sourcemap: true,// Test if #sourcemapUrl is not accidentally included in the html-output +}; import {readFile} from "node:fs/promises"; import {fileURLToPath} from "node:url"; diff --git a/tsconfig.json b/tsconfig.json index ab229a7..db4fb87 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,8 +4,9 @@ "esModuleInterop": true, "noEmit": true, "noEmitOnError": false, - "noUnusedLocals": true, - "noUnusedParameters": true, + // Surpress errors about unused stuff: doesn't solve any bugs and is just annyoing during development, leave warning about this to the IDE or linters + "noUnusedLocals": false, + "noUnusedParameters": false, "pretty": true, "sourceMap": true, "strict": true,