├── dist ├── coroutines.js ├── es6 │ ├── is-object.js │ ├── yastjson │ │ └── lib │ │ │ ├── yielder.js │ │ │ ├── expression.js │ │ │ ├── token.js │ │ │ └── parse.js │ ├── concat-async.js │ ├── map-async.js │ ├── append-async.js │ ├── filter-async.js │ ├── index-of-async.js │ ├── find-async.js │ ├── for-each-async.js │ ├── last-index-of-async.js │ ├── call.js │ ├── reduce-async.js │ ├── includes-async.js │ ├── index-of.js │ ├── find-index-async.js │ ├── useInternalEngine.js │ ├── includes.js │ ├── some-async.js │ ├── last-index-of.js │ ├── async-wrapper-utils.js │ ├── key-by-async.js │ ├── group-by-async.js │ ├── unique-by-async.js │ ├── map.js │ ├── every.js │ ├── append.js │ ├── some.js │ ├── async-json-wrappers.js │ ├── branch.js │ ├── tap.js │ ├── async-array-wrappers.js │ ├── concat.js │ ├── find-index.js │ ├── repeat.js │ ├── sort-async.js │ ├── key-by.js │ ├── find.js │ ├── reduce.js │ ├── async-wrappers.js │ ├── group-by.js │ ├── array-utilities.js │ ├── filter.js │ ├── pipe.js │ ├── unique-by.js │ ├── compose.js │ ├── for-each.js │ ├── singleton.js │ ├── coroutines.js │ ├── wrappers.js │ └── update.js ├── yastjson │ └── lib │ │ ├── yielder.js │ │ ├── expression.js │ │ └── token.js ├── sort-async.js ├── append-async.js ├── concat-async.js ├── map-async.js ├── find-async.js ├── some-async.js ├── key-by-async.js ├── async-array-wrappers.js ├── filter-async.js ├── reduce-async.js ├── call.js ├── for-each-async.js ├── group-by-async.js ├── index-of-async.js ├── includes-async.js ├── unique-by-async.js ├── find-index-async.js ├── is-object.js ├── last-index-of-async.js ├── branch.js ├── useInternalEngine.js ├── async-json-wrappers.js ├── singleton.js ├── array-utilities.js ├── async-wrapper-utils.js ├── index-of.js ├── includes.js ├── last-index-of.js ├── append.js ├── key-by.js ├── concat.js ├── tap.js ├── map.js ├── reduce.js ├── some.js ├── every.js ├── find.js ├── repeat.js ├── find-index.js ├── compose.js ├── for-each.js ├── filter.js ├── wrappers.js ├── run.js ├── group-by.js ├── unique-by.js ├── update.js ├── polyfill.js ├── pipe.js ├── async-compression-wrappers.js └── json.js ├── _config.yml ├── .gitattributes ├── public ├── favicon.ico ├── logo192.png ├── logo512.png ├── robots.txt ├── manifest.json └── index.html ├── src ├── component │ ├── is-object.js │ ├── yastjson │ │ └── lib │ │ │ ├── yielder.js │ │ │ ├── expression.js │ │ │ ├── token.js │ │ │ └── parse.js │ ├── concat-async.js │ ├── map-async.js │ ├── append-async.js │ ├── filter-async.js │ ├── index-of-async.js │ ├── find-async.js │ ├── for-each-async.js │ ├── last-index-of-async.js │ ├── call.js │ ├── reduce-async.js │ ├── includes-async.js │ ├── index-of.js │ ├── find-index-async.js │ ├── useInternalEngine.js │ ├── includes.js │ ├── some-async.js │ ├── last-index-of.js │ ├── async-wrapper-utils.js │ ├── key-by-async.js │ ├── group-by-async.js │ ├── unique-by-async.js │ ├── map.js │ ├── every.js │ ├── append.js │ ├── some.js │ ├── async-json-wrappers.js │ ├── branch.js │ ├── tap.js │ ├── async-array-wrappers.js │ ├── concat.js │ ├── find-index.js │ ├── repeat.js │ ├── sort-async.js │ ├── key-by.js │ ├── find.js │ ├── reduce.js │ ├── async-wrappers.js │ ├── group-by.js │ ├── array-utilities.js │ ├── filter.js │ ├── pipe.js │ ├── unique-by.js │ ├── compose.js │ ├── for-each.js │ ├── singleton.js │ ├── coroutines.js │ ├── wrappers.js │ └── update.js ├── setupTests.js ├── App.test.js ├── test │ ├── basic-express.js │ ├── array-async.test.js │ ├── compression.test.js │ ├── sort.test.js │ ├── json.test.js │ └── functional.test.js ├── index.css ├── index.js ├── App.css └── logo.svg ├── .idea ├── .gitignore ├── codeStyles │ └── codeStyleConfig.xml ├── vcs.xml ├── misc.xml ├── inspectionProfiles │ └── Project_Default.xml ├── modules.xml └── js-coroutines.iml ├── template ├── tmpl │ ├── example.tmpl │ ├── source.tmpl │ ├── mainpage.tmpl │ ├── augments.tmpl │ ├── augments-spread.tmpl │ ├── type.tmpl │ ├── type-spread.tmpl │ ├── examples.tmpl │ ├── returns.tmpl │ ├── tutorial.tmpl │ ├── exceptions.tmpl │ ├── members.tmpl │ ├── properties.tmpl │ └── params.tmpl ├── static │ ├── fonts │ │ ├── OpenSans-Bold-webfont.eot │ │ ├── OpenSans-Bold-webfont.woff │ │ ├── OpenSans-Italic-webfont.eot │ │ ├── OpenSans-Light-webfont.eot │ │ ├── OpenSans-Light-webfont.woff │ │ ├── OpenSans-Italic-webfont.woff │ │ ├── OpenSans-Regular-webfont.eot │ │ ├── OpenSans-Regular-webfont.woff │ │ ├── OpenSans-Semibold-webfont.eot │ │ ├── OpenSans-Semibold-webfont.ttf │ │ ├── OpenSans-BoldItalic-webfont.eot │ │ ├── OpenSans-BoldItalic-webfont.woff │ │ ├── OpenSans-LightItalic-webfont.eot │ │ ├── OpenSans-Semibold-webfont.woff │ │ ├── OpenSans-LightItalic-webfont.woff │ │ ├── OpenSans-SemiboldItalic-webfont.eot │ │ ├── OpenSans-SemiboldItalic-webfont.ttf │ │ └── OpenSans-SemiboldItalic-webfont.woff │ ├── icons │ │ ├── home.svg │ │ └── search.svg │ ├── styles │ │ ├── collapse.css │ │ ├── prettify-jsdoc.css │ │ └── prettify-tomorrow.css │ └── scripts │ │ ├── linenumber.js │ │ └── pagelocation.js └── LICENSE ├── docs ├── fonts │ ├── Montserrat │ │ ├── Montserrat-Bold.eot │ │ ├── Montserrat-Bold.ttf │ │ ├── Montserrat-Bold.woff │ │ ├── Montserrat-Bold.woff2 │ │ ├── Montserrat-Regular.eot │ │ ├── Montserrat-Regular.ttf │ │ ├── Montserrat-Regular.woff │ │ └── Montserrat-Regular.woff2 │ └── Source-Sans-Pro │ │ ├── sourcesanspro-light-webfont.eot │ │ ├── sourcesanspro-light-webfont.ttf │ │ ├── sourcesanspro-light-webfont.woff │ │ ├── sourcesanspro-light-webfont.woff2 │ │ ├── sourcesanspro-regular-webfont.eot │ │ ├── sourcesanspro-regular-webfont.ttf │ │ ├── sourcesanspro-regular-webfont.woff │ │ └── sourcesanspro-regular-webfont.woff2 ├── scripts │ ├── polyfill.js │ ├── nav.js │ ├── linenumber.js │ ├── collapse.js │ ├── prettify │ │ └── lang-css.js │ └── search.js └── styles │ └── prettify.css ├── scripts └── build.sh ├── .prettierrc ├── .gitignore ├── .babelrc ├── CONTRIBUTING.md ├── .github └── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md ├── mocha.wallaby.js ├── doc.conf.json ├── PULL_REQUEST_TEMPLATE.md └── package.json /dist/coroutines.js: -------------------------------------------------------------------------------- 1 | "use strict"; -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketalbot/js-coroutines/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketalbot/js-coroutines/HEAD/public/logo192.png -------------------------------------------------------------------------------- /public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketalbot/js-coroutines/HEAD/public/logo512.png -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /dist/es6/is-object.js: -------------------------------------------------------------------------------- 1 | export function isObject(v) { 2 | return typeof v === 'object' && !Array.isArray(v) 3 | } 4 | -------------------------------------------------------------------------------- /src/component/is-object.js: -------------------------------------------------------------------------------- 1 | export function isObject(v) { 2 | return typeof v === 'object' && !Array.isArray(v) 3 | } 4 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | -------------------------------------------------------------------------------- /template/tmpl/example.tmpl: -------------------------------------------------------------------------------- 1 | 2 |
3 | -------------------------------------------------------------------------------- /docs/fonts/Montserrat/Montserrat-Bold.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketalbot/js-coroutines/HEAD/docs/fonts/Montserrat/Montserrat-Bold.eot -------------------------------------------------------------------------------- /docs/fonts/Montserrat/Montserrat-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketalbot/js-coroutines/HEAD/docs/fonts/Montserrat/Montserrat-Bold.ttf -------------------------------------------------------------------------------- /docs/fonts/Montserrat/Montserrat-Bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketalbot/js-coroutines/HEAD/docs/fonts/Montserrat/Montserrat-Bold.woff -------------------------------------------------------------------------------- /docs/fonts/Montserrat/Montserrat-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketalbot/js-coroutines/HEAD/docs/fonts/Montserrat/Montserrat-Bold.woff2 -------------------------------------------------------------------------------- /docs/fonts/Montserrat/Montserrat-Regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketalbot/js-coroutines/HEAD/docs/fonts/Montserrat/Montserrat-Regular.eot -------------------------------------------------------------------------------- /docs/fonts/Montserrat/Montserrat-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketalbot/js-coroutines/HEAD/docs/fonts/Montserrat/Montserrat-Regular.ttf -------------------------------------------------------------------------------- /docs/fonts/Montserrat/Montserrat-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketalbot/js-coroutines/HEAD/docs/fonts/Montserrat/Montserrat-Regular.woff -------------------------------------------------------------------------------- /docs/fonts/Montserrat/Montserrat-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketalbot/js-coroutines/HEAD/docs/fonts/Montserrat/Montserrat-Regular.woff2 -------------------------------------------------------------------------------- /template/static/fonts/OpenSans-Bold-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketalbot/js-coroutines/HEAD/template/static/fonts/OpenSans-Bold-webfont.eot -------------------------------------------------------------------------------- /template/static/fonts/OpenSans-Bold-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketalbot/js-coroutines/HEAD/template/static/fonts/OpenSans-Bold-webfont.woff -------------------------------------------------------------------------------- /template/static/fonts/OpenSans-Italic-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketalbot/js-coroutines/HEAD/template/static/fonts/OpenSans-Italic-webfont.eot -------------------------------------------------------------------------------- /template/static/fonts/OpenSans-Light-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketalbot/js-coroutines/HEAD/template/static/fonts/OpenSans-Light-webfont.eot -------------------------------------------------------------------------------- /template/static/fonts/OpenSans-Light-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketalbot/js-coroutines/HEAD/template/static/fonts/OpenSans-Light-webfont.woff -------------------------------------------------------------------------------- /template/static/fonts/OpenSans-Italic-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketalbot/js-coroutines/HEAD/template/static/fonts/OpenSans-Italic-webfont.woff -------------------------------------------------------------------------------- /template/static/fonts/OpenSans-Regular-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketalbot/js-coroutines/HEAD/template/static/fonts/OpenSans-Regular-webfont.eot -------------------------------------------------------------------------------- /template/static/fonts/OpenSans-Regular-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketalbot/js-coroutines/HEAD/template/static/fonts/OpenSans-Regular-webfont.woff -------------------------------------------------------------------------------- /template/static/fonts/OpenSans-Semibold-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketalbot/js-coroutines/HEAD/template/static/fonts/OpenSans-Semibold-webfont.eot -------------------------------------------------------------------------------- /template/static/fonts/OpenSans-Semibold-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketalbot/js-coroutines/HEAD/template/static/fonts/OpenSans-Semibold-webfont.ttf -------------------------------------------------------------------------------- /template/static/fonts/OpenSans-BoldItalic-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketalbot/js-coroutines/HEAD/template/static/fonts/OpenSans-BoldItalic-webfont.eot -------------------------------------------------------------------------------- /template/static/fonts/OpenSans-BoldItalic-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketalbot/js-coroutines/HEAD/template/static/fonts/OpenSans-BoldItalic-webfont.woff -------------------------------------------------------------------------------- /template/static/fonts/OpenSans-LightItalic-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketalbot/js-coroutines/HEAD/template/static/fonts/OpenSans-LightItalic-webfont.eot -------------------------------------------------------------------------------- /template/static/fonts/OpenSans-Semibold-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketalbot/js-coroutines/HEAD/template/static/fonts/OpenSans-Semibold-webfont.woff -------------------------------------------------------------------------------- /template/static/fonts/OpenSans-LightItalic-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketalbot/js-coroutines/HEAD/template/static/fonts/OpenSans-LightItalic-webfont.woff -------------------------------------------------------------------------------- /docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketalbot/js-coroutines/HEAD/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.eot -------------------------------------------------------------------------------- /docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketalbot/js-coroutines/HEAD/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.ttf -------------------------------------------------------------------------------- /docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketalbot/js-coroutines/HEAD/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff -------------------------------------------------------------------------------- /template/static/fonts/OpenSans-SemiboldItalic-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketalbot/js-coroutines/HEAD/template/static/fonts/OpenSans-SemiboldItalic-webfont.eot -------------------------------------------------------------------------------- /template/static/fonts/OpenSans-SemiboldItalic-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketalbot/js-coroutines/HEAD/template/static/fonts/OpenSans-SemiboldItalic-webfont.ttf -------------------------------------------------------------------------------- /template/static/fonts/OpenSans-SemiboldItalic-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketalbot/js-coroutines/HEAD/template/static/fonts/OpenSans-SemiboldItalic-webfont.woff -------------------------------------------------------------------------------- /docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketalbot/js-coroutines/HEAD/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff2 -------------------------------------------------------------------------------- /docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketalbot/js-coroutines/HEAD/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.eot -------------------------------------------------------------------------------- /docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketalbot/js-coroutines/HEAD/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.ttf -------------------------------------------------------------------------------- /docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketalbot/js-coroutines/HEAD/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff -------------------------------------------------------------------------------- /docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miketalbot/js-coroutines/HEAD/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff2 -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /dist/es6/yastjson/lib/yielder.js: -------------------------------------------------------------------------------- 1 | let yieldCount = 0; 2 | export function yielder() { 3 | if (yieldCount++ > 100) { 4 | yieldCount = 0; 5 | return true; 6 | } 7 | return false; 8 | } 9 | -------------------------------------------------------------------------------- /dist/yastjson/lib/yielder.js: -------------------------------------------------------------------------------- 1 | "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.yielder=yielder;var yieldCount=0;function yielder(){return!!(100 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /src/component/yastjson/lib/yielder.js: -------------------------------------------------------------------------------- 1 | let yieldCount = 0; 2 | export function yielder() { 3 | if (yieldCount++ > 100) { 4 | yieldCount = 0; 5 | return true; 6 | } 7 | return false; 8 | } 9 | -------------------------------------------------------------------------------- /dist/yastjson/lib/expression.js: -------------------------------------------------------------------------------- 1 | "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.ExprType=void 0;var ExprType={Json:"j",Array:"a",Object:"o",Prop:"p",Value:"v"};exports.ExprType=ExprType; -------------------------------------------------------------------------------- /template/tmpl/source.tmpl: -------------------------------------------------------------------------------- 1 | 4 | 5 |
6 |
7 |
8 |
9 |
10 | -------------------------------------------------------------------------------- /template/tmpl/mainpage.tmpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 |
6 | 7 |
8 |
9 | 10 | -------------------------------------------------------------------------------- /template/static/icons/home.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /scripts/build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | rm -rf dist 4 | NODE_ENV=production babel src/component --ignore "__tests__","**/*.spec.js","**/*.test.js","__snapshots__" --out-dir dist 5 | cp -r src/component dist/es6 6 | rm -rf dist/es6/yastjson/test 7 | -------------------------------------------------------------------------------- /dist/sort-async.js: -------------------------------------------------------------------------------- 1 | "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.sortAsync=void 0;var _wrappers=require("./wrappers"),_timsort=require("./timsort"),sortAsync=(0,_wrappers.wrapAsPromise)(_timsort.sort);exports.sortAsync=sortAsync; -------------------------------------------------------------------------------- /dist/append-async.js: -------------------------------------------------------------------------------- 1 | "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.appendAsync=void 0;var _wrappers=require("./wrappers"),_append=require("./append"),appendAsync=(0,_wrappers.wrapAsPromise)(_append.append);exports.appendAsync=appendAsync; -------------------------------------------------------------------------------- /dist/concat-async.js: -------------------------------------------------------------------------------- 1 | "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.concatAsync=void 0;var _wrappers=require("./wrappers"),_concat=require("./concat"),concatAsync=(0,_wrappers.wrapAsPromise)(_concat.concat);exports.concatAsync=concatAsync; -------------------------------------------------------------------------------- /docs/scripts/polyfill.js: -------------------------------------------------------------------------------- 1 | //IE Fix, src: https://www.reddit.com/r/programminghorror/comments/6abmcr/nodelist_lacks_foreach_in_internet_explorer/ 2 | if (typeof(NodeList.prototype.forEach)!==typeof(alert)){ 3 | NodeList.prototype.forEach=Array.prototype.forEach; 4 | } -------------------------------------------------------------------------------- /dist/map-async.js: -------------------------------------------------------------------------------- 1 | "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.mapAsync=void 0;var _asyncWrapperUtils=require("./async-wrapper-utils"),_map=require("./map"),mapAsync=(0,_asyncWrapperUtils.wrapAsPromiseAndYieldFn)(_map.map);exports.mapAsync=mapAsync; -------------------------------------------------------------------------------- /dist/find-async.js: -------------------------------------------------------------------------------- 1 | "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.findAsync=void 0;var _asyncWrapperUtils=require("./async-wrapper-utils"),_find=require("./find"),findAsync=(0,_asyncWrapperUtils.wrapAsPromiseAndYieldFn)(_find.find);exports.findAsync=findAsync; -------------------------------------------------------------------------------- /dist/some-async.js: -------------------------------------------------------------------------------- 1 | "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.someAsync=void 0;var _asyncWrapperUtils=require("./async-wrapper-utils"),_some=require("./some"),someAsync=(0,_asyncWrapperUtils.wrapAsPromiseAndYieldFn)(_some.some);exports.someAsync=someAsync; -------------------------------------------------------------------------------- /dist/yastjson/lib/token.js: -------------------------------------------------------------------------------- 1 | "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.TokenType=void 0;var TokenType={LeftBrace:"{",RightBrace:"}",LeftBracket:"l",RightBracket:"r",Comma:"c",Colon:"n",Null:"0",Boolean:"t",Number:"n",String:"s"};exports.TokenType=TokenType; -------------------------------------------------------------------------------- /src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect'; 6 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "useTabs": false, 3 | "printWidth": 120, 4 | "tabWidth": 4, 5 | "singleQuote": true, 6 | "trailingComma": "es5", 7 | "jsxBracketSameLine": false, 8 | "arrowParens": "always", 9 | "semi": false, 10 | "bracketSpacing": true 11 | } 12 | -------------------------------------------------------------------------------- /template/tmpl/augments.tmpl: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /dist/key-by-async.js: -------------------------------------------------------------------------------- 1 | "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.keyByAsync=void 0;var _asyncWrapperUtils=require("./async-wrapper-utils"),_keyBy=require("./key-by"),keyByAsync=(0,_asyncWrapperUtils.wrapAsPromiseAndYieldFn)(_keyBy.keyBy);exports.keyByAsync=keyByAsync; -------------------------------------------------------------------------------- /dist/async-array-wrappers.js: -------------------------------------------------------------------------------- 1 | "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.everyAsync=void 0;var _asyncWrapperUtils=require("./async-wrapper-utils"),_every=require("./every"),everyAsync=(0,_asyncWrapperUtils.wrapAsPromiseAndYieldFn)(_every.every);exports.everyAsync=everyAsync; -------------------------------------------------------------------------------- /dist/filter-async.js: -------------------------------------------------------------------------------- 1 | "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.filterAsync=void 0;var _asyncWrapperUtils=require("./async-wrapper-utils"),_filter=require("./filter"),filterAsync=(0,_asyncWrapperUtils.wrapAsPromiseAndYieldFn)(_filter.filter);exports.filterAsync=filterAsync; -------------------------------------------------------------------------------- /dist/reduce-async.js: -------------------------------------------------------------------------------- 1 | "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.reduceAsync=void 0;var _asyncWrapperUtils=require("./async-wrapper-utils"),_reduce=require("./reduce"),reduceAsync=(0,_asyncWrapperUtils.wrapAsPromiseAndYieldFn)(_reduce.reduce);exports.reduceAsync=reduceAsync; -------------------------------------------------------------------------------- /template/tmpl/augments-spread.tmpl: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /dist/call.js: -------------------------------------------------------------------------------- 1 | "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.call=call;function call(a){for(var b=arguments.length,c=Array(1 6 | 7 | 8 | 9 | 10 | | 11 | 12 | -------------------------------------------------------------------------------- /dist/includes-async.js: -------------------------------------------------------------------------------- 1 | "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.includesAsync=void 0;var _asyncWrapperUtils=require("./async-wrapper-utils"),_includes=require("./includes"),includesAsync=(0,_asyncWrapperUtils.wrapAsPromiseAndYieldFn)(_includes.includes);exports.includesAsync=includesAsync; -------------------------------------------------------------------------------- /dist/unique-by-async.js: -------------------------------------------------------------------------------- 1 | "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.uniqueByAsync=void 0;var _asyncWrapperUtils=require("./async-wrapper-utils"),_uniqueBy=require("./unique-by"),uniqueByAsync=(0,_asyncWrapperUtils.wrapAsPromiseAndYieldFn)(_uniqueBy.uniqueBy);exports.uniqueByAsync=uniqueByAsync; -------------------------------------------------------------------------------- /template/tmpl/type-spread.tmpl: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 | 10 | | 11 | 12 | -------------------------------------------------------------------------------- /dist/find-index-async.js: -------------------------------------------------------------------------------- 1 | "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.findIndexAsync=void 0;var _asyncWrapperUtils=require("./async-wrapper-utils"),_findIndex=require("./find-index"),findIndexAsync=(0,_asyncWrapperUtils.wrapAsPromiseAndYieldFn)(_findIndex.findIndex);exports.findIndexAsync=findIndexAsync; -------------------------------------------------------------------------------- /src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from '@testing-library/react'; 3 | import App from './App'; 4 | 5 | test('renders learn react link', () => { 6 | const { getByText } = render(); 7 | const linkElement = getByText(/learn react/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /dist/is-object.js: -------------------------------------------------------------------------------- 1 | "use strict";var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");var _typeof2=_interopRequireDefault(require("@babel/runtime/helpers/typeof"));Object.defineProperty(exports,"__esModule",{value:!0}),exports.isObject=isObject;function isObject(a){return"object"===(0,_typeof2.default)(a)&&!Array.isArray(a)} -------------------------------------------------------------------------------- /dist/last-index-of-async.js: -------------------------------------------------------------------------------- 1 | "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.lastIndexOfAsync=void 0;var _asyncWrapperUtils=require("./async-wrapper-utils"),_lastIndexOf=require("./last-index-of"),lastIndexOfAsync=(0,_asyncWrapperUtils.wrapAsPromiseAndYieldFn)(_lastIndexOf.lastIndexOf);exports.lastIndexOfAsync=lastIndexOfAsync; -------------------------------------------------------------------------------- /src/test/basic-express.js: -------------------------------------------------------------------------------- 1 | const express = require('express') 2 | const app = express() 3 | const port = 3000 4 | 5 | const mapAsync = require('../../dist/index').mapAsync 6 | 7 | app.get('/', (req, res) => { 8 | res.send('Hello World!') 9 | }) 10 | 11 | app.listen(port, () => { 12 | console.log(`Example app listening at http://localhost:${port}`) 13 | }) 14 | -------------------------------------------------------------------------------- /dist/es6/concat-async.js: -------------------------------------------------------------------------------- 1 | import {wrapAsPromise} from './wrappers' 2 | import {concat} from './concat' 3 | 4 | /** 5 | * Concatenates 2 arrays into a new array 6 | * @function concatAsync 7 | * @param {Array} array1 8 | * @param {Array} array2 9 | * @returns {Promise.} a promise for combined array 10 | */ 11 | export const concatAsync = wrapAsPromise(concat) 12 | -------------------------------------------------------------------------------- /dist/branch.js: -------------------------------------------------------------------------------- 1 | "use strict";var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");var _run=_interopRequireDefault(require("./run"));Object.defineProperty(exports,"__esModule",{value:!0}),exports.branch=branch;function branch(a){return function(b){var c=a.call(this,b);return c&&(c.next?(0,_run.default)(c).catch(console.error):c.then&&c.catch(console.error)),b}} -------------------------------------------------------------------------------- /src/component/concat-async.js: -------------------------------------------------------------------------------- 1 | import {wrapAsPromise} from './wrappers' 2 | import {concat} from './concat' 3 | 4 | /** 5 | * Concatenates 2 arrays into a new array 6 | * @function concatAsync 7 | * @param {Array} array1 8 | * @param {Array} array2 9 | * @returns {Promise.} a promise for combined array 10 | */ 11 | export const concatAsync = wrapAsPromise(concat) 12 | -------------------------------------------------------------------------------- /template/tmpl/examples.tmpl: -------------------------------------------------------------------------------- 1 | 8 |

9 | 10 |

11 | 12 | 13 |
14 | 15 | -------------------------------------------------------------------------------- /dist/es6/map-async.js: -------------------------------------------------------------------------------- 1 | import {wrapAsPromiseAndYieldFn} from './async-wrapper-utils' 2 | import {map} from './map' 3 | 4 | /** 5 | * Maps the contents of an array asynchronously 6 | * @function mapAsync 7 | * @param {Array} array 8 | * @param {Map} mapFn 9 | * @returns {Promise.} promise for the mapped array 10 | */ 11 | export const mapAsync = wrapAsPromiseAndYieldFn(map) 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | 12 | # misc 13 | .DS_Store 14 | .env.local 15 | .env.development.local 16 | .env.test.local 17 | .env.production.local 18 | 19 | npm-debug.log* 20 | yarn-debug.log* 21 | yarn-error.log* 22 | -------------------------------------------------------------------------------- /dist/useInternalEngine.js: -------------------------------------------------------------------------------- 1 | "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.useInternalEngine=useInternalEngine,exports.request=void 0;var _polyfill=require("./polyfill"),request="undefined"==typeof window?(0,_polyfill.getNodeCallback)():window.requestIdleCallback;exports.request=request;function useInternalEngine(a){exports.request=request=a?(0,_polyfill.getCallback)():request} -------------------------------------------------------------------------------- /src/component/map-async.js: -------------------------------------------------------------------------------- 1 | import {wrapAsPromiseAndYieldFn} from './async-wrapper-utils' 2 | import {map} from './map' 3 | 4 | /** 5 | * Maps the contents of an array asynchronously 6 | * @function mapAsync 7 | * @param {Array} array 8 | * @param {Map} mapFn 9 | * @returns {Promise.} promise for the mapped array 10 | */ 11 | export const mapAsync = wrapAsPromiseAndYieldFn(map) 12 | -------------------------------------------------------------------------------- /dist/es6/append-async.js: -------------------------------------------------------------------------------- 1 | import {wrapAsPromise} from './wrappers' 2 | import {append} from './append' 3 | 4 | /** 5 | * Appends one array to another asynchronously 6 | * @function appendAsync 7 | * @param {Array} destination 8 | * @param {Array} source 9 | * @returns {Promise.} a promise for destination after appending 10 | */ 11 | export const appendAsync = wrapAsPromise(append) 12 | -------------------------------------------------------------------------------- /dist/es6/filter-async.js: -------------------------------------------------------------------------------- 1 | import {wrapAsPromiseAndYieldFn} from './async-wrapper-utils' 2 | import {filter} from './filter' 3 | 4 | /** 5 | * Filters an array asynchronously 6 | * @function filterAsync 7 | * @param {Array} array 8 | * @param {Filter} filter 9 | * @returns {Promise.} promise for the filtered array 10 | */ 11 | export const filterAsync = wrapAsPromiseAndYieldFn(filter) 12 | -------------------------------------------------------------------------------- /dist/es6/index-of-async.js: -------------------------------------------------------------------------------- 1 | import {wrapAsPromiseAndYieldFn} from './async-wrapper-utils' 2 | import {indexOf} from './index-of' 3 | 4 | /** 5 | * Returns a promise for the first index of an item in an array 6 | * @param array - the array to scan 7 | * @param value - the value to search for 8 | * @returns {Promise} 9 | */ 10 | export const indexOfAsync = wrapAsPromiseAndYieldFn(indexOf) 11 | -------------------------------------------------------------------------------- /src/component/append-async.js: -------------------------------------------------------------------------------- 1 | import {wrapAsPromise} from './wrappers' 2 | import {append} from './append' 3 | 4 | /** 5 | * Appends one array to another asynchronously 6 | * @function appendAsync 7 | * @param {Array} destination 8 | * @param {Array} source 9 | * @returns {Promise.} a promise for destination after appending 10 | */ 11 | export const appendAsync = wrapAsPromise(append) 12 | -------------------------------------------------------------------------------- /src/component/filter-async.js: -------------------------------------------------------------------------------- 1 | import {wrapAsPromiseAndYieldFn} from './async-wrapper-utils' 2 | import {filter} from './filter' 3 | 4 | /** 5 | * Filters an array asynchronously 6 | * @function filterAsync 7 | * @param {Array} array 8 | * @param {Filter} filter 9 | * @returns {Promise.} promise for the filtered array 10 | */ 11 | export const filterAsync = wrapAsPromiseAndYieldFn(filter) 12 | -------------------------------------------------------------------------------- /src/component/index-of-async.js: -------------------------------------------------------------------------------- 1 | import {wrapAsPromiseAndYieldFn} from './async-wrapper-utils' 2 | import {indexOf} from './index-of' 3 | 4 | /** 5 | * Returns a promise for the first index of an item in an array 6 | * @param array - the array to scan 7 | * @param value - the value to search for 8 | * @returns {Promise} 9 | */ 10 | export const indexOfAsync = wrapAsPromiseAndYieldFn(indexOf) 11 | -------------------------------------------------------------------------------- /template/tmpl/returns.tmpl: -------------------------------------------------------------------------------- 1 | 5 |
6 | 7 |
8 | 9 | 10 | 11 |
12 |
Type
13 |
14 | 15 |
16 |
17 | 18 | -------------------------------------------------------------------------------- /dist/async-json-wrappers.js: -------------------------------------------------------------------------------- 1 | "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.parseAsync=exports.stringifyAsync=void 0;var _wrappers=require("./wrappers"),_parse=require("./yastjson/lib/parse"),_json=require("./json"),stringifyAsync=(0,_wrappers.wrapAsPromise)(_json.stringify);exports.stringifyAsync=stringifyAsync;var parseAsync=(0,_wrappers.wrapAsPromise)(_parse.parse);exports.parseAsync=parseAsync; -------------------------------------------------------------------------------- /dist/es6/find-async.js: -------------------------------------------------------------------------------- 1 | import {wrapAsPromiseAndYieldFn} from './async-wrapper-utils' 2 | import {find} from './find' 3 | 4 | /** 5 | * Finds an item in an array asynchronously 6 | * @function findAsync 7 | * @param {Array} array 8 | * @param {Filter} filter 9 | * @returns {Promise.} promise for the item found or null if no match 10 | */ 11 | export const findAsync = wrapAsPromiseAndYieldFn(find) 12 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "comments": false, 3 | "presets": ["@babel/preset-env", "@babel/preset-react", 4 | [ 5 | 'minify', 6 | { 7 | "builtIns": false, 8 | "deadcode": true, 9 | "mangle": { 10 | "exclude": ["r", "o", "n"] 11 | } 12 | } 13 | ]], 14 | "plugins": [ 15 | "@babel/plugin-proposal-class-properties", "@babel/plugin-transform-runtime"] 16 | } 17 | -------------------------------------------------------------------------------- /dist/es6/for-each-async.js: -------------------------------------------------------------------------------- 1 | import {wrapAsPromiseAndYieldFn} from './async-wrapper-utils' 2 | import {forEach} from './for-each' 3 | 4 | /** 5 | * Asynchronously loop over the elements of an array 6 | * @function forEachAsync 7 | * @param {Array} array 8 | * @param {Process} fn 9 | * @returns {Promise} promise for the end of the operation 10 | */ 11 | export const forEachAsync = wrapAsPromiseAndYieldFn(forEach) 12 | -------------------------------------------------------------------------------- /dist/es6/last-index-of-async.js: -------------------------------------------------------------------------------- 1 | import {wrapAsPromiseAndYieldFn} from './async-wrapper-utils' 2 | import {lastIndexOf} from './last-index-of' 3 | 4 | /** 5 | * Returns a promise for the last index of an item in an array 6 | * @param array - the array to scan 7 | * @param value - the value to search for 8 | * @returns {Promise} 9 | */ 10 | export const lastIndexOfAsync = wrapAsPromiseAndYieldFn(lastIndexOf) 11 | -------------------------------------------------------------------------------- /src/component/find-async.js: -------------------------------------------------------------------------------- 1 | import {wrapAsPromiseAndYieldFn} from './async-wrapper-utils' 2 | import {find} from './find' 3 | 4 | /** 5 | * Finds an item in an array asynchronously 6 | * @function findAsync 7 | * @param {Array} array 8 | * @param {Filter} filter 9 | * @returns {Promise.} promise for the item found or null if no match 10 | */ 11 | export const findAsync = wrapAsPromiseAndYieldFn(find) 12 | -------------------------------------------------------------------------------- /src/component/for-each-async.js: -------------------------------------------------------------------------------- 1 | import {wrapAsPromiseAndYieldFn} from './async-wrapper-utils' 2 | import {forEach} from './for-each' 3 | 4 | /** 5 | * Asynchronously loop over the elements of an array 6 | * @function forEachAsync 7 | * @param {Array} array 8 | * @param {Process} fn 9 | * @returns {Promise} promise for the end of the operation 10 | */ 11 | export const forEachAsync = wrapAsPromiseAndYieldFn(forEach) 12 | -------------------------------------------------------------------------------- /src/component/last-index-of-async.js: -------------------------------------------------------------------------------- 1 | import {wrapAsPromiseAndYieldFn} from './async-wrapper-utils' 2 | import {lastIndexOf} from './last-index-of' 3 | 4 | /** 5 | * Returns a promise for the last index of an item in an array 6 | * @param array - the array to scan 7 | * @param value - the value to search for 8 | * @returns {Promise} 9 | */ 10 | export const lastIndexOfAsync = wrapAsPromiseAndYieldFn(lastIndexOf) 11 | -------------------------------------------------------------------------------- /template/static/icons/search.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /docs/scripts/nav.js: -------------------------------------------------------------------------------- 1 | function scrollToNavItem() { 2 | var path = window.location.href.split('/').pop().replace(/\.html/, ''); 3 | document.querySelectorAll('nav a').forEach(function(link) { 4 | var href = link.attributes.href.value.replace(/\.html/, ''); 5 | if (path === href) { 6 | link.scrollIntoView({block: 'center'}); 7 | return; 8 | } 9 | }) 10 | } 11 | 12 | scrollToNavItem(); 13 | -------------------------------------------------------------------------------- /dist/es6/call.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Create a version of a function with its end 3 | * parameters supplied 4 | * @param {Function|GeneratorFunction|AsyncFunction} fn - the function to configure 5 | * @param {...any[]} config - the additional parameters to pass 6 | * @returns {Function} 7 | */ 8 | export function call(fn, ...config) { 9 | return function (...params) { 10 | return fn.apply(this, [...params, ...config]) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /dist/es6/reduce-async.js: -------------------------------------------------------------------------------- 1 | import {wrapAsPromiseAndYieldFn} from './async-wrapper-utils' 2 | import {reduce} from './reduce' 3 | 4 | /** 5 | * Performs a reduce on an array asynchronously 6 | * @function reduceAsync 7 | * @param {Array} array 8 | * @param {Reduce} reduceFn 9 | * @param {any} initialValue 10 | * @returns {Promise.} a promise for the reduced value 11 | */ 12 | export const reduceAsync = wrapAsPromiseAndYieldFn(reduce) 13 | -------------------------------------------------------------------------------- /src/component/call.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Create a version of a function with its end 3 | * parameters supplied 4 | * @param {Function|GeneratorFunction|AsyncFunction} fn - the function to configure 5 | * @param {...any[]} config - the additional parameters to pass 6 | * @returns {Function} 7 | */ 8 | export function call(fn, ...config) { 9 | return function (...params) { 10 | return fn.apply(this, [...params, ...config]) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/component/reduce-async.js: -------------------------------------------------------------------------------- 1 | import {wrapAsPromiseAndYieldFn} from './async-wrapper-utils' 2 | import {reduce} from './reduce' 3 | 4 | /** 5 | * Performs a reduce on an array asynchronously 6 | * @function reduceAsync 7 | * @param {Array} array 8 | * @param {Reduce} reduceFn 9 | * @param {any} initialValue 10 | * @returns {Promise.} a promise for the reduced value 11 | */ 12 | export const reduceAsync = wrapAsPromiseAndYieldFn(reduce) 13 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | -------------------------------------------------------------------------------- /dist/es6/includes-async.js: -------------------------------------------------------------------------------- 1 | import {wrapAsPromiseAndYieldFn} from './async-wrapper-utils' 2 | import {includes} from './includes' 3 | 4 | /** 5 | * Returns a promise returning true if an array includes a value 6 | * @param array 7 | * @param value 8 | * @returns Promise 9 | * @example 10 | * if(await includesAsync(someArray, 'error')) { 11 | * ... 12 | * } 13 | */ 14 | export const includesAsync = wrapAsPromiseAndYieldFn(includes) 15 | -------------------------------------------------------------------------------- /dist/es6/index-of.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns a generator for an index of an item in an array 3 | * @param {Array} array - the array to scan 4 | * @param {*} value - the value to search for 5 | * @returns {Generator<*, number, *>} 6 | */ 7 | export function* indexOf(array, value) { 8 | for (let i = 0, l = array.length; i < l; i++) { 9 | if (array[i] === value) return i 10 | if ((i & 63) === 0) yield 11 | } 12 | return -1 13 | } 14 | -------------------------------------------------------------------------------- /src/component/includes-async.js: -------------------------------------------------------------------------------- 1 | import {wrapAsPromiseAndYieldFn} from './async-wrapper-utils' 2 | import {includes} from './includes' 3 | 4 | /** 5 | * Returns a promise returning true if an array includes a value 6 | * @param array 7 | * @param value 8 | * @returns Promise 9 | * @example 10 | * if(await includesAsync(someArray, 'error')) { 11 | * ... 12 | * } 13 | */ 14 | export const includesAsync = wrapAsPromiseAndYieldFn(includes) 15 | -------------------------------------------------------------------------------- /src/component/index-of.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns a generator for an index of an item in an array 3 | * @param {Array} array - the array to scan 4 | * @param {*} value - the value to search for 5 | * @returns {Generator<*, number, *>} 6 | */ 7 | export function* indexOf(array, value) { 8 | for (let i = 0, l = array.length; i < l; i++) { 9 | if (array[i] === value) return i 10 | if ((i & 63) === 0) yield 11 | } 12 | return -1 13 | } 14 | -------------------------------------------------------------------------------- /dist/es6/find-index-async.js: -------------------------------------------------------------------------------- 1 | import {wrapAsPromiseAndYieldFn} from './async-wrapper-utils' 2 | import {findIndex} from './find-index' 3 | 4 | /** 5 | * Finds an item index in an array asynchronously 6 | * @function findIndexAsync 7 | * @param {Array} array 8 | * @param {Filter} filter 9 | * @returns {Promise.} promise for the index of the first item to pass the filter or -1 10 | */ 11 | export const findIndexAsync = wrapAsPromiseAndYieldFn(findIndex) 12 | -------------------------------------------------------------------------------- /dist/singleton.js: -------------------------------------------------------------------------------- 1 | "use strict";var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");var _run=_interopRequireDefault(require("./run"));Object.defineProperty(exports,"__esModule",{value:!0}),exports.singleton=singleton;function singleton(a,b){var c=null,d=[],e=function(){return c&&(d.forEach(function(a){return a.terminate()}),d=[],c.terminate(b)),c=e._promise=(0,_run.default)(a.apply(void 0,arguments))};return e.join=function(a){return d.push(a),a},e} -------------------------------------------------------------------------------- /src/component/find-index-async.js: -------------------------------------------------------------------------------- 1 | import {wrapAsPromiseAndYieldFn} from './async-wrapper-utils' 2 | import {findIndex} from './find-index' 3 | 4 | /** 5 | * Finds an item index in an array asynchronously 6 | * @function findIndexAsync 7 | * @param {Array} array 8 | * @param {Filter} filter 9 | * @returns {Promise.} promise for the index of the first item to pass the filter or -1 10 | */ 11 | export const findIndexAsync = wrapAsPromiseAndYieldFn(findIndex) 12 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /dist/array-utilities.js: -------------------------------------------------------------------------------- 1 | "use strict";var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports,"__esModule",{value:!0}),exports.exitWith=exitWith,exports.doReturn=void 0;var _defineProperty2=_interopRequireDefault(require("@babel/runtime/helpers/defineProperty")),doReturn=Symbol("return");exports.doReturn=doReturn;function exitWith(a){var b;return b={},(0,_defineProperty2.default)(b,doReturn,!0),(0,_defineProperty2.default)(b,"value",a),b} -------------------------------------------------------------------------------- /dist/es6/useInternalEngine.js: -------------------------------------------------------------------------------- 1 | import {getCallback, getNodeCallback} from './polyfill' 2 | 3 | 4 | export let request = typeof window === 'undefined' ? getNodeCallback() : window.requestIdleCallback 5 | 6 | /** 7 | * Call with true to use the polyfilled version of 8 | * the idle callback, can be more stable in certain 9 | * circumstances 10 | * @param {Boolean} internal 11 | */ 12 | export function useInternalEngine(internal) { 13 | request = internal ? getCallback() : request 14 | } 15 | -------------------------------------------------------------------------------- /src/component/useInternalEngine.js: -------------------------------------------------------------------------------- 1 | import {getCallback, getNodeCallback} from './polyfill' 2 | 3 | 4 | export let request = typeof window === 'undefined' ? getNodeCallback() : window.requestIdleCallback 5 | 6 | /** 7 | * Call with true to use the polyfilled version of 8 | * the idle callback, can be more stable in certain 9 | * circumstances 10 | * @param {Boolean} internal 11 | */ 12 | export function useInternalEngine(internal) { 13 | request = internal ? getCallback() : request 14 | } 15 | -------------------------------------------------------------------------------- /dist/es6/includes.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns true if an array includes a value 3 | * @param {Array} array 4 | * @param {any} value 5 | * @returns {Generator<*, boolean, *>} 6 | * @example 7 | * 8 | * prices = price * (yield * includes(items, yielding(v=>v.discount))) ? .4 : 1 9 | */ 10 | export function* includes(array, value) { 11 | for (let i = 0, l = array.length; i < l; i++) { 12 | if (array[i] === value) return true 13 | if ((i & 63) === 0) yield 14 | } 15 | return false 16 | } 17 | -------------------------------------------------------------------------------- /dist/es6/some-async.js: -------------------------------------------------------------------------------- 1 | import {wrapAsPromiseAndYieldFn} from './async-wrapper-utils' 2 | import {some} from './some' 3 | 4 | /** 5 | * Asynchronously apply an array some operation 6 | * returning a promise for true if at least 7 | * one item matches 8 | * @function someAsync 9 | * @param {Array} array 10 | * @param {Filter} fn 11 | * @returns {Promise.} promise for true if at least one item matched the filter 12 | */ 13 | export const someAsync = wrapAsPromiseAndYieldFn(some) 14 | -------------------------------------------------------------------------------- /src/component/includes.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns true if an array includes a value 3 | * @param {Array} array 4 | * @param {any} value 5 | * @returns {Generator<*, boolean, *>} 6 | * @example 7 | * 8 | * prices = price * (yield * includes(items, yielding(v=>v.discount))) ? .4 : 1 9 | */ 10 | export function* includes(array, value) { 11 | for (let i = 0, l = array.length; i < l; i++) { 12 | if (array[i] === value) return true 13 | if ((i & 63) === 0) yield 14 | } 15 | return false 16 | } 17 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | overflow: hidden; 9 | height: 100vh; 10 | position: static; 11 | width: 100vw; 12 | } 13 | 14 | code { 15 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 16 | monospace; 17 | } 18 | -------------------------------------------------------------------------------- /src/component/some-async.js: -------------------------------------------------------------------------------- 1 | import {wrapAsPromiseAndYieldFn} from './async-wrapper-utils' 2 | import {some} from './some' 3 | 4 | /** 5 | * Asynchronously apply an array some operation 6 | * returning a promise for true if at least 7 | * one item matches 8 | * @function someAsync 9 | * @param {Array} array 10 | * @param {Filter} fn 11 | * @returns {Promise.} promise for true if at least one item matched the filter 12 | */ 13 | export const someAsync = wrapAsPromiseAndYieldFn(some) 14 | -------------------------------------------------------------------------------- /template/tmpl/tutorial.tmpl: -------------------------------------------------------------------------------- 1 |
2 |
3 | 0) { ?> 4 |
    5 | 8 |
  • 9 | 10 |
  • 11 | 12 |
13 | 14 | 15 |

16 | 17 |

18 |
19 | 20 |
21 | 22 |
23 |
24 | -------------------------------------------------------------------------------- /template/static/styles/collapse.css: -------------------------------------------------------------------------------- 1 | @media only screen and (min-width: 681px) { 2 | nav > ul > li:hover .methods, 3 | .active .methods { 4 | display: block; 5 | } 6 | 7 | .methods { 8 | display: none; 9 | } 10 | 11 | nav > ul > li { 12 | padding: 20px 0; 13 | } 14 | 15 | nav > ul > li > a { 16 | padding: 0; 17 | } 18 | 19 | nav > ul > li.active a { 20 | margin-bottom: 10px; 21 | } 22 | 23 | nav > ul > li:hover > a, 24 | nav > ul > li.active > a { 25 | margin-bottom: 15px; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /dist/es6/last-index-of.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns a generator for an index of an item in an array 3 | * @param {Array} array - the array to scan 4 | * @param {*} value - the value to search for 5 | * @returns {Generator<*, number, *>} 6 | * @example 7 | * 8 | * let last = yield * lastIndexOf(collection, record) 9 | * 10 | */ 11 | export function* lastIndexOf(array, value) { 12 | for (let i = array.length - 1; i >= 0; i--) { 13 | if (array[i] === value) return i 14 | if ((i & 63) === 0) yield 15 | } 16 | return -1 17 | } 18 | -------------------------------------------------------------------------------- /dist/es6/async-wrapper-utils.js: -------------------------------------------------------------------------------- 1 | import {yielding} from './wrappers' 2 | import run from './run' 3 | import {call} from './call' 4 | 5 | /** 6 | * Create a promised function 7 | * @param {Function} fn 8 | * @returns {Function} 9 | */ 10 | export function wrapAsPromiseAndYieldFn(fn) { 11 | const result = function (array, processor, ...params) { 12 | return run(fn(array, yielding(processor), ...params)) 13 | } 14 | result.with = function (...params) { 15 | return call(result, ...params) 16 | } 17 | return result 18 | } 19 | -------------------------------------------------------------------------------- /src/component/last-index-of.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns a generator for an index of an item in an array 3 | * @param {Array} array - the array to scan 4 | * @param {*} value - the value to search for 5 | * @returns {Generator<*, number, *>} 6 | * @example 7 | * 8 | * let last = yield * lastIndexOf(collection, record) 9 | * 10 | */ 11 | export function* lastIndexOf(array, value) { 12 | for (let i = array.length - 1; i >= 0; i--) { 13 | if (array[i] === value) return i 14 | if ((i & 63) === 0) yield 15 | } 16 | return -1 17 | } 18 | -------------------------------------------------------------------------------- /src/component/async-wrapper-utils.js: -------------------------------------------------------------------------------- 1 | import {yielding} from './wrappers' 2 | import run from './run' 3 | import {call} from './call' 4 | 5 | /** 6 | * Create a promised function 7 | * @param {Function} fn 8 | * @returns {Function} 9 | */ 10 | export function wrapAsPromiseAndYieldFn(fn) { 11 | const result = function (array, processor, ...params) { 12 | return run(fn(array, yielding(processor), ...params)) 13 | } 14 | result.with = function (...params) { 15 | return call(result, ...params) 16 | } 17 | return result 18 | } 19 | -------------------------------------------------------------------------------- /dist/es6/key-by-async.js: -------------------------------------------------------------------------------- 1 | import {wrapAsPromiseAndYieldFn} from './async-wrapper-utils' 2 | import {keyBy} from './key-by' 3 | 4 | /** 5 | * Promises the creation an object composed of keys generated from the results 6 | * of running each element of collection thru then supplied function. 7 | * The corresponding value of each key is the last element responsible 8 | * for generating the key. 9 | * 10 | * @param {Array|Object} collection 11 | * @param {Map} fn 12 | * @returns {Promise<{}>} 13 | */ 14 | export const keyByAsync = wrapAsPromiseAndYieldFn(keyBy) 15 | -------------------------------------------------------------------------------- /src/test/array-async.test.js: -------------------------------------------------------------------------------- 1 | import {reduceAsync} from '../component' 2 | import {should} from 'chai' 3 | 4 | should() 5 | 6 | const INPUT_ARRAY = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20] 7 | 8 | describe("Array async functions", function () { 9 | it("should handle yielding functions", async function () { 10 | let result = await reduceAsync(INPUT_ARRAY, (a,c)=>a+c) 11 | result.should.equal(210) 12 | }) 13 | it("should be able to make a pipeline and execute it", async function () { 14 | 15 | }) 16 | }) 17 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | When contributing to this repository, please first discuss the change you wish to make via issue, email, or any other method with the owners of this repository before making a change. 4 | 5 | Please note we have a code of conduct, please follow it in all your interactions with the project. 6 | 7 | ## Pull Request Process 8 | 9 | Update the CHANGELOG.md with details of changes to the interface, this includes new functions and updates to existing functions. 10 | Increase the version numbers. The versioning scheme we use is SemVer. 11 | -------------------------------------------------------------------------------- /src/component/key-by-async.js: -------------------------------------------------------------------------------- 1 | import {wrapAsPromiseAndYieldFn} from './async-wrapper-utils' 2 | import {keyBy} from './key-by' 3 | 4 | /** 5 | * Promises the creation an object composed of keys generated from the results 6 | * of running each element of collection thru then supplied function. 7 | * The corresponding value of each key is the last element responsible 8 | * for generating the key. 9 | * 10 | * @param {Array|Object} collection 11 | * @param {Map} fn 12 | * @returns {Promise<{}>} 13 | */ 14 | export const keyByAsync = wrapAsPromiseAndYieldFn(keyBy) 15 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | import * as serviceWorker from './serviceWorker'; 6 | 7 | ReactDOM.render( 8 | 9 | 10 | , 11 | document.getElementById('root') 12 | ); 13 | 14 | // If you want your app to work offline and load faster, you can change 15 | // unregister() to register() below. Note this comes with some pitfalls. 16 | // Learn more about service workers: https://bit.ly/CRA-PWA 17 | serviceWorker.unregister(); 18 | -------------------------------------------------------------------------------- /dist/es6/group-by-async.js: -------------------------------------------------------------------------------- 1 | import {wrapAsPromiseAndYieldFn} from './async-wrapper-utils' 2 | import {groupBy} from './group-by' 3 | 4 | /** 5 | * Promises the creation of an object composed of keys generated from the results 6 | * of running each element of collection thru then supplied function. 7 | * The corresponding value of each key is an collection of the elements responsible 8 | * for generating the key. 9 | * 10 | * @param {Array|Object} collection 11 | * @param {Map} fn 12 | * @returns {Promise<{}>} 13 | */ 14 | export const groupByAsync = wrapAsPromiseAndYieldFn(groupBy) 15 | -------------------------------------------------------------------------------- /src/component/group-by-async.js: -------------------------------------------------------------------------------- 1 | import {wrapAsPromiseAndYieldFn} from './async-wrapper-utils' 2 | import {groupBy} from './group-by' 3 | 4 | /** 5 | * Promises the creation of an object composed of keys generated from the results 6 | * of running each element of collection thru then supplied function. 7 | * The corresponding value of each key is an collection of the elements responsible 8 | * for generating the key. 9 | * 10 | * @param {Array|Object} collection 11 | * @param {Map} fn 12 | * @returns {Promise<{}>} 13 | */ 14 | export const groupByAsync = wrapAsPromiseAndYieldFn(groupBy) 15 | -------------------------------------------------------------------------------- /dist/es6/unique-by-async.js: -------------------------------------------------------------------------------- 1 | import {wrapAsPromiseAndYieldFn} from './async-wrapper-utils' 2 | import {uniqueBy} from './unique-by' 3 | 4 | /** 5 | * Promises the creation of an array with the unique values from the 6 | * input array, the routine is supplied with a 7 | * function that determines on what the array should 8 | * be made unique. 9 | * @param {Array} array 10 | * @param {Map} [fn] - the function to determine uniqueness, if 11 | * omitted then the item itself is used 12 | * @returns {Promise} unique array 13 | */ 14 | export const uniqueByAsync = wrapAsPromiseAndYieldFn(uniqueBy) 15 | -------------------------------------------------------------------------------- /src/component/unique-by-async.js: -------------------------------------------------------------------------------- 1 | import {wrapAsPromiseAndYieldFn} from './async-wrapper-utils' 2 | import {uniqueBy} from './unique-by' 3 | 4 | /** 5 | * Promises the creation of an array with the unique values from the 6 | * input array, the routine is supplied with a 7 | * function that determines on what the array should 8 | * be made unique. 9 | * @param {Array} array 10 | * @param {Map} [fn] - the function to determine uniqueness, if 11 | * omitted then the item itself is used 12 | * @returns {Promise} unique array 13 | */ 14 | export const uniqueByAsync = wrapAsPromiseAndYieldFn(uniqueBy) 15 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /dist/es6/map.js: -------------------------------------------------------------------------------- 1 | import {isObject} from './is-object' 2 | import {forEach} from './for-each' 3 | 4 | /** 5 | * @generator 6 | * @param {Array|Object} collection 7 | * @param {Map} fn 8 | * @returns {Generator<*, Array|Object, *>} new collection of mapped values 9 | * @example 10 | * 11 | * const values = yield * map(array, yielding(v=>v ** 2)) 12 | * 13 | */ 14 | export function* map(collection, fn) { 15 | let result = isObject(collection) ? {} : [] 16 | yield* forEach(collection, function* (value, key) { 17 | result[key] = yield* fn(value, key, collection) 18 | }) 19 | return result 20 | } 21 | -------------------------------------------------------------------------------- /src/component/map.js: -------------------------------------------------------------------------------- 1 | import {isObject} from './is-object' 2 | import {forEach} from './for-each' 3 | 4 | /** 5 | * @generator 6 | * @param {Array|Object} collection 7 | * @param {Map} fn 8 | * @returns {Generator<*, Array|Object, *>} new collection of mapped values 9 | * @example 10 | * 11 | * const values = yield * map(array, yielding(v=>v ** 2)) 12 | * 13 | */ 14 | export function* map(collection, fn) { 15 | let result = isObject(collection) ? {} : [] 16 | yield* forEach(collection, function* (value, key) { 17 | result[key] = yield* fn(value, key, collection) 18 | }) 19 | return result 20 | } 21 | -------------------------------------------------------------------------------- /.idea/js-coroutines.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /dist/async-wrapper-utils.js: -------------------------------------------------------------------------------- 1 | "use strict";var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports,"__esModule",{value:!0}),exports.wrapAsPromiseAndYieldFn=wrapAsPromiseAndYieldFn;var _wrappers=require("./wrappers"),_run=_interopRequireDefault(require("./run")),_call=require("./call");function wrapAsPromiseAndYieldFn(a){var b=function(b,c){for(var d=arguments.length,e=Array(2} true if all of the collection items matched the filter 9 | * @example 10 | * 11 | * if(! yield * every(records, yielding(r=>r.valid))) return 12 | */ 13 | export function* every(collection, fn) { 14 | let result = true 15 | yield* forEach(collection, function* (value, key) { 16 | if (!(yield* fn(value, key, collection))) { 17 | result = false 18 | return exitWith(false) 19 | } 20 | }) 21 | return result 22 | } 23 | -------------------------------------------------------------------------------- /dist/es6/append.js: -------------------------------------------------------------------------------- 1 | import {forEach} from './for-each' 2 | import {yielding} from './wrappers' 3 | 4 | /** 5 | * Appends one array to another 6 | * @generator 7 | * @param {Array} array1 - the destination 8 | * @param {Array} array2 - the source 9 | * @returns {Generator<*, Array, *>} returns array1 10 | * @example 11 | * 12 | * // Updates array1 13 | * yield * append(array1, array2) 14 | */ 15 | export function* append(array1, array2) { 16 | const l = array1.length 17 | yield true 18 | array1.length += array2.length 19 | yield 20 | yield* forEach( 21 | array2, 22 | yielding((a, i) => (array1[i + l] = a)) 23 | ) 24 | 25 | return array1 26 | } 27 | -------------------------------------------------------------------------------- /src/component/every.js: -------------------------------------------------------------------------------- 1 | import {forEach} from './for-each' 2 | import {exitWith} from './array-utilities' 3 | 4 | /** 5 | * @generator 6 | * @param {Array|Object} collection 7 | * @param {Filter} fn 8 | * @returns {Generator<*, boolean, *>} true if all of the collection items matched the filter 9 | * @example 10 | * 11 | * if(! yield * every(records, yielding(r=>r.valid))) return 12 | */ 13 | export function* every(collection, fn) { 14 | let result = true 15 | yield* forEach(collection, function* (value, key) { 16 | if (!(yield* fn(value, key, collection))) { 17 | result = false 18 | return exitWith(false) 19 | } 20 | }) 21 | return result 22 | } 23 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /src/component/append.js: -------------------------------------------------------------------------------- 1 | import {forEach} from './for-each' 2 | import {yielding} from './wrappers' 3 | 4 | /** 5 | * Appends one array to another 6 | * @generator 7 | * @param {Array} array1 - the destination 8 | * @param {Array} array2 - the source 9 | * @returns {Generator<*, Array, *>} returns array1 10 | * @example 11 | * 12 | * // Updates array1 13 | * yield * append(array1, array2) 14 | */ 15 | export function* append(array1, array2) { 16 | const l = array1.length 17 | yield true 18 | array1.length += array2.length 19 | yield 20 | yield* forEach( 21 | array2, 22 | yielding((a, i) => (array1[i + l] = a)) 23 | ) 24 | 25 | return array1 26 | } 27 | -------------------------------------------------------------------------------- /dist/es6/some.js: -------------------------------------------------------------------------------- 1 | import {forEach} from './for-each' 2 | import {exitWith} from './array-utilities' 3 | 4 | /** 5 | * @generator 6 | * @param {Array|Object} collection 7 | * @param {Filter} fn 8 | * @returns {Generator<*, boolean, *>} true if at least one item matched the filter 9 | * @example 10 | * 11 | * 12 | * if(yield * some(collection, yielding(v=>v > 2000)) { 13 | * ... 14 | * } 15 | */ 16 | export function* some(collection, fn) { 17 | let result = false 18 | yield* forEach(collection, function* (value, key) { 19 | if (yield* fn(value, key, collection)) { 20 | result = true 21 | return exitWith(true) 22 | } 23 | }) 24 | return result 25 | } 26 | -------------------------------------------------------------------------------- /dist/es6/async-json-wrappers.js: -------------------------------------------------------------------------------- 1 | import {wrapAsPromise} from './wrappers' 2 | import {parse} from './yastjson/lib/parse' 3 | import {stringify} from './json' 4 | 5 | /** 6 | * Asynchronously stringify data into JSON 7 | * @function 8 | * @name stringifyAsync 9 | * @param {any} data - Object to store 10 | * @returns {Promise.} a Promise for the JSON representation of data 11 | */ 12 | export const stringifyAsync = wrapAsPromise(stringify) 13 | /** 14 | * Asynchronously parse JSON into an object 15 | * @function parseAsync 16 | * @param {String} json - the JSON to be parsed 17 | * @returns {Promise.} a Promise for the parsed JSON 18 | */ 19 | export const parseAsync = wrapAsPromise(parse) 20 | -------------------------------------------------------------------------------- /src/component/some.js: -------------------------------------------------------------------------------- 1 | import {forEach} from './for-each' 2 | import {exitWith} from './array-utilities' 3 | 4 | /** 5 | * @generator 6 | * @param {Array|Object} collection 7 | * @param {Filter} fn 8 | * @returns {Generator<*, boolean, *>} true if at least one item matched the filter 9 | * @example 10 | * 11 | * 12 | * if(yield * some(collection, yielding(v=>v > 2000)) { 13 | * ... 14 | * } 15 | */ 16 | export function* some(collection, fn) { 17 | let result = false 18 | yield* forEach(collection, function* (value, key) { 19 | if (yield* fn(value, key, collection)) { 20 | result = true 21 | return exitWith(true) 22 | } 23 | }) 24 | return result 25 | } 26 | -------------------------------------------------------------------------------- /src/component/async-json-wrappers.js: -------------------------------------------------------------------------------- 1 | import {wrapAsPromise} from './wrappers' 2 | import {parse} from './yastjson/lib/parse' 3 | import {stringify} from './json' 4 | 5 | /** 6 | * Asynchronously stringify data into JSON 7 | * @function 8 | * @name stringifyAsync 9 | * @param {any} data - Object to store 10 | * @returns {Promise.} a Promise for the JSON representation of data 11 | */ 12 | export const stringifyAsync = wrapAsPromise(stringify) 13 | /** 14 | * Asynchronously parse JSON into an object 15 | * @function parseAsync 16 | * @param {String} json - the JSON to be parsed 17 | * @returns {Promise.} a Promise for the parsed JSON 18 | */ 19 | export const parseAsync = wrapAsPromise(parse) 20 | -------------------------------------------------------------------------------- /dist/append.js: -------------------------------------------------------------------------------- 1 | "use strict";var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports,"__esModule",{value:!0}),exports.append=append;var _regenerator=_interopRequireDefault(require("@babel/runtime/regenerator")),_forEach=require("./for-each"),_wrappers=require("./wrappers"),_marked=_regenerator.default.mark(append);function append(b,c){var d;return _regenerator.default.wrap(function(a){for(;;)switch(a.prev=a.next){case 0:return d=b.length,a.next=3,!0;case 3:return b.length+=c.length,void(a.next=6);case 6:return a.delegateYield((0,_forEach.forEach)(c,(0,_wrappers.yielding)(function(c,a){return b[a+d]=c})),"t0",7);case 7:return a.abrupt("return",b);case 8:case"end":return a.stop();}},_marked)} -------------------------------------------------------------------------------- /dist/es6/branch.js: -------------------------------------------------------------------------------- 1 | import run from './run' 2 | 3 | /** 4 | * Branches a pipeline by starting another "continuation" with 5 | * the current parameters. Starts a function but the pipeline 6 | * continues immediately creating two execution contexts 7 | * @param {Function} fn - the function to start - can be async or generator 8 | */ 9 | export function branch(fn) { 10 | return function (params) { 11 | let result = fn.call(this, params) 12 | if (result) { 13 | if (result.next) { 14 | run(result).catch(console.error) 15 | } else if (result.then) { 16 | result.catch(console.error) 17 | } 18 | } 19 | return params 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /template/static/scripts/linenumber.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* global document */ 4 | (function () { 5 | var lineId, lines, totalLines, anchorHash; 6 | var source = document.getElementsByClassName('prettyprint source linenums'); 7 | var i = 0; 8 | var lineNumber = 0; 9 | 10 | if (source && source[0]) { 11 | anchorHash = document.location.hash.substring(1); 12 | lines = source[0].getElementsByTagName('li'); 13 | totalLines = lines.length; 14 | 15 | for (; i < totalLines; i++) { 16 | lineNumber++; 17 | lineId = 'line' + lineNumber; 18 | lines[i].id = lineId; 19 | if (lineId === anchorHash) { 20 | lines[i].className += ' selected'; 21 | } 22 | } 23 | } 24 | })(); 25 | -------------------------------------------------------------------------------- /src/component/branch.js: -------------------------------------------------------------------------------- 1 | import run from './run' 2 | 3 | /** 4 | * Branches a pipeline by starting another "continuation" with 5 | * the current parameters. Starts a function but the pipeline 6 | * continues immediately creating two execution contexts 7 | * @param {Function} fn - the function to start - can be async or generator 8 | */ 9 | export function branch(fn) { 10 | return function (params) { 11 | let result = fn.call(this, params) 12 | if (result) { 13 | if (result.next) { 14 | run(result).catch(console.error) 15 | } else if (result.then) { 16 | result.catch(console.error) 17 | } 18 | } 19 | return params 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /dist/es6/tap.js: -------------------------------------------------------------------------------- 1 | import run from './run' 2 | 3 | /** 4 | * Tap into a pipeline to call a function that will probably 5 | * perform side effects but should not modify the result, its 6 | * return value is ignored 7 | * @param {Function} fn - a function to be called at this point in 8 | * the pipeline 9 | * @returns {AsyncFunction} returning the passed in parameters 10 | */ 11 | export function tap(fn) { 12 | return async function (params) { 13 | let result = fn.call(this, params) 14 | if (result) { 15 | if (result.next) { 16 | await run(result) 17 | } else if (result.then) { 18 | await result 19 | } 20 | } 21 | return params 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/component/tap.js: -------------------------------------------------------------------------------- 1 | import run from './run' 2 | 3 | /** 4 | * Tap into a pipeline to call a function that will probably 5 | * perform side effects but should not modify the result, its 6 | * return value is ignored 7 | * @param {Function} fn - a function to be called at this point in 8 | * the pipeline 9 | * @returns {AsyncFunction} returning the passed in parameters 10 | */ 11 | export function tap(fn) { 12 | return async function (params) { 13 | let result = fn.call(this, params) 14 | if (result) { 15 | if (result.next) { 16 | await run(result) 17 | } else if (result.then) { 18 | await result 19 | } 20 | } 21 | return params 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /mocha.wallaby.js: -------------------------------------------------------------------------------- 1 | module.exports = function (wallaby) { 2 | 3 | return { 4 | files: [ 5 | 'src/component/**/*.+(js|jsx|json|snap|css|less|sass|scss|jpg|jpeg|gif|png|svg)', 6 | {pattern: '**/*.js', instrument: false}, 7 | 'docker-compose.yml', 8 | '*.env', 9 | '!**/*.test.js', 10 | '!node_modules/**/*', 11 | ], 12 | 13 | tests: ['src/test/**/*.test.js?(x)'], 14 | 15 | env: { 16 | type: 'node', 17 | runner: 'node', 18 | }, 19 | compilers: { 20 | '**/*.js': wallaby.compilers.babel({ 21 | presets: ['react-app'] 22 | }) 23 | }, 24 | testFramework: 'mocha', 25 | }; 26 | }; 27 | -------------------------------------------------------------------------------- /template/tmpl/exceptions.tmpl: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |
5 |
6 | 7 |
8 |
9 |
10 |
11 |
12 |
Type
13 |
14 | 15 |
16 |
17 |
18 |
19 |
20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | -------------------------------------------------------------------------------- /dist/es6/async-array-wrappers.js: -------------------------------------------------------------------------------- 1 | import {wrapAsPromiseAndYieldFn} from './async-wrapper-utils' 2 | import {every} from './every' 3 | 4 | /** 5 | * Asynchronously check if every element in an array matches 6 | * a predicate 7 | * @function everyAsync 8 | * @param {Array} array 9 | * @param {Filter} fn 10 | * @returns {Promise.} promise for true if all items matched the filter 11 | */ 12 | export const everyAsync = wrapAsPromiseAndYieldFn(every) 13 | 14 | /** 15 | * @callback SortFunction 16 | * @param {any} item1 17 | * @param {any} item2 18 | * @returns < 0 if item 2 is bigger than item 1, === 0 if they are the same else > 0 19 | */ 20 | 21 | /** 22 | * @callback ExtractFunction 23 | * @param {any} item1 24 | * @returns {any} the value to sort item 1 by 25 | */ 26 | 27 | 28 | -------------------------------------------------------------------------------- /dist/es6/concat.js: -------------------------------------------------------------------------------- 1 | import {forEach} from './for-each' 2 | import {yielding} from './wrappers' 3 | 4 | /** 5 | * Concatenate two arrays into a new array 6 | * @generator 7 | * @param {Array} array1 8 | * @param {Array} array2 9 | * @returns {Generator<*, Array, *>} the concatenated arrays 10 | * @example 11 | * 12 | * const concatenated = yield * concat(array1, array2) 13 | */ 14 | export function* concat(array1, array2) { 15 | yield true 16 | const result = new Array(array1.length + array2.length) 17 | yield 18 | const l = array1.length 19 | yield* forEach( 20 | array1, 21 | yielding((a, i) => (result[i] = a)) 22 | ) 23 | yield* forEach( 24 | array2, 25 | yielding((a, i) => (result[i + l] = a)) 26 | ) 27 | return result 28 | } 29 | -------------------------------------------------------------------------------- /docs/scripts/linenumber.js: -------------------------------------------------------------------------------- 1 | /*global document */ 2 | (function() { 3 | var source = document.getElementsByClassName('prettyprint source linenums'); 4 | var i = 0; 5 | var lineNumber = 0; 6 | var lineId; 7 | var lines; 8 | var totalLines; 9 | var anchorHash; 10 | 11 | if (source && source[0]) { 12 | anchorHash = document.location.hash.substring(1); 13 | lines = source[0].getElementsByTagName('li'); 14 | totalLines = lines.length; 15 | 16 | for (; i < totalLines; i++) { 17 | lineNumber++; 18 | lineId = 'line' + lineNumber; 19 | lines[i].id = lineId; 20 | if (lineId === anchorHash) { 21 | lines[i].className += ' selected'; 22 | } 23 | } 24 | } 25 | })(); 26 | -------------------------------------------------------------------------------- /src/component/async-array-wrappers.js: -------------------------------------------------------------------------------- 1 | import {wrapAsPromiseAndYieldFn} from './async-wrapper-utils' 2 | import {every} from './every' 3 | 4 | /** 5 | * Asynchronously check if every element in an array matches 6 | * a predicate 7 | * @function everyAsync 8 | * @param {Array} array 9 | * @param {Filter} fn 10 | * @returns {Promise.} promise for true if all items matched the filter 11 | */ 12 | export const everyAsync = wrapAsPromiseAndYieldFn(every) 13 | 14 | /** 15 | * @callback SortFunction 16 | * @param {any} item1 17 | * @param {any} item2 18 | * @returns < 0 if item 2 is bigger than item 1, === 0 if they are the same else > 0 19 | */ 20 | 21 | /** 22 | * @callback ExtractFunction 23 | * @param {any} item1 24 | * @returns {any} the value to sort item 1 by 25 | */ 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/component/concat.js: -------------------------------------------------------------------------------- 1 | import {forEach} from './for-each' 2 | import {yielding} from './wrappers' 3 | 4 | /** 5 | * Concatenate two arrays into a new array 6 | * @generator 7 | * @param {Array} array1 8 | * @param {Array} array2 9 | * @returns {Generator<*, Array, *>} the concatenated arrays 10 | * @example 11 | * 12 | * const concatenated = yield * concat(array1, array2) 13 | */ 14 | export function* concat(array1, array2) { 15 | yield true 16 | const result = new Array(array1.length + array2.length) 17 | yield 18 | const l = array1.length 19 | yield* forEach( 20 | array1, 21 | yielding((a, i) => (result[i] = a)) 22 | ) 23 | yield* forEach( 24 | array2, 25 | yielding((a, i) => (result[i + l] = a)) 26 | ) 27 | return result 28 | } 29 | -------------------------------------------------------------------------------- /dist/es6/find-index.js: -------------------------------------------------------------------------------- 1 | import {forEach} from './for-each' 2 | import {exitWith} from './array-utilities' 3 | 4 | /** 5 | * @generator 6 | * @param {Array|Object} collection 7 | * @param {Filter} fn 8 | * @returns {Generator<*, number, *>} Index of matching element or -1 9 | * @example 10 | * 11 | * if(-1 === yield * findIndex(records, yielding(v=>v.id === '123'))) 12 | * return 13 | */ 14 | export function* findIndex(collection, fn, start) { 15 | let output = -1 16 | yield* forEach( 17 | collection, 18 | function* (value, key) { 19 | let result = yield* fn(value, key, collection) 20 | if (result) { 21 | output = key 22 | return exitWith(key) 23 | } 24 | }, 25 | start 26 | ) 27 | return output 28 | } 29 | -------------------------------------------------------------------------------- /src/component/find-index.js: -------------------------------------------------------------------------------- 1 | import {forEach} from './for-each' 2 | import {exitWith} from './array-utilities' 3 | 4 | /** 5 | * @generator 6 | * @param {Array|Object} collection 7 | * @param {Filter} fn 8 | * @returns {Generator<*, number, *>} Index of matching element or -1 9 | * @example 10 | * 11 | * if(-1 === yield * findIndex(records, yielding(v=>v.id === '123'))) 12 | * return 13 | */ 14 | export function* findIndex(collection, fn, start) { 15 | let output = -1 16 | yield* forEach( 17 | collection, 18 | function* (value, key) { 19 | let result = yield* fn(value, key, collection) 20 | if (result) { 21 | output = key 22 | return exitWith(key) 23 | } 24 | }, 25 | start 26 | ) 27 | return output 28 | } 29 | -------------------------------------------------------------------------------- /dist/es6/repeat.js: -------------------------------------------------------------------------------- 1 | import run from './run' 2 | 3 | /** 4 | * Create a function that repeats a function multiple times 5 | * passing the output of each iteration as the input to the next 6 | * @param {Function} fn - the function to repeat 7 | * @param {Number} times - the number of times to repeat 8 | * @returns {AsyncFunction} - a async function that repeats the operation 9 | */ 10 | export function repeat(fn, times) { 11 | return async function (params) { 12 | let result = params 13 | for (let i = 0; i < times; i++) { 14 | result = fn.call(this, result) 15 | if (result.next) { 16 | result = await run(result) 17 | } else if (result.then) { 18 | result = await result 19 | } 20 | } 21 | return result 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /dist/es6/sort-async.js: -------------------------------------------------------------------------------- 1 | import {wrapAsPromise} from './wrappers' 2 | import {sort} from './timsort' 3 | 4 | /** 5 | *

Sort an array (in place) by a sorting function

6 | *

Sorts an array in place asynchronously. This function is a yielding 7 | * implementation of Timsort (standard sort used in modern browsers). Timsort 8 | * is fast and stable making it ideal for multi-key sorts. It it not as fast 9 | * as Quicksort.

10 | * @function sortAsync 11 | * @param {Array} array - The array to sort 12 | * @param {SortFunction|ExtractFunction} sort - The method to sort the array 13 | * @returns {Promise.} a promise for the sorted array 14 | * @example 15 | * async function process(data) { 16 | * return await sortAsync(data, v=>v.someProperty) 17 | * } 18 | */ 19 | export const sortAsync = wrapAsPromise(sort) 20 | -------------------------------------------------------------------------------- /src/component/repeat.js: -------------------------------------------------------------------------------- 1 | import run from './run' 2 | 3 | /** 4 | * Create a function that repeats a function multiple times 5 | * passing the output of each iteration as the input to the next 6 | * @param {Function} fn - the function to repeat 7 | * @param {Number} times - the number of times to repeat 8 | * @returns {AsyncFunction} - a async function that repeats the operation 9 | */ 10 | export function repeat(fn, times) { 11 | return async function (params) { 12 | let result = params 13 | for (let i = 0; i < times; i++) { 14 | result = fn.call(this, result) 15 | if (result.next) { 16 | result = await run(result) 17 | } else if (result.then) { 18 | result = await result 19 | } 20 | } 21 | return result 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/component/sort-async.js: -------------------------------------------------------------------------------- 1 | import {wrapAsPromise} from './wrappers' 2 | import {sort} from './timsort' 3 | 4 | /** 5 | *

Sort an array (in place) by a sorting function

6 | *

Sorts an array in place asynchronously. This function is a yielding 7 | * implementation of Timsort (standard sort used in modern browsers). Timsort 8 | * is fast and stable making it ideal for multi-key sorts. It it not as fast 9 | * as Quicksort.

10 | * @function sortAsync 11 | * @param {Array} array - The array to sort 12 | * @param {SortFunction|ExtractFunction} sort - The method to sort the array 13 | * @returns {Promise.} a promise for the sorted array 14 | * @example 15 | * async function process(data) { 16 | * return await sortAsync(data, v=>v.someProperty) 17 | * } 18 | */ 19 | export const sortAsync = wrapAsPromise(sort) 20 | -------------------------------------------------------------------------------- /dist/key-by.js: -------------------------------------------------------------------------------- 1 | "use strict";var _regeneratorRuntime2=require("@babel/runtime/regenerator"),_interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports,"__esModule",{value:!0}),exports.keyBy=keyBy;var _regenerator=_interopRequireDefault(require("@babel/runtime/regenerator")),_forEach=require("./for-each"),_marked=_regeneratorRuntime2.mark(keyBy);function keyBy(a,b){var c;return _regenerator.default.wrap(function(d){for(;;)switch(d.prev=d.next){case 0:return c={},d.delegateYield((0,_forEach.forEach)(a,_regenerator.default.mark(function d(e,f){var g;return _regenerator.default.wrap(function(d){for(;;)switch(d.prev=d.next){case 0:return d.delegateYield(b(e,f,a),"t0",1);case 1:g=d.t0,c[g]=e;case 3:case"end":return d.stop();}},d)})),"t0",2);case 2:return d.abrupt("return",c);case 3:case"end":return d.stop();}},_marked)} -------------------------------------------------------------------------------- /docs/scripts/collapse.js: -------------------------------------------------------------------------------- 1 | function hideAllButCurrent(){ 2 | //by default all submenut items are hidden 3 | //but we need to rehide them for search 4 | document.querySelectorAll("nav > ul > li > ul li").forEach(function(parent) { 5 | parent.style.display = "none"; 6 | }); 7 | 8 | //only current page (if it exists) should be opened 9 | var file = window.location.pathname.split("/").pop().replace(/\.html/, ''); 10 | document.querySelectorAll("nav > ul > li > a").forEach(function(parent) { 11 | var href = parent.attributes.href.value.replace(/\.html/, ''); 12 | if (file === href) { 13 | parent.parentNode.querySelectorAll("ul li").forEach(function(elem) { 14 | elem.style.display = "block"; 15 | }); 16 | } 17 | }); 18 | } 19 | 20 | hideAllButCurrent(); -------------------------------------------------------------------------------- /dist/concat.js: -------------------------------------------------------------------------------- 1 | "use strict";var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports,"__esModule",{value:!0}),exports.concat=concat;var _regenerator=_interopRequireDefault(require("@babel/runtime/regenerator")),_forEach=require("./for-each"),_wrappers=require("./wrappers"),_marked=_regenerator.default.mark(concat);function concat(a,b){var c,d;return _regenerator.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,!0;case 2:return c=Array(a.length+b.length),void(e.next=5);case 5:return d=a.length,e.delegateYield((0,_forEach.forEach)(a,(0,_wrappers.yielding)(function(b,a){return c[a]=b})),"t0",7);case 7:return e.delegateYield((0,_forEach.forEach)(b,(0,_wrappers.yielding)(function(b,a){return c[a+d]=b})),"t1",8);case 8:return e.abrupt("return",c);case 9:case"end":return e.stop();}},_marked)} -------------------------------------------------------------------------------- /dist/es6/key-by.js: -------------------------------------------------------------------------------- 1 | import {forEach} from './for-each' 2 | 3 | /** 4 | * Creates an object composed of keys generated from the results 5 | * of running each element of collection thru then supplied function. 6 | * The corresponding value of each key is the last element responsible 7 | * for generating the key. 8 | * 9 | * @param {Array|Object} collection 10 | * @param {Map} fn 11 | * @returns {Generator<*, {}, *>} a generator for the new object 12 | * @example 13 | * 14 | * let lookup = yield * keyBy(records, yielding(r=>r.id)) 15 | * 16 | * ... 17 | * 18 | * let row = lookup[id] 19 | * 20 | */ 21 | export function* keyBy(collection, fn) { 22 | let result = {} 23 | yield* forEach(collection, function* (value, key) { 24 | let newKey = yield* fn(value, key, collection) 25 | result[newKey] = value 26 | }) 27 | return result 28 | } 29 | -------------------------------------------------------------------------------- /docs/scripts/prettify/lang-css.js: -------------------------------------------------------------------------------- 1 | PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\f\r ]+/,null," \t\r\n "]],[["str",/^"(?:[^\n\f\r"\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*"/,null],["str",/^'(?:[^\n\f\r'\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*'/,null],["lang-css-str",/^url\(([^"')]*)\)/i],["kwd",/^(?:url|rgb|!important|@import|@page|@media|@charset|inherit)(?=[^\w-]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*)\s*:/i],["com",/^\/\*[^*]*\*+(?:[^*/][^*]*\*+)*\//],["com", 2 | /^(?:<\!--|--\>)/],["lit",/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],["lit",/^#[\da-f]{3,6}/i],["pln",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i],["pun",/^[^\s\w"']+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[["kwd",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[["str",/^[^"')]+/]]),["css-str"]); 3 | -------------------------------------------------------------------------------- /dist/es6/find.js: -------------------------------------------------------------------------------- 1 | import {forEach} from './for-each' 2 | import {exitWith} from './array-utilities' 3 | 4 | /** 5 | * @generator 6 | * @param {Array|Object} collection 7 | * @param {Filter} fn 8 | * @param {any} [start] - the key to start at 9 | * @returns {Generator<*, *, *>} the first matching value in the collection or null 10 | * @example 11 | * 12 | * const record = yield * find(arrayOfRecords, yielding(v=>v.id === '1234')) 13 | */ 14 | export function* find(collection, fn, start) { 15 | let output = undefined 16 | yield* forEach( 17 | collection, 18 | function* (value, key) { 19 | let result = yield* fn(value, key, collection) 20 | if (result) { 21 | output = value 22 | return exitWith(value) 23 | } 24 | }, 25 | start 26 | ) 27 | return output 28 | } 29 | -------------------------------------------------------------------------------- /dist/es6/reduce.js: -------------------------------------------------------------------------------- 1 | import {forEach} from './for-each' 2 | 3 | /** 4 | * @param {Array|Object} target 5 | * @param {Reduce} fn 6 | * @param {any} [initial] 7 | * @returns {Generator<*, *, *>} The result of processing the reduction function on all 8 | * of the items in the target 9 | * @example 10 | * 11 | * async function sumAge(items) { 12 | * const output = await reduceAsync(items, (acc,cur)=>acc += cur.age, 0) 13 | * } 14 | */ 15 | export function* reduce(target, fn, initial) { 16 | let result = initial !== undefined ? initial : target[0] 17 | let first = true 18 | yield* forEach(target, function* (item, key) { 19 | if (first && !initial) { 20 | result = item 21 | first = false 22 | } else { 23 | result = yield* fn(result, item, key, target) 24 | } 25 | }) 26 | return result 27 | } 28 | -------------------------------------------------------------------------------- /dist/es6/yastjson/lib/expression.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2020 5u9ar (zhuyingda) 3 | * 4 | * The above copyright notice and this permission notice shall be included in all 5 | * copies or substantial portions of the Software. 6 | * 7 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 8 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 9 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 10 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 11 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 12 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 13 | * SOFTWARE. 14 | */ 15 | export const ExprType = { 16 | Json: "j", 17 | Array: "a", 18 | Object: "o", 19 | Prop: "p", 20 | Value: "v", 21 | }; 22 | -------------------------------------------------------------------------------- /src/component/key-by.js: -------------------------------------------------------------------------------- 1 | import {forEach} from './for-each' 2 | 3 | /** 4 | * Creates an object composed of keys generated from the results 5 | * of running each element of collection thru then supplied function. 6 | * The corresponding value of each key is the last element responsible 7 | * for generating the key. 8 | * 9 | * @param {Array|Object} collection 10 | * @param {Map} fn 11 | * @returns {Generator<*, {}, *>} a generator for the new object 12 | * @example 13 | * 14 | * let lookup = yield * keyBy(records, yielding(r=>r.id)) 15 | * 16 | * ... 17 | * 18 | * let row = lookup[id] 19 | * 20 | */ 21 | export function* keyBy(collection, fn) { 22 | let result = {} 23 | yield* forEach(collection, function* (value, key) { 24 | let newKey = yield* fn(value, key, collection) 25 | result[newKey] = value 26 | }) 27 | return result 28 | } 29 | -------------------------------------------------------------------------------- /dist/tap.js: -------------------------------------------------------------------------------- 1 | "use strict";var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports,"__esModule",{value:!0}),exports.tap=tap;var _regenerator=_interopRequireDefault(require("@babel/runtime/regenerator")),_asyncToGenerator2=_interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator")),_run=_interopRequireDefault(require("./run"));function tap(a){return function(){var b=(0,_asyncToGenerator2.default)(_regenerator.default.mark(function b(c){var d;return _regenerator.default.wrap(function(b){for(;;)switch(b.prev=b.next){case 0:if(d=a.call(this,c),!d){b.next=10;break}if(!d.next){b.next=7;break}return b.next=5,(0,_run.default)(d);case 5:b.next=10;break;case 7:if(!d.then){b.next=10;break}return b.next=10,d;case 10:return b.abrupt("return",c);case 11:case"end":return b.stop();}},b,this)}));return function(){return b.apply(this,arguments)}}()} -------------------------------------------------------------------------------- /src/component/find.js: -------------------------------------------------------------------------------- 1 | import {forEach} from './for-each' 2 | import {exitWith} from './array-utilities' 3 | 4 | /** 5 | * @generator 6 | * @param {Array|Object} collection 7 | * @param {Filter} fn 8 | * @param {any} [start] - the key to start at 9 | * @returns {Generator<*, *, *>} the first matching value in the collection or null 10 | * @example 11 | * 12 | * const record = yield * find(arrayOfRecords, yielding(v=>v.id === '1234')) 13 | */ 14 | export function* find(collection, fn, start) { 15 | let output = undefined 16 | yield* forEach( 17 | collection, 18 | function* (value, key) { 19 | let result = yield* fn(value, key, collection) 20 | if (result) { 21 | output = value 22 | return exitWith(value) 23 | } 24 | }, 25 | start 26 | ) 27 | return output 28 | } 29 | -------------------------------------------------------------------------------- /src/component/reduce.js: -------------------------------------------------------------------------------- 1 | import {forEach} from './for-each' 2 | 3 | /** 4 | * @param {Array|Object} target 5 | * @param {Reduce} fn 6 | * @param {any} [initial] 7 | * @returns {Generator<*, *, *>} The result of processing the reduction function on all 8 | * of the items in the target 9 | * @example 10 | * 11 | * async function sumAge(items) { 12 | * const output = await reduceAsync(items, (acc,cur)=>acc += cur.age, 0) 13 | * } 14 | */ 15 | export function* reduce(target, fn, initial) { 16 | let result = initial !== undefined ? initial : target[0] 17 | let first = true 18 | yield* forEach(target, function* (item, key) { 19 | if (first && !initial) { 20 | result = item 21 | first = false 22 | } else { 23 | result = yield* fn(result, item, key, target) 24 | } 25 | }) 26 | return result 27 | } 28 | -------------------------------------------------------------------------------- /src/component/yastjson/lib/expression.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2020 5u9ar (zhuyingda) 3 | * 4 | * The above copyright notice and this permission notice shall be included in all 5 | * copies or substantial portions of the Software. 6 | * 7 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 8 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 9 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 10 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 11 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 12 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 13 | * SOFTWARE. 14 | */ 15 | export const ExprType = { 16 | Json: "j", 17 | Array: "a", 18 | Object: "o", 19 | Prop: "p", 20 | Value: "v", 21 | }; 22 | -------------------------------------------------------------------------------- /dist/map.js: -------------------------------------------------------------------------------- 1 | "use strict";var _regeneratorRuntime2=require("@babel/runtime/regenerator"),_interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports,"__esModule",{value:!0}),exports.map=map;var _regenerator=_interopRequireDefault(require("@babel/runtime/regenerator")),_isObject=require("./is-object"),_forEach=require("./for-each"),_marked=_regeneratorRuntime2.mark(map);function map(a,b){var c;return _regenerator.default.wrap(function(d){for(;;)switch(d.prev=d.next){case 0:return c=(0,_isObject.isObject)(a)?{}:[],d.delegateYield((0,_forEach.forEach)(a,_regenerator.default.mark(function d(e,f){return _regenerator.default.wrap(function(d){for(;;)switch(d.prev=d.next){case 0:return d.delegateYield(b(e,f,a),"t0",1);case 1:c[f]=d.t0;case 2:case"end":return d.stop();}},d)})),"t0",2);case 2:return d.abrupt("return",c);case 3:case"end":return d.stop();}},_marked)} -------------------------------------------------------------------------------- /dist/reduce.js: -------------------------------------------------------------------------------- 1 | "use strict";var _regeneratorRuntime2=require("@babel/runtime/regenerator"),_interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports,"__esModule",{value:!0}),exports.reduce=reduce;var _regenerator=_interopRequireDefault(require("@babel/runtime/regenerator")),_forEach=require("./for-each"),_marked=_regeneratorRuntime2.mark(reduce);function reduce(a,b,c){var d,e;return _regenerator.default.wrap(function(f){for(;;)switch(f.prev=f.next){case 0:return d=void 0===c?a[0]:c,e=!0,f.delegateYield((0,_forEach.forEach)(a,_regenerator.default.mark(function f(g,h){return _regenerator.default.wrap(function(f){for(;;)switch(f.prev=f.next){case 0:if(!e||c){f.next=5;break}d=g,e=!1,f.next=7;break;case 5:return f.delegateYield(b(d,g,h,a),"t0",6);case 6:d=f.t0;case 7:case"end":return f.stop();}},f)})),"t0",3);case 3:return f.abrupt("return",d);case 4:case"end":return f.stop();}},_marked)} -------------------------------------------------------------------------------- /dist/es6/async-wrappers.js: -------------------------------------------------------------------------------- 1 | export * from './async-array-wrappers' 2 | export * from './async-compression-wrappers' 3 | export * from './async-json-wrappers' 4 | export {sortAsync} from './sort-async' 5 | export {findAsync} from './find-async' 6 | export {findIndexAsync} from './find-index-async' 7 | export {mapAsync} from './map-async' 8 | export {filterAsync} from './filter-async' 9 | export {reduceAsync} from './reduce-async' 10 | export {appendAsync} from './append-async' 11 | export {concatAsync} from './concat-async' 12 | export {forEachAsync} from './for-each-async' 13 | export {someAsync} from './some-async' 14 | export {includesAsync} from './includes-async' 15 | export {indexOfAsync} from './index-of-async' 16 | export {lastIndexOfAsync} from './last-index-of-async' 17 | export {keyByAsync} from './key-by-async' 18 | export {groupByAsync} from './group-by-async' 19 | export {uniqueByAsync} from './unique-by-async' 20 | -------------------------------------------------------------------------------- /src/component/async-wrappers.js: -------------------------------------------------------------------------------- 1 | export * from './async-array-wrappers' 2 | export * from './async-compression-wrappers' 3 | export * from './async-json-wrappers' 4 | export {sortAsync} from './sort-async' 5 | export {findAsync} from './find-async' 6 | export {findIndexAsync} from './find-index-async' 7 | export {mapAsync} from './map-async' 8 | export {filterAsync} from './filter-async' 9 | export {reduceAsync} from './reduce-async' 10 | export {appendAsync} from './append-async' 11 | export {concatAsync} from './concat-async' 12 | export {forEachAsync} from './for-each-async' 13 | export {someAsync} from './some-async' 14 | export {includesAsync} from './includes-async' 15 | export {indexOfAsync} from './index-of-async' 16 | export {lastIndexOfAsync} from './last-index-of-async' 17 | export {keyByAsync} from './key-by-async' 18 | export {groupByAsync} from './group-by-async' 19 | export {uniqueByAsync} from './unique-by-async' 20 | -------------------------------------------------------------------------------- /src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .info-list { 17 | position: absolute; 18 | padding: 4px; 19 | background: #0000001f; 20 | bottom: 15px; 21 | text-align: left; 22 | font-size: 16px; 23 | width: 500px; 24 | } 25 | 26 | .App-header { 27 | background-color: #282c34; 28 | min-height: 100vh; 29 | display: flex; 30 | flex-direction: column; 31 | align-items: center; 32 | justify-content: center; 33 | font-size: calc(10px + 2vmin); 34 | color: white; 35 | } 36 | 37 | .App-link { 38 | color: #61dafb; 39 | } 40 | 41 | @keyframes App-logo-spin { 42 | from { 43 | transform: rotate(0deg); 44 | } 45 | to { 46 | transform: rotate(360deg); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/test/compression.test.js: -------------------------------------------------------------------------------- 1 | import {should} from 'chai' 2 | import {compressAsync, decompressAsync, compressToUTF16Async, decompressFromUTF16Async, sortAsync} from '../component' 3 | 4 | should() 5 | const INPUT_ARRAY = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20] 6 | import test from '../component/yastjson/test/test.json' 7 | 8 | describe('compression', function () { 9 | it('should compress a string', async function () { 10 | let result = await compressAsync('abcde') 11 | let output = await decompressAsync(result) 12 | output.should.eq('abcde') 13 | result.should.eq('ↂテɠꙀ') 14 | }) 15 | it('should compress a string to UTF 16', async function () { 16 | let result = await compressToUTF16Async('abcde') 17 | let output = await decompressFromUTF16Async(result) 18 | output.should.eq('abcde') 19 | result.should.eq('ს౑䁬઄ ') 20 | }) 21 | }) 22 | -------------------------------------------------------------------------------- /dist/some.js: -------------------------------------------------------------------------------- 1 | "use strict";var _regeneratorRuntime2=require("@babel/runtime/regenerator"),_interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports,"__esModule",{value:!0}),exports.some=some;var _regenerator=_interopRequireDefault(require("@babel/runtime/regenerator")),_forEach=require("./for-each"),_arrayUtilities=require("./array-utilities"),_marked=_regeneratorRuntime2.mark(some);function some(a,b){var c;return _regenerator.default.wrap(function(d){for(;;)switch(d.prev=d.next){case 0:return c=!1,d.delegateYield((0,_forEach.forEach)(a,_regenerator.default.mark(function d(e,f){return _regenerator.default.wrap(function(d){for(;;)switch(d.prev=d.next){case 0:return d.delegateYield(b(e,f,a),"t0",1);case 1:if(!d.t0){d.next=4;break}return c=!0,d.abrupt("return",(0,_arrayUtilities.exitWith)(!0));case 4:case"end":return d.stop();}},d)})),"t0",2);case 2:return d.abrupt("return",c);case 3:case"end":return d.stop();}},_marked)} -------------------------------------------------------------------------------- /template/tmpl/members.tmpl: -------------------------------------------------------------------------------- 1 | 5 | 6 |

7 | 8 |

9 | 10 | 11 |

12 | 13 |

14 | 15 | 16 | 17 |
18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 |
Fires:
26 |
    27 | 28 |
  • 29 | 30 |
  • 31 | 32 |
33 | 34 | 35 | 36 |
Example 1? 's':'' ?>
37 | 38 | 39 | -------------------------------------------------------------------------------- /dist/es6/group-by.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Creates an object composed of keys generated from the results 3 | * of running each element of collection thru then supplied function. 4 | * The corresponding value of each key is an collection of the elements responsible 5 | * for generating the key. 6 | * 7 | * @param {Array|Object} collection 8 | * @param {Map} fn 9 | * @returns {Generator<*, {}, *>} a generator for the new object 10 | * @example 11 | * 12 | * let groups = yield * groupBy(records, yielding(v=>v.category)) 13 | * 14 | * ... 15 | * 16 | * console.log(groups['category1']) // -> [{id: 1, ...}, {id: 2, ...}] 17 | * 18 | */ 19 | export function* groupBy(collection, fn) { 20 | let result = {} 21 | let index = 0 22 | for (let item of collection) { 23 | let key = yield* fn(item, index++, collection) 24 | const array = (result[key] = result[key] || []) 25 | array.push(item) 26 | } 27 | return result 28 | } 29 | -------------------------------------------------------------------------------- /dist/every.js: -------------------------------------------------------------------------------- 1 | "use strict";var _regeneratorRuntime2=require("@babel/runtime/regenerator"),_interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports,"__esModule",{value:!0}),exports.every=every;var _regenerator=_interopRequireDefault(require("@babel/runtime/regenerator")),_forEach=require("./for-each"),_arrayUtilities=require("./array-utilities"),_marked=_regeneratorRuntime2.mark(every);function every(a,b){var c;return _regenerator.default.wrap(function(d){for(;;)switch(d.prev=d.next){case 0:return c=!0,d.delegateYield((0,_forEach.forEach)(a,_regenerator.default.mark(function d(e,f){return _regenerator.default.wrap(function(d){for(;;)switch(d.prev=d.next){case 0:return d.delegateYield(b(e,f,a),"t0",1);case 1:if(d.t0){d.next=4;break}return c=!1,d.abrupt("return",(0,_arrayUtilities.exitWith)(!1));case 4:case"end":return d.stop();}},d)})),"t0",2);case 2:return d.abrupt("return",c);case 3:case"end":return d.stop();}},_marked)} -------------------------------------------------------------------------------- /src/component/group-by.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Creates an object composed of keys generated from the results 3 | * of running each element of collection thru then supplied function. 4 | * The corresponding value of each key is an collection of the elements responsible 5 | * for generating the key. 6 | * 7 | * @param {Array|Object} collection 8 | * @param {Map} fn 9 | * @returns {Generator<*, {}, *>} a generator for the new object 10 | * @example 11 | * 12 | * let groups = yield * groupBy(records, yielding(v=>v.category)) 13 | * 14 | * ... 15 | * 16 | * console.log(groups['category1']) // -> [{id: 1, ...}, {id: 2, ...}] 17 | * 18 | */ 19 | export function* groupBy(collection, fn) { 20 | let result = {} 21 | let index = 0 22 | for (let item of collection) { 23 | let key = yield* fn(item, index++, collection) 24 | const array = (result[key] = result[key] || []) 25 | array.push(item) 26 | } 27 | return result 28 | } 29 | -------------------------------------------------------------------------------- /dist/find.js: -------------------------------------------------------------------------------- 1 | "use strict";var _regeneratorRuntime2=require("@babel/runtime/regenerator"),_interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports,"__esModule",{value:!0}),exports.find=find;var _regenerator=_interopRequireDefault(require("@babel/runtime/regenerator")),_forEach=require("./for-each"),_arrayUtilities=require("./array-utilities"),_marked=_regeneratorRuntime2.mark(find);function find(a,b,c){var d;return _regenerator.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return d=void 0,e.delegateYield((0,_forEach.forEach)(a,_regenerator.default.mark(function c(e,f){var g;return _regenerator.default.wrap(function(c){for(;;)switch(c.prev=c.next){case 0:return c.delegateYield(b(e,f,a),"t0",1);case 1:if(g=c.t0,!g){c.next=5;break}return d=e,c.abrupt("return",(0,_arrayUtilities.exitWith)(e));case 5:case"end":return c.stop();}},c)}),c),"t0",2);case 2:return e.abrupt("return",d);case 3:case"end":return e.stop();}},_marked)} -------------------------------------------------------------------------------- /dist/repeat.js: -------------------------------------------------------------------------------- 1 | "use strict";var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports,"__esModule",{value:!0}),exports.repeat=repeat;var _regenerator=_interopRequireDefault(require("@babel/runtime/regenerator")),_asyncToGenerator2=_interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator")),_run=_interopRequireDefault(require("./run"));function repeat(a,b){return function(){var c=(0,_asyncToGenerator2.default)(_regenerator.default.mark(function c(d){var e,f;return _regenerator.default.wrap(function(c){for(;;)switch(c.prev=c.next){case 0:e=d,f=0;case 2:if(!(f} collection of elements matching the filter 9 | * @example 10 | * 11 | * const filtered = yield * filter(array, yielding(v=>v.value > 1000, 100)) 12 | */ 13 | export function* filter(collection, fn) { 14 | if (isObject(collection)) { 15 | let result = {} 16 | yield* forEach(collection, function* (value, key, array) { 17 | if (yield* fn(value, key, array)) { 18 | result[key] = value 19 | } 20 | }) 21 | return result 22 | } else { 23 | let result = [] 24 | yield* forEach(collection, function* (value, key, array) { 25 | if (yield* fn(value, key, array)) { 26 | result.push(value) 27 | } 28 | }) 29 | return result 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/component/filter.js: -------------------------------------------------------------------------------- 1 | import {isObject} from './is-object' 2 | import {forEach} from './for-each' 3 | 4 | /** 5 | * @generator 6 | * @param {Array|Object} collection 7 | * @param {Filter} fn 8 | * @returns {Generator<*, Object|Array, *>} collection of elements matching the filter 9 | * @example 10 | * 11 | * const filtered = yield * filter(array, yielding(v=>v.value > 1000, 100)) 12 | */ 13 | export function* filter(collection, fn) { 14 | if (isObject(collection)) { 15 | let result = {} 16 | yield* forEach(collection, function* (value, key, array) { 17 | if (yield* fn(value, key, array)) { 18 | result[key] = value 19 | } 20 | }) 21 | return result 22 | } else { 23 | let result = [] 24 | yield* forEach(collection, function* (value, key, array) { 25 | if (yield* fn(value, key, array)) { 26 | result.push(value) 27 | } 28 | }) 29 | return result 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /dist/es6/pipe.js: -------------------------------------------------------------------------------- 1 | import run from './run' 2 | 3 | /** 4 | * Create a function that executes a pipeline of 5 | * functions asynchronously 6 | * @param {...(Function|Promise|Array<(Promise|Function|GeneratorFunction|AsyncFunction)>|GeneratorFunction|AsyncFunction)} fns - the pipeline to execute 7 | * @returns {AsyncFunction} an async function to execute the pipeline 8 | */ 9 | export function pipe(...fns) { 10 | return async function (params) { 11 | let result = params 12 | for (let fn of fns.flat(Infinity)) { 13 | if (!fn) continue 14 | let nextResult = fn.call(this, result) 15 | if (nextResult) { 16 | if (nextResult.next) { 17 | result = await run(nextResult) 18 | } else if (nextResult.then) { 19 | result = await nextResult 20 | } else { 21 | result = nextResult 22 | } 23 | } 24 | } 25 | return result 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/component/pipe.js: -------------------------------------------------------------------------------- 1 | import run from './run' 2 | 3 | /** 4 | * Create a function that executes a pipeline of 5 | * functions asynchronously 6 | * @param {...(Function|Promise|Array<(Promise|Function|GeneratorFunction|AsyncFunction)>|GeneratorFunction|AsyncFunction)} fns - the pipeline to execute 7 | * @returns {AsyncFunction} an async function to execute the pipeline 8 | */ 9 | export function pipe(...fns) { 10 | return async function (params) { 11 | let result = params 12 | for (let fn of fns.flat(Infinity)) { 13 | if (!fn) continue 14 | let nextResult = fn.call(this, result) 15 | if (nextResult) { 16 | if (nextResult.next) { 17 | result = await run(nextResult) 18 | } else if (nextResult.then) { 19 | result = await nextResult 20 | } else { 21 | result = nextResult 22 | } 23 | } 24 | } 25 | return result 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /dist/es6/unique-by.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Create an array with the unique values from the 3 | * input array, the routine is supplied with a 4 | * function that determines on what the array should 5 | * be made unique. 6 | * @param {Array} array 7 | * @param {Map} [fn] - the function to determine uniqueness, if 8 | * omitted then the item itself is used 9 | * @returns {Generator<*, Array, *>} 10 | * @example 11 | * 12 | * const uniqueValues = yield * uniqueBy(records, yielding(r=>r.id)) 13 | * 14 | */ 15 | export function* uniqueBy(array, fn) { 16 | let set = new Set() 17 | let output = [] 18 | let index = 0 19 | for (let item of array) { 20 | if (fn) { 21 | let key = yield* fn(item, index++, array) 22 | if (!set.has(key)) { 23 | output.push(item) 24 | set.add(key) 25 | } 26 | } else { 27 | if (!set.has(item)) { 28 | output.push(item) 29 | set.add(item) 30 | } 31 | } 32 | } 33 | return output 34 | } 35 | -------------------------------------------------------------------------------- /src/component/unique-by.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Create an array with the unique values from the 3 | * input array, the routine is supplied with a 4 | * function that determines on what the array should 5 | * be made unique. 6 | * @param {Array} array 7 | * @param {Map} [fn] - the function to determine uniqueness, if 8 | * omitted then the item itself is used 9 | * @returns {Generator<*, Array, *>} 10 | * @example 11 | * 12 | * const uniqueValues = yield * uniqueBy(records, yielding(r=>r.id)) 13 | * 14 | */ 15 | export function* uniqueBy(array, fn) { 16 | let set = new Set() 17 | let output = [] 18 | let index = 0 19 | for (let item of array) { 20 | if (fn) { 21 | let key = yield* fn(item, index++, array) 22 | if (!set.has(key)) { 23 | output.push(item) 24 | set.add(key) 25 | } 26 | } else { 27 | if (!set.has(item)) { 28 | output.push(item) 29 | set.add(item) 30 | } 31 | } 32 | } 33 | return output 34 | } 35 | -------------------------------------------------------------------------------- /dist/compose.js: -------------------------------------------------------------------------------- 1 | "use strict";var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports,"__esModule",{value:!0}),exports.compose=compose;var _regenerator=_interopRequireDefault(require("@babel/runtime/regenerator")),_asyncToGenerator2=_interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator")),_run=_interopRequireDefault(require("./run"));function compose(){for(var a=arguments.length,b=Array(a),c=0;c-v) 13 | result[0].should.eq(20) 14 | result[19].should.eq(1) 15 | }) 16 | it('should be able to sort more complicated things!', async function () { 17 | const result = await sortAsync([...test], v=>v.age) 18 | result[0].name.first.should.eq('Leticia') 19 | }) 20 | it('should sort an alpha array', async function () { 21 | const result = await sortAsync([...SORT_ARRAY]) 22 | result[0].should.eq('1') 23 | result[12].should.eq('z') 24 | }) 25 | it('should sort a numeric array', async function () { 26 | const result = await sortAsync([...INPUT_ARRAY]) 27 | result[0].should.eq(1) 28 | result[12].should.eq(13) 29 | }) 30 | }) 31 | -------------------------------------------------------------------------------- /dist/es6/compose.js: -------------------------------------------------------------------------------- 1 | import run from './run' 2 | 3 | /** 4 | * Create a function that executes a pipeline of 5 | * functions asynchronously, the function executes the list in 6 | * REVERSE order, allowing you to "compose on" a new function 7 | * at the head of the chain 8 | * @param {...(Function|Promise|Array<(Promise|Function|GeneratorFunction|AsyncFunction)>|GeneratorFunction|AsyncFunction)} fns - the pipeline to execute 9 | * @returns {AsyncFunction} an async function to execute the pipeline 10 | */ 11 | export function compose(...fns) { 12 | return async function (params) { 13 | let result = params 14 | 15 | let list = fns.flat(Infinity) 16 | for (let i = list.length - 1; i >= 0; i--) { 17 | let fn = list[i] 18 | if (!fn) continue 19 | let nextResult = fn.call(this, result) 20 | if (nextResult) { 21 | if (nextResult.next) { 22 | result = await run(nextResult) 23 | } else if (nextResult.then) { 24 | result = await nextResult 25 | } else { 26 | result = nextResult 27 | } 28 | } 29 | } 30 | return result 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/component/compose.js: -------------------------------------------------------------------------------- 1 | import run from './run' 2 | 3 | /** 4 | * Create a function that executes a pipeline of 5 | * functions asynchronously, the function executes the list in 6 | * REVERSE order, allowing you to "compose on" a new function 7 | * at the head of the chain 8 | * @param {...(Function|Promise|Array<(Promise|Function|GeneratorFunction|AsyncFunction)>|GeneratorFunction|AsyncFunction)} fns - the pipeline to execute 9 | * @returns {AsyncFunction} an async function to execute the pipeline 10 | */ 11 | export function compose(...fns) { 12 | return async function (params) { 13 | let result = params 14 | 15 | let list = fns.flat(Infinity) 16 | for (let i = list.length - 1; i >= 0; i--) { 17 | let fn = list[i] 18 | if (!fn) continue 19 | let nextResult = fn.call(this, result) 20 | if (nextResult) { 21 | if (nextResult.next) { 22 | result = await run(nextResult) 23 | } else if (nextResult.then) { 24 | result = await nextResult 25 | } else { 26 | result = nextResult 27 | } 28 | } 29 | } 30 | return result 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /doc.conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | ], 4 | "source": { 5 | "include": [ 6 | "src/component/coroutines.js", 7 | "src/component/array-utilities.js", 8 | "src/component/index.js", 9 | "src/component/async-wrappers.js", 10 | "src/component/wrappers.js" 11 | ] 12 | }, 13 | "opts": { 14 | "destination": "./docs/", 15 | "recurse": true, 16 | "encoding": "utf8", 17 | "template": "./node_modules/docdash", 18 | "readme": "./README.md", 19 | "tutorials": "./tutorials" 20 | }, 21 | "docdash": { 22 | "typedefs": false, 23 | "sectionOrder": [ 24 | 25 | ], 26 | "menu": { 27 | "JS-COROUTINES": { 28 | "href": "http://js-coroutines.com" 29 | } 30 | }, 31 | "meta": { 32 | "title": "js-coroutines" 33 | }, 34 | "openGraph": { 35 | // Open Graph options (mostly for Facebook and other sites to easily extract meta information) 36 | "title": "js-coroutines", 37 | // Title of the website 38 | "type": "website", 39 | // Main image/logo 40 | "site_name": "js-coroutines", 41 | // Site name 42 | "url": "http://js-coroutines.com" 43 | // Main canonical URL for the main page of the site 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /template/LICENSE: -------------------------------------------------------------------------------- 1 | ## JSDoc 3 2 | 3 | JSDoc 3 is free software, licensed under the Apache License, Version 2.0 (the 4 | "License"). Commercial and non-commercial use are permitted in compliance with 5 | the License. 6 | 7 | Copyright (c) 2011-2015 Michael Mathews and the 8 | [contributors to JSDoc](https://github.com/jsdoc3/jsdoc/graphs/contributors). 9 | All rights reserved. 10 | 11 | You may obtain a copy of the License at: 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | In addition, a copy of the License is included with this distribution. 15 | 16 | As stated in Section 7, "Disclaimer of Warranty," of the License: 17 | 18 | > Licensor provides the Work (and each Contributor provides its Contributions) 19 | > on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 20 | > express or implied, including, without limitation, any warranties or 21 | > conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 22 | > PARTICULAR PURPOSE. You are solely responsible for determining the 23 | > appropriateness of using or redistributing the Work and assume any risks 24 | > associated with Your exercise of permissions under this License. 25 | 26 | The source code for JSDoc 3 is available at: 27 | https://github.com/jsdoc3/jsdoc 28 | -------------------------------------------------------------------------------- /dist/filter.js: -------------------------------------------------------------------------------- 1 | "use strict";var _regeneratorRuntime2=require("@babel/runtime/regenerator"),_interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports,"__esModule",{value:!0}),exports.filter=filter;var _regenerator=_interopRequireDefault(require("@babel/runtime/regenerator")),_isObject=require("./is-object"),_forEach=require("./for-each"),_marked=_regeneratorRuntime2.mark(filter);function filter(a,b){var c,d;return _regenerator.default.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:if(!(0,_isObject.isObject)(a)){e.next=6;break}return c={},e.delegateYield((0,_forEach.forEach)(a,_regenerator.default.mark(function a(d,e,f){return _regenerator.default.wrap(function(a){for(;;)switch(a.prev=a.next){case 0:return a.delegateYield(b(d,e,f),"t0",1);case 1:if(!a.t0){a.next=3;break}c[e]=d;case 3:case"end":return a.stop();}},a)})),"t0",3);case 3:return e.abrupt("return",c);case 6:return d=[],e.delegateYield((0,_forEach.forEach)(a,_regenerator.default.mark(function a(c,e,f){return _regenerator.default.wrap(function(a){for(;;)switch(a.prev=a.next){case 0:return a.delegateYield(b(c,e,f),"t0",1);case 1:if(!a.t0){a.next=3;break}d.push(c);case 3:case"end":return a.stop();}},a)})),"t1",8);case 8:return e.abrupt("return",d);case 9:case"end":return e.stop();}},_marked)} -------------------------------------------------------------------------------- /PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | # Pull Request Template 2 | 3 | ## Description 4 | 5 | Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change. 6 | 7 | Fixes # (issue) 8 | 9 | ## Type of change 10 | 11 | Please delete options that are not relevant. 12 | 13 | - [ ] Bug fix (non-breaking change which fixes an issue) 14 | - [ ] New feature (non-breaking change which adds functionality) 15 | - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) 16 | - [ ] This change requires a documentation update 17 | 18 | ## How Has This Been Tested? 19 | 20 | Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration 21 | 22 | **Test Configuration**: 23 | 24 | * Hardware: 25 | * Toolchain: 26 | 27 | ## Checklist: 28 | 29 | - [ ] I have performed a self-review of my own code 30 | - [ ] I have commented my code, particularly in hard-to-understand areas 31 | - [ ] I have made corresponding changes to the documentation 32 | - [ ] My changes generate no new warnings 33 | - [ ] I have added tests that prove my fix is effective or that my feature works 34 | - [ ] I have checked my code and corrected any misspellings 35 | -------------------------------------------------------------------------------- /dist/wrappers.js: -------------------------------------------------------------------------------- 1 | "use strict";var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports,"__esModule",{value:!0}),exports.yielding=yielding,exports.wrapAsPromise=wrapAsPromise,exports.curryRight=curryRight;var _toConsumableArray2=_interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray")),_regenerator=_interopRequireDefault(require("@babel/runtime/regenerator")),_run=_interopRequireDefault(require("./run")),_call=require("./call");function yielding(a){var b=1b.length?function(){for(var d=arguments.length,e=Array(d),f=0;f} 10 | * @example 11 | * // Loop over all keys/value pairs in an object 12 | * yield * forEach(object, yielding((value, key)=> { ... })) 13 | * 14 | * // Loop over all the values in an array 15 | * yield * forEach(array, generatorFunction) 16 | * 17 | * function * generatorFunction(value, index) { 18 | * let i = 0 19 | * while(i < 10000) { 20 | * doSomething(value) 21 | * if(i % 100 === 0) yield 22 | * } 23 | * } 24 | */ 25 | export function* forEach(collection, fn, start) { 26 | if (isObject(collection)) { 27 | let started = !start 28 | for (let key in collection) { 29 | if (!started) { 30 | started = key === start 31 | } 32 | if (started) { 33 | if (Object.prototype.hasOwnProperty.call(collection, key)) { 34 | let result = yield* fn(collection[key], key, collection) 35 | if (result && result[doReturn]) return result.value 36 | } 37 | } 38 | } 39 | } else { 40 | for (let index = start || 0, length = collection.length; index < length; index++) { 41 | let result = yield* fn(collection[index], index, collection) 42 | if (result && result[doReturn]) return result.value 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/component/for-each.js: -------------------------------------------------------------------------------- 1 | import {isObject} from './is-object' 2 | import {doReturn} from './array-utilities' 3 | 4 | /** 5 | * @generator 6 | * @param {Array|Object} collection 7 | * @param {Process} fn 8 | * @param {number|string} [start] 9 | * @returns {Generator<*, *, *>} 10 | * @example 11 | * // Loop over all keys/value pairs in an object 12 | * yield * forEach(object, yielding((value, key)=> { ... })) 13 | * 14 | * // Loop over all the values in an array 15 | * yield * forEach(array, generatorFunction) 16 | * 17 | * function * generatorFunction(value, index) { 18 | * let i = 0 19 | * while(i < 10000) { 20 | * doSomething(value) 21 | * if(i % 100 === 0) yield 22 | * } 23 | * } 24 | */ 25 | export function* forEach(collection, fn, start) { 26 | if (isObject(collection)) { 27 | let started = !start 28 | for (let key in collection) { 29 | if (!started) { 30 | started = key === start 31 | } 32 | if (started) { 33 | if (Object.prototype.hasOwnProperty.call(collection, key)) { 34 | let result = yield* fn(collection[key], key, collection) 35 | if (result && result[doReturn]) return result.value 36 | } 37 | } 38 | } 39 | } else { 40 | for (let index = start || 0, length = collection.length; index < length; index++) { 41 | let result = yield* fn(collection[index], index, collection) 42 | if (result && result[doReturn]) return result.value 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/test/json.test.js: -------------------------------------------------------------------------------- 1 | import {parseAsync, stringifyAsync} from '../component' 2 | import test from '../component/yastjson/test/test.json' 3 | const testJSON = JSON.stringify(test) 4 | import {should} from 'chai' 5 | 6 | should() 7 | 8 | describe('JSON tests', function () { 9 | it("should stringify JSON", async function () { 10 | let json = await stringifyAsync({a: 1, c: 2, d: 3}) 11 | json.should.eq('{"a":1,"c":2,"d":3}') 12 | }) 13 | it("should stringify empty strings", async function () { 14 | let data = {name: "person", extra_info: '{country:"",age:35}'} 15 | let json = await stringifyAsync(data) 16 | json.should.eq(JSON.stringify(data)) 17 | console.log(JSON.stringify(data)) 18 | }) 19 | it("should parse JSON", async function () { 20 | let item = await parseAsync('{"a":1,"c":2,"d":3,"e":{"a":1}}') 21 | item.a.should.eq(1) 22 | item.d.should.eq(3) 23 | item.e.a.should.eq(1) 24 | }) 25 | it("should parse whitespaced JSON", async function () { 26 | let item = await parseAsync(' { "a":1, "c":2, "d":3, "e": { "a": 1} }') 27 | item.a.should.eq(1) 28 | item.d.should.eq(3) 29 | item.e.a.should.eq(1) 30 | }) 31 | it("should parse realistic json", async function () { 32 | let item = await parseAsync(testJSON) 33 | item[0].friends.length.should.eq(3) 34 | }) 35 | it("should be able to stringify complex JSON", async function () { 36 | let result = await stringifyAsync(test) 37 | result.should.eq(testJSON) 38 | }) 39 | 40 | }) 41 | -------------------------------------------------------------------------------- /dist/es6/singleton.js: -------------------------------------------------------------------------------- 1 | import run from './run' 2 | 3 | /** 4 | * Creates a singleton executor of a generator function. 5 | * If the function is currently running it will be 6 | * terminated with the defaultValue and a new one started. 7 | * 8 | * This would often be used with a UI to cancel a previous calculation 9 | * and begin updates on a new one. 10 | * 11 | * @param {Function} fn - the generator function to wrap 12 | * @param {any} [defaultValue] - a value to be returned if the current execution is 13 | * terminated by a new one starting 14 | * @returns {function(...[*]): Promise} a function to execute the 15 | * generator and return the value 16 | * @example 17 | * 18 | * const job = singleton(function * (array, value) { 19 | * let output = [] 20 | * for(let item of array) { 21 | * if(output.length % 100 === 0) yield 22 | * output.push(complexCalculation(array, value)) 23 | * } 24 | * return output 25 | * }, []) 26 | * 27 | * function doSomething(array) { 28 | * job(array, 2002).then(console.log) 29 | * } 30 | * 31 | * doSomething(bigArray) 32 | * doSomething(otherArray) // -> console.log([]) from first one 33 | * 34 | */ 35 | export function singleton(fn, defaultValue) { 36 | let promise = null 37 | let extraPromises = [] 38 | let result = (...params) => { 39 | if (promise) { 40 | extraPromises.forEach(p => p.terminate()) 41 | extraPromises = [] 42 | promise.terminate(defaultValue) 43 | } 44 | return promise = result._promise = run(fn(...params)) 45 | } 46 | result.join = function (promise) { 47 | extraPromises.push(promise) 48 | return promise 49 | } 50 | return result 51 | } 52 | -------------------------------------------------------------------------------- /src/component/singleton.js: -------------------------------------------------------------------------------- 1 | import run from './run' 2 | 3 | /** 4 | * Creates a singleton executor of a generator function. 5 | * If the function is currently running it will be 6 | * terminated with the defaultValue and a new one started. 7 | * 8 | * This would often be used with a UI to cancel a previous calculation 9 | * and begin updates on a new one. 10 | * 11 | * @param {Function} fn - the generator function to wrap 12 | * @param {any} [defaultValue] - a value to be returned if the current execution is 13 | * terminated by a new one starting 14 | * @returns {function(...[*]): Promise} a function to execute the 15 | * generator and return the value 16 | * @example 17 | * 18 | * const job = singleton(function * (array, value) { 19 | * let output = [] 20 | * for(let item of array) { 21 | * if(output.length % 100 === 0) yield 22 | * output.push(complexCalculation(array, value)) 23 | * } 24 | * return output 25 | * }, []) 26 | * 27 | * function doSomething(array) { 28 | * job(array, 2002).then(console.log) 29 | * } 30 | * 31 | * doSomething(bigArray) 32 | * doSomething(otherArray) // -> console.log([]) from first one 33 | * 34 | */ 35 | export function singleton(fn, defaultValue) { 36 | let promise = null 37 | let extraPromises = [] 38 | let result = (...params) => { 39 | if (promise) { 40 | extraPromises.forEach(p => p.terminate()) 41 | extraPromises = [] 42 | promise.terminate(defaultValue) 43 | } 44 | return promise = result._promise = run(fn(...params)) 45 | } 46 | result.join = function (promise) { 47 | extraPromises.push(promise) 48 | return promise 49 | } 50 | return result 51 | } 52 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /dist/run.js: -------------------------------------------------------------------------------- 1 | "use strict";var _interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports,"__esModule",{value:!0}),exports.run=run,exports.default=void 0;var _regenerator=_interopRequireDefault(require("@babel/runtime/regenerator")),_asyncToGenerator2=_interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator")),_useInternalEngine=require("./useInternalEngine"),minRemainingTime=1.75;function run(a){var b=1i)){a.next=29;break}return a.t0=k,a.next=14,m;case 14:if(a.t1=a.sent,o=a.t0.next.call(a.t0,a.t1),p=o.value,q=o.done,m=void 0,!q){a.next=22;break}return f(p),a.abrupt("return");case 22:if(!0!==p){a.next=26;break}return a.abrupt("break",29);case 26:"number"==typeof p?(i=+p,isNaN(i)&&(i=minRemainingTime)):p&&p.then&&(m=p);case 27:a.next=10;break;case 29:a.next=36;break;case 31:return a.prev=31,a.t2=a["catch"](9),console.error(a.t2),g(a.t2),a.abrupt("return");case 36:(0,_useInternalEngine.request)(h),c&&(l=setTimeout(j,c));case 38:return a.prev=38,n=!1,a.finish(38);case 41:case"end":return a.stop();}},a,null,[[2,,38,41],[9,31]])})),i.apply(this,arguments)}function j(){var a=Date.now();h({timeout:!0,timeRemaining:function timeRemaining(){return 12.5-(Date.now()-a)}})}e=f;var k=a.next?a:a();(0,_useInternalEngine.request)(h);var l=0,m=void 0,n=!1});return f.terminate=function(a){d=!0,e&&e(a)},f}var _default=run;exports.default=_default; -------------------------------------------------------------------------------- /dist/es6/coroutines.js: -------------------------------------------------------------------------------- 1 | /** 2 | *

3 | * A coroutine to be run during the gaps in other processing and animation. 4 | *

5 | *

6 | * The coroutine should yield regularly to do a time check. A plain yield will cause 7 | * a check against the standard time remaining specified when running. yield {number} will 8 | * check that number milliseconds are available and yield true will abandon any more 9 | * processing on the current frame. 10 | *

11 | * @callback Coroutine 12 | * @generator 13 | * @yields {number} either undefined to perform a standard time remaining check, a number of milliseconds required for the next step or true if we should abandon the current frame 14 | * @returns the result of the function if any to be returned to the caller 15 | */ 16 | 17 | /** 18 | * @typedef IteratorResult 19 | * @object 20 | * @property {any} [value] - the returned value 21 | * @property {boolean} done - whether the iterator is complete 22 | */ 23 | 24 | /** 25 | * @interface Iterator 26 | */ 27 | 28 | /** 29 | * Get the next value 30 | * @function 31 | * @name Iterator#next 32 | * @param {any} value - value to send to the coroutine 33 | * @returns {IteratorResult} 34 | */ 35 | 36 | /** 37 | * A coroutine to be used in high priority to animate. 38 | * 39 | * Executing a yield will cause the routine to resume at the start 40 | * of the next frame. 41 | * @callback AnimationCoroutine 42 | * @generator 43 | * @returns the result of the function if any to be returned to the caller 44 | */ 45 | 46 | 47 | /** 48 | * @callback GeneratorFunction 49 | * @generator 50 | * @param {...*} params - the parameters to pass 51 | * @returns {*} the result of the coroutine 52 | */ 53 | 54 | /** 55 | * @callback AsyncFunction 56 | * @param {*} params - the parameters to pass 57 | * @async 58 | * @returns {*} result of calling the function 59 | */ 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /src/component/coroutines.js: -------------------------------------------------------------------------------- 1 | /** 2 | *

3 | * A coroutine to be run during the gaps in other processing and animation. 4 | *

5 | *

6 | * The coroutine should yield regularly to do a time check. A plain yield will cause 7 | * a check against the standard time remaining specified when running. yield {number} will 8 | * check that number milliseconds are available and yield true will abandon any more 9 | * processing on the current frame. 10 | *

11 | * @callback Coroutine 12 | * @generator 13 | * @yields {number} either undefined to perform a standard time remaining check, a number of milliseconds required for the next step or true if we should abandon the current frame 14 | * @returns the result of the function if any to be returned to the caller 15 | */ 16 | 17 | /** 18 | * @typedef IteratorResult 19 | * @object 20 | * @property {any} [value] - the returned value 21 | * @property {boolean} done - whether the iterator is complete 22 | */ 23 | 24 | /** 25 | * @interface Iterator 26 | */ 27 | 28 | /** 29 | * Get the next value 30 | * @function 31 | * @name Iterator#next 32 | * @param {any} value - value to send to the coroutine 33 | * @returns {IteratorResult} 34 | */ 35 | 36 | /** 37 | * A coroutine to be used in high priority to animate. 38 | * 39 | * Executing a yield will cause the routine to resume at the start 40 | * of the next frame. 41 | * @callback AnimationCoroutine 42 | * @generator 43 | * @returns the result of the function if any to be returned to the caller 44 | */ 45 | 46 | 47 | /** 48 | * @callback GeneratorFunction 49 | * @generator 50 | * @param {...*} params - the parameters to pass 51 | * @returns {*} the result of the coroutine 52 | */ 53 | 54 | /** 55 | * @callback AsyncFunction 56 | * @param {*} params - the parameters to pass 57 | * @async 58 | * @returns {*} result of calling the function 59 | */ 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /dist/group-by.js: -------------------------------------------------------------------------------- 1 | "use strict";var _regeneratorRuntime2=require("@babel/runtime/regenerator"),_interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports,"__esModule",{value:!0}),exports.groupBy=groupBy;var _regenerator=_interopRequireDefault(require("@babel/runtime/regenerator")),_marked=_regeneratorRuntime2.mark(groupBy);function _createForOfIteratorHelper(o,a){var b;if("undefined"==typeof Symbol||null==o[Symbol.iterator]){if(Array.isArray(o)||(b=_unsupportedIterableToArray(o))||a&&o&&"number"==typeof o.length){b&&(o=b);var c=0,d=function(){};return{s:d,n:function n(){return c>=o.length?{done:!0}:{done:!1,value:o[c++]}},e:function e(a){throw a},f:d}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var e,f=!0,g=!1;return{s:function s(){b=o[Symbol.iterator]()},n:function n(){var a=b.next();return f=a.done,a},e:function e(a){g=!0,e=a},f:function f(){try{f||null==b.return||b.return()}finally{if(g)throw e}}}}function _unsupportedIterableToArray(o,a){if(o){if("string"==typeof o)return _arrayLikeToArray(o,a);var n=Object.prototype.toString.call(o).slice(8,-1);return"Object"===n&&o.constructor&&(n=o.constructor.name),"Map"===n||"Set"===n?Array.from(o):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?_arrayLikeToArray(o,a):void 0}}function _arrayLikeToArray(a,b){(null==b||b>a.length)&&(b=a.length);for(var c=0,d=Array(b);cyields on a regular basis 9 | * @param {Function} fn - the function to be wrapped 10 | * @param {number} [frequency=8] - 11 | * the number of times the function should be called 12 | * before performing a yield 13 | * @returns {Coroutine} The wrapped yielding 14 | * version of the function passed 15 | */ 16 | export function yielding(fn, frequency = 16) { 17 | let yieldCount = 0; 18 | if(fn._yielding) return fn; 19 | let result = function* (...params) { 20 | let result = fn(...params); 21 | if(result && result.then) { 22 | result = yield result 23 | } 24 | if (yieldCount++ % frequency === 0) { 25 | yield; 26 | } 27 | return result; 28 | }; 29 | result._yielding = true 30 | return result 31 | } 32 | 33 | /** 34 | * @callback PromiseFn 35 | * @param {...*} [parameters] the parameters for the function 36 | * @return {Promise} a promise for the result of the function 37 | */ 38 | 39 | /** 40 | * Returns a function that will execute the passed 41 | * Coroutine and return a Promise for its result. The 42 | * returned function will take any number of parameters 43 | * and pass them on to the coroutine. 44 | * 45 | * @param {Coroutine} coroutine - The coroutine to run 46 | * @returns {PromiseFn|Function} a function that can be called to execute the coroutine 47 | * and return its result on completion 48 | */ 49 | export function wrapAsPromise(coroutine) { 50 | const result = function (...params) { 51 | return run(coroutine(...params)) 52 | }; 53 | result.with = function (...params) { 54 | return call(result, ...params) 55 | } 56 | return result 57 | } 58 | 59 | export function curryRight(fn, supplied, execute) { 60 | if(fn.length > supplied.length) { 61 | return function(...params) { 62 | return curryRight.call(this, fn, [...params, ...supplied], execute) 63 | } 64 | } 65 | return execute.apply(this, supplied) 66 | } 67 | -------------------------------------------------------------------------------- /src/component/wrappers.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | import run from './run' 4 | import {call} from './call' 5 | 6 | /** 7 | * Wraps a normal function into a generator function 8 | * that yields on a regular basis 9 | * @param {Function} fn - the function to be wrapped 10 | * @param {number} [frequency=8] - 11 | * the number of times the function should be called 12 | * before performing a yield 13 | * @returns {Coroutine} The wrapped yielding 14 | * version of the function passed 15 | */ 16 | export function yielding(fn, frequency = 16) { 17 | let yieldCount = 0; 18 | if(fn._yielding) return fn; 19 | let result = function* (...params) { 20 | let result = fn(...params); 21 | if(result && result.then) { 22 | result = yield result 23 | } 24 | if (yieldCount++ % frequency === 0) { 25 | yield; 26 | } 27 | return result; 28 | }; 29 | result._yielding = true 30 | return result 31 | } 32 | 33 | /** 34 | * @callback PromiseFn 35 | * @param {...*} [parameters] the parameters for the function 36 | * @return {Promise} a promise for the result of the function 37 | */ 38 | 39 | /** 40 | * Returns a function that will execute the passed 41 | * Coroutine and return a Promise for its result. The 42 | * returned function will take any number of parameters 43 | * and pass them on to the coroutine. 44 | * 45 | * @param {Coroutine} coroutine - The coroutine to run 46 | * @returns {PromiseFn|Function} a function that can be called to execute the coroutine 47 | * and return its result on completion 48 | */ 49 | export function wrapAsPromise(coroutine) { 50 | const result = function (...params) { 51 | return run(coroutine(...params)) 52 | }; 53 | result.with = function (...params) { 54 | return call(result, ...params) 55 | } 56 | return result 57 | } 58 | 59 | export function curryRight(fn, supplied, execute) { 60 | if(fn.length > supplied.length) { 61 | return function(...params) { 62 | return curryRight.call(this, fn, [...params, ...supplied], execute) 63 | } 64 | } 65 | return execute.apply(this, supplied) 66 | } 67 | -------------------------------------------------------------------------------- /dist/unique-by.js: -------------------------------------------------------------------------------- 1 | "use strict";var _regeneratorRuntime2=require("@babel/runtime/regenerator"),_interopRequireDefault=require("@babel/runtime/helpers/interopRequireDefault");Object.defineProperty(exports,"__esModule",{value:!0}),exports.uniqueBy=uniqueBy;var _regenerator=_interopRequireDefault(require("@babel/runtime/regenerator")),_marked=_regeneratorRuntime2.mark(uniqueBy);function _createForOfIteratorHelper(o,a){var b;if("undefined"==typeof Symbol||null==o[Symbol.iterator]){if(Array.isArray(o)||(b=_unsupportedIterableToArray(o))||a&&o&&"number"==typeof o.length){b&&(o=b);var c=0,d=function(){};return{s:d,n:function n(){return c>=o.length?{done:!0}:{done:!1,value:o[c++]}},e:function e(a){throw a},f:d}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var e,f=!0,g=!1;return{s:function s(){b=o[Symbol.iterator]()},n:function n(){var a=b.next();return f=a.done,a},e:function e(a){g=!0,e=a},f:function f(){try{f||null==b.return||b.return()}finally{if(g)throw e}}}}function _unsupportedIterableToArray(o,a){if(o){if("string"==typeof o)return _arrayLikeToArray(o,a);var n=Object.prototype.toString.call(o).slice(8,-1);return"Object"===n&&o.constructor&&(n=o.constructor.name),"Map"===n||"Set"===n?Array.from(o):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?_arrayLikeToArray(o,a):void 0}}function _arrayLikeToArray(a,b){(null==b||b>a.length)&&(b=a.length);for(var c=0,d=Array(b);cv * 2), 10 | stringifyAsync 11 | ) 12 | let result = await process('[1,2,3,4]') 13 | result.should.eq('[2,4,6,8]') 14 | }) 15 | it('should be able to run a singleton', async function () { 16 | const job = singleton(test1, 99) 17 | let value = 0 18 | job(21).then(r=>value = r) 19 | let result = await job(20) 20 | result.should.eq(20) 21 | value.should.eq(99) 22 | 23 | function * test1(value) { 24 | yield new Promise(resolve=>setTimeout(resolve, 50)) 25 | return value 26 | } 27 | }) 28 | it('should be able to repeat a function', async function () { 29 | let current 30 | const process = pipe( 31 | parseAsync, 32 | tap(capture), 33 | repeat(double, 2), 34 | stringifyAsync 35 | ) 36 | let result = await process('[1,2,3,4]') 37 | result.should.eq('[4,8,12,16]') 38 | current.should.deep.eq([1, 2, 3, 4]) 39 | function double(values) { 40 | return values.map(v=>v*2) 41 | } 42 | function capture(v) { 43 | current = v 44 | } 45 | }) 46 | it('should be able to branch', async function () { 47 | let output 48 | const process = pipe( 49 | parseAsync, 50 | branch(pipe(stringifyAsync, tap(capture))), 51 | mapAsync.with(v => v * 2), 52 | stringifyAsync 53 | ) 54 | let result = await process('[1,2,3,4]') 55 | result.should.eq('[2,4,6,8]') 56 | output.should.eq('[1,2,3,4]') 57 | function capture(values) { 58 | output = values 59 | } 60 | }) 61 | }) 62 | -------------------------------------------------------------------------------- /template/static/styles/prettify-jsdoc.css: -------------------------------------------------------------------------------- 1 | /* JSDoc prettify.js theme */ 2 | 3 | /* plain text */ 4 | .pln { 5 | color: #000000; 6 | font-weight: normal; 7 | font-style: normal; 8 | } 9 | 10 | /* string content */ 11 | .str { 12 | color: hsl(104, 100%, 24%); 13 | font-weight: normal; 14 | font-style: normal; 15 | } 16 | 17 | /* a keyword */ 18 | .kwd { 19 | color: #000000; 20 | font-weight: bold; 21 | font-style: normal; 22 | } 23 | 24 | /* a comment */ 25 | .com { 26 | font-weight: normal; 27 | font-style: italic; 28 | } 29 | 30 | /* a type name */ 31 | .typ { 32 | color: #000000; 33 | font-weight: normal; 34 | font-style: normal; 35 | } 36 | 37 | /* a literal value */ 38 | .lit { 39 | color: #006400; 40 | font-weight: normal; 41 | font-style: normal; 42 | } 43 | 44 | /* punctuation */ 45 | .pun { 46 | color: #000000; 47 | font-weight: bold; 48 | font-style: normal; 49 | } 50 | 51 | /* lisp open bracket */ 52 | .opn { 53 | color: #000000; 54 | font-weight: bold; 55 | font-style: normal; 56 | } 57 | 58 | /* lisp close bracket */ 59 | .clo { 60 | color: #000000; 61 | font-weight: bold; 62 | font-style: normal; 63 | } 64 | 65 | /* a markup tag name */ 66 | .tag { 67 | color: #006400; 68 | font-weight: normal; 69 | font-style: normal; 70 | } 71 | 72 | /* a markup attribute name */ 73 | .atn { 74 | color: #006400; 75 | font-weight: normal; 76 | font-style: normal; 77 | } 78 | 79 | /* a markup attribute value */ 80 | .atv { 81 | color: #006400; 82 | font-weight: normal; 83 | font-style: normal; 84 | } 85 | 86 | /* a declaration */ 87 | .dec { 88 | color: #000000; 89 | font-weight: bold; 90 | font-style: normal; 91 | } 92 | 93 | /* a variable name */ 94 | .var { 95 | color: #000000; 96 | font-weight: normal; 97 | font-style: normal; 98 | } 99 | 100 | /* a function name */ 101 | .fun { 102 | color: #000000; 103 | font-weight: bold; 104 | font-style: normal; 105 | } 106 | 107 | /* Specify class=linenums on a pre to get line numbering */ 108 | ol.linenums { 109 | margin-top: 0; 110 | margin-bottom: 0; 111 | } 112 | -------------------------------------------------------------------------------- /dist/update.js: -------------------------------------------------------------------------------- 1 | "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.update=update;function _createForOfIteratorHelper(o,a){var b;if("undefined"==typeof Symbol||null==o[Symbol.iterator]){if(Array.isArray(o)||(b=_unsupportedIterableToArray(o))||a&&o&&"number"==typeof o.length){b&&(o=b);var c=0,d=function(){};return{s:d,n:function n(){return c>=o.length?{done:!0}:{done:!1,value:o[c++]}},e:function e(a){throw a},f:d}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var e,f=!0,g=!1;return{s:function s(){b=o[Symbol.iterator]()},n:function n(){var a=b.next();return f=a.done,a},e:function e(a){g=!0,e=a},f:function f(){try{f||null==b.return||b.return()}finally{if(g)throw e}}}}function _unsupportedIterableToArray(o,a){if(o){if("string"==typeof o)return _arrayLikeToArray(o,a);var n=Object.prototype.toString.call(o).slice(8,-1);return"Object"===n&&o.constructor&&(n=o.constructor.name),"Map"===n||"Set"===n?Array.from(o):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?_arrayLikeToArray(o,a):void 0}}function _arrayLikeToArray(a,b){(null==b||b>a.length)&&(b=a.length);for(var c=0,d=Array(b);c=o.length?{done:!0}:{done:!1,value:o[c++]}},e:function e(a){throw a},f:d}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var e,f=!0,g=!1;return{s:function s(){b=o[Symbol.iterator]()},n:function n(){var a=b.next();return f=a.done,a},e:function e(a){g=!0,e=a},f:function f(){try{f||null==b.return||b.return()}finally{if(g)throw e}}}}function _unsupportedIterableToArray(o,a){if(o){if("string"==typeof o)return _arrayLikeToArray(o,a);var n=Object.prototype.toString.call(o).slice(8,-1);return"Object"===n&&o.constructor&&(n=o.constructor.name),"Map"===n||"Set"===n?Array.from(o):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?_arrayLikeToArray(o,a):void 0}}function _arrayLikeToArray(a,b){(null==b||b>a.length)&&(b=a.length);for(var c=0,d=Array(b);c 10000) animationCallbacks = animationCallbacks.slice(-9000) 12 | } 13 | 14 | function process() { 15 | let callbacks = animationCallbacks 16 | if (callbacks.length) { 17 | requestAnimationFrame(process) 18 | } else { 19 | requested = false 20 | } 21 | animationCallbacks = [] 22 | for (let callback of callbacks) { 23 | callback() 24 | } 25 | } 26 | 27 | /** 28 | * Start an animation coroutine, the animation will continue until 29 | * you return and will be broken up between frames by using a 30 | * yield. 31 | * 32 | * @param {AnimationCoroutine|Iterator} coroutine - The animation to run 33 | * @param {...*} [params] - Parameters to be passed to the animation function 34 | * @returns {Promise} a value that will be returned to the caller 35 | * when the animation is complete. 36 | * The promise returned by update has a terminate() method 37 | * that can be used to stop the routine. 38 | */ 39 | export function update(coroutine, ...params) { 40 | if (typeof window === 'undefined') throw new Error('Requires a browser to run') 41 | let terminated = false 42 | let resolver = null 43 | const result = new Promise(function (resolve, reject) { 44 | resolver = resolve 45 | const iterator = coroutine.next ? coroutine : coroutine(...params) 46 | nextAnimationFrame(run) 47 | 48 | function run() { 49 | if (terminated) { 50 | iterator.return() 51 | return 52 | } 53 | 54 | try { 55 | const {value, done} = iterator.next() 56 | if (done) { 57 | resolve(value) 58 | return 59 | } 60 | } catch (e) { 61 | reject(e) 62 | return 63 | } 64 | 65 | nextAnimationFrame(run) 66 | } 67 | }) 68 | result.terminate = function (result) { 69 | terminated = true 70 | if (resolver) { 71 | resolver(result) 72 | } 73 | } 74 | return result 75 | } 76 | -------------------------------------------------------------------------------- /src/component/update.js: -------------------------------------------------------------------------------- 1 | let requested = false 2 | let animationCallbacks = [] 3 | 4 | function nextAnimationFrame(fn) { 5 | if (typeof window === 'undefined') throw new Error('Cannot run without a browser') 6 | if (animationCallbacks.length === 0 && !requested) { 7 | requested = true 8 | requestAnimationFrame(process) 9 | } 10 | animationCallbacks.push(fn) 11 | if (animationCallbacks.length > 10000) animationCallbacks = animationCallbacks.slice(-9000) 12 | } 13 | 14 | function process() { 15 | let callbacks = animationCallbacks 16 | if (callbacks.length) { 17 | requestAnimationFrame(process) 18 | } else { 19 | requested = false 20 | } 21 | animationCallbacks = [] 22 | for (let callback of callbacks) { 23 | callback() 24 | } 25 | } 26 | 27 | /** 28 | * Start an animation coroutine, the animation will continue until 29 | * you return and will be broken up between frames by using a 30 | * yield. 31 | * 32 | * @param {AnimationCoroutine|Iterator} coroutine - The animation to run 33 | * @param {...*} [params] - Parameters to be passed to the animation function 34 | * @returns {Promise} a value that will be returned to the caller 35 | * when the animation is complete. 36 | * The promise returned by update has a terminate() method 37 | * that can be used to stop the routine. 38 | */ 39 | export function update(coroutine, ...params) { 40 | if (typeof window === 'undefined') throw new Error('Requires a browser to run') 41 | let terminated = false 42 | let resolver = null 43 | const result = new Promise(function (resolve, reject) { 44 | resolver = resolve 45 | const iterator = coroutine.next ? coroutine : coroutine(...params) 46 | nextAnimationFrame(run) 47 | 48 | function run() { 49 | if (terminated) { 50 | iterator.return() 51 | return 52 | } 53 | 54 | try { 55 | const {value, done} = iterator.next() 56 | if (done) { 57 | resolve(value) 58 | return 59 | } 60 | } catch (e) { 61 | reject(e) 62 | return 63 | } 64 | 65 | nextAnimationFrame(run) 66 | } 67 | }) 68 | result.terminate = function (result) { 69 | terminated = true 70 | if (resolver) { 71 | resolver(result) 72 | } 73 | } 74 | return result 75 | } 76 | -------------------------------------------------------------------------------- /src/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "js-coroutines", 3 | "sideEffects": [ 4 | "./dist/polyfill.js" 5 | ], 6 | "version": "2.4.36", 7 | "private": false, 8 | "files": [ 9 | "dist", 10 | "README.md", 11 | "LICENCE.txt" 12 | ], 13 | "repository": "https://github.com/miketalbot/js-coroutines", 14 | "main": "dist/index.js", 15 | "devDependencies": { 16 | "@babel/cli": "^7.13.14", 17 | "@babel/core": "^7.13.14", 18 | "@babel/plugin-proposal-class-properties": "^7.13.0", 19 | "@babel/plugin-transform-runtime": "^7.13.10", 20 | "@babel/polyfill": "^7.10.1", 21 | "@babel/preset-env": "^7.13.12", 22 | "@babel/preset-react": "^7.13.13", 23 | "@babel/register": "^7.13.14", 24 | "@pixi/jsdoc-template": "^2.6.0", 25 | "@testing-library/jest-dom": "^5.11.10", 26 | "@testing-library/react": "^11.2.6", 27 | "@testing-library/user-event": "^13.1.1", 28 | "babel-plugin-minify-mangle-names": "^0.5.0", 29 | "babel-preset-minify": "^0.5.1", 30 | "chai": "^4.3.4", 31 | "docdash": "^1.2.0", 32 | "dts-generator": "^3.0.0", 33 | "express": "^4.17.1", 34 | "jsdoc": "^3.6.6", 35 | "lodash": "^4.17.21", 36 | "mocha": "^8.3.2", 37 | "react": "^17.0.2", 38 | "react-dom": "^17.0.2", 39 | "react-scripts": "^4.0.3", 40 | "showdown": "^1.9.1", 41 | "tern": "^0.24.3", 42 | "tsd-jsdoc": "^2.5.0", 43 | "typescript": "^4.2.3", 44 | "versiony-cli": "^1.3.0" 45 | }, 46 | "scripts": { 47 | "start": "PORT=3012 react-scripts start", 48 | "dts": "node ./build-dts.js", 49 | "document": "rm -rf ./docs && jsdoc -c ./doc.conf.json && cp -r ./docs ../js-coroutines-web/public", 50 | "tsd": "jsdoc -t node_modules/tsd-jsdoc/dist -r ./src/component", 51 | "build": "source ./scripts/build.sh", 52 | "push": "node ./node_modules/versiony-cli/bin/cli.js ./package.json --patch && npm run build && npm publish && git add . && git commit -am build && git push", 53 | "watch": "NODE_ENV=production babel src/component --watch --ignore \"__tests__\",\"**/*.spec.js\",\"**/*.test.js\",\"__snapshots__\" --out-dir dist", 54 | "test": "mocha --require @babel/register src/test/**/*.test.js --exit", 55 | "eject": "react-scripts eject", 56 | "test-express": "npm run build && node ./src/test/basic-express.js" 57 | }, 58 | "eslintConfig": { 59 | "extends": "react-app" 60 | }, 61 | "types": "dist/es6/jscoroutines.d.ts", 62 | "typings": "dist/es6/jscoroutines.d.ts", 63 | "browserslist": { 64 | "production": [ 65 | ">0.2%", 66 | "not dead", 67 | "IE 11", 68 | "not op_mini all" 69 | ], 70 | "development": [ 71 | "last 1 chrome version", 72 | "last 1 firefox version", 73 | "last 1 safari version" 74 | ] 75 | }, 76 | "peerDependencies": { 77 | "@babel/runtime": ">=7.4.8" 78 | } 79 | } -------------------------------------------------------------------------------- /dist/async-compression-wrappers.js: -------------------------------------------------------------------------------- 1 | "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.base64Decompress=exports.base64decompressFromUTF16Async=exports.decompressAsync=exports.decompressFromEncodedURIComponentAsync=exports.decompressFromUint8ArrayAsync=exports.decompressFromUTF16Async=exports.decompressFromBase64Async=exports.base64Compress=exports.base64CompressToUTF16Async=exports.compressAsync=exports.compressToEncodedURIComponentAsync=exports.compressToUint8ArrayAsync=exports.compressToUTF16Async=exports.compressToBase64Async=void 0;var _wrappers=require("./wrappers"),_base64String=require("./lz-string/base64-string"),_lzString=require("./lz-string/lz-string"),compressToBase64Async=(0,_wrappers.wrapAsPromise)(_lzString.LZStringGenerator.compressToBase64);exports.compressToBase64Async=compressToBase64Async;var compressToUTF16Async=(0,_wrappers.wrapAsPromise)(_lzString.LZStringGenerator.compressToUTF16);exports.compressToUTF16Async=compressToUTF16Async;var compressToUint8ArrayAsync=(0,_wrappers.wrapAsPromise)(_lzString.LZStringGenerator.compressToUint8Array);exports.compressToUint8ArrayAsync=compressToUint8ArrayAsync;var compressToEncodedURIComponentAsync=(0,_wrappers.wrapAsPromise)(_lzString.LZStringGenerator.compressToEncodedURIComponent);exports.compressToEncodedURIComponentAsync=compressToEncodedURIComponentAsync;var compressAsync=(0,_wrappers.wrapAsPromise)(_lzString.LZStringGenerator.compress);exports.compressAsync=compressAsync;var base64CompressToUTF16Async=(0,_wrappers.wrapAsPromise)(_base64String.Base64StringGenerator.compressToUTF16);exports.base64CompressToUTF16Async=base64CompressToUTF16Async;var base64Compress=(0,_wrappers.wrapAsPromise)(_base64String.Base64StringGenerator.compress);exports.base64Compress=base64Compress;var decompressFromBase64Async=(0,_wrappers.wrapAsPromise)(_lzString.LZStringGenerator.decompressFromBase64);exports.decompressFromBase64Async=decompressFromBase64Async;var decompressFromUTF16Async=(0,_wrappers.wrapAsPromise)(_lzString.LZStringGenerator.decompressFromUTF16);exports.decompressFromUTF16Async=decompressFromUTF16Async;var decompressFromUint8ArrayAsync=(0,_wrappers.wrapAsPromise)(_lzString.LZStringGenerator.decompressFromUint8Array);exports.decompressFromUint8ArrayAsync=decompressFromUint8ArrayAsync;var decompressFromEncodedURIComponentAsync=(0,_wrappers.wrapAsPromise)(_lzString.LZStringGenerator.decompressFromURIComponent);exports.decompressFromEncodedURIComponentAsync=decompressFromEncodedURIComponentAsync;var decompressAsync=(0,_wrappers.wrapAsPromise)(_lzString.LZStringGenerator.decompress);exports.decompressAsync=decompressAsync;var base64decompressFromUTF16Async=(0,_wrappers.wrapAsPromise)(_base64String.Base64StringGenerator.decompressFromUTF16);exports.base64decompressFromUTF16Async=base64decompressFromUTF16Async;var base64Decompress=(0,_wrappers.wrapAsPromise)(_base64String.Base64StringGenerator.decompress);exports.base64Decompress=base64Decompress; -------------------------------------------------------------------------------- /template/static/scripts/pagelocation.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | $(document).ready(function () { 4 | var currentSectionNav, target; 5 | 6 | // If an anchor hash is in the URL highlight the menu item 7 | highlightActiveHash(); 8 | // If a specific page section is in the URL highlight the menu item 9 | highlightActiveSection(); 10 | 11 | // If a specific page section is in the URL scroll that section up to the top 12 | currentSectionNav = $('#' + getCurrentSectionName() + '-nav'); 13 | 14 | if (currentSectionNav.position()) { 15 | $('nav').scrollTop(currentSectionNav.position().top); 16 | } 17 | 18 | // function to scroll to anchor when clicking an anchor linl 19 | $('a[href*="#"]:not([href="#"])').click(function () { 20 | /* eslint-disable no-invalid-this */ 21 | if (location.pathname.replace(/^\//, '') === this.pathname.replace(/^\//, '') && location.hostname === this.hostname) { 22 | target = $(this.hash); 23 | target = target.length ? target : $('[name=' + this.hash.slice(1) + ']'); 24 | if (target.length) { 25 | $('html, body').animate({ 26 | scrollTop: target.offset().top 27 | }, 1000); 28 | } 29 | } 30 | /* eslint-enable no-invalid-this */ 31 | }); 32 | }); 33 | 34 | // If a new anchor section is selected, change the hightlighted menu item 35 | $(window).bind('hashchange', function (event) { 36 | highlightActiveHash(event); 37 | }); 38 | 39 | function highlightActiveHash(event) { 40 | var oldUrl, oldSubSectionElement; 41 | 42 | // check for and remove old hash active state 43 | if (event && event.originalEvent.oldURL) { 44 | oldUrl = event.originalEvent.oldURL; 45 | 46 | if (oldUrl.indexOf('#') > -1) { 47 | oldSubSectionElement = $('#' + getCurrentSectionName() + '-' + oldUrl.substring(oldUrl.indexOf('#') + 1) + '-nav'); 48 | 49 | if (oldSubSectionElement) { 50 | oldSubSectionElement.removeClass('active'); 51 | } 52 | } 53 | } 54 | 55 | if (getCurrentHashName()) { 56 | $('#' + getCurrentSectionName() + '-' + getCurrentHashName() + '-nav').addClass('active'); 57 | } 58 | } 59 | 60 | function highlightActiveSection() { 61 | var pageId = getCurrentSectionName(); 62 | 63 | $('#' + pageId + '-nav').addClass('active'); 64 | } 65 | 66 | function getCurrentSectionName() { 67 | var path = window.location.pathname; 68 | var pageUrl = path.split('/').pop(); 69 | 70 | var sectionName = pageUrl.substring(0, pageUrl.indexOf('.')); 71 | 72 | // remove the wodr module- if its in the url 73 | sectionName = sectionName.replace('module-', ''); 74 | 75 | return sectionName; 76 | } 77 | 78 | function getCurrentHashName() { 79 | var pageSubSectionId; 80 | var pageSubSectionHash = window.location.hash; 81 | 82 | if (pageSubSectionHash) { 83 | pageSubSectionId = pageSubSectionHash.substring(1).replace('.', ''); 84 | 85 | return pageSubSectionId; 86 | } 87 | 88 | return false; 89 | } 90 | -------------------------------------------------------------------------------- /template/static/styles/prettify-tomorrow.css: -------------------------------------------------------------------------------- 1 | /* Tomorrow Theme */ 2 | /* Original theme - https://github.com/chriskempson/tomorrow-theme */ 3 | /* Pretty printing styles. Used with prettify.js. */ 4 | /* SPAN elements with the classes below are added by prettyprint. */ 5 | /* plain text */ 6 | .pln { 7 | color: #4d4d4c; } 8 | 9 | @media screen { 10 | /* string content */ 11 | .str { 12 | color: hsl(104, 100%, 24%); } 13 | 14 | /* a keyword */ 15 | .kwd { 16 | color: hsl(240, 100%, 50%); } 17 | 18 | /* a comment */ 19 | .com { 20 | color: hsl(0, 0%, 60%); } 21 | 22 | /* a type name */ 23 | .typ { 24 | color: hsl(240, 100%, 32%); } 25 | 26 | /* a literal value */ 27 | .lit { 28 | color: hsl(240, 100%, 40%); } 29 | 30 | /* punctuation */ 31 | .pun { 32 | color: #000000; } 33 | 34 | /* lisp open bracket */ 35 | .opn { 36 | color: #000000; } 37 | 38 | /* lisp close bracket */ 39 | .clo { 40 | color: #000000; } 41 | 42 | /* a markup tag name */ 43 | .tag { 44 | color: #c82829; } 45 | 46 | /* a markup attribute name */ 47 | .atn { 48 | color: #f5871f; } 49 | 50 | /* a markup attribute value */ 51 | .atv { 52 | color: #3e999f; } 53 | 54 | /* a declaration */ 55 | .dec { 56 | color: #f5871f; } 57 | 58 | /* a variable name */ 59 | .var { 60 | color: #c82829; } 61 | 62 | /* a function name */ 63 | .fun { 64 | color: #4271ae; } } 65 | /* Use higher contrast and text-weight for printable form. */ 66 | @media print, projection { 67 | .str { 68 | color: #060; } 69 | 70 | .kwd { 71 | color: #006; 72 | font-weight: bold; } 73 | 74 | .com { 75 | color: #600; 76 | font-style: italic; } 77 | 78 | .typ { 79 | color: #404; 80 | font-weight: bold; } 81 | 82 | .lit { 83 | color: #044; } 84 | 85 | .pun, .opn, .clo { 86 | color: #440; } 87 | 88 | .tag { 89 | color: #006; 90 | font-weight: bold; } 91 | 92 | .atn { 93 | color: #404; } 94 | 95 | .atv { 96 | color: #060; } } 97 | /* Style */ 98 | /* 99 | pre.prettyprint { 100 | background: white; 101 | font-family: Consolas, Monaco, 'Andale Mono', monospace; 102 | font-size: 12px; 103 | line-height: 1.5; 104 | border: 1px solid #ccc; 105 | padding: 10px; } 106 | */ 107 | 108 | /* Get LI elements to show when they are in the main article */ 109 | article ul li { 110 | list-style-type: circle; 111 | margin-left: 25px; 112 | } 113 | 114 | /* Specify class=linenums on a pre to get line numbering */ 115 | ol.linenums { 116 | margin-top: 0; 117 | margin-bottom: 0; } 118 | 119 | /* IE indents via margin-left */ 120 | li.L0, 121 | li.L1, 122 | li.L2, 123 | li.L3, 124 | li.L4, 125 | li.L5, 126 | li.L6, 127 | li.L7, 128 | li.L8, 129 | li.L9 { 130 | /* */ } 131 | 132 | /* Alternate shading for lines */ 133 | li.L1, 134 | li.L3, 135 | li.L5, 136 | li.L7, 137 | li.L9 { 138 | /* */ } 139 | -------------------------------------------------------------------------------- /dist/es6/yastjson/lib/parse.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2020 5u9ar (zhuyingda) (c) 2020 Mike Talbot (Generator mods) 3 | * 4 | * The above copyright notice and this permission notice shall be included in all 5 | * copies or substantial portions of the Software. 6 | * 7 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 8 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 9 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 10 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 11 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 12 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 13 | * SOFTWARE. 14 | */ 15 | import { Tokenizer } from "./tokenizer"; 16 | import { AST } from "./ast"; 17 | import { ExprType } from "./expression"; 18 | import { TokenType } from "./token"; 19 | import { yielder } from "./yielder"; 20 | 21 | export class ASTParser { 22 | constructor(ast) { 23 | this.ast = ast; 24 | } 25 | 26 | *getJson() { 27 | return yield* this.handleValue(this.ast); 28 | } 29 | 30 | *handleJson(astNode) { 31 | if (astNode.type !== ExprType.Json) { 32 | throw new Error("[parse AST error] unexpected node type, expect Json"); 33 | } 34 | 35 | let output; 36 | let node = astNode.childNodeList[0]; 37 | if (node.type === ExprType.Array) { 38 | output = []; 39 | for (let item of node.childNodeList) { 40 | output.push(yield* this.handleValue(item.value)); 41 | } 42 | } else if (node.type === ExprType.Object) { 43 | output = {}; 44 | for (let item of node.childNodeList) { 45 | output[item.propName] = yield* this.handleValue( 46 | item.childNodeList[0].value 47 | ); 48 | } 49 | } else { 50 | throw new Error("[parse AST error] unexpected second node type"); 51 | } 52 | return output; 53 | } 54 | 55 | *handleValue(astNode) { 56 | if (yielder()) yield; 57 | let token; 58 | switch (astNode.type) { 59 | case TokenType.Null: 60 | return null; 61 | case TokenType.Boolean: 62 | token = astNode.tokens[0].text; 63 | return token === "true"; 64 | case TokenType.Number: 65 | let num = +astNode.tokens[0].text; 66 | return num; 67 | case TokenType.String: 68 | return astNode.tokens[0].text.slice(1, -1); 69 | case ExprType.Json: 70 | return yield* this.handleJson(astNode); 71 | default: 72 | throw new Error( 73 | "[parse AST error] unexpected node type, expect a valid Value node" 74 | ); 75 | } 76 | } 77 | } 78 | 79 | export function* parse(jsonString) { 80 | const tokenizer = new Tokenizer(); 81 | const tokens = yield* tokenizer.tokenize(jsonString); 82 | const astInst = new AST(tokens); 83 | const ast = yield* astInst.buildTree(); 84 | const astParser = new ASTParser(ast); 85 | return yield* astParser.getJson(); 86 | } 87 | -------------------------------------------------------------------------------- /src/component/yastjson/lib/parse.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2020 5u9ar (zhuyingda) (c) 2020 Mike Talbot (Generator mods) 3 | * 4 | * The above copyright notice and this permission notice shall be included in all 5 | * copies or substantial portions of the Software. 6 | * 7 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 8 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 9 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 10 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 11 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 12 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 13 | * SOFTWARE. 14 | */ 15 | import { Tokenizer } from "./tokenizer"; 16 | import { AST } from "./ast"; 17 | import { ExprType } from "./expression"; 18 | import { TokenType } from "./token"; 19 | import { yielder } from "./yielder"; 20 | 21 | export class ASTParser { 22 | constructor(ast) { 23 | this.ast = ast; 24 | } 25 | 26 | *getJson() { 27 | return yield* this.handleValue(this.ast); 28 | } 29 | 30 | *handleJson(astNode) { 31 | if (astNode.type !== ExprType.Json) { 32 | throw new Error("[parse AST error] unexpected node type, expect Json"); 33 | } 34 | 35 | let output; 36 | let node = astNode.childNodeList[0]; 37 | if (node.type === ExprType.Array) { 38 | output = []; 39 | for (let item of node.childNodeList) { 40 | output.push(yield* this.handleValue(item.value)); 41 | } 42 | } else if (node.type === ExprType.Object) { 43 | output = {}; 44 | for (let item of node.childNodeList) { 45 | output[item.propName] = yield* this.handleValue( 46 | item.childNodeList[0].value 47 | ); 48 | } 49 | } else { 50 | throw new Error("[parse AST error] unexpected second node type"); 51 | } 52 | return output; 53 | } 54 | 55 | *handleValue(astNode) { 56 | if (yielder()) yield; 57 | let token; 58 | switch (astNode.type) { 59 | case TokenType.Null: 60 | return null; 61 | case TokenType.Boolean: 62 | token = astNode.tokens[0].text; 63 | return token === "true"; 64 | case TokenType.Number: 65 | let num = +astNode.tokens[0].text; 66 | return num; 67 | case TokenType.String: 68 | return astNode.tokens[0].text.slice(1, -1); 69 | case ExprType.Json: 70 | return yield* this.handleJson(astNode); 71 | default: 72 | throw new Error( 73 | "[parse AST error] unexpected node type, expect a valid Value node" 74 | ); 75 | } 76 | } 77 | } 78 | 79 | export function* parse(jsonString) { 80 | const tokenizer = new Tokenizer(); 81 | const tokens = yield* tokenizer.tokenize(jsonString); 82 | const astInst = new AST(tokens); 83 | const ast = yield* astInst.buildTree(); 84 | const astParser = new ASTParser(ast); 85 | return yield* astParser.getJson(); 86 | } 87 | -------------------------------------------------------------------------------- /template/tmpl/properties.tmpl: -------------------------------------------------------------------------------- 1 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 80 | 81 | 82 | 91 | 92 | 93 | 94 | 99 | 100 | 101 | 107 | 108 | 109 | 110 | 111 |
NameTypeAttributesDefaultDescription
76 | 77 | 78 | 79 | 83 | 84 | <optional>
85 | 86 | 87 | 88 | <nullable>
89 | 90 |
95 | 96 | 97 | 98 | 102 | 103 | 104 |
Properties
105 | 106 |
112 | -------------------------------------------------------------------------------- /docs/scripts/search.js: -------------------------------------------------------------------------------- 1 | 2 | var searchAttr = 'data-search-mode'; 3 | function contains(a,m){ 4 | return (a.textContent || a.innerText || "").toUpperCase().indexOf(m) !== -1; 5 | }; 6 | 7 | //on search 8 | document.getElementById("nav-search").addEventListener("keyup", function(event) { 9 | var search = this.value.toUpperCase(); 10 | 11 | if (!search) { 12 | //no search, show all results 13 | document.documentElement.removeAttribute(searchAttr); 14 | 15 | document.querySelectorAll("nav > ul > li:not(.level-hide)").forEach(function(elem) { 16 | elem.style.display = "block"; 17 | }); 18 | 19 | if (typeof hideAllButCurrent === "function"){ 20 | //let's do what ever collapse wants to do 21 | hideAllButCurrent(); 22 | } else { 23 | //menu by default should be opened 24 | document.querySelectorAll("nav > ul > li > ul li").forEach(function(elem) { 25 | elem.style.display = "block"; 26 | }); 27 | } 28 | } else { 29 | //we are searching 30 | document.documentElement.setAttribute(searchAttr, ''); 31 | 32 | //show all parents 33 | document.querySelectorAll("nav > ul > li").forEach(function(elem) { 34 | elem.style.display = "block"; 35 | }); 36 | //hide all results 37 | document.querySelectorAll("nav > ul > li > ul li").forEach(function(elem) { 38 | elem.style.display = "none"; 39 | }); 40 | //show results matching filter 41 | document.querySelectorAll("nav > ul > li > ul a").forEach(function(elem) { 42 | if (!contains(elem.parentNode, search)) { 43 | return; 44 | } 45 | elem.parentNode.style.display = "block"; 46 | }); 47 | //hide parents without children 48 | document.querySelectorAll("nav > ul > li").forEach(function(parent) { 49 | var countSearchA = 0; 50 | parent.querySelectorAll("a").forEach(function(elem) { 51 | if (contains(elem, search)) { 52 | countSearchA++; 53 | } 54 | }); 55 | 56 | var countUl = 0; 57 | var countUlVisible = 0; 58 | parent.querySelectorAll("ul").forEach(function(ulP) { 59 | // count all elements that match the search 60 | if (contains(ulP, search)) { 61 | countUl++; 62 | } 63 | 64 | // count all visible elements 65 | var children = ulP.children 66 | for (i=0; i 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 78 | 79 | 80 | 81 | 82 | 83 | 88 | 89 | 90 | 103 | 104 | 105 | 106 | 111 | 112 | 113 | 120 | 121 | 122 | 124 | 125 |
NameTypeAttributesDefaultDescription
84 | 85 | 86 | 87 | 91 | 92 | <optional>
93 | 94 | 95 | 96 | <nullable>
97 | 98 | 99 | 100 | <repeatable>
101 | 102 |
107 | 108 | 109 | 110 | 114 | 115 | 116 |
Properties
117 | 118 | 119 |
126 | --------------------------------------------------------------------------------