From 71a377417d3227f99d8bae02a2be6c4505f3d2a4 Mon Sep 17 00:00:00 2001 From: Miel Truyen Date: Sun, 26 Nov 2023 22:15:40 +0100 Subject: [PATCH] feat: initial support for importing html from js --- src/index.ts | 313 ++++++++++-------- test/basic/snapshots/test.js.md | 14 +- test/basic/snapshots/test.js.snap | Bin 1087 -> 1099 bytes test/js-import/fixtures/batman.js | 2 + test/js-import/fixtures/icon.svg | 3 + test/js-import/fixtures/index.html | 9 + test/js-import/fixtures/index.js | 5 + test/js-import/fixtures/joker.css | 1 + test/js-import/snapshots/test.js.md | 71 ++++ test/js-import/snapshots/test.js.snap | Bin 0 -> 1314 bytes test/js-import/test.js | 51 +++ test/live-reload/snapshots/test.js.snap | Bin 1124 -> 1149 bytes test/multi-entry/snapshots/test.js.md | 14 +- test/multi-entry/snapshots/test.js.snap | Bin 1757 -> 1757 bytes test/rewrite-url/snapshots/test.js.snap | Bin 884 -> 908 bytes .../fixtures/output/fb585fdb6db313c9.svg | 3 + test/url-plugin/snapshots/test.js.snap | Bin 1119 -> 1148 bytes test/watch/snapshots/test.js.snap | Bin 771 -> 783 bytes 18 files changed, 332 insertions(+), 154 deletions(-) create mode 100644 test/js-import/fixtures/batman.js create mode 100644 test/js-import/fixtures/icon.svg create mode 100644 test/js-import/fixtures/index.html create mode 100644 test/js-import/fixtures/index.js create mode 100644 test/js-import/fixtures/joker.css create mode 100644 test/js-import/snapshots/test.js.md create mode 100644 test/js-import/snapshots/test.js.snap create mode 100644 test/js-import/test.js create mode 100644 test/url-plugin/fixtures/output/fb585fdb6db313c9.svg diff --git a/src/index.ts b/src/index.ts index 64c23c8..afd6584 100644 --- a/src/index.ts +++ b/src/index.ts @@ -77,7 +77,7 @@ export default function html(opts: RollupHtmlOptions = {}): Plugin { let filter = createFilter(include, exclude, {}); // TODO, we need to clear all these properly at sme point to avoid odd bugs in watch mode - let htmlModules = new Map();// todo clean this per new build? + // let htmlModules = new Map();// todo clean this per new build? let virtualSources = new Map(); let addedEntries = new Map(); let entryNames = new Map(); @@ -129,22 +129,29 @@ export default function html(opts: RollupHtmlOptions = {}): Plugin { const moduleId = resolved.id; const moduleExt = extname(resolved.id); const moduleName = specifier.replace(new RegExp(`${moduleExt}\$`),''); // strip extension of the name if any - const htmlModule : HtmlModule = htmlModules.get(moduleId) ?? { - id: resolved.id, - name: moduleName, - imports: [], - assetId: null, - importers: new Set(), - }; - htmlModule.importers.add(importer); + // const htmlModule : HtmlModule = htmlModules.get(moduleId) ?? { + // id: resolved.id, + // name: moduleName, + // imports: [], + // assetId: null, + // importers: new Set(), + // }; + // htmlModule.importers.add(importer); + // htmlModules.set(htmlModule.id, htmlModule); - htmlModules.set(htmlModule.id, htmlModule); // TODO: trigger special handling when imported from a JS file (in which case we want might want to export a module returning the HTML, instead of HTML directly) return { ...resolved, meta: { ...resolved.meta, - [pluginName]: {name: specifier} + [pluginName]: { + specifier: specifier, + id: resolved.id, + name: moduleName, + imports: [], + assetId: null, + importers: new Set(), + } } } } @@ -158,145 +165,163 @@ export default function html(opts: RollupHtmlOptions = {}): Plugin { } }, transform: { + order: 'pre', async handler(...args){ const [code, id] = args; if (!filter(id)) return; // parse - const htmlModule = htmlModules.get(id); - if(htmlModule) { - const contents = await readFile(id, {encoding: "utf-8"}); - - const htmlSrc = transform ? await transform(contents, { - id, - }) : contents; - - // 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) - let htmlImports: HtmlImport[] = htmlModule.imports = []; - if (document.childNodes) { - let nodeQueue = document.childNodes; - do { - const nextQueue: DefaultTreeAdapterMap['childNode'][][] = []; - await Promise.all(nodeQueue.map(async (node) => { - const el = (node); - const loadFunction: LoadFunction = async ({ - id: sourceId, - source, - type - })=>{ - if(!sourceId){ - sourceId = makeInlineId(id, node, 'js'); - } - if(source){ - virtualSources.set(sourceId, source); - } - const resolved = await this.resolve(sourceId, id, { - isEntry: type==='entryChunk', - }); - if(!resolved){ - throw new Error(`Could not resolve ${sourceId} from ${id}`); - } - - const selfInfo = this.getModuleInfo(id); - - let entryName: string|undefined = undefined; - const parentName = entryNames.get(id)??selfInfo?.meta[pluginName].name; - if(type==='entryChunk'){ - entryName= posix.join(posix.dirname(parentName),sourceId); - entryName = entryName.slice(0,-(posix.extname(entryName).length)); // Cut off the extension (TODO, is this wise?) - } - - const importName = (source && selfInfo?.meta[pluginName].name) - ? makeInlineId(parentName, node, extname(sourceId)) - : entryName; - - const htmlImport: HtmlImport = { - id: sourceId, - resolved: resolved, - // loaded: loaded, - node: el, - type, - source, - referenceId: - (resolved && (['chunk','entryChunk'].includes(type!))) ? this.emitFile({ - type: 'chunk', // Might want to adapt, or make configurable (see LoadType) - id: resolved.id, - name: importName, - importer: id, - }) : null, - placeholder: `html-import-${crypto.randomBytes(32).toString('base64')}`, - index: htmlImports.length, - } - // if(entryName){ - // addedEntries.set(resolved.id, entryName);// (we could do this using meta?) - // } - htmlImports.push(htmlImport); - return htmlImport.placeholder; - } - - let toLoad: LoadResult | undefined = load? await Promise.resolve(load({ - node: el, - sourceId: id - }, loadFunction)) : undefined; - - if (toLoad !== false) { - let asParent = (node); - if (asParent.childNodes) { - nextQueue.push(asParent.childNodes); - } - } - })); - nodeQueue = nextQueue.flat(); - } while (nodeQueue.length > 0); + const moduleInfo = this.getModuleInfo(id); + const moduleMeta = moduleInfo!.meta ?? {}; + let htmlModule = moduleMeta[pluginName]; + if(!htmlModule){ + const moduleExt = extname(id); + const moduleName = id.replace(new RegExp(`${moduleExt}\$`),''); // strip extension of the name if any + htmlModule = moduleMeta[pluginName] = { + id: id, + name: moduleName, + imports: [], + assetId: null, + importers: new Set(), } - - 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.. - 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{ - // TODO: this will probably not do for complicated cases ( presumably no other method then emitting the chunk as file, loading its result but excluding it from the output bundle) - // html = html.replace(htmlImport.placeholder, htmlImport.loaded?.code||htmlImport.source||''); - } - } - - // TODO when importing html from .js this will not do. ( - htmlJS.prepend([ - ...moduleImports, - `export const html = \`` - ].join('\n')).append([ - `\`;`, - `export default html;`, - ].join('\n')); - - const map = htmlJS.generateMap({ - source: id, - file: `${id}.map`, - includeContent: true, - hires: 'boundary' - }); - - return { - code: htmlJS.toString(), - map: map.toString(), - }; } + // const htmlModule = htmlModules.get(id); + + // const contents = await readFile(id, {encoding: "utf-8"}); + const contents = code; + + const htmlSrc = transform ? await transform(contents, { + id, + }) : contents; + + // 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) + let htmlImports: HtmlImport[] = htmlModule.imports = []; + if (document.childNodes) { + let nodeQueue = document.childNodes; + do { + const nextQueue: DefaultTreeAdapterMap['childNode'][][] = []; + await Promise.all(nodeQueue.map(async (node) => { + const el = (node); + const loadFunction: LoadFunction = async ({ + id: sourceId, + source, + type + })=>{ + if(!sourceId){ + sourceId = makeInlineId(id, node, 'js'); + } + if(source){ + virtualSources.set(sourceId, source); + } + const resolved = await this.resolve(sourceId, id, { + isEntry: type==='entryChunk', + }); + if(!resolved){ + throw new Error(`Could not resolve ${sourceId} from ${id}`); + } + + const selfInfo = this.getModuleInfo(id); + + let entryName: string|undefined = undefined; + const parentName = entryNames.get(id)??selfInfo?.meta[pluginName].name; + if(type==='entryChunk'){ + entryName= posix.join(posix.dirname(parentName),sourceId); + entryName = entryName.slice(0,-(posix.extname(entryName).length)); // Cut off the extension (TODO, is this wise?) + } + + const importName = (source && selfInfo?.meta[pluginName].name) + ? makeInlineId(parentName, node, extname(sourceId)) + : entryName; + + const htmlImport: HtmlImport = { + id: sourceId, + resolved: resolved, + // loaded: loaded, + node: el, + type, + source, + referenceId: + (resolved && (['chunk','entryChunk'].includes(type!))) ? this.emitFile({ + type: 'chunk', // Might want to adapt, or make configurable (see LoadType) + id: resolved.id, + name: importName, + importer: id, + }) : null, + placeholder: `html-import-${crypto.randomBytes(32).toString('base64')}`, + index: htmlImports.length, + } + // if(entryName){ + // addedEntries.set(resolved.id, entryName);// (we could do this using meta?) + // } + htmlImports.push(htmlImport); + return htmlImport.placeholder; + } + + let toLoad: LoadResult | undefined = load? await Promise.resolve(load({ + node: el, + sourceId: id + }, loadFunction)) : undefined; + + if (toLoad !== false) { + let asParent = (node); + if (asParent.childNodes) { + nextQueue.push(asParent.childNodes); + } + } + })); + nodeQueue = nextQueue.flat(); + } while (nodeQueue.length > 0); + } + + 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.. + 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{ + // TODO: this will probably not do for complicated cases ( presumably no other method then emitting the chunk as file, loading its result but excluding it from the output bundle) + // html = html.replace(htmlImport.placeholder, htmlImport.loaded?.code||htmlImport.source||''); + } + } + + // TODO when importing html from .js this will not do. ( + htmlJS.prepend([ + ...moduleImports, + `export const html = \`` + ].join('\n')).append([ + `\`;`, + `export default html;`, + ].join('\n')); + + const map = htmlJS.generateMap({ + source: id, + file: `${id}.map`, + includeContent: true, + hires: 'boundary' + }); + + return { + code: htmlJS.toString(), + map: map.toString(), + meta: moduleMeta, + }; } }, outputOptions(options){ return { ...options, entryFileNames: (chunkInfo)=>{ - const htmlModule = chunkInfo.facadeModuleId ? htmlModules.get(chunkInfo.facadeModuleId!) : null; + const moduleInfo = chunkInfo.facadeModuleId? this.getModuleInfo(chunkInfo.facadeModuleId) : null; + const htmlModule = moduleInfo?.meta?.[pluginName]; + // const htmlModule = chunkInfo.facadeModuleId ? htmlModules.get(chunkInfo.facadeModuleId!) : null; const addedEntry = chunkInfo.facadeModuleId ? addedEntries.get(chunkInfo.facadeModuleId!) : null; const defaultOption = options.entryFileNames ?? "[name]-[hash].js";// This default is copied from the docs. TODO: don't like overwrite it this way, can we remove the need for this or fetch the true default? if(htmlModule){ @@ -313,7 +338,9 @@ export default function html(opts: RollupHtmlOptions = {}): Plugin { } }, resolveFileUrl(options){ - const htmlModule = htmlModules.get(options.moduleId); + // const htmlModule = htmlModules.get(options.moduleId); + const moduleInfo = this.getModuleInfo(options.moduleId); + const htmlModule = moduleInfo?.meta?.[pluginName]; if(htmlModule){ // Simply use the relative path in our HTML-fileURLs instead of the default `new URL('${fileName}', document.baseURI).href`) return `"${options.relativePath}"`; @@ -324,7 +351,9 @@ export default function html(opts: RollupHtmlOptions = {}): Plugin { order:'post', handler(chunk: RenderedChunk){ if(chunk.facadeModuleId) { - const htmlModule = htmlModules.get(chunk.facadeModuleId); + const moduleInfo = chunk.facadeModuleId? this.getModuleInfo(chunk.facadeModuleId) : null; + const htmlModule = moduleInfo?.meta?.[pluginName]; + // const htmlModule = htmlModules.get(chunk.facadeModuleId); if (htmlModule) { return modulePrefix; // Overwrite any added banner with our own } @@ -342,7 +371,11 @@ export default function html(opts: RollupHtmlOptions = {}): Plugin { const chunk = (bundle); if(chunk.facadeModuleId) { facadeToChunk.set(chunk.facadeModuleId, chunk); - const htmlModule = htmlModules.get(chunk.facadeModuleId); + + const moduleInfo = this.getModuleInfo(chunk.facadeModuleId); + const htmlModule = moduleInfo?.meta?.[pluginName]; + // const htmlModule = htmlModules.get(chunk.facadeModuleId); + if(htmlModule){ htmlResults.set(bundleName, {chunk, htmlModule})} else if(virtualSources.has(chunk.facadeModuleId)){ virtualBundles.add(bundleName); diff --git a/test/basic/snapshots/test.js.md b/test/basic/snapshots/test.js.md index 6d98cb5..84db466 100644 --- a/test/basic/snapshots/test.js.md +++ b/test/basic/snapshots/test.js.md @@ -58,6 +58,12 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 [ + { + code: undefined, + fileName: 'script.body.script.js-e3b82208.js.map', + map: undefined, + source: '{"version":3,"file":"script.body.script.js-e3b82208.js","sources":["../batman.js","../script.html.body.script.js"],"sourcesContent":["export const b = ()=>\'batman\';\\nconsole.log(b());\\n","\\n import {b} from \\"./batman.js\\";\\n document.body.appendChild(\\n document.createTextNode(`Inline script including ${b()}`)\\n );\\n "],"names":[],"mappings":"AAAO,MAAM,CAAC,GAAG,IAAI,QAAQ,CAAC;AAC9B,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;;ACCJ,QAAQ,CAAC,IAAI,CAAC,WAAW;AACrC,gBAAgB,QAAQ,CAAC,cAAc,CAAC,CAAC,wBAAwB,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AACzE,aAAa"}', + }, { code: undefined, fileName: 'script.html', @@ -71,16 +77,10 @@ Generated by [AVA](https://avajs.dev). document.body.appendChild(␊ document.createTextNode(\`Inline script including ${b()}\`)␊ );␊ - //# sourceMappingURL=script.html.body.script.js-e3b82208.js.map␊ + //# sourceMappingURL=script.body.script.js-e3b82208.js.map␊ ␊ ␊ ␊ `, }, - { - code: undefined, - fileName: 'script.html.body.script.js-e3b82208.js.map', - map: undefined, - source: '{"version":3,"file":"script.html.body.script.js-e3b82208.js","sources":["../batman.js","../script.html.body.script.js"],"sourcesContent":["export const b = ()=>\'batman\';\\nconsole.log(b());\\n","\\n import {b} from \\"./batman.js\\";\\n document.body.appendChild(\\n document.createTextNode(`Inline script including ${b()}`)\\n );\\n "],"names":[],"mappings":"AAAO,MAAM,CAAC,GAAG,IAAI,QAAQ,CAAC;AAC9B,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;;ACCJ,QAAQ,CAAC,IAAI,CAAC,WAAW;AACrC,gBAAgB,QAAQ,CAAC,cAAc,CAAC,CAAC,wBAAwB,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AACzE,aAAa"}', - }, ] diff --git a/test/basic/snapshots/test.js.snap b/test/basic/snapshots/test.js.snap index 9432e768e9bc7d8d350ff6da75b0af915f2a34cf..463bfd971a6c18497afea073d2e74b4a2c271794 100644 GIT binary patch literal 1099 zcmV-R1ho4>RzV-J>00000000B6R?lzTL=^sJz204%v`Gj;aI*}kyOOh8QdGk3CStNgRSId; zhN>#0Qv72!aqus#9hwlO5^#n;0jUU1h)SHeA|WBT!au-?BSLWEhQ{`8Z0}}MlK3!w zGxOdz&-32iHl85lGyW!#_yZRU98&xTz`p;PnhAkK`86;qFk*lE?v>J(9zs0Es3vtHmlp-c2%#| zYAs1(`@Yu;Pdp(1#X})i{+jsB0vlyGt8LxM>`S}H-z8lmX&6jc> zRJxYUZfVZIi)V-JKrR!qRRsDvf}{C4oKk##G%a5`1hpZP^o~tyksR}<%X)42qD5?@$21@gNrCx8uDtza`V5{S~A#+2nk;LJI$Zfhq zq1$vhkgGY-2@h1oi6a&$O@&f=UtOcLqjvakgVG!7Dy6IH2BjMSl9bbbZ*fZ%*j^)~x%jV)l8g5f!H`S(us{pP8c=NOtRfxLL+k+PMC}~j@B7O(p zdjP)zc!2=(r}w3=1>hS2_(=f%7J$iO&SW@q&r|iU#FtU$#Z*t^-C&Mg(--FFuP&UE zhBpc$Y53GL$FQ=>r->0S{T#~0v9_vgx^n8VoVWw)M{>94Ir65Ga%)p*WwlMu*mIbh ze5B_4%r!eZmTgwEdKq1#$Fz{W%l5-tp2@0Pt5Lqn2~k?EVegriyDh(bs8?%8TeU1y zE#<=4p0mzbX)Vu6w<*0HGtSdf6YX?v9vj9uk#vvJdmN|NQMZ>V-Cj;<8I&3+xQEM> zK3qOVO-X}+Lw&TOYLsdh(CH>p>2uc1Zj!U~x@=4PAHRPmr;{Y-o-=1t2B~(!Pv%q6 Rg*3id{|6_4k8C&$006Sz5qSUr literal 1087 zcmV-F1i<@2RzVW~6Pku(( zTbZhUv>%HI00000000B6R?Tl4MHHX0y|&qYB%u|8+iF3ojW%|hqBg`IFfmb;LTa_4 zDg{@{evIP{`(f>_NkZgGz!}b*kczlci4#{OE^vi^0I3p3gw#_HAl~e*H@j=c32{gI z?Y^0L@6FqJ^X9jYx{6_|AG@D_OFi8)XxG)vzCm@@lKXDY_T0}NX`1ZG_wx_4sDN0* zMVxyB-YbB20ByhpoL|5kaU6LcEsH-|8fa2DY+7=IWTgY+ePV_*DA(YCE<|Re;Oxe0r@W*RjS@ z*Rhx*3qF;t0HPUW40<9V zjNt9}X+tz^Z2-Az)~kVj;DG1rRo@*fz?Nk7S@;G{?010Q0Zk5}y8sLD6&Kd&3!9^w z!P&7=&8PQ{ZP3&rN$%$;ucLvR&o8@vJ$}y})+6ViCx7_Y*l-~{ul~eev5E7^gPaPz z5LSxc&#^}_aVh5#mvRwjF60qjlkMQe;&q^dep_UQX`&$|VCQ`%bhPl6DJqFbsl(4csQ*A8Hj;Z`}}seAkL@`!|wyS--2;_D|5<+MruATyCsPqy$BmX%odXfMx?g(b0L#j^_k zs{S99G8DRwZ3-PR7FI{BCAE(}bVPfITpgye~30?nT<5d+$Q99z#u258q#Xr zJTwga_|iQ>?lC`3OWIx~WP3HHr4pjX-0i~r?&_h}m=ryjt54S?nGjhV{s(!&@f1f4 F000zG7JmQ$ diff --git a/test/js-import/fixtures/batman.js b/test/js-import/fixtures/batman.js new file mode 100644 index 0000000..413d5d3 --- /dev/null +++ b/test/js-import/fixtures/batman.js @@ -0,0 +1,2 @@ +export const b = ()=>'batman'; +console.log(b()); diff --git a/test/js-import/fixtures/icon.svg b/test/js-import/fixtures/icon.svg new file mode 100644 index 0000000..bd53f96 --- /dev/null +++ b/test/js-import/fixtures/icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/test/js-import/fixtures/index.html b/test/js-import/fixtures/index.html new file mode 100644 index 0000000..010cf6a --- /dev/null +++ b/test/js-import/fixtures/index.html @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/test/js-import/fixtures/index.js b/test/js-import/fixtures/index.js new file mode 100644 index 0000000..a27aafd --- /dev/null +++ b/test/js-import/fixtures/index.js @@ -0,0 +1,5 @@ +import html from "./index.html" + +export function render(){ + return html; +} diff --git a/test/js-import/fixtures/joker.css b/test/js-import/fixtures/joker.css new file mode 100644 index 0000000..8e91621 --- /dev/null +++ b/test/js-import/fixtures/joker.css @@ -0,0 +1 @@ +* { width: 100%; } diff --git a/test/js-import/snapshots/test.js.md b/test/js-import/snapshots/test.js.md new file mode 100644 index 0000000..50c5968 --- /dev/null +++ b/test/js-import/snapshots/test.js.md @@ -0,0 +1,71 @@ +# Snapshot report for `test/js-import/test.js` + +The actual snapshot is saved in `test.js.snap`. + +Generated by [AVA](https://avajs.dev). + +## js-import + +> Snapshot 1 + + [ + { + code: `var asset0 = "data:image/svg+xml,%3Csvg%20viewBox%3D%220%200%2032%2032%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%20%20%3Cpath%20style%3D%22fill%3Anone%3Bstroke%3A%2300ff0d%3Bstroke-width%3A5%3Bstroke-linecap%3Asquare%3Bstroke-linejoin%3Amiter%3Bstroke-dasharray%3Anone%3Bstroke-opacity%3A1%22%20d%3D%22M4.1%2014.72%2016%2026.31%2028.38%205.09%22%2F%3E%3C%2Fsvg%3E";␊ + ␊ + const html = \`␊ + ␊ + ␊ + ␊ + ␊ + ␊ + ␊ + ␊ + \`;␊ + ␊ + function render(){␊ + return html;␊ + }␊ + ␊ + export { render };␊ + //# sourceMappingURL=index-f75fa1e5.js.map␊ + `, + fileName: 'index-f75fa1e5.js', + map: SourceMap { + file: 'index-f75fa1e5.js', + mappings: 'AAAA,aAAe;;ACAf,MAAA,IAAA,GAAA,CAAA;AACA,+BAA+B,EAAwD,MAAA,CAAA;AACvF;AACA;AACA;AACA;AACA;AACA;AACA,cAAa,CAAA;;ACNN,SAAS,MAAM,EAAE;AACxB,IAAI,OAAO,IAAI,CAAC;AAChB;;;;', + names: [], + sources: [ + '../icon.svg', + '../index.html', + '../index.js', + ], + sourcesContent: [ + 'export default "data:image/svg+xml,%3Csvg%20viewBox%3D%220%200%2032%2032%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%20%20%3Cpath%20style%3D%22fill%3Anone%3Bstroke%3A%2300ff0d%3Bstroke-width%3A5%3Bstroke-linecap%3Asquare%3Bstroke-linejoin%3Amiter%3Bstroke-dasharray%3Anone%3Bstroke-opacity%3A1%22%20d%3D%22M4.1%2014.72%2016%2026.31%2028.38%205.09%22%2F%3E%3C%2Fsvg%3E"', + `␊ + ␊ + ␊ + ␊ + ␊ + ␊ + ␊ + ␊ + ␊ + `, + `import html from "./index.html"␊ + ␊ + export function render(){␊ + return html;␊ + }␊ + `, + ], + version: 3, + }, + source: undefined, + }, + { + code: undefined, + fileName: 'index-f75fa1e5.js.map', + map: undefined, + source: '{"version":3,"file":"index-f75fa1e5.js","sources":["../icon.svg","../index.html","../index.js"],"sourcesContent":["export default \\"data:image/svg+xml,%3Csvg%20viewBox%3D%220%200%2032%2032%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%20%20%3Cpath%20style%3D%22fill%3Anone%3Bstroke%3A%2300ff0d%3Bstroke-width%3A5%3Bstroke-linecap%3Asquare%3Bstroke-linejoin%3Amiter%3Bstroke-dasharray%3Anone%3Bstroke-opacity%3A1%22%20d%3D%22M4.1%2014.72%2016%2026.31%2028.38%205.09%22%2F%3E%3C%2Fsvg%3E\\"","\\n \\n \\n\\n \\n \\n \\n \\n\\n","import html from \\"./index.html\\"\\n\\nexport function render(){\\n return html;\\n}\\n"],"names":[],"mappings":"AAAA,aAAe;;ACAf,MAAA,IAAA,GAAA,CAAA;AACA,+BAA+B,EAAwD,MAAA,CAAA;AACvF;AACA;AACA;AACA;AACA;AACA;AACA,cAAa,CAAA;;ACNN,SAAS,MAAM,EAAE;AACxB,IAAI,OAAO,IAAI,CAAC;AAChB;;;;"}', + }, + ] diff --git a/test/js-import/snapshots/test.js.snap b/test/js-import/snapshots/test.js.snap new file mode 100644 index 0000000000000000000000000000000000000000..13c99529e5f93bcd8339eecd904c3d48c61003bc GIT binary patch literal 1314 zcmV+-1>O2VRzVWOSj9S`4$_^rz>~^^$xP8?9#93)BHTcwWmE<< zwS+2O?9+Tu`l-}+6V>IM3RB%sv0UkT5V?o6&ijYAPNGoP>=y4IYL?j#=wK^8(d>Jg zWto~~%D-*pjr^WOA>*06BScTLiDvC+*3MusFb1{}Cx@D~W0}%$C&jchds|DfG`rPv zMMtwtE>1(5fwY4#)NI0HMm2kjizGgxDX49l?Y8NUCToMh7ah$es~1yYz^LcSAo!=p zZbFNaZX7VpCQ%@0av||u-f`vWO?s`xJ=Y6_oL|Y->SrPD-ZoY=%Uro_+>x^@Yno+R zYlbZ+t-FSOSF_Aj!+bY2+L6n(TlwnkZQM{4FJ@e*9TA1 zU`J{~!wnpGF~e#nq3sR)=2>=b=Xg_T-mKNGP*3-gcPJG@BctApk7#0eoa4<}EpyVW zUpQff<+d7us@H)Qa z1M4_5sGPLWE6@Hu48B@V+n&T@6ep6w)#)O2B^E9_v0IV``Vmx(6>9%mkh zojXikb>>Ft19_z5C?gw=*D)c4=q@3&(I73-)_3LjzHHu?O^XoHAf!d~TU&(O+S0cP z8QjaXhO+)ns_~DF?h)c<+6~g$+tVKs@=!wTO0;dMbFw9U-q-gD+0S|{LRwPN*=jTz z4SX(3g_+-~0Dn{gUY`Z{WftJCS%4b~fUV>u!|cN$nWFNgs$qJP*d(7kk3NfBH{7%# zJADcNkG)INzyswX4NRpsA)RJp(=$02rh?DM1PeuyoY_$t0r*`3n4K$@np2a?Z_NSda{%981Ne5ns60JcmzDutlc9|wpBu{sxeTG9aK4Zl zhT>AeHqR7SqL-eaiCpn2RlM9%bMi<_ze1Kdl#9giqKb2@Sop7&oOzm1@+_fTx~hAZ Yaz-I#;8E%M?+Vqw0nSnuTS5*1029=F)c^nh literal 0 HcmV?d00001 diff --git a/test/js-import/test.js b/test/js-import/test.js new file mode 100644 index 0000000..7d739db --- /dev/null +++ b/test/js-import/test.js @@ -0,0 +1,51 @@ +import {join, dirname} from "node:path"; + +import test from "ava"; +import { rollup } from "rollup"; + +import {debugPrintOutput, getCode} from "../util/test.js"; + +import html from "../../src/index.ts"; +import handlebars from "handlebars"; + +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 {fileURLToPath} from "node:url"; +import urlPlugin from "@rollup/plugin-url"; +const __dirname = dirname(fileURLToPath(import.meta.url)); +process.chdir(join(__dirname, 'fixtures')); + +const defaultAssetInclude = [ + '**/*.(png|jpg|jpeg|gif|ico|svg)',// images, svg + '**/*.(woff|woff2|eot|ttf|otf)',// fonts + '**/*.(webm|mp4)',// video +]; + +test.serial('js-import', async (t) => { + const bundle = await rollup({ + input: 'index.js', + plugins: [ + html({ + }), + // Test with assets + urlPlugin({ + include: defaultAssetInclude, + limit: Number.MAX_SAFE_INTEGER,// Always inline things + }), + ] + }); + const code = await getCode(bundle, output, true); + debugPrintOutput('js-import',code); + t.snapshot(code); +}); + + +// TODO various parameters +// - format: cjs, iifi, ... +// - sourcemap: inline, false, (and the various exotic sourcemap options) +// Watch mode tests would be its own dir +// ... diff --git a/test/live-reload/snapshots/test.js.snap b/test/live-reload/snapshots/test.js.snap index 1ef818f353d780dda31e32265d2af4b299d27a71..8687cba20c08991b5d8145f8c193b747967ce5f9 100644 GIT binary patch literal 1149 zcmV-@1cLiPRzVyCM!QbqNe%P^^u(Q+@(DO`-~=Cl1D}8o!HFBJWV^QG76vZ$jODkx@Auws zpMQG0Pus^~e)mgc3`d$oJ|mrbq(@DoOG%I>ut*$J9<;hF49uj8 zht-T@5cz!tsydnX zH+o0|+>Vl-z)>3;Od3ayHq2N?A+^G&W2$Uswd!aZJ&U76;`5Ba(9vxBO)R2*;?uh% zRt!G>kv+oKH^_~)zxmFVbt0@DiM2UJRTMc@zVXB>7jb~DAhcWt82jXVB%X^? z%JQef^7223S2?_x#p{dN&%qRr#Q~@36xVXUqI3O}CW1v=uW#0Ll}@kg7nA5UJwpn; zexO^How=x$!^u)B;*xTyJVt-TMKyVRUQXUbPo5H#_k2Z7BsHxmZ?UMxs`}Tm^7zo> zi*)62wM9;P>D~`(dN0$G(CfP6xUPG@cGq=VwLRC}tKD|p+o|QaZtH9(o7{KZ{aQ=; zP}ilkUDw^M-E6t;%~m$cc3qe4X101Lti7lFQuEeSfHZz;DSr@f@-}%PE)GGqnmHz}J=0p|bSpxFMkYg>$7eUprNx z7j}TzdXA+re!rf;OQn#sVSQJ5*074HtkdbArl!lI7dl<|eQM##?3+Hf{qm@lq~n5m zRAz1=g_&DO1?37$0NT>*Ri!xZWGn%!&pDOm?=uL{WkqGe^zw9%TIiDd1)kfbUcNJL P@salz%M-tIFbV(wrT#aY literal 1124 zcmV-q1e^OoRzVek`SRmarAV7Oz8C zrPx_%yjCKQT$(Xi*Tz78Ku+AL3cr982Tt$a6R1)^NH1he%1b8I5<;&5T?RS=8kRC9l|_?v zgbN5)K_~aBT1fE{E_jj8CPHo}rgaJ5g7`3Czx536}Y+rfro%ij>DOq>K2Z9F! zklR~^3KIA##!}MFg_ViD(HHde6WV8{(PPw40$6k~VBGKYg3vdiEaO_5qaS%gWmIcw zUc@0y$>7x{X05$@t`T_Ba**Q#qfd0oc{B?6sZQQH*8@&GDj2!P2xrVEGD@x8V0^t0#JI;-~!gOCa08lcC7Ybeuzd*RS$godG_=pK0NMsZ(|s7s7M z8plm-oMst?42pYds%T~nQrFnoAc`gY>?8qDv+XyDh=#GpZo#zf-I(cxE@l#6UCt`X1KftRLo}R_) ztFzCTsXSIYoKFX~${+Y#2N(&!r{37E>nfby(3gYgbv?BddgDm9EIUm9OqX3rsH(#2aa=4zwS8K6AmUiXM5@3q2nCZJ4%N+4y*4w&VKzW$X7e*XaFO@ ze#)ztvb7JCUcz3RbCCG&%)%wE5)*jz@&AUG7I2@PSv}bgpA%Ae)Kb>FE!A{(lity? z=lGMzAEj&}roD?m-)yf!9g(8}YwP{U9|ACUTXw3SI?%M1ow$PlDx^A0$~Ry;ehTzG zkX=FOL!hsLzN<_Qm9@{O4FTtu&XrQOcB(*6?Es7QoI+!|zaF9&3L#0u`myr3VHFct zC&Rza4VNbyI+^%uZsOwNPR}gAJZU9~Tu`sd!Y!n*a0{v6Twx6%ZEf+YQp_qDps<-y qDrN68aCNz$Qki9XVZKMLRLT90p4g>cyfbh0k@qjl6TfpX3IG7?W(|!1 diff --git a/test/multi-entry/snapshots/test.js.md b/test/multi-entry/snapshots/test.js.md index 462b5cb..aaa0728 100644 --- a/test/multi-entry/snapshots/test.js.md +++ b/test/multi-entry/snapshots/test.js.md @@ -105,6 +105,12 @@ Generated by [AVA](https://avajs.dev). map: undefined, source: '{"version":3,"file":"app-01141b67.js","sources":["../app/app.js"],"sourcesContent":["export const bootstrap = (el,deps = [])=>{\\n el.innerHtml = `\\n
I\'m \\"annoying\\" ${\\"in case we need to test \\\\`string\\\\` escaping.\\"}. Hence this file \\\\\'tries\\\\\' to include all allowed forms of \'it\'
\\n
Deps: ${deps}
\\n `;\\n}\\n"],"names":[],"mappings":"AAAY,MAAC,SAAS,GAAG,CAAC,EAAE,CAAC,IAAI,GAAG,EAAE,GAAG;AACzC,IAAI,EAAE,CAAC,SAAS,GAAG,CAAC;AACpB,4BAA4B,EAAE,8CAA8C,CAAC;AAC7E,mBAAmB,EAAE,IAAI,CAAC;AAC1B,IAAI,CAAC,CAAC;AACN;;;;"}', }, + { + code: undefined, + fileName: 'index.body.script.js-45303f0f.js.map', + map: undefined, + source: '{"version":3,"file":"index.body.script.js-45303f0f.js","sources":["../index.html.body.script.js"],"sourcesContent":["\\n import {bootstrap} from \\"./app/app.js\\"\\n bootstrap(document.getElementById(\'root\'), \\"\\");\\n "],"names":[],"mappings":";;AAEY,SAAS,CAAC,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,QAAQ,CAAC"}', + }, { code: undefined, fileName: 'index.html', @@ -116,16 +122,10 @@ Generated by [AVA](https://avajs.dev). ␊ ␊ ␊ `, }, - { - code: undefined, - fileName: 'index.html.body.script.js-45303f0f.js.map', - map: undefined, - source: '{"version":3,"file":"index.html.body.script.js-45303f0f.js","sources":["../index.html.body.script.js"],"sourcesContent":["\\n import {bootstrap} from \\"./app/app.js\\"\\n bootstrap(document.getElementById(\'root\'), \\"\\");\\n "],"names":[],"mappings":";;AAEY,SAAS,CAAC,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,QAAQ,CAAC"}', - }, ] diff --git a/test/multi-entry/snapshots/test.js.snap b/test/multi-entry/snapshots/test.js.snap index 234d8de49a8a80895c8317c10e970d90446e013f..b42d35257ad19615fb0e3d1411861bbafbe72470 100644 GIT binary patch literal 1757 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 diff --git a/test/rewrite-url/snapshots/test.js.snap b/test/rewrite-url/snapshots/test.js.snap index 54de4b23526d1a461da557c90a6b3309916d7f94..d5176bf215e66efa3b2cd568c55a38d811ab3002 100644 GIT binary patch literal 908 zcmV;719SXARzVd0qL?U5rHi4-ARKLIgv<^ zuqZ-obnDx3yv}}UcN}7@D_ler`4f^RrbUQ?o(?KRO_vJ(2?{i`ch243DT#1_#1?n& zHBYytQRz!lP3B^EEs@Q9EJ)o!;zTo4oF0wHnj-~u7f)IZVW?}{`uX%K)c z=?EVYARxfs1o+SZHjQzF)@Qp1Vkn7mMy{-^Xp_hQ4h-P20sL$Le>6?(Ig>9&d3;5OoPA%X!3;4@wm@LnlT-1wi;|ej}R%^3Xi8;(8F=mYKFwC<` z(%n3ll`O-8_UQW}=|rNaXpi38`JmT7b}6M)Bwn0lqP!{7g!bq_3)R<+;)net4nn-Y4+3`-xUP6q-+D~DnBfT;&xaRad!WU&p+*jMR9FyO+;&Z z(Z}9F<)vZaHWuLQ#fi8RrjtdGcfu%*GrwU9a*2@B7BGP=rD4%<)vDub*1q_faw)*8 z6S=xD5pO=ON@cOn>5QyZBP7S{p(v|3&)E9)4pR}?I%`B=9afuFZ2cbdJm2&Dvs9FR z=M1osXHsNR;l{i21_xj}TXX_y=_`&v4HyL5*=RdcIb>m~Q{3sWwBGWHtuxN~-Og>! zH#%FKZ*?{~-|TEC_6FxSYU&o}w`zr!DJtN6W}>+h1VO+? z=ic>|y3}zNiAUbPOp|}R*-z0`=Kb!z2&1}zy8aZsn@30enZBcO)MI6yOV*$2I<2jS zWn4&FmBSwM7oJN-WyS@(C^>tF`E|dGeFOWm*7cJn=7I4`H zezbvKZQzBvxt#HwUf!BaJhC)5s$0$Ssv1t1_S}4%t@os(CW6s_+E;q|zU#c4zLsu& zEe@u{_INI7#b8QtX?9>WR%?%kqUKF~YtK9Z%$X;ELyX4`@Wh#YCs<9;4-W8C1Jr6h iCJ4w|DwVTLFV7F$#lZN@C+_*KT=yUI7I))b2><{|&%ToY literal 884 zcmV-)1B?7YRzV@Ml00000000BsR=sc2Koq}ozFb2|T3}$pIu?*pTLOWi=0h@7)mEZKB4Q|Q zQQY`S+&Z>pyQL+{(4k`BPk^OmMTmi&4JO3Q)(QRz2Hu_HGQK&(rrXj;MS-kFbPr8sQ5Vo1p`s-mov`b3$)~?8Eg<+6=JJCkurFH!(nE6L0|d1o)mb$qku2Nh8z%bO7%FpVJ8wamZvp zgV0OB5#TG}XC`4X7B?B^lh1>WaD~k+GlA1h$DqBA@D?>4+YjV*2eKV_x+_=Zo75^A z)b)W}S-VxObtD-YwG`8~sW%_AEs!)gleLOr?$j(tH{_s2W!-fvD&uf@qbzmHl0Ix1&km ztGdxPZ8c$v@Fk3ovIs?LDe#qWl?}(|-Q4&e(!~@`59Hd&K$PKeStz4@4n_p)qvHiWGQC0+MTK8K6eeHmE6g}{K<$9(^;YE!8(`HQwF5%# zDO(^^Xp~p&?yAjVupw70L?GMYl0%PZnzmeA)U=smUDN8tIZc}@&am#Rrp<=bf~GBm z0?uPp8Tc=Hk`u+a2d3lRXa8EL$aNygQW+ZQo_o~`VX95rpu0*7lJmEV{Tfx6d9Bi- zx)C0riaJ2AJH}oucJ5@;s1gsBj?@ND9hdq|&vXOX_nK9rj@*|-4)$DHC2hyphFt|7 zLYvTuBvn*CAcVkzI(M3+|2{z?&K*O&`2m=O+v)@03*eaDTw<}QOQoy; diff --git a/test/url-plugin/fixtures/output/fb585fdb6db313c9.svg b/test/url-plugin/fixtures/output/fb585fdb6db313c9.svg new file mode 100644 index 0000000..bd53f96 --- /dev/null +++ b/test/url-plugin/fixtures/output/fb585fdb6db313c9.svg @@ -0,0 +1,3 @@ + + + diff --git a/test/url-plugin/snapshots/test.js.snap b/test/url-plugin/snapshots/test.js.snap index 679d82265cf92952177b750d1f044d12397c0d40..83059937bde72885a46e5faa8290c453fb129969 100644 GIT binary patch literal 1148 zcmV-?1cUoQRzVcA zrM1WJz3-bh^X9!b4?DIWIXmQ?4>9$qj{_%)J?zd~gkVZM5?V3oMU=e#&~+_p-Qhng zf&lD?%BZve0CfPk1^}A?a2fG4h%=MKIzVVRnwpvdBmyb|I*-uZ416A;_t_hz!_V2U zz$m$20N_^uI79%C5Wp8`K+A91+t{I~Fd9xzPp6O{5Wr)UGQe^H;C3Mg5l%qtB0#SQ z@NN;{Q4!$lVh&Oshg<|y0yG7eQQ>*E5N-yQoXEw)59~xCp^`1Nq}jRF>J{6fffZh9 zh)f>&SoNdstUWt7*APX#A4dt54kcT9&=9NDmn0JHCJw%3#jzK5U%&lID}&EFS38!j zFFWcsQ3ER$a~_mCo{wL(f{_=`ox}mUgwO{ifT2w>u;LsKpUt0s3KyTUSY~j#7cWfq zJ_lodOeQ?;4mVTy2@d5woDeSx<+@Rk*>rMUJ~@e8kuxNb>u<=aTFp$D=Ke_4jzWq< z$}9$PctYgvg(pIHFJwfa6{IuVugF0bF(TJx(=_i?ZkcAg(q@nArg^<`!!&PHwoG%Y zVVdogwaTVxZXQ#&N7n16xt@+1jYdO$@TVgndZCN=)gBG}Kf3FmLX*K)n>}o~tD-dc zHGMDKkrM2;WY390S?VRY(~>*(;__n0wU=Dms2R?RO7^;PhH6%i7@BtE9vmYhPU6K> zB8k(Q6i@xyUY*tgcW;Jz`rM2)~3E=w@fXD&tascmf03UMz zUvh)=KDRYYHB>y2;e39}*}k5dTjOCE9*3de=3jRx(lq{&J4$0NJ%*_m_#?3}IOeHB zIi|QYe*SZ=3xfnpzf0^<9;@Z0v07e6g_}IUYy5b@=ki7Y4?uE8e7-9nKo^)RBTp|J z&)mr-wbN5~LeU*`x6liHFFd8am8Z_y+kdXT{mh-Ux3l*4OuK%r@GR|(m4><(SY2Et zd)=4!1HYmeZL-%@bZyVW{k3RcF|H}Pt|_|4{)Rqyu=jr8ha}VYD2)}vRP+r+-{|-I zYTrq^R{812}iJw?|DJ@9cx((!y>G0ZRuv0|(dnnXJ|B{ejy z)6v|KaK7)kw5J&6;*p4zKgVKDkT-X&1dnUBBQI18Gw>)*jx?@CdKN2n`B~?q*m69| zSv8gwU0YPOl@zqWmTR;Jt2fsFiHk#( z2Uz3*Tpr+C9^f$#@EZ^CqVRvXIIId2FAjHwCtMuf68^S}!$$(ZC&E)M4qpiX-w6MT Oi^K0S{+Glc4*&o_og#h! literal 1119 zcmV-l1fcstRzVti zV?UHZsa1H_0oMRKfag$p5%FpeXeS5_rEE6KA(2B#4n2d=oyZxa57--p;ulOzFiQRx z5Pt=nB940i_!13h(>wY;HYiGr#D#^0(B(%kd5A&=t_HZ3h`9(eE_#yVdVu!;4*=gJ zV=kF#mrEQ6#W!u|Z z(wCN(8={DheJ`N7Q?S0*5R1i^a>P3f47{!RzUA({e(RN1}b9i ziy+grZ2YR`jG}mU){jG%5&AI2aYLIV5XE@XQUBqmaOnwyWd>(Q@xuJ*V{R;t`Gk|< z@QaC`xl`!~2gLGRsjd_x)}2(BW;>AzQshab`Wuog7b6qa^5&?iOlvxbc;V~$%fRXc?adt6u5>xCPtdZVzbs=EzPt#1@|RCQ;f zxihlfRMpK;YQRsr_or7tv|JM(%RTDYe{|MATy^)YnX1DJ#ahOpf-X$g5c#Gc3v~$m})3Fli}(3 zl(Ts~GqpE0q!`7?jH3!QNo*lBm5$sh?NWd}Ry%{eEBWE3y{=%@+89<5tL7$t#=r zkPCY8HQED-&=VU+BrqK|khq=;iVZ>o?*NCSN~zTCmdufIrEi(wtfSDCiF29L^` ztT1JzCMz{~SLM=r=(NR#t8@mVS2q8Ni$f90R25(Xz5_f2{04YY_&;16+QQt6!yVx< l7l*fnzwP4iF;IUhJmKQ-H5hy={3|XFzXLM}aTO z1;VV}>>rB=00000000BERZUOSKp1|eU%M7zK{yyclA&J9HbIQKACS5dVj_}gJfL!z zZHMjRZrf~&upz|o13Vco-tZTgc=P1n@aWN_F@|{1nCX7NmM^2Bhv_>r@AJ+xeV&=_ zu2vg?^E}#l$K!h3;CzF{j#rO-7DiqWM?1T&%VM^yeUXuYcu1BgGXM$z?gCf>Fix~F zqS~z%YZKCoa=9Fc4kCjL5%Q!19wOwGc#|ajBtl7)RKElG31ET%a|Bo>-Ll$Jb&WeQ zk^152=x74jBfu{LyqAEl67X9}LF7Y_%Q7%210@+~%fM?n1<4LVhCvjN9L9+>AvU6p z5yc5yo^&$9sj2L0y}=)_ChraCb>HQic`t4@QmJy2g+~|BqF}w{^h>-f3G{5qYnqH}Y$dLF0DF%SJPB*BjiJ zEm<8@r;M(btfXkkN)|rl8>nN_8#sX<#gx%9oi0+#qW4y5okm`;LDxgdBFd=aF~7!L zD!7<5_P8$^noy)Mk7DYvh}Ht1(~VZ(*CutHZ-zlDrdyQJ?V@g3*J$U%EV3}H`?bdp z@0X9;VZO;i{WNVZ9)|`QA>@N1thle$2_gvv|I;T|PTI*oI!6N8GG6djR1bWkaNRUS zZKH6!Eli_>kBq`oBcHbpCW`r$enKViWA4Wy@0l-5)79z>d?4zJm3`Jsh^?4LvtxkB zC>XX~sogObZM$MtM6+Pq3+B9S&liiuqOmQGeCC@1>?we$0&6O;qXKVL;G^0-`sW_? zd_|N)r(a8}DwzL;g$DKRQSJ>~J&|}~z|ZQw0o7#p$?%T@!3ND{!92+wYk0MT@a@TR5H{b32T^K*ZZSu4@Z>N&AvR1tcF_#Q7;`D}cLzMZg8D zjbhb`BD;fe&nlHl2xe#>} z=bgZ1NvANBnJTXME%v}}v)+L2bC+$DJ<)DuTyt$ZJUoaN2Wyej5Am`p*)vs-+3t)^ z;HjGX>_*^rQZwnsPUMGz#F0~@NhO&(A(NW8PMrW#K z%1XoNdeuyV!e``%PuK%>RC$A(fX9N^q(&yEiD{C1E5s)tpLMbp5<7+&$Fq5pxkTn- z5aBT{UnEJ92nK8q{F(uWu_)lpab0H{VGs$j3GA(D-88R}bYm9mF!Xuz@x%MIqgGgk z&DBq;&BdeG2oGcYAupx4SF2-+BrEuzI=OP(O8!wfaI7}z3l_zGz-i^WL1k=OIa(G5 zP5CjcEYot?-0vvopYGzaN(R6Ed3ObPS<(E0^mP`!Hb}9hqQOl|~?-&cv z7*}GI2@Un;0IfQzn~2R}@J8R!h0t@_;4QCZojh>h8K*+_R{*#EIhjg7)AI*)cDQ3hKV6+c_&+8nRw)Yy007U@ BaWnt`