From 954cd60268fcbdef9ea62bc7e5eb3bd318a76d80 Mon Sep 17 00:00:00 2001 From: Richard Forrester Date: Sun, 21 Jul 2019 08:01:08 -1000 Subject: [PATCH 01/11] add compose --- src/index.ts | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/src/index.ts b/src/index.ts index 50380a4..5fbe379 100644 --- a/src/index.ts +++ b/src/index.ts @@ -98,4 +98,39 @@ function addChild

(state: BuilderState

, child: ReactNode) { return assign({}, state, { children: [...state.children || [], child] }) } -export default njsx as NJSX \ No newline at end of file +// ══════════════════════════════════════════════════════════════════════════════════════════════════════════════════ +// Compose +// ══════════════════════════════════════════════════════════════════════════════════════════════════════════════════ + +const err = 'compose: Functions required' + +const isFunction = (val: any): val is Function => typeof val === 'function' + +function applyPipe(f: any, g: any) { + if (!isFunction(g)) { + throw new TypeError(err) + } + + return (...args: any[]) => g.call(null, f.apply(null, args)) +} + +// compose :: ((y -> z), (x -> y), ..., (a -> b)) -> a -> z +export function compose(...args: any[]) { + if (!arguments.length) { + throw new TypeError(err) + } + + const fns = args.slice().reverse() + + const head = fns[0] + + if (!isFunction(head)) { + throw new TypeError(err) + } + + const tail = fns.slice(1).concat((x: any) => x) + + return tail.reduce(applyPipe, head) +} + +export default njsx as NJSX From cca5359dc73cf7fd8b043178c5d2fe95b61e9d95 Mon Sep 17 00:00:00 2001 From: Richard Forrester Date: Sun, 21 Jul 2019 08:02:56 -1000 Subject: [PATCH 02/11] Update Readme to include new compose export --- README.md | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index f94de34..1d0181c 100644 --- a/README.md +++ b/README.md @@ -303,33 +303,34 @@ If you rather all your arguments to just be interpreted as they are, you can dis ## Point-free -Think point-free composition in your render function is a `pipe` dream? Think again, you can use `njsx` to compose components in a point-free style to help with the readability of deeply nested react components: +Think point-free composition in your render function is a `pipe` dream? Think again! You can use `njsx` to compose components in a point-free style to increase the readability of deeply nested components: ```jsx - - - - - - - +const Root = ({ store }) => ( + + + + + + + +) ``` Becomes: ```js -import { compose } from 'rambda' - -compose( - Provider({ store }), - PersistGate({ loading: null, persistor }), - BrowserRouter, - Route -)({ path: '/', component: App })() +import { compose } from 'njsx' + +const Root = ({ store }) => + compose( + Provider({ store }), + PersistGate({ loading: null, persistor }), + Router({ history }), + Route + )({ path: '/', component: App })() ``` -Please note that `compose` and `pipe` functions vary in implementation and not all will work with `njsx`, for example, `lodash/fp` seems to have issues at the moment, while `rambda` is working without issue. - ## Working with older versions If you are working with an older release this documentation might not be of any use to you. We follow the [semantic versioning standard](https://semver.org/) so any difference on the Major version will probably imply some incompatibilities. Please refer to [your version's branch](https://github.com/uqbar-project/njsx/releases) README file. From fa59d336b0d8531bb9ecae490da49b6e263b7505 Mon Sep 17 00:00:00 2001 From: Richard Forrester Date: Sun, 21 Jul 2019 10:13:35 -1000 Subject: [PATCH 03/11] change compose for better TS support, update README with call to (null) --- package-lock.json | 791 ++++++++++++++++++++++++++++++++++++++++++++++ package.json | 2 +- 2 files changed, 792 insertions(+), 1 deletion(-) create mode 100644 package-lock.json diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..aa924ec --- /dev/null +++ b/package-lock.json @@ -0,0 +1,791 @@ +{ + "name": "njsx", + "version": "3.0.1", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@babel/code-frame": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", + "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/highlight": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", + "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@types/chai": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.1.7.tgz", + "integrity": "sha512-2Y8uPt0/jwjhQ6EiluT0XCri1Dbplr0ZxfFXUz+ye13gaqE8u5gL5ppao1JrUYr9cIip5S6MvQzBS7Kke7U9VA==", + "dev": true + }, + "@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", + "dev": true, + "optional": true + }, + "@types/mocha": { + "version": "5.2.7", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.7.tgz", + "integrity": "sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ==", + "dev": true + }, + "@types/prop-types": { + "version": "15.7.1", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.1.tgz", + "integrity": "sha512-CFzn9idOEpHrgdw8JsoTkaDDyRWk1jrzIV8djzcgpq0y9tG4B4lFT+Nxh52DVpDXV+n4+NPNv7M1Dj5uMp6XFg==", + "dev": true + }, + "@types/react": { + "version": "16.8.23", + "resolved": "https://registry.npmjs.org/@types/react/-/react-16.8.23.tgz", + "integrity": "sha512-abkEOIeljniUN9qB5onp++g0EY38h7atnDHxwKUFz1r3VH1+yG1OKi2sNPTyObL40goBmfKFpdii2lEzwLX1cA==", + "dev": true, + "requires": { + "@types/prop-types": "*", + "csstype": "^2.2.0" + } + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=", + "dev": true + }, + "assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "chai": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", + "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", + "dev": true, + "requires": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.2", + "deep-eql": "^3.0.1", + "get-func-name": "^2.0.0", + "pathval": "^1.1.0", + "type-detect": "^4.0.5" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", + "dev": true + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "commander": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "core-js": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", + "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=", + "dev": true + }, + "csstype": { + "version": "2.6.6", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.6.tgz", + "integrity": "sha512-RpFbQGUE74iyPgvr46U9t1xoQBM8T4BL8SxrN66Le2xYAPSaDJJKeztV3awugusb3g3G9iL8StmkBBXhcbbXhg==", + "dev": true + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-eql": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", + "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "dev": true, + "requires": { + "type-detect": "^4.0.0" + } + }, + "deepmerge": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.2.1.tgz", + "integrity": "sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==", + "dev": true, + "optional": true + }, + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true + }, + "encoding": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", + "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", + "dev": true, + "requires": { + "iconv-lite": "~0.4.13" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "fbjs": { + "version": "0.8.17", + "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.17.tgz", + "integrity": "sha1-xNWY6taUkRJlPWWIsBpc3Nn5D90=", + "dev": true, + "requires": { + "core-js": "^1.0.0", + "isomorphic-fetch": "^2.1.1", + "loose-envify": "^1.0.0", + "object-assign": "^4.1.0", + "promise": "^7.1.1", + "setimmediate": "^1.0.5", + "ua-parser-js": "^0.7.18" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "dev": true + }, + "get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", + "dev": true + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "he": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", + "dev": true + }, + "homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "dev": true, + "requires": { + "parse-passwd": "^1.0.0" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "isomorphic-fetch": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", + "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=", + "dev": true, + "requires": { + "node-fetch": "^1.0.1", + "whatwg-fetch": ">=0.10.0" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "optional": true, + "requires": { + "minimist": "^1.2.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true, + "optional": true + } + } + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "make-error": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.5.tgz", + "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "mocha": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz", + "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==", + "dev": true, + "requires": { + "browser-stdout": "1.3.1", + "commander": "2.15.1", + "debug": "3.1.0", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "glob": "7.1.2", + "growl": "1.10.5", + "he": "1.1.1", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "supports-color": "5.4.0" + } + }, + "mock-require": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/mock-require/-/mock-require-3.0.3.tgz", + "integrity": "sha512-lLzfLHcyc10MKQnNUCv7dMcoY/2Qxd6wJfbqCcVk3LDb8An4hF6ohk5AztrvgKhJCqj36uyzi/p5se+tvyD+Wg==", + "dev": true, + "requires": { + "get-caller-file": "^1.0.2", + "normalize-path": "^2.1.1" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node-fetch": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", + "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", + "dev": true, + "requires": { + "encoding": "^0.1.11", + "is-stream": "^1.0.1" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "pathval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", + "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", + "dev": true + }, + "promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "dev": true, + "requires": { + "asap": "~2.0.3" + } + }, + "react": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/react/-/react-15.0.0.tgz", + "integrity": "sha1-PH4WUx1jDhXBpQqUfxS6YXRq+Kc=", + "dev": true, + "requires": { + "fbjs": "^0.8.0", + "loose-envify": "^1.1.0", + "object-assign": "^4.0.1" + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "resolve": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.1.tgz", + "integrity": "sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "semver": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", + "dev": true + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "source-map-support": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", + "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", + "dev": true, + "requires": { + "source-map": "^0.5.6" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "ts-mocha": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-mocha/-/ts-mocha-1.3.0.tgz", + "integrity": "sha512-hmgivryGUk854cPI49YE3MNd52053PaxivdXmjSWYhADAEJ0zQsaXt0Z45CicdKJnsmViuVMrnzPcQDdHCOY2A==", + "dev": true, + "requires": { + "ts-node": "3.3.0", + "tsconfig-paths": "^3.5.0" + } + }, + "ts-node": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-3.3.0.tgz", + "integrity": "sha1-wTxqMCTjC+EYDdUwOPwgkonUv2k=", + "dev": true, + "requires": { + "arrify": "^1.0.0", + "chalk": "^2.0.0", + "diff": "^3.1.0", + "make-error": "^1.1.1", + "minimist": "^1.2.0", + "mkdirp": "^0.5.1", + "source-map-support": "^0.4.0", + "tsconfig": "^6.0.0", + "v8flags": "^3.0.0", + "yn": "^2.0.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "tsconfig": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-6.0.0.tgz", + "integrity": "sha1-aw6DdgA9evGGT434+J3QBZ/80DI=", + "dev": true, + "requires": { + "strip-bom": "^3.0.0", + "strip-json-comments": "^2.0.0" + } + }, + "tsconfig-paths": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.8.0.tgz", + "integrity": "sha512-zZEYFo4sjORK8W58ENkRn9s+HmQFkkwydDG7My5s/fnfr2YYCaiyXe/HBUcIgU8epEKOXwiahOO+KZYjiXlWyQ==", + "dev": true, + "optional": true, + "requires": { + "@types/json5": "^0.0.29", + "deepmerge": "^2.0.1", + "json5": "^1.0.1", + "minimist": "^1.2.0", + "strip-bom": "^3.0.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true, + "optional": true + } + } + }, + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==", + "dev": true + }, + "tslint": { + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.18.0.tgz", + "integrity": "sha512-Q3kXkuDEijQ37nXZZLKErssQVnwCV/+23gFEMROi8IlbaBG6tXqLPQJ5Wjcyt/yHPKBC+hD5SzuGaMora+ZS6w==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "builtin-modules": "^1.1.1", + "chalk": "^2.3.0", + "commander": "^2.12.1", + "diff": "^3.2.0", + "glob": "^7.1.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "resolve": "^1.3.2", + "semver": "^5.3.0", + "tslib": "^1.8.0", + "tsutils": "^2.29.0" + } + }, + "tslint-react": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/tslint-react/-/tslint-react-3.6.0.tgz", + "integrity": "sha512-AIv1QcsSnj7e9pFir6cJ6vIncTqxfqeFF3Lzh8SuuBljueYzEAtByuB6zMaD27BL0xhMEqsZ9s5eHuCONydjBw==", + "dev": true, + "requires": { + "tsutils": "^2.13.1" + } + }, + "tsutils": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", + "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true + }, + "typescript": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.9.2.tgz", + "integrity": "sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w==", + "dev": true + }, + "ua-parser-js": { + "version": "0.7.20", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.20.tgz", + "integrity": "sha512-8OaIKfzL5cpx8eCMAhhvTlft8GYF8b2eQr6JkCyVdrgjcytyOmPCXrqXFcUnhonRpLlh5yxEZVohm6mzaowUOw==", + "dev": true + }, + "v8flags": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.3.tgz", + "integrity": "sha512-amh9CCg3ZxkzQ48Mhcb8iX7xpAfYJgePHxWMQCBWECpOSqJUXgY26ncA61UTV0BkPqfhcy6mzwCIoP4ygxpW8w==", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "whatwg-fetch": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz", + "integrity": "sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q==", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "yn": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz", + "integrity": "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=", + "dev": true + } + } +} diff --git a/package.json b/package.json index 1bb6c07..b858e0b 100644 --- a/package.json +++ b/package.json @@ -41,4 +41,4 @@ "functional", "syntax sugar" ] -} \ No newline at end of file +} From 4d95c83cf8120761e81b85be9dfcd3a0cf357b6b Mon Sep 17 00:00:00 2001 From: Richard Forrester Date: Sun, 21 Jul 2019 22:30:00 -1000 Subject: [PATCH 04/11] implement nest and update README --- README.md | 272 +++++++++++++++++++++++++++++++-------------------- src/index.ts | 56 ++++------- 2 files changed, 184 insertions(+), 144 deletions(-) diff --git a/README.md b/README.md index 1d0181c..93c3bde 100644 --- a/README.md +++ b/README.md @@ -3,20 +3,16 @@ [![Build Status](https://travis-ci.org/uqbar-project/njsx.svg?branch=master)](https://travis-ci.org/uqbar-project/njsx) [![npm version](https://badge.fury.io/js/njsx.svg)](https://badge.fury.io/js/njsx) -A pure function based interface for creating [React](https://facebook.github.io/react/) and [React Native](https://facebook.github.io/react-native/) components without *JSX* tags. +A pure function based interface for creating [React](https://facebook.github.io/react/) and [React Native](https://facebook.github.io/react-native/) components without _JSX_ tags. -If you love *React* but don't quite like the embeded *HTML* tags this library may be what you are looking for. Construct your components with code only in a clean, declarative way. +If you love _React_ but don't quite like the embeded _HTML_ tags this library may be what you are looking for. Construct your components with code only in a clean, declarative way. ```js const myView = () => - div.app( - div.header( - img({src: logo, alt:'logo'}), - h2('Welcome to NJSX') - ) - )() + div.app(div.header(img({ src: logo, alt: 'logo' }), h2('Welcome to NJSX')))() ``` -------------------------------------------------- + +--- #### Table of Content @@ -35,42 +31,42 @@ const myView = () => - [Contributions](#contributions) - [License](#license) -------------------------------------------------- +--- ## Installation -*NJSX* is available on [npm](https://www.npmjs.com), just pick between the *React* and *React Native* flavours and add it to your project's dependencies. +_NJSX_ is available on [npm](https://www.npmjs.com), just pick between the _React_ and _React Native_ flavours and add it to your project's dependencies. **For React Projects:** + ```bash npm install njsx-react --save ``` **For React Native Projects:** + ```bash npm install njsx-react-native --save ``` - ## Usage -*NJSX* is super easy to use: It's all about **Builder Functions**. - -You can use *Builders* to to cleanly instantiate *React* and *React Native* elements, or further refine your component configuration just by applying them. +_NJSX_ is super easy to use: It's all about **Builder Functions**. +You can use _Builders_ to to cleanly instantiate _React_ and _React Native_ elements, or further refine your component configuration just by applying them. ### Getting a Builder #### Default Component Builders -*NJSX* provides *Builder Functions* for all the default *React* and *React Native* components. Just import whatever element you need from the `react` or `react-native` modules and you are ready to go: +_NJSX_ provides _Builder Functions_ for all the default _React_ and _React Native_ components. Just import whatever element you need from the `react` or `react-native` modules and you are ready to go: ```js // React project -import {div, p} from 'njsx-react' +import { div, p } from 'njsx-react' // React Native project -import {View, Text} from 'njsx-react-native' +import { View, Text } from 'njsx-react-native' ``` #### Third-Party Component Builders @@ -88,7 +84,7 @@ class SomeStatefulComponent extends React.Component { } // These are all valid Component Builders. -const someComponent = njsx(SomeComponent) +const someComponent = njsx(SomeComponent) const someFunctionalComponent = njsx(SomeFunctionalComponent) const someStatefulComponent = njsx(SomeFunctionalComponent) @@ -98,23 +94,23 @@ const aDivBuilder = njsx('div') ### Creating Elements -Each *NJSX* builder, once **applied with no arguments**, will return a **ReactElement** just as if you had used the component inside a *JSX* tag: +Each _NJSX_ builder, once **applied with no arguments**, will return a **ReactElement** just as if you had used the component inside a _JSX_ tag: ```jsx -import {div} from 'njsx-react' +import { div } from 'njsx-react' // These two lines are equivalent. -

