From 3fae95c11734a88e6c183daac3595df66bc54b6b Mon Sep 17 00:00:00 2001 From: Edward Faulkne Date: Thu, 21 May 2020 01:55:23 -0400 Subject: [PATCH] handle customized rootURL --- src/fastboot-schema.js | 2 +- src/html-entrypoint.js | 30 ++++++++++++++----- test/html-entrypoint-test.js | 57 +++++++++++++++++++++++++++++++----- yarn.lock | 5 ---- 4 files changed, 73 insertions(+), 21 deletions(-) diff --git a/src/fastboot-schema.js b/src/fastboot-schema.js index 5654b6e..91fcede 100644 --- a/src/fastboot-schema.js +++ b/src/fastboot-schema.js @@ -79,7 +79,7 @@ function loadConfig(distPath) { ({ appName, config, html, scripts } = loadManifest(distPath, pkg.fastboot, schemaVersion)); } else { appName = pkg.name; - ({ config, html, scripts } = htmlEntrypoint(distPath, pkg.fastboot.htmlEntrypoint)); + ({ config, html, scripts } = htmlEntrypoint(appName, distPath, pkg.fastboot.htmlEntrypoint)); } let sandboxRequire = buildWhitelistedRequire( diff --git a/src/html-entrypoint.js b/src/html-entrypoint.js index f83d033..8e2a221 100644 --- a/src/html-entrypoint.js +++ b/src/html-entrypoint.js @@ -4,7 +4,7 @@ const { JSDOM } = require('jsdom'); const fs = require('fs'); const path = require('path'); -function htmlEntrypoint(distPath, htmlPath) { +function htmlEntrypoint(appName, distPath, htmlPath) { let html = fs.readFileSync(path.join(distPath, htmlPath), 'utf8'); let dom = new JSDOM(html); let scripts = []; @@ -19,11 +19,15 @@ function htmlEntrypoint(distPath, htmlPath) { } } + let rootURL = getRootURL(appName, config); + for (let element of dom.window.document.querySelectorAll('script,fastboot-script')) { let src = extractSrc(element); - let ignored = extractIgnore(element); - if (!ignored && isRelativeURL(src)) { - scripts.push(path.join(distPath, src)); + if (!extractIgnore(element)) { + let relativeSrc = urlWithin(src, rootURL); + if (relativeSrc) { + scripts.push(path.join(distPath, relativeSrc)); + } } if (element.tagName === 'FASTBOOT-SCRIPT') { removeWithWhitespaceTrim(element); @@ -51,10 +55,20 @@ function extractIgnore(element) { return false; } -function isRelativeURL(url) { - return ( - url && new URL(url, 'http://_the_current_origin_').origin === 'http://_the_current_origin_' - ); +function getRootURL(appName, config) { + let rootURL = (config[appName] && config[appName].rootURL) || '/'; + if (!rootURL.endsWith('/')) { + rootURL = rootURL + '/'; + } + return rootURL; +} + +function urlWithin(candidate, root) { + let candidateURL = new URL(candidate, 'http://_the_current_origin_'); + let rootURL = new URL(root, 'http://_the_current_origin_'); + if (candidateURL.href.startsWith(rootURL.href)) { + return candidateURL.href.slice(rootURL.href.length); + } } // removes an element, and if that element was on a line by itself with nothing diff --git a/test/html-entrypoint-test.js b/test/html-entrypoint-test.js index 2823552..df8030f 100644 --- a/test/html-entrypoint-test.js +++ b/test/html-entrypoint-test.js @@ -38,7 +38,7 @@ describe('htmlEntrypoint', function() { fixturify.writeSync(tmpLocation, project); - let { html, scripts } = htmlEntrypoint(tmpLocation, 'index.html'); + let { html, scripts } = htmlEntrypoint('my-app', tmpLocation, 'index.html'); expect(html).to.be.equalHTML(project['index.html']); expect(scripts).to.deep.equal([]); @@ -61,7 +61,7 @@ describe('htmlEntrypoint', function() { fixturify.writeSync(tmpLocation, project); - let { html, scripts } = htmlEntrypoint(tmpLocation, 'index.html'); + let { html, scripts } = htmlEntrypoint('my-app', tmpLocation, 'index.html'); expect(html).to.be.equalHTML(project['index.html']); expect(scripts).to.deep.equal([ @@ -88,7 +88,7 @@ describe('htmlEntrypoint', function() { fixturify.writeSync(tmpLocation, project); - let { html, scripts } = htmlEntrypoint(tmpLocation, 'index.html'); + let { html, scripts } = htmlEntrypoint('my-app', tmpLocation, 'index.html'); expect(html).to.be.equalHTML(` @@ -119,7 +119,7 @@ describe('htmlEntrypoint', function() { fixturify.writeSync(tmpLocation, project); - let { html } = htmlEntrypoint(tmpLocation, 'index.html'); + let { html } = htmlEntrypoint('my-app', tmpLocation, 'index.html'); expect(html).to.be.equalHTML(` @@ -148,7 +148,7 @@ describe('htmlEntrypoint', function() { fixturify.writeSync(tmpLocation, project); - let { html, scripts } = htmlEntrypoint(tmpLocation, 'index.html'); + let { html, scripts } = htmlEntrypoint('my-app', tmpLocation, 'index.html'); expect(html).to.be.equalHTML(` @@ -178,7 +178,7 @@ describe('htmlEntrypoint', function() { fixturify.writeSync(tmpLocation, project); - let { html, scripts } = htmlEntrypoint(tmpLocation, 'index.html'); + let { html, scripts } = htmlEntrypoint('my-app', tmpLocation, 'index.html'); expect(html).to.be.equalHTML(` @@ -207,7 +207,7 @@ describe('htmlEntrypoint', function() { fixturify.writeSync(tmpLocation, project); - let { html, scripts } = htmlEntrypoint(tmpLocation, 'index.html'); + let { html, scripts } = htmlEntrypoint('my-app', tmpLocation, 'index.html'); expect(html).to.be.equalHTML(` @@ -218,4 +218,47 @@ describe('htmlEntrypoint', function() { `); expect(scripts).to.deep.equal([]); }); + + it('extracts configs from meta', function() { + let tmpobj = tmp.dirSync(); + let tmpLocation = tmpobj.name; + + let project = { + 'index.html': ` + + + + + + + `, + }; + + fixturify.writeSync(tmpLocation, project); + let { config } = htmlEntrypoint('my-app', tmpLocation, 'index.html'); + expect(config).to.deep.equal({ + 'my-app': { APP: { autoboot: false }, rootURL: '/custom-root-url/' }, + }); + }); + + it('understands customized rootURL', function() { + let tmpobj = tmp.dirSync(); + let tmpLocation = tmpobj.name; + + let project = { + 'index.html': ` + + + + + + + `, + }; + + fixturify.writeSync(tmpLocation, project); + + let { scripts } = htmlEntrypoint('my-app', tmpLocation, 'index.html'); + expect(scripts).to.deep.equal([`${tmpLocation}/bar.js`]); + }); }); diff --git a/yarn.lock b/yarn.lock index 12487bd..04614d1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4235,11 +4235,6 @@ simple-dom@^1.4.0: "@simple-dom/serializer" "^1.4.0" "@simple-dom/void-map" "^1.4.0" -simple-html-tokenizer@^0.5.9: - version "0.5.9" - resolved "https://registry.yarnpkg.com/simple-html-tokenizer/-/simple-html-tokenizer-0.5.9.tgz#1a83fe97f5a3e39b335fddf71cfe9b0263b581c2" - integrity sha512-w/3FEDN94r4JQ9WoYrIr8RqDIPZdyNkdpbK9glFady1CAEyD97XWCv8HFetQO21w81e7h7Nh59iYTyG1mUJftg== - slash@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"