├── .babelrc
├── .gitignore
├── README.md
├── lib
└── index.js
├── package.json
├── src
└── index.js
└── test
└── dom.spec.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [["@babel/preset-env", { "loose": true }], "@babel/preset-react"],
3 | "plugins":[
4 | "@babel/plugin-proposal-class-properties"
5 | ]
6 | }
7 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | .idea
3 | .vscode
4 | node_modules
5 | *.log
6 | TODOs.md
7 | TODO.md
8 | explorations
9 | test/e2e/reports
10 | test/e2e/screenshots
11 | coverage
12 | dist
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # react-propers
2 |
3 | > Select react doms , and update props.
4 |
5 |
6 |
7 | ### Usage
8 |
9 | ```
10 | import React from "react"
11 | import ReactDOM from "react-dom"
12 | import Propers from "react-propers"
13 |
14 | ReactDOM.render(
15 | {
16 | switch(key){
17 | case "aaa":
18 | return {
19 | className:"aaa"
20 | }
21 | case "bbb":
22 | return {
23 | className:"bbb"
24 | }
25 | case "ccc":
26 | return {
27 | className:"ccc"
28 | }
29 | case "ddd":
30 | return false
31 | }
32 | return props
33 | }}>
34 | {React=>(
35 | <>
36 | 111
37 | 222
38 | 333
39 | 444
40 | >
41 | )}
42 |
43 | )
44 |
45 | //out put
46 |
47 |
111
222
333
48 | ```
49 |
50 |
51 |
52 | ### Install
53 |
54 | ```
55 | npm install --save react-propers
56 | ```
57 |
58 | ### API
59 |
60 | #### `selector : String | Array`
61 |
62 | > Support single selector and multi selector.
63 |
64 | #### `traverse : Function`
65 |
66 | > You can use [qverse](https://github.com/janryWang/qverse) to easily update props.
67 |
68 | ### LICENSE
69 |
70 | The MIT License (MIT)
71 |
72 | Copyright (c) 2018 JanryWang
73 |
74 | 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:
75 |
76 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
77 |
78 | 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.
--------------------------------------------------------------------------------
/lib/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | exports.__esModule = true;
4 | exports.default = exports.Propers = void 0;
5 |
6 | var _react = _interopRequireDefault(require("react"));
7 |
8 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
9 |
10 | function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
11 |
12 | function _inheritsLoose(subClass, superClass) { subClass.prototype.__proto__ = superClass && superClass.prototype; subClass.__proto__ = superClass; }
13 |
14 | function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
15 |
16 | var isArr = function isArr(val) {
17 | return Array.isArray(val);
18 | };
19 |
20 | var isStr = function isStr(val) {
21 | return typeof val === "string";
22 | };
23 |
24 | var isFn = function isFn(fn) {
25 | return typeof fn === "function";
26 | };
27 |
28 | var getPathSegments = function getPathSegments(path) {
29 | if (isArr(path)) return path;
30 |
31 | if (isStr(path) && path) {
32 | return (path || "").trim().split(/\s*\.\s*/);
33 | }
34 |
35 | return [];
36 | };
37 |
38 | var _createElement = _react.default.createElement;
39 |
40 | var getSelector = function getSelector(props, selector) {
41 | selector = Array.isArray(selector) ? selector : [selector];
42 |
43 | for (var i = 0; i < selector.length; i++) {
44 | var item = props[selector[i]];
45 | if (item !== undefined && item !== null) return item;
46 | }
47 | };
48 |
49 | var Propers =
50 | /*#__PURE__*/
51 | function (_React$Component) {
52 | function Propers() {
53 | return _React$Component.apply(this, arguments) || this;
54 | }
55 |
56 | var _proto = Propers.prototype;
57 |
58 | _proto.buildCreateElement = function buildCreateElement() {
59 | var _this$props = this.props,
60 | traverse = _this$props.traverse,
61 | selector = _this$props.selector,
62 | state = _this$props.state;
63 | return function (component, props) {
64 | for (var _len = arguments.length, children = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
65 | children[_key - 2] = arguments[_key];
66 | }
67 |
68 | if (!isFn(traverse)) return _createElement.apply(null, arguments);
69 | var $selector = props && getSelector(props, selector);
70 | var $props = $selector ? traverse(props, Object.defineProperties({}, {
71 | path: {
72 | get: function get() {
73 | return getPathSegments(String($selector));
74 | }
75 | },
76 | key: {
77 | value: $selector,
78 | writable: false
79 | },
80 | payload: {
81 | value: props,
82 | writable: false
83 | },
84 | index: {
85 | value: $selector,
86 | writable: false
87 | },
88 | component: {
89 | value: component,
90 | writable: false
91 | },
92 | state: {
93 | value: state,
94 | writable: false
95 | }
96 | })) : props;
97 |
98 | if ($selector) {
99 | if ($props && !$props["data-propers-hidden"]) {
100 | return _createElement.apply(void 0, [component, $props].concat(children));
101 | }
102 | } else {
103 | return _createElement.apply(void 0, [component, $props].concat(children));
104 | }
105 | };
106 | };
107 |
108 | _proto.render = function render() {
109 | var children = this.props.children;
110 | if (!isFn(children)) return children;
111 | this.react = this.react || _extends({}, _react.default, {
112 | createElement: this.buildCreateElement()
113 | });
114 | return children(this.react);
115 | };
116 |
117 | _inheritsLoose(Propers, _React$Component);
118 |
119 | return Propers;
120 | }(_react.default.Component);
121 |
122 | exports.Propers = Propers;
123 |
124 | _defineProperty(Propers, "defaultProps", {
125 | selector: "id"
126 | });
127 |
128 | var _default = Propers;
129 | exports.default = _default;
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-propers",
3 | "version": "0.1.5",
4 | "description": "",
5 | "main": "lib/index.js",
6 | "scripts": {
7 | "test": " cross-env NODE_ENV=test ava",
8 | "build": "babel src/index.js --out-dir lib",
9 | "precommit": "npm run build && lint-staged && npm run test && git add -A"
10 | },
11 | "repository": {
12 | "type": "git",
13 | "url": "git+https://github.com/janryWang/react-propers.git"
14 | },
15 | "author": "janry",
16 | "license": "MIT",
17 | "bugs": {
18 | "url": "https://github.com/janryWang/react-propers/issues"
19 | },
20 | "homepage": "https://github.com/janryWang/react-propers#readme",
21 | "devDependencies": {
22 | "@babel/cli": "^7.0.0-beta.46",
23 | "@babel/core": "^7.0.0-beta.46",
24 | "@babel/plugin-proposal-class-properties": "^7.0.0-beta.46",
25 | "@babel/preset-env": "^7.0.0-beta.46",
26 | "@babel/preset-react": "^7.0.0-beta.46",
27 | "@babel/register": "^7.0.0-beta.46",
28 | "ava": "^1.0.0-beta.4",
29 | "cross-env": "^5.1.4",
30 | "enzyme": "^3.3.0",
31 | "enzyme-adapter-react-16": "^1.1.1",
32 | "husky": "^0.14.3",
33 | "lint-staged": "^4.3.0",
34 | "prettier": "^1.11.x",
35 | "qverse": "^0.1.0",
36 | "react": "^16.3.2",
37 | "react-dom": "^16.3.2"
38 | },
39 | "lint-staged": {
40 | "src/*.js": [
41 | "prettier --write --tab-width 4 --no-semi",
42 | "git add"
43 | ],
44 | "dist/*.js": [
45 | "prettier --write --tab-width 4 --no-semi",
46 | "git add"
47 | ],
48 | "test.js": [
49 | "prettier --write --tab-width 4 --no-semi",
50 | "git add"
51 | ]
52 | },
53 | "ava": {
54 | "require": [
55 | "@babel/register"
56 | ],
57 | "files": [
58 | "test/**/*.spec.js",
59 | "test/*.spec.js"
60 | ],
61 | "babel": {
62 | "testOptions": {
63 | "babelrc": false,
64 | "presets": [
65 | [
66 | "@babel/preset-env",
67 | {
68 | "loose": true
69 | }
70 | ],
71 | "@babel/preset-react"
72 | ],
73 | "plugins": [
74 | "@babel/plugin-proposal-class-properties"
75 | ]
76 | }
77 | }
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from "react"
2 |
3 | const isArr = val => Array.isArray(val)
4 | const isStr = val => typeof val === "string"
5 | const isFn = fn => typeof fn === "function"
6 |
7 | const getPathSegments = path => {
8 | if (isArr(path)) return path
9 | if (isStr(path) && path) {
10 | return (path || "").trim().split(/\s*\.\s*/)
11 | }
12 | return []
13 | }
14 |
15 | const _createElement = React.createElement
16 |
17 | const getSelector = (props, selector) => {
18 | selector = Array.isArray(selector) ? selector : [selector]
19 | for (let i = 0; i < selector.length; i++) {
20 | let item = props[selector[i]]
21 | if (item !== undefined && item !== null) return item
22 | }
23 | }
24 |
25 | export class Propers extends React.Component {
26 | static defaultProps = {
27 | selector: "id"
28 | }
29 |
30 | buildCreateElement() {
31 | const { traverse, selector, state } = this.props
32 | return function(component, props, ...children) {
33 | if (!isFn(traverse)) return _createElement.apply(null, arguments)
34 | const $selector = props && getSelector(props, selector)
35 | const $props = $selector
36 | ? traverse(
37 | props,
38 | Object.defineProperties(
39 | {},
40 | {
41 | path: {
42 | get: () => {
43 | return getPathSegments(String($selector))
44 | }
45 | },
46 | key: {
47 | value: $selector,
48 | writable: false
49 | },
50 | payload: {
51 | value: props,
52 | writable: false
53 | },
54 | index: {
55 | value: $selector,
56 | writable: false
57 | },
58 | component: {
59 | value: component,
60 | writable: false
61 | },
62 | state: {
63 | value: state,
64 | writable: false
65 | }
66 | }
67 | )
68 | )
69 | : props
70 | if ($selector) {
71 | if ($props && !$props["data-propers-hidden"]) {
72 | return _createElement(component, $props, ...children)
73 | }
74 | } else {
75 | return _createElement(component, $props, ...children)
76 | }
77 | }
78 | }
79 |
80 | render() {
81 | const { children } = this.props
82 | if (!isFn(children)) return children
83 |
84 | this.react = this.react || {
85 | ...React,
86 | createElement: this.buildCreateElement()
87 | }
88 |
89 | return children(this.react)
90 | }
91 | }
92 |
93 | export default Propers
94 |
--------------------------------------------------------------------------------
/test/dom.spec.js:
--------------------------------------------------------------------------------
1 | import test from "ava"
2 | import React from "react"
3 | import Enzyme, { shallow } from "enzyme"
4 | import Adapter from "enzyme-adapter-react-16"
5 | import Propers from "../src/index"
6 | import qverse from "qverse"
7 |
8 | Enzyme.configure({ adapter: new Adapter() })
9 |
10 | const testAll = (cases)=>{
11 | cases.forEach((_case,index)=>{
12 | _case && test(`${index+1}th case.`,(t)=>{
13 | const dom = shallow(
14 |
17 | {_case.render}
18 |
19 | )
20 | t.is(dom.html(),_case.equal)
21 | })
22 | })
23 | }
24 |
25 | testAll([
26 | {
27 | render(React){
28 | return
29 | },
30 | traverse($){
31 | $("*").display(false)
32 | },
33 | equal:""
34 | },
35 | {
36 | render(React){
37 | return (
38 |
lalalalala
39 |
hahahahaha
40 |
)
41 | },
42 | traverse($){
43 | $("*").produce((props)=>{
44 | props.className = "123"
45 | })
46 | },
47 | equal:''
48 | }
49 | ])
50 |
--------------------------------------------------------------------------------