+;
div() ``` -This means that *JSX* and *NJSX* elements are completely interchangeable. You can use components created from builders as children for *JSX*'s tags, or refine a builder with tag shaped children, so you can try *NJSX* on any react based project and integrate it gradually. +This means that _JSX_ and _NJSX_ elements are completely interchangeable. You can use components created from builders as children for _JSX_'s tags, or refine a builder with tag shaped children, so you can try _NJSX_ on any react based project and integrate it gradually. ### Refining Builders Of course, an empty element is not that useful, so how do you customize it? -When a *Builder* is applied with **one or more arguments**, these will be used to configure the building component. Refining a *Builder* this way returns another ***Builder***, so you can keep refining your component any number of times. +When a _Builder_ is applied with **one or more arguments**, these will be used to configure the building component. Refining a _Builder_ this way returns another **_Builder_**, so you can keep refining your component any number of times. ```jsx import {p} from 'njsx-react' @@ -128,79 +124,75 @@ p(['some', ' ', 'text'])

some text

``` -It's important to note that refining a builder causes **no side effects or state changes at all**. This means you can safely reuse *Builders*, or partially refine one and pass it forward. +It's important to note that refining a builder causes **no side effects or state changes at all**. This means you can safely reuse _Builders_, or partially refine one and pass it forward. #### Builder Arguments -*Builders* will get refined in a different way, depending on what arguments you apply them with: +_Builders_ will get refined in a different way, depending on what arguments you apply them with: - - `Basic Objects` are treated as **Component Properties**. Refining a builder with a second set of properties will result in the merge of both, favoring the later in case of repetition. - - ```jsx - img({src: path, onClick: cb}) - img({src: path}, {onClick: cb}) - img({src: thisWillBeLost, onClick: cb})({src: path}) +- `Basic Objects` are treated as **Component Properties**. Refining a builder with a second set of properties will result in the merge of both, favoring the later in case of repetition. - // All these lines build the same: - - ``` + ```jsx + img({src: path, onClick: cb}) + img({src: path}, {onClick: cb}) + img({src: thisWillBeLost, onClick: cb})({src: path}) + // All these lines build the same: + + ``` - - `Strings`, `Numbers`, `React Elements` and even other `Builders` will become **Component Children**. +* `Strings`, `Numbers`, `React Elements` and even other `Builders` will become **Component Children**. - ```jsx - div( - div('the answer is ', 42) // <- No need for building it. - ) - - // This line builds: -
the answer is 42
- ``` + ```jsx + div( + div('the answer is ', 42) // <- No need for building it. + ) - Notice that, since *Builders* can be children too, most of the time you won't be needing to apply them with no arguments to instantiate elements. + // This line builds: +
the answer is 42
+ ``` + Notice that, since _Builders_ can be children too, most of the time you won't be needing to apply them with no arguments to instantiate elements. - - `null`, `undefined` and `Booleans` will be ignored. This allows for a clean way to conditionally set properties and children using `&&` and `||`. +- `null`, `undefined` and `Booleans` will be ignored. This allows for a clean way to conditionally set properties and children using `&&` and `||`. - ```jsx - div(null) - div(undefined) - div(false && "this won't show") + ```jsx + div(null) + div(undefined) + div(false && "this won't show") - //All these lines the same: -
- ``` + //All these lines the same: +
+ ``` - - `Arrays` of any valid argument will be handled as a sequence of refinements. +- `Arrays` of any valid argument will be handled as a sequence of refinements. - ```jsx - const guards = ['Nobby', 'Colon', 'Carrot'] - - ul(guards.map(guard => li(guard))) - ul(guards.map(li)) + ```jsx + const guards = ['Nobby', 'Colon', 'Carrot'] - //All these lines the same: -
    {guards.map(guard =>
  • {guard}
  • )}
- ``` + ul(guards.map(guard => li(guard))) + ul(guards.map(li)) + //All these lines the same: +
    {guards.map(guard =>
  • {guard}
  • )}
+ ``` - - Finally, you can also pass a `Refinement Function`, which should take the previous *Component Properties* (including the `children` field) and return the next one. +* Finally, you can also pass a `Refinement Function`, which should take the previous _Component Properties_ (including the `children` field) and return the next one. - ```jsx - const myRefinement = (src, text) => (prev) => - {...prev, {src, children: text} } - img(myRefinement(foo, bar)) + ```jsx + const myRefinement = (src, text) => (prev) => + {...prev, {src, children: text} } + img(myRefinement(foo, bar)) - // This line builds: - bar - ``` + // This line builds: + bar + ``` To wrap it all, any unsuported argument application will raise a `TypeError`. - #### Dynamic Selectors -You can also refine a *Builder* by accessing any keyword as if it was a property. A common use for this is to treat the keyword as a `className`, so you can add classes to components by just naming them: +You can also refine a _Builder_ by accessing any keyword as if it was a property. A common use for this is to treat the keyword as a `className`, so you can add classes to components by just naming them: ```jsx p.highlighted.small("Nice!") @@ -212,7 +204,7 @@ p("Nice!").highlighted['.small']

Nice!

``` -Treating these selectors as class names is the default behavior of *NJSX*, but you can change it to whatever you want by changing the `NJSXConfig. dynamicSelectorHandler` setting: +Treating these selectors as class names is the default behavior of _NJSX_, but you can change it to whatever you want by changing the `NJSXConfig. dynamicSelectorHandler` setting: ```jsx import { NJSXConfig } from 'njsx' @@ -238,15 +230,13 @@ div.baz NJSXConfig.dynamicSelectorHandler = undefined ``` - -Notice that this feature can only be used on [environments that support *ES6's Proxy*](https://kangax.github.io/compat-table/es6/#test-Proxy) so, sadly, it's not available on *React-Native* projects. - +Notice that this feature can only be used on [environments that support _ES6's Proxy_](https://kangax.github.io/compat-table/es6/#test-Proxy) so, sadly, it's not available on _React-Native_ projects. ## Argument Transformation -You don't like the way arguments are being handled? No problem! You can customize the way *NJSX's Builders* interpret arguments to fine tune it to your needs. +You don't like the way arguments are being handled? No problem! You can customize the way _NJSX's Builders_ interpret arguments to fine tune it to your needs. -The `NJSXConfig` object can be used to specify **Argument Transformations**, which are just functions that take each argument and return whatever you want that argument to be. These functions are automatically called each time a *Builder* is applied. +The `NJSXConfig` object can be used to specify **Argument Transformations**, which are just functions that take each argument and return whatever you want that argument to be. These functions are automatically called each time a _Builder_ is applied. ```jsx import { NJSXConfig } from 'njsx' @@ -270,40 +260,40 @@ p("!this should be translated") Please take into account that **all transformations are reduced on every argument**, so don't overdo it and mind the order. -*NJSX* comes with some of these transformations set up by default: +_NJSX_ comes with some of these transformations set up by default: - - In *React* projects, **Strings starting with a dot** will be interpreted as a *classNames*: +- In _React_ projects, **Strings starting with a dot** will be interpreted as a _classNames_: - ```jsx - div('.foo .bar')( - 'Some content' - ) + ```jsx + div('.foo .bar')( + 'Some content' + ) - // This builds: -
Some content
- ``` + // This builds: +
Some content
+ ``` - - In *React-Native* projects, **StyleSheet** arguments are interpreted as *styles* (Just import `StyleSheet` from `njsx-react-native` instead of `react-native`). +- In _React-Native_ projects, **StyleSheet** arguments are interpreted as _styles_ (Just import `StyleSheet` from `njsx-react-native` instead of `react-native`). - ```jsx - import {StyleSheet, View, Text} from 'njsx-react-native' + ```jsx + import {StyleSheet, View, Text} from 'njsx-react-native' - // Same StyleSheet interface - StyleSheet.create({ - container: { /* ...your regular react-native styles... */ } - description: { /* ...your regular react-native styles... */ } - }) + // Same StyleSheet interface + StyleSheet.create({ + container: { /* ...your regular react-native styles... */ } + description: { /* ...your regular react-native styles... */ } + }) - View(styles.container)( - Text(style.description)("These are styled!") - ) - ``` + View(styles.container)( + Text(style.description)("These are styled!") + ) + ``` If you rather all your arguments to just be interpreted as they are, you can disable this feature by setting the `NJSXConfig.argumentTransformations` to an empty array. ## Point-free -Think point-free composition in your render function is a `pipe` dream? Think again! You can use `njsx` to compose components in a point-free style to increase the readability of deeply nested components: +Think point-free composition in your render is a `pipe` dream? Think again! You can use `njsx` to compose components in a point-free style to increase the readability of deeply nested components: ```jsx const Root = ({ store }) => ( @@ -320,28 +310,98 @@ const Root = ({ store }) => ( Becomes: ```js -import { compose } from 'njsx' +import { nest } from 'njsx' const Root = ({ store }) => - compose( + nest( Provider({ store }), PersistGate({ loading: null, persistor }), Router({ history }), - Route - )({ path: '/', component: App })() + Route({ path: '/', component: App }) + )() +``` + +## Example Refactoring +JSX: +```jsx +export const Loading = () => ( +
+
+
+
+

Welcome back!

+
+ +
+

Please hang tight while we load your app.

+
+ +
+
+
+ +
+
+
+
+
+
+) +``` +NJSX nested: +```js +export const Loading = () => + div ({ className: 'row', style: { marginTop: '10em' } }) ( + div ({ className: 'col-sm-7', style: { float: 'none', margin: 'auto' } }) ( + div ({ className: 'well well-lg', style: { paddingTop: '0px' } }) ( + div ({ className: 'row', style: { marginTop: 0, marginBottom: 10 } }) ( + h2 ({ className: 'col-sm-12' }) ('Welcome back!') + ), + div ({ className: 'row' }) ( + p ({ className: 'col-sm-12' }) ('Please hang tight while we load your app.') + ), + div ({ className: 'row' }) ( + div ({ className: 'col-sm-12' }) ( + div ({ className: 'pull-right' }) (Spinner ({ style: { top: 16, width: 42 } })) + ) + ) + ) + ) + ) () +``` +NJSX composed: +```js +export const Loading = () => + nest ( + div ({ className: 'row', style: { marginTop: '10em' } }), + div ({ className: 'col-sm-7', style: { float: 'none', margin: 'auto' } }), + div ({ className: 'well well-lg', style: { paddingTop: '0px' } }) ( + nest ( + div ({ className: 'row', style: { marginTop: 0, marginBottom: 10 } }), + h2 ({ className: 'col-sm-12' }) ('Welcome back!') + ), + nest ( + div ({ className: 'row' }), + p ({ className: 'col-sm-12' }) ('Please hang tight while we load your app.') + ), + nest ( + div ({ className: 'row' }), + div ({ className: 'col-sm-12' }), + div ({ className: 'pull-right' }) (Spinner ({ style: { top: 16, width: 42 } })) + ) + ) + ) () ``` ## Working with older versions If you are working with an older release this documentation might not be of any use to you. We follow the [semantic versioning standard](https://semver.org/) so any difference on the Major version will probably imply some incompatibilities. Please refer to [your version's branch](https://github.com/uqbar-project/njsx/releases) README file. - ## Contributions Please report any bugs, requests or ideas on [the issues section of this repository](https://github.com/uqbar-project/njsx/issues) and we will try to see to it as soon as possible. Pull requests are always welcome! Just try to keep them small and clean. - ## License This code is open source software licensed under the [ISC License](https://opensource.org/licenses/ISC) by [The Uqbar Foundation](http://www.uqbar-project.org/). Feel free to use it accordingly. diff --git a/src/index.ts b/src/index.ts index 5fbe379..f6fa16b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,9 +5,9 @@ import { createElement, ReactChild, ReactElement, ReactNode, ReactType } from 'r const { assign } = Object const { isArray } = Array -// ══════════════════════════════════════════════════════════════════════════════════════════════════════════════════ +// ══════════════════════════════════════════════════════════════════════════════════════ // CONFIGURATION -// ══════════════════════════════════════════════════════════════════════════════════════════════════════════════════ +// ══════════════════════════════════════════════════════════════════════════════════════ export type ArgumentTransformation = (arg: any) => any @@ -21,9 +21,9 @@ export const NJSXConfig: { }, } -// ══════════════════════════════════════════════════════════════════════════════════════════════════════════════════ +// ══════════════════════════════════════════════════════════════════════════════════════ // BUILDERS -// ══════════════════════════════════════════════════════════════════════════════════════════════════════════════════ +// ══════════════════════════════════════════════════════════════════════════════════════ export interface Builder

{ (): ReactElement

, @@ -47,9 +47,9 @@ export type BuilderState

= Partial

export type BuilderRefinement

= (state: BuilderState

) => BuilderState

-// ══════════════════════════════════════════════════════════════════════════════════════════════════════════════════ +// ══════════════════════════════════════════════════════════════════════════════════════ // FACADE -// ══════════════════════════════════════════════════════════════════════════════════════════════════════════════════ +// ══════════════════════════════════════════════════════════════════════════════════════ export type NJSX =

(type: ReactType

) => Builder

const njsx =

(type: ReactType

, baseState: BuilderState

= {}): Builder

=> { @@ -98,39 +98,19 @@ function addChild

(state: BuilderState

, child: ReactNode) { return assign({}, state, { children: [...state.children || [], child] }) } -// ══════════════════════════════════════════════════════════════════════════════════════════════════════════════════ -// Compose -// ══════════════════════════════════════════════════════════════════════════════════════════════════════════════════ +// ══════════════════════════════════════════════════════════════════════════════════════ +// Compose (nest) +// ══════════════════════════════════════════════════════════════════════════════════════ -const err = 'compose: Functions required' +type nest = (x: Builder, ...xs: Builder[]) => Builder -const isFunction = (val: any): val is Function => typeof val === 'function' - -function applyPipe(f: any, g: any) { - if (!isFunction(g)) { - throw new TypeError(err) - } - - return (...args: any[]) => g.call(null, f.apply(null, args)) -} - -// compose :: ((y -> z), (x -> y), ..., (a -> b)) -> a -> z -export function compose(...args: any[]) { - if (!arguments.length) { - throw new TypeError(err) - } - - const fns = args.slice().reverse() - - const head = fns[0] - - if (!isFunction(head)) { - throw new TypeError(err) - } - - const tail = fns.slice(1).concat((x: any) => x) - - return tail.reduce(applyPipe, head) -} +export const nest: nest = (...xs) => + xs + .slice(0, -1) + .reverse() + .reduce( + (r: Builder, y: Builder): Builder => y(r), + xs.slice(-1)[0] + ) export default njsx as NJSX From 6fb253d79966f8de10c6afbf7ded13bbb945b3cc Mon Sep 17 00:00:00 2001 From: Richard Forrester Date: Sun, 21 Jul 2019 22:38:19 -1000 Subject: [PATCH 05/11] add typing for test --- README.md | 37 ++++++++++++++++++------------------- src/index.ts | 4 ++-- 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 93c3bde..cfa7a3f 100644 --- a/README.md +++ b/README.md @@ -371,26 +371,25 @@ export const Loading = () => ``` NJSX composed: ```js -export const Loading = () => - nest ( - div ({ className: 'row', style: { marginTop: '10em' } }), - div ({ className: 'col-sm-7', style: { float: 'none', margin: 'auto' } }), - div ({ className: 'well well-lg', style: { paddingTop: '0px' } }) ( - nest ( - div ({ className: 'row', style: { marginTop: 0, marginBottom: 10 } }), - h2 ({ className: 'col-sm-12' }) ('Welcome back!') - ), - nest ( - div ({ className: 'row' }), - p ({ className: 'col-sm-12' }) ('Please hang tight while we load your app.') - ), - nest ( - div ({ className: 'row' }), - div ({ className: 'col-sm-12' }), - div ({ className: 'pull-right' }) (Spinner ({ style: { top: 16, width: 42 } })) - ) +export const Loading = nest ( + div ({ className: 'row', style: { marginTop: '10em' } }), + div ({ className: 'col-sm-7', style: { float: 'none', margin: 'auto' } }), + div ({ className: 'well well-lg', style: { paddingTop: '0px' } }) ( + nest ( + div ({ className: 'row', style: { marginTop: 0, marginBottom: 10 } }), + h2 ({ className: 'col-sm-12' }) ('Welcome back!') + ), + nest ( + div ({ className: 'row' }), + p ({ className: 'col-sm-12' }) ('Please hang tight while we load your app.') + ), + nest ( + div ({ className: 'row' }), + div ({ className: 'col-sm-12' }), + div ({ className: 'pull-right' }) (Spinner ({ style: { top: 16, width: 42 } })) ) - ) () + ) +) ``` ## Working with older versions diff --git a/src/index.ts b/src/index.ts index f6fa16b..b9f367b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,4 @@ -import { createElement, ReactChild, ReactElement, ReactNode, ReactType } from 'react' +import { createElement, ReactChild, ReactElement, ReactNode, ReactType } from 'react'; // TODO: Perhaps we could add an example project // TODO: Replace with spread operator once Typescript suports spread of generics (https://github.com/Microsoft/TypeScript/pull/13288) @@ -104,7 +104,7 @@ function addChild

