@ecomfe/san-devhook
Advanced tools
Comparing version 0.0.4 to 0.0.5
{ | ||
"name": "@ecomfe/san-devhook", | ||
"version": "0.0.4", | ||
"version": "0.0.5", | ||
"description": "Hook for san-devtool.", | ||
@@ -32,3 +32,2 @@ "keywords": [ | ||
"babel-preset-stage-1": "^6.22.0", | ||
"body-parser": "^1.16.0", | ||
"chrome-killer": "^2.2.1", | ||
@@ -41,6 +40,4 @@ "chrome-launcher": "^0.8.0", | ||
"extract-text-webpack-plugin": "^1.0.1", | ||
"file-loader": "^0.9.0", | ||
"graceful-copy": "1.1.0", | ||
"html-webpack-plugin": "^2.26.0", | ||
"san": "^3.5.5", | ||
"san": "3.1.0", | ||
"san-store": "^1.1.0", | ||
@@ -51,3 +48,3 @@ "webpack": "^2.7.0", | ||
}, | ||
"main": "dist/invasion.js", | ||
"main": "dist/san_devhook.js", | ||
"repository": { | ||
@@ -54,0 +51,0 @@ "type": "git", |
@@ -11,3 +11,3 @@ /** | ||
import {isSanComponent, getXPath} from './utils'; | ||
import {__3_INFO__} from './constants'; | ||
import {__3_INFO__, INVALID, COMP_CONSTRUCTOR_NAME, SUB_KEY} from './constants'; | ||
@@ -111,2 +111,61 @@ | ||
/** | ||
* Get component's DOM index of the parent referring to DOM tree. | ||
* | ||
* @param {Object} component Component instance | ||
* @return {number} | ||
*/ | ||
export function getDOMIndexUnderParent(component) { | ||
if (!component) { | ||
return INVALID; | ||
} | ||
let childrenArray = []; | ||
const parent = component.parentComponent; | ||
if (!parent || (!parent.children && !parent.childs)) { | ||
return INVALID; | ||
} | ||
function flattenChildren(children) { | ||
if (!children || !Array.isArray(children)) { | ||
return; | ||
} | ||
for (let i = 0; i < children.length; i++) { | ||
if (children[i].constructor.name === COMP_CONSTRUCTOR_NAME) { | ||
childrenArray.push(children[i]); | ||
} | ||
else { | ||
flattenChildren(children[i].children || children[i].childs); | ||
} | ||
} | ||
} | ||
flattenChildren(parent.children || parent.childs); | ||
return childrenArray.indexOf(component); | ||
} | ||
/** | ||
* Get component's ancestor DOM index list. | ||
* | ||
* @param {Object} component Component instance | ||
* @return {Array} | ||
*/ | ||
export function getAncestorDOMIndexList(component) { | ||
let list = []; | ||
let comp = component; | ||
while (comp) { | ||
let index = getDOMIndexUnderParent(comp); | ||
if (index === INVALID) { | ||
break; | ||
} | ||
list.unshift(index); | ||
comp = comp.parentComponent; | ||
} | ||
list.unshift(INVALID); | ||
return list; | ||
} | ||
export function getComponentTreeItemData(component) { | ||
@@ -128,4 +187,147 @@ const name = getComponentName(component); | ||
extras: [getComponentRouteExtraData(component)], | ||
idPath: component.idPath | ||
idPath: component.idPath, | ||
ancestorDOMIndexList: getAncestorDOMIndexList(component), | ||
domIndex: getDOMIndexUnderParent(component), | ||
parentDOMIndex: getDOMIndexUnderParent(component.parentComponent) | ||
}; | ||
} | ||
export function getAncestorComponent(component) { | ||
let c = component; | ||
let ancestor = [c]; | ||
while (c) { | ||
c = c.parentComponent; | ||
if (c) { | ||
ancestor.unshift(c); | ||
} | ||
} | ||
return ancestor; | ||
} | ||
export default class CNode { | ||
constructor(component, {subKey = SUB_KEY, fake = {}} = {}) { | ||
this._subKey = subKey; | ||
if (!isSanComponent(component)) { | ||
this.init(fake); | ||
return; | ||
} | ||
if (!component.id) { | ||
console.warn('Component is not initialized.') | ||
return; | ||
} | ||
this._component = component; | ||
this.init(); | ||
// Avoid circular structure. | ||
delete this._component; | ||
} | ||
init(fake) { | ||
if (typeof fake === 'object') { | ||
for (let k in fake) { | ||
if (typeof fake[k] !== 'function') { | ||
this[k] = fake[k]; | ||
} | ||
} | ||
return; | ||
} | ||
this.id = this._component.id; | ||
this.name = this._getName(); | ||
this.data = this._getData(); | ||
this.ancestorPath = this._getAncestorPath(); | ||
this.ancestorDOMIndexList = this._getAncestorDOMIndexList(); | ||
this.history = this._getHistoryInfo(); | ||
this.route = this._getRouteInfo(); | ||
} | ||
append(node) { | ||
if (IsCNode(node)) { | ||
this.createSubKeyIfNeeded(); | ||
Append(this.getSubKey(), node); | ||
} | ||
} | ||
update(node, index) { | ||
if (IsCNode(node)) { | ||
this.createSubKeyIfNeeded(); | ||
Update(this.getSubKey(), node, index); | ||
} | ||
} | ||
insertBefore(node, before) { | ||
if (IsCNode(node)) { | ||
this.createSubKeyIfNeeded(); | ||
InsertBefore(this.getSubKey(), node, before); | ||
} | ||
} | ||
removeAt(at) { | ||
RemoveAt(this.getSubKey(), at); | ||
} | ||
createSubKeyIfNeeded = () => { | ||
if (!Array.isArray(this.getSubKey())) { | ||
this.setSubKey([]); | ||
} | ||
}; | ||
deleteSubKey = () => { | ||
if (Array.isArray(this.getSubKey())) { | ||
delete this[this._subKey]; | ||
} | ||
} | ||
getSubKey = () => this[this._subKey]; | ||
setSubKey = children => (this[this._subKey] = children); | ||
_getName = () => (this._component.subTag || this._component.constructor.name); | ||
_getData = () => (this._component.data && (this._component.data.raw || this._component.data.data)); | ||
_getAncestorPath = () => getAncestorComponent(this._component).map(v => v.id); | ||
_getAncestorDOMIndexList = () => getAncestorComponent(this._component).map(v => getDOMIndexUnderParent(v)); | ||
_getHistoryInfo = () => ({ | ||
id: this.id, | ||
idPath: this.ancestorPath, | ||
componentName: this.name, | ||
timestamp: Date.now(), | ||
compData: 1 | ||
}); | ||
_getRouteInfo = () => ({ | ||
id: this.id, | ||
timestamp: Date.now(), | ||
routeData: this.data && this.data['route'] | ||
}); | ||
static IsCNode = node => (node instanceof CNode); | ||
static Append = (root, node) => { | ||
if (Array.isArray(root)) { | ||
root.push(node); | ||
} | ||
} | ||
static Update = (root, node, index) => { | ||
if (Array.isArray(root)) { | ||
root[index] = node; | ||
} | ||
} | ||
static InsertBefore = (root, node, before) => { | ||
if (Array.isArray(root)) { | ||
root.splice(before, 0, node); | ||
} | ||
} | ||
static RemoveAt = (root, at) => { | ||
if (Array.isArray(root)) { | ||
root.splice(at, 1); | ||
} | ||
} | ||
} |
@@ -59,1 +59,5 @@ /** | ||
export const __3_INFO__ = '__SAN_INFO__'; | ||
export const INVALID = -1; | ||
export const COMP_CONSTRUCTOR_NAME = 'ComponentClass'; |
@@ -39,3 +39,4 @@ /** | ||
selectedComponentId: null, | ||
treeData: [] | ||
treeData: [], | ||
cnode: [] | ||
}, | ||
@@ -42,0 +43,0 @@ // 记录 San devtool 事件触发列表。 |
@@ -9,3 +9,3 @@ /** | ||
import {SAN_EVENTS, STORE_EVENTS, COMP_ROUTE, | ||
import {SAN_EVENTS, STORE_EVENTS, COMP_ROUTE, COMP_DETACHED, COMP_ATTACHED, COMP_UPDATED, | ||
__3_COMP__, __3_PATH__, __3_DATA__, __3_TREE_INDEX__, __3_INFO__} | ||
@@ -15,3 +15,3 @@ from './constants'; | ||
import {getDevtoolNS} from './utils'; | ||
import {serialize, getComponentPath, getComponentName, getHistoryInfo, | ||
import CNode, {serialize, getComponentPath, getComponentName, getHistoryInfo, | ||
getRouteInfo, getComponentTreeItemData} from './components'; | ||
@@ -269,3 +269,3 @@ import componentTreeBuilder from './tree_builder'; | ||
const builder = new componentTreeBuilder({root: sanDevtool.data.treeData}); | ||
const builder = new componentTreeBuilder({root: sanDevtool.data.cnode}); | ||
@@ -307,3 +307,8 @@ // 8 种事件。 | ||
buildHistory(component, sanDevtool, message); | ||
builder.emit(message, data); | ||
//if (message === COMP_ATTACHED || message === COMP_UPDATED || message === COMP_DETACHED) { | ||
const cnode = new CNode(component); | ||
builder.emit(message, cnode/*data*/); | ||
//} | ||
const indexList = builder.getIndexListByPath(idPath); | ||
@@ -310,0 +315,0 @@ const compData = component.data.raw || component.data.data; |
@@ -10,10 +10,6 @@ /** | ||
import {COMP_ATTACHED, COMP_DETACHED, COMP_UPDATED} from './constants'; | ||
import {getConfig} from './config'; | ||
import {COMP_ATTACHED, COMP_DETACHED, COMP_UPDATED, INVALID} from './constants'; | ||
import CNode from './components'; | ||
const INVALID = -1; | ||
const EMPTY_ARRAY = []; | ||
export default class { | ||
@@ -27,3 +23,2 @@ constructor({ | ||
this._root = root; | ||
this.SUB_KEY = getConfig().subKey; | ||
} | ||
@@ -35,93 +30,118 @@ | ||
emit(event, data) { | ||
if (!data || typeof data !== 'object' || !data.id) { | ||
emit(event, node) { | ||
if (!node || !(CNode.IsCNode(node)) || !node.id) { | ||
return; | ||
} | ||
let root = this._root; | ||
switch (event) { | ||
case COMP_ATTACHED: | ||
case COMP_UPDATED: { | ||
this.appendOrUpdateNode(data); | ||
this.appendNode(node); | ||
break; | ||
} | ||
case COMP_DETACHED: { | ||
this.removeNode(data); | ||
this.removeNode(node); | ||
break; | ||
} | ||
default: | ||
break; | ||
} | ||
} | ||
appendOrUpdateNode(data) { | ||
let path = data.idPath; | ||
appendNode(node) { | ||
let path = node.ancestorPath; | ||
if (!this._isValidPath(path)) { | ||
return; | ||
} | ||
let node = this._root; | ||
let root = this._root; | ||
path.forEach((id, i, p) => { | ||
let index = this.getIdListByNode(node).indexOf(id); | ||
let index = this.getIdListByNode(root).indexOf(id); | ||
let next; | ||
if (index < 0) { | ||
let newData = {...data, id}; | ||
// Create a fake CNode for unattached parent component. | ||
let newNode = new CNode(null, {fake: {...node, id}}); | ||
if (i !== p.length - 1) { | ||
newData[this.SUB_KEY] = []; | ||
newNode.createSubKeyIfNeeded(); | ||
} | ||
node && node.push(newData); | ||
if (root) { | ||
let list = node.ancestorDOMIndexList; | ||
let domIndex = i === p.length - 1 ? list[list.length - 1] : list[i]; | ||
if (domIndex > INVALID) { | ||
CNode.InsertBefore(root, newNode, domIndex); | ||
} | ||
else { | ||
CNode.Append(root, newNode); | ||
} | ||
if (i < p.length - 1) { | ||
next = newNode; | ||
root = newNode.getSubKey(); | ||
return; | ||
} | ||
} | ||
} | ||
else { | ||
if (node[index] && node[index].id === data.id) { | ||
node[index] = { | ||
...node[index], | ||
...data | ||
} | ||
if (root[index] && root[index].id === node.id) { | ||
node.setSubKey(root[index].getSubKey()); | ||
CNode.Update(root, node, index); | ||
} | ||
} | ||
let next = index < 0 ? node[node.length - 1] : node[index]; | ||
if (i < p.length - 1 && !next[this.SUB_KEY]) { | ||
next[this.SUB_KEY] = []; | ||
if (!next) { | ||
next = root[index]; | ||
} | ||
node = next[this.SUB_KEY]; | ||
if (!CNode.IsCNode(next)) { | ||
return; | ||
} | ||
if (i < p.length - 1 && !next.getSubKey()) { | ||
next.createSubKeyIfNeeded(); | ||
} | ||
root = next.getSubKey(); | ||
}); | ||
} | ||
removeNode(data) { | ||
let path = data.idPath; | ||
removeNode(node) { | ||
let path = node.ancestorPath; | ||
if (!this._isValidPath(path)) { | ||
return; | ||
} | ||
let node = this._root; | ||
let root = this._root; | ||
let prev; | ||
path.forEach((id, i, p) => { | ||
let index = this.getIdListByNode(node).indexOf(id); | ||
let index = this.getIdListByNode(root).indexOf(id); | ||
if (index < 0) { | ||
return; | ||
} | ||
if (i === p.length - 1) { | ||
node.splice(index, 1); | ||
if (node.length === 0 && prev) { | ||
delete prev[this.SUB_KEY]; | ||
CNode.RemoveAt(root, index); | ||
if (root.length === 0 && prev) { | ||
prev.deleteSubKey(); | ||
} | ||
} | ||
if (!node) { | ||
if (!root) { | ||
return; | ||
} | ||
if (node[index]) { | ||
prev = node[index]; | ||
node = node[index][this.SUB_KEY] ? node[index][this.SUB_KEY] : null; | ||
prev = root[index]; | ||
if (!CNode.IsCNode(prev)) { | ||
return; | ||
} | ||
root = prev.getSubKey() ? prev.getSubKey() : null; | ||
}); | ||
} | ||
getIdList(path) { | ||
if (_isValidPath(path)) { | ||
this.getNode | ||
} | ||
else { | ||
return this._data.filter(x => x.id).map(x => x.id); | ||
} | ||
} | ||
getIdListByNode(node) { | ||
if (!node || !Array.isArray(node)) { | ||
return EMPTY_ARRAY; | ||
return []; | ||
} | ||
@@ -133,7 +153,9 @@ return node.filter(x => x.id).map(x => x.id); | ||
if (!path || !Array.isArray(path)) { | ||
return EMPTY_ARRAY; | ||
return []; | ||
} | ||
let node = this._root; | ||
let a = path.map((id, i, p) => { | ||
let index = this.getIndexByNode(node, id); | ||
let root = this._root; | ||
return path.map((id, i, p) => { | ||
let index = this.getIndexByNode(root, id); | ||
if (index < 0 && i !== p.length - 1) { | ||
@@ -143,7 +165,6 @@ return; | ||
if (i < p.length - 1) { | ||
node = node[index][this.SUB_KEY]; | ||
root = root[index].getSubKey(); | ||
} | ||
return index; | ||
}); | ||
return a.filter(v => v); | ||
}).filter(v => v); | ||
} | ||
@@ -150,0 +171,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
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 2 instances in 1 package
23
0
2
100422
21
1331