From 831e60759174884d269e7d76be0119cb5244e4b6 Mon Sep 17 00:00:00 2001 From: Miel Truyen Date: Thu, 27 Apr 2023 21:49:13 +0200 Subject: [PATCH] WIP: Basic working version. Will import .html files and resolve its dependencies. But it will generate invalid html when sourcemaps are enabled, assets like do not yet work... --- CHANGELOG.md | 1 + package.json | 5 +- src/index.ts | 78 ++++++++++++++------------------ test/hbs/fixtures/index.hbs | 10 ++-- test/hbs/snapshots/test.js.md | 70 +++++++++++++++++++++------- test/hbs/snapshots/test.js.snap | Bin 469 -> 1035 bytes test/hbs/test.js | 6 ++- tsconfig.json | 5 +- 8 files changed, 105 insertions(+), 70 deletions(-) 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 f57403c531c2aecb9a78399080dbe6a4a8e84b8d..342d38eb3886803a7ac72ce9b9c88dd974108060 100644 GIT binary patch literal 1035 zcmV+m1oZnsRzV~v4hM2vzB zzwX!dey^(DuU=Qz({`&HxSvLkzva@GU4GbcgxBRQCye|^IQ^&-$msD?&vT@6*LS<>h6BO@y-upTpQ6bO6>9^~BozS(%15 z4Gd;Rk8lOdD&V4l&~?B^#&CrEUh9y%5*uT4Wo1Q&d*$YMNXQ769)9OI(OEq5Mg-N56+7vp&RZWQR{HWYnWts)p}eyL`i>1@<`UHLkG@U<&0Qs1>W&QOyq`sUy>+v>$K&_o+B=` zuQ~43jdr_y7*QgR`@Bwjfp^s9v{9=J_=65ivsTgF!2oJLW~K5riGrih<#(KZ-xmiT ze|Wp@3y(i4D?+*F^vy(K#kSw&A2_{Ha@aiMBfNz1PaxLFmw^rv@%h1c`n9n5YVDpQ zHxQ8|B9P5s*KhlzPS)1zjT426tbYT6y!YA|rhwUa1baTU^YB;)? zR=O4)L`HP;9xazE1B&u|GInhRLUJJ$W4InOs>2q^^03GCVXFeMXIIF$MB+7Kt0J+* zsV!z!i7nJz1*oZ#0JAqJ3V5T8vAfnC#N8W4Ekb#&)aFboGWdtv$x}tS!ai zjB)EGV>hjXZN?6^2d(3q3hKPC2-@79h}0c#jmOb_=n%N*>1&tAQha;(hh>59rB=mR z-?3^)TmP9ls~n5Ca05P?9Y6s18t@G81K^j!a4#=4N1rXuB>w<~KY^7kBD4W`0r&$@ zDj~F9nvO0`{S5L+eN}p?`(<3~Q5M4nq`&^1(%ILa(<$p_Z=$&{R7X2LpKvV2WlM}# z7_NYR&#K$2=AODk&CS910{tHfUn}z@UCHleDf#j>lq|;1O4-<1DelY7@#W|EN^u`H z3=^TE89$_%Nz%JOcrQUZmpsYAp>08>H_m=xayw3?7+<3K8}fhfyPos6{tNYyvw-*t F001gc1y29~ literal 469 zcmV;`0V@7MRzVV8L&)8 zI%N|*Qbu3j3Be3Iu^w$wBl&`5u(z;oBlZ#NP+fz{L6)%@z=AcKO#%)9i@*xN;oOMq zDzA`dRGyGNBTj*k8^i+?S=HlUEV%*eleSu|56cTmUJ-AIRf~|eRkGMWEe!%o1e&O^ zHozuOS%W36ge)5CmUP2u%1xwF+6@^uDx3A_g;O`PiBusKGK^A5ecz{@g|I{0?c$)% z5<&Nh=F7k1)C=D24V=qf_uE4-opz>LQf;z`o6f+&b=gB*Y0l*^iscbY7PCSPNJ7JR#ZZ}FNRjsBOpC{BB|GbV`+5Kw*CrX7p?~hCp|24v|knba48xC{#t}{%e zVKo1-HjUKAcbV(qZlJ^ri{@E0F;r*Vcl+Mwy