(state: BuilderState

, child: ReactNode) { type nest = (x: Builder, ...xs: Builder[]) => Builder -export const nest: nest = (...xs) => +export const nest: nest = (...xs: Builder[]): Builder => xs .slice(0, -1) .reverse() From 713630feaa8114677308303163e9757cb6f85c60 Mon Sep 17 00:00:00 2001 From: Richard Forrester Date: Sun, 21 Jul 2019 22:57:06 -1000 Subject: [PATCH 06/11] update README --- README.md | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index cfa7a3f..078bcb5 100644 --- a/README.md +++ b/README.md @@ -351,18 +351,18 @@ export const Loading = () => ( NJSX nested: ```js export const Loading = () => - div ({ className: 'row', style: { marginTop: '10em' } }) ( - div ({ className: 'col-sm-7', style: { float: 'none', margin: 'auto' } }) ( - div ({ className: 'well well-lg', style: { paddingTop: '0px' } }) ( - div ({ className: 'row', style: { marginTop: 0, marginBottom: 10 } }) ( - h2 ({ className: 'col-sm-12' }) ('Welcome back!') + div ({className: 'row', style: {marginTop: '10em'}}) ( + div ({className: 'col-sm-7', style: {float: 'none', margin: 'auto'}}) ( + div ({className: 'well well-lg', style: {paddingTop: '0px'}}) ( + div ({className: 'row', style: {marginTop: 0, marginBottom: 10}}) ( + h2 ({className: 'col-sm-12'}) ('Welcome back!') ), - div ({ className: 'row' }) ( - p ({ className: 'col-sm-12' }) ('Please hang tight while we load your app.') + div ({className: 'row'}) ( + p ({className: 'col-sm-12'}) ('Please hang tight while we load your app.') ), - div ({ className: 'row' }) ( - div ({ className: 'col-sm-12' }) ( - div ({ className: 'pull-right' }) (Spinner ({ style: { top: 16, width: 42 } })) + div ({className: 'row'}) ( + div ({className: 'col-sm-12'}) ( + div ({className: 'pull-right'}) (Spinner ({style: {top: 16, width: 42}})) ) ) ) @@ -372,24 +372,25 @@ export const Loading = () => NJSX composed: ```js export const Loading = nest ( - div ({ className: 'row', style: { marginTop: '10em' } }), - div ({ className: 'col-sm-7', style: { float: 'none', margin: 'auto' } }), - div ({ className: 'well well-lg', style: { paddingTop: '0px' } }) ( + div ({className: 'row', style: {marginTop: '10em'}}), + div ({className: 'col-sm-7', style: {float: 'none', margin: 'auto'}}), + div ({className: 'well well-lg', style: {paddingTop: '0px'}}) ( nest ( - div ({ className: 'row', style: { marginTop: 0, marginBottom: 10 } }), - h2 ({ className: 'col-sm-12' }) ('Welcome back!') + div ({className: 'row', style: {marginTop: 0, marginBottom: 10}}), + h2 ({className: 'col-sm-12'}) ('Welcome back!') ), nest ( - div ({ className: 'row' }), - p ({ className: 'col-sm-12' }) ('Please hang tight while we load your app.') + div ({className: 'row'}), + p ({className: 'col-sm-12'}) ('Please hang tight while we load your app.') ), nest ( - div ({ className: 'row' }), - div ({ className: 'col-sm-12' }), - div ({ className: 'pull-right' }) (Spinner ({ style: { top: 16, width: 42 } })) + div ({className: 'row'}), + div ({className: 'col-sm-12'}), + div ({className: 'pull-right'}) (Spinner ({style: {top: 16, width: 42}})) ) ) ) + ``` ## Working with older versions From 3eb5fcbbc04084c41e23dfac645d0d53c0c19b79 Mon Sep 17 00:00:00 2001 From: Richard Forrester Date: Sun, 21 Jul 2019 23:48:48 -1000 Subject: [PATCH 07/11] fix README --- README.md | 53 +++++++++++++++++++++++++---------------------------- 1 file changed, 25 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 078bcb5..c8ad869 100644 --- a/README.md +++ b/README.md @@ -351,17 +351,15 @@ export const Loading = () => ( NJSX nested: ```js export const Loading = () => - div ({className: 'row', style: {marginTop: '10em'}}) ( - div ({className: 'col-sm-7', style: {float: 'none', margin: 'auto'}}) ( - div ({className: 'well well-lg', style: {paddingTop: '0px'}}) ( - div ({className: 'row', style: {marginTop: 0, marginBottom: 10}}) ( - h2 ({className: 'col-sm-12'}) ('Welcome back!') + Row ({style: {marginTop: '10em'}}) ( + Col ({sm: 7, style: {float: 'none', margin: 'auto'}}) ( + Well ({bsSize: 'lg', style: {paddingTop: '0px'}}) ( + Row ({style: {marginTop: 0, marginBottom: 10}}) ( + Col ({sm: 12}) (h2 ('Welcome back!')) ), - div ({className: 'row'}) ( - p ({className: 'col-sm-12'}) ('Please hang tight while we load your app.') - ), - div ({className: 'row'}) ( - div ({className: 'col-sm-12'}) ( + Row (Col ({sm: 12}) (p ('Please hang tight while we load your app.'))), + Row ( + Col ({sm: 12}) ( div ({className: 'pull-right'}) (Spinner ({style: {top: 16, width: 42}})) ) ) @@ -371,25 +369,24 @@ export const Loading = () => ``` NJSX composed: ```js -export const Loading = nest ( - div ({className: 'row', style: {marginTop: '10em'}}), - div ({className: 'col-sm-7', style: {float: 'none', margin: 'auto'}}), - div ({className: 'well well-lg', style: {paddingTop: '0px'}}) ( - nest ( - div ({className: 'row', style: {marginTop: 0, marginBottom: 10}}), - h2 ({className: 'col-sm-12'}) ('Welcome back!') - ), - nest ( - div ({className: 'row'}), - p ({className: 'col-sm-12'}) ('Please hang tight while we load your app.') - ), - nest ( - div ({className: 'row'}), - div ({className: 'col-sm-12'}), - div ({className: 'pull-right'}) (Spinner ({style: {top: 16, width: 42}})) +export const Loading = () => + nest ( + Row ({style: {marginTop: '10em'}}), + Col ({sm: 7, style: {float: 'none', margin: 'auto'}}), + Well ({bsSize: 'lg', style: {paddingTop: '0px'}}) ( + nest ( + Row ({style: {marginTop: 0, marginBottom: 10}}), + Col ({sm: 12}), + h2 ('Welcome back!') + ), + nest (Row, Col ({sm: 12}), p ('Please hang tight while we load your app.')), + nest ( + Row, + Col ({sm: 12}), + div ({className: 'pull-right'}) (Spinner ({style: {top: 16, width: 42}})) + ) ) - ) -) + ) () ``` From eaa2dea1a442851b149b7f3b8e81d709a41e4f12 Mon Sep 17 00:00:00 2001 From: Richard Forrester Date: Sun, 21 Jul 2019 23:56:46 -1000 Subject: [PATCH 08/11] fix README re jsx example` --- README.md | 42 +++++++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index c8ad869..fcdc301 100644 --- a/README.md +++ b/README.md @@ -325,27 +325,31 @@ const Root = ({ store }) => JSX: ```jsx export const Loading = () => ( -

-
-
-
-

Welcome back!

-
- -
-

Please hang tight while we load your app.

-
- -
-
+ + + + + +

Welcome back!

+ +
+ + + +

Please hang tight while we load your app.

+ +
+ + +
- +
-
-
-
-
-
+ + + + + ) ``` NJSX nested: From b67239e9f2f37be970278d6720f535955c9c9788 Mon Sep 17 00:00:00 2001 From: Richard Forrester Date: Mon, 22 Jul 2019 19:26:30 -1000 Subject: [PATCH 09/11] rebase --- README.md | 108 +++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 91 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index f94de34..3c49f03 100644 --- a/README.md +++ b/README.md @@ -303,32 +303,106 @@ If you rather all your arguments to just be interpreted as they are, you can dis ## Point-free -Think point-free composition in your render function is a `pipe` dream? Think again, you can use `njsx` to compose components in a point-free style to help with the readability of deeply nested react components: +Think point-free composition in your render is a `pipe` dream? Think again! You can use `njsx` to compose components in a point-free style to increase the readability of deeply nested components: ```jsx - - - - - - - +const Root = ({ store }) => ( + + + + + + + +) ``` Becomes: ```js -import { compose } from 'rambda' - -compose( - Provider({ store }), - PersistGate({ loading: null, persistor }), - BrowserRouter, - Route -)({ path: '/', component: App })() +import { nest } from 'njsx' + +const Root = ({ store }) => + nest( + Provider({ store }), + PersistGate({ loading: null, persistor }), + Router({ history }), + Route({ path: '/', component: App }) + )() +``` + +## Example Refactoring +JSX: +```jsx +export const Loading = () => ( + + + + + +

Welcome back!

+ +
+ + + +

Please hang tight while we load your app.

+ +
+ + + +
+ +
+ +
+
+ +
+) +``` +NJSX nested: +```js +export const Loading = () => + Row ({style: {marginTop: '10em'}}) ( + Col ({sm: 7, style: {float: 'none', margin: 'auto'}}) ( + Well ({bsSize: 'lg', style: {paddingTop: '0px'}}) ( + Row ({style: {marginTop: 0, marginBottom: 10}}) ( + Col ({sm: 12}) (h2 ('Welcome back!')) + ), + Row (Col ({sm: 12}) (p ('Please hang tight while we load your app.'))), + Row ( + Col ({sm: 12}) ( + div ({className: 'pull-right'}) (Spinner ({style: {top: 16, width: 42}})) + ) + ) + ) + ) + ) () ``` +NJSX composed: +```js +export const Loading = () => + nest ( + Row ({style: {marginTop: '10em'}}), + Col ({sm: 7, style: {float: 'none', margin: 'auto'}}), + Well ({bsSize: 'lg', style: {paddingTop: '0px'}}) ( + nest ( + Row ({style: {marginTop: 0, marginBottom: 10}}), + Col ({sm: 12}), + h2 ('Welcome back!') + ), + nest (Row, Col ({sm: 12}), p ('Please hang tight while we load your app.')), + nest ( + Row, + Col ({sm: 12}), + div ({className: 'pull-right'}) (Spinner ({style: {top: 16, width: 42}})) + ) + ) + ) () -Please note that `compose` and `pipe` functions vary in implementation and not all will work with `njsx`, for example, `lodash/fp` seems to have issues at the moment, while `rambda` is working without issue. +``` ## Working with older versions From 3e72053069955fe6b38bad8904a2ce82ecff8937 Mon Sep 17 00:00:00 2001 From: Richard Forrester Date: Mon, 22 Jul 2019 19:28:42 -1000 Subject: [PATCH 10/11] rebase --- src/index.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/index.ts b/src/index.ts index 50380a4..28d9557 100644 --- a/src/index.ts +++ b/src/index.ts @@ -98,4 +98,19 @@ function addChild

(state: BuilderState

, child: ReactNode) { return assign({}, state, { children: [...state.children || [], child] }) } +// ══════════════════════════════════════════════════════════════════════════════════════ +// Compose (nest) +// ══════════════════════════════════════════════════════════════════════════════════════ + +type nest = (x: Builder, ...xs: Builder[]) => Builder + +export const nest: nest = (...xs: Builder[]): Builder => + xs + .slice(0, -1) + .reverse() + .reduce( + (r: Builder, y: Builder): Builder => y(r), + xs.slice(-1)[0] + ) + export default njsx as NJSX \ No newline at end of file From 57a31aae04c110f8bf3f826731488349b6ddcf02 Mon Sep 17 00:00:00 2001 From: Richard Forrester Date: Mon, 22 Jul 2019 19:42:14 -1000 Subject: [PATCH 11/11] add toc reference and remove comma --- README.md | 1 + src/index.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 3c49f03..0a6f2c4 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,7 @@ const myView = () => - [Dynamic Selectors](#dynamic-selectors) - [Argument Transformation](#argument-transformation) - [Point-free](#point-free) + - [Example Refactoring](#example-refactoring) - [Working with older versions](#working-with-older-versions) - [Contributions](#contributions) - [License](#license) diff --git a/src/index.ts b/src/index.ts index b9f367b..e6e1193 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,4 @@ -import { createElement, ReactChild, ReactElement, ReactNode, ReactType } from 'react'; +import { createElement, ReactChild, ReactElement, ReactNode, ReactType } from 'react' // TODO: Perhaps we could add an example project // TODO: Replace with spread operator once Typescript suports spread of generics (https://github.com/Microsoft/TypeScript/pull/13288)