mirror of
https://github.com/reduxjs/redux-devtools.git
synced 2024-11-21 17:16:42 +03:00
Merge map2tree package (#426)
* Merge map2tree from romseguy/map2tree * Dependences and npm package config * Add credits
This commit is contained in:
parent
d2084892b4
commit
c09c9a4e13
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -2,5 +2,6 @@ node_modules
|
|||
*.log
|
||||
.DS_Store
|
||||
lib
|
||||
dist
|
||||
coverage
|
||||
.idea
|
||||
|
|
7736
packages/d3tooltip/dist/d3tooltip.js
vendored
7736
packages/d3tooltip/dist/d3tooltip.js
vendored
File diff suppressed because it is too large
Load Diff
2
packages/d3tooltip/dist/d3tooltip.min.js
vendored
2
packages/d3tooltip/dist/d3tooltip.min.js
vendored
File diff suppressed because one or more lines are too long
3
packages/map2tree/.babelrc
Executable file
3
packages/map2tree/.babelrc
Executable file
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"presets": ["es2015-loose", "stage-0"]
|
||||
}
|
4
packages/map2tree/.eslintignore
Executable file
4
packages/map2tree/.eslintignore
Executable file
|
@ -0,0 +1,4 @@
|
|||
lib
|
||||
**/node_modules
|
||||
**/webpack.config.js
|
||||
examples/**/server.js
|
10
packages/map2tree/.eslintrc
Executable file
10
packages/map2tree/.eslintrc
Executable file
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"extends": "eslint:recommended",
|
||||
"env": {
|
||||
"browser": true,
|
||||
"node": true,
|
||||
"es6": true
|
||||
},
|
||||
|
||||
"parser": "babel-eslint"
|
||||
}
|
21
packages/map2tree/LICENSE.md
Executable file
21
packages/map2tree/LICENSE.md
Executable file
|
@ -0,0 +1,21 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Romain Séguy
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
88
packages/map2tree/README.md
Executable file
88
packages/map2tree/README.md
Executable file
|
@ -0,0 +1,88 @@
|
|||
A pure function to convert a map into a tree structure. Created by [@romseguy](https://github.com/romseguy) and merged from [`romseguy/map2tree`](https://github.com/romseguy/map2tree).
|
||||
|
||||
The following opinions must be taken into account since the primary use case of this library is [redux-devtools-chart-monitor](https://github.com/romseguy/redux-devtools-chart-monitor):
|
||||
|
||||
- Objects and arrays deeply nested within collections are not converted into a tree structure. See `someNestedObject` and `someNestedArray` in the [output](https://github.com/romseguy/map2tree#output) below, or the [corresponding test](https://github.com/romseguy/map2tree/blob/master/test/map2tree.js#L140).
|
||||
- Provides support for [Immutable.js](https://github.com/facebook/immutable-js) data structures (only List and Map though).
|
||||
|
||||
|
||||
# Usage
|
||||
|
||||
|
||||
```javascript
|
||||
map2tree(someMap, options = {
|
||||
key: 'state', // the name you want for as the root node of the output tree
|
||||
pushMethod: 'push' // use 'unshift' to change the order children nodes are added
|
||||
})
|
||||
```
|
||||
|
||||
# Input
|
||||
|
||||
```javascript
|
||||
const someMap = {
|
||||
someReducer: {
|
||||
todos: [
|
||||
{title: 'map', someNestedObject: {foo: 'bar'}},
|
||||
{title: 'to', someNestedArray: ['foo', 'bar']},
|
||||
{title: 'tree'},
|
||||
{title: 'map2tree'}
|
||||
],
|
||||
completedCount: 1
|
||||
},
|
||||
otherReducer: {
|
||||
foo: 0,
|
||||
bar:{key: 'value'}
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
# Output
|
||||
|
||||
```javascript
|
||||
{
|
||||
name: `${options.key}`,
|
||||
children: [
|
||||
{
|
||||
name: 'someReducer',
|
||||
children: [
|
||||
{
|
||||
name: 'todos',
|
||||
children: [
|
||||
{
|
||||
name: 'todo[0]',
|
||||
object: {
|
||||
title: 'map',
|
||||
someNestedObject: {foo: 'bar'}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'todo[1]',
|
||||
object: {
|
||||
title: 'to',
|
||||
someNestedArray: ['foo', 'bar']
|
||||
}
|
||||
},
|
||||
// ...
|
||||
]
|
||||
},
|
||||
// ...
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'otherReducer',
|
||||
children: [
|
||||
{
|
||||
name: 'foo',
|
||||
value: 0
|
||||
},
|
||||
{
|
||||
name: 'bar',
|
||||
object: {
|
||||
key: 'value'
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
66
packages/map2tree/package.json
Executable file
66
packages/map2tree/package.json
Executable file
|
@ -0,0 +1,66 @@
|
|||
{
|
||||
"name": "map2tree",
|
||||
"version": "1.4.0",
|
||||
"description": "Utility for mapping maps to trees",
|
||||
"main": "lib/index.js",
|
||||
"scripts": {
|
||||
"clean": "rimraf lib dist",
|
||||
"build": "babel src --out-dir lib",
|
||||
"build:umd": "webpack src/index.js dist/map2tree.js && NODE_ENV=production webpack src/index.js dist/map2tree.min.js",
|
||||
"lint": "eslint src test",
|
||||
"test": "babel-node test/map2tree.js | tap-diff",
|
||||
"check": "npm run lint && npm run test",
|
||||
"prepare": "npm run build && npm run build:umd",
|
||||
"prepublishOnly": "npm run check && npm run clean && npm run build && npm run build:umd"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/reduxjs/redux-devtools.git"
|
||||
},
|
||||
"keywords": [
|
||||
"map2tree",
|
||||
"map-to-tree",
|
||||
"mapToTree",
|
||||
"map",
|
||||
"tree"
|
||||
],
|
||||
"author": "romseguy",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/reduxjs/redux-devtools/issues"
|
||||
},
|
||||
"homepage": "https://github.com/reduxjs/redux-devtools",
|
||||
"devDependencies": {
|
||||
"babel-cli": "^6.3.15",
|
||||
"babel-core": "^6.1.20",
|
||||
"babel-eslint": "4.1.8",
|
||||
"babel-loader": "^6.2.0",
|
||||
"babel-preset-es2015-loose": "^6.1.3",
|
||||
"babel-preset-react": "^6.3.13",
|
||||
"babel-preset-stage-0": "^6.3.13",
|
||||
"eslint": "1.10.3",
|
||||
"immutable": "3.7.6",
|
||||
"rimraf": "^2.3.4",
|
||||
"tap-diff": "0.1.1",
|
||||
"tap-spec": "4.1.1",
|
||||
"tape": "4.4.0",
|
||||
"webpack": "1.12.13"
|
||||
},
|
||||
"dependencies": {
|
||||
"lodash": "^4.2.1"
|
||||
},
|
||||
"npmName": "map2tree",
|
||||
"files": [
|
||||
"lib",
|
||||
"dist",
|
||||
"src"
|
||||
],
|
||||
"npmFileMap": [
|
||||
{
|
||||
"basePath": "/dist/",
|
||||
"files": [
|
||||
"*.js"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
68
packages/map2tree/src/index.js
Executable file
68
packages/map2tree/src/index.js
Executable file
|
@ -0,0 +1,68 @@
|
|||
import isArray from 'lodash/isArray';
|
||||
import isPlainObject from 'lodash/isPlainObject';
|
||||
import mapValues from 'lodash/mapValues';
|
||||
|
||||
function visit(parent, visitFn, childrenFn) {
|
||||
if (!parent) return;
|
||||
|
||||
visitFn(parent);
|
||||
|
||||
const children = childrenFn(parent);
|
||||
if (children) {
|
||||
const count = children.length;
|
||||
for (let i = 0; i < count; i++) {
|
||||
visit(children[i], visitFn, childrenFn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getNode(tree, key) {
|
||||
let node = null;
|
||||
|
||||
visit(tree, d => {
|
||||
if (d.name === key) {
|
||||
node = d;
|
||||
}
|
||||
}, d => d.children);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
export default function map2tree(root, options = {}, tree = {name: options.key || 'state', children: []}) {
|
||||
if (!isPlainObject(root) && root && !root.toJS) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const { key: rootNodeKey = 'state', pushMethod = 'push' } = options;
|
||||
const currentNode = getNode(tree, rootNodeKey);
|
||||
|
||||
if (currentNode === null) {
|
||||
return {};
|
||||
}
|
||||
|
||||
mapValues(root && root.toJS ? root.toJS() : root, (maybeImmutable, key) => {
|
||||
const value = maybeImmutable && maybeImmutable.toJS ? maybeImmutable.toJS() : maybeImmutable;
|
||||
let newNode = {name: key};
|
||||
|
||||
if (isArray(value)) {
|
||||
newNode.children = [];
|
||||
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
newNode.children[pushMethod]({
|
||||
name: `${key}[${i}]`,
|
||||
[isPlainObject(value[i]) ? 'object' : 'value']: value[i]
|
||||
});
|
||||
}
|
||||
} else if (isPlainObject(value)) {
|
||||
newNode.children = [];
|
||||
} else {
|
||||
newNode.value = value;
|
||||
}
|
||||
|
||||
currentNode.children[pushMethod](newNode);
|
||||
|
||||
map2tree(value, {key, pushMethod}, tree);
|
||||
});
|
||||
|
||||
return tree;
|
||||
}
|
253
packages/map2tree/test/map2tree.js
Executable file
253
packages/map2tree/test/map2tree.js
Executable file
|
@ -0,0 +1,253 @@
|
|||
import test from 'tape';
|
||||
import map2tree from '../src';
|
||||
import immutable from 'immutable';
|
||||
|
||||
test('# rootNodeKey', assert => {
|
||||
const map = {};
|
||||
const options = {key: 'foo'};
|
||||
|
||||
assert.equal(map2tree(map, options).name, 'foo');
|
||||
assert.end();
|
||||
});
|
||||
|
||||
test('# shallow map', nest => {
|
||||
nest.test('## null', assert => {
|
||||
const map = {
|
||||
a: null
|
||||
};
|
||||
|
||||
const expected = {
|
||||
name: 'state',
|
||||
children: [
|
||||
{name: 'a', value: null}
|
||||
]
|
||||
};
|
||||
|
||||
assert.deepEqual(map2tree(map), expected);
|
||||
assert.deepEqual(map2tree(immutable.fromJS(map)), expected, 'immutable');
|
||||
assert.end();
|
||||
});
|
||||
|
||||
nest.test('## value', assert => {
|
||||
const map = {
|
||||
a: 'foo',
|
||||
b: 'bar'
|
||||
};
|
||||
|
||||
const expected = {
|
||||
name: 'state',
|
||||
children: [
|
||||
{name: 'a', value: 'foo'},
|
||||
{name: 'b', value: 'bar'}
|
||||
]
|
||||
};
|
||||
|
||||
assert.deepEqual(map2tree(map), expected);
|
||||
assert.deepEqual(map2tree(immutable.fromJS(map)), expected, 'immutable');
|
||||
assert.end();
|
||||
});
|
||||
|
||||
nest.test('## object', assert => {
|
||||
const map = {
|
||||
a: {aa: 'foo'}
|
||||
};
|
||||
|
||||
const expected = {
|
||||
name: 'state',
|
||||
children: [
|
||||
{name: 'a', children: [{name: 'aa', value: 'foo'}]}
|
||||
]
|
||||
};
|
||||
|
||||
assert.deepEqual(map2tree(map), expected);
|
||||
assert.deepEqual(map2tree(immutable.fromJS(map)), expected, 'immutable');
|
||||
assert.end();
|
||||
});
|
||||
|
||||
nest.test('## immutable Map', assert => {
|
||||
const map = {
|
||||
a: immutable.fromJS({aa: 'foo', ab: 'bar'})
|
||||
};
|
||||
|
||||
const expected = {
|
||||
name: 'state',
|
||||
children: [
|
||||
{name: 'a', children: [{name: 'aa', value: 'foo'}, {name: 'ab', value: 'bar'}]}
|
||||
]
|
||||
};
|
||||
|
||||
assert.deepEqual(map2tree(map), expected);
|
||||
assert.end();
|
||||
})
|
||||
});
|
||||
|
||||
test('# deep map', nest => {
|
||||
nest.test('## null', assert => {
|
||||
const map = {
|
||||
a: {aa: null}
|
||||
};
|
||||
|
||||
const expected = {
|
||||
name: 'state',
|
||||
children: [
|
||||
{
|
||||
name: 'a',
|
||||
children: [
|
||||
{
|
||||
name: 'aa',
|
||||
value: null
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
assert.deepEqual(map2tree(map), expected);
|
||||
assert.deepEqual(map2tree(immutable.fromJS(map)), expected, 'immutable');
|
||||
assert.end();
|
||||
});
|
||||
|
||||
nest.test('## object', assert => {
|
||||
const map = {
|
||||
a: {aa: {aaa: 'foo'}}
|
||||
};
|
||||
|
||||
const expected = {
|
||||
name: 'state',
|
||||
children: [
|
||||
{
|
||||
name: 'a',
|
||||
children: [
|
||||
{
|
||||
name: 'aa',
|
||||
children: [
|
||||
{name: 'aaa', value: 'foo'}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
assert.deepEqual(map2tree(map), expected);
|
||||
assert.deepEqual(map2tree(immutable.fromJS(map)), expected, 'immutable');
|
||||
assert.end();
|
||||
});
|
||||
});
|
||||
|
||||
test('# array map', nest => {
|
||||
const map = {
|
||||
a: [
|
||||
1,
|
||||
2
|
||||
]
|
||||
};
|
||||
|
||||
nest.test('## push', assert => {
|
||||
const expected = {
|
||||
name: 'state',
|
||||
children: [{
|
||||
name: 'a',
|
||||
children: [
|
||||
{name: 'a[0]', value: 1},
|
||||
{name: 'a[1]', value: 2}]
|
||||
}]
|
||||
};
|
||||
|
||||
assert.deepEqual(map2tree(map), expected);
|
||||
assert.deepEqual(map2tree(immutable.fromJS(map)), expected, 'immutable');
|
||||
assert.end();
|
||||
});
|
||||
|
||||
nest.test('## unshift', assert => {
|
||||
const options = {pushMethod: 'unshift'};
|
||||
const expected = {
|
||||
name: 'state',
|
||||
children: [{
|
||||
name: 'a',
|
||||
children: [
|
||||
{name: 'a[1]', value: 2},
|
||||
{name: 'a[0]', value: 1}
|
||||
]
|
||||
}]
|
||||
};
|
||||
|
||||
assert.deepEqual(map2tree(map, options), expected);
|
||||
assert.deepEqual(map2tree(immutable.fromJS(map), options), expected, 'immutable');
|
||||
assert.end();
|
||||
});
|
||||
|
||||
nest.test('## null', assert => {
|
||||
const map = {
|
||||
a: [
|
||||
null
|
||||
]
|
||||
};
|
||||
|
||||
const expected = {
|
||||
name: 'state',
|
||||
children: [{
|
||||
name: 'a',
|
||||
children: [
|
||||
{name: 'a[0]', value: null}
|
||||
]
|
||||
}]
|
||||
};
|
||||
|
||||
assert.deepEqual(map2tree(map), expected);
|
||||
assert.deepEqual(map2tree(immutable.fromJS(map)), expected, 'immutable');
|
||||
assert.end();
|
||||
})
|
||||
});
|
||||
|
||||
test('# collection map', nest => {
|
||||
nest.test('## value', assert => {
|
||||
const map = {
|
||||
a: [
|
||||
{aa: 1},
|
||||
{aa: 2}
|
||||
]
|
||||
};
|
||||
|
||||
const expected = {
|
||||
name: 'state',
|
||||
children: [
|
||||
{
|
||||
name: 'a',
|
||||
children: [
|
||||
{name: 'a[0]', object: {aa: 1}},
|
||||
{name: 'a[1]', object: {aa: 2}}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
assert.deepEqual(map2tree(map), expected);
|
||||
assert.deepEqual(map2tree(immutable.fromJS(map)), expected, 'immutable');
|
||||
assert.end();
|
||||
});
|
||||
|
||||
nest.test('## object', assert => {
|
||||
const map = {
|
||||
a: [
|
||||
{aa: {aaa: 'foo'}}
|
||||
]
|
||||
};
|
||||
|
||||
const expected = {
|
||||
name: 'state',
|
||||
children: [
|
||||
{
|
||||
name: 'a',
|
||||
children: [
|
||||
{name: 'a[0]', object: {aa: {aaa: 'foo'}}}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
assert.deepEqual(map2tree(map), expected);
|
||||
assert.deepEqual(map2tree(immutable.fromJS(map)), expected, 'immutable');
|
||||
assert.end();
|
||||
})
|
||||
});
|
39
packages/map2tree/webpack.config.js
Executable file
39
packages/map2tree/webpack.config.js
Executable file
|
@ -0,0 +1,39 @@
|
|||
'use strict';
|
||||
|
||||
var webpack = require('webpack');
|
||||
|
||||
var plugins = [
|
||||
new webpack.optimize.OccurenceOrderPlugin(),
|
||||
new webpack.DefinePlugin({
|
||||
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
|
||||
})
|
||||
];
|
||||
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
plugins.push(
|
||||
new webpack.optimize.UglifyJsPlugin({
|
||||
compressor: {
|
||||
screw_ie8: true,
|
||||
warnings: false
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
module: {
|
||||
loaders: [{
|
||||
test: /\.js$/,
|
||||
loaders: ['babel-loader'],
|
||||
exclude: /node_modules/
|
||||
}]
|
||||
},
|
||||
output: {
|
||||
library: 'map2tree',
|
||||
libraryTarget: 'umd'
|
||||
},
|
||||
plugins: plugins,
|
||||
resolve: {
|
||||
extensions: ['', '.js']
|
||||
}
|
||||
};
|
Loading…
Reference in New Issue
Block a user