@sidiousvic/phantom
Advanced tools
Comparing version 1.7.7 to 2.0.0
@@ -9,2 +9,14 @@ # Changelog | ||
## [v2.0.0] — 2020.07.19 | ||
## Features | ||
- [x] Implemented [phantomStore](https://github.com/sidiousvic/phantom#manage-state), annihilated Redux from Phantom | ||
### APIs | ||
- [x] `createStore (from redux)` > `createPhantomStore (from phantom)` | ||
- [x] `sanitizeHTML` > `phantomExorciser` | ||
- [x] `phantom.launch` > `phantom.appear` | ||
## [v1.7.7] — 2020.07.13 | ||
@@ -14,3 +26,3 @@ | ||
- Replaced Webpack for build, building with Typescript. | ||
- [x] Replaced Webpack for build, building with Typescript. | ||
@@ -21,5 +33,5 @@ ## [v1.6.0] — 2020.07.11 | ||
- Danger JS for automated PR messaging. | ||
- Kermitoid is implemented, and will respond to certain PR events. 🐸 | ||
- Added `CHANGELOG.md`. | ||
- [x] Danger JS for automated PR messaging. | ||
- [x] Kermitoid is implemented, and will respond to certain PR events. 🐸 | ||
- [x] Added `CHANGELOG.md`. | ||
@@ -30,4 +42,4 @@ ## [v1.4.94] — 2020.07.08 | ||
- Implemented `throw DOMException` for dangerous nodes in `phantom.ts` and `sanitizer.ts` | ||
- Added test coverage for `<iframe>` elements | ||
- [x] Implemented `throw DOMException` for dangerous nodes in `phantom.ts` and `sanitizer.ts` | ||
- [x] Added test coverage for `<iframe>` elements | ||
@@ -38,11 +50,12 @@ ## [v1.4.7] — 2020.07.07 | ||
- `sanitizer/` dir | ||
- `sanitizer/sanitizer.ts` | ||
- `sanitizer/allowlist.ts` allowlists for attrs, tags and css | ||
- [x] `sanitizer/` dir | ||
- [x] `sanitizer/sanitizer.ts` | ||
- [x] `sanitizer/allowlist.ts` allowlists for attrs, tags and css | ||
### Changed | ||
- In `phantom.ts` instances of `innerHTML` injection were reinforced with the sanitizer. HMTL is now sanitized before rendering to DOM. | ||
- [x] In `phantom.ts` instances of `innerHTML` injection were reinforced with the sanitizer. HMTL is now sanitized before rendering to DOM. | ||
[unreleased]: https://github.com/sidiousvic/phantom/compare/v1.6.0...HEAD | ||
[v2.0.0]: https://github.com/sidiousvic/phantom/compare/v1.7.7...v2.0.0 | ||
[v1.7.7]: https://github.com/sidiousvic/phantom/compare/v1.6.0...v1.7.7 | ||
@@ -49,0 +62,0 @@ [v1.6.0]: https://github.com/sidiousvic/phantom/compare/v1.4.94...v1.6.0 |
@@ -1,6 +0,11 @@ | ||
declare function PHANTOM(reduxStore: any, XDOM: XDOMFunction): { | ||
declare function PHANTOM(phantomStore: any, XDOM: XDOMFunction): { | ||
fire: any; | ||
data: any; | ||
launch: () => HTMLElement; | ||
appear: () => HTMLElement; | ||
}; | ||
export declare function createPhantomStore(reducer: PhantomReducer): { | ||
data: () => any; | ||
fire: (action: PhantomAction) => void; | ||
subscribe: (subscription: Subscription) => void; | ||
}; | ||
export default PHANTOM; |
@@ -6,5 +6,6 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const sanitizer_1 = __importDefault(require("./sanitizer/sanitizer")); | ||
function PHANTOM(reduxStore, XDOM) { | ||
let pseudoDOM = { | ||
exports.createPhantomStore = void 0; | ||
const exorciser_1 = __importDefault(require("./exorciser/exorciser")); | ||
function PHANTOM(phantomStore, XDOM) { | ||
let phantomDOM = { | ||
test: { | ||
@@ -26,3 +27,3 @@ tagName: "div", | ||
try { | ||
const DOM = renderPseudoElement(); | ||
const DOM = renderPhantomElement(); | ||
swapElement(DOM, document.querySelector("#PHANTOM")); | ||
@@ -39,11 +40,11 @@ return DOM; | ||
${XDOM()} | ||
</div> | ||
</div> | ||
`; | ||
} | ||
function renderPseudoElement(pseudoElement = transmuteHTMLtoPseudoElement(coalescePhantomDOM())) { | ||
const { tagName, attributes, innerHTML, children } = pseudoElement; | ||
let $children = []; | ||
function renderPhantomElement(phantomElement = transmuteHTMLtoPhantomElement(coalescePhantomDOM())) { | ||
const { tagName, attributes, innerHTML, children } = phantomElement; | ||
let phantomElementChildren = []; | ||
if (children && children.length) { | ||
$children = Array.prototype.map.call(children, (child) => { | ||
renderPseudoElement(child); | ||
phantomElementChildren = Array.prototype.map.call(children, (child) => { | ||
renderPhantomElement(child); | ||
}); | ||
@@ -54,11 +55,11 @@ } | ||
DOM diffing ahead. ↓↓↓ | ||
We look at the current pseudoDOM, and for every pseudoDOMNode, if | ||
* the id of the pseudoDOMNode and current pseudoElement match, and | ||
We look at the current phantomDOM, and for every phantomDOMNode, if | ||
* the id of the phantomDOMNode and current phantomElement match, and | ||
* the nodes' dataset (data-phantom) are different (their data has changed), | ||
we swap the nodes. | ||
*/ | ||
Object.values(pseudoDOM).map((pseudoDOMNode) => { | ||
if (pseudoDOMNode.attributes.id === pseudoElement.attributes.id && | ||
JSON.stringify(pseudoDOMNode.dataset) !== | ||
JSON.stringify(pseudoElement.dataset)) { | ||
Object.values(phantomDOM).map((phantomDOMNode) => { | ||
if (phantomDOMNode.attributes.id === phantomElement.attributes.id && | ||
JSON.stringify(phantomDOMNode.dataset) !== | ||
JSON.stringify(phantomElement.dataset)) { | ||
let newNode = document.createElement(tagName); | ||
@@ -76,3 +77,3 @@ for (const [k, v] of Object.entries(attributes)) { | ||
try { | ||
newNode.innerHTML = sanitizer_1.default(innerHTML); | ||
newNode.innerHTML = exorciser_1.default(innerHTML); | ||
let targetNode = document.getElementById(attributes.id); | ||
@@ -87,3 +88,3 @@ swapElement(newNode, targetNode); | ||
}); | ||
pseudoDOM[attributes.id] = pseudoElement; | ||
phantomDOM[attributes.id] = phantomElement; | ||
DOMElement = document.createElement(tagName); | ||
@@ -101,3 +102,3 @@ for (const [k, v] of Object.entries(attributes)) { | ||
try { | ||
DOMElement.innerHTML = sanitizer_1.default(innerHTML); | ||
DOMElement.innerHTML = exorciser_1.default(innerHTML); | ||
return DOMElement; | ||
@@ -109,3 +110,3 @@ } | ||
} | ||
function transmuteHTMLtoPseudoElement(html) { | ||
function transmuteHTMLtoPhantomElement(html) { | ||
if (typeof html !== "string") | ||
@@ -118,6 +119,6 @@ html = html.outerHTML; | ||
const { tagName, children, id, dataset, classList, innerHTML, outerHTML, } = $el; | ||
let $children = []; | ||
let phantomElementChildren = []; | ||
if (children && children.length) { | ||
$children = Array.prototype.map.call(children, (child) => { | ||
return transmuteHTMLtoPseudoElement(child); | ||
phantomElementChildren = Array.prototype.map.call(children, (child) => { | ||
return transmuteHTMLtoPhantomElement(child); | ||
}); | ||
@@ -132,3 +133,3 @@ } | ||
dataset, | ||
children: $children, | ||
children: phantomElementChildren, | ||
innerHTML, | ||
@@ -142,11 +143,26 @@ outerHTML, | ||
} | ||
reduxStore.subscribe(() => { | ||
renderPseudoElement(); | ||
phantomStore.subscribe(() => { | ||
renderPhantomElement(); | ||
}); | ||
return { | ||
fire: reduxStore.dispatch, | ||
data: reduxStore.getState, | ||
launch: launchDOM, | ||
fire: phantomStore.fire, | ||
data: phantomStore.data, | ||
appear: launchDOM, | ||
}; | ||
} | ||
function createPhantomStore(reducer) { | ||
let state = reducer(undefined, {}); | ||
const subscriptions = []; | ||
return { | ||
data: () => state, | ||
fire: (action) => { | ||
state = reducer(state, action); | ||
subscriptions.forEach((subscription) => subscription()); | ||
}, | ||
subscribe: (subscription) => { | ||
subscriptions.push(subscription); | ||
}, | ||
}; | ||
} | ||
exports.createPhantomStore = createPhantomStore; | ||
exports.default = PHANTOM; |
{ | ||
"name": "@sidiousvic/phantom", | ||
"version": "1.7.7", | ||
"description": "A Redux—powered, reactive state DOM renderer", | ||
"version": "2.0.0", | ||
"description": "A state—reactive DOM rendering engine for building UIs. 👻", | ||
"main": "dist/phantom.js", | ||
@@ -23,3 +23,4 @@ "access": "public", | ||
"hooks": { | ||
"pre-commit": "pretty-quick --staged --no-restage" | ||
"pre-commit": "pretty-quick --staged --no-restage", | ||
"pre-push": "npm run test" | ||
} | ||
@@ -40,5 +41,7 @@ }, | ||
"framework", | ||
"redux", | ||
"functional", | ||
"component" | ||
"UI", | ||
"state management", | ||
"components", | ||
"DOM", | ||
"functional" | ||
], | ||
@@ -63,3 +66,2 @@ "dependencies": {}, | ||
"pretty-quick": "^2.0.1", | ||
"redux": "^4.0.5", | ||
"serialize-javascript": "^4.0.0", | ||
@@ -66,0 +68,0 @@ "style-loader": "^1.2.1", |
@@ -5,3 +5,3 @@ # **Phantom** | ||
### A Redux powered, state—reactive DOM rendering engine. 👻 | ||
### A state—reactive DOM rendering engine for building UIs. 👻 | ||
@@ -24,3 +24,3 @@ ### `npm i @sidiousvic/phantom` | ||
#### You update data via Redux, and Phantom swaps DOM nodes for you. | ||
#### You update data via actions, and Phantom swaps DOM nodes for you. | ||
@@ -43,8 +43,6 @@ <br> | ||
### 1. Create a Redux Store | ||
### 1. Create a Phantom store | ||
Phantom will couple with **Redux** to subscribe DOM rendering to state updates. | ||
Phantom will integrate with a Redux—like store to subscribe DOM rendering to state updates. Use `createPhantomStore` to produce your store. | ||
#### Install [Redux](https://redux.js.org/introduction/getting-started) `npm i redux` | ||
<details> | ||
@@ -54,3 +52,3 @@ <summary><b>Show code ↯</b></summary> | ||
```js | ||
import { createStore } from "redux"; | ||
import { createPhantomStore } from "@sidiousvic/phantom"; | ||
@@ -71,5 +69,5 @@ const data = { | ||
const store = createStore(reducer); | ||
const store = createPhantomStore(reducer); | ||
export default reduxStore; | ||
export default phantomStore; | ||
``` | ||
@@ -98,5 +96,5 @@ | ||
### 3. Initialize and `phantom.launch()` | ||
### 3. Initialize Phantom and `appear()` | ||
Start the Phantom engine with the `reduxStore` and a `phantomElement`. | ||
Start the Phantom engine with the `phantomStore` and a `phantomElement`. | ||
@@ -108,16 +106,20 @@ <details> | ||
import phantom from "@sidiousvic/phantom"; | ||
import reduxStore from "./reduxStore.js"; | ||
import phantomStore from "./phantomStore.js"; | ||
import Pizza from "./ui/Pizza.js"; | ||
export const { fire, data, launch } = phantom(reduxStore, phantomComponent); | ||
const { fire, data, appear } = phantom(phantomStore, phantomComponent); | ||
launch(); // initial render | ||
appear(); // 3, 2, 1... 🚀 initial render! | ||
``` | ||
Phantom will expose three key methods: `fire`, `data`, and `launch`. | ||
Phantom will then expose the methods `fire`, `data` and `appear`. | ||
`fire` and `data` are only syntactic pointers to the `reduxStore`'s `dispatch` and `getState` methods respectively. **You are welcome to avoid them and call the store directly for action dispatching and state getting.** | ||
`fire` and `data` are pointers to the phantomStore. You're welcome to call them from the store directly. | ||
`launch` will perform the initial DOM render on call. | ||
`fire` takes an action and _fires_ it through the store. | ||
`data` returns the current in—store _data_. | ||
`appear` will perform the initial DOM render on call, your UI's first _apparition_. 👻 | ||
</details> | ||
@@ -129,3 +131,3 @@ | ||
### Use `data()` to read state from the Redux store. | ||
### Use `data` to read state from the Phantom store. | ||
@@ -157,4 +159,2 @@ ```js | ||
<br> | ||
| ⚠️ Specify an id attribute for _all_ elements. | | ||
@@ -164,3 +164,3 @@ | :---------------------------------------------------- | | ||
### Use `fire()` to fire an action and trigger a state update + re—render. | ||
### Use `fire` to dispatch an action and trigger a state update + re—render. | ||
@@ -172,3 +172,3 @@ ```js | ||
if (e.target.id === "slices-h1") { | ||
fire({ type: "EAT_PIZZA" }); // fire an action to the store | ||
fire({ type: "EAT_PIZZA" }); | ||
} | ||
@@ -201,3 +201,3 @@ } | ||
The Phantom engine integrates with your Redux store and subscribes to state updates. It swaps nodes when their data changes. | ||
The Phantom engine integrates with a store and subscribes to state updates. It swaps nodes when their data changes. | ||
@@ -251,12 +251,2 @@ #### 👩🏾🏭 Closer to the JS _metal_ | ||
## Instructions | ||
0. **Read** the [Code of Conduct](./CODEOFCONDUCT.md) | ||
1. **Fork** the repo on GitHub | ||
2. **Clone** the project to your machine | ||
3. **Install** dependencies with `npm i` | ||
4. **Commit** updates to your own branch | ||
5. **Push** your work to your fork | ||
6. **Pull request** for your changes to be reviewed | ||
## Scripts | ||
@@ -263,0 +253,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
30294
24
556
269