-
-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from CanopyTax/initial-impl
Initial implementation
- Loading branch information
Showing
9 changed files
with
4,878 additions
and
1 deletion.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{ | ||
"presets": ["@babel/preset-env"], | ||
"plugins": ["@babel/plugin-transform-modules-umd"] | ||
} |
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 |
---|---|---|
|
@@ -59,3 +59,5 @@ typings/ | |
|
||
# next.js build output | ||
.next | ||
|
||
lib |
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,5 @@ | ||
.gitignore | ||
lib | ||
LICENSE | ||
yarn.lock | ||
.prettierignore |
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,4 @@ | ||
language: node_js | ||
node_js: | ||
- "node" | ||
script: yarn test && yarn check-format && yarn build |
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 |
---|---|---|
@@ -1,2 +1,5 @@ | ||
# single-spa-html | ||
A helper library for single-spa and vanilla html / web components | ||
|
||
A helper library for single-spa and vanilla html / web components. | ||
|
||
[Full documentation](https://single-spa.js.org/docs/ecosystem-html-web-components.html) |
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,42 @@ | ||
{ | ||
"name": "single-spa-html", | ||
"description": "A helper library for mounting and unmount html / web components as single-spa applications and parcels", | ||
"scripts": { | ||
"build": "rimraf lib && babel src --out-dir lib --ignore '**/*.test.js' --source-maps", | ||
"prepublisOnly": "yarn build", | ||
"check-format": "prettier '**/*' --check", | ||
"test": "jest" | ||
}, | ||
"files": [ | ||
"lib", | ||
"typings" | ||
], | ||
"keywords": [ | ||
"single-spa", | ||
"web components", | ||
"polymer" | ||
], | ||
"husky": { | ||
"hooks": { | ||
"pre-commit": "pretty-quick --staged" | ||
} | ||
}, | ||
"version": "1.0.0", | ||
"main": "lib/single-spa-html.js", | ||
"repository": "https://github.com/CanopyTax/single-spa-html.git", | ||
"author": "Joel Denning <joeldenning@gmail.com>", | ||
"license": "MIT", | ||
"devDependencies": { | ||
"@babel/cli": "^7.5.5", | ||
"@babel/core": "^7.5.5", | ||
"@babel/plugin-transform-modules-umd": "^7.2.0", | ||
"@babel/preset-env": "^7.5.5", | ||
"@types/jest": "^24.0.15", | ||
"babel-jest": "^24.8.0", | ||
"husky": "^3.0.1", | ||
"jest": "^24.8.0", | ||
"prettier": "^1.18.2", | ||
"pretty-quick": "^1.11.1", | ||
"rimraf": "^2.6.3" | ||
} | ||
} |
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,92 @@ | ||
const defaultOpts = { | ||
template: "", | ||
domElementGetter: null | ||
}; | ||
|
||
export default function singleSpaHtml(opts) { | ||
if (!opts) { | ||
throw Error(`single-spa-html must be called with an opts object`); | ||
} | ||
|
||
opts = { ...defaultOpts, ...opts }; | ||
|
||
if (typeof opts.template !== "string" || opts.template.trim().length === 0) { | ||
throw Error( | ||
`single-spa-html must be passed a 'template' opt that is a non empty string` | ||
); | ||
} | ||
|
||
if (opts.domElementGetter && typeof opts.domElementGetter !== "function") { | ||
throw Error( | ||
`single-spa-html was given 'opts.domElementGetter', but it isn't a function` | ||
); | ||
} | ||
|
||
return { | ||
bootstrap: bootstrap.bind(null, opts), | ||
mount: mount.bind(null, opts), | ||
unmount: unmount.bind(null, opts) | ||
}; | ||
} | ||
|
||
function bootstrap(opts, props) { | ||
return Promise.resolve(); | ||
} | ||
|
||
function mount(opts, props) { | ||
return Promise.resolve().then(() => { | ||
const domElementGetter = chooseDomElementGetter(opts, props); | ||
const domEl = domElementGetter(); | ||
if (!domEl) { | ||
throw Error( | ||
`single-spa-html: domElementGetter did not return a valid dom element` | ||
); | ||
} | ||
domEl.innerHTML = opts.template; | ||
}); | ||
} | ||
|
||
function unmount(opts, props) { | ||
return Promise.resolve().then(() => { | ||
const domElementGetter = chooseDomElementGetter(opts, props); | ||
const domEl = domElementGetter(); | ||
if (!domEl) { | ||
throw Error( | ||
`single-spa-html: domElementGetter did not return a valid dom element` | ||
); | ||
} | ||
domEl.innerHTML = ""; | ||
}); | ||
} | ||
|
||
function chooseDomElementGetter(opts, props) { | ||
if (props.domElement) { | ||
return () => props.domElement; | ||
} else if (props.domElementGetter) { | ||
return props.domElementGetter; | ||
} else if (opts.domElementGetter) { | ||
return opts.domElementGetter; | ||
} else { | ||
return defaultDomElementGetter(props); | ||
} | ||
} | ||
|
||
function defaultDomElementGetter(props) { | ||
const htmlId = `single-spa-application:${props.appName || props.name}`; | ||
if (!htmlId) { | ||
throw Error( | ||
`single-spa-html was not given an application name as a prop, so it can't make a unique dom element container for the ht l application` | ||
); | ||
} | ||
|
||
return function defaultDomEl() { | ||
let domElement = document.getElementById(htmlId); | ||
if (!domElement) { | ||
domElement = document.createElement("div"); | ||
domElement.id = htmlId; | ||
document.body.appendChild(domElement); | ||
} | ||
|
||
return domElement; | ||
}; | ||
} |
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,68 @@ | ||
import singleSpaHtml from "./single-spa-html"; | ||
|
||
describe("single-spa-html", () => { | ||
const domElementGetter = () => document.getElementById("test-div"); | ||
let props; | ||
|
||
beforeEach(() => { | ||
const div = document.createElement("div"); | ||
div.id = "test-div"; | ||
document.body.appendChild(div); | ||
|
||
props = { name: "test" }; | ||
}); | ||
|
||
afterEach(() => { | ||
document.getElementById("test-div").remove(); | ||
}); | ||
|
||
it("adds html to a provided dom element", () => { | ||
const lifecycles = singleSpaHtml({ | ||
template: "<some-web-component></some-web-component>", | ||
domElementGetter | ||
}); | ||
|
||
const domEl = domElementGetter(); | ||
expect(domEl.innerHTML.trim()).toBe(""); | ||
return lifecycles | ||
.bootstrap(props) | ||
.then(() => lifecycles.mount(props)) | ||
.then(() => { | ||
expect(domEl.innerHTML.trim()).toBe( | ||
"<some-web-component></some-web-component>" | ||
); | ||
return lifecycles.unmount(props); | ||
}) | ||
.then(() => { | ||
expect(domEl.innerHTML.trim()).toBe(""); | ||
return lifecycles.mount(props); | ||
}) | ||
.then(() => { | ||
expect(domEl.innerHTML.trim()).toBe( | ||
"<some-web-component></some-web-component>" | ||
); | ||
}); | ||
}); | ||
|
||
it(`throws if you don't provide a template`, () => { | ||
expect(() => { | ||
singleSpaHtml({}); | ||
}).toThrow(); | ||
}); | ||
|
||
it(`throws if you provide a non-string template`, () => { | ||
expect(() => { | ||
singleSpaHtml({ | ||
template: 123 | ||
}); | ||
}).toThrow(); | ||
}); | ||
|
||
it(`throws if you provide a domElementGetter that is not a function`, () => { | ||
expect(() => { | ||
singleSpaHtml({ | ||
template: 123 | ||
}); | ||
}).toThrow(); | ||
}); | ||
}); |
Oops, something went wrong.