-
Notifications
You must be signed in to change notification settings - Fork 159
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
html-oriented manifest format ----------------------------- In the new schema format, which is defined in ember-fastboot/fastboot@3fd5bc9 the manifest is written into HTML and later extracted by fastboot on server side instead of previously reading from dist/package.json Note: The new schema in fastboot does not handle fastboot config https://github.com/ember-fastboot/ember-cli-fastboot/tree/e4d0b7c7bcdf82def0dc8726835b49d707673f41#providing-additional-config This commit changes to read Fastboot.config from dist/package.json instead of ignoring it Allow to require module path from whitelisted dependency ------------------------------------------------------- Incrementing schema to 5 also included the changes in schema 4 strictWhitelist See ember-fastboot/fastboot#200 Revert back to put config in dist/package.json add data-fastboot-ignore to unexpected files properly ignore files that should not execute in fastboot
- Loading branch information
Showing
10 changed files
with
231 additions
and
70 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
123 changes: 123 additions & 0 deletions
123
packages/ember-cli-fastboot/lib/broccoli/html-writer.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
'use strict'; | ||
|
||
const Filter = require('broccoli-persistent-filter'); | ||
const { JSDOM } = require('jsdom'); | ||
|
||
module.exports = class BasePageWriter extends Filter { | ||
constructor(inputNodes, { annotation, fastbootConfig, appName, manifest, outputPaths }) { | ||
super(inputNodes, { | ||
annotation, | ||
extensions: ['html'], | ||
targetExtension: 'html', | ||
}); | ||
this._manifest = manifest; | ||
this._rootURL = getRootURL(fastbootConfig, appName); | ||
this._appJsPath = outputPaths.app.js; | ||
this._expectedFiles = expectedFiles(outputPaths); | ||
} | ||
|
||
getDestFilePath() { | ||
let filteredRelativePath = super.getDestFilePath(...arguments); | ||
|
||
return filteredRelativePath === this._manifest.htmlFile ? filteredRelativePath : null; | ||
} | ||
|
||
processString(content) { | ||
let dom = new JSDOM(content); | ||
let scriptTags = dom.window.document.querySelectorAll('script'); | ||
|
||
this._ignoreUnexpectedScripts(scriptTags); | ||
|
||
let fastbootScripts = this._findFastbootScriptToInsert(scriptTags); | ||
let appJsTag = findAppJsTag(scriptTags, this._appJsPath, this._rootURL); | ||
insertFastbootScriptsBeforeAppJsTags(fastbootScripts, appJsTag); | ||
|
||
return dom.serialize(); | ||
} | ||
|
||
_findFastbootScriptToInsert(scriptTags) { | ||
let rootURL = this._rootURL; | ||
let scriptSrcs = []; | ||
for (let element of scriptTags) { | ||
scriptSrcs.push(urlWithin(element.getAttribute('src'), rootURL)); | ||
} | ||
|
||
return this._manifest.vendorFiles | ||
.concat(this._manifest.appFiles) | ||
.map(src => urlWithin(src, rootURL)) | ||
.filter(src => !scriptSrcs.includes(src)); | ||
} | ||
|
||
_ignoreUnexpectedScripts(scriptTags) { | ||
let expectedFiles = this._expectedFiles; | ||
let rootURL = this._rootURL; | ||
for (let element of scriptTags) { | ||
if (!expectedFiles.includes(urlWithin(element.getAttribute('src'), rootURL))) { | ||
element.setAttribute('data-fastboot-ignore', ''); | ||
} | ||
} | ||
} | ||
}; | ||
|
||
function expectedFiles(outputPaths) { | ||
function stripLeadingSlash(filePath) { | ||
return filePath.replace(/^\//, ''); | ||
} | ||
|
||
let appFilePath = stripLeadingSlash(outputPaths.app.js); | ||
let appFastbootFilePath = appFilePath.replace(/\.js$/, '') + '-fastboot.js'; | ||
let vendorFilePath = stripLeadingSlash(outputPaths.vendor.js); | ||
return [appFilePath, appFastbootFilePath, vendorFilePath]; | ||
} | ||
|
||
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); | ||
} | ||
} | ||
|
||
function findAppJsTag(scriptTags, appJsPath, rootURL) { | ||
appJsPath = urlWithin(appJsPath, rootURL); | ||
for (let e of scriptTags) { | ||
if (urlWithin(e.getAttribute('src'), rootURL) === appJsPath) { | ||
return e; | ||
} | ||
} | ||
} | ||
|
||
function insertFastbootScriptsBeforeAppJsTags(fastbootScripts, appJsTag) { | ||
let range = new NodeRange(appJsTag); | ||
|
||
for (let src of fastbootScripts) { | ||
range.insertAsScriptTag(src); | ||
} | ||
} | ||
|
||
class NodeRange { | ||
constructor(initial) { | ||
this.start = initial.ownerDocument.createTextNode(''); | ||
initial.parentElement.insertBefore(this.start, initial); | ||
this.end = initial; | ||
} | ||
|
||
insertAsScriptTag(src) { | ||
let newTag = this.end.ownerDocument.createElement('fastboot-script'); | ||
newTag.setAttribute('src', src); | ||
this.insertNode(newTag); | ||
this.insertNode(this.end.ownerDocument.createTextNode('\n')); | ||
} | ||
|
||
insertNode(node) { | ||
this.end.parentElement.insertBefore(node, this.end); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.