diff --git a/.gitignore b/.gitignore index 9b08949279..1d7c0b3e5e 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,4 @@ export lib node_modules tachyons.min.css +zig-cache \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index cb8d32e4f1..79db3d4140 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,9 @@ language: node_js node_js: - - "10" + - "12" + - "11" branches: - only: - - master - - develop + only: + - master + - develop diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 62d0cd935f..f29043e999 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,43 +2,48 @@ Firstly, thanks for taking an interest in these projects! -There're many ways you can contribute and help to improve these projects and -help spread the word. This doc describes some guidelines for some of them. +There're many ways you can contribute and help to improve these projects +and help spread the word. This doc describes some guidelines for some of +them. ## Usage questions & issues -Please feel free to use the GH issue tracker for submitting any questions related -to any package in this repo. When doing so, please also follow the instructions in -the new issue template and use issue labels to tag your issue. +Please feel free to use the GH issue tracker for submitting any +questions related to any package in this repo. When doing so, please +also follow the instructions in the "new issue" template and use issue +labels to tag your issue. -When running into code troubles, please try to include a minimal reproducible example. -If the example is too large for including in the issue, please create a gist or repo -and add a link to it. +When running into code troubles, please try to include a minimal +reproducible example. If the example is too large for including in the +issue, please create a gist or repo and add a link to it. ## Documentation, examples & advocacy -Documentation is still sparse in some (many) areas, so any contributions -in the form listed below are very welcome. I primarily can only work on this -project in my spare time, so have to balance between adding new features (always my -priority) & documentation whenever I can. +Documentation is still sparse in some areas, so any contributions in the +form listed below are very welcome. I primarily can only work on this +project in my spare time, so have to balance between adding new features +(always my priority) & documentation whenever I can. ### Wiki additions, blog posts, examples -The wiki of this repo is currently still empty, however FAQs, tutorials, best practice -tips, feature ideas/roadmaps and a collection of links to blog posts, 3rd party examples -etc. is planned. If you have anything to contribute (or have already done so elsewhere), +The wiki of this repo is still pretty barebones, however adding some +gallery, FAQs, tutorials, best practice tips, feature ideas/roadmaps and +a collection of links to blog posts, 3rd party examples etc. is planned. +If you have anything to contribute (or have already done so elsewhere), please do get in touch. ### Small, standalone examples in the repo -Learn by example has been my life's motto. The examples included in the repo are each -focused on a specific feature and kept quite lowkey for reasons of simplicity. Since -many of the projects are meant to be integrated with other 3rd party projects, I'm always -on the lookout for similar small demos showcasing these integrations -(e.g. w/ React, WebGL, SVG etc.) +"Learning by example" has been my life's motto. The ~60 examples +included in the repo are each focused on a specific feature and kept +quite lowkey for reasons of simplicity. Since many of the projects are +meant to be integrated with other 3rd party projects, I'm always on the +lookout for similar small demos showcasing these integrations (e.g. w/ +React, WebGL, SVG etc.) -The repo contains a generator bash script to create a new example project skeleton in the -repo's `/examples` dir. Use it like below (and make sure the name is not already taken): +The repo contains a generator bash script to create a new example +project skeleton in the repo's `/examples` dir. Use it like below (and +make sure the name isn't already taken :) ``` cd umbrella @@ -47,22 +52,32 @@ scripts/make-example my-example cd examples/my-example ``` -(Note 1: the package versions used by this generator MIGHT be occasionally out-of-date) +(Note 1: the package versions used by this generator MIGHT be +occasionally out-of-date) -(Note 2: **If you've cloned the repo and built all packages, DO NOT run `yarn install` -in the example dir. `yarn dev` will work without and re-use the built packages -(irrespective of their version) in the project root**) +(Note 2: **If you've cloned the repo and built all packages, DO NOT run +`yarn install` in the example dir. `yarn start` will work without and +re-use the built packages (irrespective of their version) in the project +root**) -If you choose to add a new example this way (and not elsewhere on the interweb), -please also read the next section... +FWIW I usually launch examples from the repo root like this: + +```bash +(cd examples/webgl-msdf && yarn start) +``` + +If you choose to add a new example this way (and not elsewhere on the +interweb), please also read the next section... ## Contributing code -**IMPORTANT:** To avoid misunderstandings or disappointment, please always first submit -an issue discussing a new feature or large refactoring before starting to code and -submitting PRs. For small bugfixes or new examples it's usually fine without, though. -Not trying to complicate things, but it's always good to first talk about larger -contributions. +**IMPORTANT:** To avoid misunderstandings or disappointment, please +always first submit an issue discussing any new feature or large +refactoring before starting to code and submitting PRs. For small bug +fixes or new examples it's usually fine without, though. I'm not trying +to complicate things, but it's always good to first talk about larger +contributions and there're also various feature branches, incl. some +existing WIP relevant to your issue / proposal. ### Fork it @@ -74,15 +89,18 @@ cd umbrella yarn build ``` -### Create a feature branch: +### Create a feature branch + +**Always use `develop` as base branch!** ``` git checkout -b feature/my-feature develop ``` -I'm in the process of switching to the git-flow branching model for this repo and all -new development should be done on feature branches based off the current `develop` branch. -PR's submitted directly against the `master` branch MIGHT be refused in the future. +This repo is using the `git-flow` branching model and all new +development should be done on feature branches based off the current +`develop` branch. PR's submitted directly against the `master` branch +MIGHT be refused. ### Commit your changes @@ -109,11 +127,14 @@ The Conventional Commits classifiers/prefixes used in this project are: ### Run & add tests -All sub-projects have a varying (but growing) number of unit tests. -If you're adding a new feature (or think you've fixed a bug), please -add some related tests (if possible). Either by adding a new file -under a project's `/test` dir or editing one of the existing test -cases in there. +I'm heavily using the node REPL during development and do much of my +testing as part of that workflow. Still, I'm aware that this is no full +replacement for a large suite of tests, therefore most packages do have +a varying (and growing) number of unit tests. If you're adding a new +feature (or think you've fixed a bug), please add some related tests (if +possible) too for extra brownie points. Either add a new file under a +project's `/test` dir or add / edit one of the existing test cases in +there. ### Push to the branch @@ -133,43 +154,34 @@ Most packages in this repo share this pattern: - `/src/index.ts` - only used for re-exports - `/src/api.ts` - interface, enum, type alias and module global consts definitions -- `/test` - contains Mocha unit tests +- `/test` - Mocha unit tests -In larger packages (e.g. [@thi.ng/transducers](https://github.com/thi-ng/umbrella/tree/master/packages/transducers)) +In larger packages (e.g. +[@thi.ng/transducers](https://github.com/thi-ng/umbrella/tree/master/packages/transducers)) topically related files are grouped in sub-folders under `/src`. ### Imports -To encourage small(er) file sizes of production artefacts most source files -are organized to only contain a minimum number of related functions/classes. -That too means, when importing from other packages, please try to refrain from -whole module imports and specify exactly which imports are required. - -NAY: -```typescript -import * as tx from "thi.ng/transducers"; -``` - -YAY: -```typescript## -import { step } from "thi.ng/transducers/step"; -import { map } from "thi.ng/transducers/xform/map"; -import { permutations } from "thi.ng/transducers/iter/permutations"; -``` +To encourage small(er) file sizes of production artefacts most source +files are organized to only contain a small number of related functions +/ classes. Package internal imports MUST always refer to the actual +source file, whereas imports from other packages MUST only use the +package name. This is because of the way each package is built and +output in 3 different module formats (ES6, CJS, UMD). ### No default exports -Nuff said. They're potentially problematic in terms of refactoring and too cause -inconsistencies compared to the above named import pattern. +Nuff said. They're potentially problematic in terms of refactoring and +too cause inconsistencies compared to the above named import pattern. ### No 3rd party dependencies -Unless absolutely warranted. Yes, this is somewhat a case of _Not-Invented-Here_, -but here done for reasons of sanity & clarity, not to prove a point. If you plan -to submit code with 3rd party deps, please get in touch first and explain why -it's necessary. +**This does NOT apply to examples, only code in source packages** -**This does NOT apply to examples, only code in main packages** +Unless absolutely warranted. Yes, this is somewhat a case of +_Not-Invented-Here_, but here done for reasons of sanity & clarity, not +to prove a point. If you plan to submit code with 3rd party deps, please +get in touch first and explain why it's necessary IYHO. ### 4 spaces @@ -181,10 +193,11 @@ Personally I use VSCode with TSLint's recommended rules ## Donations -I've been developing this project (as well as several large other open source -projects since the late '90s) in my spare time. If you would like to support -the continued development of this project, your donations to the following -addresses would be greatly appreciated: +I've been developing this project (as well as several large other open +source projects since the late '90s) in my spare time since early 2016 +(some packages even older). If you would like to support the continued +development of this project, your donations to the following addresses +would be greatly appreciated: - BTC: 132aMfzNypBPgEy4Lz2tPQsKGimixdFrsb - LTC: LMyfhJoXTq62W9zvUBvk9o6pCDZJx12dPV diff --git a/README.md b/README.md index f7712af23d..32715c5f74 100644 --- a/README.md +++ b/README.md @@ -7,17 +7,20 @@ ## About -Mono-repository for thi.ng TypeScript/ES6 projects, a wide collection of -largely data transformation oriented packages and building blocks for: - -- functional programming (composition, memoization, transducers, multi-methods) -- stream based, reactive programming, dataflow graphs / pipelines -- data structures & data transformations for wide range of use cases -- data driven UI components, event & side effect handling -- immutable data handling -- geometry generation, processing & visualization -- vector & matrix implementations with optional support for strided layouts -- low-level tooling for binary data, shared memory / WASM / WebGL interop +Mono-repository for almost 100 thi.ng TypeScript/ES6 projects, a wide +collection of largely data transformation oriented packages and building +blocks for: + +- Functional programming (composition, memoization, transducers, multi-methods) +- Stream based, reactive programming, dataflow graphs / pipelines +- Data structures & data transformations for wide range of use cases +- Data driven UI components, event & side effect handling +- Immutable data handling +- Geometry generation, processing & visualization +- Vector & matrix implementations with optional support for strided layouts +- Declarative WebGL 1/2 abstraction layer +- DSL for shader functions defined in TypeScript and cross-compilation to GLSL, JS, VEX etc. +- Low-level tooling for binary data, shared memory / WASM / WebGL interop - etc. (see package overview below) **...all with a keen eye on simplicity, re-use & minimalism without @@ -46,7 +49,7 @@ Most packages: ## Examples -There's a steadily growing number (40+) of standalone examples +There's a steadily growing number (~60) of standalone examples (different complexities, often combining functionality from several packages) in the [examples](./examples) directory. @@ -60,6 +63,14 @@ packages) in the [examples](./examples) directory. - [Part 3 - Convolution, 1D/2D Cellular automata](https://medium.com/@thi.ng/of-umbrellas-transducers-reactive-streams-mushrooms-pt-3-a1c4e621db9b) - [Part 4 - Disjoint Sets, Graph analysis, Signed Distance Fields](https://medium.com/@thi.ng/of-umbrellas-transducers-reactive-streams-mushrooms-pt-4-62d8e71e5603) +## Community + +Join our little community on our [Discord +server](https://discord.gg/JhYcmBw) or get in touch via +[Twitter](https://twitter.com/thing_umbrella) or the [issue +tracker](https://github.com/thi-ng/umbrella/issues). If you'd like to +contribute, please first read [this document](./CONTRIBUTING.md). + ## Projects ### Fundamentals @@ -170,20 +181,32 @@ packages) in the [examples](./examples) directory. | [`@thi.ng/poisson`](./packages/poisson) | [![version](https://img.shields.io/npm/v/@thi.ng/poisson.svg)](https://www.npmjs.com/package/@thi.ng/poisson) | [changelog](./packages/poisson/CHANGELOG.md) | nD Poisson disk sampling | | [`@thi.ng/vectors`](./packages/vectors) | [![version](https://img.shields.io/npm/v/@thi.ng/vectors.svg)](https://www.npmjs.com/package/@thi.ng/vectors) | [changelog](./packages/vectors/CHANGELOG.md) | Fixed & arbitrary-length vector ops | +### WebGL / GPGPU + +| Project | Version | Changelog | Description | +|-------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------|------------------------------------| +| [`@thi.ng/shader-ast`](./packages/shader-ast) | [![version](https://img.shields.io/npm/v/@thi.ng/shader-ast.svg)](https://www.npmjs.com/package/@thi.ng/shader-ast) | [changelog](./packages/shader-ast/CHANGELOG.md) | AST DSL for x-platform shader code | +| [`@thi.ng/shader-ast-glsl`](./packages/shader-ast-glsl) | [![version](https://img.shields.io/npm/v/@thi.ng/shader-ast-glsl.svg)](https://www.npmjs.com/package/@thi.ng/shader-ast-glsl) | [changelog](./packages/shader-ast-glsl/CHANGELOG.md) | GLSL code generator | +| [`@thi.ng/shader-ast-js`](./packages/shader-ast-js) | [![version](https://img.shields.io/npm/v/@thi.ng/shader-ast-js.svg)](https://www.npmjs.com/package/@thi.ng/shader-ast-js) | [changelog](./packages/shader-ast-js/CHANGELOG.md) | JS code generator | +| [`@thi.ng/shader-ast-stdlib`](./packages/shader-ast-stdlib) | [![version](https://img.shields.io/npm/v/@thi.ng/shader-ast-stdlib.svg)](https://www.npmjs.com/package/@thi.ng/shader-ast-stdlib) | [changelog](./packages/shader-ast-stdlib/CHANGELOG.md) | Useful AST shader functions | +| [`@thi.ng/webgl`](./packages/webgl) | [![version](https://img.shields.io/npm/v/@thi.ng/webgl.svg)](https://www.npmjs.com/package/@thi.ng/webgl) | [changelog](./packages/webgl/CHANGELOG.md) | WebGL 1/2 / GPGPU facilities | +| [`@thi.ng/webgl-msdf`](./packages/webgl-msdf) | [![version](https://img.shields.io/npm/v/@thi.ng/webgl-msdf.svg)](https://www.npmjs.com/package/@thi.ng/webgl-msdf) | [changelog](./packages/webgl-msdf/CHANGELOG.md) | MSDF font rendering | + ### Low-level, binary, memory management -| Project | Version | Changelog | Description | -|---------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------|-------------------------------------------| -| [`@thi.ng/bencode`](./packages/bencode) | [![version](https://img.shields.io/npm/v/@thi.ng/bencode.svg)](https://www.npmjs.com/package/@thi.ng/bencode) | [changelog](./packages/bencode/CHANGELOG.md) | Bencode binary format encoding | -| [`@thi.ng/binary`](./packages/binary) | [![version](https://img.shields.io/npm/v/@thi.ng/binary.svg)](https://www.npmjs.com/package/@thi.ng/binary) | [changelog](./packages/binary/CHANGELOG.md) | Assorted binary / bitwise ops, utilities | -| [`@thi.ng/bitstream`](./packages/bitstream) | [![version](https://img.shields.io/npm/v/@thi.ng/bitstream.svg)](https://www.npmjs.com/package/@thi.ng/bitstream) | [changelog](./packages/bitstream/CHANGELOG.md) | Bitwise input / output streams | -| [`@thi.ng/dlogic`](./packages/dlogic) | [![version](https://img.shields.io/npm/v/@thi.ng/dlogic.svg)](https://www.npmjs.com/package/@thi.ng/dlogic) | [changelog](./packages/dlogic/CHANGELOG.md) | Digital logic ops / constructs | -| [`@thi.ng/malloc`](./packages/malloc) | [![version](https://img.shields.io/npm/v/@thi.ng/malloc.svg)](https://www.npmjs.com/package/@thi.ng/malloc) | [changelog](./packages/malloc/CHANGELOG.md) | Raw & typed array memory pool & allocator | -| [`@thi.ng/morton`](./packages/morton) | [![version](https://img.shields.io/npm/v/@thi.ng/morton.svg)](https://www.npmjs.com/package/@thi.ng/morton) | [changelog](./packages/morton/CHANGELOG.md) | Z-order-curve / Morton coding | -| [`@thi.ng/range-coder`](./packages/range-coder) | [![version](https://img.shields.io/npm/v/@thi.ng/range-coder.svg)](https://www.npmjs.com/package/@thi.ng/range-coder) | [changelog](./packages/range-coder/CHANGELOG.md) | Binary data Range encoder / decoder | -| [`@thi.ng/rle-pack`](./packages/rle-pack) | [![version](https://img.shields.io/npm/v/@thi.ng/rle-pack.svg)](https://www.npmjs.com/package/@thi.ng/rle-pack) | [changelog](./packages/rle-pack/CHANGELOG.md) | Run-length encoding data compression | -| [`@thi.ng/unionstruct`](./packages/unionstruct) | [![version](https://img.shields.io/npm/v/@thi.ng/unionstruct.svg)](https://www.npmjs.com/package/@thi.ng/unionstruct) | [changelog](./packages/unionstruct/CHANGELOG.md) | Wrapper for C-like structs / unions | -| [`@thi.ng/vector-pools`](./packages/vector-pools) | [![version](https://img.shields.io/npm/v/@thi.ng/vector-pools.svg)](https://www.npmjs.com/package/@thi.ng/vector-pools) | [changelog](./packages/vector-pools/CHANGELOG.md) | data structures for memory mapped vectors | +| Project | Version | Changelog | Description | +|---------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------|--------------------------------------------| +| [`@thi.ng/bencode`](./packages/bencode) | [![version](https://img.shields.io/npm/v/@thi.ng/bencode.svg)](https://www.npmjs.com/package/@thi.ng/bencode) | [changelog](./packages/bencode/CHANGELOG.md) | Bencode binary format encoding | +| [`@thi.ng/binary`](./packages/binary) | [![version](https://img.shields.io/npm/v/@thi.ng/binary.svg)](https://www.npmjs.com/package/@thi.ng/binary) | [changelog](./packages/binary/CHANGELOG.md) | Assorted binary / bitwise ops, utilities | +| [`@thi.ng/bitstream`](./packages/bitstream) | [![version](https://img.shields.io/npm/v/@thi.ng/bitstream.svg)](https://www.npmjs.com/package/@thi.ng/bitstream) | [changelog](./packages/bitstream/CHANGELOG.md) | Bitwise input / output streams | +| [`@thi.ng/dlogic`](./packages/dlogic) | [![version](https://img.shields.io/npm/v/@thi.ng/dlogic.svg)](https://www.npmjs.com/package/@thi.ng/dlogic) | [changelog](./packages/dlogic/CHANGELOG.md) | Digital logic ops / constructs | +| [`@thi.ng/leb128`](./packages/leb128) | [![version](https://img.shields.io/npm/v/@thi.ng/leb128.svg)](https://www.npmjs.com/package/@thi.ng/leb128) | [changelog](./packages/leb128/CHANGELOG.md) | WASM based LEB128 varint encoder / decoder | +| [`@thi.ng/malloc`](./packages/malloc) | [![version](https://img.shields.io/npm/v/@thi.ng/malloc.svg)](https://www.npmjs.com/package/@thi.ng/malloc) | [changelog](./packages/malloc/CHANGELOG.md) | Raw & typed array memory pool & allocator | +| [`@thi.ng/morton`](./packages/morton) | [![version](https://img.shields.io/npm/v/@thi.ng/morton.svg)](https://www.npmjs.com/package/@thi.ng/morton) | [changelog](./packages/morton/CHANGELOG.md) | Z-order-curve / Morton coding | +| [`@thi.ng/range-coder`](./packages/range-coder) | [![version](https://img.shields.io/npm/v/@thi.ng/range-coder.svg)](https://www.npmjs.com/package/@thi.ng/range-coder) | [changelog](./packages/range-coder/CHANGELOG.md) | Binary data Range encoder / decoder | +| [`@thi.ng/rle-pack`](./packages/rle-pack) | [![version](https://img.shields.io/npm/v/@thi.ng/rle-pack.svg)](https://www.npmjs.com/package/@thi.ng/rle-pack) | [changelog](./packages/rle-pack/CHANGELOG.md) | Run-length encoding data compression | +| [`@thi.ng/unionstruct`](./packages/unionstruct) | [![version](https://img.shields.io/npm/v/@thi.ng/unionstruct.svg)](https://www.npmjs.com/package/@thi.ng/unionstruct) | [changelog](./packages/unionstruct/CHANGELOG.md) | Wrapper for C-like structs / unions | +| [`@thi.ng/vector-pools`](./packages/vector-pools) | [![version](https://img.shields.io/npm/v/@thi.ng/vector-pools.svg)](https://www.npmjs.com/package/@thi.ng/vector-pools) | [changelog](./packages/vector-pools/CHANGELOG.md) | data structures for memory mapped vectors | ### DSLs @@ -192,10 +215,6 @@ packages) in the [examples](./examples) directory. | [`@thi.ng/pointfree`](./packages/pointfree) | [![version](https://img.shields.io/npm/v/@thi.ng/pointfree.svg)](https://www.npmjs.com/package/@thi.ng/pointfree) | [changelog](./packages/pointfree/CHANGELOG.md) | Stack-based DSL & functional composition | | [`@thi.ng/pointfree-lang`](./packages/pointfree-lang) | [![version](https://img.shields.io/npm/v/@thi.ng/pointfree-lang.svg)](https://www.npmjs.com/package/@thi.ng/pointfree-lang) | [changelog](./packages/pointfree-lang/CHANGELOG.md) | Forth-like syntax layer for @thi.ng/pointfree | -### WIP / unreleased - -- [@thi.ng/webgl](https://github.com/thi-ng/umbrella/tree/feature/webgl/packages/webgl) - ## Building ```bash diff --git a/assets/screenshots/shader-ast-01.jpg b/assets/screenshots/shader-ast-01.jpg new file mode 100644 index 0000000000..16cde7d999 Binary files /dev/null and b/assets/screenshots/shader-ast-01.jpg differ diff --git a/assets/screenshots/shader-ast-raymarch-compare.jpg b/assets/screenshots/shader-ast-raymarch-compare.jpg new file mode 100644 index 0000000000..25be7ccc6e Binary files /dev/null and b/assets/screenshots/shader-ast-raymarch-compare.jpg differ diff --git a/assets/screenshots/shader-ast-raymarch-vex-sm.gif b/assets/screenshots/shader-ast-raymarch-vex-sm.gif new file mode 100644 index 0000000000..ac323f9ee1 Binary files /dev/null and b/assets/screenshots/shader-ast-raymarch-vex-sm.gif differ diff --git a/examples/README.md b/examples/README.md index 7b7c365fbf..f1191ac313 100644 --- a/examples/README.md +++ b/examples/README.md @@ -26,27 +26,44 @@ in touch via PR, issue tracker, email or twitter! | 15 | [hdom-canvas-clock](./hdom-canvas-clock) | hdom-canvas rendered clock | hdom, hdom-canvas, transducers | basic | | 16 | [hdom-canvas-draw](./hdom-canvas-draw) | hdom-canvas mouse / touch gesture drawing | hdom, hdom-canvas, transducers | intermediate | | 17 | [hdom-canvas-shapes](./hdom-canvas-shapes) | various hdom-canvas shape tests | hdom, hdom-canvas, rstream, transducers | basic | -| 18 | [hdom-dyn-context](./hdom-dyn-context) | dynamic hdom user context / theming | atom, hdom | basic | -| 19 | [hdom-skip](./hdom-skip) | selective component updates | hdom | basic | -| 20 | [hdom-theme-adr-0003](./hdom-theme-adr-0003) | hdom themed components proposal | hdom | intermediate | -| 21 | [hmr-basics](./hmr-basics) | hdom & hot module replacement | hdom, memoize | basic | -| 22 | [hydrate-basics](./hydrate-basics) | hiccup / hdom DOM hydration | hiccup, hdom | intermediate | -| 23 | [interceptor-basics](./interceptor-basics) | Event handling w/ interceptors and side effects | atom, hdom, interceptors | basic | -| 24 | [interceptor-basics2](./interceptor-basics2) | Event handling w/ interceptors and side effects | atom, hdom, interceptors | intermediate | -| 25 | [json-components](./json-components) | JSON->component transformation, live editor | hdom, transducers | intermediate | -| 26 | [login-form](./login-form) | Basic SPA without router | atom, hdom | intermediate | -| 27 | [mandelbrot](./mandelbrot) | Worker-based mandelbrot fractal renderer | rstream, rstream-gestures, transducers-hdom | advanced | -| 28 | [markdown](./markdown) | Markdown parser & editor w/ live preview | fsm, rstream, transducers-hdom | advanced | -| 29 | [pointfree-svg](./pointfree-svg) | Generate SVG using pointfree DSL | hiccup, hiccup-svg, pointfree-lang | intermediate | -| 30 | [router-basics](./router-basics) | Complete mini SPA | atom, hdom, interceptors, router | advanced | -| 31 | [rstream-dataflow](./rstream-dataflow) | Dataflow graph | atom, hdom, rstream, rstream-gestures, rstream-graph, transducers | intermediate | -| 32 | [rstream-grid](./rstream-grid) | Dataflow graph SVG grid | atom, hdom, hiccup-svg, interceptors, rstream-graph, transducers | advanced | -| 33 | [rstream-hdom](./rstream-hdom) | rstream based UI updates & state handling | hdom, rstream, transducers | intermediate | -| 34 | [svg-barchart](./svg-barchart) | hdom SVG barchart component | hdom, transducers | basic | -| 35 | [svg-particles](./svg-particles) | hdom SVG generation / animation | hdom, transducers | basic | -| 36 | [svg-waveform](./svg-waveform) | hdom SVG generation / undo history | atom, hdom, hiccup-svg, interceptors, iterators | intermediate | -| 37 | [todo-list](./todo-list) | Canonical Todo list with undo/redo | atom, hdom, transducers | intermediate | -| 38 | [transducers-hdom](./transducers-hdom) | Transducer & rstream based hdom UI updates | hdom, rstream, transducers-hdom | basic | -| 39 | [triple-query](./triple-query) | Triple store query results & sortable table | atom, hdom, hdom-components, rstream-query, transducers | intermediate | -| 40 | [webgl](./webgl) | Canvas component handling | hdom, hdom-components | basic | -| 41 | [xml-converter](./xml-converter) | XML/HTML/SVG to hiccup conversion as you type | rstream, sax, transducers, transducers-hdom | advanced | +| 18 | [hdom-dropdown](./hdom-dropdown) | custom dropdown menu | hdom, hdom-components | intermediate | +| 19 | [hdom-dropdown-fuzzy](./hdom-dropdown-fuzzy) | custom dropdown menu w/ fuzzy autocomplete | hdom, hdom-components | advanced | +| 20 | [hdom-dyn-context](./hdom-dyn-context) | dynamic hdom user context / theming | atom, hdom | basic | +| 21 | [hdom-inner-html](./hdom-inner-html) | using `.innerHTML` w/ hdom | hdom | intermediate | +| 22 | [hdom-localstate](./hdom-localstate) | hdom component with local state | hdom | intermediate | +| 23 | [hdom-skip](./hdom-skip) | selective component updates | hdom | basic | +| 24 | [hdom-theme-adr-0003](./hdom-theme-adr-0003) | hdom themed components proposal | hdom | intermediate | +| 25 | [hdom-vscroller](./hdom-vscroller) | virtual scroller component for large tables / lists | hdom | advanced | +| 26 | [hmr-basics](./hmr-basics) | hdom & hot module replacement | hdom, memoize | basic | +| 27 | [hydrate-basics](./hydrate-basics) | hiccup / hdom DOM hydration | hiccup, hdom | intermediate | +| 28 | [interceptor-basics](./interceptor-basics) | Event handling w/ interceptors and side effects | atom, hdom, interceptors | basic | +| 29 | [interceptor-basics2](./interceptor-basics2) | Event handling w/ interceptors and side effects | atom, hdom, interceptors | intermediate | +| 30 | [iso-plasma](./iso-plasma) | 2D contour line extraction & animation | geom, geom-isoline | intermediate | +| 31 | [json-components](./json-components) | JSON->component transformation, live editor | hdom, transducers | intermediate | +| 32 | [login-form](./login-form) | Basic SPA without router | atom, hdom | intermediate | +| 33 | [mandelbrot](./mandelbrot) | Worker-based mandelbrot fractal renderer | rstream, rstream-gestures, transducers-hdom | advanced | +| 34 | [markdown](./markdown) | Markdown parser & editor w/ live preview | fsm, rstream, transducers-hdom | advanced | +| 35 | [package-stats](./package-stats) | CLI util to visualize umbrella pkg stats | hiccup-svg, transducers | intermediate | +| 36 | [pointfree-svg](./pointfree-svg) | Generate SVG using pointfree DSL | hiccup, hiccup-svg, pointfree-lang | intermediate | +| 37 | [router-basics](./router-basics) | Complete mini SPA | atom, hdom, interceptors, router | advanced | +| 38 | [rstream-dataflow](./rstream-dataflow) | Dataflow graph | atom, hdom, rstream, rstream-gestures, rstream-graph, transducers | intermediate | +| 39 | [rstream-grid](./rstream-grid) | Dataflow graph SVG grid | atom, hdom, hiccup-svg, interceptors, rstream-graph, transducers | advanced | +| 40 | [rstream-hdom](./rstream-hdom) | rstream based UI updates & state handling | hdom, rstream, transducers | intermediate | +| 41 | [shader-ast-canvas2d](shader-ast-canvas2d) | 2D canvas shader emulation | shader-ast | basic | +| 42 | [shader-ast-noise](shader-ast-noise) | HOF shader function composition | shader-ast, webgl | basic | +| 43 | [shader-ast-raymarch](shader-ast-raymarch) | WebGL & Canvas2D raymarch shader | shader-ast, webgl | intermediate | +| 44 | [shader-ast-sdf2d](shader-ast-sdf2d) | WebGL & Canvas2D SDF | shader-ast, webgl | basic | +| 45 | [shader-ast-tunnel](shader-ast-tunnel) | WebGL & Canvas2D textured tunnel shader | shader-ast, webgl | basic | +| 46 | [svg-barchart](./svg-barchart) | hdom SVG barchart component | hdom, transducers | basic | +| 47 | [svg-particles](./svg-particles) | hdom SVG generation / animation | hdom, transducers | basic | +| 48 | [svg-waveform](./svg-waveform) | hdom SVG generation / undo history | atom, hdom, hiccup-svg, interceptors, iterators | intermediate | +| 49 | [talk-slides](./talk-slides) | Presentation slides from ClojureX 2018 | hdom, rstream, transducers-hdom | intermediate | +| 50 | [todo-list](./todo-list) | Canonical Todo list with undo/redo | atom, hdom, transducers | intermediate | +| 51 | [transducers-hdom](./transducers-hdom) | Transducer & rstream based hdom UI updates | hdom, rstream, transducers-hdom | basic | +| 52 | [triple-query](./triple-query) | Triple store query results & sortable table | atom, hdom, hdom-components, rstream-query, transducers | intermediate | +| 53 | [webgl-cubemap](./webgl-cubemap) | WebGL cubemap, async texture loading | hdom, webgl, shader-ast | intermediate | +| 54 | [webgl-gpgpu-basics](./webgl-gpgpu-basics) | Minimal GPGPU example | webgl, shader-ast | basic | +| 55 | [webgl-grid](./webgl-grid) | WebGL instancing | webgl, hdom | intermediate | +| 56 | [webgl-msdf](./webgl-msdf) | WebGL MSDF font rendering & particle system | webgl, webgl-msdf, shader-ast, hdom | intermediate | +| 57 | [webgl-ssao](./webgl-ssao) | WebGL screenspace ambient occlusion | webgl, shader-ast, rstream, hdom | advanced | +| 58 | [xml-converter](./xml-converter) | XML/HTML/SVG to hiccup conversion as you type | rstream, sax, transducers, transducers-hdom | advanced | diff --git a/examples/async-effect/package.json b/examples/async-effect/package.json index d21b9ce2d3..a6a9e2aa51 100644 --- a/examples/async-effect/package.json +++ b/examples/async-effect/package.json @@ -12,8 +12,8 @@ }, "devDependencies": { "parcel-bundler": "^1.12.3", - "terser": "^3.17.0", - "typescript": "^3.4.1" + "terser": "^4.0.0", + "typescript": "^3.5.2" }, "dependencies": { "@thi.ng/api": "latest", @@ -26,4 +26,4 @@ "browser": { "process": false } -} +} \ No newline at end of file diff --git a/examples/bitmap-font/package.json b/examples/bitmap-font/package.json index b870312608..1f44f95758 100644 --- a/examples/bitmap-font/package.json +++ b/examples/bitmap-font/package.json @@ -12,8 +12,8 @@ "devDependencies": { "parcel-bundler": "^1.12.3", "rimraf": "^2.6.3", - "terser": "^3.17.0", - "typescript": "^3.4.1" + "terser": "^4.0.0", + "typescript": "^3.5.2" }, "dependencies": { "@thi.ng/api": "latest", @@ -30,4 +30,4 @@ "browser": { "process": false } -} +} \ No newline at end of file diff --git a/examples/bitmap-font/src/index.ts b/examples/bitmap-font/src/index.ts index 7df02d85db..4c2a02f256 100644 --- a/examples/bitmap-font/src/index.ts +++ b/examples/bitmap-font/src/index.ts @@ -1,7 +1,12 @@ import { IObjectOf } from "@thi.ng/api"; import { dropdown } from "@thi.ng/hdom-components"; import { clamp } from "@thi.ng/math"; -import { stream, Stream, sync } from "@thi.ng/rstream"; +import { + stream, + Stream, + Subscription, + sync +} from "@thi.ng/rstream"; import { comp, map, @@ -17,6 +22,9 @@ import { bits } from "@thi.ng/transducers-binary"; import { updateDOM } from "@thi.ng/transducers-hdom"; import { FONT } from "./font"; +const emitOnStream = (stream: Subscription) => (e: Event) => + stream.next((e.target).value); + // retrieve font bytes for given char const lookupChar = (c: string) => FONT[clamp(c.charCodeAt(0) - 32, 0, FONT.length - 1)]; @@ -62,7 +70,7 @@ const charSelector = (stream: Stream) => [ dropdown, { class: "ml3", - onchange: (e) => stream.next(e.target.value) + onchange: emitOnStream(stream) }, [ ["#", "#"], @@ -80,14 +88,14 @@ const charSelector = (stream: Stream) => [ ]; // main UI root component -const app = ({ raw, result }) => [ +const app = ({ raw, result }: any) => [ "div", [ "div", [ "input", { - oninput: (e) => input.next(e.target.value), + oninput: emitOnStream(input), value: raw } ], @@ -103,9 +111,11 @@ const on = stream(); const off = stream(); // transforming stream combinator -const xformer = sync({ src: { input, on, off } }).transform(map(banner)); +const xformer = sync({ src: { input, on, off } }).transform( + map(banner) +); -const main = sync({ src: { raw: input, result: xformer } }); +const main = sync({ src: { raw: input, result: xformer } }); main.transform(map(app), updateDOM()); // kick off diff --git a/examples/bitmap-font/tsconfig.json b/examples/bitmap-font/tsconfig.json index bbf112cc18..3c1d9eef6d 100644 --- a/examples/bitmap-font/tsconfig.json +++ b/examples/bitmap-font/tsconfig.json @@ -3,9 +3,8 @@ "compilerOptions": { "outDir": ".", "target": "es6", - "sourceMap": true + "sourceMap": true, + "strictBindCallApply": false }, - "include": [ - "./src/**/*.ts" - ] + "include": ["./src/**/*.ts"] } diff --git a/examples/canvas-dial/package.json b/examples/canvas-dial/package.json index 842a748f52..9eaaafae2e 100644 --- a/examples/canvas-dial/package.json +++ b/examples/canvas-dial/package.json @@ -11,8 +11,8 @@ }, "devDependencies": { "parcel-bundler": "^1.12.3", - "terser": "^3.17.0", - "typescript": "^3.4.1" + "terser": "^4.0.0", + "typescript": "^3.5.2" }, "dependencies": { "@thi.ng/api": "latest", @@ -33,4 +33,4 @@ "browser": { "process": false } -} +} \ No newline at end of file diff --git a/examples/canvas-dial/src/dial.ts b/examples/canvas-dial/src/dial.ts index 14fab20cc5..fb6181da5b 100644 --- a/examples/canvas-dial/src/dial.ts +++ b/examples/canvas-dial/src/dial.ts @@ -111,8 +111,8 @@ const TAU = 2 * PI; * * @param opts */ -export const dial = (opts: Partial) => { - opts = { +export const dial = (_opts: Partial) => { + const opts = { cx: 0.5, cy: 0.5, r1: 0.5, @@ -126,10 +126,10 @@ export const dial = (opts: Partial) => { labelColor: "black", labelYOffset: 0, font: "10px sans-serif", - ...opts + ..._opts }; let events: Subscription; - let cx, cy; + let cx: number, cy: number; const startTheta = opts.base + opts.gap / 2; const drawRing = ( diff --git a/examples/canvas-dial/src/index.ts b/examples/canvas-dial/src/index.ts index cf4594fb73..d4b44c6336 100644 --- a/examples/canvas-dial/src/index.ts +++ b/examples/canvas-dial/src/index.ts @@ -57,7 +57,7 @@ const app = () => { label: (x) => percent(2)(x), onchange: (x) => ctx.streams.c.next(x) }); - return ({ a, b, c }) => [ + return ({ a, b, c }: any) => [ "div", ctx.ui.root, [dialA, ctx.ui.dial, a], @@ -67,7 +67,7 @@ const app = () => { }; // stream combinator & reactive DOM update -sync({ +sync({ src: ctx.streams, xform: comp(map(app()), updateDOM()) }); diff --git a/examples/cellular-automata/package.json b/examples/cellular-automata/package.json index 5495bc90bf..ad14dd101f 100644 --- a/examples/cellular-automata/package.json +++ b/examples/cellular-automata/package.json @@ -11,8 +11,8 @@ }, "devDependencies": { "parcel-bundler": "^1.12.3", - "terser": "^3.17.0", - "typescript": "^3.4.1" + "terser": "^4.0.0", + "typescript": "^3.5.2" }, "dependencies": { "@thi.ng/hdom": "latest", @@ -26,4 +26,4 @@ "browser": { "process": false } -} +} \ No newline at end of file diff --git a/examples/cellular-automata/src/index.ts b/examples/cellular-automata/src/index.ts index 65513fc610..7e8297e2fe 100644 --- a/examples/cellular-automata/src/index.ts +++ b/examples/cellular-automata/src/index.ts @@ -46,7 +46,7 @@ const parseRules = step( comp(map((x: string) => parseInt(x.replace("-", ""), 2)), bits(18)) ); -const applyRules = (raw) => { +const applyRules = (raw: string) => { if (raw.length >= 18) { rules = parseRules(raw); randomizeGrid(); @@ -55,7 +55,7 @@ const applyRules = (raw) => { }; // create random bit sequence w/ ones appearing in given probability -const randomSeq = (num, prob = 0.5) => [ +const randomSeq = (num: number, prob = 0.5) => [ ...repeatedly(() => (Math.random() < prob ? 1 : 0), num) ]; @@ -80,7 +80,7 @@ export const convolve = ( rstride = 9, wrap = true ) => - transduce( + transduce( comp( convolve2d({ src, width, height, kernel, wrap }), mapIndexed((i, x) => rules[x + src[i] * rstride]) @@ -102,32 +102,36 @@ const format = (src: number[], width: number, fill = "\u2588", empty = " ") => ); // event handler for rule edits -const setRule = (i: number, j: number, s: number, rstride = 9) => { +const setRule = (i: number, j: number, s: boolean, rstride = 9) => { rules[i * rstride + j] = s ? 1 : 0; setHash(); }; // single checkbox component -const checkbox = (x, onchange) => [ +const checkbox = (x: number, onchange: EventListener) => [ "input", { type: "checkbox", checked: !!x, onchange } ]; // component for single CA rule group (alive / dead FSM) -const ruleBoxes = (prefix, i, rstride = 9) => [ +const ruleBoxes = (prefix: string, i: number, rstride = 9) => [ "div", ["label", prefix], ...rules .slice(i * rstride, (i + 1) * rstride) .map((rule, j) => - checkbox(rule, (e) => setRule(i, j, e.target.checked)) + checkbox(rule, (e) => + setRule(i, j, (e.target).checked) + ) ) ]; -const isPreset = (id) => presets.findIndex((x) => x[0] === id) !== -1; +const isPreset = (id: string) => presets.findIndex((x) => x[0] === id) !== -1; // Use Conway CA default state rules [[dead], [alive]] if no preset present in hash -applyRules(location.hash.length > 18 ? location.hash.substr(1) : presets[1][0]); +applyRules( + location.hash.length > 18 ? location.hash.substr(1) : presets[1][0] +); // define & start main app component start(() => { @@ -142,7 +146,10 @@ start(() => { ["button", { onclick: () => randomizeGrid() }, "reset grid"], [ dropdown, - { onchange: (e) => applyRules(e.target.value) }, + { + onchange: (e: Event) => + applyRules((e.target).value) + }, presets, isPreset(id) ? id : "" ] diff --git a/examples/commit-table-ssr/package.json b/examples/commit-table-ssr/package.json index 0ad7427c71..02ce03a9c3 100644 --- a/examples/commit-table-ssr/package.json +++ b/examples/commit-table-ssr/package.json @@ -13,8 +13,8 @@ }, "devDependencies": { "parcel-bundler": "^1.12.3", - "terser": "^3.17.0", - "typescript": "^3.4.1" + "terser": "^4.0.0", + "typescript": "^3.5.2" }, "dependencies": { "express": "^4.16.3", @@ -33,4 +33,4 @@ "browser": { "process": false } -} +} \ No newline at end of file diff --git a/examples/crypto-chart/package.json b/examples/crypto-chart/package.json index 983641eae5..d0d66c06b2 100644 --- a/examples/crypto-chart/package.json +++ b/examples/crypto-chart/package.json @@ -11,8 +11,8 @@ }, "devDependencies": { "parcel-bundler": "^1.12.3", - "terser": "^3.17.0", - "typescript": "^3.4.1" + "terser": "^4.0.0", + "typescript": "^3.5.2" }, "dependencies": { "@thi.ng/hdom-components": "latest", @@ -30,4 +30,4 @@ "browser": { "process": false } -} +} \ No newline at end of file diff --git a/examples/crypto-chart/src/index.ts b/examples/crypto-chart/src/index.ts index 532ddceef6..bcaeafe1ee 100644 --- a/examples/crypto-chart/src/index.ts +++ b/examples/crypto-chart/src/index.ts @@ -1,3 +1,4 @@ +import { Fn, IObjectOf } from "@thi.ng/api"; import { dropdown, DropDownOption } from "@thi.ng/hdom-components"; import { group, @@ -8,12 +9,14 @@ import { svg, text } from "@thi.ng/hiccup-svg"; +import { fit } from "@thi.ng/math"; import { resolve } from "@thi.ng/resolve-map"; import { fromEvent, fromInterval, resolve as resolvePromise, stream, + Subscription, sync, trace } from "@thi.ng/rstream"; @@ -30,10 +33,16 @@ import { pluck, push, range, - transduce + transduce, + Transducer } from "@thi.ng/transducers"; import { updateDOM } from "@thi.ng/transducers-hdom"; -import { ema, hma, sma, wma } from "@thi.ng/transducers-stats"; +import { + ema, + hma, + sma, + wma +} from "@thi.ng/transducers-stats"; // this example demonstrates how to use @thi.ng/rstream & // @thi.ng/transducer constructs to create a basic cryptocurrency candle @@ -58,7 +67,7 @@ interface MarketResponse { // constant definitions // supported chart (and API) timeframes -const TIMEFRAMES = { +const TIMEFRAMES: IObjectOf = { 1: "Minute", 60: "Hour", 1440: "Day" @@ -74,7 +83,10 @@ const SYMBOL_PAIRS: DropDownOption[] = [ ["XMRUSD", "XMR-USD"] ]; -const MA_MODES = { +const MA_MODES: IObjectOf<{ + fn: Fn>; + label: string; +}> = { ema: { fn: ema, label: "Exponential" }, hma: { fn: hma, label: "Hull" }, sma: { fn: sma, label: "Simple" }, @@ -86,13 +98,13 @@ const MARGIN_X = 80; const MARGIN_Y = 60; const DAY = 60 * 60 * 24; -const TIME_TICKS = { +const TIME_TICKS: IObjectOf = { 1: 15 * 60, 60: DAY, 1440: DAY * 14 }; -const TIME_FORMATS = { +const TIME_FORMATS: IObjectOf> = { 1: (t: number) => { const d = new Date(t * 1000); return `${Z2(d.getUTCHours())}:${Z2(d.getUTCMinutes())}`; @@ -112,7 +124,7 @@ const TIME_FORMATS = { }; // UI theme presets -const THEMES = { +const THEMES: any = { light: { id: "light", label: "Light", @@ -155,7 +167,7 @@ const THEMES = { // constructs request URL from given inputs // API docs: https://min-api.cryptocompare.com/ -const API_URL = (market, symbol, period) => +const API_URL = (market: string, symbol: string, period: number) => `https://min-api.cryptocompare.com/data/histo${TIMEFRAMES[ period ].toLowerCase()}?fsym=${symbol.substr(0, 3)}&tsym=${symbol.substr( @@ -166,19 +178,21 @@ const API_URL = (market, symbol, period) => // const API_URL = (..._) => `ohlc.json`; // helper functions -const clamp = (x: number, min: number, max: number) => - x < min ? min : x > max ? max : x; -const fit = (x, a, b, c, d) => c + (d - c) * clamp((x - a) / (b - a), 0, 1); const Z2 = padLeft(2, "0"); -const emitOnStream = (stream) => (e) => stream.next(e.target.value); +const emitOnStream = (stream: Subscription) => (e: Event) => + stream.next((e.target).value); -const menu = (stream, title, items) => +const menu = ( + stream: Subscription, + title: string, + items: DropDownOption[] +) => map((x: any) => dropdown( null, { class: "w-100", onchange: emitOnStream(stream) }, - [[, title, true], ...items], + [[null, title, true], ...items], String(x) ) ); @@ -199,7 +213,7 @@ error.subscribe({ next: (e) => alert(`An error occurred:\n${e}`) }); const refresh = fromInterval(60000).subscribe(trace("refresh")); // this stream combinator performs API requests to obtain OHLC data -const response = sync({ +const response = sync({ src: { market, symbol, period, refresh }, xform: map((inst) => fetch(API_URL(inst.market, inst.symbol, inst.period)) @@ -214,7 +228,7 @@ const response = sync({ // this stream combinator computes a number of statistics on incoming OHLC data // including calculation of moving averages (based on current mode selection) -const data = sync({ +const data = sync({ src: { response, avg: avgMode.transform(map((id: string) => MA_MODES[id].fn)) @@ -362,7 +376,8 @@ const chart = sync({ ), // moving averages map( - ([period, vals]) => sma(vals, theme.chart[`sma${period}`]), + ([period, vals]: [number, number[]]) => + sma(vals, theme.chart[`sma${period}`]), data.sma ), // candles @@ -433,7 +448,8 @@ sync({ map((x) => x.id), menu(theme, "Theme", [ ...map( - ([id, theme]) => [id, theme.label], + ([id, theme]: [string, any]) => + [id, theme.label], pairs(THEMES) ) ]) diff --git a/examples/dashboard/package.json b/examples/dashboard/package.json index 146da0ee73..a1d189d625 100644 --- a/examples/dashboard/package.json +++ b/examples/dashboard/package.json @@ -11,8 +11,8 @@ }, "devDependencies": { "parcel-bundler": "^1.12.3", - "terser": "^3.17.0", - "typescript": "^3.4.1" + "terser": "^4.0.0", + "typescript": "^3.5.2" }, "dependencies": { "@thi.ng/hdom": "latest" @@ -23,4 +23,4 @@ "browser": { "process": false } -} +} \ No newline at end of file diff --git a/examples/dashboard/src/index.ts b/examples/dashboard/src/index.ts index edb85a2ca1..20580e289a 100644 --- a/examples/dashboard/src/index.ts +++ b/examples/dashboard/src/index.ts @@ -1,7 +1,7 @@ import { start } from "@thi.ng/hdom"; // static component function to create styled box -const box = (prefix, body) => [ +const box = (prefix: string, body: any) => [ "div", { style: { @@ -20,7 +20,7 @@ const box = (prefix, body) => [ ]; // stateful component function -const counter = (id, from = 0, step = 1) => () => +const counter = (id: string, from = 0, step = 1) => () => box(id, (from += step).toLocaleString()); // dynamic component function (external state, i.e. date) diff --git a/examples/devcards/package.json b/examples/devcards/package.json index 67b9e73eae..b6a60dd016 100644 --- a/examples/devcards/package.json +++ b/examples/devcards/package.json @@ -11,8 +11,8 @@ }, "devDependencies": { "parcel-bundler": "^1.12.3", - "terser": "^3.17.0", - "typescript": "^3.4.1" + "terser": "^4.0.0", + "typescript": "^3.5.2" }, "dependencies": { "@thi.ng/api": "latest", @@ -25,4 +25,4 @@ "browser": { "process": false } -} +} \ No newline at end of file diff --git a/examples/devcards/src/index.ts b/examples/devcards/src/index.ts index b7b55fd658..bc568a9fda 100644 --- a/examples/devcards/src/index.ts +++ b/examples/devcards/src/index.ts @@ -86,8 +86,8 @@ function slider(state: IAtom, opts: SliderOpts) { const attribs = { ...opts, type: "range", - oninput: (e) => { - state.reset(e.target.value); + oninput: (e: Event) => { + state.reset((e.target).value); opts.onchange && opts.onchange(e); } }; @@ -141,7 +141,7 @@ function bmi(state: IAtom) { ); // another derived view to create SVG visualization - const bmiScale = (x) => ((x - 10) / 30) * 100 + "%"; + const bmiScale = (x: number) => ((x - 10) / 30) * 100 + "%"; const bmiViz = state.addView("bmi", (bmi: number) => [ "div", [ diff --git a/examples/geom-knn/package.json b/examples/geom-knn/package.json index ae009b253e..74e4d7b66b 100644 --- a/examples/geom-knn/package.json +++ b/examples/geom-knn/package.json @@ -11,8 +11,8 @@ }, "devDependencies": { "parcel-bundler": "^1.12.3", - "terser": "^3.17.0", - "typescript": "^3.4.1" + "terser": "^4.0.0", + "typescript": "^3.5.2" }, "dependencies": { "@thi.ng/bench": "latest", @@ -30,4 +30,4 @@ "browser": { "process": false } -} +} \ No newline at end of file diff --git a/examples/geom-knn/src/index.ts b/examples/geom-knn/src/index.ts index 35a0a114db..d98119ac41 100644 --- a/examples/geom-knn/src/index.ts +++ b/examples/geom-knn/src/index.ts @@ -1,13 +1,13 @@ import { timedResult } from "@thi.ng/bench"; import { KdTree } from "@thi.ng/geom-accel"; import { canvas } from "@thi.ng/hdom-canvas"; -import { sync, trigger } from "@thi.ng/rstream"; +import { StreamSync, sync, trigger } from "@thi.ng/rstream"; import { gestureStream } from "@thi.ng/rstream-gestures"; import { map, mapcat } from "@thi.ng/transducers"; import { updateDOM } from "@thi.ng/transducers-hdom"; import { Vec } from "@thi.ng/vectors"; -const app = (main) => { +const app = (main: StreamSync) => { // augment hdom-canvas component w/ `init` lifecycle method: this is // method is called when the canvas DOM element is first created and // used to attach a mouse & touch event stream to it. this stream is @@ -25,7 +25,7 @@ const app = (main) => { let tree = new KdTree(2); // return root component function, triggered by each new mouse / touch event - return ({ mpos }) => { + return ({ mpos }: { mpos: Vec }) => { // recreate tree every 500 points (in lieu of re-balancing) if (!(tree.length % 500)) { tree = new KdTree(2, tree); @@ -67,7 +67,7 @@ const app = (main) => { "div", `Points: ${tree.length}, Sel: ${selected.length}, `, `Neighbors: ${neighbors.length}, Q1: ${t1}ms, Q2: ${t2}ms, `, - `Height: ${tree.root.height()}, Ratio: ${tree + `Height: ${tree.root!.height()}, Ratio: ${tree .balanceRatio() .toFixed(2)}` ], @@ -97,7 +97,7 @@ const app = (main) => { // component's `init` method is called which attaches the above gesture // stream dynamically. the entire UI then only updates when there are new // user interactions... -const main = sync({ src: { trigger: trigger() } }); +const main = sync({ src: { trigger: trigger() } }); // transform result stream using the // root component fn and the hdom differential // update transducer diff --git a/examples/geom-tessel/package.json b/examples/geom-tessel/package.json index 897de978ba..85a6f76857 100644 --- a/examples/geom-tessel/package.json +++ b/examples/geom-tessel/package.json @@ -11,8 +11,8 @@ }, "devDependencies": { "parcel-bundler": "^1.12.3", - "terser": "^3.17.0", - "typescript": "^3.4.1" + "terser": "^4.0.0", + "typescript": "^3.5.2" }, "dependencies": { "@thi.ng/compose": "latest", @@ -28,4 +28,4 @@ "browser": { "process": false } -} +} \ No newline at end of file diff --git a/examples/geom-tessel/src/index.ts b/examples/geom-tessel/src/index.ts index 5d2c8f70df..21fe68b806 100644 --- a/examples/geom-tessel/src/index.ts +++ b/examples/geom-tessel/src/index.ts @@ -1,12 +1,4 @@ import { partial } from "@thi.ng/compose/partial"; -import { IShape, Tessellator } from "@thi.ng/geom-api"; -import { edgeSplit, quadFan, triFan } from "@thi.ng/geom-tessellate"; -import { canvas } from "@thi.ng/hdom-canvas"; -import { deg, fit01, fit11 } from "@thi.ng/math"; -import { fromInterval, sync } from "@thi.ng/rstream"; -import { map } from "@thi.ng/transducers"; -import { updateDOM } from "@thi.ng/transducers-hdom"; -import { polar, Vec } from "@thi.ng/vectors"; import { arcLength, asPolygon, @@ -16,6 +8,14 @@ import { polygon, tessellate } from "@thi.ng/geom"; +import { IShape, Tessellator } from "@thi.ng/geom-api"; +import { edgeSplit, quadFan, triFan } from "@thi.ng/geom-tessellate"; +import { canvas } from "@thi.ng/hdom-canvas"; +import { deg, fit01, fit11 } from "@thi.ng/math"; +import { fromInterval, sync } from "@thi.ng/rstream"; +import { map } from "@thi.ng/transducers"; +import { updateDOM } from "@thi.ng/transducers-hdom"; +import { polar, Vec } from "@thi.ng/vectors"; type Tint = (p: Polygon) => string; @@ -37,7 +37,7 @@ const W2 = W / 2; * space to HSL. */ const centroidToHSL = (p: IShape) => { - const c = polar(null, centroid(p)); + const c = polar(null, centroid(p)!); const h = deg(c[1]); const s = fit01(c[0] / W2, 0, 100); const l = fit01(c[0] / W2, 100, 50); @@ -77,7 +77,7 @@ const tessellation = (t: number, tessel: Tessellator[], tint: Tint) => { ).map(partial(tintedPoly, tint)); }; -const main = sync({ +const main = sync({ src: { time: fromInterval(16) } diff --git a/examples/gesture-analysis/package.json b/examples/gesture-analysis/package.json index b773d3646f..e7ec63feed 100644 --- a/examples/gesture-analysis/package.json +++ b/examples/gesture-analysis/package.json @@ -11,8 +11,8 @@ }, "devDependencies": { "parcel-bundler": "^1.12.3", - "terser": "^3.17.0", - "typescript": "^3.4.1" + "terser": "^4.0.0", + "typescript": "^3.5.2" }, "dependencies": { "@thi.ng/arrays": "latest", @@ -29,4 +29,4 @@ "browser": { "process": false } -} +} \ No newline at end of file diff --git a/examples/gesture-analysis/src/index.ts b/examples/gesture-analysis/src/index.ts index dcc241f463..7b07e0355f 100644 --- a/examples/gesture-analysis/src/index.ts +++ b/examples/gesture-analysis/src/index.ts @@ -1,13 +1,14 @@ import { peek } from "@thi.ng/arrays"; import { identity } from "@thi.ng/compose"; import { polyline as gPolyline, resample, vertices } from "@thi.ng/geom"; -import { circle, group, polyline, svg } from "@thi.ng/hiccup-svg"; -import { fromIterable, merge, sync } from "@thi.ng/rstream"; import { - GestureEvent, - gestureStream, - GestureType -} from "@thi.ng/rstream-gestures"; + circle, + group, + polyline, + svg +} from "@thi.ng/hiccup-svg"; +import { fromIterable, merge, sync } from "@thi.ng/rstream"; +import { GestureEvent, gestureStream, GestureType } from "@thi.ng/rstream-gestures"; import { comp, filter, @@ -18,7 +19,12 @@ import { transduce } from "@thi.ng/transducers"; import { updateDOM } from "@thi.ng/transducers-hdom"; -import { angleBetween2, mixN2, sub2, Vec } from "@thi.ng/vectors"; +import { + angleBetween2, + mixN2, + sub2, + Vec +} from "@thi.ng/vectors"; import { CTA } from "./config"; /** @@ -28,7 +34,13 @@ import { CTA } from "./config"; * @param raw * @param processed */ -const app = ({ raw, processed }) => [ +const app = ({ + raw, + processed +}: { + raw: Vec[]; + processed: { path: Vec[]; corners: Vec[] }; +}) => [ "div", svg( { @@ -122,7 +134,7 @@ const collectPath = () => { }; // gesture input stream(s) -const gesture = merge({ +const gesture = merge({ src: [ // the initial CTA (call-to-action) gesture (see config.ts) // will be shown prior to first user interaction. @@ -144,7 +156,7 @@ const gesture = merge({ // to create a resampled version and apply a corner detector // the resulting stream will emit tuple objects of this structure: // `{ raw: Vec2[], processed: { path: Vec2[], corners: Vec2[] } } -sync({ +sync({ src: { raw: gesture, processed: gesture.transform( diff --git a/examples/hdom-basics/package.json b/examples/hdom-basics/package.json index 877c1fe33c..b481e8a0a0 100644 --- a/examples/hdom-basics/package.json +++ b/examples/hdom-basics/package.json @@ -11,8 +11,8 @@ }, "devDependencies": { "parcel-bundler": "^1.12.3", - "terser": "^3.17.0", - "typescript": "^3.4.1" + "terser": "^4.0.0", + "typescript": "^3.5.2" }, "dependencies": { "@thi.ng/hdom": "latest" @@ -23,4 +23,4 @@ "browser": { "process": false } -} +} \ No newline at end of file diff --git a/examples/hdom-basics/src/index.ts b/examples/hdom-basics/src/index.ts index 29be03371f..cb3eb8f968 100644 --- a/examples/hdom-basics/src/index.ts +++ b/examples/hdom-basics/src/index.ts @@ -3,7 +3,7 @@ import { start } from "@thi.ng/hdom"; // stateless component w/ params // the first arg is an auto-injected context object // (not used here, see `hdom-context-basics` example for details) -const greeter = (_, name) => ["h1.title", "hello ", name]; +const greeter = (_: any, name: string) => ["h1.title", "hello ", name]; // component w/ local state const counter = (i = 0) => { diff --git a/examples/hdom-benchmark/package.json b/examples/hdom-benchmark/package.json index 4de16dc597..155ac0439e 100644 --- a/examples/hdom-benchmark/package.json +++ b/examples/hdom-benchmark/package.json @@ -11,8 +11,8 @@ }, "devDependencies": { "parcel-bundler": "^1.12.3", - "terser": "^3.17.0", - "typescript": "^3.4.1" + "terser": "^4.0.0", + "typescript": "^3.5.2" }, "dependencies": { "@thi.ng/hdom": "latest", @@ -27,4 +27,4 @@ "browser": { "process": false } -} +} \ No newline at end of file diff --git a/examples/hdom-benchmark/src/index.ts b/examples/hdom-benchmark/src/index.ts index 8d1de207f6..6cd0820942 100644 --- a/examples/hdom-benchmark/src/index.ts +++ b/examples/hdom-benchmark/src/index.ts @@ -47,18 +47,18 @@ const box = (index: number, id: number) => [ * @param txtCol */ const fpsCounter = ( - src: Stream, + src: Stream | null, width = 100, height = 30, period = 50, col = "#09f", txtCol = "#000" ) => { - let ctx; + let ctx: CanvasRenderingContext2D; let scale = height / 60; (src || fromRAF()).subscribe( { - next(samples) { + next(samples: number[]) { ctx.clearRect(0, 0, width, height); ctx.fillStyle = col; ctx.beginPath(); @@ -86,8 +86,8 @@ const fpsCounter = ( ); return [ { - init: (el) => { - ctx = el.getContext("2d"); + init: (el: HTMLCanvasElement) => { + ctx = el.getContext("2d")!; ctx.fillStyle = txtCol; ctx.fillText("sampling...", 2, height - 4); }, @@ -107,7 +107,7 @@ const app = () => { const menu = dropdown( null, { - onchange: (e) => { + onchange: (e: Event) => { num = parseInt((e.target).value); } }, diff --git a/examples/hdom-benchmark2/package.json b/examples/hdom-benchmark2/package.json index feca804b5c..c550573f8e 100644 --- a/examples/hdom-benchmark2/package.json +++ b/examples/hdom-benchmark2/package.json @@ -11,8 +11,8 @@ }, "devDependencies": { "parcel-bundler": "^1.12.3", - "terser": "^3.17.0", - "typescript": "^3.4.1" + "terser": "^4.0.0", + "typescript": "^3.5.2" }, "dependencies": { "@thi.ng/binary": "latest", @@ -28,4 +28,4 @@ "browser": { "process": false } -} +} \ No newline at end of file diff --git a/examples/hdom-benchmark2/src/index.ts b/examples/hdom-benchmark2/src/index.ts index 0cf0f5a199..0310b29f03 100644 --- a/examples/hdom-benchmark2/src/index.ts +++ b/examples/hdom-benchmark2/src/index.ts @@ -1,5 +1,5 @@ import { splat4_24 } from "@thi.ng/binary"; -import { start } from "@thi.ng/hdom"; +import { ILifecycle, start } from "@thi.ng/hdom"; import { dropdown, fpsCounter } from "@thi.ng/hdom-components"; import { css, injectStyleSheet } from "@thi.ng/hiccup-css"; import { U24 } from "@thi.ng/strings"; @@ -52,8 +52,14 @@ injectStyleSheet( ]) ); -const grid = { - render(_, cells, w, numChanges, frame) { +const grid = { + render( + _: any, + cells: number[], + w: number, + numChanges: number, + frame: number + ) { if (!frame) { this.prevChanged = null; this.prevChangedRows = null; @@ -76,11 +82,11 @@ const grid = { isFirst || this.prevChanged.has(i) ? { key: "c" + i, class: `cell cell-${x}` } : changed.has(i) - ? { - key: "c" + i, - class: `cell xcell-${x}` - } - : { key: "c" + i, __skip: true } + ? { + key: "c" + i, + class: `cell xcell-${x}` + } + : { key: "c" + i, __skip: true } ]), partition(w), mapIndexed((i, row) => [ @@ -121,7 +127,7 @@ const grid = { } }; -const domStats = (_, grid, res, _static) => +const domStats = (_: any, grid: any, res: number, _static: number) => grid && grid.stats ? [ "div", @@ -135,7 +141,7 @@ const domStats = (_, grid, res, _static) => ] : null; -const newCells = (res) => new Array(res * res).fill(0); +const newCells = (res: number) => new Array(res * res).fill(0); const stats = fpsCounter({ history: 50, sparkline: { width: 100 } }); @@ -169,8 +175,8 @@ const cancel = start(() => { dropdown, { class: "w3 code", - onchange: (e) => ( - (res = parseInt(e.target.value)), + onchange: (e: Event) => ( + (res = parseInt((e.target).value)), (frame = -1), (cells = newCells(res)) ) @@ -186,7 +192,8 @@ const cancel = start(() => { dropdown, { class: "w3 code", - onchange: (e) => (delta = parseInt(e.target.value)) + onchange: (e: Event) => + (delta = parseInt((e.target).value)) }, deltaOpts, delta diff --git a/examples/hdom-canvas-clock/package.json b/examples/hdom-canvas-clock/package.json index 4e71cdf28e..32e67e13aa 100644 --- a/examples/hdom-canvas-clock/package.json +++ b/examples/hdom-canvas-clock/package.json @@ -11,8 +11,8 @@ }, "devDependencies": { "parcel-bundler": "^1.12.3", - "terser": "^3.17.0", - "typescript": "^3.4.1" + "terser": "^4.0.0", + "typescript": "^3.5.2" }, "dependencies": { "@thi.ng/hdom": "latest", @@ -27,4 +27,4 @@ "browser": { "process": false } -} +} \ No newline at end of file diff --git a/examples/hdom-canvas-draw/package.json b/examples/hdom-canvas-draw/package.json index a730ca35e2..3f1069a18f 100644 --- a/examples/hdom-canvas-draw/package.json +++ b/examples/hdom-canvas-draw/package.json @@ -11,8 +11,8 @@ }, "devDependencies": { "parcel-bundler": "^1.12.3", - "terser": "^3.17.0", - "typescript": "^3.4.1" + "terser": "^4.0.0", + "typescript": "^3.5.2" }, "dependencies": { "@thi.ng/hdom-canvas": "latest", @@ -28,4 +28,4 @@ "browser": { "process": false } -} +} \ No newline at end of file diff --git a/examples/hdom-canvas-draw/src/index.ts b/examples/hdom-canvas-draw/src/index.ts index f23d387722..38038385f1 100644 --- a/examples/hdom-canvas-draw/src/index.ts +++ b/examples/hdom-canvas-draw/src/index.ts @@ -1,11 +1,7 @@ import { canvas } from "@thi.ng/hdom-canvas"; import { HALF_PI, PI } from "@thi.ng/math"; -import { sync, trigger } from "@thi.ng/rstream"; -import { - GestureEvent, - gestureStream, - GestureType -} from "@thi.ng/rstream-gestures"; +import { StreamSync, sync, trigger } from "@thi.ng/rstream"; +import { GestureEvent, gestureStream, GestureType } from "@thi.ng/rstream-gestures"; import { filter, map, @@ -23,7 +19,7 @@ const W = 480; // higher order line/shape component function // takes a tuple of 2 points and returns a component fn -const line = ([a, b]: number[][]) => (_, attribs) => [ +const line = ([a, b]: number[][]) => (_: any, attribs: any) => [ "line", { ...attribs, weight: dist(a, b) / 4 }, a, @@ -33,7 +29,7 @@ const line = ([a, b]: number[][]) => (_, attribs) => [ // higher order root component function. takes a @thi.ng/rstream // `StreamSync` instance as argument to dynamically add a new input // stream to later -const app = (main) => { +const app = (main: StreamSync) => { // augment hdom-canvas component w/ `init` lifecycle method: this is // method is called when the canvas DOM element is first created and // used to attach a mouse & touch event stream to it. this stream is @@ -68,7 +64,7 @@ const app = (main) => { // each time any inputs have changed... // the only input used here is the above stream of mouse events // transformed into line components - return ({ gesture }) => [ + return ({ gesture }: any) => [ "div.sans-serif.ma2", "Click & draw in the box below...", // all child elements of the canvas component @@ -142,7 +138,7 @@ const app = (main) => { // component's `init` method is called which attaches the above gesture // stream dynamically. the entire UI then only updates when there are new // user interactions... -const main = sync({ src: { trigger: trigger() } }); +const main = sync({ src: { trigger: trigger() } }); // transform result stream using the // root component fn and the hdom differential // update transducer diff --git a/examples/hdom-canvas-shapes/package.json b/examples/hdom-canvas-shapes/package.json index a3c828cc3e..07e4a7c904 100644 --- a/examples/hdom-canvas-shapes/package.json +++ b/examples/hdom-canvas-shapes/package.json @@ -11,8 +11,8 @@ }, "devDependencies": { "parcel-bundler": "^1.12.3", - "terser": "^3.17.0", - "typescript": "^3.4.1" + "terser": "^4.0.0", + "typescript": "^3.5.2" }, "dependencies": { "@thi.ng/hdom-canvas": "latest", @@ -30,4 +30,4 @@ "browser": { "process": false } -} +} \ No newline at end of file diff --git a/examples/hdom-canvas-shapes/src/index.ts b/examples/hdom-canvas-shapes/src/index.ts index 12879591c7..cd99f9f969 100644 --- a/examples/hdom-canvas-shapes/src/index.ts +++ b/examples/hdom-canvas-shapes/src/index.ts @@ -6,7 +6,12 @@ import { COMMENT, serialize } from "@thi.ng/hiccup"; import { convertTree, svg } from "@thi.ng/hiccup-svg"; import { sincos } from "@thi.ng/math"; import { concat, skewX23, translation23 } from "@thi.ng/matrices"; -import { fromRAF, stream, sync } from "@thi.ng/rstream"; +import { + fromRAF, + stream, + Subscription, + sync +} from "@thi.ng/rstream"; import { map, range, repeatedly } from "@thi.ng/transducers"; import { updateDOM } from "@thi.ng/transducers-hdom"; import { addN } from "@thi.ng/vectors"; @@ -30,7 +35,7 @@ const randdir = (n = 1) => [ // various tests for different shapes & canvas drawing options // each test is a standalone component (only one used at a time) -const TESTS = { +const TESTS: any = { "dash offset": { attribs: {}, desc: "Simple path w/ animated stroke dash pattern", @@ -282,13 +287,14 @@ const TESTS = { }; // test case selection dropdown -const choices = (_, target, id) => [ +const choices = (_: any, target: Subscription, id: string) => [ dropdown, { class: "w4 ma2", - onchange: (e) => { - window.location.hash = e.target.value.replace(/\s/g, "-"); - target.next(e.target.value); + onchange: (e: Event) => { + const val = (e.target).value; + window.location.hash = val.replace(/\s/g, "-"); + target.next(val); } }, Object.keys(TESTS).map((k) => [k, k]), @@ -302,7 +308,7 @@ const selection = stream(); // stream combinator updating & normalizing selected test component tree // (one of the inputs is linked to RAF to trigger updates) -const scene = sync({ +const scene = sync({ src: { id: selection, time: fromRAF() @@ -354,7 +360,7 @@ scene.transform( // stream combinator which triggers SVG conversion and file download // when both inputs have triggered (one of them being linked to the export button) -sync({ +sync({ src: { scene, trigger }, reset: true, xform: map(({ scene }) => diff --git a/examples/hdom-dropdown-fuzzy/package.json b/examples/hdom-dropdown-fuzzy/package.json index 3e856dda9f..e5e32fb21f 100644 --- a/examples/hdom-dropdown-fuzzy/package.json +++ b/examples/hdom-dropdown-fuzzy/package.json @@ -11,8 +11,8 @@ }, "devDependencies": { "parcel-bundler": "^1.12.3", - "terser": "^3.17.0", - "typescript": "^3.4.1" + "terser": "^4.0.0", + "typescript": "^3.5.2" }, "dependencies": { "@thi.ng/api": "latest", @@ -29,4 +29,4 @@ "browser": { "process": false } -} +} \ No newline at end of file diff --git a/examples/hdom-dropdown-fuzzy/src/dropdown.ts b/examples/hdom-dropdown-fuzzy/src/dropdown.ts index ca60e224a7..c206940b8c 100644 --- a/examples/hdom-dropdown-fuzzy/src/dropdown.ts +++ b/examples/hdom-dropdown-fuzzy/src/dropdown.ts @@ -52,7 +52,7 @@ export function dropdown(themeCtxPath: Path) { return state.open ? [ "div", - { ...ui.root, onkeydown: (e) => console.log(e) }, + { ...ui.root, onkeydown: (e: Event) => console.log(e) }, [ appLink, { ...hattribs, ...ui.itemSelected }, @@ -63,14 +63,14 @@ export function dropdown(themeCtxPath: Path) { "div", ui.bodyOpen, state.items.length - ? state.items.map((x) => [ + ? state.items.map((x: any) => [ "a", { ...(x[0] === state.selected ? ui.itemSelected : ui.item), href: "#", - onclick: opts.onchange(x[0]) + onclick: opts.onchange!(x[0]) }, ...(isString(x[1]) ? [x[1]] : x[1]) ]) @@ -87,7 +87,7 @@ export function dropdown(themeCtxPath: Path) { state.hover ? opts.hoverLabel : (state.items.find( - (x) => x[0] === state.selected + (x: any) => x[0] === state.selected ) || [, opts.hoverLabel])[1] ], ["div", ui.bodyClosed] @@ -104,7 +104,7 @@ export const dropdownListeners = ( onmouseleave: () => ctx.bus.dispatch([EV_SET_VALUE, [[...basePath, "hover"], false]]), ontoggle: () => ctx.bus.dispatch([EV_TOGGLE_VALUE, [...basePath, "open"]]), - onchange: (x) => () => { + onchange: (x: any) => () => { ctx.bus.dispatch( [EV_SET_VALUE, [[...basePath, "selected"], x]], [EV_SET_VALUE, [[...basePath, "open"], false]] diff --git a/examples/hdom-dropdown-fuzzy/src/fuzzy.ts b/examples/hdom-dropdown-fuzzy/src/fuzzy.ts index c8ba1b5beb..0eece5a260 100644 --- a/examples/hdom-dropdown-fuzzy/src/fuzzy.ts +++ b/examples/hdom-dropdown-fuzzy/src/fuzzy.ts @@ -1,6 +1,11 @@ import { IView } from "@thi.ng/atom"; import { EV_SET_VALUE } from "@thi.ng/interceptors"; -import { comp, filterFuzzy, iterator, map } from "@thi.ng/transducers"; +import { + comp, + filterFuzzy, + iterator, + map +} from "@thi.ng/transducers"; import { DropdownItem, dropdownListeners, DropdownState } from "./dropdown"; export interface FuzzyArgs { @@ -12,7 +17,7 @@ export interface FuzzyArgs { placeholder: string; } -export const fuzzyDropdown = (ctx, opts: FuzzyArgs) => { +export const fuzzyDropdown = (ctx: any, opts: FuzzyArgs) => { const close = () => ctx.bus.dispatch([EV_SET_VALUE, [opts.state.path + ".open", false]]); const filterInput = [ @@ -20,10 +25,10 @@ export const fuzzyDropdown = (ctx, opts: FuzzyArgs) => { { state: opts.filter.deref(), placeholder: opts.placeholder, - oninput: (e) => + oninput: (e: Event) => ctx.bus.dispatch([ EV_SET_VALUE, - [opts.filter.path, e.target.value] + [opts.filter.path, (e.target).value] ]), onclear: () => ctx.bus.dispatch([EV_SET_VALUE, [opts.filter.path, ""]]), @@ -32,8 +37,8 @@ export const fuzzyDropdown = (ctx, opts: FuzzyArgs) => { } ]; return () => { - const state = { ...opts.state.deref() }; - const filter = opts.filter.deref().toLowerCase(); + const state: any = { ...opts.state.deref() }; + const filter = opts.filter.deref()!.toLowerCase(); if (filter && state.open) { state.items = [ ...iterator( diff --git a/examples/hdom-dropdown-fuzzy/src/index.ts b/examples/hdom-dropdown-fuzzy/src/index.ts index c5ce67921d..3c018baaea 100644 --- a/examples/hdom-dropdown-fuzzy/src/index.ts +++ b/examples/hdom-dropdown-fuzzy/src/index.ts @@ -23,7 +23,7 @@ const dd = dropdown("theme.dd"); const input = cancelableInput("theme.input"); start( - (ctx) => { + (ctx: any) => { ctx.bus.processQueue(); return [ "div", diff --git a/examples/hdom-dropdown-fuzzy/src/input.ts b/examples/hdom-dropdown-fuzzy/src/input.ts index 1094c38002..b67a975e37 100644 --- a/examples/hdom-dropdown-fuzzy/src/input.ts +++ b/examples/hdom-dropdown-fuzzy/src/input.ts @@ -15,10 +15,10 @@ export interface InputArgs { } export function cancelableInput(themeCtxPath: Path) { - let input; + let input: HTMLElement; return { init: (el: HTMLElement) => (input = el.firstChild).focus(), - render: (ctx, args: InputArgs) => [ + render: (ctx: any, args: InputArgs) => [ "span.relative", [ "input", @@ -51,7 +51,7 @@ export function cancelableInput(themeCtxPath: Path) { "a", { href: "#", - onclick: (e) => { + onclick: (e: Event) => { e.stopPropagation(); input.focus(); args.onclear(e); diff --git a/examples/hdom-dropdown/package.json b/examples/hdom-dropdown/package.json index c745a34592..32cd6642cb 100644 --- a/examples/hdom-dropdown/package.json +++ b/examples/hdom-dropdown/package.json @@ -11,8 +11,8 @@ }, "devDependencies": { "parcel-bundler": "^1.12.3", - "terser": "^3.17.0", - "typescript": "^3.4.1" + "terser": "^4.0.0", + "typescript": "^3.5.2" }, "dependencies": { "@thi.ng/api": "latest", @@ -28,4 +28,4 @@ "browser": { "process": false } -} +} \ No newline at end of file diff --git a/examples/hdom-dropdown/src/dropdown.ts b/examples/hdom-dropdown/src/dropdown.ts index 3e684bc587..92142f4e74 100644 --- a/examples/hdom-dropdown/src/dropdown.ts +++ b/examples/hdom-dropdown/src/dropdown.ts @@ -56,13 +56,13 @@ export function dropdown(themeCtxPath: Path) { [ "div", ui.bodyOpen, - state.items.map((x) => + state.items.map((x: any) => appLink( null, x[0] === state.selected ? ui.itemSelected : ui.item, - opts.onchange(x[0]), + opts.onchange!(x[0]), x[1] ) ) @@ -78,7 +78,7 @@ export function dropdown(themeCtxPath: Path) { state.hover ? opts.hoverLabel : (state.items.find( - (x) => x[0] === state.selected + (x: any) => x[0] === state.selected ) || [, opts.hoverLabel])[1] ], ["div", ui.bodyClosed] @@ -95,7 +95,7 @@ export const dropdownListeners = ( onmouseleave: () => ctx.bus.dispatch([EV_SET_VALUE, [[...basePath, "hover"], false]]), ontoggle: () => ctx.bus.dispatch([EV_TOGGLE_VALUE, [...basePath, "open"]]), - onchange: (x) => () => { + onchange: (x: any) => () => { ctx.bus.dispatch( [EV_SET_VALUE, [[...basePath, "selected"], x]], [EV_SET_VALUE, [[...basePath, "open"], false]] diff --git a/examples/hdom-dropdown/src/index.ts b/examples/hdom-dropdown/src/index.ts index 87a2106603..b7a0c27420 100644 --- a/examples/hdom-dropdown/src/index.ts +++ b/examples/hdom-dropdown/src/index.ts @@ -10,7 +10,7 @@ bus.instrumentWith([trace]); const dd = dropdown("theme.dd"); start( - (ctx) => { + (ctx: any) => { bus.processQueue(); return [ "div", diff --git a/examples/hdom-dyn-context/package.json b/examples/hdom-dyn-context/package.json index a533d1ba35..42f37838ab 100644 --- a/examples/hdom-dyn-context/package.json +++ b/examples/hdom-dyn-context/package.json @@ -11,8 +11,8 @@ }, "devDependencies": { "parcel-bundler": "^1.12.3", - "terser": "^3.17.0", - "typescript": "^3.4.1" + "terser": "^4.0.0", + "typescript": "^3.5.2" }, "dependencies": { "@thi.ng/atom": "latest", @@ -24,4 +24,4 @@ "browser": { "process": false } -} +} \ No newline at end of file diff --git a/examples/hdom-dyn-context/src/index.ts b/examples/hdom-dyn-context/src/index.ts index 327b94d62b..c88ddc9dd0 100644 --- a/examples/hdom-dyn-context/src/index.ts +++ b/examples/hdom-dyn-context/src/index.ts @@ -39,7 +39,7 @@ const toggle = () => db.swapIn("id", (id: number) => (id + 1) % THEMES.length); // root component function // the destructuring form is for the context object which is always // passed as 1st arg -const app = ({ theme, themeID }) => [ +const app = ({ theme, themeID }: any) => [ "div", theme.root, ["h1", `Current theme: ${themeID}`], diff --git a/examples/hdom-inner-html/package.json b/examples/hdom-inner-html/package.json index 6a5a585bac..87c768aae2 100644 --- a/examples/hdom-inner-html/package.json +++ b/examples/hdom-inner-html/package.json @@ -12,8 +12,8 @@ "devDependencies": { "parcel-bundler": "^1.12.3", "rimraf": "^2.6.3", - "terser": "^3.17.0", - "typescript": "^3.4.1" + "terser": "^4.0.0", + "typescript": "^3.5.2" }, "dependencies": { "@thi.ng/hdom": "latest" @@ -24,4 +24,4 @@ "browser": { "process": false } -} +} \ No newline at end of file diff --git a/examples/hdom-inner-html/src/index.ts b/examples/hdom-inner-html/src/index.ts index cc92a3e98a..cae69c1875 100644 --- a/examples/hdom-inner-html/src/index.ts +++ b/examples/hdom-inner-html/src/index.ts @@ -5,25 +5,26 @@ import { start } from "@thi.ng/hdom"; * returned component takes a single HTML string as arg and updates each * time the given string has changed. */ -const innerHtmlWrapper = () => ({ - init(el, _, html) { - this.el = el; - this.prev = html; - el.innerHTML = html; - }, - render(_, body) { - if (this.el && this.prev != body) { - this.el.innerHTML = body; - this.prev = body; +const innerHtmlWrapper = () => + { + init(el: any, _: any, html: string) { + this.el = el; + this.prev = html; + el.innerHTML = html; + }, + render(_: any, html: string) { + if (this.el && this.prev != html) { + this.el.innerHTML = html; + this.prev = html; + } + return ["div"]; + }, + release() { + this.el.innerHTML = ""; + delete this.prev; + delete this.el; } - return ["div"]; - }, - release() { - this.el.innerHTML = ""; - delete this.prev; - delete this.el; - } -}); + }; /** * Root component. diff --git a/examples/hdom-skip/package.json b/examples/hdom-skip/package.json index 2d1974b942..199b0add07 100644 --- a/examples/hdom-skip/package.json +++ b/examples/hdom-skip/package.json @@ -11,8 +11,8 @@ }, "devDependencies": { "parcel-bundler": "^1.12.3", - "terser": "^3.17.0", - "typescript": "^3.4.1" + "terser": "^4.0.0", + "typescript": "^3.5.2" }, "dependencies": { "@thi.ng/hdom": "latest" @@ -23,4 +23,4 @@ "browser": { "process": false } -} +} \ No newline at end of file diff --git a/examples/hdom-skip/src/index.ts b/examples/hdom-skip/src/index.ts index 82d19a3c9b..cc65c42456 100644 --- a/examples/hdom-skip/src/index.ts +++ b/examples/hdom-skip/src/index.ts @@ -1,7 +1,7 @@ import { start } from "@thi.ng/hdom"; -const timer = (period, name = `${period}ms`) => { - return { +const timer = (period: number, name = `${period}ms`) => { + return { // life cycle init method // called when the component is being added to the real DOM init() { @@ -32,7 +32,7 @@ const timer = (period, name = `${period}ms`) => { }; // root component object w/ life cycle methods -const app = { +const app = { init() { // create timer component instances this.timers = [[timer(1000)], [timer(500)], [timer(250)]]; diff --git a/examples/hdom-theme-adr-0003/package.json b/examples/hdom-theme-adr-0003/package.json index 0a5893cf8e..5293df00ab 100644 --- a/examples/hdom-theme-adr-0003/package.json +++ b/examples/hdom-theme-adr-0003/package.json @@ -11,8 +11,8 @@ }, "devDependencies": { "parcel-bundler": "^1.12.3", - "terser": "^3.17.0", - "typescript": "^3.4.1" + "terser": "^4.0.0", + "typescript": "^3.5.2" }, "dependencies": { "@thi.ng/api": "latest", @@ -25,4 +25,4 @@ "browser": { "process": false } -} +} \ No newline at end of file diff --git a/examples/hdom-theme-adr-0003/src/index.ts b/examples/hdom-theme-adr-0003/src/index.ts index bd3a596f7b..0a2b33cd39 100644 --- a/examples/hdom-theme-adr-0003/src/index.ts +++ b/examples/hdom-theme-adr-0003/src/index.ts @@ -54,9 +54,9 @@ const button = (themeCtxPath: Path, behavior?: Partial) => { const theme = getIn(ctx, themeCtxPath); if (args.disabled) { return [ - behavior.tagDisabled, + behavior!.tagDisabled, { - ...behavior.attribs, + ...behavior!.attribs, ...theme.disabled, ...args }, @@ -64,7 +64,7 @@ const button = (themeCtxPath: Path, behavior?: Partial) => { ]; } else { const attribs = { - ...behavior.attribs, + ...behavior!.attribs, ...theme[args.selected ? "selected" : "default"], ...args }; @@ -73,9 +73,11 @@ const button = (themeCtxPath: Path, behavior?: Partial) => { args.onclick && (args.href == null || args.href === "#") ) { - attribs.onclick = (e) => (e.preventDefault(), args.onclick(e)); + attribs.onclick = (e: Event) => ( + e.preventDefault(), args.onclick!(e) + ); } - return [behavior.tag, attribs, ...body]; + return [behavior!.tag, attribs, ...body]; } }; }; @@ -161,7 +163,7 @@ const btFixed = button("theme.button", { attribs: { style: { width: "8rem" } } }); -const app = (ctx) => [ +const app = (ctx: any) => [ "div", ctx.theme.body, "Current theme: ", diff --git a/examples/hdom-vscroller/package.json b/examples/hdom-vscroller/package.json index 3614e74926..367dd6c429 100644 --- a/examples/hdom-vscroller/package.json +++ b/examples/hdom-vscroller/package.json @@ -12,8 +12,8 @@ "devDependencies": { "parcel-bundler": "^1.12.3", "rimraf": "^2.6.3", - "terser": "^3.17.0", - "typescript": "^3.4.1" + "terser": "^4.0.0", + "typescript": "^3.5.2" }, "dependencies": { "@thi.ng/api": "latest", @@ -26,4 +26,4 @@ "browser": { "process": false } -} +} \ No newline at end of file diff --git a/examples/hdom-vscroller/src/index.ts b/examples/hdom-vscroller/src/index.ts index 5357294fee..274746a082 100644 --- a/examples/hdom-vscroller/src/index.ts +++ b/examples/hdom-vscroller/src/index.ts @@ -23,29 +23,29 @@ let pkgTop = 0; const filterCommit = (q: string) => (x: Commit) => x[2].toLowerCase().indexOf(q) >= 0 || x[1].indexOf(q) >= 0; -const setQuery = (e) => { +const setQuery = (e: Event) => { try { - query = e.target.value; + query = (e.target).value; filtered = COMMITS.filter(filterCommit(query)); commitsOffset = 0; commitsTop = 0; } catch (e) {} }; -const queryFilter = (_, query, items) => [ +const queryFilter = (_: any, query: EventListener, items: any[]) => [ "div.pv2.ph3.bg-black.white", "Filter: ", ["input", { type: "text", oninput: setQuery, value: query }], ` (${items.length})` ]; -const repoLink = (_, sha, body) => [ +const repoLink = (_: any, sha: string, body: any) => [ "a.link.blue", { href: `${REPO_BASE}commit/${sha}` }, body ]; -const packageLink = (_, name) => [ +const packageLink = (_: any, name: any) => [ "a.link.blue", { href: `${REPO_BASE}tree/master/packages/${name.substr(8)}` }, name diff --git a/examples/hdom-vscroller/src/vscroller.ts b/examples/hdom-vscroller/src/vscroller.ts index d8539796af..c7c23efa54 100644 --- a/examples/hdom-vscroller/src/vscroller.ts +++ b/examples/hdom-vscroller/src/vscroller.ts @@ -1,5 +1,10 @@ import { Fn2 } from "@thi.ng/api"; -import { comp, drop, iterator, take } from "@thi.ng/transducers"; +import { + comp, + drop, + iterator, + take +} from "@thi.ng/transducers"; interface VScrollOpts { /** @@ -44,8 +49,8 @@ export const virtualScroller = ({ }: VScrollOpts) => [ "div.overflow-y-scroll", { - onscroll: (e) => { - const top = e.target.scrollTop; + onscroll: (e: Event) => { + const top = (e.target).scrollTop; const offset = Math.min( Math.floor(top / itemHeight), numItems - numVisible diff --git a/examples/hmr-basics/package.json b/examples/hmr-basics/package.json index cccac73d48..07143819de 100644 --- a/examples/hmr-basics/package.json +++ b/examples/hmr-basics/package.json @@ -11,8 +11,8 @@ }, "devDependencies": { "parcel-bundler": "^1.12.3", - "terser": "^3.17.0", - "typescript": "^3.4.1" + "terser": "^4.0.0", + "typescript": "^3.5.2" }, "dependencies": { "@thi.ng/atom": "latest", @@ -27,4 +27,4 @@ "browser": { "process": false } -} +} \ No newline at end of file diff --git a/examples/hmr-basics/src/app.ts b/examples/hmr-basics/src/app.ts index ff8a850d92..eabb41e0e4 100644 --- a/examples/hmr-basics/src/app.ts +++ b/examples/hmr-basics/src/app.ts @@ -4,7 +4,7 @@ // when this module is being replaced via HMR // root component function -export const app = ({ now, state }) => [ +export const app = ({ now, state }: any) => [ "div.pa2.sans-serif.f6.bg-light-yellow", ["h1.pa0.ma0.bb", "State"], [ @@ -21,9 +21,13 @@ export const app = ({ now, state }) => [ ] ]; -const item = (_, label, value) => ["li", ["span.dib.b.w4", label], value]; +const item = (_: any, label: string, value: any) => [ + "li", + ["span.dib.b.w4", label], + value +]; -const repoLink = (_, file) => [ +const repoLink = (_: any, file: string) => [ "a.pa1.link.black.bg-light-gray", { href: `https://github.com/thi-ng/umbrella/tree/master/examples/hmr-basics/${file}` diff --git a/examples/hydrate-basics/package.json b/examples/hydrate-basics/package.json index ec9cfabab7..37c567216f 100644 --- a/examples/hydrate-basics/package.json +++ b/examples/hydrate-basics/package.json @@ -11,8 +11,8 @@ }, "devDependencies": { "parcel-bundler": "^1.12.3", - "terser": "^3.17.0", - "typescript": "^3.4.1" + "terser": "^4.0.0", + "typescript": "^3.5.2" }, "dependencies": { "@thi.ng/atom": "latest", @@ -26,4 +26,4 @@ "browser": { "process": false } -} +} \ No newline at end of file diff --git a/examples/hydrate-basics/src/index.ts b/examples/hydrate-basics/src/index.ts index 84f2f31e12..15c9be9fba 100644 --- a/examples/hydrate-basics/src/index.ts +++ b/examples/hydrate-basics/src/index.ts @@ -1,3 +1,4 @@ +import { IDeref } from "@thi.ng/api"; import { Atom } from "@thi.ng/atom"; import { start } from "@thi.ng/hdom"; import { canvas2D, dropdown } from "@thi.ng/hdom-components"; @@ -42,8 +43,8 @@ const app = () => { // during hydration (1st frame of hdom update loop) // btw. the class names are for tachyons css - return (state) => { - state = state.deref(); + return (_state: IDeref) => { + const state = _state.deref(); return [ "div#root.w-50-ns.flex.ma2.sans-serif", [ @@ -61,7 +62,8 @@ const app = () => { { id: "bg", class: "w-100", - onchange: (e) => setBg(e.target.value) + onchange: (e: Event) => + setBg((e.target).value) }, [ ["", "Choose..."], @@ -86,7 +88,12 @@ const app = () => { max: 0.02, step: 0.001, value: state.freq, - oninput: (e) => setFreq(parseFloat(e.target.value)) + oninput: (e: Event) => + setFreq( + parseFloat( + (e.target).value + ) + ) } ] ] @@ -97,7 +104,7 @@ const app = () => { // emulate SSR by serializing to HTML const html = serialize(app()(state), null, false, true); -document.getElementById("app").innerHTML = html; +document.getElementById("app")!.innerHTML = html; console.log(html); // ..then start hdom update loop w/ hydrate enabled diff --git a/examples/interceptor-basics/package.json b/examples/interceptor-basics/package.json index 279822ef51..599eb11c38 100644 --- a/examples/interceptor-basics/package.json +++ b/examples/interceptor-basics/package.json @@ -11,8 +11,8 @@ }, "devDependencies": { "parcel-bundler": "^1.12.3", - "terser": "^3.17.0", - "typescript": "^3.4.1" + "terser": "^4.0.0", + "typescript": "^3.5.2" }, "dependencies": { "@thi.ng/atom": "latest", @@ -26,4 +26,4 @@ "browser": { "process": false } -} +} \ No newline at end of file diff --git a/examples/interceptor-basics/src/index.ts b/examples/interceptor-basics/src/index.ts index 8cf43a9952..ba64e4b571 100644 --- a/examples/interceptor-basics/src/index.ts +++ b/examples/interceptor-basics/src/index.ts @@ -31,7 +31,7 @@ start( // this root component function will be executed via RAF. // it first processes events and then only returns an updated // component if there was a state update... - (ctx) => + (ctx: any) => ctx.bus.processQueue() ? [ "button", diff --git a/examples/interceptor-basics2/package.json b/examples/interceptor-basics2/package.json index 4b5a46c86a..ce7a6fb108 100644 --- a/examples/interceptor-basics2/package.json +++ b/examples/interceptor-basics2/package.json @@ -11,8 +11,8 @@ }, "devDependencies": { "parcel-bundler": "^1.12.3", - "terser": "^3.17.0", - "typescript": "^3.4.1" + "terser": "^4.0.0", + "typescript": "^3.5.2" }, "dependencies": { "@thi.ng/api": "latest", @@ -26,4 +26,4 @@ "browser": { "process": false } -} +} \ No newline at end of file diff --git a/examples/interceptor-basics2/src/index.ts b/examples/interceptor-basics2/src/index.ts index 417bd313cd..2be30bfc3e 100644 --- a/examples/interceptor-basics2/src/index.ts +++ b/examples/interceptor-basics2/src/index.ts @@ -6,6 +6,7 @@ import { ensureStateLessThan, EV_SET_VALUE, EV_UPDATE_VALUE, + Event, EventBus, EventDef, FX_DISPATCH_NOW, @@ -34,11 +35,15 @@ const events: IObjectOf = { // note how we also inject the predicate interceptors here to ensure // counter values will be always be in the range between 0 .. 100 [EV_INC]: [ - ensureStateLessThan(100, null, () => console.warn("eek, reached max")), + ensureStateLessThan(100, undefined, () => + console.warn("eek, reached max") + ), (_, [__, path]) => ({ [FX_DISPATCH_NOW]: [EV_ADD_VALUE, [path, 1]] }) ], [EV_DEC]: [ - ensureStateGreaterThan(0, null, () => console.warn("eek, reached min")), + ensureStateGreaterThan(0, undefined, () => + console.warn("eek, reached min") + ), (_, [__, path]) => ({ [FX_DISPATCH_NOW]: [EV_ADD_VALUE, [path, -1]] }) ], @@ -49,7 +54,7 @@ const events: IObjectOf = { [EV_ADD_VALUE]: [ trace, (_, [__, [path, y]]) => ({ - [FX_DISPATCH_NOW]: [EV_UPDATE_VALUE, [path, (x) => x + y]] + [FX_DISPATCH_NOW]: [EV_UPDATE_VALUE, [path, (x: number) => x + y]] }) ], @@ -77,7 +82,7 @@ const effects: IObjectOf = {}; /////////////////////////////////////////////////////////////////////// // components -const button = (bus, event, label, id?) => [ +const button = (bus: IDispatch, event: Event, label: string, id?: string) => [ "button", { id, onclick: () => bus.dispatch(event) }, label @@ -105,7 +110,7 @@ const counter = (bus: IDispatch, path: Path, start = 0, color: string) => { const app = () => { // an array to store counter component instances // (only using component local state for KISS reasons) - const counters = []; + const counters: any[] = []; // create event bus with app state atom and configure with above handlers/effects const bus = new EventBus(null, events, effects); diff --git a/examples/iso-plasma/package.json b/examples/iso-plasma/package.json index 79bf59cb55..827fe10a45 100644 --- a/examples/iso-plasma/package.json +++ b/examples/iso-plasma/package.json @@ -12,8 +12,8 @@ "devDependencies": { "parcel-bundler": "^1.12.3", "rimraf": "^2.6.3", - "terser": "^3.17.0", - "typescript": "^3.4.1" + "terser": "^4.0.0", + "typescript": "^3.5.2" }, "dependencies": { "@thi.ng/api": "latest", @@ -31,4 +31,4 @@ "browser": { "process": false } -} +} \ No newline at end of file diff --git a/examples/iso-plasma/src/index.ts b/examples/iso-plasma/src/index.ts index 237b816cae..f2c7ec85e9 100644 --- a/examples/iso-plasma/src/index.ts +++ b/examples/iso-plasma/src/index.ts @@ -36,7 +36,7 @@ const plasma = (n: number, t: number) => { }; // compute full pattern via given fn -const makeField = (fn: Fn, width, height) => +const makeField = (fn: Fn, width: number, height: number) => setBorder([...map(fn, range2d(width, height))], width, height, 1000); // hdom root component @@ -44,11 +44,11 @@ const app = () => { const src = makeField(plasma(6, (Date.now() - t0) * 0.001), W, W); const contours = iterator( comp( - mapIndexed((i, x) => [x, [i / 20, 0, 1 - i / 20]]), + mapIndexed((i, x) => <[number, Vec]>[x, [i / 20, 0, 1 - i / 20]]), mapcat(([i, col]) => - map((pts) => [pts, col], isolines(src, W, W, i)) + map((pts) => <[Vec[], Vec]>[pts, col], isolines(src, W, W, i)) ), - map(([pts, col]: [Vec[], Vec]) => polygon(pts, { stroke: col })) + map(([pts, col]) => polygon(pts, { stroke: col })) ), range(-1, 1, 0.1) ); diff --git a/examples/json-components/package.json b/examples/json-components/package.json index d3ec46977a..440b8ff0fe 100644 --- a/examples/json-components/package.json +++ b/examples/json-components/package.json @@ -11,8 +11,8 @@ }, "devDependencies": { "parcel-bundler": "^1.12.3", - "terser": "^3.17.0", - "typescript": "^3.4.1" + "terser": "^4.0.0", + "typescript": "^3.5.2" }, "dependencies": { "@thi.ng/hdom": "latest", @@ -24,4 +24,4 @@ "browser": { "process": false } -} +} \ No newline at end of file diff --git a/examples/json-components/src/index.ts b/examples/json-components/src/index.ts index 3d65b449fc..3cd7e6a86e 100644 --- a/examples/json-components/src/index.ts +++ b/examples/json-components/src/index.ts @@ -35,28 +35,28 @@ let db = [ // the `item` function is the root component for each JSON object // it's a higher-order function, since we will create different // instances for theming purposes... see below -const item = (theme) => (item) => [ +const item = (theme: any) => (item: any) => [ `div.item.${theme}`, item.title, item.meta, item.content ]; -const meta = (meta) => ["div.meta", meta.author, meta.created, meta.tags]; -const author = (author) => [ +const meta = (meta: any) => ["div.meta", meta.author, meta.created, meta.tags]; +const author = (author: any) => [ "div", ["strong", "author: "], link(`mailto:${author.email}`, author.name) ]; -const date = (iso) => [ +const date = (iso: string) => [ "div", ["strong", "date: "], new Date(Date.parse(iso)).toLocaleString() ]; -const link = (href, body) => ["a", { href }, body]; -const tag = (tag) => ["li", link("#", tag)]; -const tags = (tags) => ["ul.tags", ...tags.map(tag)]; -const title = (title, level = 3) => [`h${level}`, title]; -const content = (body) => ["div", body]; +const link = (href: string, body: any) => ["a", { href }, body]; +const tag = (tag: string) => ["li", link("#", tag)]; +const tags = (tags: string[]) => ["ul.tags", ...tags.map(tag)]; +const title = (title: string, level = 3) => [`h${level}`, title]; +const content = (body: any) => ["div", body]; // now compose themed component functions for the above JSON object format // the spec below is is only partially complete and will be reused by @@ -97,9 +97,9 @@ const editor = (() => { return [ "textarea", { - oninput: (e) => { + oninput: (e: Event) => { try { - db = JSON.parse(e.target.value); + db = JSON.parse((e.target).value); } catch (_) {} } }, diff --git a/examples/login-form/package.json b/examples/login-form/package.json index cc6122c622..dfb81bec62 100644 --- a/examples/login-form/package.json +++ b/examples/login-form/package.json @@ -11,8 +11,8 @@ }, "devDependencies": { "parcel-bundler": "^1.12.3", - "terser": "^3.17.0", - "typescript": "^3.4.1" + "terser": "^4.0.0", + "typescript": "^3.5.2" }, "dependencies": { "@thi.ng/atom": "latest", @@ -25,4 +25,4 @@ "browser": { "process": false } -} +} \ No newline at end of file diff --git a/examples/login-form/src/index.ts b/examples/login-form/src/index.ts index 592bd09f38..233a9c6002 100644 --- a/examples/login-form/src/index.ts +++ b/examples/login-form/src/index.ts @@ -1,6 +1,6 @@ import { Atom } from "@thi.ng/atom"; import { start } from "@thi.ng/hdom"; -import { setIn } from "@thi.ng/paths"; +import { Path, setIn } from "@thi.ng/paths"; // central immutable app state const db = new Atom({ state: "login" }); @@ -9,18 +9,18 @@ const db = new Atom({ state: "login" }); const appState = db.addView("state"); const error = db.addView("error"); // specify a view transformer for the username value -const user = db.addView( - "user.name", - (x) => (x ? x.charAt(0).toUpperCase() + x.substr(1) : null) +const user = db.addView("user.name", (x) => + x ? x.charAt(0).toUpperCase() + x.substr(1) : null ); // state update functions -const setValue = (path, val) => db.swap((state) => setIn(state, path, val)); -const setState = (s) => setValue(appState.path, s); -const setError = (err) => setValue(error.path, err); -const setUser = (e) => setValue(user.path, e.target.value); +const setValue = (path: Path, val: any) => + db.swap((state) => setIn(state, path, val)); +const setState = (s: any) => setValue(appState.path, s); +const setError = (err: string | null) => setValue(error.path, err); +const setUser = (e: Event) => setValue(user.path, (e.target).value); const loginUser = () => { - if (user.deref() && user.deref().toLowerCase() === "admin") { + if (user.deref() && user.deref()!.toLowerCase() === "admin") { setError(null); setState("main"); } else { @@ -34,7 +34,7 @@ const logoutUser = () => { // components for different app states // note how the value views are used here -const uiViews = { +const uiViews: any = { // dummy login form login: () => [ "div#login", diff --git a/examples/mandelbrot/package.json b/examples/mandelbrot/package.json index 527708bd06..bac08841f6 100644 --- a/examples/mandelbrot/package.json +++ b/examples/mandelbrot/package.json @@ -12,8 +12,8 @@ }, "devDependencies": { "parcel-bundler": "^1.12.3", - "terser": "^3.17.0", - "typescript": "^3.4.1" + "terser": "^4.0.0", + "typescript": "^3.5.2" }, "dependencies": { "@thi.ng/api": "latest", @@ -33,4 +33,4 @@ "browser": { "process": false } -} +} \ No newline at end of file diff --git a/examples/mandelbrot/src/gradient.ts b/examples/mandelbrot/src/gradient.ts index a4ed93b936..74a07c2103 100644 --- a/examples/mandelbrot/src/gradient.ts +++ b/examples/mandelbrot/src/gradient.ts @@ -28,7 +28,7 @@ const cosColor = ( zip(dc, amp, fmod, phase) ); -export const cosineGradient = (n: number, spec: number[][]) => { +export const cosineGradient = (n: number, spec: number[][]): number[] => { const [dc, amp, fmod, phase] = spec; return transduce( comp( diff --git a/examples/mandelbrot/src/index.ts b/examples/mandelbrot/src/index.ts index cb00265f6d..27a50f983c 100644 --- a/examples/mandelbrot/src/index.ts +++ b/examples/mandelbrot/src/index.ts @@ -1,7 +1,12 @@ import { equiv } from "@thi.ng/equiv"; import { canvas2D } from "@thi.ng/hdom-components"; import { fit, mix } from "@thi.ng/math"; -import { stream, sync, tunnel } from "@thi.ng/rstream"; +import { + stream, + Stream, + sync, + tunnel +} from "@thi.ng/rstream"; import { gestureStream, GestureType } from "@thi.ng/rstream-gestures"; import { padLeft } from "@thi.ng/strings"; import { map } from "@thi.ng/transducers"; @@ -30,11 +35,13 @@ const x2 = stream(); const y2 = stream(); const iter = stream(); const gradient = stream(); -const sel1 = stream(); -const sel2 = stream(); +const sel1 = stream(); +const sel2 = stream(); // main stream combinator -const main = sync({ src: { x1, y1, x2, y2, iter, gradient, sel1, sel2 } }); +const main = sync({ + src: { x1, y1, x2, y2, iter, gradient, sel1, sel2 } +}); // URL hash updater main.subscribe({ @@ -99,11 +106,13 @@ const app = () => { // the `interrupt` option and ensures only the most recent // configuration is being fully executed without having to // wait for older render tasks to complete... - sync({ src: { x1, y1, x2, y2, iter, gradient } }) + sync({ src: { x1, y1, x2, y2, iter, gradient } }) .transform( map((obj) => ({ ...obj, w: el.width, h: el.height })) ) - .subscribe(tunnel({ src: "./worker.js", interrupt: true })) + .subscribe( + tunnel({ src: "./worker.js", interrupt: true }) + ) .subscribe({ next: (pix: ArrayBuffer) => { img.data.set(new Uint8Array(pix)); @@ -111,7 +120,7 @@ const app = () => { // frame export & auto zoom out if (AUTO_ZOOM) { el.toBlob((b) => - download(`frame-${Z4(frame++)}.png`, b) + download(`frame-${Z4(frame++)}.png`, b!) ); setTimeout(() => updateZoom(-0.02), 100); } @@ -124,7 +133,7 @@ const app = () => { absZoom: false, smooth: 1e-3 }).subscribe({ - next: ([type, { pos, zoom }]: [GestureType, any]) => { + next([type, { pos, zoom }]: any) { const _x1 = x1.deref(); const _y1 = y1.deref(); const _x2 = x2.deref(); @@ -138,7 +147,7 @@ const app = () => { break; case GestureType.END: { const p = sel1.deref(); - if (equiv(p, pos)) return; + if (!p || equiv(p, pos)) return; // compute target coord based on current zoom region let ax = fit(p[0], 0, el.width, _x1, _x2); let ay = fit(p[1], 0, el.height, _y1, _y2); @@ -217,7 +226,7 @@ const app = () => { } }); // return actual root component function - return ({ sel1, sel2 }) => { + return ({ sel1, sel2 }: any) => { return [ "div.flex-l.sans-serif.f7", [canvas, { id: "main", width: SIZE, height: SIZE }, sel1, sel2], @@ -233,7 +242,8 @@ const app = () => { [ "button", { - onclick: () => newRender.apply(null, DEFAULT_CONFIG) + onclick: () => + newRender.apply(null, DEFAULT_CONFIG) }, "reset" ], @@ -255,7 +265,14 @@ const app = () => { }; // slider component which emits value changes on given stream -const slider = (_, stream, min, max, step, label) => [ +const slider = ( + _: any, + stream: Stream, + min: number, + max: number, + step: number, + label: string +) => [ "div", ["div", ["strong", `${label}: `], stream.deref()], [ @@ -267,7 +284,8 @@ const slider = (_, stream, min, max, step, label) => [ max, step, value: stream.deref(), - oninput: (e) => stream.next(parseFloat(e.target.value)) + oninput: (e: Event) => + stream.next(parseFloat((e.target).value)) } ] ]; @@ -276,15 +294,12 @@ const slider = (_, stream, min, max, step, label) => [ main.transform(map(app()), updateDOM()); // init parameter streams, if possible from location.hash -newRender.apply( - null, - location.hash.length > 1 - ? location.hash - .substr(1) - .split(";") - .map(parseFloat) - : DEFAULT_CONFIG -); +newRender.apply(null, (location.hash.length > 1 + ? location.hash + .substr(1) + .split(";") + .map(parseFloat) + : DEFAULT_CONFIG)); // HMR handling if (process.env.NODE_ENV !== "production") { diff --git a/examples/mandelbrot/src/worker.ts b/examples/mandelbrot/src/worker.ts index 770e8a2eab..0fdb3d379e 100644 --- a/examples/mandelbrot/src/worker.ts +++ b/examples/mandelbrot/src/worker.ts @@ -24,7 +24,7 @@ const mandelbrot = (x0: number, y0: number, n: number) => { }; // generates new fractal image based on given config tuple -const render = ({ x1, y1, x2, y2, iter, w, h, gradient }) => { +const render = ({ x1, y1, x2, y2, iter, w, h, gradient }: any) => { const grad = GRADIENTS[gradient]; const pix = new Uint32Array(w * h); for (let y = 0, i = 0; y < h; y++) { diff --git a/examples/markdown/package.json b/examples/markdown/package.json index 4828e10178..01064a05ee 100644 --- a/examples/markdown/package.json +++ b/examples/markdown/package.json @@ -12,8 +12,8 @@ }, "devDependencies": { "parcel-bundler": "^1.12.3", - "terser": "^3.17.0", - "typescript": "^3.4.1" + "terser": "^4.0.0", + "typescript": "^3.5.2" }, "dependencies": { "@thi.ng/api": "latest", @@ -28,4 +28,4 @@ "browser": { "process": false } -} +} \ No newline at end of file diff --git a/examples/markdown/src/index.ts b/examples/markdown/src/index.ts index 02e8663635..60b214b0a4 100644 --- a/examples/markdown/src/index.ts +++ b/examples/markdown/src/index.ts @@ -1,11 +1,11 @@ import { timedResult } from "@thi.ng/bench"; -import { TagFactories, parse } from "@thi.ng/hiccup-markdown"; +import { parse, TagFactories } from "@thi.ng/hiccup-markdown"; import { stream, Stream } from "@thi.ng/rstream"; -import { updateDOM } from "@thi.ng/transducers-hdom"; import { iterator, map } from "@thi.ng/transducers"; +import { updateDOM } from "@thi.ng/transducers-hdom"; +import readme from "../README.txt"; // ignore error, resolved by parcel -import readme from "../README.md"; // const readme = "README.af35c500.md" // custom tag factories (passed to parser) @@ -30,7 +30,10 @@ const CUSTOM_TAGS: Partial = { }; // UI root component -const app = (input: Stream) => ({ src, parsed: [hiccup, time] }) => [ +const app = (input: Stream) => ({ + src, + parsed: [hiccup, time] +}: any) => [ "div.flex.vh-100.sans-serif.flex-column.flex-row-l", [ "div.w-100.h-50.w-50-l.h-100-l", @@ -38,7 +41,8 @@ const app = (input: Stream) => ({ src, parsed: [hiccup, time] }) => [ "textarea.w-100.vh-50.vh-100-l.bg-washed-blue.navy.pa3.f7.code.lh-copy", { value: src, - oninput: (e) => input.next(e.target.value) + oninput: (e: Event) => + input.next((e.target).value) } ] ], diff --git a/examples/package-stats/package.json b/examples/package-stats/package.json index 2627d437f4..f1f6fcd5b5 100644 --- a/examples/package-stats/package.json +++ b/examples/package-stats/package.json @@ -6,12 +6,13 @@ "license": "Apache-2.0", "scripts": { "clean": "rm -rf *.js *.svg lib", - "build": "yarn clean && tsc && node lib/index.js" + "build": "yarn clean && ts-node src/index.ts" }, "devDependencies": { "parcel-bundler": "^1.12.3", - "terser": "^3.17.0", - "typescript": "^3.4.1" + "terser": "^4.0.0", + "typescript": "^3.5.2", + "ts-node": "^8.2.0" }, "dependencies": { "@thi.ng/checks": "latest", @@ -19,9 +20,10 @@ "@thi.ng/hiccup": "latest", "@thi.ng/hiccup-svg": "latest", "@thi.ng/math": "latest", - "@thi.ng/path": "latest", + "@thi.ng/paths": "latest", "@thi.ng/strings": "latest", - "@thi.ng/transducers": "latest" + "@thi.ng/transducers": "latest", + "@thi.ng/vectors": "latest" }, "browserslist": [ "last 3 Chrome versions" @@ -29,4 +31,4 @@ "browser": { "process": false } -} +} \ No newline at end of file diff --git a/examples/package-stats/src/dep-chart.ts b/examples/package-stats/src/dep-chart.ts index a82eb83fce..97bac3091d 100644 --- a/examples/package-stats/src/dep-chart.ts +++ b/examples/package-stats/src/dep-chart.ts @@ -17,11 +17,11 @@ import { zip } from "@thi.ng/transducers"; import * as fs from "fs"; -import { barChart, labeledTickY, labeledTickX } from "./viz"; +import { barChart, labeledTickX, labeledTickY } from "./viz"; const BASE_DIR = "../../packages/"; -const packages = transduce( +const packages: { id: string; v: string; deps: string[] }[] = transduce( comp( map((f) => BASE_DIR + f), filter((f) => fs.statSync(f).isDirectory()), @@ -44,15 +44,15 @@ const packages = transduce( const graph = transduce( mapcat((p: any) => zip(repeat(p.id), p.deps)), - reducer(() => new DGraph(), (g, [p, d]) => g.addDependency(p, d)), + reducer(() => new DGraph(), (g, [p, d]: any) => g.addDependency(p, d)), packages ); const packageDeps = packages - .map((p) => [p.id, graph.transitiveDependents(p.id).size]) + .map((p: any) => [p.id, graph.transitiveDependents(p.id).size]) .sort((a, b) => b[1] - a[1]); -const maxDeps = transduce(pluck(1), max(), packageDeps); +const maxDeps = transduce(pluck(1), max(), packageDeps); const width = packages.length * 16; diff --git a/examples/package-stats/src/size-chart.ts b/examples/package-stats/src/size-chart.ts index 79e0e41e7d..e8c16f23e2 100644 --- a/examples/package-stats/src/size-chart.ts +++ b/examples/package-stats/src/size-chart.ts @@ -29,7 +29,7 @@ const meta = transduce( console.log(meta.length); -const fileSizeChart = (stats, modType, type) => { +const fileSizeChart = (stats: any, modType: string, type: string) => { const get = getter([1, modType, type]); stats = [...stats].sort((a, b) => get(b) - get(a)); @@ -56,7 +56,7 @@ const fileSizeChart = (stats, modType, type) => { axis: [80, width - 15, 170], domain: [0, stats.length, 1], range: [80, width - 5], - ticks: [...map((x) => x[0], stats)], + ticks: [...map((x: any) => x[0], stats)], label: labeledTickX }, y: { diff --git a/examples/package-stats/src/viz.ts b/examples/package-stats/src/viz.ts index 8a3972ad12..870acaeb1d 100644 --- a/examples/package-stats/src/viz.ts +++ b/examples/package-stats/src/viz.ts @@ -1,6 +1,18 @@ -import { group, line, svg, text, rect } from "@thi.ng/hiccup-svg"; +import { + group, + line, + rect, + svg, + text +} from "@thi.ng/hiccup-svg"; import { fit, fit01 } from "@thi.ng/math"; -import { map, mapcat, range, normRange, mapIndexed } from "@thi.ng/transducers"; +import { + map, + mapcat, + mapIndexed, + normRange, + range +} from "@thi.ng/transducers"; // iterator of range mapped tuples: `[mapped, orig]` const mappedRange = ( @@ -33,7 +45,7 @@ const tickX = (y: number) => ([x, n]: [number, any]) => const tickY = (x: number) => ([y, n]: [number, any]) => tick(x - 10, y, x, y, x - 15, y, n); -export const labeledTickX = (y) => ([x, n]: any[]) => [ +export const labeledTickX = (y: number) => ([x, n]: any[]) => [ line([x, y], [x, y + 5]), text([x, y + 15], n, { stroke: "none", @@ -42,16 +54,15 @@ export const labeledTickX = (y) => ([x, n]: any[]) => [ }) ]; -export const labeledTickY = (width, fmt = (x) => String(x)) => (x) => ([y, n]: [ - number, - any -]) => [ +export const labeledTickY = (width: number, fmt = (x: number) => String(x)) => ( + x: number +) => ([y, n]: [number, any]) => [ ...tick(x - 5, y, x, y, x - 10, y + 4, n > 0 ? fmt(n) : 0), n > 0 ? line([x + 20, y], [width, y], { "stroke-dasharray": "1 3" }) : null ]; // x-axis with ticks as SVG group -const axisX = ({ axis: a, domain: d, range: r, label, ticks }) => [ +export const axisX = ({ axis: a, domain: d, range: r, label, ticks }: any) => [ "g", { "text-anchor": "middle" }, line([a[0], a[2]], [a[1], a[2]]), @@ -64,7 +75,7 @@ const axisX = ({ axis: a, domain: d, range: r, label, ticks }) => [ ]; // y-axis with ticks as SVG group -const axisY = ({ axis: a, domain: d, range: r, label, ticks }) => [ +export const axisY = ({ axis: a, domain: d, range: r, label, ticks }: any) => [ "g", { "text-anchor": "end" }, line([a[2], a[0]], [a[2], a[1]]), @@ -77,16 +88,16 @@ const axisY = ({ axis: a, domain: d, range: r, label, ticks }) => [ ]; // mapping fn to create a single bar from `[domainPos, value]` -const bar = ({ domain: xd, range: xr }, { domain: yd, range: yr }) => ([ - xx, - yy -]) => { +const bar = ( + { domain: xd, range: xr }: any, + { domain: yd, range: yr }: any +) => ([xx, yy]: any) => { const y = fit(yy, yd[0], yd[1], yr[0], yr[1]); return rect([fit(xx, xd[0], xd[1], xr[0], xr[1]) - 5, y], 10, yr[0] - y); }; // complete bar chart component -export const barChart = (_, opts, values, ...xs) => +export const barChart = (_: any, opts: any, values: any, ...xs: any) => svg( opts.attribs, group( diff --git a/examples/package-stats/tsconfig.json b/examples/package-stats/tsconfig.json index 933ec03d70..373b7a7d9c 100644 --- a/examples/package-stats/tsconfig.json +++ b/examples/package-stats/tsconfig.json @@ -5,9 +5,7 @@ "module": "commonjs", "target": "es6", "noUnusedLocals": false, - "noUnusedParameters": false, + "noUnusedParameters": false }, - "include": [ - "./src/**/*.ts" - ] -} \ No newline at end of file + "include": ["./src/**/*.ts"] +} diff --git a/examples/pointfree-svg/package.json b/examples/pointfree-svg/package.json index 35e453a219..104ff42caa 100644 --- a/examples/pointfree-svg/package.json +++ b/examples/pointfree-svg/package.json @@ -5,7 +5,7 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn clean && tsc && node index.js", + "build": "yarn clean && ts-node src/index.ts", "clean": "rm -rf *.js" }, "dependencies": { @@ -15,6 +15,7 @@ "@thi.ng/pointfree-lang": "latest" }, "devDependencies": { - "typescript": "^3.4.1" + "ts-node": "^8.2.0", + "typescript": "^3.5.2" } -} +} \ No newline at end of file diff --git a/examples/router-basics/package.json b/examples/router-basics/package.json index 88390fb98e..4b616458e5 100644 --- a/examples/router-basics/package.json +++ b/examples/router-basics/package.json @@ -21,8 +21,8 @@ }, "devDependencies": { "parcel-bundler": "^1.12.3", - "terser": "^3.17.0", - "typescript": "^3.4.1" + "terser": "^4.0.0", + "typescript": "^3.5.2" }, "browserslist": [ "last 3 Chrome versions" @@ -30,4 +30,4 @@ "browser": { "process": false } -} +} \ No newline at end of file diff --git a/examples/router-basics/src/app.ts b/examples/router-basics/src/app.ts index 7272d70846..e12b52da55 100644 --- a/examples/router-basics/src/app.ts +++ b/examples/router-basics/src/app.ts @@ -4,7 +4,12 @@ import { isArray } from "@thi.ng/checks"; import { start } from "@thi.ng/hdom"; import { EventBus, trace, valueSetter } from "@thi.ng/interceptors"; import { EVENT_ROUTE_CHANGED, HTMLRouter } from "@thi.ng/router"; -import { AppConfig, AppContext, AppViews, ViewSpec } from "./api"; +import { + AppConfig, + AppContext, + AppViews, + ViewSpec +} from "./api"; import { debugContainer } from "./components/debug-container"; import { nav } from "./components/nav"; import * as fx from "./effects"; @@ -37,7 +42,7 @@ export class App { views: {}, ui: config.ui }; - this.addViews(this.config.views); + this.addViews(this.config.views); this.router = new HTMLRouter(config.router); // connect router to event bus so that routing events are processed // as part of the normal batched event processing loop @@ -81,7 +86,7 @@ export class App { * @param specs */ addViews(specs: IObjectOf) { - const views = this.ctx.views; + const views: any = this.ctx.views; for (let id in specs) { const spec = specs[id]; if (isArray(spec)) { @@ -116,7 +121,7 @@ export class App { * by current route and the derived view defined above. */ rootComponent(): any { - const debug = this.ctx.views.debug.deref(); + const debug = this.ctx.views.debug.deref()!; const ui = this.ctx.ui; return [ "div", diff --git a/examples/router-basics/src/components/all-users.ts b/examples/router-basics/src/components/all-users.ts index b98865d233..eb471e1ca7 100644 --- a/examples/router-basics/src/components/all-users.ts +++ b/examples/router-basics/src/components/all-users.ts @@ -1,10 +1,10 @@ import { AppContext, StatusType, User } from "../api"; import { LOAD_USER_LIST, SET_STATUS } from "../events"; import { USER_PROFILE } from "../routes"; - import { routeLink } from "./route-link"; import { status } from "./status"; + /** * Dummy user list component. Triggers JSON I/O request if user data has * not been loaded yet. @@ -13,7 +13,7 @@ import { status } from "./status"; */ export function allUsers(ctx: AppContext) { ctx.bus.dispatch( - ctx.views.userlist.deref().length + ctx.views.userlist.deref()!.length ? [SET_STATUS, [StatusType.SUCCESS, "list loaded from cache", true]] : [LOAD_USER_LIST] ); @@ -32,7 +32,7 @@ function userList(ctx: AppContext) { list && [ "section", ctx.ui.userlist.root, - list.map((u) => [user, u, !!profiles[u.id]]) + list.map((u) => [user, u, !!profiles![u.id]]) ] ); } diff --git a/examples/router-basics/src/components/event-link.ts b/examples/router-basics/src/components/event-link.ts index 8f75a22b18..1f2fa41e7d 100644 --- a/examples/router-basics/src/components/event-link.ts +++ b/examples/router-basics/src/components/event-link.ts @@ -1,7 +1,7 @@ import { Event } from "@thi.ng/interceptors"; - import { AppContext } from "../api"; + /** * Customizable hyperlink component emitting given event on app's event * bus when clicked. @@ -21,7 +21,7 @@ export function eventLink( "a", { ...attribs, - onclick: (e) => { + onclick: (e: any) => { e.preventDefault(); ctx.bus.dispatch(event); } diff --git a/examples/router-basics/src/components/route-link.ts b/examples/router-basics/src/components/route-link.ts index d0e61f2365..563b71ed1a 100644 --- a/examples/router-basics/src/components/route-link.ts +++ b/examples/router-basics/src/components/route-link.ts @@ -21,7 +21,7 @@ export function routeLink( "a", { ...attribs, - onclick: (e) => { + onclick: (e: Event) => { e.preventDefault(); ctx.bus.dispatch([ROUTE_TO, [routeID, routeParams]]); } diff --git a/examples/router-basics/src/components/status.ts b/examples/router-basics/src/components/status.ts index de5fc5160d..05d2535bfc 100644 --- a/examples/router-basics/src/components/status.ts +++ b/examples/router-basics/src/components/status.ts @@ -6,6 +6,6 @@ import { AppContext } from "../api"; * @param ctx injected context object */ export function status(ctx: AppContext) { - const [type, msg] = ctx.views.status.deref(); + const [type, msg] = ctx.views.status.deref()!; return ["p", ctx.ui.status[type], msg]; } diff --git a/examples/router-basics/src/components/user-profile.ts b/examples/router-basics/src/components/user-profile.ts index 7e4bed5369..36bd2f779f 100644 --- a/examples/router-basics/src/components/user-profile.ts +++ b/examples/router-basics/src/components/user-profile.ts @@ -1,8 +1,8 @@ -import { StatusType, AppContext } from "../api"; +import { AppContext, StatusType } from "../api"; import { LOAD_USER, SET_STATUS } from "../events"; - import { status } from "./status"; + /** * Single user profile page. Triggers JSON I/O request on init if user * data has not been loaded yet. @@ -10,9 +10,9 @@ import { status } from "./status"; * @param ctx injected context object */ export function userProfile(ctx: AppContext) { - const id = ctx.views.route.deref().params.id; + const id = ctx.views.route.deref()!.params.id; ctx.bus.dispatch( - ctx.views.users.deref()[id] + ctx.views.users.deref()![id] ? [SET_STATUS, [StatusType.SUCCESS, "loaded from cache", true]] : [LOAD_USER, id] ); @@ -21,7 +21,7 @@ export function userProfile(ctx: AppContext) { // based on: http://tachyons.io/components/cards/profile-card/index.html function userCard(ctx: AppContext, id: number) { - const user = ctx.views.users.deref()[id]; + const user = ctx.views.users.deref()![id]; const ui = ctx.ui.card; return user ? [ diff --git a/examples/rstream-dataflow/package.json b/examples/rstream-dataflow/package.json index f0a9f5cf0e..4c744403a2 100644 --- a/examples/rstream-dataflow/package.json +++ b/examples/rstream-dataflow/package.json @@ -11,8 +11,8 @@ }, "devDependencies": { "parcel-bundler": "^1.12.3", - "terser": "^3.17.0", - "typescript": "^3.4.1" + "terser": "^4.0.0", + "typescript": "^3.5.2" }, "dependencies": { "@thi.ng/atom": "latest", @@ -31,4 +31,4 @@ "browser": { "process": false } -} +} \ No newline at end of file diff --git a/examples/rstream-dataflow/src/index.ts b/examples/rstream-dataflow/src/index.ts index 1e3413e707..1e28faa91b 100644 --- a/examples/rstream-dataflow/src/index.ts +++ b/examples/rstream-dataflow/src/index.ts @@ -5,8 +5,19 @@ import { getIn } from "@thi.ng/paths"; import { fromRAF } from "@thi.ng/rstream"; import { toDot, walk } from "@thi.ng/rstream-dot"; import { gestureStream } from "@thi.ng/rstream-gestures"; -import { extract, initGraph, mul, node, node1 } from "@thi.ng/rstream-graph"; -import { choices, comp, dedupe, map } from "@thi.ng/transducers"; +import { + extract, + initGraph, + mul, + node, + node1 +} from "@thi.ng/rstream-graph"; +import { + choices, + comp, + dedupe, + map +} from "@thi.ng/transducers"; import { circle } from "./circle"; // infinite iterator of randomized colors (Tachyons CSS class names) @@ -30,7 +41,7 @@ const db = new Atom({}); // this stream produces tuples of: // [eventtype, [pos, clickpos, delta]] // Note: only single touches are supported, no multitouch! -const gestures = gestureStream(document.getElementById("app")); +const gestures = gestureStream(document.getElementById("app")!); // requestAnimationFrame() based counter stream. this is consumed by the // "sine" graph node below, but predefined here for visualization @@ -94,11 +105,10 @@ const graph = initGraph(db, { // with multiple inputs circle: { fn: node( - map( - ({ click, radius, color }) => - click && radius && color - ? circle(color, click[0], click[1], radius * 2) - : undefined + map(({ click, radius, color }) => + click && radius && color + ? circle(color, click[0], click[1], radius * 2) + : undefined ) ), ins: { diff --git a/examples/rstream-grid/package.json b/examples/rstream-grid/package.json index 5b6f008b11..bc8d0a9b29 100644 --- a/examples/rstream-grid/package.json +++ b/examples/rstream-grid/package.json @@ -26,8 +26,8 @@ "devDependencies": { "@types/node": "^9.6.2", "parcel-bundler": "^1.12.3", - "terser": "^3.17.0", - "typescript": "^3.4.1" + "terser": "^4.0.0", + "typescript": "^3.5.2" }, "browserslist": [ "last 3 Chrome versions" @@ -35,4 +35,4 @@ "browser": { "process": false } -} +} \ No newline at end of file diff --git a/examples/rstream-grid/src/app.ts b/examples/rstream-grid/src/app.ts index ab05cec2f9..2856ea3cda 100644 --- a/examples/rstream-grid/src/app.ts +++ b/examples/rstream-grid/src/app.ts @@ -3,7 +3,12 @@ import { Atom, Cursor, History } from "@thi.ng/atom"; import { isArray } from "@thi.ng/checks"; import { start } from "@thi.ng/hdom"; import { EventBus } from "@thi.ng/interceptors"; -import { AppConfig, AppContext, AppViews, ViewSpec } from "./api"; +import { + AppConfig, + AppContext, + AppViews, + ViewSpec +} from "./api"; import { initDataflow } from "./dataflow"; import * as ev from "./events"; import { PARAM_BASE } from "./paths"; @@ -40,7 +45,7 @@ export class App { ui: config.ui }; // initialize derived views - this.addViews(this.config.views); + this.addViews(this.config.views); } /** @@ -54,9 +59,9 @@ export class App { for (let id in specs) { const spec = specs[id]; if (isArray(spec)) { - views[id] = this.state.addView(spec[0], spec[1]); + (views)[id] = this.state.addView(spec[0], spec[1]); } else { - views[id] = this.state.addView(spec); + (views)[id] = this.state.addView(spec); } } } diff --git a/examples/rstream-grid/src/components/button-group.ts b/examples/rstream-grid/src/components/button-group.ts index c47c26e393..3d09013fd8 100644 --- a/examples/rstream-grid/src/components/button-group.ts +++ b/examples/rstream-grid/src/components/button-group.ts @@ -1,7 +1,7 @@ import { AppContext } from "../api"; import { button } from "./button"; -export const buttonGroup = (ctx: AppContext, ...buttons) => [ +export const buttonGroup = (ctx: AppContext, ...buttons: any[]) => [ "section", ctx.ui.buttongroup, buttons.map((bt) => [button, ...bt]) diff --git a/examples/rstream-grid/src/components/event-link.ts b/examples/rstream-grid/src/components/event-link.ts index 640972e68a..b0a3c801d8 100644 --- a/examples/rstream-grid/src/components/event-link.ts +++ b/examples/rstream-grid/src/components/event-link.ts @@ -1,7 +1,7 @@ import { Event } from "@thi.ng/interceptors"; - import { AppContext } from "../api"; + /** * Customizable hyperlink component emitting given event on event bus * when clicked. @@ -20,7 +20,7 @@ export const eventLink = ( "a", { ...attribs, - onclick: (e) => { + onclick: (e: any) => { e.preventDefault(); ctx.bus.dispatch(event); } diff --git a/examples/rstream-grid/src/components/link.ts b/examples/rstream-grid/src/components/link.ts index 971889ead2..f8f02097f6 100644 --- a/examples/rstream-grid/src/components/link.ts +++ b/examples/rstream-grid/src/components/link.ts @@ -1,6 +1,6 @@ import { AppContext } from "../api"; -export const link = (ctx: AppContext, href, ...body) => [ +export const link = (ctx: AppContext, href: string, ...body: any[]) => [ "a", { ...ctx.ui.link, href }, ...body diff --git a/examples/rstream-grid/src/components/slider.ts b/examples/rstream-grid/src/components/slider.ts index 51a17097a6..7240893bf2 100644 --- a/examples/rstream-grid/src/components/slider.ts +++ b/examples/rstream-grid/src/components/slider.ts @@ -26,8 +26,11 @@ export interface SliderOpts { export const slider = (ctx: AppContext, opts: SliderOpts) => { opts = Object.assign( { - oninput: (e) => - ctx.bus.dispatch([opts.event, parseFloat(e.target.value)]), + oninput: (e: Event) => + ctx.bus.dispatch([ + opts.event, + parseFloat((e.target).value) + ]), min: 0, max: 100, step: 1 @@ -44,7 +47,7 @@ export const slider = (ctx: AppContext, opts: SliderOpts) => { ...ui.range, ...opts, type: "range", - value: ctx.views[opts.view].deref() + value: (ctx.views)[opts.view].deref() } ], [ @@ -57,7 +60,7 @@ export const slider = (ctx: AppContext, opts: SliderOpts) => { ...ui.number, ...opts, type: "number", - value: ctx.views[opts.view].deref() + value: (ctx.views)[opts.view].deref() } ] ] diff --git a/examples/rstream-grid/src/config.ts b/examples/rstream-grid/src/config.ts index 9ce9dc99e8..df4d003dc5 100644 --- a/examples/rstream-grid/src/config.ts +++ b/examples/rstream-grid/src/config.ts @@ -31,7 +31,7 @@ export const CONFIG: AppConfig = { // interceptor to record a snapshot of the current app state // before applying new slider value ...SLIDERS.reduce( - (events, spec) => ( + (events: any, spec) => ( (events[spec.event] = [snapshot(), valueSetter(spec.path)]), events ), diff --git a/examples/rstream-grid/src/dataflow.ts b/examples/rstream-grid/src/dataflow.ts index f6dcec0f20..5b3bc6934c 100644 --- a/examples/rstream-grid/src/dataflow.ts +++ b/examples/rstream-grid/src/dataflow.ts @@ -70,7 +70,7 @@ const grid = node( const rotate = node( map(({ shapes, theta }) => shapes.map( - (s) => ( + (s: any) => ( (s[1].transform = `rotate(${theta} ${s[1].x + 0.5} ${s[1].y + 0.5})`), s diff --git a/examples/rstream-grid/src/index.ts b/examples/rstream-grid/src/index.ts index 8ebcb7ec8c..edc3088d0b 100644 --- a/examples/rstream-grid/src/index.ts +++ b/examples/rstream-grid/src/index.ts @@ -4,7 +4,7 @@ import { CONFIG } from "./config"; // export app to global var in dev mode // (for interaction via browser dev tools) if (process.env.NODE_ENV === "development") { - (window["APP"] = new App(CONFIG)).start(); + ((window)["APP"] = new App(CONFIG)).start(); } else { new App(CONFIG).start(); } diff --git a/examples/rstream-hdom/package.json b/examples/rstream-hdom/package.json index 0af87613b6..4be3ab816a 100644 --- a/examples/rstream-hdom/package.json +++ b/examples/rstream-hdom/package.json @@ -11,8 +11,8 @@ }, "devDependencies": { "parcel-bundler": "^1.12.3", - "terser": "^3.17.0", - "typescript": "^3.4.1" + "terser": "^4.0.0", + "typescript": "^3.5.2" }, "dependencies": { "@thi.ng/arrays": "latest", @@ -26,4 +26,4 @@ "browser": { "process": false } -} +} \ No newline at end of file diff --git a/examples/rstream-hdom/src/index.ts b/examples/rstream-hdom/src/index.ts index e90a6ffe9c..95e4dd59fd 100644 --- a/examples/rstream-hdom/src/index.ts +++ b/examples/rstream-hdom/src/index.ts @@ -7,7 +7,12 @@ import { subscription, sync } from "@thi.ng/rstream"; -import { map, reducer, scan, vals } from "@thi.ng/transducers"; +import { + map, + reducer, + scan, + vals +} from "@thi.ng/transducers"; import { updateDOM } from "@thi.ng/transducers-hdom"; // example user context object @@ -48,7 +53,7 @@ const ctx = { */ const domUpdate = (root: HTMLElement, tree: ISubscribable, ctx?: any) => tree - .subscribe(sidechainPartition(fromRAF())) + .subscribe(sidechainPartition(fromRAF())) .transform(map(peek), updateDOM({ root, ctx })); /** @@ -70,7 +75,7 @@ const button = (ctx: any, onclick: EventListener, body: any) => [ * @param _ hdom user context (unused) * @param stream counter stream */ -const clickButton = (_, stream: Subscription) => [ +const clickButton = (_: any, stream: Subscription) => [ button, () => stream.next(true), stream.deref() @@ -82,7 +87,7 @@ const clickButton = (_, stream: Subscription) => [ * @param _ hdom user context (unused) * @param counters streams to reset */ -const resetButton = (_, counters: Subscription[]) => [ +const resetButton = (_: any, counters: Subscription[]) => [ button, () => counters.forEach((c) => c.next(false)), "reset" @@ -98,7 +103,7 @@ const resetButton = (_, counters: Subscription[]) => [ */ const counter = (start: number, step: number) => { const s = subscription( - null, + undefined, // the `scan` transducer is used to provide counter functionality // see: https://github.com/thi-ng/umbrella/blob/master/packages/transducers/src/xform/scan.ts scan(reducer(() => start, (x, y) => (y ? x + step : start))) @@ -117,7 +122,7 @@ const counter = (start: number, step: number) => { */ const app = (ctx: any, initial: number[][]) => { const counters = initial.map(([start, step]) => counter(start, step)); - return sync({ + return sync({ src: counters.map((c) => c.transform(map(() => [clickButton, c]))), xform: map( // build the app's actual root component @@ -142,7 +147,7 @@ const app = (ctx: any, initial: number[][]) => { // start app & DOM updates domUpdate( - document.getElementById("app"), + document.getElementById("app")!, app(ctx, [[10, 1], [20, 5], [30, 10]]), ctx ); diff --git a/examples/webgl/.gitignore b/examples/shader-ast-canvas2d/.gitignore similarity index 100% rename from examples/webgl/.gitignore rename to examples/shader-ast-canvas2d/.gitignore diff --git a/examples/shader-ast-canvas2d/README.md b/examples/shader-ast-canvas2d/README.md new file mode 100644 index 0000000000..7e7341d254 --- /dev/null +++ b/examples/shader-ast-canvas2d/README.md @@ -0,0 +1,18 @@ +# shader-ast-canvas2d + +[Live demo](http://demo.thi.ng/umbrella/shader-ast-canvas2d/) + +WIP example of using +[@thi.ng/shader-ast](https://github.com/thi-ng/umbrella/tree/master/packages/shader-ast) +to port an existing WebGL fragment shader to JavaScript and execute in a +canvas 2D context. + +Please refer to the [example build instructions](https://github.com/thi-ng/umbrella/wiki/Example-build-instructions) on the wiki. + +## Authors + +- Karsten Schmidt + +## License + +© 2018 Karsten Schmidt // Apache Software License 2.0 diff --git a/examples/shader-ast-canvas2d/index.html b/examples/shader-ast-canvas2d/index.html new file mode 100644 index 0000000000..61d3636434 --- /dev/null +++ b/examples/shader-ast-canvas2d/index.html @@ -0,0 +1,18 @@ + + + + + + + shader-ast-canvas2d + + + + +
+ + + diff --git a/examples/shader-ast-canvas2d/package.json b/examples/shader-ast-canvas2d/package.json new file mode 100644 index 0000000000..70cfc7b252 --- /dev/null +++ b/examples/shader-ast-canvas2d/package.json @@ -0,0 +1,29 @@ +{ + "name": "shader-ast-canvas2d", + "version": "0.0.1", + "repository": "https://github.com/thi-ng/umbrella", + "author": "Karsten Schmidt ", + "license": "Apache-2.0", + "scripts": { + "clean": "rm -rf .cache build out", + "build": "yarn clean && parcel build index.html -d out --public-url ./ --no-source-maps --no-cache --detailed-report", + "start": "parcel index.html -p 8080 --open" + }, + "devDependencies": { + "parcel-bundler": "^1.12.3", + "terser": "^4.0.0", + "typescript": "^3.5.2" + }, + "dependencies": { + "@thi.ng/shader-ast": "latest", + "@thi.ng/shader-ast-glsl": "latest", + "@thi.ng/shader-ast-js": "latest", + "@thi.ng/shader-ast-stdlib": "latest" + }, + "browserslist": [ + "last 3 Chrome versions" + ], + "browser": { + "process": false + } +} \ No newline at end of file diff --git a/examples/shader-ast-canvas2d/src/index.ts b/examples/shader-ast-canvas2d/src/index.ts new file mode 100644 index 0000000000..3ecb1933bf --- /dev/null +++ b/examples/shader-ast-canvas2d/src/index.ts @@ -0,0 +1,89 @@ +import { + $x, + $y, + add, + cos, + defn, + div, + dot, + float, + FloatSym, + mul, + ret, + sin, + sym, + Vec2Sym, + vec3, + vec4 +} from "@thi.ng/shader-ast"; +import { targetGLSL } from "@thi.ng/shader-ast-glsl"; +import { initRuntime, targetJS } from "@thi.ng/shader-ast-js"; +import { fit0111, fit1101 } from "@thi.ng/shader-ast-stdlib"; + +const js = targetJS(); +const gl = targetGLSL(); + +// ported from: http://glslsandbox.com/e#55242.0 +const main = defn( + // return type + "vec4", + // func name + "main", + // args (names are optional) + [["vec2", "fragCoord"], ["vec2", "res"], ["float", "time"]], + // bound args given to function body + (frag, res, time) => { + let a: FloatSym; + let p: FloatSym; + let uv: Vec2Sym; + let sp: Vec2Sym; + let dp: FloatSym; + let p2: FloatSym; + let m: FloatSym; + return [ + (a = sym(add(mul(sin(time), float(2)), float(3)))), + (p = sym(add(mul($y(frag), $x(res)), $x(frag)))), + (uv = sym(fit0111(div(frag, res)))), + (sp = sym(mul(uv, a))), + (dp = sym(dot(sp, sp))), + (p2 = sym(add(mul($y(sp), $x(res)), $x(sp)))), + (m = sym( + mul( + div(add(p2, mul(p, a)), mul($x(res), $y(res))), + mul($x(sp), $y(sp)) + ) + )), + ret( + vec4( + fit1101( + cos(mul(add(sin(mul(vec3(1, 2, 3), m)), dp), float(2))) + ), + 1 + ) + ) + ]; + } +); + +console.log("JS:"); +console.log(js(main)); +console.log("GLSL:"); +console.log(gl(main)); + +const fn = js.compile(main).main; + +const W = 640; +const H = 480; +const size = [W, H]; +const canvas = document.createElement("canvas"); +canvas.width = W; +canvas.height = H; +document.body.appendChild(canvas); + +const rt = initRuntime({ canvas }); +const t0 = Date.now(); + +setInterval(() => { + const time = (Date.now() - t0) * 0.001; + rt.update((frag) => fn(frag, size, time)); +}, 16); diff --git a/examples/webgl/tsconfig.json b/examples/shader-ast-canvas2d/tsconfig.json similarity index 57% rename from examples/webgl/tsconfig.json rename to examples/shader-ast-canvas2d/tsconfig.json index 21c832b5d7..bbf112cc18 100644 --- a/examples/webgl/tsconfig.json +++ b/examples/shader-ast-canvas2d/tsconfig.json @@ -2,13 +2,10 @@ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": ".", - "module": "es6", "target": "es6", - "sourceMap": true, - "noUnusedLocals": false, - "noUnusedParameters": false + "sourceMap": true }, "include": [ "./src/**/*.ts" ] -} \ No newline at end of file +} diff --git a/examples/shader-ast-noise/.gitignore b/examples/shader-ast-noise/.gitignore new file mode 100644 index 0000000000..0c5abcab62 --- /dev/null +++ b/examples/shader-ast-noise/.gitignore @@ -0,0 +1,5 @@ +.cache +out +node_modules +yarn.lock +*.js diff --git a/examples/shader-ast-noise/README.md b/examples/shader-ast-noise/README.md new file mode 100644 index 0000000000..a20c798013 --- /dev/null +++ b/examples/shader-ast-noise/README.md @@ -0,0 +1,14 @@ +# shader-ast-noise + +- [Live demo (WebGL)](http://demo.thi.ng/umbrella/shader-ast-noise/) +- [Live demo (Canvas 2D)](http://demo.thi.ng/umbrella/shader-ast-noise/#2d) + +Please refer to the [example build instructions](https://github.com/thi-ng/umbrella/wiki/Example-build-instructions) on the wiki. + +## Authors + +- Karsten Schmidt + +## License + +© 2019 Karsten Schmidt // Apache Software License 2.0 diff --git a/examples/shader-ast-noise/index.html b/examples/shader-ast-noise/index.html new file mode 100644 index 0000000000..7a1fc0bfb0 --- /dev/null +++ b/examples/shader-ast-noise/index.html @@ -0,0 +1,37 @@ + + + + + + + shader-ast-noise + + + + +
+
+

+ Shader generated with + thi.ng/shader-ast.
(see console for generated sources) +

+

+ Append #2d to URL, then + reload to view canvas 2D version +

+

+ Source code +

+
+ + + diff --git a/examples/shader-ast-noise/package.json b/examples/shader-ast-noise/package.json new file mode 100644 index 0000000000..b65f104e82 --- /dev/null +++ b/examples/shader-ast-noise/package.json @@ -0,0 +1,31 @@ +{ + "name": "shader-ast-noise", + "version": "0.0.1", + "repository": "https://github.com/thi-ng/umbrella", + "author": "Karsten Schmidt ", + "license": "Apache-2.0", + "scripts": { + "clean": "rm -rf .cache build out", + "build": "yarn clean && parcel build index.html -d out --public-url ./ --no-source-maps --no-cache --detailed-report", + "build:webpack": "../../node_modules/.bin/webpack --mode production", + "start": "parcel index.html -p 8080 --open" + }, + "devDependencies": { + "parcel-bundler": "^1.12.3", + "terser": "^3.17.0", + "typescript": "^3.4.1" + }, + "dependencies": { + "@thi.ng/shader-ast": "latest", + "@thi.ng/shader-ast-glsl": "latest", + "@thi.ng/shader-ast-js": "latest", + "@thi.ng/shader-ast-stdlib": "latest", + "@thi.ng/webgl": "latest" + }, + "browserslist": [ + "last 3 Chrome versions" + ], + "browser": { + "process": false + } +} \ No newline at end of file diff --git a/examples/shader-ast-noise/src/index.ts b/examples/shader-ast-noise/src/index.ts new file mode 100644 index 0000000000..0112b17656 --- /dev/null +++ b/examples/shader-ast-noise/src/index.ts @@ -0,0 +1,133 @@ +import { + $xy, + add, + assign, + defMain, + defn, + float, + FloatSym, + program, + ret, + sym, + vec2, + Vec2Sym, + vec3, + vec4 +} from "@thi.ng/shader-ast"; +import { GLSLVersion, targetGLSL } from "@thi.ng/shader-ast-glsl"; +import { initRuntime, targetJS } from "@thi.ng/shader-ast-js"; +import { + additive, + aspectCorrectedUV, + fit1101, + snoise2 +} from "@thi.ng/shader-ast-stdlib"; +import { + compileModel, + draw, + quad, + shader +} from "@thi.ng/webgl"; + +// set URL hash to "#2d" to enable JS Canvas2D version +const JS_MODE = location.hash.indexOf("2d") >= 0; + +// AST compile targets +const GL = targetGLSL({ version: GLSLVersion.GLES_100 }); // WebGL +const JS = targetJS(); + +// https://www.shadertoy.com/view/Ms2SWW (by iq) +const mainImage = defn( + "vec4", + "mainImage", + [["vec2", "fragCoord"], ["vec2", "res"], ["float", "time"]], + (fragCoord, res, time) => { + let uv: Vec2Sym; + let col: FloatSym; + return [ + (uv = sym(aspectCorrectedUV(fragCoord, res))), + // dynamically create a multi-octave version of `snoise2` + // computed over 4 octaves w/ given phase shift and decay + // factor (both per octave) + (col = sym( + additive("vec2", snoise2, 4)(add(uv, time), vec2(2), float(0.5)) + )), + ret(vec4(vec3(fit1101(col)), 1)) + ]; + } +); + +// build call graph for given entry function, sort in topological order +// and bundle all functions in a global scope for code generation... +const shaderProgram = program([mainImage]); + +console.log("JS"); +console.log(JS(shaderProgram)); +console.log("GLSL"); +console.log(GL(shaderProgram)); + +const W = 256; +const H = 256; +const size = [W, H]; +const canvas = document.createElement("canvas"); +canvas.width = W; +canvas.height = H; +document.body.appendChild(canvas); +const info = document.createElement("div"); +info.innerText = (JS_MODE ? "Canvas2D" : "WebGL") + " version"; +document.body.appendChild(info); + +if (JS_MODE) { + // + // JS Canvas 2D shader emulation from here... + // + const fn = JS.compile(shaderProgram).mainImage; + const rt = initRuntime({ canvas }); + let time = 0; + + setInterval(() => { + time += 0.01; + rt.update((frag) => fn(frag, size, time)); + }, 16); +} else { + // + // WebGL mode... + // + const ctx: WebGLRenderingContext = canvas.getContext("webgl")!; + // build fullscreen quad + const model = quad(false); + // set shader + model.shader = shader(ctx, { + vs: (gl, _, attribs) => [ + defMain(() => [ + assign(gl.gl_Position, vec4(attribs.position, 0, 1)) + ]) + ], + fs: (gl, unis, _, outs) => [ + mainImage, + defMain(() => [ + assign( + outs.fragColor, + mainImage($xy(gl.gl_FragCoord), unis.resolution, unis.time) + ) + ]) + ], + attribs: { + position: "vec2" + }, + uniforms: { + resolution: ["vec2", [W, H]], + time: "float" + } + }); + // compile model (attrib buffers) + compileModel(ctx, model); + + const t0 = Date.now(); + // render loop + setInterval(() => { + const time = (Date.now() - t0) * 0.001; + model.uniforms!.time = time; + draw(model); + }); +} diff --git a/examples/shader-ast-noise/tsconfig.json b/examples/shader-ast-noise/tsconfig.json new file mode 100644 index 0000000000..bbf112cc18 --- /dev/null +++ b/examples/shader-ast-noise/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": ".", + "target": "es6", + "sourceMap": true + }, + "include": [ + "./src/**/*.ts" + ] +} diff --git a/examples/shader-ast-noise/webpack.config.js b/examples/shader-ast-noise/webpack.config.js new file mode 100644 index 0000000000..bf16021356 --- /dev/null +++ b/examples/shader-ast-noise/webpack.config.js @@ -0,0 +1,23 @@ +module.exports = { + entry: "./src/index.ts", + output: { + filename: "bundle.[hash].js", + path: __dirname + "/out" + }, + resolve: { + extensions: [".ts", ".js"] + }, + module: { + rules: [ + { + test: /\.(png|jpg|gif)$/, + loader: "file-loader", + options: { name: "[path][hash].[ext]" } + }, + { test: /\.ts$/, use: "ts-loader" } + ] + }, + node: { + process: false + } +}; diff --git a/examples/shader-ast-raymarch/.gitignore b/examples/shader-ast-raymarch/.gitignore new file mode 100644 index 0000000000..0c5abcab62 --- /dev/null +++ b/examples/shader-ast-raymarch/.gitignore @@ -0,0 +1,5 @@ +.cache +out +node_modules +yarn.lock +*.js diff --git a/examples/shader-ast-raymarch/README.md b/examples/shader-ast-raymarch/README.md new file mode 100644 index 0000000000..c48c8b134e --- /dev/null +++ b/examples/shader-ast-raymarch/README.md @@ -0,0 +1,19 @@ +# shader-ast-raymarch + +- [Live demo (WebGL)](http://demo.thi.ng/umbrella/shader-ast-raymarch/) +- [Live demo (Canvas 2D)](http://demo.thi.ng/umbrella/shader-ast-raymarch/#2d) + +Basic 3D raymarch shader defined via higher-order constructs of +[@thi.ng/shader-ast](https://github.com/thi-ng/umbrella/tree/master/packages/shader-ast) +and cross-compiled to GLSL and JavaScript, the latter for emulating the +shader using Canvas 2D API (`getImageData()`). + +Please refer to the [example build instructions](https://github.com/thi-ng/umbrella/wiki/Example-build-instructions) on the wiki. + +## Authors + +- Karsten Schmidt + +## License + +© 2019 Karsten Schmidt // Apache Software License 2.0 diff --git a/examples/shader-ast-raymarch/assets/tex.jpg b/examples/shader-ast-raymarch/assets/tex.jpg new file mode 100644 index 0000000000..d9ee61d1c0 Binary files /dev/null and b/examples/shader-ast-raymarch/assets/tex.jpg differ diff --git a/examples/shader-ast-raymarch/index.html b/examples/shader-ast-raymarch/index.html new file mode 100644 index 0000000000..4df683ba16 --- /dev/null +++ b/examples/shader-ast-raymarch/index.html @@ -0,0 +1,37 @@ + + + + + + + shader-ast-raymarch + + + + +
+
+

+ Shader generated with + thi.ng/shader-ast.
(see console for generated sources) +

+

+ Append #2d to URL, then + reload to view canvas 2D version +

+

+ Source code +

+
+ + + diff --git a/examples/shader-ast-raymarch/package.json b/examples/shader-ast-raymarch/package.json new file mode 100644 index 0000000000..379ab10974 --- /dev/null +++ b/examples/shader-ast-raymarch/package.json @@ -0,0 +1,31 @@ +{ + "name": "shader-ast-raymarch", + "version": "0.0.1", + "repository": "https://github.com/thi-ng/umbrella", + "author": "Karsten Schmidt ", + "license": "Apache-2.0", + "scripts": { + "clean": "rm -rf .cache build out", + "build": "yarn clean && parcel build index.html -d out --public-url ./ --no-source-maps --no-cache --detailed-report", + "build:webpack": "../../node_modules/.bin/webpack --mode production", + "start": "parcel index.html -p 8080 --open" + }, + "devDependencies": { + "parcel-bundler": "^1.12.3", + "terser": "^3.17.0", + "typescript": "^3.4.1" + }, + "dependencies": { + "@thi.ng/shader-ast": "latest", + "@thi.ng/shader-ast-glsl": "latest", + "@thi.ng/shader-ast-js": "latest", + "@thi.ng/shader-ast-stdlib": "latest", + "@thi.ng/webgl": "latest" + }, + "browserslist": [ + "last 3 Chrome versions" + ], + "browser": { + "process": false + } +} \ No newline at end of file diff --git a/examples/shader-ast-raymarch/src/index.ts b/examples/shader-ast-raymarch/src/index.ts new file mode 100644 index 0000000000..c4d0298539 --- /dev/null +++ b/examples/shader-ast-raymarch/src/index.ts @@ -0,0 +1,249 @@ +import { + $x, + $xy, + $xyz, + assign, + defMain, + defn, + float, + FloatSym, + gte, + ifThen, + mix, + mul, + program, + ret, + sym, + vec2, + Vec2Sym, + vec3, + Vec3Sym, + vec4 +} from "@thi.ng/shader-ast"; +import { GLSLVersion, targetGLSL } from "@thi.ng/shader-ast-glsl"; +import { initRuntime, targetJS } from "@thi.ng/shader-ast-js"; +import { + clamp01, + diffuseLighting, + fit1101, + fogExp2, + halfLambert, + lookat, + raymarchAO, + raymarchDir, + raymarchNormal, + raymarchScene, + rayPointAt, + sdfBox3, + sdfRepeat3, + sdfSmoothUnion, + sdfSphere +} from "@thi.ng/shader-ast-stdlib"; +import { + compileModel, + draw, + GLVec3, + quad, + shader +} from "@thi.ng/webgl"; + +// set URL hash to "#2d" to enable JS Canvas2D version +const JS_MODE = location.hash.indexOf("2d") >= 0; + +// AST compile targets +const GL = targetGLSL({ version: GLSLVersion.GLES_100, versionPragma: false }); // WebGL +const JS = targetJS(); + +// scene definition for raymarch function. uses SDF primitive functions +// included in "standard library" bundled with shader-ast pkg +const scene = defn("vec2", "scene", [["vec3"]], (pos) => { + let d1: FloatSym; + let d2: FloatSym; + let d3: FloatSym; + let d4: FloatSym; + return [ + assign(pos, sdfRepeat3(pos, vec3(2.1))), + (d1 = sym(sdfSphere(pos, float(0.5)))), + (d2 = sym(sdfBox3(pos, vec3(1, 0.2, 0.2)))), + (d3 = sym(sdfBox3(pos, vec3(0.2, 0.2, 1)))), + (d4 = sym(sdfBox3(pos, vec3(0.2, 1, 0.2)))), + ret( + vec2( + sdfSmoothUnion( + sdfSmoothUnion( + sdfSmoothUnion(d1, d2, float(0.2)), + d3, + float(0.2) + ), + d4, + float(0.2) + ), + 1 + ) + ) + ]; +}); + +// main fragment shader function +// again uses several shader-ast std lib helpers +const mainImage = defn( + "vec4", + "mainImage", + [["vec2"], ["vec2"], ["vec3"], ["vec3"]], + (frag, res, eyePos, lightDir) => { + let dir: Vec3Sym; + let result: Vec2Sym; + let isec: Vec3Sym; + let norm: Vec3Sym; + let material: Vec3Sym; + let diffuse: FloatSym; + // background color + const bg = vec3(1.5, 0.6, 0); + const ambient = vec3(0.15, 0.06, 0); + return [ + // compute ray dir from fragCoord, viewport res and FOV + // then apply basic camera settings (eye, target, up) + (dir = sym( + $xyz( + mul( + lookat(eyePos, vec3(), vec3(0, 1, 0)), + vec4(raymarchDir(frag, res, float(120)), 0) + ) + ) + )), + // perform raymarch + (result = sym( + // `raymarchScene` is a higher-order, configurable function which constructs + // a raymarch function using our supplied scene fn + raymarchScene(scene, { steps: JS_MODE ? 60 : 80, eps: 0.005 })( + eyePos, + dir + ) + )), + // early bailout if nothing hit + ifThen(gte($x(result), float(10)), [ret(vec4(bg, 1))]), + // set intersection pos + (isec = sym(rayPointAt(eyePos, dir, $x(result)))), + // surface normal + (norm = sym( + // higher-order fn to compute surface normal + raymarchNormal(scene)(isec, float(0.01)) + )), + // set material color + (material = sym(fit1101(isec))), + // compute diffuse term + (diffuse = sym( + mul( + halfLambert(norm, lightDir), + // higher order fn to compute ambient occlusion + raymarchAO(scene)(isec, norm) + ) + )), + // combine lighting & material colors + ret( + vec4( + mix( + clamp01( + diffuseLighting(diffuse, material, vec3(1), ambient) + ), + bg, + fogExp2($x(result), float(0.2)) + ), + 1 + ) + ) + ]; + } +); + +// build call graph for given entry function, sort in topological order +// and bundle all functions in a global scope for code generation... +const shaderProgram = program([mainImage]); + +console.log("JS"); +console.log(JS(shaderProgram)); +console.log("GLSL"); +console.log(GL(shaderProgram)); + +const W = 320; +const H = 240; +const size = [W, H]; +const canvas = document.createElement("canvas"); +canvas.width = W; +canvas.height = H; +document.body.appendChild(canvas); +const info = document.createElement("div"); +info.innerText = (JS_MODE ? "Canvas2D" : "WebGL") + " version"; +document.body.appendChild(info); + +const lightDir = [0.707, 0.707, 0]; + +if (JS_MODE) { + // + // JS Canvas 2D shader emulation from here... + // + const fn = JS.compile(shaderProgram).mainImage; + const rt = initRuntime({ canvas }); + let time = 0; + + setInterval(() => { + time += 0.1; + const eyePos = [ + Math.cos(time) * 2.5, + Math.cos(time / 2) * 0.7, + Math.sin(time) * 2.5 + ]; + rt.update((frag) => fn(frag, size, eyePos, lightDir)); + }, 16); +} else { + // + // WebGL mode... + // + const ctx: WebGLRenderingContext = canvas.getContext("webgl")!; + // build fullscreen quad + const model = quad(false); + // set shader + model.shader = shader(ctx, { + vs: (_, __, attribs) => [ + defMain(() => [ + assign(GL.gl_Position, vec4(attribs.position, 0, 1)) + ]) + ], + fs: (gl, unis, _, outputs) => [ + mainImage, + defMain(() => [ + assign( + outputs.fragColor, + mainImage( + $xy(gl.gl_FragCoord), + unis.resolution, + unis.eyePos, + unis.lightDir + ) + ) + ]) + ], + attribs: { + position: "vec2" + }, + uniforms: { + eyePos: "vec3", + lightDir: ["vec3", lightDir], + resolution: ["vec2", [W, H]] + } + }); + // compile model (attrib buffers) + compileModel(ctx, model); + + const t0 = Date.now(); + // render loop + setInterval(() => { + const time = (Date.now() - t0) * 0.001; + model.uniforms!.eyePos = [ + Math.cos(time) * 2.5, + Math.cos(time / 2) * 0.7, + Math.sin(time) * 2.5 + ]; + draw(model); + }); +} diff --git a/examples/shader-ast-raymarch/tsconfig.json b/examples/shader-ast-raymarch/tsconfig.json new file mode 100644 index 0000000000..bbf112cc18 --- /dev/null +++ b/examples/shader-ast-raymarch/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": ".", + "target": "es6", + "sourceMap": true + }, + "include": [ + "./src/**/*.ts" + ] +} diff --git a/examples/shader-ast-raymarch/webpack.config.js b/examples/shader-ast-raymarch/webpack.config.js new file mode 100644 index 0000000000..bf16021356 --- /dev/null +++ b/examples/shader-ast-raymarch/webpack.config.js @@ -0,0 +1,23 @@ +module.exports = { + entry: "./src/index.ts", + output: { + filename: "bundle.[hash].js", + path: __dirname + "/out" + }, + resolve: { + extensions: [".ts", ".js"] + }, + module: { + rules: [ + { + test: /\.(png|jpg|gif)$/, + loader: "file-loader", + options: { name: "[path][hash].[ext]" } + }, + { test: /\.ts$/, use: "ts-loader" } + ] + }, + node: { + process: false + } +}; diff --git a/examples/shader-ast-sdf2d/.gitignore b/examples/shader-ast-sdf2d/.gitignore new file mode 100644 index 0000000000..0c5abcab62 --- /dev/null +++ b/examples/shader-ast-sdf2d/.gitignore @@ -0,0 +1,5 @@ +.cache +out +node_modules +yarn.lock +*.js diff --git a/examples/shader-ast-sdf2d/README.md b/examples/shader-ast-sdf2d/README.md new file mode 100644 index 0000000000..1eb3e162a4 --- /dev/null +++ b/examples/shader-ast-sdf2d/README.md @@ -0,0 +1,19 @@ +# shader-ast-sdf2 + +- [Live demo (WebGL)](http://demo.thi.ng/umbrella/shader-ast-raymarch/) +- [Live demo (Canvas 2D)](http://demo.thi.ng/umbrella/shader-ast-raymarch/#2d) + +Basic 3D raymarch shader defined via higher-order constructs of +[@thi.ng/shader-ast](https://github.com/thi-ng/umbrella/tree/master/packages/shader-ast) +and cross-compiled to GLSL and JavaScript, the latter for emulating the +shader using Canvas 2D API (`getImageData()`). + +Please refer to the [example build instructions](https://github.com/thi-ng/umbrella/wiki/Example-build-instructions) on the wiki. + +## Authors + +- Karsten Schmidt + +## License + +© 2019 Karsten Schmidt // Apache Software License 2.0 diff --git a/examples/shader-ast-sdf2d/assets/tex.jpg b/examples/shader-ast-sdf2d/assets/tex.jpg new file mode 100644 index 0000000000..d9ee61d1c0 Binary files /dev/null and b/examples/shader-ast-sdf2d/assets/tex.jpg differ diff --git a/examples/shader-ast-sdf2d/index.html b/examples/shader-ast-sdf2d/index.html new file mode 100644 index 0000000000..bf6558aac0 --- /dev/null +++ b/examples/shader-ast-sdf2d/index.html @@ -0,0 +1,37 @@ + + + + + + + shader-ast-sdf2 + + + + +
+
+

+ Shader generated with + thi.ng/shader-ast.
(see console for generated sources) +

+

+ Append #2d to URL, then + reload to view canvas 2D version +

+

+ Source code +

+
+ + + diff --git a/examples/webgl/package.json b/examples/shader-ast-sdf2d/package.json similarity index 66% rename from examples/webgl/package.json rename to examples/shader-ast-sdf2d/package.json index 5f0da6216c..0ec2eff6fb 100644 --- a/examples/webgl/package.json +++ b/examples/shader-ast-sdf2d/package.json @@ -1,12 +1,12 @@ { - "name": "webgl", + "name": "shader-ast-sdf2", "version": "0.0.1", "repository": "https://github.com/thi-ng/umbrella", "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { "clean": "rm -rf .cache build out", - "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --experimental-scope-hoisting --detailed-report --public-url ./", + "build": "yarn clean && parcel build index.html -d out --public-url ./ --no-source-maps --no-cache --detailed-report", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { @@ -15,9 +15,11 @@ "typescript": "^3.4.1" }, "dependencies": { - "@thi.ng/hdom": "latest", - "@thi.ng/hdom-components": "latest", - "@thi.ng/transducers": "latest" + "@thi.ng/shader-ast": "latest", + "@thi.ng/shader-ast-glsl": "latest", + "@thi.ng/shader-ast-js": "latest", + "@thi.ng/shader-ast-stdlib": "latest", + "@thi.ng/webgl": "latest" }, "browserslist": [ "last 3 Chrome versions" @@ -25,4 +27,4 @@ "browser": { "process": false } -} +} \ No newline at end of file diff --git a/examples/shader-ast-sdf2d/src/index.ts b/examples/shader-ast-sdf2d/src/index.ts new file mode 100644 index 0000000000..c6b799a674 --- /dev/null +++ b/examples/shader-ast-sdf2d/src/index.ts @@ -0,0 +1,164 @@ +import { + $xy, + assign, + cos, + defMain, + defn, + float, + FloatSym, + min, + mul, + program, + ret, + sym, + vec2, + Vec2Sym, + vec3, + vec4 +} from "@thi.ng/shader-ast"; +import { GLSLVersion, targetGLSL } from "@thi.ng/shader-ast-glsl"; +import { initRuntime, targetJS } from "@thi.ng/shader-ast-js"; +import { + aspectCorrectedUV, + fit1101, + sdfBox2, + sdfSmoothUnion, + sdfTriangle2 +} from "@thi.ng/shader-ast-stdlib"; +import { + compileModel, + draw, + quad, + shader +} from "@thi.ng/webgl"; + +// set URL hash to "#2d" to enable JS Canvas2D version +const JS_MODE = location.hash.indexOf("2d") >= 0; + +// AST compile targets +const GL = targetGLSL({ version: GLSLVersion.GLES_100 }); // WebGL +const JS = targetJS(); + +// scene definition for raymarch function. uses SDF primitive functions +// included in "standard library" bundled with shader-ast pkg +const scene = defn("float", "scene", [["vec2"]], (pos) => { + let d1: FloatSym; + let d2: FloatSym; + let d3: FloatSym; + return [ + // assign(pos, sdTxRepeat2(pos, vec2(2))), + (d1 = sym( + sdfTriangle2(pos, vec2(1, 0.7), vec2(0, -1.3), vec2(-1, 0.7)) + )), + assign( + d1, + min( + d1, + sdfTriangle2(pos, vec2(1, -0.7), vec2(0, 1.3), vec2(-1, -0.7)) + ) + ), + (d2 = sym(sdfBox2(pos, vec2(1.5, 0.2)))), + (d3 = sym(sdfBox2(pos, vec2(0.2, 1.5)))), + assign( + d1, + sdfSmoothUnion(sdfSmoothUnion(d3, d2, float(0.5)), d1, float(0.5)) + ), + ret(d1) + ]; +}); + +// main fragment shader function +// again uses several shader-ast std lib helpers +const mainImage = defn( + "vec4", + "mainImage", + [["vec2", "fragCoord"], ["vec2", "res"]], + (frag, res) => { + let uv: Vec2Sym; + let d: FloatSym; + let f = 100; + return [ + (uv = sym(mul(aspectCorrectedUV(frag, res), float(2)))), + (d = sym(scene(uv))), + ret( + vec4( + vec3( + fit1101(cos(mul(d, float(f)))), + fit1101(cos(mul(d, float(f * 1.02)))), + fit1101(cos(mul(d, float(f * 1.05)))) + ), + 1 + ) + ) + ]; + } +); + +// build call graph for given entry function, sort in topological order +// and bundle all functions in a global scope for code generation... +const shaderProgram = program([mainImage]); + +console.log("JS"); +console.log(JS(shaderProgram)); +console.log("GLSL"); +console.log(GL(shaderProgram)); + +const W = 640; +const H = 640; +const size = [W, H]; +const canvas = document.createElement("canvas"); +canvas.width = W; +canvas.height = H; +document.body.appendChild(canvas); +const info = document.createElement("div"); +info.innerText = (JS_MODE ? "Canvas2D" : "WebGL2") + " version"; +document.body.appendChild(info); + +if (JS_MODE) { + // + // JS Canvas 2D shader emulation from here... + // + const fn = JS.compile(shaderProgram).mainImage; + const rt = initRuntime({ canvas }); + + setInterval(() => { + rt.update((frag) => fn(frag, size)); + }, 16); +} else { + // + // WebGL mode... + // + const ctx: WebGLRenderingContext = canvas.getContext("webgl")!; + // build fullscreen quad + const model = quad(false); + // set shader + model.shader = shader(ctx, { + vs: (gl, _, attribs) => [ + defMain(() => [ + assign(gl.gl_Position, vec4(attribs.position, 0, 1)) + ]) + ], + fs: (gl, unis, _, outs) => [ + mainImage, + defMain(() => [ + assign( + outs.fragColor, + mainImage($xy(gl.gl_FragCoord), unis.resolution) + ) + ]) + ], + attribs: { + position: "vec2" + }, + uniforms: { + resolution: ["vec2", [W, H]] + } + }); + // compile model (attrib buffers) + compileModel(ctx, model); + + // render loop + setInterval(() => { + draw(model); + }); +} diff --git a/examples/shader-ast-sdf2d/tsconfig.json b/examples/shader-ast-sdf2d/tsconfig.json new file mode 100644 index 0000000000..bbf112cc18 --- /dev/null +++ b/examples/shader-ast-sdf2d/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": ".", + "target": "es6", + "sourceMap": true + }, + "include": [ + "./src/**/*.ts" + ] +} diff --git a/examples/shader-ast-tunnel/.gitignore b/examples/shader-ast-tunnel/.gitignore new file mode 100644 index 0000000000..0c5abcab62 --- /dev/null +++ b/examples/shader-ast-tunnel/.gitignore @@ -0,0 +1,5 @@ +.cache +out +node_modules +yarn.lock +*.js diff --git a/examples/shader-ast-tunnel/README.md b/examples/shader-ast-tunnel/README.md new file mode 100644 index 0000000000..ea9a48da52 --- /dev/null +++ b/examples/shader-ast-tunnel/README.md @@ -0,0 +1,22 @@ +# shader-ast-tunnel + +- [Live demo (WebGL)](http://demo.thi.ng/umbrella/shader-ast-tunnel/) +- [Live demo (Canvas 2D)](http://demo.thi.ng/umbrella/shader-ast-tunnel/#2d) + +One of [Inigo Quilez' (IQ) Shadertoy tunnel +shaders](https://www.shadertoy.com/view/Ms2SWW) ported to +[@thi.ng/shader-ast](https://github.com/thi-ng/umbrella/tree/master/packages/shader-ast) +and cross-compiled to GLSL and JavaScript, the latter for emulating the +shader (incl. texture lookups) via +[@thi.ng/vectors](https://github.com/thi-ng/umbrella/tree/master/packages/vectors) +and Canvas 2D API. + +Please refer to the [example build instructions](https://github.com/thi-ng/umbrella/wiki/Example-build-instructions) on the wiki. + +## Authors + +- Karsten Schmidt + +## License + +© 2019 Karsten Schmidt // Apache Software License 2.0 diff --git a/examples/shader-ast-tunnel/assets/tex.jpg b/examples/shader-ast-tunnel/assets/tex.jpg new file mode 100644 index 0000000000..d9ee61d1c0 Binary files /dev/null and b/examples/shader-ast-tunnel/assets/tex.jpg differ diff --git a/examples/shader-ast-tunnel/index.html b/examples/shader-ast-tunnel/index.html new file mode 100644 index 0000000000..c0b8c1f0e7 --- /dev/null +++ b/examples/shader-ast-tunnel/index.html @@ -0,0 +1,37 @@ + + + + + + + shader-ast-tunnel + + + + +
+
+

+ Shader generated with + thi.ng/shader-ast.
(see console for generated sources) +

+

+ Append #2d to URL, then + reload to view canvas 2D version +

+

+ Source code +

+
+ + + diff --git a/examples/shader-ast-tunnel/package.json b/examples/shader-ast-tunnel/package.json new file mode 100644 index 0000000000..596518ba93 --- /dev/null +++ b/examples/shader-ast-tunnel/package.json @@ -0,0 +1,32 @@ +{ + "name": "shader-ast-tunnel", + "version": "0.0.1", + "repository": "https://github.com/thi-ng/umbrella", + "author": "Karsten Schmidt ", + "license": "Apache-2.0", + "scripts": { + "clean": "rm -rf .cache build out", + "build": "yarn clean && parcel build index.html -d out --public-url ./ --no-source-maps --no-cache --detailed-report", + "start": "parcel index.html -p 8080 --open" + }, + "devDependencies": { + "parcel-bundler": "^1.12.3", + "terser": "^3.17.0", + "typescript": "^3.4.1" + }, + "dependencies": { + "@thi.ng/binary": "latest", + "@thi.ng/color": "latest", + "@thi.ng/shader-ast": "latest", + "@thi.ng/shader-ast-glsl": "latest", + "@thi.ng/shader-ast-js": "latest", + "@thi.ng/shader-ast-stdlib": "latest", + "@thi.ng/webgl": "latest" + }, + "browserslist": [ + "last 3 Chrome versions" + ], + "browser": { + "process": false + } +} \ No newline at end of file diff --git a/examples/shader-ast-tunnel/src/index.ts b/examples/shader-ast-tunnel/src/index.ts new file mode 100644 index 0000000000..89e68f38c0 --- /dev/null +++ b/examples/shader-ast-tunnel/src/index.ts @@ -0,0 +1,196 @@ +import { swizzle8 } from "@thi.ng/binary"; +import { int32Rgba } from "@thi.ng/color"; +import { + $x, + $xy, + $xyz, + $y, + add, + assign, + atan, + defMain, + defn, + div, + float, + FloatSym, + mul, + neg, + pow, + program, + ret, + sym, + texture, + vec2, + Vec2Sym, + vec4 +} from "@thi.ng/shader-ast"; +import { GLSLVersion, targetGLSL } from "@thi.ng/shader-ast-glsl"; +import { initRuntime, JS_DEFAULT_ENV, targetJS } from "@thi.ng/shader-ast-js"; +import { + compileModel, + draw, + quad, + shader, + texture as glTexture +} from "@thi.ng/webgl"; +import TEX_URL from "../assets/tex.jpg"; + +// set URL hash to "#2d" to enable JS Canvas2D version +const JS_MODE = location.hash.indexOf("2d") >= 0; + +// AST compile targets +const GL = targetGLSL({ version: GLSLVersion.GLES_100 }); // WebGL +const JS = targetJS(); + +// https://www.shadertoy.com/view/Ms2SWW (by iq) +const mainImage = defn( + "vec4", + "mainImage", + [ + ["vec2", "fragCoord"], + ["vec2", "res"], + ["float", "time"], + ["sampler2D", "tex"] + ], + (frag, res, time, tex) => { + let p: Vec2Sym; + let uv: Vec2Sym; + let r: FloatSym; + return [ + (p = sym(div(add(neg(res), mul(frag, float(2))), $y(res)))), + (r = sym( + pow( + add( + pow(mul($x(p), $x(p)), float(4)), + pow(mul($y(p), $y(p)), float(4)) + ), + float(1 / 8) + ) + )), + (uv = sym( + vec2( + add(div(float(0.3), r), time), + div(atan(div($y(p), $x(p))), float(Math.PI)) + ) + )), + ret(vec4(mul($xyz(texture(tex, uv)), r), float(1))) + ]; + } +); + +// assemble all functions in a global scope for code generation... +const shaderProgram = program([mainImage]); + +console.log("JS"); +console.log(JS(shaderProgram)); +console.log("GLSL"); +console.log(GL(shaderProgram)); + +const W = 320; +const H = 240; +const size = [W, H]; +const canvas = document.createElement("canvas"); +canvas.width = W; +canvas.height = H; +document.body.appendChild(canvas); +const info = document.createElement("div"); +info.innerText = (JS_MODE ? "Canvas2D" : "WebGL") + " version"; +document.body.appendChild(info); + +const tex = new Image(); + +// preload texture +const preload = (async () => { + tex.src = TEX_URL; + await tex.decode(); +})(); + +if (JS_MODE) { + // + // JS Canvas 2D shader emulation from here... + // + preload.then(() => { + const texCanv = document.createElement("canvas"); + const TW = (texCanv.width = tex.width); + const TH = (texCanv.height = tex.height); + const texCtx = texCanv.getContext("2d")!; + texCtx.drawImage(tex, 0, 0); + const texData = new Uint32Array( + texCtx!.getImageData(0, 0, TW, TH).data.buffer + ); + + // since texture sampling is not (yet) supported for the JS + // codegen target, we're patching in a simple wrap-around 2D + // lookup ourselves... + JS_DEFAULT_ENV.sampler2D.texture = (_, uv) => { + let x = ((uv[0] * TW) | 0) % TW; + let y = ((uv[1] * TH) | 0) % TH; + x < 0 && (x += TW); + y < 0 && (y += TH); + return int32Rgba([], swizzle8(texData[y * TW + x], 0, 3, 2, 1)); + }; + + // compile AST to actual JS: + // under the hood all vector & matrix operations delegate to + // thi.ng/vectors and thi.ng/matrices packages by default + const fn = JS.compile(shaderProgram).mainImage; + const rt = initRuntime({ canvas }); + let time = 0; + + setInterval(() => { + time += 0.05; + rt.update((frag) => fn(frag, size, time)); + }, 16); + }); +} else { + // + // WebGL mode... + // + preload.then(() => { + const ctx: WebGLRenderingContext = canvas.getContext("webgl")!; + // build fullscreen quad + const model = quad(false); + // set shader + model.shader = shader(ctx, { + vs: (gl, _, attribs) => [ + defMain(() => [ + assign(gl.gl_Position, vec4(attribs.position, 0, 1)) + ]) + ], + fs: (gl, unis, _, outs) => [ + mainImage, + defMain(() => [ + assign( + outs.fragColor, + mainImage( + $xy(gl.gl_FragCoord), + unis.resolution, + unis.time, + unis.tex + ) + ) + ]) + ], + attribs: { + position: "vec2" + }, + uniforms: { + resolution: ["vec2", [W, H]], + time: "float", + tex: ["sampler2D", 0] + } + }); + model.textures = [glTexture(ctx, { image: tex, filter: ctx.LINEAR })]; + + // compile model (attrib buffers) + compileModel(ctx, model); + + const t0 = Date.now(); + // render loop + setInterval(() => { + const time = (Date.now() - t0) * 0.001; + model.uniforms!.time = time; + draw(model); + }); + }); +} diff --git a/examples/shader-ast-tunnel/tsconfig.json b/examples/shader-ast-tunnel/tsconfig.json new file mode 100644 index 0000000000..bbf112cc18 --- /dev/null +++ b/examples/shader-ast-tunnel/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": ".", + "target": "es6", + "sourceMap": true + }, + "include": [ + "./src/**/*.ts" + ] +} diff --git a/examples/svg-barchart/package.json b/examples/svg-barchart/package.json index 0060210bec..78183d7c39 100644 --- a/examples/svg-barchart/package.json +++ b/examples/svg-barchart/package.json @@ -11,8 +11,8 @@ }, "devDependencies": { "parcel-bundler": "^1.12.3", - "terser": "^3.17.0", - "typescript": "^3.4.1" + "terser": "^4.0.0", + "typescript": "^3.5.2" }, "dependencies": { "@thi.ng/hdom": "latest", @@ -24,4 +24,4 @@ "browser": { "process": false } -} +} \ No newline at end of file diff --git a/examples/svg-barchart/src/index.ts b/examples/svg-barchart/src/index.ts index f167622c22..53e192ca6a 100644 --- a/examples/svg-barchart/src/index.ts +++ b/examples/svg-barchart/src/index.ts @@ -1,30 +1,43 @@ import { clearDOM, renderOnce } from "@thi.ng/hdom"; -import { range, map, mapcat } from "@thi.ng/transducers"; - -// fit `x` from range (a,b) => (c,d) -const fit = (x, a, b, c, d) => ((x - a) / (b - a)) * (d - c) + c; +import { fit } from "@thi.ng/math"; +import { map, mapcat, range } from "@thi.ng/transducers"; // iterator of range mapped tuples: `[mapped, orig]` -const mappedRange = (from, to, step, start, end) => - map((n) => [fit(n, from, to, start, end), n], range(from, to, step)); +const mappedRange = ( + from: number, + to: number, + step: number, + start: number, + end: number +) => map((n) => [fit(n, from, to, start, end), n], range(from, to, step)); // syntax sugar to create SVG line -const line = (x1, y1, x2, y2) => ["line", { x1, y1, x2, y2 }]; +const line = (x1: number, y1: number, x2: number, y2: number) => [ + "line", + { x1, y1, x2, y2 } +]; // reusuable axis tick & label combo -const tick = (x1, y1, x2, y2, tx, ty, label) => [ - line(x1, y1, x2, y2), - ["text", { x: tx, y: ty, stroke: "none" }, label] -]; +const tick = ( + x1: number, + y1: number, + x2: number, + y2: number, + tx: number, + ty: number, + label: string +) => [line(x1, y1, x2, y2), ["text", { x: tx, y: ty, stroke: "none" }, label]]; // mapping fn for x-axis ticks -const tickX = (y) => ([x, n]) => tick(x, y, x, y + 10, x, y + 20, n); +const tickX = (y: number) => ([x, n]: any) => + tick(x, y, x, y + 10, x, y + 20, n); // mapping fn for y-axis ticks -const tickY = (x) => ([y, n]) => tick(x - 10, y, x, y, x - 15, y, n); +const tickY = (x: number) => ([y, n]: any) => + tick(x - 10, y, x, y, x - 15, y, n); // x-axis with ticks as SVG group -const axisX = ({ axis: a, domain: d, range: r }) => [ +const axisX = ({ axis: a, domain: d, range: r }: any) => [ "g", { "text-anchor": "middle" }, line(a[0], a[2], a[1], a[2]), @@ -32,7 +45,7 @@ const axisX = ({ axis: a, domain: d, range: r }) => [ ]; // y-axis with ticks as SVG group -const axisY = ({ axis: a, domain: d, range: r }) => [ +const axisY = ({ axis: a, domain: d, range: r }: any) => [ "g", { "text-anchor": "end" }, line(a[2], a[0], a[2], a[1]), @@ -40,10 +53,10 @@ const axisY = ({ axis: a, domain: d, range: r }) => [ ]; // mapping fn to create a single bar from `[domainPos, value]` -const bar = ({ domain: xd, range: xr }, { domain: yd, range: yr }) => ([ - xx, - yy -]) => { +const bar = ( + { domain: xd, range: xr }: any, + { domain: yd, range: yr }: any +) => ([xx, yy]: number[]) => { const y = fit(yy, yd[0], yd[1], yr[0], yr[1]); return [ "rect", @@ -57,7 +70,7 @@ const bar = ({ domain: xd, range: xr }, { domain: yd, range: yr }) => ([ }; // complete bar chart component -const barChart = (_, opts, values) => [ +const barChart = (_: any, opts: any, values: any) => [ "svg", opts.attribs, ["g", { stroke: opts.axis, fill: opts.axis }, axisX(opts.x), axisY(opts.y)], @@ -96,5 +109,5 @@ renderOnce([ if (process.env.NODE_ENV !== "production") { const hot = (module).hot; - hot && hot.dispose(() => clearDOM(document.getElementById("app"))); + hot && hot.dispose(() => clearDOM(document.getElementById("app")!)); } diff --git a/examples/svg-particles/package.json b/examples/svg-particles/package.json index 307edd8f29..68bd0c9769 100644 --- a/examples/svg-particles/package.json +++ b/examples/svg-particles/package.json @@ -11,8 +11,8 @@ }, "devDependencies": { "parcel-bundler": "^1.12.3", - "terser": "^3.17.0", - "typescript": "^3.4.1" + "terser": "^4.0.0", + "typescript": "^3.5.2" }, "dependencies": { "@thi.ng/hdom": "latest", @@ -25,4 +25,4 @@ "browser": { "process": false } -} +} \ No newline at end of file diff --git a/examples/svg-particles/src/index.ts b/examples/svg-particles/src/index.ts index 766851c610..a358e4c9d6 100644 --- a/examples/svg-particles/src/index.ts +++ b/examples/svg-particles/src/index.ts @@ -6,7 +6,7 @@ const width = window.innerWidth; const height = window.innerHeight; const hex6 = radix(16, 6); -const updateParticle = (p, v) => { +const updateParticle = (p: any, v: number[]) => { let x = p.cx + v[0]; let y = p.cy + v[1]; x < 0 && ((x *= -1), (v[0] *= -1)); @@ -17,7 +17,7 @@ const updateParticle = (p, v) => { p.cy = y | 0; }; -const rand = (a, b) => +const rand = (a: number, b: number) => (a + (b - a) * Math.random()) * (Math.random() < 0.5 ? 1 : -1); const randomParticle = () => { @@ -33,7 +33,7 @@ const randomParticle = () => { ]; }; -const velocities = [null]; +const velocities: any[] = [null]; const particles: any[] = ["g", ...repeatedly(randomParticle, 100)]; const app = () => { diff --git a/examples/svg-waveform/package.json b/examples/svg-waveform/package.json index ca332fb415..a4ae409e51 100644 --- a/examples/svg-waveform/package.json +++ b/examples/svg-waveform/package.json @@ -22,8 +22,8 @@ "devDependencies": { "@types/node": "^9.6.2", "parcel-bundler": "^1.12.3", - "terser": "^3.17.0", - "typescript": "^3.4.1" + "terser": "^4.0.0", + "typescript": "^3.5.2" }, "browserslist": [ "last 3 Chrome versions" @@ -31,4 +31,4 @@ "browser": { "process": false } -} +} \ No newline at end of file diff --git a/examples/svg-waveform/src/app.ts b/examples/svg-waveform/src/app.ts index 1e7d5d35de..e2c173fc96 100644 --- a/examples/svg-waveform/src/app.ts +++ b/examples/svg-waveform/src/app.ts @@ -3,7 +3,12 @@ import { Atom, History } from "@thi.ng/atom"; import { isArray } from "@thi.ng/checks"; import { start } from "@thi.ng/hdom"; import { EventBus } from "@thi.ng/interceptors"; -import { AppConfig, AppContext, AppViews, ViewSpec } from "./api"; +import { + AppConfig, + AppContext, + AppViews, + ViewSpec +} from "./api"; import * as ev from "./events"; /** @@ -32,7 +37,7 @@ export class App { views: {}, ui: config.ui }; - this.addViews(this.config.views); + this.addViews(this.config.views); } /** @@ -46,9 +51,9 @@ export class App { for (let id in specs) { const spec = specs[id]; if (isArray(spec)) { - views[id] = this.state.addView(spec[0], spec[1]); + (views)[id] = this.state.addView(spec[0], spec[1]); } else { - views[id] = this.state.addView(spec); + (views)[id] = this.state.addView(spec); } } } diff --git a/examples/svg-waveform/src/components/button-group.ts b/examples/svg-waveform/src/components/button-group.ts index 0c13cef0a3..dd70af2090 100644 --- a/examples/svg-waveform/src/components/button-group.ts +++ b/examples/svg-waveform/src/components/button-group.ts @@ -1,7 +1,7 @@ import { AppContext } from "../api"; import { button } from "./button"; -export function buttonGroup(ctx: AppContext, ...buttons) { +export function buttonGroup(ctx: AppContext, ...buttons: any[]) { return [ "section", ctx.ui.buttongroup, diff --git a/examples/svg-waveform/src/components/event-link.ts b/examples/svg-waveform/src/components/event-link.ts index ad2a2a35b9..be4758aae2 100644 --- a/examples/svg-waveform/src/components/event-link.ts +++ b/examples/svg-waveform/src/components/event-link.ts @@ -1,7 +1,7 @@ import { Event } from "@thi.ng/interceptors"; - import { AppContext } from "../api"; + /** * Customizable hyperlink component emitting given event on event bus * when clicked. @@ -21,7 +21,7 @@ export function eventLink( "a", { ...attribs, - onclick: (e) => { + onclick: (e: any) => { e.preventDefault(); ctx.bus.dispatch(event); } diff --git a/examples/svg-waveform/src/components/link.ts b/examples/svg-waveform/src/components/link.ts index 4718784714..46509d1401 100644 --- a/examples/svg-waveform/src/components/link.ts +++ b/examples/svg-waveform/src/components/link.ts @@ -1,5 +1,5 @@ import { AppContext } from "../api"; -export function link(ctx: AppContext, href, ...body) { +export function link(ctx: AppContext, href: string, ...body: any[]) { return ["a", { ...ctx.ui.link, href }, ...body]; } diff --git a/examples/svg-waveform/src/components/main.ts b/examples/svg-waveform/src/components/main.ts index dafe17f31b..9740a075e3 100644 --- a/examples/svg-waveform/src/components/main.ts +++ b/examples/svg-waveform/src/components/main.ts @@ -1,9 +1,9 @@ import { AppContext } from "../api"; import { SLIDERS } from "../sliders"; - import { sidebar } from "./sidebar"; import { waveform } from "./waveform"; + export function main(ctx: AppContext) { const bar = sidebar(ctx, ...SLIDERS); return () => [ @@ -11,11 +11,11 @@ export function main(ctx: AppContext) { ctx.ui.root, bar, waveform(ctx, { - phase: ctx.views.phase.deref(), - freq: ctx.views.freq.deref(), - amp: ctx.views.amp.deref(), - harmonics: ctx.views.harmonics.deref(), - hstep: ctx.views.hstep.deref(), + phase: ctx.views.phase.deref()!, + freq: ctx.views.freq.deref()!, + amp: ctx.views.amp.deref()!, + harmonics: ctx.views.harmonics.deref()!, + hstep: ctx.views.hstep.deref()!, res: 1000, stroke: "#f04", fill1: "#f04", diff --git a/examples/svg-waveform/src/components/slider.ts b/examples/svg-waveform/src/components/slider.ts index c9540f6b2c..64b22c0e66 100644 --- a/examples/svg-waveform/src/components/slider.ts +++ b/examples/svg-waveform/src/components/slider.ts @@ -26,8 +26,11 @@ export interface SliderOpts { export function slider(ctx: AppContext, opts: SliderOpts) { opts = Object.assign( { - oninput: (e) => - ctx.bus.dispatch([opts.event, parseFloat(e.target.value)]), + oninput: (e: Event) => + ctx.bus.dispatch([ + opts.event, + parseFloat((e.target).value) + ]), min: 0, max: 100, step: 1 @@ -43,7 +46,7 @@ export function slider(ctx: AppContext, opts: SliderOpts) { ...ctx.ui.slider.range, ...opts, type: "range", - value: ctx.views[opts.view].deref() + value: (ctx.views)[opts.view].deref() } ], [ @@ -55,7 +58,7 @@ export function slider(ctx: AppContext, opts: SliderOpts) { ...ctx.ui.slider.number, ...opts, type: "number", - value: ctx.views[opts.view].deref() + value: (ctx.views)[opts.view].deref() } ] ] diff --git a/examples/svg-waveform/src/config.ts b/examples/svg-waveform/src/config.ts index 77a00f4061..655de9d5d8 100644 --- a/examples/svg-waveform/src/config.ts +++ b/examples/svg-waveform/src/config.ts @@ -1,11 +1,11 @@ import { ensureParamRange, snapshot, valueSetter } from "@thi.ng/interceptors"; import { AppConfig } from "./api"; +import { main } from "./components/main"; +import { SLIDERS } from "./sliders"; // import * as ev from "./events"; // import * as fx from "./effects"; -import { main } from "./components/main"; -import { SLIDERS } from "./sliders"; // main App configuration export const CONFIG: AppConfig = { @@ -30,7 +30,7 @@ export const CONFIG: AppConfig = { // 3) update param in app state // the last 2 steps are only be executed if validation succeeded // else the event is canceled - ...SLIDERS.reduce((events, spec) => { + ...SLIDERS.reduce((events: any, spec) => { events[spec.event] = [ ensureParamRange(spec.min, spec.max), snapshot(), diff --git a/examples/svg-waveform/src/index.ts b/examples/svg-waveform/src/index.ts index 408b3861c3..d72f64a3bc 100644 --- a/examples/svg-waveform/src/index.ts +++ b/examples/svg-waveform/src/index.ts @@ -4,7 +4,7 @@ import { CONFIG } from "./config"; // export app to global var in dev mode // (for interaction via browser dev tools) if (process.env.NODE_ENV == "development") { - (window["APP"] = new App(CONFIG)).start(); + ((window)["APP"] = new App(CONFIG)).start(); } else { new App(CONFIG).start(); } diff --git a/examples/talk-slides/package.json b/examples/talk-slides/package.json index 9ebb38c67c..cb9a613400 100644 --- a/examples/talk-slides/package.json +++ b/examples/talk-slides/package.json @@ -11,8 +11,8 @@ }, "devDependencies": { "parcel-bundler": "^1.12.3", - "terser": "^3.17.0", - "typescript": "^3.4.1" + "terser": "^4.0.0", + "typescript": "^3.5.2" }, "dependencies": { "@thi.ng/hdom": "latest", @@ -28,4 +28,4 @@ "browser": { "process": false } -} +} \ No newline at end of file diff --git a/examples/talk-slides/src/components.ts b/examples/talk-slides/src/components.ts index 71c857d060..55b6e87491 100644 --- a/examples/talk-slides/src/components.ts +++ b/examples/talk-slides/src/components.ts @@ -1,16 +1,16 @@ -export const link = (ctx, href, body?) => [ +export const link = (ctx: any, href: string, body?: any) => [ "a", { ...ctx.link, href }, body || href ]; -export const twitterLink = (_, username) => [ +export const twitterLink = (_: any, username: string) => [ link, `https://twitter.com/${username}`, "@" + username ]; -export const navButton = (ctx, step) => [ +export const navButton = (ctx: any, step: number) => [ "a", { ...ctx.navButton[step < 0 ? "prev" : "next"], @@ -19,17 +19,30 @@ export const navButton = (ctx, step) => [ step < 0 ? "<" : ">" ]; -export const footer = (ctx, ...body) => ["footer", ctx.footer, ...body]; +export const footer = (ctx: any, ...body: any[]) => [ + "footer", + ctx.footer, + ...body +]; -export const codeBlock = (ctx, body) => ["pre", ctx.code, body.trim()]; +export const codeBlock = (ctx: any, body: string) => [ + "pre", + ctx.code, + body.trim() +]; -export const list = (ctx, ...items) => [ +export const list = (ctx: any, ...items: any[]) => [ "ul", ctx.list, ...items.map((i) => ["li", i]) ]; -export const titlePage = (ctx, clazz, title, ...body) => [ +export const titlePage = ( + ctx: any, + clazz: string, + title: string, + ...body: any[] +) => [ "div", { ...ctx.titlePage.root, @@ -46,21 +59,26 @@ export const titlePage = (ctx, clazz, title, ...body) => [ ] ]; -export const contentPage = (ctx, title, ...body) => [ +export const contentPage = (ctx: any, title: string, ...body: any[]) => [ "div", ctx.contentPage.root, ["h2", ctx.contentPage.title, title], ["div", ctx.contentPage.body, ...body] ]; -export const quotePage = (ctx, quote, author) => [ +export const quotePage = (ctx: any, quote: any[], author: string) => [ "div", ctx.quotePage.root, ["div", ctx.quotePage.quote, ...quote.map((x) => ["div", x])], ["div", ctx.quotePage.author, `— ${author}`] ]; -export const bgImagePage = (ctx, clazz, src, ...extra) => [ +export const bgImagePage = ( + ctx: any, + clazz: string, + src: string, + ...extra: any[] +) => [ "div", { class: `${ctx.bgImagePage.class} ${clazz}`, @@ -73,13 +91,13 @@ export const bgImagePage = (ctx, clazz, src, ...extra) => [ ...extra ]; -export const imagePage = (ctx, clazz, src) => [ +export const imagePage = (ctx: any, clazz: string, src: string) => [ "div", { ...ctx.imagePage.root, class: `${ctx.imagePage.root.class} ${clazz}` }, ["div.w-100", ["img", { ...ctx.imagePage.img, src }]] ]; -export const ytVideo = (ctx, id) => [ +export const ytVideo = (ctx: any, id: string) => [ "div", [ "iframe", @@ -94,7 +112,11 @@ export const ytVideo = (ctx, id) => [ [navButton, 1] ]; -export const app = (slideCount, ctx) => ({ slideID, content, time }) => [ +export const app = (slideCount: number, ctx: any) => ({ + slideID, + content, + time +}: any) => [ "div", ctx.app.root, content, @@ -106,7 +128,7 @@ export const app = (slideCount, ctx) => ({ slideID, content, time }) => [ ] ]; -export const printApp = (ctx, slides) => [ +export const printApp = (ctx: any, slides: any[]) => [ "div", ...slides.map((content) => ["div.slide", ctx.app.root, content]) ]; diff --git a/examples/talk-slides/src/config.ts b/examples/talk-slides/src/config.ts index 2256699d08..85cf93ba8b 100644 --- a/examples/talk-slides/src/config.ts +++ b/examples/talk-slides/src/config.ts @@ -1,4 +1,4 @@ -export const ctx = { +export const ctx: any = { // place holder for slide number stream slide: null, diff --git a/examples/talk-slides/src/index.ts b/examples/talk-slides/src/index.ts index 1c2e4b49ce..a777525320 100644 --- a/examples/talk-slides/src/index.ts +++ b/examples/talk-slides/src/index.ts @@ -1,8 +1,20 @@ import { renderOnce } from "@thi.ng/hdom"; import { clamp } from "@thi.ng/math"; -import { fromEvent, fromInterval, stream, sync } from "@thi.ng/rstream"; +import { + fromDOMEvent, + fromInterval, + stream, + Stream, + sync +} from "@thi.ng/rstream"; import { padLeft } from "@thi.ng/strings"; -import { dedupe, map, reducer, scan, sideEffect } from "@thi.ng/transducers"; +import { + dedupe, + map, + reducer, + scan, + sideEffect +} from "@thi.ng/transducers"; import { updateDOM } from "@thi.ng/transducers-hdom"; import { app, printApp } from "./components"; import { ctx } from "./config"; @@ -12,8 +24,8 @@ const INTERACTIVE = true; const D2 = padLeft(2, "0"); -const initKeys = (stream) => - fromEvent(window, "keydown").transform( +const initKeys = (stream: Stream) => + fromDOMEvent(window, "keydown").transform( map((e: KeyboardEvent) => { // console.log(e.code); switch (e.code) { @@ -37,13 +49,13 @@ const parseSlideID = (str: string) => { }; const slideCTRL = (ctx.slide = stream()); -const slideID = slideCTRL.transform( +const slideID = slideCTRL.transform( scan(reducer(() => 0, (x, y) => clamp(x + y, 0, SLIDES.length - 1))), dedupe(), sideEffect((id) => (location.hash = "#" + id)) ); -const main = sync({ +const main = sync({ src: { slideID, content: slideID.transform(map((id: number) => SLIDES[id])), diff --git a/examples/todo-list/package.json b/examples/todo-list/package.json index 55f9f7ddb4..83a8cf5997 100644 --- a/examples/todo-list/package.json +++ b/examples/todo-list/package.json @@ -11,8 +11,8 @@ }, "devDependencies": { "parcel-bundler": "^1.12.3", - "terser": "^3.17.0", - "typescript": "^3.4.1" + "terser": "^4.0.0", + "typescript": "^3.5.2" }, "dependencies": { "@thi.ng/api": "latest", @@ -27,4 +27,4 @@ "browser": { "process": false } -} +} \ No newline at end of file diff --git a/examples/todo-list/src/index.ts b/examples/todo-list/src/index.ts index 8bd0a6f06d..e37c2aeedf 100644 --- a/examples/todo-list/src/index.ts +++ b/examples/todo-list/src/index.ts @@ -27,13 +27,13 @@ const addNewTask = () => tasks.swap((tasks) => setIn(tasks, nextID.swap((id) => id + 1), { body: "", done: false }) ); -const toggleTask = (id) => +const toggleTask = (id: string) => tasks.swap((tasks) => updateIn(tasks, [id, "done"], (done) => !done)); -const updateTask = (id, body) => +const updateTask = (id: string, body: string) => tasks.swap((tasks) => setIn(tasks, [id, "body"], body)); // single task component -const taskItem = (id, task: Task) => { +const taskItem = (id: string, task: Task) => { const checkAttribs = { type: "checkbox", checked: task.done, @@ -43,8 +43,8 @@ const taskItem = (id, task: Task) => { type: "text", placeholder: "todo...", value: task.body, - onkeydown: (e) => e.key === "Enter" && e.target.blur(), - onblur: (e) => updateTask(id, (e.target).value) + onkeydown: (e: any) => e.key === "Enter" && e.target.blur(), + onblur: (e: any) => updateTask(id, (e.target).value) }; return [ "div", @@ -57,17 +57,16 @@ const taskItem = (id, task: Task) => { // complete task list // uses transducer to transform all tasks using above component function const taskList = () => { - const _items = items.deref(); + const _items = items.deref()!; return _items.length ? ["div#tasks", _items] : ["div", "nothing todo, get busy..."]; }; -const button = (onclick, body) => (_, disabled) => [ - "button", - { onclick, disabled }, - body -]; +const button = (onclick: EventListener, body: string) => ( + _: any, + disabled: boolean +) => ["button", { onclick, disabled }, body]; const toolbar = () => { const btAdd = button(() => addNewTask(), "+ Add"); diff --git a/examples/transducers-hdom/package.json b/examples/transducers-hdom/package.json index b64b780d05..fc1dfddf77 100644 --- a/examples/transducers-hdom/package.json +++ b/examples/transducers-hdom/package.json @@ -11,8 +11,8 @@ }, "devDependencies": { "parcel-bundler": "^1.12.3", - "terser": "^3.17.0", - "typescript": "^3.4.1" + "terser": "^4.0.0", + "typescript": "^3.5.2" }, "dependencies": { "@thi.ng/rstream": "latest", @@ -25,4 +25,4 @@ "browser": { "process": false } -} +} \ No newline at end of file diff --git a/examples/transducers-hdom/src/index.ts b/examples/transducers-hdom/src/index.ts index b3ee4ffe9b..cb896d3b9e 100644 --- a/examples/transducers-hdom/src/index.ts +++ b/examples/transducers-hdom/src/index.ts @@ -4,7 +4,7 @@ import { updateDOM } from "@thi.ng/transducers-hdom"; // root component function // (using Tachyons CSS classes for styling) -const app = ({ ticks, clicks }) => [ +const app = ({ ticks, clicks }: any) => [ "div.vh-100.dt.w-100.bg-dark-pink.sans-serif", [ "div.dtc.v-mid.tc.white.ph3.ph4-l", @@ -37,7 +37,7 @@ const clickStream = stream().transform(scan(count(-1))); // stream combinator // waits until all inputs have produced at least one value, // then updates whenever any input has changed -sync({ +sync({ // streams to synchronize src: { ticks: fromInterval(1000), diff --git a/examples/triple-query/package.json b/examples/triple-query/package.json index ed0e3f73ad..d5a148469f 100644 --- a/examples/triple-query/package.json +++ b/examples/triple-query/package.json @@ -11,8 +11,8 @@ }, "devDependencies": { "parcel-bundler": "^1.12.3", - "terser": "^3.17.0", - "typescript": "^3.4.1" + "terser": "^4.0.0", + "typescript": "^3.5.2" }, "dependencies": { "@thi.ng/api": "latest", @@ -31,4 +31,4 @@ "browser": { "process": false } -} +} \ No newline at end of file diff --git a/examples/triple-query/src/app.ts b/examples/triple-query/src/app.ts index 244c7fe638..4be371c812 100644 --- a/examples/triple-query/src/app.ts +++ b/examples/triple-query/src/app.ts @@ -4,7 +4,12 @@ import { isArray } from "@thi.ng/checks"; import { start } from "@thi.ng/hdom"; import { EV_SET_VALUE, EventBus } from "@thi.ng/interceptors"; import { TripleStore } from "@thi.ng/rstream-query"; -import { AppConfig, AppContext, AppViews, ViewSpec } from "./api"; +import { + AppConfig, + AppContext, + AppViews, + ViewSpec +} from "./api"; import * as ev from "./events"; /** @@ -32,7 +37,7 @@ export class App { views: {}, ui: config.ui }; - this.addViews(this.config.views); + this.addViews(this.config.views); } /** @@ -46,9 +51,9 @@ export class App { for (let id in specs) { const spec = specs[id]; if (isArray(spec)) { - views[id] = this.state.addView(spec[0], spec[1]); + (views)[id] = this.state.addView(spec[0], spec[1]); } else { - views[id] = this.state.addView(spec); + (views)[id] = this.state.addView(spec); } } } diff --git a/examples/triple-query/src/components/button-group.ts b/examples/triple-query/src/components/button-group.ts index 0c13cef0a3..dd70af2090 100644 --- a/examples/triple-query/src/components/button-group.ts +++ b/examples/triple-query/src/components/button-group.ts @@ -1,7 +1,7 @@ import { AppContext } from "../api"; import { button } from "./button"; -export function buttonGroup(ctx: AppContext, ...buttons) { +export function buttonGroup(ctx: AppContext, ...buttons: any[]) { return [ "section", ctx.ui.buttongroup, diff --git a/examples/triple-query/src/components/event-link.ts b/examples/triple-query/src/components/event-link.ts index ad2a2a35b9..be4758aae2 100644 --- a/examples/triple-query/src/components/event-link.ts +++ b/examples/triple-query/src/components/event-link.ts @@ -1,7 +1,7 @@ import { Event } from "@thi.ng/interceptors"; - import { AppContext } from "../api"; + /** * Customizable hyperlink component emitting given event on event bus * when clicked. @@ -21,7 +21,7 @@ export function eventLink( "a", { ...attribs, - onclick: (e) => { + onclick: (e: any) => { e.preventDefault(); ctx.bus.dispatch(event); } diff --git a/examples/triple-query/src/components/link.ts b/examples/triple-query/src/components/link.ts index 4718784714..46509d1401 100644 --- a/examples/triple-query/src/components/link.ts +++ b/examples/triple-query/src/components/link.ts @@ -1,5 +1,5 @@ import { AppContext } from "../api"; -export function link(ctx: AppContext, href, ...body) { +export function link(ctx: AppContext, href: string, ...body: any[]) { return ["a", { ...ctx.ui.link, href }, ...body]; } diff --git a/examples/triple-query/src/components/section.ts b/examples/triple-query/src/components/section.ts index e8ed8eb9c3..9289dd7818 100644 --- a/examples/triple-query/src/components/section.ts +++ b/examples/triple-query/src/components/section.ts @@ -2,8 +2,9 @@ import { title } from "@thi.ng/hdom-components"; const h1 = title({ subAttribs: { class: "moon-gray" } }); -export const section = (_, title, subtitle, ...body) => [ - "section", - [h1, title, subtitle], - ...body -]; +export const section = ( + _: any, + title: string, + subtitle: string, + ...body: any[] +) => ["section", [h1, title, subtitle], ...body]; diff --git a/examples/triple-query/src/components/triple-table.ts b/examples/triple-query/src/components/triple-table.ts index 3f26b7a369..d5a74e0727 100644 --- a/examples/triple-query/src/components/triple-table.ts +++ b/examples/triple-query/src/components/triple-table.ts @@ -1,5 +1,4 @@ import { pager } from "@thi.ng/hdom-components"; - import { AppContext } from "../api"; import { SET_PAGE, SET_SORT } from "../events"; import { PAGE_LEN } from "../handlers"; @@ -8,6 +7,7 @@ import { eventLink } from "./event-link"; import { section } from "./section"; import { table } from "./table"; + export const tripleTable = () => { const _pager = pager({ root: (ctx, ...body) => ["div", ctx.ui.pager.root, ...body], @@ -22,7 +22,7 @@ export const tripleTable = () => { groupPages: (ctx, bts) => ["div", ctx.ui.pager.pages, bts] }); return (ctx: AppContext, triples: any[], num: number, page: number) => { - const [sid, sdir] = ctx.views.sort.deref(); + const [sid, sdir] = ctx.views.sort.deref()!; const icon = sdir ? "🔽" : "🔼"; return [ section, diff --git a/examples/triple-query/src/index.ts b/examples/triple-query/src/index.ts index 408b3861c3..d72f64a3bc 100644 --- a/examples/triple-query/src/index.ts +++ b/examples/triple-query/src/index.ts @@ -4,7 +4,7 @@ import { CONFIG } from "./config"; // export app to global var in dev mode // (for interaction via browser dev tools) if (process.env.NODE_ENV == "development") { - (window["APP"] = new App(CONFIG)).start(); + ((window)["APP"] = new App(CONFIG)).start(); } else { new App(CONFIG).start(); } diff --git a/examples/triple-query/tsconfig.json b/examples/triple-query/tsconfig.json index 50a1cade93..86aea29daa 100644 --- a/examples/triple-query/tsconfig.json +++ b/examples/triple-query/tsconfig.json @@ -4,9 +4,8 @@ "outDir": ".", "module": "es6", "target": "es6", - "sourceMap": true + "sourceMap": true, + "strictFunctionTypes": false }, - "include": [ - "./src/**/*.ts" - ] -} \ No newline at end of file + "include": ["./src/**/*.ts"] +} diff --git a/examples/webgl-cubemap/.gitignore b/examples/webgl-cubemap/.gitignore new file mode 100644 index 0000000000..0c5abcab62 --- /dev/null +++ b/examples/webgl-cubemap/.gitignore @@ -0,0 +1,5 @@ +.cache +out +node_modules +yarn.lock +*.js diff --git a/examples/webgl-cubemap/README.md b/examples/webgl-cubemap/README.md new file mode 100644 index 0000000000..d195e78c10 --- /dev/null +++ b/examples/webgl-cubemap/README.md @@ -0,0 +1,24 @@ +# webgl-cubemap + +WebGL 360Ëš panorama / cube map example. Images by [Emil +Persson](http://www.humus.name/index.php?page=Textures). + +If you want to use your own cube maps, make sure the images are of a +power of 2 or disable mip-mapping in the source code. + +By default, the demo uses WebGL 1. To switch to WebGL2, replace the +`canvasWebGL` component with `canvasWebGL2`. + +[Live demo](http://demo.thi.ng/umbrella/webgl-cubemap/) + +Please refer to the [example build +instructions](https://github.com/thi-ng/umbrella/wiki/Example-build-instructions) +on the wiki. + +## Authors + +- Karsten Schmidt + +## License + +© 2018 Karsten Schmidt // Apache Software License 2.0 diff --git a/examples/webgl-cubemap/assets/golden-gate/negx.jpg b/examples/webgl-cubemap/assets/golden-gate/negx.jpg new file mode 100755 index 0000000000..4a0a2f1b93 Binary files /dev/null and b/examples/webgl-cubemap/assets/golden-gate/negx.jpg differ diff --git a/examples/webgl-cubemap/assets/golden-gate/negy.jpg b/examples/webgl-cubemap/assets/golden-gate/negy.jpg new file mode 100755 index 0000000000..6152352ace Binary files /dev/null and b/examples/webgl-cubemap/assets/golden-gate/negy.jpg differ diff --git a/examples/webgl-cubemap/assets/golden-gate/negz.jpg b/examples/webgl-cubemap/assets/golden-gate/negz.jpg new file mode 100755 index 0000000000..68120c20ea Binary files /dev/null and b/examples/webgl-cubemap/assets/golden-gate/negz.jpg differ diff --git a/examples/webgl-cubemap/assets/golden-gate/posx.jpg b/examples/webgl-cubemap/assets/golden-gate/posx.jpg new file mode 100755 index 0000000000..d041ba5f94 Binary files /dev/null and b/examples/webgl-cubemap/assets/golden-gate/posx.jpg differ diff --git a/examples/webgl-cubemap/assets/golden-gate/posy.jpg b/examples/webgl-cubemap/assets/golden-gate/posy.jpg new file mode 100755 index 0000000000..778e123760 Binary files /dev/null and b/examples/webgl-cubemap/assets/golden-gate/posy.jpg differ diff --git a/examples/webgl-cubemap/assets/golden-gate/posz.jpg b/examples/webgl-cubemap/assets/golden-gate/posz.jpg new file mode 100755 index 0000000000..1ed0c23be1 Binary files /dev/null and b/examples/webgl-cubemap/assets/golden-gate/posz.jpg differ diff --git a/examples/webgl-cubemap/assets/golden-gate/readme.txt b/examples/webgl-cubemap/assets/golden-gate/readme.txt new file mode 100755 index 0000000000..d9bd514116 --- /dev/null +++ b/examples/webgl-cubemap/assets/golden-gate/readme.txt @@ -0,0 +1,13 @@ +Author +====== + +This is the work of Emil Persson, aka Humus. +http://www.humus.name + + + +License +======= + +This work is licensed under a Creative Commons Attribution 3.0 Unported License. +http://creativecommons.org/licenses/by/3.0/ diff --git a/examples/webgl-cubemap/assets/langholmen2/negx.jpg b/examples/webgl-cubemap/assets/langholmen2/negx.jpg new file mode 100644 index 0000000000..4628453e59 Binary files /dev/null and b/examples/webgl-cubemap/assets/langholmen2/negx.jpg differ diff --git a/examples/webgl-cubemap/assets/langholmen2/negy.jpg b/examples/webgl-cubemap/assets/langholmen2/negy.jpg new file mode 100644 index 0000000000..abbdb85db4 Binary files /dev/null and b/examples/webgl-cubemap/assets/langholmen2/negy.jpg differ diff --git a/examples/webgl-cubemap/assets/langholmen2/negz.jpg b/examples/webgl-cubemap/assets/langholmen2/negz.jpg new file mode 100644 index 0000000000..c5fd2608d3 Binary files /dev/null and b/examples/webgl-cubemap/assets/langholmen2/negz.jpg differ diff --git a/examples/webgl-cubemap/assets/langholmen2/posx.jpg b/examples/webgl-cubemap/assets/langholmen2/posx.jpg new file mode 100644 index 0000000000..b05e6c33f6 Binary files /dev/null and b/examples/webgl-cubemap/assets/langholmen2/posx.jpg differ diff --git a/examples/webgl-cubemap/assets/langholmen2/posy.jpg b/examples/webgl-cubemap/assets/langholmen2/posy.jpg new file mode 100644 index 0000000000..6e2a374e42 Binary files /dev/null and b/examples/webgl-cubemap/assets/langholmen2/posy.jpg differ diff --git a/examples/webgl-cubemap/assets/langholmen2/posz.jpg b/examples/webgl-cubemap/assets/langholmen2/posz.jpg new file mode 100644 index 0000000000..3afd37e71b Binary files /dev/null and b/examples/webgl-cubemap/assets/langholmen2/posz.jpg differ diff --git a/examples/webgl-cubemap/assets/langholmen2/readme.txt b/examples/webgl-cubemap/assets/langholmen2/readme.txt new file mode 100755 index 0000000000..d9bd514116 --- /dev/null +++ b/examples/webgl-cubemap/assets/langholmen2/readme.txt @@ -0,0 +1,13 @@ +Author +====== + +This is the work of Emil Persson, aka Humus. +http://www.humus.name + + + +License +======= + +This work is licensed under a Creative Commons Attribution 3.0 Unported License. +http://creativecommons.org/licenses/by/3.0/ diff --git a/examples/webgl-cubemap/assets/maskonaive2/negx.jpg b/examples/webgl-cubemap/assets/maskonaive2/negx.jpg new file mode 100755 index 0000000000..014c4457cb Binary files /dev/null and b/examples/webgl-cubemap/assets/maskonaive2/negx.jpg differ diff --git a/examples/webgl-cubemap/assets/maskonaive2/negy.jpg b/examples/webgl-cubemap/assets/maskonaive2/negy.jpg new file mode 100755 index 0000000000..3fe940fe2b Binary files /dev/null and b/examples/webgl-cubemap/assets/maskonaive2/negy.jpg differ diff --git a/examples/webgl-cubemap/assets/maskonaive2/negz.jpg b/examples/webgl-cubemap/assets/maskonaive2/negz.jpg new file mode 100755 index 0000000000..d8b3f1340e Binary files /dev/null and b/examples/webgl-cubemap/assets/maskonaive2/negz.jpg differ diff --git a/examples/webgl-cubemap/assets/maskonaive2/posx.jpg b/examples/webgl-cubemap/assets/maskonaive2/posx.jpg new file mode 100755 index 0000000000..26e867673d Binary files /dev/null and b/examples/webgl-cubemap/assets/maskonaive2/posx.jpg differ diff --git a/examples/webgl-cubemap/assets/maskonaive2/posy.jpg b/examples/webgl-cubemap/assets/maskonaive2/posy.jpg new file mode 100755 index 0000000000..a13c354157 Binary files /dev/null and b/examples/webgl-cubemap/assets/maskonaive2/posy.jpg differ diff --git a/examples/webgl-cubemap/assets/maskonaive2/posz.jpg b/examples/webgl-cubemap/assets/maskonaive2/posz.jpg new file mode 100755 index 0000000000..215e01a754 Binary files /dev/null and b/examples/webgl-cubemap/assets/maskonaive2/posz.jpg differ diff --git a/examples/webgl-cubemap/assets/maskonaive2/readme.txt b/examples/webgl-cubemap/assets/maskonaive2/readme.txt new file mode 100755 index 0000000000..d9bd514116 --- /dev/null +++ b/examples/webgl-cubemap/assets/maskonaive2/readme.txt @@ -0,0 +1,13 @@ +Author +====== + +This is the work of Emil Persson, aka Humus. +http://www.humus.name + + + +License +======= + +This work is licensed under a Creative Commons Attribution 3.0 Unported License. +http://creativecommons.org/licenses/by/3.0/ diff --git a/examples/webgl/index.html b/examples/webgl-cubemap/index.html similarity index 56% rename from examples/webgl/index.html rename to examples/webgl-cubemap/index.html index 15743bce1a..20e1385a0f 100644 --- a/examples/webgl/index.html +++ b/examples/webgl-cubemap/index.html @@ -1,25 +1,16 @@ - - webgl + webgl-cubemap + -
- + - - \ No newline at end of file + diff --git a/examples/webgl-cubemap/package.json b/examples/webgl-cubemap/package.json new file mode 100644 index 0000000000..3ffe77eacf --- /dev/null +++ b/examples/webgl-cubemap/package.json @@ -0,0 +1,32 @@ +{ + "name": "webgl-cubemap", + "version": "0.0.1", + "repository": "https://github.com/thi-ng/umbrella", + "author": "Karsten Schmidt ", + "license": "Apache-2.0", + "scripts": { + "clean": "rm -rf .cache build out", + "build": "yarn clean && parcel build index.html -d out --public-url ./ --no-source-maps --no-cache --detailed-report --experimental-scope-hoisting", + "build:webpack": "../../node_modules/.bin/webpack --mode production && cp -r assets out/", + "start": "cp -R assets dist/ && parcel index.html -p 8080 --open" + }, + "devDependencies": { + "parcel-bundler": "^1.12.3", + "terser": "^4.0.0", + "typescript": "^3.4.1" + }, + "dependencies": { + "@thi.ng/dsp": "latest", + "@thi.ng/hdom": "latest", + "@thi.ng/hdom-components": "latest", + "@thi.ng/matrices": "latest", + "@thi.ng/webgl": "latest" + }, + "browserslist": [ + "last 3 Chrome versions" + ], + "browser": { + "process": false, + "setTimeout": false + } +} \ No newline at end of file diff --git a/examples/webgl-cubemap/src/index.ts b/examples/webgl-cubemap/src/index.ts new file mode 100644 index 0000000000..0aee8401bc --- /dev/null +++ b/examples/webgl-cubemap/src/index.ts @@ -0,0 +1,157 @@ +import { sin } from "@thi.ng/dsp"; +import { start } from "@thi.ng/hdom"; +import { adaptDPI, canvasWebGL, dropdown } from "@thi.ng/hdom-components"; +import { + concat, + lookAt, + perspective, + transform44 +} from "@thi.ng/matrices"; +import { fromPromise, metaStream, stream } from "@thi.ng/rstream"; +import { + assign, + defMain, + mul, + normalize, + texture, + vec4 +} from "@thi.ng/shader-ast"; +import { + compileModel, + cube, + cubeMap, + draw, + GLMat4, + ModelSpec, + shader, + ShaderSpec +} from "@thi.ng/webgl"; + +const CUBEMAP_SHADER: ShaderSpec = { + vs: (gl, unis, ins, outs) => [ + defMain(() => [ + assign(outs.vnormal, ins.position), + assign(gl.gl_Position, mul(unis.mvp, vec4(ins.position, 1))) + ]) + ], + fs: (_, unis, ins, outs) => [ + defMain(() => [ + assign(outs.fragColor, texture(unis.tex, normalize(ins.vnormal))) + ]) + ], + attribs: { + position: "vec3" + }, + varying: { + vnormal: "vec3" + }, + uniforms: { + mvp: "mat4", + tex: "samplerCube" + }, + state: { + depth: true + } +}; + +const CUBE_MAPS = [ + ["langholmen2", "Langholmen"], + ["golden-gate", "Golden Gate"], + ["maskonaive2", "Maskonaive"] +]; + +const app = () => { + const selection = stream(); + selection.next(CUBE_MAPS[0][0]); + let model: ModelSpec; + const canvas = canvasWebGL({ + init: (_, gl) => { + selection + .subscribe( + metaStream((id: string) => + fromPromise(loadCubeMap(`assets/${id}/`)) + ) + ) + .subscribe({ + next(faces) { + try { + model = compileModel(gl, { + ...cube({ normal: false, uv: false }), + shader: shader(gl, CUBEMAP_SHADER), + uniforms: {}, + textures: [ + cubeMap(gl, faces, { + filter: [ + gl.LINEAR_MIPMAP_LINEAR, + gl.LINEAR + ], + mipmap: true + }) + ] + }); + } catch (err) { + console.warn(err); + } + }, + error(e) { + console.warn(e); + } + }); + }, + // prettier-ignore + update: (el, gl, __, time) => { + if (!model) return; + const bg = 0.1; + const p = perspective([], 45, gl.drawingBufferWidth/gl.drawingBufferHeight, 0.01, 5); + const v = lookAt([],[0, 0, sin(time, 0.00008, 1.99, 2)],[0, 0, 0], [0, 1, 0]); + const m = transform44([], [0, 0, 0], [sin(time, 0.0001, 0.7, 0.5), time * 0.0007,0], 1); + model.uniforms!.mvp = concat([], p, v, m); + adaptDPI(el, window.innerWidth, window.innerHeight); + gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight); + gl.clearColor(bg, bg, bg, 1); + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + draw(model); + } + }); + return () => [ + "div.sans-serif", + [canvas, { width: window.innerWidth, height: window.innerHeight }], + [ + "div.fixed.top-0.left-0.z-1.ma3", + [ + dropdown, + { + onchange: (e: Event) => + selection.next((e.target).value) + }, + CUBE_MAPS, + selection.deref() + ] + ] + ]; +}; + +const imagePromise = (url: string) => + new Promise((resolve, fail) => { + const img = new Image(); + img.onload = () => resolve(img); + img.onerror = (e) => { + console.warn("error loading: " + url); + fail(e); + }; + img.src = url; + }); + +const loadCubeMap = (base: string) => + Promise.all( + ["posx", "negx", "posy", "negy", "posz", "negz"].map((id) => + imagePromise(base + id + ".jpg") + ) + ); + +const cancel = start(app()); + +if (process.env.NODE_ENV !== "production") { + const hot = (module).hot; + hot && hot.dispose(cancel); +} diff --git a/examples/webgl-cubemap/tsconfig.json b/examples/webgl-cubemap/tsconfig.json new file mode 100644 index 0000000000..bbf112cc18 --- /dev/null +++ b/examples/webgl-cubemap/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": ".", + "target": "es6", + "sourceMap": true + }, + "include": [ + "./src/**/*.ts" + ] +} diff --git a/examples/webgl-cubemap/webpack.config.js b/examples/webgl-cubemap/webpack.config.js new file mode 100644 index 0000000000..bf16021356 --- /dev/null +++ b/examples/webgl-cubemap/webpack.config.js @@ -0,0 +1,23 @@ +module.exports = { + entry: "./src/index.ts", + output: { + filename: "bundle.[hash].js", + path: __dirname + "/out" + }, + resolve: { + extensions: [".ts", ".js"] + }, + module: { + rules: [ + { + test: /\.(png|jpg|gif)$/, + loader: "file-loader", + options: { name: "[path][hash].[ext]" } + }, + { test: /\.ts$/, use: "ts-loader" } + ] + }, + node: { + process: false + } +}; diff --git a/examples/webgl-gpgpu-basics/.gitignore b/examples/webgl-gpgpu-basics/.gitignore new file mode 100644 index 0000000000..0c5abcab62 --- /dev/null +++ b/examples/webgl-gpgpu-basics/.gitignore @@ -0,0 +1,5 @@ +.cache +out +node_modules +yarn.lock +*.js diff --git a/examples/webgl-gpgpu-basics/README.md b/examples/webgl-gpgpu-basics/README.md new file mode 100644 index 0000000000..24afc550c6 --- /dev/null +++ b/examples/webgl-gpgpu-basics/README.md @@ -0,0 +1,19 @@ +# webgl-gpgpu-basics + +[Live demo](http://demo.thi.ng/umbrella/webgl-gpgpu-basics/) + +Minimal example demonstrating usage of +[@thi.ng/webgl](https://github.com/thi-ng/umbrella/tree/master/packages/webgl)'s +GPGPU capability. Additionally, the actual GPU code is written directly +in TypeScript, using +[@thi.ng/shader-ast](https://github.com/thi-ng/umbrella/tree/master/packages/shader-ast). + +Please refer to the [example build instructions](https://github.com/thi-ng/umbrella/wiki/Example-build-instructions) on the wiki. + +## Authors + +- Karsten Schmidt + +## License + +© 2018 Karsten Schmidt // Apache Software License 2.0 diff --git a/examples/webgl-gpgpu-basics/index.html b/examples/webgl-gpgpu-basics/index.html new file mode 100644 index 0000000000..92708882b3 --- /dev/null +++ b/examples/webgl-gpgpu-basics/index.html @@ -0,0 +1,19 @@ + + + + + + + webgl-gpgpu-basics + + + + +

webgl-gpgpu-basics

+
Open console to view results...
+ + + diff --git a/examples/webgl-gpgpu-basics/package.json b/examples/webgl-gpgpu-basics/package.json new file mode 100644 index 0000000000..23dfdd4fb3 --- /dev/null +++ b/examples/webgl-gpgpu-basics/package.json @@ -0,0 +1,29 @@ +{ + "name": "webgl-gpgpu-basics", + "version": "0.0.1", + "repository": "https://github.com/thi-ng/umbrella", + "author": "Karsten Schmidt ", + "license": "Apache-2.0", + "scripts": { + "clean": "rm -rf .cache build out", + "build": "yarn clean && parcel build index.html -d out --public-url ./ --no-source-maps --no-cache --detailed-report --experimental-scope-hoisting", + "build:webpack": "../../node_modules/.bin/webpack --mode production", + "start": "parcel index.html -p 8080 --open" + }, + "devDependencies": { + "parcel-bundler": "^1.12.3", + "terser": "^4.0.0", + "typescript": "^3.5.2" + }, + "dependencies": { + "@thi.ng/shader-ast": "latest", + "@thi.ng/transducers": "latest", + "@thi.ng/webgl": "latest" + }, + "browserslist": [ + "last 3 Chrome versions" + ], + "browser": { + "process": false + } +} \ No newline at end of file diff --git a/examples/webgl-gpgpu-basics/src/index.ts b/examples/webgl-gpgpu-basics/src/index.ts new file mode 100644 index 0000000000..db9c24c869 --- /dev/null +++ b/examples/webgl-gpgpu-basics/src/index.ts @@ -0,0 +1,63 @@ +import { + assign, + defMain, + index, + mul, + sym, + texture, + Vec4Sym +} from "@thi.ng/shader-ast"; +import { range } from "@thi.ng/transducers"; +import { gpgpu } from "@thi.ng/webgl"; + +const ctx = gpgpu({ + size: 64, // might be adjusted / rounded up to next power of 2 + inputs: 1, // max inputs + outputs: 3, // max outputs + version: 2 // webgl version +}); + +const job = ctx.newJob({ + inputs: 1, + outputs: 2, + src: (_, unis, ins, outs) => [ + defMain(() => { + let val: Vec4Sym; + return [ + (val = sym(texture(index(unis.inputs, 0), ins.v_uv))), + assign(outs.output0, mul(val, unis.factorA)), + assign(outs.output1, mul(val, unis.factorB)) + ]; + }) + ], + uniforms: { + // uniform params incl. default values + // an `inputs` uniform (sampler2D[]) will be injected automatically + factorA: ["float", 2], + factorB: ["float", 3] + } +}); + +const src = new Float32Array([...range(ctx.inputSize(0))]); +console.log("Original input data:"); +console.log(src); + +job.run({ inputs: [src] }); +console.log("Results of first iteration:"); +// obtain results as Float32Array +console.log(job.result(null, 0)); +console.log(job.result(null, 1)); + +job.run({ inputs: [ctx.outputs[0].tex], outputs: [1, 2] }); +console.log("Results of second iteration:"); +console.log(job.result(null, 1)); +console.log(job.result(null, 2)); + +job.run({ + inputs: [ctx.outputs[1].tex], + outputs: [0, 2], + uniforms: { factorA: 10, factorB: 100 } +}); +console.log("Final results:"); +console.log(job.result(null, 0)); +console.log(job.result(null, 2)); diff --git a/examples/webgl-gpgpu-basics/tsconfig.json b/examples/webgl-gpgpu-basics/tsconfig.json new file mode 100644 index 0000000000..bbf112cc18 --- /dev/null +++ b/examples/webgl-gpgpu-basics/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": ".", + "target": "es6", + "sourceMap": true + }, + "include": [ + "./src/**/*.ts" + ] +} diff --git a/examples/webgl-gpgpu-basics/webpack.config.js b/examples/webgl-gpgpu-basics/webpack.config.js new file mode 100644 index 0000000000..bf16021356 --- /dev/null +++ b/examples/webgl-gpgpu-basics/webpack.config.js @@ -0,0 +1,23 @@ +module.exports = { + entry: "./src/index.ts", + output: { + filename: "bundle.[hash].js", + path: __dirname + "/out" + }, + resolve: { + extensions: [".ts", ".js"] + }, + module: { + rules: [ + { + test: /\.(png|jpg|gif)$/, + loader: "file-loader", + options: { name: "[path][hash].[ext]" } + }, + { test: /\.ts$/, use: "ts-loader" } + ] + }, + node: { + process: false + } +}; diff --git a/examples/webgl-grid/.gitignore b/examples/webgl-grid/.gitignore new file mode 100644 index 0000000000..0c5abcab62 --- /dev/null +++ b/examples/webgl-grid/.gitignore @@ -0,0 +1,5 @@ +.cache +out +node_modules +yarn.lock +*.js diff --git a/examples/webgl-grid/README.md b/examples/webgl-grid/README.md new file mode 100644 index 0000000000..58690b02df --- /dev/null +++ b/examples/webgl-grid/README.md @@ -0,0 +1,13 @@ +# webgl-grid + +[Live demo](http://demo.thi.ng/umbrella/webgl-grid/) + +Please refer to the [example build instructions](https://github.com/thi-ng/umbrella/wiki/Example-build-instructions) on the wiki. + +## Authors + +- Karsten Schmidt + +## License + +© 2018 Karsten Schmidt // Apache Software License 2.0 diff --git a/examples/webgl-grid/index.html b/examples/webgl-grid/index.html new file mode 100644 index 0000000000..2f3752a5e5 --- /dev/null +++ b/examples/webgl-grid/index.html @@ -0,0 +1,18 @@ + + + + + + + webgl-grid + + + + +
+ + + diff --git a/examples/webgl-grid/package.json b/examples/webgl-grid/package.json new file mode 100644 index 0000000000..63b48ecea0 --- /dev/null +++ b/examples/webgl-grid/package.json @@ -0,0 +1,35 @@ +{ + "name": "webgl-grid", + "version": "0.0.1", + "repository": "https://github.com/thi-ng/umbrella", + "author": "Karsten Schmidt ", + "license": "Apache-2.0", + "scripts": { + "clean": "rm -rf .cache build out", + "build": "yarn clean && parcel build index.html -d out --public-url ./ --no-source-maps --no-cache --detailed-report --experimental-scope-hoisting", + "build:webpack": "../../node_modules/.bin/webpack --mode production", + "start": "parcel index.html -p 8080 --open" + }, + "devDependencies": { + "parcel-bundler": "^1.12.3", + "rimraf": "^2.6.3", + "terser": "^4.0.0", + "typescript": "^3.5.2" + }, + "dependencies": { + "@thi.ng/hdom": "latest", + "@thi.ng/hdom-components": "latest", + "@thi.ng/math": "latest", + "@thi.ng/matrices": "latest", + "@thi.ng/transducers": "latest", + "@thi.ng/vectors": "latest", + "@thi.ng/webgl": "latest" + }, + "browserslist": [ + "last 3 Chrome versions" + ], + "browser": { + "process": false, + "setTimeout": false + } +} \ No newline at end of file diff --git a/examples/webgl-grid/src/index.ts b/examples/webgl-grid/src/index.ts new file mode 100644 index 0000000000..fdd1a798e7 --- /dev/null +++ b/examples/webgl-grid/src/index.ts @@ -0,0 +1,114 @@ +import { start } from "@thi.ng/hdom"; +import { adaptDPI, canvasWebGL } from "@thi.ng/hdom-components"; +import { PI } from "@thi.ng/math"; +import { lookAt, ortho, scale44 } from "@thi.ng/matrices"; +import { mapcat, range2d } from "@thi.ng/transducers"; +import { normalize, rotateY } from "@thi.ng/vectors"; +import { + checkerboard, + compileModel, + cube, + draw, + GLMat4, + GLVec3, + LAMBERT, + ModelSpec, + shader, + texture +} from "@thi.ng/webgl"; + +const app = () => { + let model: ModelSpec; + const GRID = 16; + const canvas = canvasWebGL({ + init: (_, gl) => { + const C1 = [0.5, 0.5, 0.5]; + const C2 = [1, 1, 1]; + model = compileModel(gl, { + ...cube({ size: 0.9 }), + instances: { + attribs: { + offset: { + data: new Float32Array([ + ...mapcat( + ([x, z]) => [ + x * 2, + Math.sin(x * 0.4) + Math.sin(z * 0.4), + z * 2 + ], + range2d(-GRID + 1, GRID, -GRID + 1, GRID) + ) + ]) + }, + icol: { + data: new Float32Array([ + ...mapcat( + () => (Math.random() < 0.5 ? C1 : C2), + range2d(-GRID + 1, GRID, -GRID + 1, GRID) + ) + ]) + } + }, + num: (GRID * 2 - 1) ** 2 + }, + shader: shader( + gl, + LAMBERT({ + uv: "uv", + instancePos: "offset", + instanceColor: "icol", + state: { cull: true } + }) + ), + uniforms: {}, + textures: [ + texture(gl, { + image: checkerboard({ + size: 8, + col1: 0xff808080, + col2: 0xffffffff, + corners: true + }), + filter: gl.NEAREST, + wrap: gl.CLAMP_TO_EDGE + }) + ] + }); + }, + update: (el, gl, __, time) => { + adaptDPI(el, window.innerWidth, window.innerHeight); + const cam = [0, 2, 5]; + const eye = rotateY( + null, + [cam[0] + Math.sin(time * 0.0007) * 0, cam[1], cam[2]], + -PI / 4 + Math.sin(time * 0.0005) * 0.1 + ); + const aspect = gl.drawingBufferWidth / gl.drawingBufferHeight; + const zoom = Math.sin(time * 0.0005) * 0.4 + 0.5; + const scl = ((GRID * 2) / 3) * zoom; + // prettier-ignore + Object.assign(model.uniforms, { + proj: ortho([], -scl * aspect, scl * aspect, -scl, scl, -GRID * 2, GRID * 2), + view: lookAt([], eye, [0, 0, 0], [0, 1, 0]), + model: scale44([], [1, Math.sin(time * 0.001) + 1, 1]), + lightDir: rotateY(null, normalize(null, [-0.25, 1, 1]), 0) + }); + const bg = 0.1; + gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight); + gl.clearColor(bg, bg, bg, 1); + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + draw(model); + } + }); + return () => [ + canvas, + { width: window.innerWidth, height: window.innerHeight } + ]; +}; + +const cancel = start(app()); + +if (process.env.NODE_ENV !== "production") { + const hot = (module).hot; + hot && hot.dispose(cancel); +} diff --git a/examples/webgl-grid/tsconfig.json b/examples/webgl-grid/tsconfig.json new file mode 100644 index 0000000000..bbf112cc18 --- /dev/null +++ b/examples/webgl-grid/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": ".", + "target": "es6", + "sourceMap": true + }, + "include": [ + "./src/**/*.ts" + ] +} diff --git a/examples/webgl-grid/webpack.config.js b/examples/webgl-grid/webpack.config.js new file mode 100644 index 0000000000..bf16021356 --- /dev/null +++ b/examples/webgl-grid/webpack.config.js @@ -0,0 +1,23 @@ +module.exports = { + entry: "./src/index.ts", + output: { + filename: "bundle.[hash].js", + path: __dirname + "/out" + }, + resolve: { + extensions: [".ts", ".js"] + }, + module: { + rules: [ + { + test: /\.(png|jpg|gif)$/, + loader: "file-loader", + options: { name: "[path][hash].[ext]" } + }, + { test: /\.ts$/, use: "ts-loader" } + ] + }, + node: { + process: false + } +}; diff --git a/examples/webgl-msdf/.gitignore b/examples/webgl-msdf/.gitignore new file mode 100644 index 0000000000..0c5abcab62 --- /dev/null +++ b/examples/webgl-msdf/.gitignore @@ -0,0 +1,5 @@ +.cache +out +node_modules +yarn.lock +*.js diff --git a/examples/webgl-msdf/README.md b/examples/webgl-msdf/README.md new file mode 100644 index 0000000000..37974f31b0 --- /dev/null +++ b/examples/webgl-msdf/README.md @@ -0,0 +1,13 @@ +# webgl-msdf + +[Live demo](http://demo.thi.ng/umbrella/webgl-msdf/) + +Please refer to the [example build instructions](https://github.com/thi-ng/umbrella/wiki/Example-build-instructions) on the wiki. + +## Authors + +- Karsten Schmidt + +## License + +© 2018 Karsten Schmidt // Apache Software License 2.0 diff --git a/examples/webgl-msdf/assets/inputmono-extralight-msdf.json b/examples/webgl-msdf/assets/inputmono-extralight-msdf.json new file mode 100755 index 0000000000..be31e44283 --- /dev/null +++ b/examples/webgl-msdf/assets/inputmono-extralight-msdf.json @@ -0,0 +1 @@ +{"pages":["InputMono-ExtraLight.png"],"chars":[{"id":41,"index":474,"char":")","width":17,"height":43,"xoffset":4,"yoffset":3,"xadvance":27,"chnl":15,"x":0,"y":0,"page":0},{"id":123,"index":477,"char":"{","width":22,"height":43,"xoffset":0,"yoffset":3,"xadvance":27,"chnl":15,"x":0,"y":44,"page":0},{"id":125,"index":478,"char":"}","width":22,"height":43,"xoffset":4,"yoffset":3,"xadvance":27,"chnl":15,"x":18,"y":0,"page":0},{"id":81,"index":76,"char":"Q","width":25,"height":43,"xoffset":2,"yoffset":3,"xadvance":27,"chnl":15,"x":0,"y":88,"page":0},{"id":40,"index":473,"char":"(","width":17,"height":43,"xoffset":6,"yoffset":3,"xadvance":27,"chnl":15,"x":23,"y":44,"page":0},{"id":106,"index":262,"char":"j","width":19,"height":43,"xoffset":2,"yoffset":3,"xadvance":27,"chnl":15,"x":0,"y":132,"page":0},{"id":92,"index":509,"char":"\\","width":22,"height":42,"xoffset":2,"yoffset":3,"xadvance":27,"chnl":15,"x":0,"y":176,"page":0},{"id":47,"index":508,"char":"/","width":22,"height":42,"xoffset":2,"yoffset":3,"xadvance":27,"chnl":15,"x":20,"y":132,"page":0},{"id":124,"index":511,"char":"|","width":6,"height":42,"xoffset":10,"yoffset":3,"xadvance":27,"chnl":15,"x":26,"y":88,"page":0},{"id":64,"index":513,"char":"@","width":23,"height":39,"xoffset":2,"yoffset":3,"xadvance":27,"chnl":15,"x":33,"y":88,"page":0},{"id":36,"index":557,"char":"$","width":22,"height":38,"xoffset":2,"yoffset":2,"xadvance":27,"chnl":15,"x":41,"y":0,"page":0},{"id":37,"index":480,"char":"%","width":27,"height":36,"xoffset":0,"yoffset":3,"xadvance":27,"chnl":15,"x":41,"y":39,"page":0},{"id":88,"index":108,"char":"X","width":28,"height":35,"xoffset":-1,"yoffset":3,"xadvance":27,"chnl":15,"x":64,"y":0,"page":0},{"id":87,"index":103,"char":"W","width":27,"height":35,"xoffset":0,"yoffset":3,"xadvance":27,"chnl":15,"x":0,"y":219,"page":0},{"id":86,"index":102,"char":"V","width":27,"height":35,"xoffset":0,"yoffset":3,"xadvance":27,"chnl":15,"x":23,"y":175,"page":0},{"id":85,"index":91,"char":"U","width":22,"height":35,"xoffset":2,"yoffset":3,"xadvance":27,"chnl":15,"x":43,"y":128,"page":0},{"id":33,"index":503,"char":"!","width":10,"height":35,"xoffset":8,"yoffset":3,"xadvance":27,"chnl":15,"x":57,"y":76,"page":0},{"id":50,"index":453,"char":2,"width":23,"height":35,"xoffset":2,"yoffset":3,"xadvance":27,"chnl":15,"x":0,"y":255,"page":0},{"id":35,"index":479,"char":"#","width":26,"height":35,"xoffset":0,"yoffset":3,"xadvance":27,"chnl":15,"x":0,"y":291,"page":0},{"id":51,"index":454,"char":3,"width":24,"height":35,"xoffset":1,"yoffset":3,"xadvance":27,"chnl":15,"x":24,"y":255,"page":0},{"id":52,"index":455,"char":4,"width":26,"height":35,"xoffset":1,"yoffset":3,"xadvance":27,"chnl":15,"x":28,"y":211,"page":0},{"id":84,"index":87,"char":"T","width":26,"height":35,"xoffset":0,"yoffset":3,"xadvance":27,"chnl":15,"x":51,"y":164,"page":0},{"id":38,"index":514,"char":"&","width":28,"height":35,"xoffset":0,"yoffset":3,"xadvance":27,"chnl":15,"x":66,"y":112,"page":0},{"id":83,"index":81,"char":"S","width":25,"height":35,"xoffset":1,"yoffset":3,"xadvance":27,"chnl":15,"x":68,"y":76,"page":0},{"id":53,"index":456,"char":5,"width":24,"height":35,"xoffset":1,"yoffset":3,"xadvance":27,"chnl":15,"x":69,"y":36,"page":0},{"id":54,"index":457,"char":6,"width":23,"height":35,"xoffset":2,"yoffset":3,"xadvance":27,"chnl":15,"x":93,"y":0,"page":0},{"id":82,"index":77,"char":"R","width":24,"height":35,"xoffset":2,"yoffset":3,"xadvance":27,"chnl":15,"x":94,"y":36,"page":0},{"id":59,"index":501,"char":";","width":13,"height":35,"xoffset":6,"yoffset":11,"xadvance":27,"chnl":15,"x":117,"y":0,"page":0},{"id":55,"index":458,"char":7,"width":23,"height":35,"xoffset":2,"yoffset":3,"xadvance":27,"chnl":15,"x":94,"y":72,"page":0},{"id":80,"index":75,"char":"P","width":23,"height":35,"xoffset":2,"yoffset":3,"xadvance":27,"chnl":15,"x":0,"y":327,"page":0},{"id":79,"index":66,"char":"O","width":23,"height":35,"xoffset":2,"yoffset":3,"xadvance":27,"chnl":15,"x":0,"y":363,"page":0},{"id":56,"index":459,"char":8,"width":23,"height":35,"xoffset":2,"yoffset":3,"xadvance":27,"chnl":15,"x":0,"y":399,"page":0},{"id":78,"index":61,"char":"N","width":22,"height":35,"xoffset":2,"yoffset":3,"xadvance":27,"chnl":15,"x":0,"y":435,"page":0},{"id":49,"index":452,"char":1,"width":24,"height":35,"xoffset":3,"yoffset":3,"xadvance":27,"chnl":15,"x":0,"y":471,"page":0},{"id":57,"index":460,"char":9,"width":23,"height":35,"xoffset":2,"yoffset":3,"xadvance":27,"chnl":15,"x":23,"y":435,"page":0},{"id":69,"index":24,"char":"E","width":23,"height":35,"xoffset":2,"yoffset":3,"xadvance":27,"chnl":15,"x":25,"y":471,"page":0},{"id":68,"index":22,"char":"D","width":23,"height":35,"xoffset":2,"yoffset":3,"xadvance":27,"chnl":15,"x":24,"y":327,"page":0},{"id":63,"index":506,"char":"?","width":25,"height":35,"xoffset":0,"yoffset":3,"xadvance":27,"chnl":15,"x":27,"y":291,"page":0},{"id":90,"index":114,"char":"Z","width":24,"height":35,"xoffset":2,"yoffset":3,"xadvance":27,"chnl":15,"x":49,"y":247,"page":0},{"id":98,"index":226,"char":"b","width":22,"height":35,"xoffset":2,"yoffset":3,"xadvance":27,"chnl":15,"x":55,"y":200,"page":0},{"id":100,"index":233,"char":"d","width":22,"height":35,"xoffset":2,"yoffset":3,"xadvance":27,"chnl":15,"x":24,"y":363,"page":0},{"id":48,"index":451,"char":0,"width":23,"height":35,"xoffset":2,"yoffset":3,"xadvance":27,"chnl":15,"x":24,"y":399,"page":0},{"id":102,"index":245,"char":"f","width":23,"height":35,"xoffset":1,"yoffset":3,"xadvance":27,"chnl":15,"x":47,"y":363,"page":0},{"id":103,"index":246,"char":"g","width":26,"height":35,"xoffset":0,"yoffset":11,"xadvance":27,"chnl":15,"x":48,"y":327,"page":0},{"id":104,"index":251,"char":"h","width":22,"height":35,"xoffset":2,"yoffset":3,"xadvance":27,"chnl":15,"x":47,"y":435,"page":0},{"id":105,"index":253,"char":"i","width":22,"height":35,"xoffset":2,"yoffset":3,"xadvance":27,"chnl":15,"x":48,"y":399,"page":0},{"id":89,"index":109,"char":"Y","width":28,"height":35,"xoffset":-1,"yoffset":3,"xadvance":27,"chnl":15,"x":49,"y":471,"page":0},{"id":107,"index":264,"char":"k","width":21,"height":35,"xoffset":4,"yoffset":3,"xadvance":27,"chnl":15,"x":70,"y":435,"page":0},{"id":108,"index":266,"char":"l","width":22,"height":35,"xoffset":2,"yoffset":3,"xadvance":27,"chnl":15,"x":78,"y":471,"page":0},{"id":77,"index":60,"char":"M","width":24,"height":35,"xoffset":1,"yoffset":3,"xadvance":27,"chnl":15,"x":53,"y":283,"page":0},{"id":112,"index":285,"char":"p","width":22,"height":35,"xoffset":2,"yoffset":11,"xadvance":27,"chnl":15,"x":74,"y":236,"page":0},{"id":113,"index":286,"char":"q","width":22,"height":35,"xoffset":2,"yoffset":11,"xadvance":27,"chnl":15,"x":71,"y":363,"page":0},{"id":76,"index":56,"char":"L","width":20,"height":35,"xoffset":4,"yoffset":3,"xadvance":27,"chnl":15,"x":71,"y":399,"page":0},{"id":116,"index":297,"char":"t","width":24,"height":35,"xoffset":1,"yoffset":3,"xadvance":27,"chnl":15,"x":75,"y":319,"page":0},{"id":75,"index":54,"char":"K","width":24,"height":35,"xoffset":2,"yoffset":3,"xadvance":27,"chnl":15,"x":78,"y":272,"page":0},{"id":74,"index":52,"char":"J","width":23,"height":35,"xoffset":1,"yoffset":3,"xadvance":27,"chnl":15,"x":92,"y":399,"page":0},{"id":73,"index":42,"char":"I","width":22,"height":35,"xoffset":2,"yoffset":3,"xadvance":27,"chnl":15,"x":92,"y":435,"page":0},{"id":72,"index":40,"char":"H","width":22,"height":35,"xoffset":2,"yoffset":3,"xadvance":27,"chnl":15,"x":101,"y":471,"page":0},{"id":121,"index":319,"char":"y","width":24,"height":35,"xoffset":1,"yoffset":11,"xadvance":27,"chnl":15,"x":115,"y":435,"page":0},{"id":71,"index":35,"char":"G","width":24,"height":35,"xoffset":2,"yoffset":3,"xadvance":27,"chnl":15,"x":124,"y":471,"page":0},{"id":65,"index":4,"char":"A","width":27,"height":35,"xoffset":0,"yoffset":3,"xadvance":27,"chnl":15,"x":94,"y":355,"page":0},{"id":66,"index":15,"char":"B","width":23,"height":35,"xoffset":2,"yoffset":3,"xadvance":27,"chnl":15,"x":116,"y":391,"page":0},{"id":67,"index":16,"char":"C","width":24,"height":35,"xoffset":2,"yoffset":3,"xadvance":27,"chnl":15,"x":100,"y":308,"page":0},{"id":70,"index":34,"char":"F","width":23,"height":35,"xoffset":2,"yoffset":3,"xadvance":27,"chnl":15,"x":122,"y":344,"page":0},{"id":62,"index":533,"char":">","width":23,"height":29,"xoffset":2,"yoffset":8,"xadvance":27,"chnl":15,"x":140,"y":380,"page":0},{"id":60,"index":532,"char":"<","width":23,"height":29,"xoffset":2,"yoffset":8,"xadvance":27,"chnl":15,"x":140,"y":410,"page":0},{"id":115,"index":291,"char":"s","width":23,"height":28,"xoffset":2,"yoffset":11,"xadvance":27,"chnl":15,"x":140,"y":440,"page":0},{"id":101,"index":235,"char":"e","width":22,"height":28,"xoffset":2,"yoffset":11,"xadvance":27,"chnl":15,"x":149,"y":469,"page":0},{"id":99,"index":227,"char":"c","width":22,"height":28,"xoffset":2,"yoffset":11,"xadvance":27,"chnl":15,"x":78,"y":148,"page":0},{"id":111,"index":276,"char":"o","width":22,"height":28,"xoffset":2,"yoffset":11,"xadvance":27,"chnl":15,"x":95,"y":108,"page":0},{"id":58,"index":500,"char":":","width":10,"height":28,"xoffset":8,"yoffset":11,"xadvance":27,"chnl":15,"x":78,"y":177,"page":0},{"id":43,"index":526,"char":"+","width":25,"height":28,"xoffset":1,"yoffset":9,"xadvance":27,"chnl":15,"x":78,"y":206,"page":0},{"id":97,"index":215,"char":"a","width":26,"height":28,"xoffset":1,"yoffset":11,"xadvance":27,"chnl":15,"x":89,"y":177,"page":0},{"id":110,"index":271,"char":"n","width":22,"height":27,"xoffset":2,"yoffset":11,"xadvance":27,"chnl":15,"x":97,"y":235,"page":0},{"id":122,"index":324,"char":"z","width":20,"height":27,"xoffset":3,"yoffset":11,"xadvance":27,"chnl":15,"x":104,"y":206,"page":0},{"id":118,"index":312,"char":"v","width":24,"height":27,"xoffset":1,"yoffset":11,"xadvance":27,"chnl":15,"x":101,"y":137,"page":0},{"id":117,"index":301,"char":"u","width":22,"height":27,"xoffset":2,"yoffset":11,"xadvance":27,"chnl":15,"x":116,"y":165,"page":0},{"id":114,"index":287,"char":"r","width":20,"height":27,"xoffset":4,"yoffset":11,"xadvance":27,"chnl":15,"x":103,"y":263,"page":0},{"id":109,"index":270,"char":"m","width":25,"height":27,"xoffset":1,"yoffset":11,"xadvance":27,"chnl":15,"x":120,"y":234,"page":0},{"id":94,"index":567,"char":"^","width":26,"height":27,"xoffset":0,"yoffset":3,"xadvance":27,"chnl":15,"x":125,"y":193,"page":0},{"id":119,"index":313,"char":"w","width":27,"height":27,"xoffset":0,"yoffset":11,"xadvance":27,"chnl":15,"x":124,"y":262,"page":0},{"id":120,"index":318,"char":"x","width":23,"height":27,"xoffset":2,"yoffset":11,"xadvance":27,"chnl":15,"x":146,"y":221,"page":0},{"id":42,"index":495,"char":"*","width":24,"height":26,"xoffset":1,"yoffset":3,"xadvance":27,"chnl":15,"x":125,"y":290,"page":0},{"id":95,"index":468,"char":"_","width":25,"height":7,"xoffset":1,"yoffset":38,"xadvance":27,"chnl":15,"x":146,"y":249,"page":0},{"id":126,"index":568,"char":"~","width":25,"height":19,"xoffset":1,"yoffset":11,"xadvance":27,"chnl":15,"x":125,"y":317,"page":0},{"id":61,"index":531,"char":"=","width":25,"height":17,"xoffset":1,"yoffset":14,"xadvance":27,"chnl":15,"x":150,"y":290,"page":0},{"id":45,"index":469,"char":"-","width":25,"height":7,"xoffset":1,"yoffset":19,"xadvance":27,"chnl":15,"x":150,"y":308,"page":0},{"id":34,"index":483,"char":"\"","width":20,"height":18,"xoffset":3,"yoffset":3,"xadvance":27,"chnl":15,"x":152,"y":257,"page":0},{"id":96,"index":570,"char":"`","width":14,"height":18,"xoffset":6,"yoffset":3,"xadvance":27,"chnl":15,"x":146,"y":337,"page":0},{"id":44,"index":499,"char":",","width":13,"height":18,"xoffset":6,"yoffset":28,"xadvance":27,"chnl":15,"x":151,"y":316,"page":0},{"id":39,"index":482,"char":"'","width":8,"height":18,"xoffset":9,"yoffset":3,"xadvance":27,"chnl":15,"x":146,"y":356,"page":0},{"id":46,"index":498,"char":".","width":10,"height":10,"xoffset":8,"yoffset":28,"xadvance":27,"chnl":15,"x":101,"y":165,"page":0},{"id":32,"index":3,"char":" ","width":0,"height":0,"xoffset":-2,"yoffset":34,"xadvance":27,"chnl":15,"x":150,"y":316,"page":0}],"info":{"face":"InputMono-ExtraLight","size":42,"bold":0,"italic":0,"charset":[" ",0,1,2,3,4,5,6,7,8,9,"\\","n","-","=","`","~","!","@","#","$","%","^","&","*","(",")","_","+",";","'",",",".","/",":","\"","{","}","<",">","?","|","a","b","c","d","e","f","g","h","i","j","k","l","m","o","p","q","r","s","t","u","v","w","x","y","z","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"],"unicode":1,"stretchH":100,"smooth":1,"aa":1,"padding":[0,0,0,0],"spacing":[0,0]},"common":{"lineHeight":46,"base":34,"scaleW":512,"scaleH":512,"pages":1,"packed":0,"alphaChnl":0,"redChnl":0,"greenChnl":0,"blueChnl":0},"distanceField":{"fieldType":"msdf","distanceRange":4},"kernings":[]} \ No newline at end of file diff --git a/examples/webgl-msdf/assets/inputmono-extralight.png b/examples/webgl-msdf/assets/inputmono-extralight.png new file mode 100755 index 0000000000..a4bca4b8a7 Binary files /dev/null and b/examples/webgl-msdf/assets/inputmono-extralight.png differ diff --git a/examples/webgl-msdf/index.html b/examples/webgl-msdf/index.html new file mode 100644 index 0000000000..a03267553b --- /dev/null +++ b/examples/webgl-msdf/index.html @@ -0,0 +1,16 @@ + + + + + + + webgl-msdf + + + + +
+ + + diff --git a/examples/webgl-msdf/package.json b/examples/webgl-msdf/package.json new file mode 100644 index 0000000000..91de2433f6 --- /dev/null +++ b/examples/webgl-msdf/package.json @@ -0,0 +1,29 @@ +{ + "name": "webgl-msdf", + "version": "0.0.1", + "repository": "https://github.com/thi-ng/umbrella", + "author": "Karsten Schmidt ", + "license": "Apache-2.0", + "scripts": { + "clean": "rm -rf .cache build out", + "build": "yarn clean && parcel build index.html -d out --public-url ./ --no-source-maps --no-cache --detailed-report --experimental-scope-hoisting", + "build:webpack": "../../node_modules/.bin/webpack --mode production && cp -r assets out/", + "start": "parcel index.html -p 8080 --open" + }, + "devDependencies": { + "parcel-bundler": "^1.12.3", + "terser": "^4.0.0", + "typescript": "^3.4.1" + }, + "dependencies": { + "@thi.ng/api": "latest", + "@thi.ng/rstream": "latest", + "@thi.ng/transducers-hdom": "latest" + }, + "browserslist": [ + "last 3 Chrome versions" + ], + "browser": { + "process": false + } +} \ No newline at end of file diff --git a/examples/webgl-msdf/src/index.ts b/examples/webgl-msdf/src/index.ts new file mode 100644 index 0000000000..56917cd584 --- /dev/null +++ b/examples/webgl-msdf/src/index.ts @@ -0,0 +1,294 @@ +import { start } from "@thi.ng/hdom"; +import { canvasWebGL } from "@thi.ng/hdom-components"; +import { fitClamped } from "@thi.ng/math"; +import { + concat, + lookAt, + perspective, + transform44 +} from "@thi.ng/matrices"; +import { SYSTEM } from "@thi.ng/random"; +import { fromDOMEvent, Subscription } from "@thi.ng/rstream"; +import { + $w, + add, + assign, + defMain, + div, + float, + length, + mod, + mul, + sin, + smoothstep, + sub, + vec3, + vec4 +} from "@thi.ng/shader-ast"; +import { map } from "@thi.ng/transducers"; +import { AttribPool, GLType } from "@thi.ng/vector-pools"; +import { + fit3, + madd, + mixN, + mulN, + ReadonlyVec, + Y3, + ZERO3 +} from "@thi.ng/vectors"; +import { + adaptDPI, + compileModel, + DEFAULT_BLEND, + draw, + GLMat4, + ModelSpec, + shader, + texture +} from "@thi.ng/webgl"; +import { + alignCenter, + convertGlyphs, + MSDFFont, + msdfShader, + text +} from "@thi.ng/webgl-msdf"; +import GLYPHS from "../assets/inputmono-extralight-msdf.json"; +import GLYPH_TEX from "../assets/inputmono-extralight.png"; + +const TEXT = `Do not go gentle into that good night, +Old age should burn and rave at close of day; +Rage, rage against the dying of the light. + +Though wise men at their end know dark is right, +Because their words had forked no lightning they +Do not go gentle into that good night. + +Good men, the last wave by, crying how bright +Their frail deeds might have danced in a green bay, +Rage, rage against the dying of the light. + +Wild men who caught and sang the sun in flight, +And learn, too late, they grieved it on its way, +Do not go gentle into that good night. + +Grave men, near death, who see with blinding sight +Blind eyes could blaze like meteors and be gay, +Rage, rage against the dying of the light. + +And you, my father, there on that sad height, +Curse, bless, me now with your fierce tears, I pray. +Do not go gentle into that good night. +Rage, rage against the dying of the light. + +Dylan Thomas`; + +const createText = ( + gl: WebGLRenderingContext, + font: MSDFFont, + img: HTMLImageElement, + txt: string, + col = [1, 0.8, 0, 1] +) => { + const model = { + ...text(font, txt, { + align: alignCenter, + leading: 1.4, + spacing: 1, + dirY: -1, + useColor: true + }), + shader: shader(gl, msdfShader({ color: true })), + textures: [ + texture(gl, { + image: img, + filter: gl.LINEAR, + wrap: gl.CLAMP_TO_EDGE + }) + ], + uniforms: { + bg: [0, 0, 0, 1], + thresh: -0.2 + } + }; + // update bottom vertex colors of each character + for (let i = 2; i < model.attribPool!.capacity; i += 4) { + model.attribPool!.setAttribValues("color", [col, col], i); + } + return compileModel(gl, model); +}; + +const createStarField = (gl: WebGLRenderingContext, num = 1000) => { + const pool = new AttribPool({ + attribs: { + position: { type: GLType.F32, size: 3, byteOffset: 0 }, + dir: { type: GLType.F32, size: 3, byteOffset: 12 }, + id: { type: GLType.F32, size: 1, byteOffset: 24 } + }, + mem: { + size: num * 28 + 8 + }, + num + }); + for (let i = 0, r = SYSTEM; i < num; i++) { + const pos = [r.minmax(-15, 15), r.minmax(0, 10), 0]; + pool.setAttribValue("position", i, pos); + pool.setAttribValue( + "dir", + i, + mixN([], mulN([], pos, 0.1), [0, -1, r.minmax(2, 5)], 0.8) + ); + pool.setAttribValue("id", i, i); + } + return compileModel(gl, { + attribs: {}, + attribPool: pool, + uniforms: {}, + shader: shader(gl, { + vs: (gl, unis, ins, outs) => [ + defMain(() => [ + assign( + outs.valpha, + add( + mul(sin(mul(ins.id, float(37.13829))), float(0.3)), + float(0.7) + ) + ), + assign( + gl.gl_Position, + mul( + mul(unis.proj, unis.modelview), + vec4( + sub( + mod( + add( + ins.position, + mul(ins.dir, unis.time) + ), + float(10) + ), + float(5) + ), + 1 + ) + ) + ), + assign(gl.gl_PointSize, div(float(20), $w(gl.gl_Position))) + ]) + ], + fs: (gl, _, ins, outs) => [ + defMain(() => [ + assign( + outs.fragColor, + vec4( + vec3(ins.valpha), + sub( + float(1), + smoothstep( + float(0.1), + float(0.5), + length(sub(gl.gl_PointCoord, float(0.5))) + ) + ) + ) + ) + ]) + ], + attribs: { + position: "vec3", + dir: "vec3", + id: "float" + }, + varying: { + valpha: "float" + }, + uniforms: { + modelview: "mat4", + proj: "mat4", + time: "float" + }, + state: { + blend: true, + blendFn: DEFAULT_BLEND + } + }), + mode: gl.POINTS, + num + }); +}; + +const app = () => { + const glyphs = convertGlyphs(GLYPHS); + let stars: ModelSpec; + let body: ModelSpec; + let mouse: Subscription; + let bg = 0; + const canvas = canvasWebGL({ + init: async (el, gl) => { + const img = new Image(); + img.src = GLYPH_TEX; + await img.decode(); + body = createText(gl, glyphs, img, TEXT); + stars = createStarField(gl); + body.uniforms!.proj = stars.uniforms!.proj = ( + perspective( + [], + 60, + gl.drawingBufferWidth / gl.drawingBufferHeight, + 0.1, + 20 + ) + ); + mouse = fromDOMEvent(el, "mousemove").transform( + map((e) => + fit3( + [], + [e.clientX, e.clientY, 0], + ZERO3, + [window.innerWidth, window.innerHeight, 0], + [-1, -1, 0], + [1, 1, 0] + ) + ) + ); + }, + update: (el, gl, __, time) => { + if (!body) return; + adaptDPI(el, window.innerWidth, window.innerHeight); + // prettier-ignore + const eye = madd( + null, + mouse.deref() || ZERO3, + [2, 0.5, 0], + [0, -4, 5] + ); + const view = lookAt([], eye, ZERO3, Y3); + body.uniforms!.modelview = ( + concat( + [], + view, + transform44( + [], + [0, fitClamped(time % 70000, 0, 70000, -3.5, 20), 0], + ZERO3, + 0.005 + ) + ) + ); + stars.uniforms!.modelview = view; + stars.uniforms!.time = 10 + time * 0.001; + gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight); + gl.clearColor(bg, bg, bg, 1); + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + draw([stars, body]); + } + }); + return [canvas, { width: window.innerWidth, height: window.innerHeight }]; +}; + +const cancel = start(app()); + +if (process.env.NODE_ENV !== "production") { + const hot = (module).hot; + hot && hot.dispose(cancel); +} diff --git a/examples/webgl-msdf/tsconfig.json b/examples/webgl-msdf/tsconfig.json new file mode 100644 index 0000000000..bbf112cc18 --- /dev/null +++ b/examples/webgl-msdf/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": ".", + "target": "es6", + "sourceMap": true + }, + "include": [ + "./src/**/*.ts" + ] +} diff --git a/examples/webgl-msdf/webpack.config.js b/examples/webgl-msdf/webpack.config.js new file mode 100644 index 0000000000..bf16021356 --- /dev/null +++ b/examples/webgl-msdf/webpack.config.js @@ -0,0 +1,23 @@ +module.exports = { + entry: "./src/index.ts", + output: { + filename: "bundle.[hash].js", + path: __dirname + "/out" + }, + resolve: { + extensions: [".ts", ".js"] + }, + module: { + rules: [ + { + test: /\.(png|jpg|gif)$/, + loader: "file-loader", + options: { name: "[path][hash].[ext]" } + }, + { test: /\.ts$/, use: "ts-loader" } + ] + }, + node: { + process: false + } +}; diff --git a/examples/webgl-ssao/.gitignore b/examples/webgl-ssao/.gitignore new file mode 100644 index 0000000000..0c5abcab62 --- /dev/null +++ b/examples/webgl-ssao/.gitignore @@ -0,0 +1,5 @@ +.cache +out +node_modules +yarn.lock +*.js diff --git a/examples/webgl-ssao/README.md b/examples/webgl-ssao/README.md new file mode 100644 index 0000000000..c2de9d5fa7 --- /dev/null +++ b/examples/webgl-ssao/README.md @@ -0,0 +1,13 @@ +# webgl-ssao + +[Live demo](http://demo.thi.ng/umbrella/webgl-ssao/) + +Please refer to the [example build instructions](https://github.com/thi-ng/umbrella/wiki/Example-build-instructions) on the wiki. + +## Authors + +- Karsten Schmidt + +## License + +© 2018 Karsten Schmidt // Apache Software License 2.0 diff --git a/examples/webgl-ssao/index.html b/examples/webgl-ssao/index.html new file mode 100644 index 0000000000..636ce24dba --- /dev/null +++ b/examples/webgl-ssao/index.html @@ -0,0 +1,16 @@ + + + + + + + webgl-deferred + + + + +
+ + + diff --git a/examples/webgl-ssao/package.json b/examples/webgl-ssao/package.json new file mode 100644 index 0000000000..8dcd402b6c --- /dev/null +++ b/examples/webgl-ssao/package.json @@ -0,0 +1,29 @@ +{ + "name": "webgl-ssao", + "version": "0.0.1", + "repository": "https://github.com/thi-ng/umbrella", + "author": "Karsten Schmidt ", + "license": "Apache-2.0", + "scripts": { + "clean": "rm -rf .cache build out", + "build": "yarn clean && parcel build index.html -d out --public-url ./ --no-source-maps --no-cache --detailed-report --experimental-scope-hoisting", + "build:webpack": "../../node_modules/.bin/webpack --mode production", + "start": "parcel index.html -p 8080 --open" + }, + "devDependencies": { + "parcel-bundler": "^1.12.3", + "terser": "^4.0.0", + "typescript": "^3.4.1" + }, + "dependencies": { + "@thi.ng/api": "latest", + "@thi.ng/rstream": "latest", + "@thi.ng/transducers-hdom": "latest" + }, + "browserslist": [ + "last 3 Chrome versions" + ], + "browser": { + "process": false + } +} \ No newline at end of file diff --git a/examples/webgl-ssao/src/index.ts b/examples/webgl-ssao/src/index.ts new file mode 100644 index 0000000000..70e6aa951e --- /dev/null +++ b/examples/webgl-ssao/src/index.ts @@ -0,0 +1,210 @@ +import { IDeref } from "@thi.ng/api"; +import { sin } from "@thi.ng/dsp"; +import { start } from "@thi.ng/hdom"; +import { canvasWebGL2 } from "@thi.ng/hdom-components"; +import { lookAt, perspective, transform44 } from "@thi.ng/matrices"; +import { fromRAF, tweenNumber } from "@thi.ng/rstream"; +import { + benchmark, + map, + movingAverage, + repeatedly +} from "@thi.ng/transducers"; +import { rotateY } from "@thi.ng/vectors"; +import { + checkerboard, + compileModel, + cube, + draw, + fbo, + FBO, + GLMat4, + GLVec3, + ModelSpec, + quad, + rbo, + shader, + texture, + TextureOpts +} from "@thi.ng/webgl"; +import { CONTROLS, PARAM_DEFS, PARAMS } from "./params"; +import { FINAL_SHADER, LIGHT_SHADER, SSAO_SHADER } from "./shaders"; + +// FBO size +const W = 1024; +const H = 512; + +const LIGHT_POS = [-5, 1.5, -1]; +const Z_NEAR = 0.1; +const Z_FAR = 20; + +// noise texture data for SSAO shader +const NOISE = new Float32Array([ + ...repeatedly(() => Math.random() * 2 - 1, W * H * 2) +]); + +// instance position data for animated cubes +const instancePositions = (o: number) => + // prettier-ignore + new Float32Array([ + -o, 0, 0, o, 0, 0, + 0, -2 * o, 0, 0, 2 * o, 0, + 0, 0, -2 * o, 0, 0, 2 * o +]); + +const app = () => { + let model: ModelSpec; + let ssaoQuad: ModelSpec; + let finalQuad: ModelSpec; + let fboGeo: FBO; + let fboSSAO: FBO; + const raf = fromRAF(); + const fps = raf.transform( + benchmark(), + movingAverage(100), + map((x: number) => (1000 / x).toFixed(2)) + ); + const canvas = canvasWebGL2({ + init(_, gl: WebGL2RenderingContext) { + if (!gl.getExtension("EXT_color_buffer_float")) { + alert("EXT_color_buffer_float not available"); + return; + } + const [colorTex, posTex, normTex, noiseTex, ssaoTex] = [ + {}, + { internalFormat: gl.RGBA16F, type: gl.FLOAT }, + { internalFormat: gl.RGBA16F, type: gl.FLOAT }, + { + image: NOISE, + internalFormat: gl.RG16F, + format: gl.RG, + type: gl.FLOAT + }, + {} + ].map((opts: Partial) => + texture(gl, { + width: W, + height: H, + image: null, + filter: gl.NEAREST, + wrap: gl.CLAMP_TO_EDGE, + ...opts + }) + ); + fboGeo = fbo(gl, { + tex: [colorTex, posTex, normTex], + depth: rbo(gl, { width: W, height: H }) + }); + fboSSAO = fbo(gl, { + tex: [ssaoTex] + }); + model = compileModel(gl, { + ...cube({ uv: true }), + shader: shader(gl, LIGHT_SHADER), + instances: { + attribs: { + offset: { + data: instancePositions(1.05) + } + }, + num: 6 + }, + uniforms: { + eyePos: tweenNumber( + PARAMS.eyeDist, + PARAM_DEFS.eyeDist[2], + 0.05, + 1e-3, + raf + ).transform(map((z) => [0, 0, z])), + lightPos: tweenNumber( + PARAMS.lightTheta, + PARAM_DEFS.lightTheta[2], + 0.05, + 1e-3, + raf + ).transform( + map((theta) => rotateY([], LIGHT_POS, theta)) + ), + specular: PARAMS.specular + }, + textures: [ + texture(gl, { + image: checkerboard({ + size: 16, + col1: 0xffc0c0c0, + col2: 0xffe0e0e0, + corners: true + }), + filter: gl.NEAREST, + wrap: gl.CLAMP_TO_EDGE + }) + ] + }); + ssaoQuad = compileModel(gl, { + ...quad(false), + shader: shader(gl, SSAO_SHADER), + textures: [posTex, normTex, noiseTex], + uniforms: { + sampleRadius: PARAMS.radius, + bias: PARAMS.bias, + attenuate: PARAMS.baseAttenuation, + attenuateDist: PARAMS.distAttenuation, + depthRange: [Z_NEAR, Z_FAR] + } + }); + finalQuad = compileModel(gl, { + ...quad(), + shader: shader(gl, FINAL_SHADER), + textures: [colorTex, ssaoTex], + uniforms: { + amp: PARAMS.amp + } + }); + }, + update(_, gl, __, time, frame) { + if (frame < 1 || !model) return; + const bg = 0.1; + const eye = (>model.uniforms!.eyePos).deref(); + const p = perspective([], 45, W / H, Z_NEAR, Z_FAR); + const v = lookAt([], eye, [0, 0, 0], [0, 1, 0]); + const m = transform44( + [], + [0, 0, 0], + [sin(time, 0.00005, 1, 0), time * 0.0003, 0], + 1 + ); + model.instances!.attribs.offset.buffer!.set( + instancePositions(sin(time, 0.0004, 0.14, 1.15)) + ); + model.uniforms!.model = m; + model.uniforms!.view = v; + model.uniforms!.proj = p; + gl.viewport(0, 0, W, H); + fboGeo.bind(); + gl.clearColor(bg, bg, bg, 1); + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + draw(model); + fboSSAO.bind(); + draw(ssaoQuad); + fboSSAO.unbind(); + gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight); + draw(finalQuad); + } + }); + return () => [ + "div.sans-serif.pa3.bg-dark-gray.white", + [canvas, { width: W, height: H }], + ["div.fixed.top-0.left-0.z-1.ma3.pa3", fps, " fps"], + ["div.mt3", ...CONTROLS] + ]; +}; + +const cancel = start(app()); + +if (process.env.NODE_ENV !== "production") { + const hot = (module).hot; + hot && hot.dispose(cancel); +} + +//window["params"] = PARAMS; diff --git a/examples/webgl-ssao/src/params.ts b/examples/webgl-ssao/src/params.ts new file mode 100644 index 0000000000..5212cc7b6e --- /dev/null +++ b/examples/webgl-ssao/src/params.ts @@ -0,0 +1,53 @@ +import { IObjectOf } from "@thi.ng/api"; +import { stream, Stream } from "@thi.ng/rstream"; +import { + assocObj, + map, + pairs, + push, + transduce +} from "@thi.ng/transducers"; + +const slider = (label: string, attribs: any, stream: Stream) => () => [ + "div.mb2", + ["span.dib.w4", label], + [ + "input.w5", + { + ...attribs, + type: "range", + value: stream.deref(), + oninput: (e: Event) => + stream.next(parseFloat((e.target).value)) + } + ], + ["span.ml3", stream.deref()] +]; + +// prettier-ignore +export const PARAM_DEFS: IObjectOf<[string, any, number]> = { + radius: ["radius", { min: 2, max: 64, step: 1 }, 32], + bias: ["bias", { min: -0.2, max: 0.2, step: 0.01 }, 0.09], + baseAttenuation: ["base attenuation", { min: 0.1, max: 2, step: 0.01 }, 1], + distAttenuation: ["dist attenuation", { min: 0.1, max: 2, step: 0.01 }, 1.2], + amp: ["amplitude", { min: 0, max: 1, step: 0.01 }, 1], + specular: ["specular", { min: 0, max: 1, step: 0.01 }, 0.25], + lightTheta: ["light rotation", { min: 0, max: 3.14, step: 0.01 }, 0.48], + eyeDist: ["cam distance", { min: 5, max: 10, step: 0.01 }, 5] +}; + +export const PARAMS = transduce( + map(([id, spec]) => { + const param = stream(); + param.next(spec[2]); + return [id, param]; + }), + assocObj>(), + pairs(PARAM_DEFS) +); + +export const CONTROLS = transduce( + map(([id, [label, attribs]]) => slider(label, attribs, PARAMS[id])), + push(), + pairs(PARAM_DEFS) +); diff --git a/examples/webgl-ssao/src/shaders.ts b/examples/webgl-ssao/src/shaders.ts new file mode 100644 index 0000000000..bb52662115 --- /dev/null +++ b/examples/webgl-ssao/src/shaders.ts @@ -0,0 +1,145 @@ +import { mergeDeepObj } from "@thi.ng/associative"; +import { + $x, + $xyz, + assign, + defMain, + mul, + sub, + texture, + vec4 +} from "@thi.ng/shader-ast"; +import { clamp01 } from "@thi.ng/shader-ast-stdlib"; +import { FX_SHADER_SPEC, ShaderFn, ShaderSpec } from "@thi.ng/webgl"; + +export const LIGHT_SHADER: ShaderSpec = { + vs: `void main() { + v_position = model * vec4(position + offset, 1.0); + v_normal = model * vec4(normal, 0.0); + v_uv = uv; + v_viewPos = view * v_position; + v_viewNormal = view * v_normal; + gl_Position = proj * v_viewPos; +}`, + fs: `void main() { + vec3 position = v_position.xyz; + vec3 normal = normalize(v_normal.xyz); + vec3 baseColor = texture(tex, v_uv).xyz; + vec3 eyeDir = normalize(eyePos - position); + vec3 lightDir = normalize(lightPos - position); + vec3 reflectDir = reflect(-lightDir, normal); + float diffuse = max(dot(lightDir, normal), 0.0); + float spec = pow(max(dot(reflectDir, eyeDir), 0.0), shininess); + o_color = vec4((ambient + diffuse + spec * specular) * baseColor, 1.0); + o_viewPos = v_viewPos; + o_viewNormal = v_viewNormal; +}`, + attribs: { + position: "vec3", + normal: "vec3", + offset: "vec3", + uv: "vec2" + }, + varying: { + v_position: "vec4", + v_normal: "vec4", + v_uv: "vec2", + v_viewPos: "vec4", + v_viewNormal: "vec4" + }, + uniforms: { + model: "mat4", + view: "mat4", + proj: "mat4", + eyePos: "vec3", + lightPos: "vec3", + shininess: ["float", 250], + specular: "float", + ambient: ["float", 0.15], + tex: "sampler2D" + }, + outputs: { + o_color: ["vec4", 0], + o_viewPos: ["vec4", 1], + o_viewNormal: ["vec4", 2] + }, + state: { + depth: true, + cull: true + } +}; + +export const SSAO_SHADER: ShaderSpec = { + ...FX_SHADER_SPEC, + fs: `const vec2 kernel[4] = vec2[]( + vec2(-K, 0.0), vec2(K, 0.0), + vec2(0.0, -K), vec2(0.0, K) +); + +float occlusionAt(vec3 pos, vec3 normal, ivec2 ipos) { + vec3 posVec = texelFetch(positionTex, ipos, 0).xyz - pos; + float intensity = max(dot(normal, normalize(posVec)) - bias, 0.0); + float attenuation = attenuate + attenuateDist * length(posVec); + return intensity / attenuation; +} + +void main() { + ivec2 ipos = ivec2(gl_FragCoord.xy); + vec3 pos = texelFetch(positionTex, ipos, 0).xyz; + vec3 normal = texelFetch(normalTex, ipos, 0).xyz; + vec2 noise = normalize(texelFetch(noiseTex, ipos, 0).xy); + float depth = (length(pos) - depthRange.x) / (depthRange.y - depthRange.x); + float rScale = sampleRadius * (1.0 - depth); + + float sum = 0.0; + for (int i = 0; i < 4; i++) { + vec2 k1 = reflect(kernel[i], noise) * rScale; + vec2 k2 = vec2(k1.x - k1.y, k1.x + k1.y) * rScale; + sum += occlusionAt(pos, normal, ipos + ivec2(k1)); + sum += occlusionAt(pos, normal, ipos + ivec2(k2 * 0.75)); + sum += occlusionAt(pos, normal, ipos + ivec2(k1 * 0.5)); + sum += occlusionAt(pos, normal, ipos + ivec2(k2 * 0.25)); + } + + o_occlusion = clamp(sum / 16.0, 0.0, 1.0); +}`, + pre: "#define K (0.707107)", + uniforms: { + positionTex: ["sampler2D", 0], + normalTex: ["sampler2D", 1], + noiseTex: ["sampler2D", 2], + sampleRadius: ["float", 32], + bias: ["float", 0.09], + attenuate: ["float", 1], + attenuateDist: ["float", 1], + depthRange: ["vec2", [0.1, 10]] + }, + outputs: { + o_occlusion: "float" + } +}; + +export const FINAL_SHADER: ShaderSpec = mergeDeepObj(FX_SHADER_SPEC, { + fs: ( + ((_, unis, ins, outs) => [ + defMain(() => [ + assign( + outs.fragColor, + vec4( + clamp01( + sub( + $xyz(texture(unis.tex, ins.v_uv)), + mul($x(texture(unis.tex2, ins.v_uv)), unis.amp) + ) + ), + 1 + ) + ) + ]) + ]) + ), + uniforms: { + tex2: ["sampler2D", 1], + amp: ["float", 1] + } +}); diff --git a/examples/webgl-ssao/tsconfig.json b/examples/webgl-ssao/tsconfig.json new file mode 100644 index 0000000000..bbf112cc18 --- /dev/null +++ b/examples/webgl-ssao/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": ".", + "target": "es6", + "sourceMap": true + }, + "include": [ + "./src/**/*.ts" + ] +} diff --git a/examples/webgl-ssao/webpack.config.js b/examples/webgl-ssao/webpack.config.js new file mode 100644 index 0000000000..bf16021356 --- /dev/null +++ b/examples/webgl-ssao/webpack.config.js @@ -0,0 +1,23 @@ +module.exports = { + entry: "./src/index.ts", + output: { + filename: "bundle.[hash].js", + path: __dirname + "/out" + }, + resolve: { + extensions: [".ts", ".js"] + }, + module: { + rules: [ + { + test: /\.(png|jpg|gif)$/, + loader: "file-loader", + options: { name: "[path][hash].[ext]" } + }, + { test: /\.ts$/, use: "ts-loader" } + ] + }, + node: { + process: false + } +}; diff --git a/examples/webgl/README.md b/examples/webgl/README.md deleted file mode 100644 index 30c1423225..0000000000 --- a/examples/webgl/README.md +++ /dev/null @@ -1,15 +0,0 @@ -# webgl - -[Live demo](https://demo.thi.ng/umbrella/webgl/) - -Please refer to the [example build -instructions](https://github.com/thi-ng/umbrella/wiki/Example-build-instructions) -on the wiki. - -## Authors - -- Karsten Schmidt - -## License - -© 2018 Karsten Schmidt // Apache Software License 2.0 diff --git a/examples/webgl/src/index.ts b/examples/webgl/src/index.ts deleted file mode 100644 index ddbf3e5023..0000000000 --- a/examples/webgl/src/index.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { start } from "@thi.ng/hdom"; -import { canvasWebGL } from "@thi.ng/hdom-components"; -import { repeatedly } from "@thi.ng/transducers"; - -// canvas init hook -const initGL = (_: HTMLCanvasElement, __: WebGLRenderingContext) => { - console.log("init webgl canvas"); - // GL context initialization steps - // ... -}; - -/** - * WebGL canvas update/render hook - * - * @param el canvas element - * @param gl GL context - * @param ctx hdom user context - * @param time ms since init - * @param frame current frame - * @param args component args - */ -const updateGL = ( - el: HTMLCanvasElement, - gl: WebGLRenderingContext, - ctx: any, - time: number, - frame: number, - ...args: any[] -) => { - // destructure args passed to component (see below in `app()`) - // (ignore 1st arg, i.e. canvas attribs) - const [_, phase, freq] = args; - const f = phase + frame * freq; - const red = Math.sin(f) * 0.5 + 0.5; - const green = Math.sin(f + (Math.PI * 1) / 3) * 0.5 + 0.5; - const blue = Math.sin(f + (Math.PI * 2) / 3) * 0.5 + 0.5; - gl.clearColor(red, green, blue, 1); - gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); -}; - -const app = () => { - const attribs = { width: 100, height: 100 }; - const [c1, c2, c3] = repeatedly( - () => canvasWebGL({ init: initGL, update: updateGL }), - 3 - ); - return [ - "div", - ["p", "3 WebGL canvas component instances"], - [c1, attribs, 0, 0.01], - [c2, attribs, 200, 0.025], - [c3, attribs, 400, 0.05] - ]; -}; - -start(app()); diff --git a/examples/wolfram/package.json b/examples/wolfram/package.json index 29e0b26324..c8867c17fb 100644 --- a/examples/wolfram/package.json +++ b/examples/wolfram/package.json @@ -12,8 +12,8 @@ "devDependencies": { "parcel-bundler": "^1.12.3", "rimraf": "^2.6.3", - "terser": "^3.17.0", - "typescript": "^3.4.1" + "terser": "^4.0.0", + "typescript": "^3.5.2" }, "dependencies": { "@thi.ng/api": "latest", @@ -29,4 +29,4 @@ "browser": { "process": false } -} +} \ No newline at end of file diff --git a/examples/wolfram/src/index.ts b/examples/wolfram/src/index.ts index c52a0baa6a..ee31902e65 100644 --- a/examples/wolfram/src/index.ts +++ b/examples/wolfram/src/index.ts @@ -34,7 +34,7 @@ const HEIGHT = 32; const resetCA = () => [...randomBits(0.25, WIDTH)]; -const evolveCA = (src, { kernel, rule, reset }) => +const evolveCA = (src: number[], { kernel, rule, reset }: any) => reset ? resetCA() : [ @@ -57,14 +57,15 @@ const triggerReset = () => const triggerOBJExport = () => objExport.next(1); -const setRule = (e) => { - rule.next(parseInt(e.target.value)); +const setRule = (e: Event) => { + rule.next(parseInt((e.target).value)); triggerReset(); }; -const setKernel = (e) => kernel.next(parseInt(e.target.value)); +const setKernel = (e: Event) => + kernel.next(parseInt((e.target).value)); -const app = ({ id, ksize, sim }) => [ +const app = ({ id, ksize, sim }: any) => [ "div.sans-serif.ma3", [ "div", @@ -112,9 +113,11 @@ const app = ({ id, ksize, sim }) => [ const rule = stream(); const kernel = stream(); -const objExport = metaStream(() => fromIterable([true, false], 17)); +const objExport = metaStream(() => + fromIterable([true, false], 17) +); -const wolfram = sync({ +const wolfram = sync({ src: { rule: rule.transform(map((x) => [...bits(32, false, [x])])), kernel: kernel.transform( @@ -125,12 +128,12 @@ const wolfram = sync({ xform: scan(reducer(resetCA, evolveCA)) }); -const main = sync({ +const main = sync({ src: { id: rule, ksize: kernel, sim: wolfram.transform( - map((gen) => gen.map((x) => " â–ˆ"[x]).join("")), + map((gen) => gen.map((x: number) => " â–ˆ"[x]).join("")), slidingWindow(HEIGHT), map((win: string[]) => win.join("\n")) ) @@ -147,7 +150,7 @@ wolfram .transform(slidingWindow(WIDTH)) // sidechainToggle is only letting new values through if enabled by // objExport stream - .subscribe(sidechainToggle(objExport, false)) + .subscribe(sidechainToggle(objExport, false)) // actual OBJ conversion & export .transform( map((grid) => diff --git a/examples/xml-converter/package.json b/examples/xml-converter/package.json index f4382038f9..b707ff3ebf 100644 --- a/examples/xml-converter/package.json +++ b/examples/xml-converter/package.json @@ -12,8 +12,8 @@ }, "devDependencies": { "parcel-bundler": "^1.12.3", - "terser": "^3.17.0", - "typescript": "^3.4.1" + "terser": "^4.0.0", + "typescript": "^3.5.2" }, "dependencies": { "@thi.ng/arrays": "latest", @@ -32,4 +32,4 @@ "browser": { "process": false } -} +} \ No newline at end of file diff --git a/examples/xml-converter/src/convert.ts b/examples/xml-converter/src/convert.ts index f9e0290dbe..670eaa7198 100644 --- a/examples/xml-converter/src/convert.ts +++ b/examples/xml-converter/src/convert.ts @@ -1,5 +1,10 @@ import { isString } from "@thi.ng/checks"; -import { parse, ParseElement, ParseEvent, Type } from "@thi.ng/sax"; +import { + parse, + ParseElement, + ParseEvent, + Type +} from "@thi.ng/sax"; import { assocObj, comp, @@ -38,7 +43,7 @@ export const convertXML = (src: string, opts: Partial = {}) => { // event, which will be related to the final close tag and contains the // entire tree const parseXML = (src: string) => - transduce( + transduce( comp( parse({ trim: true, boolean: true, entities: true }), filter((e) => e.type === Type.ELEM_END || e.type === Type.ERROR) @@ -49,7 +54,7 @@ const parseXML = (src: string) => // transforms string of CSS properties into a plain object const transformCSS = (css: string) => - css.split(";").reduce((acc, p) => { + css.split(";").reduce((acc: any, p) => { const [k, v] = p.split(":"); v != null && (acc[k.trim()] = parseAttrib([k, v.trim()])[1]); return acc; @@ -64,17 +69,17 @@ const parseAttrib = (attrib: string[]) => { return k === "style" ? [k, transformCSS(v)] : v === "true" - ? [k, true] - : v === "false" - ? [k, false] - : [k, /^[0-9.e+-]+$/.test(v) ? parseFloat(v) : v]; + ? [k, true] + : v === "false" + ? [k, false] + : [k, /^[0-9.e+-]+$/.test(v) ? parseFloat(v) : v]; } return attrib; }; // transforms an entire object of attributes const transformAttribs = (attribs: any, remove: Set = new Set()) => - transduce( + transduce( comp(filter((a) => !remove.has(a[0])), map(parseAttrib)), assocObj(), {}, @@ -106,11 +111,11 @@ const transformTree = ( if ((tree).type === Type.ERROR) { return ["error", tree.body]; } - if (opts.removeTags.has(tree.tag)) { + if (opts.removeTags.has(tree.tag!)) { return; } const attribs = transformAttribs(tree.attribs, opts.removeAttribs); - const res: any[] = [transformTag(tree.tag, attribs)]; + const res: any[] = [transformTag(tree.tag!, attribs)]; if (Object.keys(attribs).length) { res.push(attribs); } @@ -118,7 +123,7 @@ const transformTree = ( res.push(tree.body); } if (tree.children && tree.children.length) { - transduce( + transduce( comp(map((t: any) => transformTree(t, opts)), filter((t) => !!t)), push(), res, diff --git a/examples/xml-converter/src/index.ts b/examples/xml-converter/src/index.ts index 45bca01386..f2f3622615 100644 --- a/examples/xml-converter/src/index.ts +++ b/examples/xml-converter/src/index.ts @@ -18,7 +18,7 @@ const inputs = { }; // stream combinator to assemble formatter options -const formatOpts = sync({ +const formatOpts = sync({ src: { trailingComma: inputs.trailingComma, doubleQuote: inputs.doubleQuote, @@ -32,7 +32,7 @@ const formatOpts = sync({ }); // stream combinator to assemble conversion options -const opts = sync({ +const opts = sync({ src: { format: formatOpts, removeAttribs: inputs.removeAttribs.transform(xformAsSet), @@ -41,7 +41,7 @@ const opts = sync({ }); // main stream combinator to create & update UI -const main = sync({ +const main = sync({ src: { src: inputs.xml, copy: inputs.copyButton, diff --git a/examples/xml-converter/src/ui.ts b/examples/xml-converter/src/ui.ts index 84107e9888..9ce98be253 100644 --- a/examples/xml-converter/src/ui.ts +++ b/examples/xml-converter/src/ui.ts @@ -1,3 +1,4 @@ +import { Subscription } from "@thi.ng/rstream"; import { mapIndexed } from "@thi.ng/transducers"; import { handleTab } from "./utils"; @@ -73,7 +74,7 @@ export const UI = { // transformer and receives a tuple of xml & formatted hiccup strings. // defined as closure to avoid using global vars. the `ctx` is the above // `UI.main` and `inputs` are defined in `index.ts`. -export const app = (ctx: any, inputs: any) => ({ src, hiccup }) => [ +export const app = (ctx: any, inputs: any) => ({ src, hiccup }: any) => [ "div.flex-ns", [ editPane, @@ -83,7 +84,7 @@ export const app = (ctx: any, inputs: any) => ({ src, hiccup }) => [ onkeydown: handleTab(inputs.xml), // emitting a new value to the stream will // re-trigger conversion & UI update - oninput: (e) => inputs.xml.next(e.target.value) + oninput: (e: any) => inputs.xml.next(e.target.value) }, src ], @@ -106,7 +107,13 @@ export const app = (ctx: any, inputs: any) => ({ src, hiccup }) => [ // configurable editor panel UI component // (uses Tachyons CSS classes for styling) -const editPane = ({ editor }, title, attribs, value, ...extra) => [ +const editPane = ( + { editor }: any, + title: string, + attribs: any, + value: string, + ...extra: any[] +) => [ "div", editor.root, ["h3", editor.title, ...title], @@ -116,29 +123,35 @@ const editPane = ({ editor }, title, attribs, value, ...extra) => [ ]; // configurable input UI component -const input = ({ input }, label, attribs) => [ +const input = ({ input }: any, label: string, attribs: any) => [ "div", input.root, ["label", { ...input.label, for: attribs.id }, label], ["input", { ...input.input, ...attribs }] ]; -const iconButton = ({ button }, attribs, icon, label) => [ - `a.${button.class}`, - { ...button, ...attribs }, - icon, - label -]; +const iconButton = ( + { button }: any, + attribs: any, + icon: any, + label: string +) => [`a.${button.class}`, { ...button, ...attribs }, icon, label]; // button which, when clicked, copies given `text` to clipboard and // emits true on `stream`. resets stream back to false after given // `delay` time. -const copyButton = ({ copyButton }, attribs, stream, text, delay = 500) => [ +const copyButton = ( + { copyButton }: any, + attribs: any, + stream: Subscription, + text: string, + delay = 500 +) => [ iconButton, { ...copyButton, ...attribs, - onclick: (e) => { + onclick: (e: any) => { e.preventDefault(); e.target.blur(); (navigator).clipboard.writeText(text).then( @@ -155,7 +168,7 @@ const copyButton = ({ copyButton }, attribs, stream, text, delay = 500) => [ ]; // combined transform options input components -const transformOpts = (_, inputs) => [ +const transformOpts = (_: any, inputs: any) => [ "div", ["h3", "Options"], mapIndexed( @@ -168,7 +181,7 @@ const transformOpts = (_, inputs) => [ id: "opt" + i, type, [v]: stream.deref(), - oninput: (e) => stream.next(e.target[v]) + oninput: (e: any) => stream.next(e.target[v]) } ]; }, diff --git a/examples/xml-converter/src/utils.ts b/examples/xml-converter/src/utils.ts index 1d9825fa8c..215e56ee2f 100644 --- a/examples/xml-converter/src/utils.ts +++ b/examples/xml-converter/src/utils.ts @@ -1,3 +1,4 @@ +import { Subscription } from "@thi.ng/rstream"; import { splice } from "@thi.ng/strings"; import { map } from "@thi.ng/transducers"; @@ -8,7 +9,9 @@ export const xformAsSet = map(asSet); // key event handler for textareas to override Tab key behavior and // insert spaces at cursor position instead of changing keyboard focus -export const handleTab = (stream) => (e: KeyboardEvent) => { +export const handleTab = (stream: Subscription) => ( + e: KeyboardEvent +) => { // override tab to insert spaces at edit pos if (e.key === "Tab") { e.preventDefault(); diff --git a/package.json b/package.json index 81e12f8a09..e8b33bc590 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ ], "devDependencies": { "benchmark": "^2.1.4", - "file-loader": "^3.0.1", + "file-loader": "^4.0.0", "gzip-size": "^5.1.0", "lerna": "^3.13.3", "mocha": "^6.1.4", @@ -14,10 +14,10 @@ "rimraf": "^2.6.3", "rollup": "^1.10.1", "rollup-plugin-cleanup": "^3.1.1", - "terser": "^3.17.0", - "ts-loader": "^5.4.3", + "terser": "^4.0.0", + "ts-loader": "^6.0.2", "tslint": "^5.16.0", - "typescript": "^3.4.5", + "typescript": "^3.5.2", "webpack": "^4.30.0", "webpack-cli": "^3.3.1" }, @@ -33,4 +33,4 @@ "test": "yarn build && yarn test:only", "test:only": "lerna run test" } -} +} \ No newline at end of file diff --git a/packages/adjacency/CHANGELOG.md b/packages/adjacency/CHANGELOG.md index cb25a1f70e..2a616b3526 100644 --- a/packages/adjacency/CHANGELOG.md +++ b/packages/adjacency/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.1.16](https://github.com/thi-ng/umbrella/compare/@thi.ng/adjacency@0.1.15...@thi.ng/adjacency@0.1.16) (2019-07-07) + +**Note:** Version bump only for package @thi.ng/adjacency + + + + + ## [0.1.15](https://github.com/thi-ng/umbrella/compare/@thi.ng/adjacency@0.1.14...@thi.ng/adjacency@0.1.15) (2019-05-22) **Note:** Version bump only for package @thi.ng/adjacency diff --git a/packages/adjacency/package.json b/packages/adjacency/package.json index b2ace67abd..6cacd4db0e 100644 --- a/packages/adjacency/package.json +++ b/packages/adjacency/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/adjacency", - "version": "0.1.15", + "version": "0.1.16", "description": "Sparse & bitwise adjacency matrices for directed / undirected graphs", "module": "./index.js", "main": "./lib/index.js", @@ -24,21 +24,21 @@ "pub": "yarn build && yarn publish --access public" }, "devDependencies": { - "@thi.ng/vectors": "^2.5.6", + "@thi.ng/vectors": "^3.0.0", "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/api": "^6.2.0", - "@thi.ng/binary": "^1.0.6", - "@thi.ng/bitfield": "^0.1.8", - "@thi.ng/checks": "^2.1.6", - "@thi.ng/dcons": "^2.0.19", - "@thi.ng/sparse": "^0.1.15" + "@thi.ng/api": "^6.3.0", + "@thi.ng/binary": "^1.0.7", + "@thi.ng/bitfield": "^0.1.9", + "@thi.ng/checks": "^2.2.0", + "@thi.ng/dcons": "^2.1.0", + "@thi.ng/sparse": "^0.1.16" }, "keywords": [ "adjacency", diff --git a/packages/adjacency/src/bfs.ts b/packages/adjacency/src/bfs.ts index 5cb9a2e089..86830d7fa5 100644 --- a/packages/adjacency/src/bfs.ts +++ b/packages/adjacency/src/bfs.ts @@ -29,7 +29,7 @@ export class BFS { marked.setAt(id); } while (queue.length) { - const v = queue.drop(); + const v = queue.drop()!; for (let n of this.graph.neighbors(v)) { const c = dist[v] + cost(v, n); if (c < dist[n] || !marked.at(n)) { diff --git a/packages/adjacency/test/binary.ts b/packages/adjacency/test/binary.ts index 2ed319a73a..411d2cf6fe 100644 --- a/packages/adjacency/test/binary.ts +++ b/packages/adjacency/test/binary.ts @@ -1,19 +1,14 @@ import { Pair } from "@thi.ng/api"; -import { AdjacencyBitMatrix } from "../src/index"; import * as assert from "assert"; +import { AdjacencyBitMatrix } from "../src/index"; -const edges: Pair[] = [ - [2, 3], - [0, 1], - [5, 4], - [2, 0], -]; +const edges: Pair[] = [[2, 3], [0, 1], [5, 4], [2, 0]]; describe("adjacency (bitmatrix)", () => { it("fromEdges, undirected", () => { const m = AdjacencyBitMatrix.fromEdges(6, edges, true); assert.deepEqual( - m.mat.data.slice(0, 6), + [...m.mat.data.slice(0, 6)], [ 1610612736, 2147483648, diff --git a/packages/api/CHANGELOG.md b/packages/api/CHANGELOG.md index 3c92bc2329..17d8c12919 100644 --- a/packages/api/CHANGELOG.md +++ b/packages/api/CHANGELOG.md @@ -3,6 +3,19 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [6.3.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/api@6.2.0...@thi.ng/api@6.3.0) (2019-07-07) + + +### Features + +* **api:** add Select2/3/4 conditional types ([a4bfb88](https://github.com/thi-ng/umbrella/commit/a4bfb88)) +* **api:** enable TS strict compiler flags (refactor) ([0430d01](https://github.com/thi-ng/umbrella/commit/0430d01)) +* **api:** update assert() message arg types ([6137b48](https://github.com/thi-ng/umbrella/commit/6137b48)) + + + + + # [6.2.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/api@6.1.1...@thi.ng/api@6.2.0) (2019-05-22) diff --git a/packages/api/package.json b/packages/api/package.json index 10db06c17c..56d8e5a41f 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/api", - "version": "6.2.0", + "version": "6.3.0", "description": "Common, generic types & interfaces for thi.ng projects", "module": "./index.js", "main": "./lib/index.js", @@ -25,14 +25,14 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/errors": "^1.0.6" + "@thi.ng/errors": "^1.1.0" }, "keywords": [ "compare", diff --git a/packages/api/src/api.ts b/packages/api/src/api.ts index 00ac09614a..bc9c57630a 100644 --- a/packages/api/src/api.ts +++ b/packages/api/src/api.ts @@ -297,6 +297,22 @@ export type Predicate = Fn; */ export type Predicate2 = Fn2; +export type Select2 = T extends Q ? A : B; + +export type Select3 = T extends Q1 + ? A + : T extends Q2 + ? B + : C; + +export type Select4 = T extends Q1 + ? A + : T extends Q2 + ? B + : T extends Q3 + ? C + : D; + /** * Higher order `Predicate` builder. Possibly stateful. */ @@ -505,12 +521,12 @@ export interface IEnable { * Disables this entity. * @param opts optional implementation specific arg */ - disable(opts: T); + disable(opts?: T): any; /** * Enables this entity. * @param opts optional implementation specific arg */ - enable(opts: T); + enable(opts?: T): any; toggle?(): boolean; } @@ -549,7 +565,7 @@ export interface Event extends IID { * @param V value type */ export interface IGet { - get(key: K, notfound?: V): V; + get(key: K, notfound?: V): V | undefined; } /** @@ -557,7 +573,7 @@ export interface IGet { * @param V value type */ export interface IGetIn { - getIn(key: K[], notfound?: V): V; + getIn(key: K[], notfound?: V): V | undefined; } /** @@ -682,18 +698,18 @@ export interface ISet extends IInto { * * @param V value type * @param P return type for pop() - * @param Q return type for push() + * @param S return type for push() */ -export interface IStack { +export interface IStack { /** * Returns top-of-stack item. */ - peek(): V; + peek(): V | undefined; /** * Removes top-of-stack item and returns type P. */ - pop(): P; - push(x: V): Q; + pop(): P | undefined; + push(x: V): S; } export interface IToHiccup { diff --git a/packages/api/src/assert.ts b/packages/api/src/assert.ts index 5e18eebbaf..8fd2c688f3 100644 --- a/packages/api/src/assert.ts +++ b/packages/api/src/assert.ts @@ -1,4 +1,4 @@ -import { NO_OP } from "./api"; +import { Fn0, NO_OP } from "./api"; /** * Takes a `test` result or predicate function without args and throws @@ -10,9 +10,12 @@ export const assert = typeof process === "undefined" || process.env.NODE_ENV !== "production" || process.env.UMBRELLA_ASSERTS === "1" - ? (test: boolean | (() => boolean), msg = "assertion failed") => { + ? ( + test: boolean | Fn0, + msg: string | Fn0 = "assertion failed" + ) => { if ((typeof test === "function" && !test()) || !test) { - throw new Error(msg); + throw new Error(typeof msg === "function" ? msg() : msg); } } : NO_OP; diff --git a/packages/api/src/mixin.ts b/packages/api/src/mixin.ts index 03c4d299fe..cd3da372ca 100644 --- a/packages/api/src/mixin.ts +++ b/packages/api/src/mixin.ts @@ -10,12 +10,12 @@ * @param sharedBehaviour * @returns decorator function */ -export const mixin = (behaviour: any, sharedBehaviour = {}) => { +export const mixin = (behaviour: any, sharedBehaviour: any = {}) => { const instanceKeys = Reflect.ownKeys(behaviour); const sharedKeys = Reflect.ownKeys(sharedBehaviour); const typeTag = Symbol("isa"); - function _mixin(clazz) { + function _mixin(clazz: any) { for (let key of instanceKeys) { const existing = Object.getOwnPropertyDescriptor( clazz.prototype, @@ -42,7 +42,7 @@ export const mixin = (behaviour: any, sharedBehaviour = {}) => { } Object.defineProperty(_mixin, Symbol.hasInstance, { - value: (x) => !!x[typeTag] + value: (x: any) => !!x[typeTag] }); return _mixin; diff --git a/packages/api/src/mixins/ienable.ts b/packages/api/src/mixins/ienable.ts index 4a9de0d542..d9a86311c3 100644 --- a/packages/api/src/mixins/ienable.ts +++ b/packages/api/src/mixins/ienable.ts @@ -6,6 +6,11 @@ import { } from "../api"; import { mixin } from "../mixin"; +interface _IEnable extends IEnable { + _enabled: boolean; + notify?(e: Event): void; +} + /** * Mixin class decorator, injects IEnable default implementation, incl. * a `_enabled` property. If the target also implements the `INotify` @@ -16,25 +21,27 @@ export const IEnableMixin = mixin(>{ _enabled: true, isEnabled() { - return this._enabled; + return (<_IEnable>this)._enabled; }, enable() { - this._enabled = true; - if (this.notify) { - this.notify({ id: EVENT_ENABLE, target: this }); + const $this = <_IEnable>this; + $this._enabled = true; + if ($this.notify) { + $this.notify({ id: EVENT_ENABLE, target: this }); } }, disable() { - this._enabled = false; - if (this.notify) { - this.notify({ id: EVENT_DISABLE, target: this }); + const $this = <_IEnable>this; + $this._enabled = false; + if ($this.notify) { + $this.notify({ id: EVENT_DISABLE, target: this }); } }, toggle() { - this._enabled ? this.disable() : this.enable(); - return this._enabled; + (<_IEnable>this)._enabled ? this.disable() : this.enable(); + return (<_IEnable>this)._enabled; } }); diff --git a/packages/api/src/mixins/inotify.ts b/packages/api/src/mixins/inotify.ts index 41ecf7923b..6d9b4f33c1 100644 --- a/packages/api/src/mixins/inotify.ts +++ b/packages/api/src/mixins/inotify.ts @@ -2,10 +2,16 @@ import { Event, EVENT_ALL, INotify, + IObjectOf, Listener } from "../api"; import { mixin } from "../mixin"; +interface _INotify extends INotify { + _listeners: IObjectOf<[Listener, any][]>; + __listener(listeners: any[][], f: Listener, scope: any): number; +} + export const inotify_dispatch = (listeners: any[][], e: Event) => { if (!listeners) return; for (let i = 0, n = listeners.length, l; i < n; i++) { @@ -23,23 +29,24 @@ export const inotify_dispatch = (listeners: any[][], e: Event) => { * registered listeners. */ export const INotifyMixin = mixin({ - addListener(id: PropertyKey, fn: Listener, scope?: any) { - let l = (this._listeners = this._listeners || {})[id]; + addListener(id: string, fn: Listener, scope?: any) { + let l = ((<_INotify>this)._listeners = + (<_INotify>this)._listeners || {})[id]; if (!l) { - l = this._listeners[id] = []; + l = (this)._listeners[id] = []; } - if (this.__listener(l, fn, scope) === -1) { + if ((<_INotify>this).__listener(l, fn, scope) === -1) { l.push([fn, scope]); return true; } return false; }, - removeListener(id: PropertyKey, fn: Listener, scope?: any) { - if (!this._listeners) return false; - const l: any[][] = this._listeners[id]; + removeListener(id: string, fn: Listener, scope?: any) { + if (!(<_INotify>this)._listeners) return false; + const l = (<_INotify>this)._listeners[id]; if (l) { - const idx = this.__listener(l, fn, scope); + const idx = (<_INotify>this).__listener(l, fn, scope); if (idx !== -1) { l.splice(idx, 1); return true; @@ -49,13 +56,13 @@ export const INotifyMixin = mixin({ }, notify(e: Event) { - if (!this._listeners) return; + if (!(<_INotify>this)._listeners) return; e.target === undefined && (e.target = this); - inotify_dispatch(this._listeners[e.id], e); - inotify_dispatch(this._listeners[EVENT_ALL], e); + inotify_dispatch((<_INotify>this)._listeners[e.id], e); + inotify_dispatch((<_INotify>this)._listeners[EVENT_ALL], e); }, - __listener(listeners: any[][], f: Listener, scope: any) { + __listener(listeners: [Listener, any][], f: Listener, scope: any) { let i = listeners.length; while (--i >= 0) { const l = listeners[i]; diff --git a/packages/api/src/mixins/iwatch.ts b/packages/api/src/mixins/iwatch.ts index 26b351e13c..fcbe9400ac 100644 --- a/packages/api/src/mixins/iwatch.ts +++ b/packages/api/src/mixins/iwatch.ts @@ -1,28 +1,37 @@ -import { Fn3, IWatch } from "../api"; +import { + Fn3, + IObjectOf, + IWatch, + Watch +} from "../api"; import { mixin } from "../mixin"; +interface _IWatch extends IWatch { + _watches: IObjectOf>; +} + export const IWatchMixin = mixin(>{ addWatch(id: string, fn: Fn3) { - this._watches = this._watches || {}; - if (this._watches[id]) { + (<_IWatch>this)._watches = (<_IWatch>this)._watches || {}; + if ((<_IWatch>this)._watches[id]) { return false; } - this._watches[id] = fn; + (<_IWatch>this)._watches[id] = fn; return true; }, removeWatch(id: string) { - if (!this._watches) return; - if (this._watches[id]) { - delete this._watches[id]; + if (!(<_IWatch>this)._watches) return; + if ((<_IWatch>this)._watches[id]) { + delete (<_IWatch>this)._watches[id]; return true; } return false; }, notifyWatches(oldState: any, newState: any) { - if (!this._watches) return; - const w = this._watches; + if (!(<_IWatch>this)._watches) return; + const w = (<_IWatch>this)._watches; for (let id in w) { w[id](id, oldState, newState); } diff --git a/packages/api/test/mixins.ts b/packages/api/test/mixins.ts index 27c1e8fc3c..1135ec5565 100644 --- a/packages/api/test/mixins.ts +++ b/packages/api/test/mixins.ts @@ -7,7 +7,6 @@ import { } from "../src/api"; import { INotifyMixin } from "../src/mixins/inotify"; - describe("mixins", () => { it("INotify", () => { @INotifyMixin @@ -25,8 +24,8 @@ describe("mixins", () => { const res: any = {}; const foo = new Foo(); - const l = (e) => (res[e.id] = e.value); - const lall = (e) => (res[EVENT_ALL] = e.value); + const l = (e: Event) => (res[e.id] = e.value); + const lall = (e: Event) => (res[EVENT_ALL] = e.value); assert.doesNotThrow(() => foo.addListener("x", l)); assert.doesNotThrow(() => foo.addListener(EVENT_ALL, lall)); foo.notify({ id: "x", value: 1 }); diff --git a/packages/arrays/CHANGELOG.md b/packages/arrays/CHANGELOG.md index 1968695069..a3160f732e 100644 --- a/packages/arrays/CHANGELOG.md +++ b/packages/arrays/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.2.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/arrays@0.1.9...@thi.ng/arrays@0.2.0) (2019-07-07) + + +### Features + +* **arrays:** enable TS strict compiler flags (refactor) ([8724f9e](https://github.com/thi-ng/umbrella/commit/8724f9e)) + + + + + ## [0.1.9](https://github.com/thi-ng/umbrella/compare/@thi.ng/arrays@0.1.8...@thi.ng/arrays@0.1.9) (2019-05-22) **Note:** Version bump only for package @thi.ng/arrays diff --git a/packages/arrays/package.json b/packages/arrays/package.json index a74af22139..b46a78c84d 100644 --- a/packages/arrays/package.json +++ b/packages/arrays/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/arrays", - "version": "0.1.9", + "version": "0.2.0", "description": "Array / Arraylike utilities", "module": "./index.js", "main": "./lib/index.js", @@ -25,19 +25,19 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/api": "^6.2.0", - "@thi.ng/checks": "^2.1.6", - "@thi.ng/compare": "^1.0.6", - "@thi.ng/equiv": "^1.0.6", - "@thi.ng/errors": "^1.0.6", - "@thi.ng/random": "^1.1.7" + "@thi.ng/api": "^6.3.0", + "@thi.ng/checks": "^2.2.0", + "@thi.ng/compare": "^1.0.7", + "@thi.ng/equiv": "^1.0.7", + "@thi.ng/errors": "^1.1.0", + "@thi.ng/random": "^1.1.8" }, "keywords": [ "arrays", diff --git a/packages/arrays/src/swizzle.ts b/packages/arrays/src/swizzle.ts index 94eb85c6dd..492d7fbdfd 100644 --- a/packages/arrays/src/swizzle.ts +++ b/packages/arrays/src/swizzle.ts @@ -27,23 +27,23 @@ export const swizzle = (order: string | PropertyKey[]): Fn => { case 0: return () => []; case 1: - return (x) => [x[a]]; + return (x: any) => [x[a]]; case 2: - return (x) => [x[a], x[b]]; + return (x: any) => [x[a], x[b]]; case 3: - return (x) => [x[a], x[b], x[c]]; + return (x: any) => [x[a], x[b], x[c]]; case 4: - return (x) => [x[a], x[b], x[c], x[d]]; + return (x: any) => [x[a], x[b], x[c], x[d]]; case 5: - return (x) => [x[a], x[b], x[c], x[d], x[e]]; + return (x: any) => [x[a], x[b], x[c], x[d], x[e]]; case 6: - return (x) => [x[a], x[b], x[c], x[d], x[e], x[f]]; + return (x: any) => [x[a], x[b], x[c], x[d], x[e], x[f]]; case 7: - return (x) => [x[a], x[b], x[c], x[d], x[e], x[f], x[g]]; + return (x: any) => [x[a], x[b], x[c], x[d], x[e], x[f], x[g]]; case 8: - return (x) => [x[a], x[b], x[c], x[d], x[e], x[f], x[g], x[h]]; + return (x: any) => [x[a], x[b], x[c], x[d], x[e], x[f], x[g], x[h]]; default: - return (x) => { + return (x: any) => { const res = []; for (let i = order.length; --i >= 0; ) { res[i] = x[order[i]]; diff --git a/packages/associative/CHANGELOG.md b/packages/associative/CHANGELOG.md index 5d65aab39d..71090a2119 100644 --- a/packages/associative/CHANGELOG.md +++ b/packages/associative/CHANGELOG.md @@ -3,6 +3,23 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [2.4.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/associative@2.3.0...@thi.ng/associative@2.4.0) (2019-07-07) + + +### Bug Fixes + +* **associative:** update generics (TS3.5.2) ([75a4f72](https://github.com/thi-ng/umbrella/commit/75a4f72)) +* **associative:** update SortedMap.fromObject() - PropertyKey => string ([48688da](https://github.com/thi-ng/umbrella/commit/48688da)) + + +### Features + +* **associative:** enable TS strict compiler flags (refactor) ([7931e14](https://github.com/thi-ng/umbrella/commit/7931e14)) + + + + + # [2.3.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/associative@2.2.3...@thi.ng/associative@2.3.0) (2019-05-22) diff --git a/packages/associative/package.json b/packages/associative/package.json index ebbf03d305..36521193f6 100644 --- a/packages/associative/package.json +++ b/packages/associative/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/associative", - "version": "2.3.0", + "version": "2.4.0", "description": "Alternative Set & Map data type implementations with customizable equality semantics & supporting operations", "module": "./index.js", "main": "./lib/index.js", @@ -25,21 +25,21 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/api": "^6.2.0", - "@thi.ng/binary": "^1.0.6", - "@thi.ng/checks": "^2.1.6", - "@thi.ng/compare": "^1.0.6", - "@thi.ng/dcons": "^2.0.19", - "@thi.ng/equiv": "^1.0.6", - "@thi.ng/errors": "^1.0.6", - "@thi.ng/transducers": "^5.3.7" + "@thi.ng/api": "^6.3.0", + "@thi.ng/binary": "^1.0.7", + "@thi.ng/checks": "^2.2.0", + "@thi.ng/compare": "^1.0.7", + "@thi.ng/dcons": "^2.1.0", + "@thi.ng/equiv": "^1.0.7", + "@thi.ng/errors": "^1.1.0", + "@thi.ng/transducers": "^5.4.0" }, "keywords": [ "data structures", diff --git a/packages/associative/src/api.ts b/packages/associative/src/api.ts index ce6998c080..1d2b9d2996 100644 --- a/packages/associative/src/api.ts +++ b/packages/associative/src/api.ts @@ -17,12 +17,12 @@ export interface IEquivSet IGet, IInto> { disj(xs: Iterable): this; - first(): T; + first(): T | undefined; } export interface EquivSetConstructor { new (): IEquivSet; - new (values?: Iterable, opts?: any): IEquivSet; + new (values?: Iterable | null, opts?: any): IEquivSet; readonly prototype: IEquivSet; } diff --git a/packages/associative/src/array-set.ts b/packages/associative/src/array-set.ts index 1929d45143..a908aec9be 100644 --- a/packages/associative/src/array-set.ts +++ b/packages/associative/src/array-set.ts @@ -24,14 +24,17 @@ const __private = new WeakMap, ArraySetProps>(); * `IEquiv` interfaces itself. */ export class ArraySet extends Set implements IEquivSet { - constructor(vals?: Iterable, opts: Partial> = {}) { + constructor( + vals?: Iterable | null, + opts: Partial> = {} + ) { super(); __private.set(this, { equiv: opts.equiv || equiv, vals: [] }); vals && this.into(vals); } - *[Symbol.iterator]() { - yield* __private.get(this).vals; + *[Symbol.iterator](): IterableIterator { + yield* __private.get(this)!.vals; } get [Symbol.species]() { @@ -42,14 +45,14 @@ export class ArraySet extends Set implements IEquivSet { return "ArraySet"; } - get size() { - return __private.get(this).vals.length; + get size(): number { + return __private.get(this)!.vals.length; } - copy() { - const $this = __private.get(this); + copy(): ArraySet { + const $this = __private.get(this)!; const s = new ArraySet(null, { equiv: $this.equiv }); - __private.get(s).vals = $this.vals.slice(); + __private.get(s)!.vals = $this.vals.slice(); return s; } @@ -58,17 +61,17 @@ export class ArraySet extends Set implements IEquivSet { } clear() { - __private.get(this).vals.length = 0; + __private.get(this)!.vals.length = 0; } - first() { + first(): T | undefined { if (this.size) { - return __private.get(this).vals[0]; + return __private.get(this)!.vals[0]; } } add(x: T) { - !this.has(x) && __private.get(this).vals.push(x); + !this.has(x) && __private.get(this)!.vals.push(x); return this; } @@ -91,7 +94,7 @@ export class ArraySet extends Set implements IEquivSet { * @param notFound */ get(x: T, notFound?: T): T | undefined { - const $this = __private.get(this); + const $this = __private.get(this)!; const eq = $this.equiv; const vals = $this.vals; for (let i = vals.length - 1; i >= 0; i--) { @@ -103,7 +106,7 @@ export class ArraySet extends Set implements IEquivSet { } delete(x: T) { - const $this = __private.get(this); + const $this = __private.get(this)!; const eq = $this.equiv; const vals = $this.vals; for (let i = vals.length - 1; i >= 0; i--) { @@ -132,7 +135,7 @@ export class ArraySet extends Set implements IEquivSet { if (this.size !== o.size) { return false; } - const vals = __private.get(this).vals; + const vals = __private.get(this)!.vals; for (let i = vals.length; --i >= 0; ) { if (!o.has(vals[i])) { return false; @@ -142,7 +145,7 @@ export class ArraySet extends Set implements IEquivSet { } forEach(fn: Fn3, Readonly, Set, void>, thisArg?: any) { - const vals = __private.get(this).vals; + const vals = __private.get(this)!.vals; for (let i = vals.length; --i >= 0; ) { const v = vals[i]; fn.call(thisArg, v, v, this); @@ -150,13 +153,13 @@ export class ArraySet extends Set implements IEquivSet { } *entries(): IterableIterator> { - for (let v of __private.get(this).vals) { + for (let v of __private.get(this)!.vals) { yield [v, v]; } } *keys(): IterableIterator { - yield* __private.get(this).vals; + yield* __private.get(this)!.vals; } *values(): IterableIterator { @@ -164,6 +167,6 @@ export class ArraySet extends Set implements IEquivSet { } opts(): EquivSetOpts { - return { equiv: __private.get(this).equiv }; + return { equiv: __private.get(this)!.equiv }; } } diff --git a/packages/associative/src/common-keys.ts b/packages/associative/src/common-keys.ts index 8b40f0c141..d9ee19a5b8 100644 --- a/packages/associative/src/common-keys.ts +++ b/packages/associative/src/common-keys.ts @@ -29,7 +29,7 @@ export const commonKeysMap = ( * @param b * @param out */ -export const commonKeysObj = ( +export const commonKeysObj = ( a: A, b: B, out: string[] = [] diff --git a/packages/associative/src/difference.ts b/packages/associative/src/difference.ts index f0312209db..62ad7f8143 100644 --- a/packages/associative/src/difference.ts +++ b/packages/associative/src/difference.ts @@ -16,7 +16,7 @@ export const difference = (a: Set, b: Set, out?: Set): Set => { } out = out ? into(out, a) : copy(a, Set); for (let i of b) { - out.delete(i); + out!.delete(i); } - return out; + return out!; }; diff --git a/packages/associative/src/equiv-map.ts b/packages/associative/src/equiv-map.ts index 779c9d4eb9..82bfdf6841 100644 --- a/packages/associative/src/equiv-map.ts +++ b/packages/associative/src/equiv-map.ts @@ -56,7 +56,10 @@ export class EquivMap extends Map * @param pairs * @param opts */ - constructor(pairs?: Iterable>, opts?: Partial>) { + constructor( + pairs?: Iterable> | null, + opts?: Partial> + ) { super(); const _opts: EquivMapOpts = { equiv, keys: ArraySet, ...opts }; __private.set(this, { @@ -81,22 +84,22 @@ export class EquivMap extends Map return "EquivMap"; } - get size() { - return __private.get(this).keys.size; + get size(): number { + return __private.get(this)!.keys.size; } clear() { - const $this = __private.get(this); + const $this = __private.get(this)!; $this.keys.clear(); $this.map.clear(); } - empty() { - return new EquivMap(null, __private.get(this).opts); + empty(): EquivMap { + return new EquivMap(null, __private.get(this)!.opts); } copy() { - const $this = __private.get(this); + const $this = __private.get(this)!; const m = new EquivMap(); __private.set(m, { keys: $this.keys.copy(), @@ -116,7 +119,7 @@ export class EquivMap extends Map if (this.size !== o.size) { return false; } - for (let p of __private.get(this).map.entries()) { + for (let p of __private.get(this)!.map.entries()) { if (!equiv(o.get(p[0]), p[1])) { return false; } @@ -125,7 +128,7 @@ export class EquivMap extends Map } delete(key: K) { - const $this = __private.get(this); + const $this = __private.get(this)!; key = $this.keys.get(key, SEMAPHORE); if (key !== SEMAPHORE) { $this.map.delete(key); @@ -143,13 +146,13 @@ export class EquivMap extends Map } forEach(fn: Fn3, Map, void>, thisArg?: any) { - for (let pair of __private.get(this).map) { + for (let pair of __private.get(this)!.map) { fn.call(thisArg, pair[1], pair[0], this); } } get(key: K, notFound?: V): V | undefined { - const $this = __private.get(this); + const $this = __private.get(this)!; key = $this.keys.get(key, SEMAPHORE); if (key !== SEMAPHORE) { return $this.map.get(key); @@ -157,12 +160,12 @@ export class EquivMap extends Map return notFound; } - has(key: K) { - return __private.get(this).keys.has(key); + has(key: K): boolean { + return __private.get(this)!.keys.has(key); } set(key: K, value: V) { - const $this = __private.get(this); + const $this = __private.get(this)!; const k = $this.keys.get(key, SEMAPHORE); if (k !== SEMAPHORE) { $this.map.set(k, value); @@ -181,18 +184,18 @@ export class EquivMap extends Map } entries(): IterableIterator> { - return __private.get(this).map.entries(); + return __private.get(this)!.map.entries(); } keys(): IterableIterator { - return __private.get(this).map.keys(); + return __private.get(this)!.map.keys(); } values(): IterableIterator { - return __private.get(this).map.values(); + return __private.get(this)!.map.values(); } opts(): EquivMapOpts { - return __private.get(this).opts; + return __private.get(this)!.opts; } } diff --git a/packages/associative/src/hash-map.ts b/packages/associative/src/hash-map.ts index 45583500a0..14bffc14a8 100644 --- a/packages/associative/src/hash-map.ts +++ b/packages/associative/src/hash-map.ts @@ -49,7 +49,7 @@ export class HashMap extends Map ICopy>, IEmpty>, IEquiv { - constructor(pairs: Iterable>, opts: HashMapOpts) { + constructor(pairs: Iterable> | null, opts: HashMapOpts) { super(); const m = ceilPow2(Math.min(opts.cap || DEFAULT_CAP, 4)) - 1; __private.set(this, { @@ -73,8 +73,8 @@ export class HashMap extends Map return "HashMap"; } - get size() { - return __private.get(this).size; + get size(): number { + return __private.get(this)!.size; } [Symbol.iterator]() { @@ -82,31 +82,31 @@ export class HashMap extends Map } *entries(): IterableIterator> { - for (let p of __private.get(this).bins) { + for (let p of __private.get(this)!.bins) { if (p) yield [p[0], p[1]]; } } *keys(): IterableIterator { - for (let p of __private.get(this).bins) { + for (let p of __private.get(this)!.bins) { if (p) yield p[0]; } } *values(): IterableIterator { - for (let p of __private.get(this).bins) { + for (let p of __private.get(this)!.bins) { if (p) yield p[1]; } } forEach(fn: Fn3, Map, void>, thisArg?: any) { - for (let pair of __private.get(this).bins) { + for (let pair of __private.get(this)!.bins) { fn.call(thisArg, pair[1], pair[0], this); } } clear() { - const $this = __private.get(this); + const $this = __private.get(this)!; $this.bins = new Array(DEFAULT_CAP); $this.mask = 15; $this.size = 0; @@ -117,7 +117,7 @@ export class HashMap extends Map } copy() { - const $this = __private.get(this); + const $this = __private.get(this)!; const m = new HashMap(null, this.opts({ cap: 4 })); Object.assign(__private.get(m), { bins: $this.bins.slice(), @@ -137,7 +137,7 @@ export class HashMap extends Map if (this.size !== o.size) { return false; } - for (let p of __private.get(this).bins) { + for (let p of __private.get(this)!.bins) { if (p && !equiv(o.get(p[0]), p[1])) { return false; } @@ -145,20 +145,20 @@ export class HashMap extends Map return true; } - has(key: K) { - const $this = __private.get(this); + has(key: K): boolean { + const $this = __private.get(this)!; const i = this.find(key, $this); return i >= 0 && $this.bins[i] != undefined; } - get(key: K, notFound?: V) { - const $this = __private.get(this); + get(key: K, notFound?: V): V | undefined { + const $this = __private.get(this)!; const i = this.find(key, $this); return i >= 0 && $this.bins[i] ? $this.bins[i][1] : notFound; } set(key: K, val: V) { - const $this = __private.get(this); + const $this = __private.get(this)!; let i = this.find(key, $this); if (i >= 0 && $this.bins[i]) { $this.bins[i][1] = val; @@ -174,7 +174,7 @@ export class HashMap extends Map } delete(key: K) { - const $this = __private.get(this); + const $this = __private.get(this)!; let i = this.find(key, $this); const bins = $this.bins; if (i >= 0 && !bins[i]) { @@ -185,7 +185,7 @@ export class HashMap extends Map let j = i; let k: number; while (true) { - bins[i] = undefined; + delete bins[i]; do { j = (j + 1) & m; if (!bins[j]) return true; @@ -210,8 +210,8 @@ export class HashMap extends Map return this; } - opts(overrides?: Partial>) { - const $this = __private.get(this); + opts(overrides?: Partial>): HashMapOpts { + const $this = __private.get(this)!; return >{ hash: $this.hash, equiv: $this.equiv, diff --git a/packages/associative/src/intersection.ts b/packages/associative/src/intersection.ts index c89cd44f14..8fe4431d74 100644 --- a/packages/associative/src/intersection.ts +++ b/packages/associative/src/intersection.ts @@ -14,15 +14,15 @@ import { empty } from "./utils"; export const intersection = (a: Set, b: Set, out?: Set): Set => { out = out || empty(a, Set); if (a === b) { - return into(out, a); + return into(out!, a); } if (b.size < a.size) { return intersection(b, a, out); } for (let i of b) { if (a.has(i)) { - out.add(i); + out!.add(i); } } - return out; + return out!; }; diff --git a/packages/associative/src/join.ts b/packages/associative/src/join.ts index 1f90e2358d..2614249218 100644 --- a/packages/associative/src/join.ts +++ b/packages/associative/src/join.ts @@ -1,4 +1,3 @@ -import { IObjectOf } from "@thi.ng/api"; import { commonKeysObj } from "./common-keys"; import { indexed } from "./indexed"; import { invertObj } from "./invert"; @@ -97,11 +96,11 @@ export const joinWith = ( ): Set => { if (a.size && b.size) { let aa: Set, bb: Set; - let k: IObjectOf; + let k: { [id in keyof A]?: keyof B }; if (a.size <= b.size) { aa = a; bb = b; - k = invertObj(kmap); + k = invertObj(kmap); } else { aa = b; bb = a; @@ -111,7 +110,7 @@ export const joinWith = ( const ks = Object.keys(k); const res: Set = empty(a, Set); for (let x of bb) { - const found = idx.get(renameKeysObj(selectKeysObj(x, ks), k)); + const found = idx.get(renameKeysObj(selectKeysObj(x, ks), k)); if (found) { for (let f of found) { res.add(mergeObj({ ...f }, x)); diff --git a/packages/associative/src/ll-set.ts b/packages/associative/src/ll-set.ts index 64d8b2e117..7a4a418c7e 100644 --- a/packages/associative/src/ll-set.ts +++ b/packages/associative/src/ll-set.ts @@ -25,7 +25,10 @@ const __private = new WeakMap, SetProps>(); * `IEquiv` interfaces itself. */ export class LLSet extends Set implements IEquivSet { - constructor(vals?: Iterable, opts: Partial> = {}) { + constructor( + vals?: Iterable | null, + opts: Partial> = {} + ) { super(); __private.set(this, { equiv: opts.equiv || equiv, @@ -35,7 +38,7 @@ export class LLSet extends Set implements IEquivSet { } *[Symbol.iterator](): IterableIterator { - yield* __private.get(this).vals; + yield* __private.get(this)!.vals; } get [Symbol.species]() { @@ -46,14 +49,14 @@ export class LLSet extends Set implements IEquivSet { return "LLSet"; } - get size() { - return __private.get(this).vals.length; + get size(): number { + return __private.get(this)!.vals.length; } copy() { - const $this = __private.get(this); + const $this = __private.get(this)!; const s = new LLSet(null, this.opts()); - __private.get(s).vals = $this.vals.copy(); + __private.get(s)!.vals = $this.vals.copy(); return s; } @@ -62,17 +65,17 @@ export class LLSet extends Set implements IEquivSet { } clear() { - __private.get(this).vals.clear(); + __private.get(this)!.vals.clear(); } - first() { + first(): T | undefined { if (this.size) { - return __private.get(this).vals.head.value; + return __private.get(this)!.vals.head!.value; } } add(x: T) { - !this.has(x) && __private.get(this).vals.push(x); + !this.has(x) && __private.get(this)!.vals.push(x); return this; } @@ -95,7 +98,7 @@ export class LLSet extends Set implements IEquivSet { * @param notFound */ get(x: T, notFound?: T): T | undefined { - const $this = __private.get(this); + const $this = __private.get(this)!; const eq = $this.equiv; let i = $this.vals.head; while (i) { @@ -108,7 +111,7 @@ export class LLSet extends Set implements IEquivSet { } delete(x: T) { - const $this = __private.get(this); + const $this = __private.get(this)!; const eq = $this.equiv; let i = $this.vals.head; while (i) { @@ -138,7 +141,7 @@ export class LLSet extends Set implements IEquivSet { if (this.size !== o.size) { return false; } - let i = __private.get(this).vals.head; + let i = __private.get(this)!.vals.head; while (i) { if (!o.has(i.value)) { return false; @@ -149,7 +152,7 @@ export class LLSet extends Set implements IEquivSet { } forEach(fn: Fn3, Readonly, Set, void>, thisArg?: any) { - let i = __private.get(this).vals.head; + let i = __private.get(this)!.vals.head; while (i) { fn.call(thisArg, i.value, i.value, this); i = i.next; @@ -157,13 +160,13 @@ export class LLSet extends Set implements IEquivSet { } *entries(): IterableIterator> { - for (let v of __private.get(this).vals) { + for (let v of __private.get(this)!.vals) { yield [v, v]; } } *keys(): IterableIterator { - yield* __private.get(this).vals; + yield* __private.get(this)!.vals; } *values(): IterableIterator { @@ -171,6 +174,6 @@ export class LLSet extends Set implements IEquivSet { } opts(): EquivSetOpts { - return { equiv: __private.get(this).equiv }; + return { equiv: __private.get(this)!.equiv }; } } diff --git a/packages/associative/src/merge-deep.ts b/packages/associative/src/merge-deep.ts index 735834718b..99130b28f4 100644 --- a/packages/associative/src/merge-deep.ts +++ b/packages/associative/src/merge-deep.ts @@ -2,7 +2,10 @@ import { IObjectOf } from "@thi.ng/api"; import { isPlainObject } from "@thi.ng/checks"; import { mergeObjWith } from "./merge-with"; -export const mergeDeepObj = (dest: IObjectOf, ...xs: IObjectOf[]) => +export const mergeDeepObj = ( + dest: IObjectOf, + ...xs: IObjectOf[] +): any => mergeObjWith( (a, b) => isPlainObject(a) && isPlainObject(b) ? mergeDeepObj(a, b) : b, diff --git a/packages/associative/src/merge-with.ts b/packages/associative/src/merge-with.ts index c876db26c4..35d52d8af8 100644 --- a/packages/associative/src/merge-with.ts +++ b/packages/associative/src/merge-with.ts @@ -9,7 +9,7 @@ export const mergeMapWith = ( const res: Map = copy(dest, Map); for (let x of xs) { for (let [k, v] of x) { - res.set(k, res.has(k) ? f(res.get(k), v) : v); + res.set(k, res.has(k) ? f(res.get(k)!, v) : v); } } return res; diff --git a/packages/associative/src/rename-keys.ts b/packages/associative/src/rename-keys.ts index ddb0aac22b..31fbb25855 100644 --- a/packages/associative/src/rename-keys.ts +++ b/packages/associative/src/rename-keys.ts @@ -15,7 +15,7 @@ export const renameKeysMap = ( ) => { out = out || empty(src, Map); for (let [k, v] of src) { - out.set(km.has(k) ? km.get(k) : k, v); + out!.set(km.has(k) ? km.get(k)! : k, v); } return out; }; diff --git a/packages/associative/src/select-keys.ts b/packages/associative/src/select-keys.ts index 05e6952703..cf24a0a213 100644 --- a/packages/associative/src/select-keys.ts +++ b/packages/associative/src/select-keys.ts @@ -25,13 +25,13 @@ export const selectKeysMap = ( * @param src * @param ks */ -export const selectKeysObj = ( +export const selectKeysObj = ( src: T, ks: Iterable ): { [id in keyof T]?: T[id] } => { const dest: any = {}; for (let k of ks) { - src.hasOwnProperty(k) && (dest[k] = src[k]); + src.hasOwnProperty(k) && (dest[k] = (src)[k]); } return dest; }; diff --git a/packages/associative/src/sorted-map.ts b/packages/associative/src/sorted-map.ts index e06eefd25e..ffb88e8c04 100644 --- a/packages/associative/src/sorted-map.ts +++ b/packages/associative/src/sorted-map.ts @@ -21,11 +21,11 @@ interface SortedMapState { } class Node { - k: K; - v: V; + k: K | null; + v: V | null; next: Node[]; - constructor(k: K, v: V, h: number) { + constructor(k: K | null, v: V | null, h: number) { this.k = k; this.v = v; this.next = new Array(h + 1); @@ -46,9 +46,9 @@ export class SortedMap extends Map { */ static fromObject( obj: IObjectOf, - opts?: Partial> - ): SortedMap { - const m = new SortedMap(null, { + opts?: Partial> + ): SortedMap { + const m = new SortedMap(null, { capacity: Object.keys(obj).length, ...opts }); @@ -69,7 +69,7 @@ export class SortedMap extends Map { * @param opts */ constructor( - pairs?: Iterable>, + pairs?: Iterable> | null, opts: Partial> = {} ) { super(); @@ -94,17 +94,17 @@ export class SortedMap extends Map { } *[Symbol.iterator](): IterableIterator> { - let node = __private.get(this).head; + let node = __private.get(this)!.head; while ((node = node.next[0])) { yield [node.k, node.v]; } } *entries(key?: K, max = false): IterableIterator> { - const $this = __private.get(this); + const $this = __private.get(this)!; let node = $this.head; const cmp = $this.cmp; - let code: number; + let code: number | undefined; if (max) { while ((node = node.next[0])) { if (key === undefined || (code = cmp(node.k, key)) <= 0) { @@ -129,12 +129,12 @@ export class SortedMap extends Map { return map((p) => p[1], this.entries(key, max)); } - get size() { - return __private.get(this).length; + get size(): number { + return __private.get(this)!.length; } clear() { - const $this = __private.get(this); + const $this = __private.get(this)!; $this.head = new Node(null, null, 0); $this.length = 0; $this.h = 0; @@ -189,14 +189,14 @@ export class SortedMap extends Map { return true; } - first(): Pair { - const node = __private.get(this).head.next[0]; + first(): Pair | undefined { + const node = __private.get(this)!.head.next[0]; return node ? [node.k, node.v] : undefined; } get(k: K, notFound?: V): V | undefined { const node = this.findPredNode(k).next[0]; - return node && __private.get(this).cmp(node.k, k) === 0 + return node && __private.get(this)!.cmp(node.k, k) === 0 ? node.v : notFound; } @@ -206,12 +206,12 @@ export class SortedMap extends Map { } set(k: K, v: V) { - const $this = __private.get(this); + const $this = __private.get(this)!; let node = $this.head; let level = $this.h; let stack = new Array(level); const cmp = $this.cmp; - let code: number; + let code: number | undefined; while (level >= 0) { while ( node.next[level] && @@ -245,12 +245,12 @@ export class SortedMap extends Map { } delete(k: K) { - const $this = __private.get(this); + const $this = __private.get(this)!; let node: Node = $this.head; let level = $this.h; let removed = false; const cmp = $this.cmp; - let code: number; + let code: number | undefined; while (level >= 0) { while ( node.next[level] && @@ -292,7 +292,7 @@ export class SortedMap extends Map { } $reduce(rfn: ReductionFn>, acc: any) { - let node = __private.get(this).head; + let node = __private.get(this)!.head; while ((node = node.next[0]) && !isReduced(acc)) { acc = rfn(acc, [node.k, node.v]); } @@ -300,7 +300,7 @@ export class SortedMap extends Map { } opts(): SortedMapOpts { - const $this = __private.get(this); + const $this = __private.get(this)!; return { capacity: $this.cap, compare: $this.cmp, @@ -309,7 +309,7 @@ export class SortedMap extends Map { } protected findPredNode(k: K) { - const $this = __private.get(this); + const $this = __private.get(this)!; const cmp = $this.cmp; let node = $this.head; let level = $this.h; diff --git a/packages/associative/src/sorted-set.ts b/packages/associative/src/sorted-set.ts index 30d16deeab..aaca4c4fcb 100644 --- a/packages/associative/src/sorted-set.ts +++ b/packages/associative/src/sorted-set.ts @@ -31,7 +31,7 @@ export class SortedSet extends Set * @param values * @param opts */ - constructor(values?: Iterable, opts?: Partial>) { + constructor(values?: Iterable | null, opts?: Partial>) { super(); __private.set( this, @@ -54,8 +54,8 @@ export class SortedSet extends Set return "SortedSet"; } - get size() { - return __private.get(this).size; + get size(): number { + return __private.get(this)!.size; } copy(): SortedSet { @@ -104,24 +104,24 @@ export class SortedSet extends Set return true; } - $reduce(rfn: ReductionFn, acc: any) { - return __private.get(this).$reduce((_acc, x) => rfn(_acc, x[0]), acc); + $reduce(rfn: ReductionFn, acc: any): any { + return __private.get(this)!.$reduce((_acc, x) => rfn(_acc, x[0]), acc); } entries(key?: T, max = false): IterableIterator> { - return __private.get(this).entries(key, max); + return __private.get(this)!.entries(key, max); } keys(key?: T, max = false): IterableIterator { - return __private.get(this).keys(key, max); + return __private.get(this)!.keys(key, max); } values(key?: T, max = false): IterableIterator { - return __private.get(this).values(key, max); + return __private.get(this)!.values(key, max); } add(value: T) { - __private.get(this).set(value, value); + __private.get(this)!.set(value, value); return this; } @@ -133,16 +133,16 @@ export class SortedSet extends Set } clear(): void { - __private.get(this).clear(); + __private.get(this)!.clear(); } first(): T { - const first = __private.get(this).first(); + const first = __private.get(this)!.first(); return first ? first[0] : undefined; } delete(value: T): boolean { - return __private.get(this).delete(value); + return __private.get(this)!.delete(value); } disj(xs: Iterable) { @@ -157,19 +157,19 @@ export class SortedSet extends Set thisArg?: any ): void { for (let p of this) { - fn.call(thisArg, p[0], p[0], this); + fn.call(thisArg, p, p, this); } } has(value: T): boolean { - return __private.get(this).has(value); + return __private.get(this)!.has(value); } get(value: T, notFound?: T): T | undefined { - return __private.get(this).get(value, notFound); + return __private.get(this)!.get(value, notFound); } opts(): SortedSetOpts { - return __private.get(this).opts(); + return __private.get(this)!.opts(); } } diff --git a/packages/associative/src/sparse-set.ts b/packages/associative/src/sparse-set.ts index 5e66bd0501..af7e96e51b 100644 --- a/packages/associative/src/sparse-set.ts +++ b/packages/associative/src/sparse-set.ts @@ -37,16 +37,16 @@ export abstract class ASparseSet extends Set return this.keys(); } - get size() { - return __private.get(this).n; + get size(): number { + return __private.get(this)!.n; } get capacity() { - return __private.get(this).dense.length; + return __private.get(this)!.dense.length; } clear() { - __private.get(this).n = 0; + __private.get(this)!.n = 0; } equiv(o: any) { @@ -59,7 +59,7 @@ export abstract class ASparseSet extends Set if (this.size !== o.size) { return false; } - const $this = __private.get(this); + const $this = __private.get(this)!; const d = $this.dense; for (let i = $this.n; --i >= 0; ) { if (!o.has(d[i])) { @@ -70,7 +70,7 @@ export abstract class ASparseSet extends Set } add(k: number) { - const $this = __private.get(this); + const $this = __private.get(this)!; const dense = $this.dense; const sparse = $this.sparse; const max = dense.length; @@ -85,7 +85,7 @@ export abstract class ASparseSet extends Set } delete(k: number) { - const $this = __private.get(this); + const $this = __private.get(this)!; const dense = $this.dense; const sparse = $this.sparse; const i = sparse[k]; @@ -98,8 +98,8 @@ export abstract class ASparseSet extends Set return false; } - has(k: number) { - const $this = __private.get(this); + has(k: number): boolean { + const $this = __private.get(this)!; const i = $this.sparse[k]; return i < $this.n && $this.dense[i] === k; } @@ -109,7 +109,7 @@ export abstract class ASparseSet extends Set } first() { - const $this = __private.get(this); + const $this = __private.get(this)!; return $this.n ? $this.dense[0] : undefined; } @@ -128,7 +128,7 @@ export abstract class ASparseSet extends Set } forEach(fn: Fn3, void>, thisArg?: any) { - const $this = __private.get(this); + const $this = __private.get(this)!; const d = $this.dense; const n = $this.n; for (let i = 0; i < n; i++) { @@ -138,7 +138,7 @@ export abstract class ASparseSet extends Set } *entries(): IterableIterator> { - const $this = __private.get(this); + const $this = __private.get(this)!; const d = $this.dense; const n = $this.n; for (let i = 0; i < n; i++) { @@ -146,8 +146,8 @@ export abstract class ASparseSet extends Set } } - *keys() { - const $this = __private.get(this); + *keys(): IterableIterator { + const $this = __private.get(this)!; const d = $this.dense; const n = $this.n; for (let i = 0; i < n; i++) { @@ -160,8 +160,8 @@ export abstract class ASparseSet extends Set } protected __copy(c: ASparseSet) { - const $this = __private.get(this); - const $c = __private.get(c); + const $this = __private.get(this)!; + const $c = __private.get(c)!; $c.dense = $this.dense.slice(); $c.sparse = $this.sparse.slice(); $c.n = $this.n; @@ -175,8 +175,8 @@ export class SparseSet8 extends ASparseSet constructor(n: number | Uint8Array, sparse?: Uint8Array) { isNumber(n) ? super(new Uint8Array(n), new Uint8Array(n)) - : n.length === sparse.length - ? super(n, sparse) + : n.length === sparse!.length + ? super(n, sparse!) : fail(); } @@ -206,8 +206,8 @@ export class SparseSet16 extends ASparseSet constructor(n: number | Uint16Array, sparse?: Uint16Array) { isNumber(n) ? super(new Uint16Array(n), new Uint16Array(n)) - : n.length === sparse.length - ? super(n, sparse) + : n.length === sparse!.length + ? super(n, sparse!) : fail(); } @@ -237,8 +237,8 @@ export class SparseSet32 extends ASparseSet constructor(n: number | Uint32Array, sparse?: Uint32Array) { isNumber(n) ? super(new Uint32Array(n), new Uint32Array(n)) - : n.length === sparse.length - ? super(n, sparse) + : n.length === sparse!.length + ? super(n, sparse!) : fail(); } diff --git a/packages/associative/src/union.ts b/packages/associative/src/union.ts index 8cc548c1ba..24ff0bc694 100644 --- a/packages/associative/src/union.ts +++ b/packages/associative/src/union.ts @@ -11,5 +11,5 @@ import { copy } from "./utils"; */ export const union = (a: Set, b: Set, out?: Set): Set => { out = out ? into(out, a) : copy(a, Set); - return a === b ? out : into(out, b); + return a === b ? out! : into(out!, b); }; diff --git a/packages/associative/src/utils.ts b/packages/associative/src/utils.ts index d00f426bc3..9c7fc587a0 100644 --- a/packages/associative/src/utils.ts +++ b/packages/associative/src/utils.ts @@ -1,12 +1,12 @@ import { Pair } from "@thi.ng/api"; import { implementsFunction, isMap, isSet } from "@thi.ng/checks"; -export const empty = (x, ctor) => +export const empty = (x: any, ctor: Function) => implementsFunction(x, "empty") ? x.empty() : new (x[Symbol.species] || ctor)(); -export const copy = (x, ctor) => +export const copy = (x: any, ctor: Function) => implementsFunction(x, "copy") ? x.copy() : new (x[Symbol.species] || ctor)(x); diff --git a/packages/associative/test/difference.ts b/packages/associative/test/difference.ts index ef81b1662d..30f902e7c3 100644 --- a/packages/associative/test/difference.ts +++ b/packages/associative/test/difference.ts @@ -1,3 +1,4 @@ +import { equiv } from "@thi.ng/equiv"; import * as assert from "assert"; import { ArraySet } from "../src/array-set"; import { difference } from "../src/difference"; @@ -30,7 +31,7 @@ describe("difference", () => { const b = new ArraySet([{ a: 3 }, { a: 4 }, { a: 5 }]); const d = difference(a, b); assert.equal(d.size, 2); - assert.deepEqual(d, new Set([{ a: 1 }, { a: 2 }])); + assert(equiv(d, new ArraySet([{ a: 1 }, { a: 2 }]))); assert.notStrictEqual(d, a); assert.notStrictEqual(d, b); }); diff --git a/packages/associative/test/sparse-set.ts b/packages/associative/test/sparse-set.ts index 2862a5e4ee..739651d2ae 100644 --- a/packages/associative/test/sparse-set.ts +++ b/packages/associative/test/sparse-set.ts @@ -1,4 +1,5 @@ import { isSet } from "@thi.ng/checks"; +import { equiv } from "@thi.ng/equiv"; import * as assert from "assert"; import { SparseSet8 } from "../src"; @@ -25,24 +26,26 @@ describe("SparseSet", () => { }); it("add", () => { - assert.deepEqual( - set.into([1, 4, 3, 7, 9, 2, 0, 1, 2]), - new Set([0, 1, 2, 3, 4, 7]) + assert( + equiv( + set.into([1, 4, 3, 7, 9, 2, 0, 1, 2]), + new Set([0, 1, 2, 3, 4, 7]) + ) ); }); it("delete", () => { set.into([1, 4, 3, 7, 9, 2, 0, 1, 2]); assert(set.delete(4)); - assert.deepEqual(set, new Set([0, 1, 2, 3, 7])); + assert(equiv(set, new Set([0, 1, 2, 3, 7]))); assert(set.delete(0)); - assert.deepEqual(set, new Set([1, 2, 3, 7])); + assert(equiv(set, new Set([1, 2, 3, 7]))); assert(set.delete(7)); - assert.deepEqual(set, new Set([1, 2, 3])); + assert(equiv(set, new Set([1, 2, 3]))); assert(!set.delete(7)); assert(!set.delete(4)); set.add(4); - assert.deepEqual(set, new Set([1, 2, 3, 4])); + assert(equiv(set, new Set([1, 2, 3, 4]))); }); it("has", () => { diff --git a/packages/atom/CHANGELOG.md b/packages/atom/CHANGELOG.md index 863bde6595..5cd4e3b3cf 100644 --- a/packages/atom/CHANGELOG.md +++ b/packages/atom/CHANGELOG.md @@ -3,6 +3,29 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [3.0.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/atom@2.0.12...@thi.ng/atom@3.0.0) (2019-07-07) + + +### Code Refactoring + +* **atom:** TS strictNullChecks ([493ea57](https://github.com/thi-ng/umbrella/commit/493ea57)) + + +### Features + +* **atom:** enable TS strict compiler flags (refactor) ([c5d2853](https://github.com/thi-ng/umbrella/commit/c5d2853)) + + +### BREAKING CHANGES + +* **atom:** IView & IHistory methods can return undefined + +- Atom ctor requires an initial state now + + + + + ## [2.0.12](https://github.com/thi-ng/umbrella/compare/@thi.ng/atom@2.0.11...@thi.ng/atom@2.0.12) (2019-05-22) **Note:** Version bump only for package @thi.ng/atom diff --git a/packages/atom/package.json b/packages/atom/package.json index 4e4e803309..38958f6690 100644 --- a/packages/atom/package.json +++ b/packages/atom/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/atom", - "version": "2.0.12", + "version": "3.0.0", "description": "Mutable wrappers for nested immutable values w/ optional undo/redo history", "module": "./index.js", "main": "./lib/index.js", @@ -25,18 +25,18 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/api": "^6.2.0", - "@thi.ng/checks": "^2.1.6", - "@thi.ng/equiv": "^1.0.6", - "@thi.ng/errors": "^1.0.6", - "@thi.ng/paths": "^2.0.9" + "@thi.ng/api": "^6.3.0", + "@thi.ng/checks": "^2.2.0", + "@thi.ng/equiv": "^1.0.7", + "@thi.ng/errors": "^1.1.0", + "@thi.ng/paths": "^2.1.0" }, "keywords": [ "derived views", diff --git a/packages/atom/src/api.ts b/packages/atom/src/api.ts index a88ab6ee08..ba5425407a 100644 --- a/packages/atom/src/api.ts +++ b/packages/atom/src/api.ts @@ -30,11 +30,11 @@ export interface ISwap { swapIn(path: Path, fn: SwapFn, ...args: any[]): T; } -export interface IView extends IDeref, IID, IRelease { +export interface IView extends IDeref, IID, IRelease { readonly path: PropertyKey[]; - readonly value: T; + readonly value: T | undefined; - view(): T; + view(): T | undefined; changed(): boolean; } @@ -53,8 +53,8 @@ export interface IHistory extends IAtom, INotify { canUndo(): boolean; canRedo(): boolean; - undo(): T; - redo(): T; + undo(): T | undefined; + redo(): T | undefined; clear(): void; record(): void; diff --git a/packages/atom/src/atom.ts b/packages/atom/src/atom.ts index 26f3547313..f31cf9cd8e 100644 --- a/packages/atom/src/atom.ts +++ b/packages/atom/src/atom.ts @@ -21,10 +21,10 @@ import { View } from "./view"; @IWatchMixin export class Atom implements IAtom, IEquiv { protected _value: T; - protected valid: Predicate; + protected valid: Predicate | undefined; protected _watches: any; - constructor(val?: T, valid?: Predicate) { + constructor(val: T, valid?: Predicate) { if (valid && !valid(val)) { illegalState("initial state value did not validate"); } diff --git a/packages/atom/src/cursor.ts b/packages/atom/src/cursor.ts index 17996f1d15..f8a91a8b29 100644 --- a/packages/atom/src/cursor.ts +++ b/packages/atom/src/cursor.ts @@ -3,6 +3,7 @@ import { Fn2, IID, IRelease, + Predicate, Watch } from "@thi.ng/api"; import { isArray, isFunction } from "@thi.ng/checks"; @@ -49,7 +50,6 @@ export class Cursor implements IAtom, IID, IRelease { parent: IAtom; protected local: Atom; - protected lookup: Fn; protected selfUpdate: boolean; constructor(opts: CursorOpts); @@ -60,7 +60,12 @@ export class Cursor implements IAtom, IID, IRelease { update: Fn2 ); constructor(...args: any[]) { - let parent, id, lookup, update, validate, opts: CursorOpts; + let parent!: IAtom; + let lookup: Fn | undefined; + let update: Fn2 | undefined; + let validate: Predicate | undefined; + let opts: CursorOpts; + let id: string | undefined; switch (args.length) { case 1: opts = args[0]; @@ -69,7 +74,7 @@ export class Cursor implements IAtom, IID, IRelease { validate = opts.validate; if (opts.path) { if (isArray(opts.path) && isFunction(opts.path[0])) { - [lookup, update] = opts.path; + [lookup, update] = opts.path; } else { lookup = getter(opts.path); update = setter(opts.path); @@ -95,18 +100,18 @@ export class Cursor implements IAtom, IID, IRelease { if (!lookup || !update) { illegalArgs(); } - this.local = new Atom(lookup(parent.deref()), validate); + this.local = new Atom(lookup!(parent.deref()), validate); this.local.addWatch(this.id, (_, prev, curr) => { if (prev !== curr) { this.selfUpdate = true; - parent.swap((state) => update(state, curr)); + parent.swap((state) => update!(state, curr)); this.selfUpdate = false; } }); parent.addWatch(this.id, (_, prev, curr) => { if (!this.selfUpdate) { - const cval = lookup(curr); - if (cval !== lookup(prev)) { + const cval = lookup!(curr); + if (cval !== lookup!(prev)) { this.local.reset(cval); } } diff --git a/packages/atom/src/history.ts b/packages/atom/src/history.ts index 7d60296d13..81d663313e 100644 --- a/packages/atom/src/history.ts +++ b/packages/atom/src/history.ts @@ -40,8 +40,8 @@ export class History implements IHistory { maxLen: number; changed: Predicate2; - history: T[]; - future: T[]; + history!: T[]; + future!: T[]; /** * @param state parent state @@ -97,7 +97,7 @@ export class History implements IHistory { if (this.history.length) { const prev = this.state.deref(); this.future.push(prev); - const curr = this.state.reset(this.history.pop()); + const curr = this.state.reset(this.history.pop()!); this.notify({ id: History.EVENT_UNDO, value: { prev, curr } }); return curr; } @@ -121,7 +121,7 @@ export class History implements IHistory { if (this.future.length) { const prev = this.state.deref(); this.history.push(prev); - const curr = this.state.reset(this.future.pop()); + const curr = this.state.reset(this.future.pop()!); this.notify({ id: History.EVENT_REDO, value: { prev, curr } }); return curr; } @@ -202,7 +202,7 @@ export class History implements IHistory { if (n >= this.maxLen) { history.shift(); } - history.push(state); + history.push(state!); this.notify({ id: History.EVENT_RECORD, value: state }); this.future.length = 0; } diff --git a/packages/atom/src/view.ts b/packages/atom/src/view.ts index 3f0ac79a36..4f73d32d77 100644 --- a/packages/atom/src/view.ts +++ b/packages/atom/src/view.ts @@ -50,7 +50,7 @@ export class View implements IView { readonly parent: ReadonlyAtom; readonly path: PropertyKey[]; - protected state: T; + protected state: T | undefined; protected tx: ViewTransform; protected unprocessed: any; protected isDirty: boolean; diff --git a/packages/atom/test/cursor.ts b/packages/atom/test/cursor.ts index bd168fbada..5420ecdd42 100644 --- a/packages/atom/test/cursor.ts +++ b/packages/atom/test/cursor.ts @@ -3,11 +3,10 @@ import { getIn } from "@thi.ng/paths"; import * as assert from "assert"; import { Atom, Cursor } from "../src/index"; -describe("cursor", function () { - +describe("cursor", function() { let a: Atom; let c: Cursor; - let src; + let src: any; beforeEach(() => { src = { a: { b: { c: 23, g: { h: 88 } }, d: { e: 42 } }, f: 66 }; @@ -45,7 +44,11 @@ describe("cursor", function () { }); it("works with get/set", () => { - c = new Cursor(a, (s) => s.a.b, (s, x) => ({ ...s, a: { ...s.a, b: x } })); + c = new Cursor( + a, + (s) => s.a.b, + (s, x) => ({ ...s, a: { ...s.a, b: x } }) + ); assert.strictEqual(c.deref(), src.a.b); c.reset(42); assert.equal(c.deref(), 42); @@ -55,10 +58,7 @@ describe("cursor", function () { it("works with get/set opts", () => { c = new Cursor({ parent: a, - path: [ - (s) => s.a.b, - (s, x) => ({ ...s, a: { ...s.a, b: x } }) - ] + path: [(s) => s.a.b, (s, x) => ({ ...s, a: { ...s.a, b: x } })] }); assert.strictEqual(c.deref(), src.a.b); c.reset(42); @@ -70,17 +70,19 @@ describe("cursor", function () { c = new Cursor({ parent: a, path: "a.b.c", - validate: isNumber, + validate: isNumber }); assert.equal(c.reset(42), 42); assert.equal(c.reset("a"), 42); assert.equal(c.reset(null), 42); - assert.throws(() => new Cursor({ parent: a, path: "x", validate: isNumber })); - }) + assert.throws( + () => new Cursor({ parent: a, path: "x", validate: isNumber }) + ); + }); it("can be swapped'd (a.b.c)", () => { c = new Cursor(a, "a.b.c"); - assert.equal(c.swap(x => x + 1), src.a.b.c + 1); + assert.equal(c.swap((x) => x + 1), src.a.b.c + 1); assert.equal(c.deref(), src.a.b.c + 1); assert.equal(a.deref().a.b.c, src.a.b.c + 1); assert.strictEqual(a.deref().a.d, src.a.d); @@ -102,7 +104,7 @@ describe("cursor", function () { it("can update invalid path (x.y.z)", () => { c = new Cursor(a, "x.y.z"); - let add = (x) => x != null ? x + 1 : 0; + let add = (x: any) => (x != null ? x + 1 : 0); assert.equal(c.swap(add), 0); assert.equal(c.deref(), 0); assert.equal(c.swap(add), 1); @@ -132,10 +134,16 @@ describe("cursor", function () { it("can add & remove watch", () => { c = new Cursor(a, "a.b.c"); - assert.ok(c.addWatch("foo", () => { }), "can't add watch"); - assert.ok((c).local._watches && (c).local._watches.foo, "watch missing"); + assert.ok(c.addWatch("foo", () => {}), "can't add watch"); + assert.ok( + (c).local._watches && (c).local._watches.foo, + "watch missing" + ); assert.ok(c.removeWatch("foo"), "can't remove watch"); - assert.ok(!c.removeWatch("foo"), "should fail to remove invalid watch id"); + assert.ok( + !c.removeWatch("foo"), + "should fail to remove invalid watch id" + ); }); it("can be watched", () => { diff --git a/packages/atom/test/history.ts b/packages/atom/test/history.ts index 20a7e49732..cf05fd2757 100644 --- a/packages/atom/test/history.ts +++ b/packages/atom/test/history.ts @@ -4,9 +4,8 @@ import { Cursor } from "../src/cursor"; import { History } from "../src/history"; describe("history", () => { - let a: Atom; - let add = (x) => x + 1; + let add = (x: number) => x + 1; beforeEach(() => { a = new Atom({ a: 10, b: { c: 20, d: 30 }, e: 40 }); @@ -41,23 +40,31 @@ describe("history", () => { }); it("does record & shift (nested)", () => { - let c = new Cursor(a, "b"); + let c = new Cursor(a, "b"); let h = new History(c, 3); - h.swap(s => ({ ...s, c: 21 })); + h.swap((s) => ({ ...s, c: 21 })); assert.equal(h.history.length, 1); assert.deepEqual(h.history, [{ c: 20, d: 30 }]); - h.swap(s => ({ ...s, d: 31 })); + h.swap((s) => ({ ...s, d: 31 })); assert.equal(h.history.length, 2); assert.deepEqual(h.history, [{ c: 20, d: 30 }, { c: 21, d: 30 }]); - h.swap(s => ({ ...s, x: 100 })); + h.swap((s) => ({ ...s, x: 100 })); assert.equal(h.history.length, 3); - assert.deepEqual(h.history, [{ c: 20, d: 30 }, { c: 21, d: 30 }, { c: 21, d: 31 }]); + assert.deepEqual(h.history, [ + { c: 20, d: 30 }, + { c: 21, d: 30 }, + { c: 21, d: 31 } + ]); h.reset(null); assert.equal(h.history.length, 3); - assert.deepEqual(h.history, [{ c: 21, d: 30 }, { c: 21, d: 31 }, { c: 21, d: 31, x: 100 }]); + assert.deepEqual(h.history, [ + { c: 21, d: 30 }, + { c: 21, d: 31 }, + { c: 21, d: 31, x: 100 } + ]); h.clear(); assert.equal(h.history.length, 0); @@ -68,7 +75,7 @@ describe("history", () => { let h = new History(a, 3); h.reset(a.deref()); assert.equal(h.history.length, 0); - h.swap(s => s); + h.swap((s) => s); assert.equal(h.history.length, 0); }); @@ -130,5 +137,4 @@ describe("history", () => { h.reset(c.deref()); assert.equal(c.deref(), 24); }); - }); diff --git a/packages/bench/CHANGELOG.md b/packages/bench/CHANGELOG.md index 0fbc933ef4..b1aff7ea03 100644 --- a/packages/bench/CHANGELOG.md +++ b/packages/bench/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.0.7](https://github.com/thi-ng/umbrella/compare/@thi.ng/bench@1.0.6...@thi.ng/bench@1.0.7) (2019-07-07) + +**Note:** Version bump only for package @thi.ng/bench + + + + + ## [1.0.6](https://github.com/thi-ng/umbrella/compare/@thi.ng/bench@1.0.5...@thi.ng/bench@1.0.6) (2019-04-24) **Note:** Version bump only for package @thi.ng/bench diff --git a/packages/bench/package.json b/packages/bench/package.json index f08f2441fb..d8ebc8525a 100644 --- a/packages/bench/package.json +++ b/packages/bench/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/bench", - "version": "1.0.6", + "version": "1.0.7", "description": "Basic benchmarking helpers", "module": "./index.js", "main": "./lib/index.js", @@ -25,11 +25,11 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "keywords": [ "benchmark", diff --git a/packages/bencode/CHANGELOG.md b/packages/bencode/CHANGELOG.md index d5a55b78bc..5cb01df1f9 100644 --- a/packages/bencode/CHANGELOG.md +++ b/packages/bencode/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.3.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/bencode@0.2.17...@thi.ng/bencode@0.3.0) (2019-07-07) + + +### Features + +* **bencode:** enable TS strict compiler flags (refactor) ([1be1a14](https://github.com/thi-ng/umbrella/commit/1be1a14)) + + + + + ## [0.2.17](https://github.com/thi-ng/umbrella/compare/@thi.ng/bencode@0.2.16...@thi.ng/bencode@0.2.17) (2019-05-22) **Note:** Version bump only for package @thi.ng/bencode diff --git a/packages/bencode/package.json b/packages/bencode/package.json index 89052a30c7..d320fe8b11 100644 --- a/packages/bencode/package.json +++ b/packages/bencode/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/bencode", - "version": "0.2.17", + "version": "0.3.0", "description": "Bencode binary encoder / decoder with optional UTF8 encoding", "module": "./index.js", "main": "./lib/index.js", @@ -25,20 +25,20 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/api": "^6.2.0", - "@thi.ng/arrays": "^0.1.9", - "@thi.ng/checks": "^2.1.6", - "@thi.ng/defmulti": "^1.0.9", - "@thi.ng/errors": "^1.0.6", - "@thi.ng/transducers": "^5.3.7", - "@thi.ng/transducers-binary": "^0.3.12" + "@thi.ng/api": "^6.3.0", + "@thi.ng/arrays": "^0.2.0", + "@thi.ng/checks": "^2.2.0", + "@thi.ng/defmulti": "^1.1.0", + "@thi.ng/errors": "^1.1.0", + "@thi.ng/transducers": "^5.4.0", + "@thi.ng/transducers-binary": "^0.4.0" }, "keywords": [ "bencode", diff --git a/packages/bencode/src/index.ts b/packages/bencode/src/index.ts index 895c314601..a6ab6d0231 100644 --- a/packages/bencode/src/index.ts +++ b/packages/bencode/src/index.ts @@ -9,7 +9,7 @@ import { isString } from "@thi.ng/checks"; import { defmulti } from "@thi.ng/defmulti"; -import { illegalState } from "@thi.ng/errors"; +import { illegalState, unsupported } from "@thi.ng/errors"; import { mapcat } from "@thi.ng/transducers"; import { BinStructItem, @@ -63,7 +63,7 @@ const encodeBin = defmulti( ? Type.LIST : isPlainObject(x) ? Type.DICT - : undefined + : unsupported(`unsupported data type: ${x}`) ); encodeBin.addAll({ @@ -131,10 +131,10 @@ export const decode = (buf: Iterable, utf8 = true) => { const parent = peek(stack); if (parent) { if (parent.type === Type.LIST) { - parent.val.push(x.val); + (parent.val).push(x.val); } else if (parent.type === Type.DICT) { - parent.val[parent.key] = x.val; - parent.key = null; + (parent.val)[(parent).key] = x.val; + (parent).key = null; } } else { return x.val; @@ -145,7 +145,10 @@ export const decode = (buf: Iterable, utf8 = true) => { break; default: if (x >= Lit.ZERO && x <= Lit.NINE) { - x = readBytes(iter, readInt(iter, x - Lit.ZERO, Lit.COLON)); + x = readBytes( + iter, + readInt(iter, x - Lit.ZERO, Lit.COLON)! + ); x = collect(stack, x, utf8); if (x !== undefined) { return x; diff --git a/packages/bencode/test/index.ts b/packages/bencode/test/index.ts index 1bac80e7ef..4f161022eb 100644 --- a/packages/bencode/test/index.ts +++ b/packages/bencode/test/index.ts @@ -1,15 +1,17 @@ +import { equiv } from "@thi.ng/equiv"; import * as assert from "assert"; -import { encode, decode } from "../src/index"; +import { decode, encode } from "../src/index"; const src = { foo: [1, "a", { bar: "baz" }, [42.123]] }; const src2 = { foo: new Uint8Array([0, 1, 2, 3, 255, 254, 253]) }; +// prettier-ignore describe("bencode", () => { it("roundtrip (utf8)", () => { let bytes; assert.deepEqual( - bytes = encode(src), + bytes = [...encode(src)], [ 0x64, 0x33, 0x3a, 0x66, 0x6f, 0x6f, 0x6c, 0x69, 0x31, 0x65, 0x31, 0x3a, 0x61, 0x64, 0x33, 0x3a, 0x62, 0x61, 0x72, 0x33, 0x3a, 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x66, 0x34, 0x32, 0x2e, 0x31, 0x32, @@ -22,10 +24,12 @@ describe("bencode", () => { it("roundtrip (raw)", () => { let bytes; - assert.deepEqual( - bytes = encode(src2), - [0x64, 0x33, 0x3a, 0x66, 0x6f, 0x6f, 0x37, 0x3a, 0x00, 0x01, 0x02, 0x03, 0xff, 0xfe, 0xfd, 0x65] + assert( + equiv( + bytes = encode(src2), + [0x64, 0x33, 0x3a, 0x66, 0x6f, 0x6f, 0x37, 0x3a, 0x00, 0x01, 0x02, 0x03, 0xff, 0xfe, 0xfd, 0x65] + ) ) - assert.deepEqual(decode(bytes, false), src2); + assert(equiv(decode(bytes, false), src2)); }); }); diff --git a/packages/binary/CHANGELOG.md b/packages/binary/CHANGELOG.md index f87af433e8..2bff605dbe 100644 --- a/packages/binary/CHANGELOG.md +++ b/packages/binary/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.0.7](https://github.com/thi-ng/umbrella/compare/@thi.ng/binary@1.0.6...@thi.ng/binary@1.0.7) (2019-07-07) + +**Note:** Version bump only for package @thi.ng/binary + + + + + ## [1.0.6](https://github.com/thi-ng/umbrella/compare/@thi.ng/binary@1.0.5...@thi.ng/binary@1.0.6) (2019-04-24) **Note:** Version bump only for package @thi.ng/binary diff --git a/packages/binary/package.json b/packages/binary/package.json index dc0cee67da..add0b6061c 100644 --- a/packages/binary/package.json +++ b/packages/binary/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/binary", - "version": "1.0.6", + "version": "1.0.7", "description": "Assorted binary / bitwise operations, conversions, utilities.", "module": "./index.js", "main": "./lib/index.js", @@ -25,11 +25,11 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "keywords": [ "alignment", diff --git a/packages/bitfield/CHANGELOG.md b/packages/bitfield/CHANGELOG.md index 1021a50ed2..e8b60aa76f 100644 --- a/packages/bitfield/CHANGELOG.md +++ b/packages/bitfield/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.1.9](https://github.com/thi-ng/umbrella/compare/@thi.ng/bitfield@0.1.8...@thi.ng/bitfield@0.1.9) (2019-07-07) + +**Note:** Version bump only for package @thi.ng/bitfield + + + + + ## [0.1.8](https://github.com/thi-ng/umbrella/compare/@thi.ng/bitfield@0.1.7...@thi.ng/bitfield@0.1.8) (2019-05-22) **Note:** Version bump only for package @thi.ng/bitfield diff --git a/packages/bitfield/package.json b/packages/bitfield/package.json index 1e1ec62b55..5b321c669c 100644 --- a/packages/bitfield/package.json +++ b/packages/bitfield/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/bitfield", - "version": "0.1.8", + "version": "0.1.9", "description": "1D / 2D bit field implementations", "module": "./index.js", "main": "./lib/index.js", @@ -25,16 +25,16 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/api": "^6.2.0", - "@thi.ng/binary": "^1.0.6", - "@thi.ng/strings": "^1.1.3" + "@thi.ng/api": "^6.3.0", + "@thi.ng/binary": "^1.0.7", + "@thi.ng/strings": "^1.2.0" }, "keywords": [ "1D", diff --git a/packages/bitstream/CHANGELOG.md b/packages/bitstream/CHANGELOG.md index 05b39b3aad..3dc7b14b14 100644 --- a/packages/bitstream/CHANGELOG.md +++ b/packages/bitstream/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.1.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/bitstream@1.0.6...@thi.ng/bitstream@1.1.0) (2019-07-07) + + +### Features + +* **bitstream:** enable TS strict compiler flags (refactor) ([ab18310](https://github.com/thi-ng/umbrella/commit/ab18310)) + + + + + ## [1.0.6](https://github.com/thi-ng/umbrella/compare/@thi.ng/bitstream@1.0.5...@thi.ng/bitstream@1.0.6) (2019-04-24) **Note:** Version bump only for package @thi.ng/bitstream diff --git a/packages/bitstream/package.json b/packages/bitstream/package.json index c4e1f977ab..97c0305b95 100644 --- a/packages/bitstream/package.json +++ b/packages/bitstream/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/bitstream", - "version": "1.0.6", + "version": "1.1.0", "description": "ES6 iterator based read/write bit streams & support for variable word widths", "module": "./index.js", "main": "./lib/index.js", @@ -24,15 +24,15 @@ "pub": "yarn build && yarn publish --access public" }, "dependencies": { - "@thi.ng/errors": "^1.0.6" + "@thi.ng/errors": "^1.1.0" }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "keywords": [ "binary", diff --git a/packages/bitstream/src/input.ts b/packages/bitstream/src/input.ts index 566485ebb7..7c0c67aa22 100644 --- a/packages/bitstream/src/input.ts +++ b/packages/bitstream/src/input.ts @@ -5,10 +5,10 @@ const U32 = Math.pow(2, 32); export class BitInputStream { buffer: Uint8Array; protected start: number; - protected pos: number; protected limit: number; - protected bit: number; - protected bitPos: number; + protected pos!: number; + protected bitPos!: number; + protected bit!: number; constructor(buffer: Uint8Array, offset = 0, limit = buffer.length << 3) { this.buffer = buffer; @@ -49,7 +49,7 @@ export class BitInputStream { return this; } - read(wordSize = 1) { + read(wordSize = 1): number { if (wordSize > 32) { return this.read(wordSize - 32) * U32 + this.read(32); } else if (wordSize > 8) { @@ -82,7 +82,7 @@ export class BitInputStream { } readStruct(fields: ([string, number])[]) { - return fields.reduce((acc, [id, word]) => { + return fields.reduce((acc: any, [id, word]) => { return (acc[id] = this.read(word)), acc; }, {}); } @@ -102,7 +102,7 @@ export class BitInputStream { protected _read(wordSize: number) { this.checkLimit(wordSize); let l = this.bit - wordSize, - out; + out: number; if (l >= 0) { this.bit = l; out = (this.buffer[this.pos] >>> l) & ((1 << wordSize) - 1); diff --git a/packages/bitstream/src/output.ts b/packages/bitstream/src/output.ts index 99a0683049..8ea0a5c753 100644 --- a/packages/bitstream/src/output.ts +++ b/packages/bitstream/src/output.ts @@ -7,9 +7,9 @@ const U32 = Math.pow(2, 32); export class BitOutputStream { buffer: Uint8Array; protected start: number; - protected pos: number; - protected bit: number; - protected bitPos: number; + protected pos!: number; + protected bit!: number; + protected bitPos!: number; constructor(buffer?: number | Uint8Array, offset = 0) { this.buffer = diff --git a/packages/bitstream/test/index.ts b/packages/bitstream/test/index.ts index da632c1d66..a16f075801 100644 --- a/packages/bitstream/test/index.ts +++ b/packages/bitstream/test/index.ts @@ -1,28 +1,43 @@ import * as assert from "assert"; import * as bits from "../src/index"; -describe("BitInputStream", function () { - let src = new Uint8Array([0xbe, 0xef, 0xde, 0xca, 0xfb, 0xad, 0xf0, 0x0b, 0xaa]); +describe("BitInputStream", function() { + let src = new Uint8Array([ + 0xbe, + 0xef, + 0xde, + 0xca, + 0xfb, + 0xad, + 0xf0, + 0x0b, + 0xaa + ]); it("iterator", () => { assert.equal( [...new bits.BitInputStream(src)].join(""), "101111101110111111011110110010101111101110101101111100000000101110101010", - "all"); + "all" + ); assert.equal( [...new bits.BitInputStream(src, 0, 18)].join(""), "101111101110111111", - "0-18"); + "0-18" + ); assert.equal( [...new bits.BitInputStream(src, 49)].join(""), "11100000000101110101010", - "49-..."); + "49-..." + ); assert.equal( [...new bits.BitInputStream(src, 49, 49 + 12)].join(""), "111000000001", - "49+12"); + "49+12" + ); assert.throws( () => new bits.BitInputStream(new Uint8Array(0)), - "empty input"); + "empty input" + ); }); it("read", () => { let i = new bits.BitInputStream(src); @@ -49,10 +64,12 @@ describe("BitInputStream", function () { }); it("mapBitfields", () => { assert.deepStrictEqual( - new bits.BitInputStream(src).readFields([4, 8, 1, 3, 44, 5, 7]).map(x => x.toString(16)), + new bits.BitInputStream(src) + .readFields([4, 8, 1, 3, 44, 5, 7]) + .map((x) => x.toString(16)), ["b", "ee", "1", "7", "decafbadf00", "17", "2a"], "map hex" - ) + ); }); it("position", () => { let src = new Uint8Array(2); @@ -67,39 +84,40 @@ describe("BitInputStream", function () { }); }); +// prettier-ignore describe("BitOutputStream", function () { it("write", () => { let o = new bits.BitOutputStream(8); - assert.deepEqual(o.write(0xff, 1).buffer, [0x80, 0, 0, 0, 0, 0, 0, 0], "1"); - assert.deepEqual(o.write(0xff, 2).buffer, [0xe0, 0, 0, 0, 0, 0, 0, 0], "2"); - assert.deepEqual(o.write(0xff, 4).buffer, [0xfe, 0, 0, 0, 0, 0, 0, 0], "4"); - assert.deepEqual(o.write(0xff, 8).buffer, [0xff, 0xfe, 0, 0, 0, 0, 0, 0], "8"); - assert.deepEqual(o.write(0, 1).buffer, [0xff, 0xfe, 0, 0, 0, 0, 0, 0], "1 zero"); - assert.deepEqual(o.write(0xdecafbad, 16).buffer, [0xff, 0xfe, 0xfb, 0xad, 0, 0, 0, 0], "16"); - assert.deepEqual(o.write(0xdecafbad, 32).buffer.slice(0, 8), [0xff, 0xfe, 0xfb, 0xad, 0xde, 0xca, 0xfb, 0xad], "32"); + assert.deepEqual([...o.write(0xff, 1).buffer], [0x80, 0, 0, 0, 0, 0, 0, 0], "1"); + assert.deepEqual([...o.write(0xff, 2).buffer], [0xe0, 0, 0, 0, 0, 0, 0, 0], "2"); + assert.deepEqual([...o.write(0xff, 4).buffer], [0xfe, 0, 0, 0, 0, 0, 0, 0], "4"); + assert.deepEqual([...o.write(0xff, 8).buffer], [0xff, 0xfe, 0, 0, 0, 0, 0, 0], "8"); + assert.deepEqual([...o.write(0, 1).buffer], [0xff, 0xfe, 0, 0, 0, 0, 0, 0], "1 zero"); + assert.deepEqual([...o.write(0xdecafbad, 16).buffer], [0xff, 0xfe, 0xfb, 0xad, 0, 0, 0, 0], "16"); + assert.deepEqual([...o.write(0xdecafbad, 32).buffer.slice(0, 8)], [0xff, 0xfe, 0xfb, 0xad, 0xde, 0xca, 0xfb, 0xad], "32"); o = new bits.BitOutputStream(8, 4); - assert.deepEqual(o.write(0xf00baaf00b, 40).buffer, [0x0f, 0x0, 0xba, 0xaf, 0x00, 0xb0, 0, 0], "40"); + assert.deepEqual([...o.write(0xf00baaf00b, 40).buffer], [0x0f, 0x0, 0xba, 0xaf, 0x00, 0xb0, 0, 0], "40"); }); it("writeBit", () => { let o = new bits.BitOutputStream(1); - assert.deepEqual(o.writeBit(1).buffer, [0x80], "1"); - assert.deepEqual(o.writeBit(1).buffer, [0xc0], "2"); - assert.deepEqual(o.writeBit(1).buffer, [0xe0], "3"); - assert.deepEqual(o.writeBit(0).buffer, [0xe0], "4"); - assert.deepEqual(o.writeBit(1).buffer, [0xe8], "5"); - assert.deepEqual(o.writeBit(1).buffer, [0xec], "6"); - assert.deepEqual(o.writeBit(1).buffer, [0xee], "7"); - assert.deepEqual(o.writeBit(1).buffer, [0xef, 0x00], "8"); + assert.deepEqual([...o.writeBit(1).buffer], [0x80], "1"); + assert.deepEqual([...o.writeBit(1).buffer], [0xc0], "2"); + assert.deepEqual([...o.writeBit(1).buffer], [0xe0], "3"); + assert.deepEqual([...o.writeBit(0).buffer], [0xe0], "4"); + assert.deepEqual([...o.writeBit(1).buffer], [0xe8], "5"); + assert.deepEqual([...o.writeBit(1).buffer], [0xec], "6"); + assert.deepEqual([...o.writeBit(1).buffer], [0xee], "7"); + assert.deepEqual([...o.writeBit(1).buffer], [0xef, 0x00], "8"); assert.equal(o.buffer.length, 2, "len"); - assert.deepEqual(o.writeBit(1).buffer, [0xef, 0x80], "9"); - assert.deepEqual(o.seek(0).writeBit(0).buffer, [0x6f, 0x80], "seek 0"); - assert.deepEqual(o.seek(0).writeBit(1).buffer, [0xef, 0x80], "seek 0 1"); - assert.deepEqual(o.write(0, 4).buffer, [0x87, 0x80], "write 4"); + assert.deepEqual([...o.writeBit(1).buffer], [0xef, 0x80], "9"); + assert.deepEqual([...o.seek(0).writeBit(0).buffer], [0x6f, 0x80], "seek 0"); + assert.deepEqual([...o.seek(0).writeBit(1).buffer], [0xef, 0x80], "seek 0 1"); + assert.deepEqual([...o.write(0, 4).buffer], [0x87, 0x80], "write 4"); }); it("bytes", () => { - assert.deepEqual(new bits.BitOutputStream().bytes(), [], "empty"); - assert.deepEqual(new bits.BitOutputStream(1, 7).bytes(), [0], "7"); - assert.deepEqual(new bits.BitOutputStream(2, 8).bytes(), [0], "8"); - assert.deepEqual(new bits.BitOutputStream(2, 9).bytes(), [0, 0], "9"); + assert.deepEqual([...new bits.BitOutputStream().bytes()], [], "empty"); + assert.deepEqual([...new bits.BitOutputStream(1, 7).bytes()], [0], "7"); + assert.deepEqual([...new bits.BitOutputStream(2, 8).bytes()], [0], "8"); + assert.deepEqual([...new bits.BitOutputStream(2, 9).bytes()], [0, 0], "9"); }); -}); \ No newline at end of file +}); diff --git a/packages/cache/CHANGELOG.md b/packages/cache/CHANGELOG.md index 624929b793..8ae089bf6b 100644 --- a/packages/cache/CHANGELOG.md +++ b/packages/cache/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.0.20](https://github.com/thi-ng/umbrella/compare/@thi.ng/cache@1.0.19...@thi.ng/cache@1.0.20) (2019-07-07) + +**Note:** Version bump only for package @thi.ng/cache + + + + + ## [1.0.19](https://github.com/thi-ng/umbrella/compare/@thi.ng/cache@1.0.18...@thi.ng/cache@1.0.19) (2019-05-22) **Note:** Version bump only for package @thi.ng/cache diff --git a/packages/cache/package.json b/packages/cache/package.json index 6102f75c5e..d5e9530c35 100644 --- a/packages/cache/package.json +++ b/packages/cache/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/cache", - "version": "1.0.19", + "version": "1.0.20", "description": "In-memory cache implementations with ES6 Map-like API and different eviction strategies", "module": "./index.js", "main": "./lib/index.js", @@ -25,16 +25,16 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/api": "^6.2.0", - "@thi.ng/dcons": "^2.0.19", - "@thi.ng/transducers": "^5.3.7" + "@thi.ng/api": "^6.3.0", + "@thi.ng/dcons": "^2.1.0", + "@thi.ng/transducers": "^5.4.0" }, "keywords": [ "cache", diff --git a/packages/cache/src/lru.ts b/packages/cache/src/lru.ts index 2dbfe5adde..1c42b537b6 100644 --- a/packages/cache/src/lru.ts +++ b/packages/cache/src/lru.ts @@ -9,7 +9,10 @@ export class LRUCache implements ICache { protected opts: CacheOpts; protected _size: number; - constructor(pairs?: Iterable<[K, V]>, opts?: Partial>) { + constructor( + pairs?: Iterable<[K, V]> | null, + opts?: Partial> + ) { const _opts = >Object.assign( { maxlen: Infinity, @@ -112,7 +115,7 @@ export class LRUCache implements ICache { v: value, s: size }); - this.map.set(key, this.items.tail); + this.map.set(key, this.items.tail!); } } return value; diff --git a/packages/cache/src/mru.ts b/packages/cache/src/mru.ts index 3ba1e6bd39..e00213cb33 100644 --- a/packages/cache/src/mru.ts +++ b/packages/cache/src/mru.ts @@ -3,7 +3,10 @@ import { CacheEntry, CacheOpts } from "./api"; import { LRUCache } from "./lru"; export class MRUCache extends LRUCache { - constructor(pairs?: Iterable<[K, V]>, opts?: Partial>) { + constructor( + pairs?: Iterable<[K, V]> | null, + opts?: Partial> + ) { super(pairs, opts); } @@ -29,7 +32,7 @@ export class MRUCache extends LRUCache { v: value, s: size }); - this.map.set(key, this.items.head); + this.map.set(key, this.items.head!); } } return value; diff --git a/packages/cache/src/tlru.ts b/packages/cache/src/tlru.ts index c13b0c0466..e21940b3ee 100644 --- a/packages/cache/src/tlru.ts +++ b/packages/cache/src/tlru.ts @@ -22,11 +22,14 @@ export interface TLRUCacheEntry extends CacheEntry { * If no instance TTL is given, TTL defaults to 1 hour. */ export class TLRUCache extends LRUCache { - protected opts: TLRUCacheOpts; - protected map: Map>>; - protected items: DCons>; + protected opts!: TLRUCacheOpts; + protected map!: Map>>; + protected items!: DCons>; - constructor(pairs?: Iterable<[K, V]>, opts?: Partial>) { + constructor( + pairs?: Iterable<[K, V]> | null, + opts?: Partial> + ) { opts = Object.assign({ ttl: 60 * 60 * 1000 }, opts); super(pairs, opts); } @@ -71,7 +74,7 @@ export class TLRUCache extends LRUCache { s: size, t }); - this.map.set(key, this.items.tail); + this.map.set(key, this.items.tail!); } } return value; diff --git a/packages/checks/CHANGELOG.md b/packages/checks/CHANGELOG.md index 31ad912962..5935dfc8d3 100644 --- a/packages/checks/CHANGELOG.md +++ b/packages/checks/CHANGELOG.md @@ -3,6 +3,22 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [2.2.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/checks@2.1.6...@thi.ng/checks@2.2.0) (2019-07-07) + + +### Bug Fixes + +* **checks:** isMobile for Chrome iOS ([8216d48](https://github.com/thi-ng/umbrella/commit/8216d48)) + + +### Features + +* **checks:** enable TS strict compiler flags (refactor) ([90515e7](https://github.com/thi-ng/umbrella/commit/90515e7)) + + + + + ## [2.1.6](https://github.com/thi-ng/umbrella/compare/@thi.ng/checks@2.1.5...@thi.ng/checks@2.1.6) (2019-04-24) **Note:** Version bump only for package @thi.ng/checks diff --git a/packages/checks/package.json b/packages/checks/package.json index 771a6551c5..af61af96af 100644 --- a/packages/checks/package.json +++ b/packages/checks/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/checks", - "version": "2.1.6", + "version": "2.2.0", "description": "Single-function sub-modules for type, feature & value checks", "module": "./index.js", "main": "./lib/index.js", @@ -25,11 +25,11 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "keywords": [ "check", diff --git a/packages/checks/src/has-wasm.ts b/packages/checks/src/has-wasm.ts index fe0a72cc90..61402e6819 100644 --- a/packages/checks/src/has-wasm.ts +++ b/packages/checks/src/has-wasm.ts @@ -1,5 +1,5 @@ export const hasWASM = () => (typeof window !== "undefined" && - typeof window["WebAssembly"] !== "undefined") || + typeof (window)["WebAssembly"] !== "undefined") || (typeof global !== "undefined" && - typeof global["WebAssembly"] !== "undefined"); + typeof (global)["WebAssembly"] !== "undefined"); diff --git a/packages/checks/src/is-chrome.ts b/packages/checks/src/is-chrome.ts index a94e7020ca..cdd17b3797 100644 --- a/packages/checks/src/is-chrome.ts +++ b/packages/checks/src/is-chrome.ts @@ -1,2 +1,2 @@ export const isChrome = () => - typeof window !== "undefined" && !!window["chrome"]; + typeof window !== "undefined" && !!(window)["chrome"]; diff --git a/packages/checks/src/is-firefox.ts b/packages/checks/src/is-firefox.ts index 7eb6569d12..68a2ae5d53 100644 --- a/packages/checks/src/is-firefox.ts +++ b/packages/checks/src/is-firefox.ts @@ -1,2 +1,2 @@ export const isFirefox = () => - typeof window !== "undefined" && !!window["InstallTrigger"]; + typeof window !== "undefined" && !!(window)["InstallTrigger"]; diff --git a/packages/checks/src/is-ie.ts b/packages/checks/src/is-ie.ts index 664a2d8291..802b557d65 100644 --- a/packages/checks/src/is-ie.ts +++ b/packages/checks/src/is-ie.ts @@ -1,4 +1,4 @@ export const isIE = () => typeof document !== "undefined" && - (typeof document["documentMode"] !== "undefined" || + (typeof (document)["documentMode"] !== "undefined" || navigator.userAgent.indexOf("MSIE") > 0); diff --git a/packages/checks/src/is-mobile.ts b/packages/checks/src/is-mobile.ts index a8678e562f..3568663ff2 100644 --- a/packages/checks/src/is-mobile.ts +++ b/packages/checks/src/is-mobile.ts @@ -1,4 +1,3 @@ export const isMobile = () => typeof navigator !== "undefined" && - /mobile|tablet|ip(ad|hone|od)|android|silk/i.test(navigator.userAgent) && - !/crios/i.test(navigator.userAgent); + /mobile|tablet|ip(ad|hone|od)|android|silk|crios/i.test(navigator.userAgent); diff --git a/packages/checks/test/index.ts b/packages/checks/test/index.ts index 7e6b24f135..bab4eb88d9 100644 --- a/packages/checks/test/index.ts +++ b/packages/checks/test/index.ts @@ -19,7 +19,7 @@ describe("checks", function() { assert.ok(existsAndNotNull({}), "obj"); assert.ok(existsAndNotNull("[]"), "string"); assert.ok(existsAndNotNull(0), "zero"); - assert.ok(!existsAndNotNull({}["foobar"]), "prop"); + assert.ok(!existsAndNotNull(({})["foobar"]), "prop"); assert.ok(!existsAndNotNull(null), "null"); assert.ok(!existsAndNotNull(undefined), "null"); }); @@ -61,11 +61,11 @@ describe("checks", function() { assert.ok(!isArrayLike(0), "zero"); assert.ok(!isArrayLike(null), "null"); assert.ok(!isArrayLike(undefined), "null"); - assert.ok(!isArrayLike((x, y) => x + y), "null"); + assert.ok(!isArrayLike((x: any, y: any) => x + y), "null"); }); it("isObject", () => { - function Foo() {} + class Foo {} assert.ok(isObject([]), "empty array"); assert.ok(isObject(new Uint8Array(1)), "typedarray"); assert.ok(isObject({}), "obj"); @@ -81,13 +81,16 @@ describe("checks", function() { const ctxClass = vm.runInNewContext("class A {}; new A();"); const ctxObj = vm.runInNewContext("({})"); - function Foo() {} + class Foo {} assert.ok(isPlainObject({}), "obj"); assert.ok(isPlainObject(Object.create(null)), "obj"); assert.ok(isPlainObject(new Object()), "obj ctor"); assert.ok(!isPlainObject(Foo), "fn"); - assert.ok(!isPlainObject((function*() {})()), "generator"); + assert.ok( + !isPlainObject((function*(): IterableIterator {})()), + "generator" + ); assert.ok(!isPlainObject(new Foo()), "class"); assert.ok(!isPlainObject([]), "empty array"); assert.ok(!isPlainObject(new Uint8Array(1)), "typedarray"); @@ -111,7 +114,7 @@ describe("checks", function() { }); it("isFunction", () => { - assert.ok(isFunction((_) => null), "fn"); + assert.ok(isFunction((_: any) => {}), "fn"); assert.ok(isFunction(Uint8Array), "ctor"); assert.ok(isFunction("a".toString), "toString"); assert.ok(!isFunction("a"), "empty string"); diff --git a/packages/color/CHANGELOG.md b/packages/color/CHANGELOG.md index e313f70087..06c5c8c108 100644 --- a/packages/color/CHANGELOG.md +++ b/packages/color/CHANGELOG.md @@ -3,6 +3,18 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.2.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/color@0.1.21...@thi.ng/color@0.2.0) (2019-07-07) + + +### Features + +* **color:** enable TS strict compiler flags (refactor) ([8c13166](https://github.com/thi-ng/umbrella/commit/8c13166)) +* **color:** TS strictNullChecks, update color conversion fns ([04dc356](https://github.com/thi-ng/umbrella/commit/04dc356)) + + + + + ## [0.1.21](https://github.com/thi-ng/umbrella/compare/@thi.ng/color@0.1.20...@thi.ng/color@0.1.21) (2019-05-22) **Note:** Version bump only for package @thi.ng/color diff --git a/packages/color/package.json b/packages/color/package.json index fd82884d1c..a0d2d4aa39 100644 --- a/packages/color/package.json +++ b/packages/color/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/color", - "version": "0.1.21", + "version": "0.2.0", "description": "Raw, array-based, color ops, conversions, opt. type wrappers, multi-color gradients", "module": "./index.js", "main": "./lib/index.js", @@ -25,21 +25,21 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/api": "^6.2.0", - "@thi.ng/compose": "^1.2.5", - "@thi.ng/defmulti": "^1.0.9", - "@thi.ng/errors": "^1.0.6", - "@thi.ng/math": "^1.3.0", - "@thi.ng/strings": "^1.1.3", - "@thi.ng/transducers": "^5.3.7", - "@thi.ng/vectors": "^2.5.6" + "@thi.ng/api": "^6.3.0", + "@thi.ng/compose": "^1.3.0", + "@thi.ng/defmulti": "^1.1.0", + "@thi.ng/errors": "^1.1.0", + "@thi.ng/math": "^1.4.0", + "@thi.ng/strings": "^1.2.0", + "@thi.ng/transducers": "^5.4.0", + "@thi.ng/vectors": "^3.0.0" }, "keywords": [ "alpha", diff --git a/packages/color/src/alpha.ts b/packages/color/src/alpha.ts index 21c9025e3d..5232343e0b 100644 --- a/packages/color/src/alpha.ts +++ b/packages/color/src/alpha.ts @@ -4,5 +4,8 @@ import { Color, ReadonlyColor } from "./api"; export const alpha = (src: ReadonlyColor) => src[3] !== undefined ? src[3] : 1; -export const setAlpha = (out: Color, src: ReadonlyColor, alpha: number) => - setC4(out || src, src[0], src[1], src[2], alpha); +export const setAlpha = ( + out: Color | null, + src: ReadonlyColor, + alpha: number +) => setC4(out || src, src[0], src[1], src[2], alpha); diff --git a/packages/color/src/api.ts b/packages/color/src/api.ts index aa95c6b86c..a0e9ae1df1 100644 --- a/packages/color/src/api.ts +++ b/packages/color/src/api.ts @@ -4,33 +4,19 @@ import { ReadonlyVec, Vec } from "@thi.ng/vectors"; export type Color = Vec; export type ReadonlyColor = ReadonlyVec; +// prettier-ignore export type ColorMatrix = [ - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number, - number + number, number, number, number, number, + number, number, number, number, number, + number, number, number, number, number, + number, number, number, number, number, ]; export type CosCoeffs = [number, number, number, number]; export type CosGradientSpec = [CosCoeffs, CosCoeffs, CosCoeffs, CosCoeffs]; export type ColorConversion = (out: Color, src: T) => Color; +export type ColorOp = (out: Color | null, src: ReadonlyColor) => Color; export const enum ColorMode { RGBA, diff --git a/packages/color/src/clamp.ts b/packages/color/src/clamp.ts index 94545bd3ee..d1ebcd7753 100644 --- a/packages/color/src/clamp.ts +++ b/packages/color/src/clamp.ts @@ -13,7 +13,7 @@ import { ensureHue } from "./internal/ensure-hue"; * @param src * @param alpha */ -export const clamp = (out: Color, src: ReadonlyColor, alpha = 1) => +export const clamp = (out: Color | null, src: ReadonlyColor, alpha = 1) => setC4( out || src, clamp01(src[0]), @@ -30,7 +30,7 @@ export const clamp = (out: Color, src: ReadonlyColor, alpha = 1) => * @param src * @param alpha */ -export const clampH = (out: Color, src: ReadonlyColor, alpha = 1) => +export const clampH = (out: Color | null, src: ReadonlyColor, alpha = 1) => setC4( out || src, ensureHue(src[0]), diff --git a/packages/color/src/convert.ts b/packages/color/src/convert.ts index efa7046b5d..c93a951dde 100644 --- a/packages/color/src/convert.ts +++ b/packages/color/src/convert.ts @@ -1,7 +1,7 @@ import { DEFAULT, defmulti, - Implementation3, + Implementation2O, MultiFn2O } from "@thi.ng/defmulti"; import { illegalArgs } from "@thi.ng/errors"; @@ -39,20 +39,17 @@ export const convert: MultiFn2O< ColorMode, ColorMode, Color | string | number -> = defmulti( - (col: any, mdest, msrc) => - col.mode !== undefined - ? `${mdest}-${col.mode}` - : msrc !== undefined - ? `${mdest}-${msrc}` - : illegalArgs(`missing src color mode`) +> = defmulti((col: any, mdest, msrc) => + col.mode !== undefined + ? `${mdest}-${col.mode}` + : msrc !== undefined + ? `${mdest}-${msrc}` + : illegalArgs(`missing src color mode`) ); -convert.add( - DEFAULT, - (col: any, mdest, msrc) => - (col.mode !== undefined && col.mode === mdest) || mdest === msrc - ? col - : illegalArgs(`missing conversion for mode ${msrc} -> ${mdest}`) +convert.add(DEFAULT, (col: any, mdest, msrc) => + (col.mode !== undefined && col.mode === mdest) || mdest === msrc + ? col + : illegalArgs(`missing conversion for mode ${msrc} -> ${mdest}`) ); export function asCSS(col: IColor): string; @@ -130,8 +127,8 @@ export function asYCbCrA(col: any, mode?: ColorMode) { const defConversion = ( dest: ColorMode, src: ColorMode, - impl: Implementation3< - string | number | ReadonlyColor, + impl: Implementation2O< + string | number | ReadonlyColor | IColor, ColorMode, ColorMode, Color | string | number @@ -153,7 +150,7 @@ const defConversions = ( // CSS -defConversion(ColorMode.RGBA, ColorMode.CSS, (x: string) => parseCss(x)); +defConversion(ColorMode.RGBA, ColorMode.CSS, (x: any) => parseCss(x)); [ ColorMode.HCYA, @@ -164,7 +161,7 @@ defConversion(ColorMode.RGBA, ColorMode.CSS, (x: string) => parseCss(x)); ColorMode.XYZA, ColorMode.YCBCRA ].forEach((id) => - defConversion(id, ColorMode.CSS, (x: string) => + defConversion(id, ColorMode.CSS, (x: any) => convert(parseCss(x), id, ColorMode.RGBA) ) ); @@ -182,7 +179,7 @@ defConversions( ColorMode.YCBCRA ); -defConversion(ColorMode.CSS, ColorMode.INT32, (x: number) => int32Css(x)); +defConversion(ColorMode.CSS, ColorMode.INT32, (x: any) => int32Css(x)); // HCYA @@ -223,11 +220,9 @@ defConversions( ColorMode.YCBCRA ); -defConversion(ColorMode.CSS, ColorMode.HSLA, (x: ReadonlyColor) => hslaCss(x)); +defConversion(ColorMode.CSS, ColorMode.HSLA, (x: any) => hslaCss(x)); -defConversion(ColorMode.HSVA, ColorMode.HSLA, (x: ReadonlyColor) => - hslaHsva([], x) -); +defConversion(ColorMode.HSVA, ColorMode.HSLA, (x: any) => hslaHsva([], x)); // HSVA @@ -241,30 +236,26 @@ defConversions( ColorMode.YCBCRA ); -defConversion(ColorMode.CSS, ColorMode.HSVA, (x: ReadonlyColor) => hsvaCss(x)); +defConversion(ColorMode.CSS, ColorMode.HSVA, (x: any) => hsvaCss(x)); -defConversion(ColorMode.HSLA, ColorMode.HSVA, (x: ReadonlyColor) => - hsvaHsla([], x) -); +defConversion(ColorMode.HSLA, ColorMode.HSVA, (x: any) => hsvaHsla([], x)); // RGBA -[ +(<[ColorMode, ColorConversion][]>[ [ColorMode.HCYA, rgbaHcya], [ColorMode.HSIA, rgbaHsia], [ColorMode.HSLA, rgbaHsla], [ColorMode.HSVA, rgbaHsva], [ColorMode.XYZA, rgbaXyza], [ColorMode.YCBCRA, rgbaYcbcra] -].forEach(([id, fn]: [ColorMode, ColorConversion]) => - defConversion(id, ColorMode.RGBA, (x: ReadonlyColor) => fn([], x)) +]).forEach(([id, fn]) => + defConversion(id, ColorMode.RGBA, (x: any) => fn([], x)) ); -defConversion(ColorMode.CSS, ColorMode.RGBA, (x: ReadonlyColor) => rgbaCss(x)); +defConversion(ColorMode.CSS, ColorMode.RGBA, (x: any) => rgbaCss(x)); -defConversion(ColorMode.INT32, ColorMode.RGBA, (x: ReadonlyColor) => - rgbaInt(x) -); +defConversion(ColorMode.INT32, ColorMode.RGBA, (x: any) => rgbaInt(x)); // XYZA diff --git a/packages/color/src/hcya-rgba.ts b/packages/color/src/hcya-rgba.ts index 011306c55a..b88f363ede 100644 --- a/packages/color/src/hcya-rgba.ts +++ b/packages/color/src/hcya-rgba.ts @@ -1,10 +1,10 @@ import { clamp01 } from "@thi.ng/math"; import { dot3, setC3 } from "@thi.ng/vectors"; -import { Color, ReadonlyColor, RGB_LUMINANCE } from "./api"; +import { ColorOp, RGB_LUMINANCE } from "./api"; import { hueRgba } from "./hue-rgba"; import { ensureAlpha } from "./internal/ensure-alpha"; -export const hcyaRgba = (out: Color, src: ReadonlyColor) => { +export const hcyaRgba: ColorOp = (out, src) => { const h = src[0]; let c = src[1]; const y = src[2]; diff --git a/packages/color/src/hcya.ts b/packages/color/src/hcya.ts index 1a731b36a4..e97c7513a7 100644 --- a/packages/color/src/hcya.ts +++ b/packages/color/src/hcya.ts @@ -1,4 +1,4 @@ -import { IVector, declareIndices } from "@thi.ng/vectors"; +import { declareIndices, IVector } from "@thi.ng/vectors"; import { Color, ColorMode } from "./api"; import { AColor } from "./internal/acolor"; import { ensureArgs } from "./internal/ensure-args"; @@ -10,10 +10,10 @@ export function hcya(...args: any[]) { } export class HCYA extends AColor implements IVector { - h: number; - c: number; - y: number; - a: number; + h!: number; + c!: number; + y!: number; + a!: number; get mode() { return ColorMode.HCYA; diff --git a/packages/color/src/hsia-rgba.ts b/packages/color/src/hsia-rgba.ts index ec2632b4fb..1d1d6e0c10 100644 --- a/packages/color/src/hsia-rgba.ts +++ b/packages/color/src/hsia-rgba.ts @@ -1,10 +1,10 @@ import { setC3 } from "@thi.ng/vectors"; -import { Color, ReadonlyColor } from "./api"; +import { ColorOp } from "./api"; import { clampH } from "./clamp"; // https://en.wikipedia.org/wiki/HSL_and_HSV#From_HSI -export const hsiaRgba = (out: Color, src: ReadonlyColor) => { +export const hsiaRgba: ColorOp = (out, src) => { out = clampH(out || src, src); const s = out[1]; const i = out[2]; diff --git a/packages/color/src/hsia.ts b/packages/color/src/hsia.ts index c074d53968..f6e38eb240 100644 --- a/packages/color/src/hsia.ts +++ b/packages/color/src/hsia.ts @@ -10,10 +10,10 @@ export function hsia(...args: any[]) { } export class HSIA extends AColor implements IVector { - h: number; - s: number; - i: number; - a: number; + h!: number; + s!: number; + i!: number; + a!: number; get mode() { return ColorMode.HSIA; diff --git a/packages/color/src/hsla-hsva.ts b/packages/color/src/hsla-hsva.ts index 74078f7fd9..90901e274b 100644 --- a/packages/color/src/hsla-hsva.ts +++ b/packages/color/src/hsla-hsva.ts @@ -1,7 +1,7 @@ -import { Color, ReadonlyColor } from "./api"; +import { ColorOp } from "./api"; import { clampH } from "./clamp"; -export const hslaHsva = (out: Color, src: ReadonlyColor) => { +export const hslaHsva: ColorOp = (out, src) => { out = clampH(out || src, src); const s = out[1]; const l = out[2]; diff --git a/packages/color/src/hsla-rgba.ts b/packages/color/src/hsla-rgba.ts index 232d7d6eac..1374f30420 100644 --- a/packages/color/src/hsla-rgba.ts +++ b/packages/color/src/hsla-rgba.ts @@ -1,10 +1,10 @@ import { clamp01 } from "@thi.ng/math"; import { setC3 } from "@thi.ng/vectors"; -import { Color, ReadonlyColor } from "./api"; +import { ColorOp } from "./api"; import { hueRgba } from "./hue-rgba"; import { ensureAlpha } from "./internal/ensure-alpha"; -export const hslaRgba = (out: Color, src: ReadonlyColor) => { +export const hslaRgba: ColorOp = (out, src) => { const s = clamp01(src[1]); const l = clamp01(src[2]); out = hueRgba(out || src, src[0], ensureAlpha(src[3])); diff --git a/packages/color/src/hsla.ts b/packages/color/src/hsla.ts index 53325395d4..04a9b0cbb5 100644 --- a/packages/color/src/hsla.ts +++ b/packages/color/src/hsla.ts @@ -10,10 +10,10 @@ export function hsla(...args: any[]) { } export class HSLA extends AColor implements IVector { - h: number; - s: number; - l: number; - a: number; + h!: number; + s!: number; + l!: number; + a!: number; get mode() { return ColorMode.HSLA; diff --git a/packages/color/src/hsva-hsla.ts b/packages/color/src/hsva-hsla.ts index 284495ae26..f7251ca3b5 100644 --- a/packages/color/src/hsva-hsla.ts +++ b/packages/color/src/hsva-hsla.ts @@ -1,7 +1,7 @@ -import { ReadonlyColor, Color } from "./api"; +import { ColorOp } from "./api"; import { clampH } from "./clamp"; -export const hsvaHsla = (out: Color, src: ReadonlyColor) => { +export const hsvaHsla: ColorOp = (out, src) => { out = clampH(out || src, src); const s = out[1]; const v = out[2]; diff --git a/packages/color/src/hsva-rgba.ts b/packages/color/src/hsva-rgba.ts index 6c18a621a8..3de30f3f38 100644 --- a/packages/color/src/hsva-rgba.ts +++ b/packages/color/src/hsva-rgba.ts @@ -1,9 +1,9 @@ import { setC3 } from "@thi.ng/vectors"; -import { Color, ReadonlyColor } from "./api"; +import { ColorOp } from "./api"; import { clampH } from "./clamp"; import { hueRgba } from "./hue-rgba"; -export const hsvaRgba = (out: Color, src: ReadonlyColor) => { +export const hsvaRgba: ColorOp = (out, src) => { out = clampH(out || src, src); const s = out[1]; const v = out[2]; diff --git a/packages/color/src/hsva.ts b/packages/color/src/hsva.ts index 29c67d86ed..764a897c44 100644 --- a/packages/color/src/hsva.ts +++ b/packages/color/src/hsva.ts @@ -1,4 +1,4 @@ -import { IVector, declareIndices } from "@thi.ng/vectors"; +import { declareIndices, IVector } from "@thi.ng/vectors"; import { Color, ColorMode } from "./api"; import { AColor } from "./internal/acolor"; import { ensureArgs } from "./internal/ensure-args"; @@ -10,10 +10,10 @@ export function hsva(...args: any[]) { } export class HSVA extends AColor implements IVector { - h: number; - s: number; - v: number; - a: number; + h!: number; + s!: number; + v!: number; + a!: number; get mode() { return ColorMode.HSVA; diff --git a/packages/color/src/hue-rgba.ts b/packages/color/src/hue-rgba.ts index c663e42068..bad20f919e 100644 --- a/packages/color/src/hue-rgba.ts +++ b/packages/color/src/hue-rgba.ts @@ -10,10 +10,10 @@ import { ensureHue } from "./internal/ensure-hue"; * @param out * @param hue */ -export const hueRgba = (out: Color, hue: number, alpha = 1): Color => { +export const hueRgba = (out: Color | null, hue: number, alpha = 1): Color => { hue = ensureHue(hue) * 6; return setC4( - out, + out || [], clamp01(Math.abs(hue - 3) - 1), clamp01(2 - Math.abs(hue - 2)), clamp01(2 - Math.abs(hue - 4)), @@ -21,5 +21,5 @@ export const hueRgba = (out: Color, hue: number, alpha = 1): Color => { ); }; -export const namedHueRgba = (out: Color, hue: Hue, alpha = 1) => +export const namedHueRgba = (out: Color | null, hue: Hue, alpha = 1) => hueRgba(out, hue / 12, alpha); diff --git a/packages/color/src/int-rgba.ts b/packages/color/src/int-rgba.ts index 341524171d..d081b00511 100644 --- a/packages/color/src/int-rgba.ts +++ b/packages/color/src/int-rgba.ts @@ -2,7 +2,7 @@ import { IDeref } from "@thi.ng/api"; import { setC4 } from "@thi.ng/vectors"; import { Color, INV8BIT } from "./api"; -export const int32Rgba = (out: Color, src: number | IDeref) => { +export const int32Rgba = (out: Color | null, src: number | IDeref) => { src = typeof src === "number" ? src : src.deref(); return setC4( out || [], @@ -13,7 +13,7 @@ export const int32Rgba = (out: Color, src: number | IDeref) => { ); }; -export const int24Rgba = (out: Color, src: number | IDeref) => { +export const int24Rgba = (out: Color | null, src: number | IDeref) => { src = typeof src === "number" ? src : src.deref(); return int32Rgba(out, src | 0xff000000); }; diff --git a/packages/color/src/internal/acolor.ts b/packages/color/src/internal/acolor.ts index 01982039cb..00de8a7340 100644 --- a/packages/color/src/internal/acolor.ts +++ b/packages/color/src/internal/acolor.ts @@ -1,7 +1,7 @@ import { IDeref } from "@thi.ng/api"; import { EPS } from "@thi.ng/math"; import { eqDelta4, values } from "@thi.ng/vectors"; -import { Color, IColor } from "../api"; +import { Color, ColorMode, IColor } from "../api"; export abstract class AColor implements IColor, IDeref { buf: Color; @@ -19,7 +19,7 @@ export abstract class AColor implements IColor, IDeref { return values(this.buf, 4, this.offset, this.stride); } - abstract get mode(); + abstract get mode(): ColorMode; get length() { return 4; diff --git a/packages/color/src/internal/matrix-ops.ts b/packages/color/src/internal/matrix-ops.ts index 0a74362aa1..78dfab84df 100644 --- a/packages/color/src/internal/matrix-ops.ts +++ b/packages/color/src/internal/matrix-ops.ts @@ -5,7 +5,7 @@ import { Color, ColorMatrix, ReadonlyColor } from "../api"; import { ensureAlpha } from "./ensure-alpha"; export const mulV33 = ( - out: Color, + out: Color | null, mat: number[], src: ReadonlyColor, clampOut = true @@ -20,7 +20,7 @@ export const mulV33 = ( }; export const mulV45 = ( - out: Color, + out: Color | null, mat: ColorMatrix, src: ReadonlyColor, clampOut = true diff --git a/packages/color/src/invert.ts b/packages/color/src/invert.ts index 280371b21d..5a2d39d615 100644 --- a/packages/color/src/invert.ts +++ b/packages/color/src/invert.ts @@ -1,5 +1,5 @@ import { ONE3, sub3 } from "@thi.ng/vectors"; -import { Color, ReadonlyColor } from "./api"; +import { ColorOp } from "./api"; import { clamp } from "./clamp"; /** @@ -8,7 +8,7 @@ import { clamp } from "./clamp"; * @param out * @param src */ -export const invertRGB = (out: Color, src: ReadonlyColor) => ( +export const invertRGB: ColorOp = (out, src) => ( (out = clamp(out || src, src)), sub3(out, ONE3, out) ); diff --git a/packages/color/src/kelvin-rgba.ts b/packages/color/src/kelvin-rgba.ts index 94cc8a46a9..b5d5bcabcb 100644 --- a/packages/color/src/kelvin-rgba.ts +++ b/packages/color/src/kelvin-rgba.ts @@ -1,4 +1,6 @@ import { clamp01 } from "@thi.ng/math"; +import { setC4 } from "@thi.ng/vectors"; +import { Color } from "./api"; const G1 = -0.6088425710866344; const G2 = -0.001748900018414868; @@ -20,25 +22,28 @@ const B3 = 0.453646839257496; * * Uses adjusted coefficients to produce normalized RGB values. * + * @param out * @param kelvin color temperature * @param alpha target alpha channel */ -export const kelvinRgba = (kelvin: number, alpha = 1) => { +export const kelvinRgba = (out: Color | null, kelvin: number, alpha = 1) => { kelvin *= 0.01; let t: number; return kelvin < 66 - ? [ + ? setC4( + out || [], 1, clamp01(G1 + G2 * (t = kelvin - 2) + G3 * Math.log(t)), kelvin < 20 ? 0 : clamp01(B1 + B2 * (t = kelvin - 10) + B3 * Math.log(t)), alpha - ] - : [ + ) + : setC4( + out || [], clamp01(R1 + R2 * (t = kelvin - 55) + R3 * Math.log(t)), clamp01(G4 + G5 * (t = kelvin - 50) - G6 * Math.log(t)), 1, alpha - ]; + ); }; diff --git a/packages/color/src/luminance.ts b/packages/color/src/luminance.ts index 2000adc80a..5f3af11953 100644 --- a/packages/color/src/luminance.ts +++ b/packages/color/src/luminance.ts @@ -13,16 +13,15 @@ export const luminance: MultiFn1O< number | string | ReadonlyColor | IColor, ColorMode, number -> = defmulti( - (col: any, mode) => - col.mode !== undefined - ? col.mode - : mode !== undefined - ? mode - : illegalArgs(`missing color mode`) +> = defmulti((col: any, mode) => + col.mode !== undefined + ? col.mode + : mode !== undefined + ? mode + : illegalArgs(`missing color mode`) ); -luminance.add(ColorMode.RGBA, (x: ReadonlyColor) => luminanceRGB(x)); +luminance.add(ColorMode.RGBA, (x: any) => luminanceRGB(x)); luminance.add(ColorMode.INT32, (x: any) => luminanceInt(typeof x === "number" ? x : x.deref()) diff --git a/packages/color/src/mix.ts b/packages/color/src/mix.ts index 3947c934f5..98a29b1048 100644 --- a/packages/color/src/mix.ts +++ b/packages/color/src/mix.ts @@ -3,13 +3,17 @@ import { mixN4, setC4 } from "@thi.ng/vectors"; import { Color, ReadonlyColor } from "./api"; export const mix: ( - out: Color, + out: Color | null, a: ReadonlyColor, b: ReadonlyColor, t: number ) => Color = mixN4; -export const mixAlpha = (out: Color, a: ReadonlyColor, b: ReadonlyColor) => +export const mixAlpha = ( + out: Color | null, + a: ReadonlyColor, + b: ReadonlyColor +) => setC4( out || a, _mix(a[0], b[0], a[3]), diff --git a/packages/color/src/names.ts b/packages/color/src/names.ts index b1e0860842..759fb6a1a4 100644 --- a/packages/color/src/names.ts +++ b/packages/color/src/names.ts @@ -1,4 +1,6 @@ -export const CSS_NAMES = { +import { IObjectOf } from "@thi.ng/api"; + +export const CSS_NAMES: IObjectOf = { aliceblue: "f0f8ff", antiquewhite: "faebd7", aqua: "0ff", diff --git a/packages/color/src/parse-css.ts b/packages/color/src/parse-css.ts index 147d3157c2..885fcd03f1 100644 --- a/packages/color/src/parse-css.ts +++ b/packages/color/src/parse-css.ts @@ -2,7 +2,7 @@ import { IDeref } from "@thi.ng/api"; import { illegalArgs } from "@thi.ng/errors"; import { clamp01 } from "@thi.ng/math"; import { maybeParseFloat, maybeParseInt } from "@thi.ng/strings"; -import { INV8BIT, Color } from "./api"; +import { Color, INV8BIT } from "./api"; import { hslaRgba } from "./hsla-rgba"; import { int32Rgba } from "./int-rgba"; import { CSS_NAMES } from "./names"; @@ -67,7 +67,7 @@ export const parseHex = (src: string): number => { default: } } - illegalArgs(`invalid hex color: "${src}"`); + return illegalArgs(`invalid hex color: "${src}"`); }; const parseChannel = (c: string) => diff --git a/packages/color/src/porter-duff.ts b/packages/color/src/porter-duff.ts index 114d7b6170..55fa417579 100644 --- a/packages/color/src/porter-duff.ts +++ b/packages/color/src/porter-duff.ts @@ -37,10 +37,10 @@ export const porterDuff = ( : (s: number, d: number, sda: number, sy: number) => f(s, d) * sda + s * sy : z - ? (s: number, d: number, sda: number, _, sz: number) => + ? (s: number, d: number, sda: number, _: number, sz: number) => f(s, d) * sda + d * sz : (s: number, d: number, sda: number) => f(s, d) * sda; - return (out: Color, src: ReadonlyColor, dest: ReadonlyColor) => { + return (out: Color | null, src: ReadonlyColor, dest: ReadonlyColor) => { const sa = src[3]; const da = dest[3]; const sda = sa * da; @@ -69,7 +69,7 @@ export const porterDuffP = ( out: Color, src: ReadonlyColor, dest: ReadonlyColor, - mode: Fn3 + mode: Fn3 ) => postmultiply( null, diff --git a/packages/color/src/premultiply.ts b/packages/color/src/premultiply.ts index a650150f0d..740ec44e0e 100644 --- a/packages/color/src/premultiply.ts +++ b/packages/color/src/premultiply.ts @@ -1,5 +1,5 @@ import { set, setC4 } from "@thi.ng/vectors"; -import { Color, ReadonlyColor } from "./api"; +import { ColorOp } from "./api"; /** * RGBA only. Multiplies RGB channels w/ alpha channel. Assumes alpha is @@ -8,7 +8,7 @@ import { Color, ReadonlyColor } from "./api"; * @param out * @param src */ -export const premultiply = (out: Color, src: ReadonlyColor) => { +export const premultiply: ColorOp = (out, src) => { const a = src[3]; return setC4(out || src, src[0] * a, src[1] * a, src[2] * a, a); }; @@ -20,11 +20,11 @@ export const premultiply = (out: Color, src: ReadonlyColor) => { * @param out * @param src */ -export const postmultiply = (out: Color, src: ReadonlyColor) => { +export const postmultiply: ColorOp = (out, src) => { const a = src[3]; return a > 0 ? setC4(out || src, src[0] / a, src[1] / a, src[2] / a, a) : !out && out != src - ? set(out, src) - : src; + ? set(out, src) + : src; }; diff --git a/packages/color/src/rgba-hcva.ts b/packages/color/src/rgba-hcva.ts index 2dd140abe3..b681710937 100644 --- a/packages/color/src/rgba-hcva.ts +++ b/packages/color/src/rgba-hcva.ts @@ -1,6 +1,6 @@ -import { EPS, clamp01 } from "@thi.ng/math"; +import { clamp01, EPS } from "@thi.ng/math"; import { setC3 } from "@thi.ng/vectors"; -import { Color, ReadonlyColor } from "./api"; +import { ColorOp } from "./api"; import { clamp } from "./clamp"; /** @@ -10,7 +10,7 @@ import { clamp } from "./clamp"; * @param out * @param src */ -export const rgbaHcva = (out: Color, src: ReadonlyColor) => { +export const rgbaHcva: ColorOp = (out, src) => { out = clamp(out || src, src); const p = out[1] < out[2] diff --git a/packages/color/src/rgba-hcya.ts b/packages/color/src/rgba-hcya.ts index 6727867a6f..6937f87647 100644 --- a/packages/color/src/rgba-hcya.ts +++ b/packages/color/src/rgba-hcya.ts @@ -1,5 +1,5 @@ import { EPS } from "@thi.ng/math"; -import { Color, ReadonlyColor } from "./api"; +import { ColorOp } from "./api"; import { hueRgba } from "./hue-rgba"; import { luminanceRGB } from "./luminance-rgb"; import { rgbaHcva } from "./rgba-hcva"; @@ -11,7 +11,7 @@ import { rgbaHcva } from "./rgba-hcva"; * @param out * @param src */ -export const rgbaHcya = (out: Color, src: ReadonlyColor) => { +export const rgbaHcya: ColorOp = (out, src) => { const y = luminanceRGB(src); out = rgbaHcva(out, src); const z = luminanceRGB(hueRgba([], out[0])); diff --git a/packages/color/src/rgba-hsia.ts b/packages/color/src/rgba-hsia.ts index 1cadc10f8c..fbd756250c 100644 --- a/packages/color/src/rgba-hsia.ts +++ b/packages/color/src/rgba-hsia.ts @@ -1,13 +1,18 @@ -import { atan2Abs, SQRT3, TAU, THIRD } from "@thi.ng/math"; +import { + atan2Abs, + SQRT3, + TAU, + THIRD +} from "@thi.ng/math"; import { setC3 } from "@thi.ng/vectors"; -import { Color, ReadonlyColor } from "./api"; +import { ColorOp } from "./api"; import { clamp } from "./clamp"; // https://en.wikipedia.org/wiki/HSL_and_HSV#Hue_and_chroma const SQRT32 = SQRT3 / 2; -export const rgbaHsia = (out: Color, src: ReadonlyColor) => { +export const rgbaHsia: ColorOp = (out, src) => { out = clamp(out || src, src); const r = out[0]; const g = out[1]; diff --git a/packages/color/src/rgba-hsla.ts b/packages/color/src/rgba-hsla.ts index b96deb7a4f..dc0343bc1b 100644 --- a/packages/color/src/rgba-hsla.ts +++ b/packages/color/src/rgba-hsla.ts @@ -1,8 +1,8 @@ import { EPS } from "@thi.ng/math"; -import { Color, ReadonlyColor } from "./api"; +import { ColorOp } from "./api"; import { rgbaHcva } from "./rgba-hcva"; -export const rgbaHsla = (out: Color, src: ReadonlyColor) => { +export const rgbaHsla: ColorOp = (out, src) => { out = rgbaHcva(out, src); out[2] -= out[1] * 0.5; out[1] /= 1 + EPS - Math.abs(out[2] * 2 - 1); diff --git a/packages/color/src/rgba-hsva.ts b/packages/color/src/rgba-hsva.ts index 3a4823d003..7c36e957da 100644 --- a/packages/color/src/rgba-hsva.ts +++ b/packages/color/src/rgba-hsva.ts @@ -1,8 +1,8 @@ import { EPS } from "@thi.ng/math"; -import { Color, ReadonlyColor } from "./api"; +import { ColorOp } from "./api"; import { rgbaHcva } from "./rgba-hcva"; -export const rgbaHsva = (out: Color, src: ReadonlyColor) => { +export const rgbaHsva: ColorOp = (out, src) => { out = rgbaHcva(out, src); out[1] /= out[2] + EPS; return out; diff --git a/packages/color/src/rgba-xyza.ts b/packages/color/src/rgba-xyza.ts index d459f7bc6b..03987e56d8 100644 --- a/packages/color/src/rgba-xyza.ts +++ b/packages/color/src/rgba-xyza.ts @@ -1,7 +1,7 @@ -import { Color, ReadonlyColor, RGB_XYZ } from "./api"; +import { ColorOp, RGB_XYZ } from "./api"; import { clamp } from "./clamp"; -import { mulV33 } from "./internal/matrix-ops"; import { ensureAlpha } from "./internal/ensure-alpha"; +import { mulV33 } from "./internal/matrix-ops"; /** * https://en.wikipedia.org/wiki/CIE_1931_color_space @@ -9,7 +9,7 @@ import { ensureAlpha } from "./internal/ensure-alpha"; * @param out * @param src */ -export const rgbaXyza = (out: Color, src: ReadonlyColor) => { +export const rgbaXyza: ColorOp = (out, src) => { out = mulV33(null, RGB_XYZ, clamp(out || src, src), false); out[3] = ensureAlpha(src[3]); return out; diff --git a/packages/color/src/rgba-ycbcra.ts b/packages/color/src/rgba-ycbcra.ts index dafa68f9b8..1925f046c9 100644 --- a/packages/color/src/rgba-ycbcra.ts +++ b/packages/color/src/rgba-ycbcra.ts @@ -1,9 +1,9 @@ import { setC3 } from "@thi.ng/vectors"; -import { Color, ReadonlyColor } from "./api"; +import { ColorOp } from "./api"; import { clamp } from "./clamp"; import { luminanceRGB } from "./luminance-rgb"; -export const rgbaYcbcra = (out: Color, src: ReadonlyColor) => { +export const rgbaYcbcra: ColorOp = (out, src) => { out = clamp(out || src, src); const y = luminanceRGB(src); return setC3(out, y, (src[2] - y) * 0.565, (src[0] - y) * 0.713); diff --git a/packages/color/src/rgba.ts b/packages/color/src/rgba.ts index 7ec3323ad2..a5e1c60be2 100644 --- a/packages/color/src/rgba.ts +++ b/packages/color/src/rgba.ts @@ -10,10 +10,10 @@ export function rgba(...args: any[]) { } export class RGBA extends AColor implements IVector { - r: number; - g: number; - b: number; - a: number; + r!: number; + g!: number; + b!: number; + a!: number; get mode() { return ColorMode.RGBA; diff --git a/packages/color/src/srgba.ts b/packages/color/src/srgba.ts index c4d9497e36..75bf581a1f 100644 --- a/packages/color/src/srgba.ts +++ b/packages/color/src/srgba.ts @@ -1,5 +1,5 @@ import { setC4 } from "@thi.ng/vectors"; -import { Color, ReadonlyColor, SRGB_ALPHA } from "./api"; +import { ColorOp, SRGB_ALPHA } from "./api"; import { ensureAlpha } from "./internal/ensure-alpha"; /** @@ -32,7 +32,7 @@ export const srgbLinear = (x: number) => * @param out * @param src */ -export const rgbaSrgba = (out: Color, src: ReadonlyColor) => +export const rgbaSrgba: ColorOp = (out, src) => setC4( out || src, linearSrgb(src[0]), @@ -47,7 +47,7 @@ export const rgbaSrgba = (out: Color, src: ReadonlyColor) => * @param out * @param src */ -export const srgbaRgba = (out: Color, src: ReadonlyColor) => +export const srgbaRgba: ColorOp = (out, src) => setC4( out || src, srgbLinear(src[0]), diff --git a/packages/color/src/transform.ts b/packages/color/src/transform.ts index b70cadbbdb..0f1573fef9 100644 --- a/packages/color/src/transform.ts +++ b/packages/color/src/transform.ts @@ -1,6 +1,11 @@ import { mix } from "@thi.ng/math"; -import { ColorMatrix, RGB_LUMINANCE, ReadonlyColor, WHITE } from "./api"; -import { mulV45, mulM45 } from "./internal/matrix-ops"; +import { + ColorMatrix, + ReadonlyColor, + RGB_LUMINANCE, + WHITE +} from "./api"; +import { mulM45, mulV45 } from "./internal/matrix-ops"; // https://drafts.fxtf.org/filter-effects/#feColorMatrixElement @@ -46,27 +51,12 @@ export const transform = mulV45; export const concat = (mat: ColorMatrix, ...xs: ColorMatrix[]) => xs.reduce(mulM45, mat); +// prettier-ignore export const IDENTITY: ColorMatrix = [ - 1, - 0, - 0, - 0, - 0, - 0, - 1, - 0, - 0, - 0, - 0, - 0, - 1, - 0, - 0, - 0, - 0, - 0, - 1, - 0 + 1, 0, 0, 0, 0, + 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 1, 0 ]; /** @@ -76,27 +66,12 @@ export const IDENTITY: ColorMatrix = [ * * @param src */ +// prettier-ignore export const subtract = (src: ReadonlyColor = WHITE): ColorMatrix => [ - -1, - 0, - 0, - 0, - src[0], - 0, - -1, - 0, - 0, - src[1], - 0, - 0, - -1, - 0, - src[2], - 0, - 0, - 0, - 1, - 0 + -1, 0, 0, 0, src[0], + 0, -1, 0, 0, src[1], + 0, 0, -1, 0, src[2], + 0, 0, 0, 1, 0 ]; /** @@ -108,192 +83,72 @@ export const subtract = (src: ReadonlyColor = WHITE): ColorMatrix => [ * * @param x */ +// prettier-ignore export const brightness = (x: number): ColorMatrix => [ - 1, - 0, - 0, - 0, - x, - 0, - 1, - 0, - 0, - x, - 0, - 0, - 1, - 0, - x, - 0, - 0, - 0, - 1, - 0 + 1, 0, 0, 0, x, + 0, 1, 0, 0, x, + 0, 0, 1, 0, x, + 0, 0, 0, 1, 0 ]; +// prettier-ignore export const contrast = (x: number, o = 0.5 * (1 - x)): ColorMatrix => [ - x, - 0, - 0, - 0, - o, - 0, - x, - 0, - 0, - o, - 0, - 0, - x, - 0, - o, - 0, - 0, - 0, - 1, - 0 + x, 0, 0, 0, o, + 0, x, 0, 0, o, + 0, 0, x, 0, o, + 0, 0, 0, 1, 0 ]; +// prettier-ignore export const exposure = (x: number): ColorMatrix => [ - x, - 0, - 0, - 0, - 0, - 0, - x, - 0, - 0, - 0, - 0, - 0, - x, - 0, - 0, - 0, - 0, - 0, - 1, - 0 + x, 0, 0, 0, 0, + 0, x, 0, 0, 0, + 0, 0, x, 0, 0, + 0, 0, 0, 1, 0 ]; +// prettier-ignore export const saturation = (x: number): ColorMatrix => [ - S1 + S4 * x, - S3 - S3 * x, - S0 - S0 * x, - 0, - 0, - S1 - S1 * x, - S3 + S2 * x, - S0 - S0 * x, - 0, - 0, - S1 - S1 * x, - S3 - S3 * x, - S0 + S5 * x, - 0, - 0, - 0, - 0, - 0, - 1, - 0 + S1 + S4 * x, S3 - S3 * x, S0 - S0 * x, 0, 0, + S1 - S1 * x, S3 + S2 * x, S0 - S0 * x, 0, 0, + S1 - S1 * x, S3 - S3 * x, S0 + S5 * x, 0, 0, + 0, 0, 0, 1, 0 ]; +// prettier-ignore export const hueRotate = (theta: number): ColorMatrix => { const s = Math.sin(theta); const c = Math.cos(theta); return [ - S1 + c * S4 - s * S1, - S3 - c * S3 - s * S3, - S0 - c * S0 + s * S5, - 0, - 0, - S1 - c * S1 + s * S7, - S3 + c * S2 + s * S6, - S0 - c * S0 - s * S8, - 0, - 0, - S1 - c * S1 - s * S4, - S3 - c * S3 + s * S3, - S0 + c * S5 + s * S0, - 0, - 0, - 0, - 0, - 0, - 1, - 0 + S1 + c * S4 - s * S1, S3 - c * S3 - s * S3, S0 - c * S0 + s * S5, 0, 0, + S1 - c * S1 + s * S7, S3 + c * S2 + s * S6, S0 - c * S0 - s * S8, 0, 0, + S1 - c * S1 - s * S4, S3 - c * S3 + s * S3, S0 + c * S5 + s * S0, 0, 0, + 0, 0, 0, 1, 0 ]; }; +// prettier-ignore export const temperature = (x: number): ColorMatrix => [ - 1 + x, - 0, - 0, - 0, - 0, - 0, - 1, - 0, - 0, - 0, - 0, - 0, - 1 - x, - 0, - 0, - 0, - 0, - 0, - 1, - 0 + 1 + x, 0, 0, 0, 0, + 0, 1, 0, 0, 0, + 0, 0, 1 - x, 0, 0, + 0, 0, 0, 1, 0 ]; +// prettier-ignore export const sepia = (x = 1): ColorMatrix => [ - mix(1, 0.393, x), - 0.769 * x, - 0.189 * x, - 0, - 0, - 0.349 * x, - mix(1, 0.686, x), - 0.168 * x, - 0, - 0, - 0.272 * x, - 0.534 * x, - mix(1, 0.131, x), - 0, - 0, - 0, - 0, - 0, - 1, - 0 + mix(1, 0.393, x), 0.769 * x, 0.189 * x, 0, 0, + 0.349 * x, mix(1, 0.686, x), 0.168 * x, 0, 0, + 0.272 * x, 0.534 * x, mix(1, 0.131, x), 0, 0, + 0, 0, 0, 1, 0 ]; +// prettier-ignore export const tint = (x: number): ColorMatrix => [ - 1 + x, - 0, - 0, - 0, - 0, - 0, - 1, - 0, - 0, - 0, - 0, - 0, - 1 + x, - 0, - 0, - 0, - 0, - 0, - 1, - 0 + 1 + x, 0, 0, 0, 0, + 0, 1, 0, 0, 0, + 0, 0, 1 + x, 0, 0, + 0, 0, 0, 1, 0 ]; /** @@ -303,27 +158,12 @@ export const tint = (x: number): ColorMatrix => [ * @param x * @param coeffs */ +// prettier-ignore export const grayscale = (x = 0, [r, g, b] = RGB_LUMINANCE): ColorMatrix => [ - r, - g, - b, - 0, - x, - r, - g, - b, - 0, - x, - r, - g, - b, - 0, - x, - 0, - 0, - 0, - 1, - 0 + r, g, b, 0, x, + r, g, b, 0, x, + r, g, b, 0, x, + 0, 0, 0, 1, 0 ]; /** @@ -333,25 +173,10 @@ export const grayscale = (x = 0, [r, g, b] = RGB_LUMINANCE): ColorMatrix => [ * * @param coeffs */ +// prettier-ignore export const luminanceAlpha = ([r, g, b] = RGB_LUMINANCE): ColorMatrix => [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - r, - g, - b, - 0, - 0 + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + r, g, b, 0, 0 ]; diff --git a/packages/color/src/xyza-rgba.ts b/packages/color/src/xyza-rgba.ts index a100b8fe33..4988f8caed 100644 --- a/packages/color/src/xyza-rgba.ts +++ b/packages/color/src/xyza-rgba.ts @@ -1,4 +1,4 @@ -import { Color, ReadonlyColor, XYZ_RGB } from "./api"; +import { ColorOp, XYZ_RGB } from "./api"; import { mulV33 } from "./internal/matrix-ops"; /** @@ -7,5 +7,4 @@ import { mulV33 } from "./internal/matrix-ops"; * @param out * @param src */ -export const xyzaRgba = (out: Color, src: ReadonlyColor) => - mulV33(out || src, XYZ_RGB, src); +export const xyzaRgba: ColorOp = (out, src) => mulV33(out || src, XYZ_RGB, src); diff --git a/packages/color/src/xyza.ts b/packages/color/src/xyza.ts index 9e8d1fd688..209531726c 100644 --- a/packages/color/src/xyza.ts +++ b/packages/color/src/xyza.ts @@ -10,10 +10,10 @@ export function xyza(...args: any[]) { } export class XYZA extends AColor implements IVector { - x: number; - y: number; - z: number; - a: number; + x!: number; + y!: number; + z!: number; + a!: number; get mode() { return ColorMode.XYZA; diff --git a/packages/color/src/ycbcr.ts b/packages/color/src/ycbcr.ts index 0d24660e0d..270fb904f7 100644 --- a/packages/color/src/ycbcr.ts +++ b/packages/color/src/ycbcr.ts @@ -10,10 +10,10 @@ export function ycbcra(...args: any[]) { } export class YCbCrA extends AColor implements IVector { - y: number; - b: number; - r: number; - a: number; + y!: number; + b!: number; + r!: number; + a!: number; get mode() { return ColorMode.YCBCRA; diff --git a/packages/color/src/ycbcra-rgba.ts b/packages/color/src/ycbcra-rgba.ts index 3098e0a3dc..e7f074847d 100644 --- a/packages/color/src/ycbcra-rgba.ts +++ b/packages/color/src/ycbcra-rgba.ts @@ -1,14 +1,14 @@ import { clamp01 } from "@thi.ng/math"; import { setC4 } from "@thi.ng/vectors"; -import { Color, ReadonlyColor } from "./api"; +import { ColorOp } from "./api"; import { ensureAlpha } from "./internal/ensure-alpha"; -export const ycbcraRgba = (out: Color, src: ReadonlyColor) => { +export const ycbcraRgba: ColorOp = (out, src) => { const y = src[0]; const b = src[1]; const r = src[2]; return setC4( - out, + out || [], clamp01(y + 1.403 * r), clamp01(y - 0.344 * b - 0.714 * r), clamp01(y + 1.77 * b), diff --git a/packages/color/tsconfig.json b/packages/color/tsconfig.json index faed4e5fe7..fbd44a729e 100644 --- a/packages/color/tsconfig.json +++ b/packages/color/tsconfig.json @@ -4,9 +4,7 @@ "outDir": ".", "module": "es6", "target": "es6", - "preserveConstEnums": false + "preserveConstEnums": true }, - "include": [ - "./src/**/*.ts" - ] -} \ No newline at end of file + "include": ["./src/**/*.ts"] +} diff --git a/packages/compare/CHANGELOG.md b/packages/compare/CHANGELOG.md index dc87a149cb..06d0f47e35 100644 --- a/packages/compare/CHANGELOG.md +++ b/packages/compare/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.0.7](https://github.com/thi-ng/umbrella/compare/@thi.ng/compare@1.0.6...@thi.ng/compare@1.0.7) (2019-07-07) + +**Note:** Version bump only for package @thi.ng/compare + + + + + ## [1.0.6](https://github.com/thi-ng/umbrella/compare/@thi.ng/compare@1.0.5...@thi.ng/compare@1.0.6) (2019-04-24) **Note:** Version bump only for package @thi.ng/compare diff --git a/packages/compare/package.json b/packages/compare/package.json index 789a67444e..7d9fa97f55 100644 --- a/packages/compare/package.json +++ b/packages/compare/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/compare", - "version": "1.0.6", + "version": "1.0.7", "description": "Comparator with optional delegation for types implementing @thi.ng/api/ICompare interface", "module": "./index.js", "main": "./lib/index.js", @@ -25,11 +25,11 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "keywords": [ "comparator", diff --git a/packages/compose/CHANGELOG.md b/packages/compose/CHANGELOG.md index 5f9be43a93..c79fe52b67 100644 --- a/packages/compose/CHANGELOG.md +++ b/packages/compose/CHANGELOG.md @@ -3,6 +3,19 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.3.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/compose@1.2.5...@thi.ng/compose@1.3.0) (2019-07-07) + + +### Features + +* **compose:** add ifDef() ([64aba00](https://github.com/thi-ng/umbrella/commit/64aba00)) +* **compose:** address TS strictNullChecks, make Delay.value protected ([1540f37](https://github.com/thi-ng/umbrella/commit/1540f37)) +* **compose:** enable TS strict compiler flags (refactor) ([8ea894a](https://github.com/thi-ng/umbrella/commit/8ea894a)) + + + + + ## [1.2.5](https://github.com/thi-ng/umbrella/compare/@thi.ng/compose@1.2.4...@thi.ng/compose@1.2.5) (2019-05-22) **Note:** Version bump only for package @thi.ng/compose diff --git a/packages/compose/package.json b/packages/compose/package.json index 1f18af3c17..d4e40e4091 100644 --- a/packages/compose/package.json +++ b/packages/compose/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/compose", - "version": "1.2.5", + "version": "1.3.0", "description": "Arity-optimized functional composition helpers", "module": "./index.js", "main": "./lib/index.js", @@ -25,15 +25,15 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/api": "^6.2.0", - "@thi.ng/errors": "^1.0.6" + "@thi.ng/api": "^6.3.0", + "@thi.ng/errors": "^1.1.0" }, "keywords": [ "composition", diff --git a/packages/compose/src/comp.ts b/packages/compose/src/comp.ts index ddbf39953a..03c7448f8e 100644 --- a/packages/compose/src/comp.ts +++ b/packages/compose/src/comp.ts @@ -200,7 +200,7 @@ export function compL( ...xs: Fn[] ): FnAny; export function compL(...fns: any[]): any { - return comp.apply(null, fns.reverse()); + return comp.apply(null, fns.reverse()); } /** diff --git a/packages/compose/src/complement.ts b/packages/compose/src/complement.ts index fc46e935da..081c4905c4 100644 --- a/packages/compose/src/complement.ts +++ b/packages/compose/src/complement.ts @@ -33,5 +33,5 @@ export function complement( f: Fn8 ): Fn8; export function complement(f: FnAny) { - return (...xs) => !f(...xs); + return (...xs: any[]) => !f(...xs); } diff --git a/packages/compose/src/delay.ts b/packages/compose/src/delay.ts index 2483936400..70c84330e1 100644 --- a/packages/compose/src/delay.ts +++ b/packages/compose/src/delay.ts @@ -3,7 +3,7 @@ import { Fn0, IDeref } from "@thi.ng/api"; export const delay = (body: Fn0) => new Delay(body); export class Delay implements IDeref { - value: T; + protected value!: T; protected body: Fn0; protected realized: boolean; diff --git a/packages/compose/src/delayed.ts b/packages/compose/src/delayed.ts index 14becb21e8..14388c052a 100644 --- a/packages/compose/src/delayed.ts +++ b/packages/compose/src/delayed.ts @@ -1,2 +1,2 @@ export const delayed = (x: T, t: number) => - new Promise((resolve) => setTimeout(() => resolve(x), t)); + new Promise((resolve) => setTimeout(() => resolve(x), t)); diff --git a/packages/compose/src/ifdef.ts b/packages/compose/src/ifdef.ts new file mode 100644 index 0000000000..83787283c4 --- /dev/null +++ b/packages/compose/src/ifdef.ts @@ -0,0 +1,10 @@ +import { Fn } from "@thi.ng/api"; + +/** + * Returns f(x) iff `x` is not null or undefined. + * + * @param f + * @param x + */ +export const ifDef = (f: Fn, x: A | null | undefined) => + x != null ? f(x) : undefined; diff --git a/packages/compose/src/index.ts b/packages/compose/src/index.ts index 330397535b..4835f6a9e6 100644 --- a/packages/compose/src/index.ts +++ b/packages/compose/src/index.ts @@ -4,6 +4,7 @@ export * from "./constantly"; export * from "./delay"; export * from "./delayed"; export * from "./identity"; +export * from "./ifdef"; export * from "./juxt"; export * from "./partial"; export * from "./thread-first"; diff --git a/packages/compose/src/juxt.ts b/packages/compose/src/juxt.ts index 1f3769d507..e055e89b67 100644 --- a/packages/compose/src/juxt.ts +++ b/packages/compose/src/juxt.ts @@ -62,21 +62,21 @@ export function juxt(...fns: Fn[]) { const [a, b, c, d, e, f, g, h] = fns; switch (fns.length) { case 1: - return (x) => [a(x)]; + return (x: T) => [a(x)]; case 2: - return (x) => [a(x), b(x)]; + return (x: T) => [a(x), b(x)]; case 3: - return (x) => [a(x), b(x), c(x)]; + return (x: T) => [a(x), b(x), c(x)]; case 4: - return (x) => [a(x), b(x), c(x), d(x)]; + return (x: T) => [a(x), b(x), c(x), d(x)]; case 5: - return (x) => [a(x), b(x), c(x), d(x), e(x)]; + return (x: T) => [a(x), b(x), c(x), d(x), e(x)]; case 6: - return (x) => [a(x), b(x), c(x), d(x), e(x), f(x)]; + return (x: T) => [a(x), b(x), c(x), d(x), e(x), f(x)]; case 7: - return (x) => [a(x), b(x), c(x), d(x), e(x), f(x), g(x)]; + return (x: T) => [a(x), b(x), c(x), d(x), e(x), f(x), g(x)]; case 8: - return (x) => [a(x), b(x), c(x), d(x), e(x), f(x), g(x), h(x)]; + return (x: T) => [a(x), b(x), c(x), d(x), e(x), f(x), g(x), h(x)]; default: return (x: T) => { let res = new Array(fns.length); diff --git a/packages/compose/src/partial.ts b/packages/compose/src/partial.ts index 49f1eb2ecc..a936a4cd87 100644 --- a/packages/compose/src/partial.ts +++ b/packages/compose/src/partial.ts @@ -64,7 +64,7 @@ export function partial( g: G, h: H ): FnAny; -export function partial(fn, ...args: any[]) { +export function partial(fn: any, ...args: any[]) { let [a, b, c, d, e, f, g, h] = args; switch (args.length) { case 1: diff --git a/packages/compose/test/partial.ts b/packages/compose/test/partial.ts index 9c154f31bf..e44e759a24 100644 --- a/packages/compose/test/partial.ts +++ b/packages/compose/test/partial.ts @@ -1,10 +1,18 @@ -import { partial } from "../src"; - import * as assert from "assert"; +import { partial } from "../src"; describe("partial", () => { - - const fn = (a, b, c, d, e, f, g, h, i) => [a, b, c, d, e, f, g, h, i]; + const fn = ( + a: any, + b: any, + c: any, + d: any, + e: any, + f: any, + g: any, + h: any, + i: any + ) => [a, b, c, d, e, f, g, h, i]; const res = [0, 1, 2, 3, 4, 5, 6, 7, 8]; it("1-arg", () => { diff --git a/packages/csp/CHANGELOG.md b/packages/csp/CHANGELOG.md index efe283c7f9..c279a85b47 100644 --- a/packages/csp/CHANGELOG.md +++ b/packages/csp/CHANGELOG.md @@ -3,6 +3,23 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.1.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/csp@1.0.19...@thi.ng/csp@1.1.0) (2019-07-07) + + +### Bug Fixes + +* **csp:** TS strictNullChecks, update various return types ([da909ac](https://github.com/thi-ng/umbrella/commit/da909ac)) + + +### Features + +* **csp:** enable TS strict compiler flags (refactor) ([3d7fba2](https://github.com/thi-ng/umbrella/commit/3d7fba2)) +* **csp:** update Mult.tap() to use set semantics ([c9bc953](https://github.com/thi-ng/umbrella/commit/c9bc953)) + + + + + ## [1.0.19](https://github.com/thi-ng/umbrella/compare/@thi.ng/csp@1.0.18...@thi.ng/csp@1.0.19) (2019-05-22) **Note:** Version bump only for package @thi.ng/csp diff --git a/packages/csp/package.json b/packages/csp/package.json index 81dc0796ac..ed8bddd576 100644 --- a/packages/csp/package.json +++ b/packages/csp/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/csp", - "version": "1.0.19", + "version": "1.1.0", "description": "ES6 promise based CSP implementation", "module": "./index.js", "main": "./lib/index.js", @@ -29,19 +29,19 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/api": "^6.2.0", - "@thi.ng/arrays": "^0.1.9", - "@thi.ng/checks": "^2.1.6", - "@thi.ng/dcons": "^2.0.19", - "@thi.ng/errors": "^1.0.6", - "@thi.ng/transducers": "^5.3.7" + "@thi.ng/api": "^6.3.0", + "@thi.ng/arrays": "^0.2.0", + "@thi.ng/checks": "^2.2.0", + "@thi.ng/dcons": "^2.1.0", + "@thi.ng/errors": "^1.1.0", + "@thi.ng/transducers": "^5.4.0" }, "keywords": [ "async", diff --git a/packages/csp/src/api.ts b/packages/csp/src/api.ts index 5a9533415c..9ca8d23fea 100644 --- a/packages/csp/src/api.ts +++ b/packages/csp/src/api.ts @@ -25,13 +25,13 @@ export interface ChannelItem { export interface IBuffer extends ILength, IRelease { isEmpty(): boolean; isFull(): boolean; - drop(): ChannelItem; + drop(): ChannelItem | undefined; push(x: ChannelItem): boolean; } export interface IChannel extends IID { channel(): Channel; - close(flush?: boolean); + close(flush?: boolean): Promise | undefined; } export interface IReadableChannel extends IChannel { diff --git a/packages/csp/src/channel.ts b/packages/csp/src/channel.ts index 28bd441d0b..e340d3644a 100644 --- a/packages/csp/src/channel.ts +++ b/packages/csp/src/channel.ts @@ -1,4 +1,10 @@ -import { Fn, Fn0, Predicate } from "@thi.ng/api"; +import { + Fn, + Fn0, + Fn2, + FnAny, + Predicate +} from "@thi.ng/api"; import { shuffle } from "@thi.ng/arrays"; import { isFunction } from "@thi.ng/checks"; import { DCons } from "@thi.ng/dcons"; @@ -48,7 +54,7 @@ export class Channel implements IReadWriteableChannel { step: number, delay: number ): Channel; - static range(...args: any[]) { + static range(...args: any[]): Channel { const [from, to, step, delay] = args; return Channel.from( range(from, to, step), @@ -94,10 +100,14 @@ export class Channel implements IReadWriteableChannel { return chan; } - static from(src: Iterable); - static from(src: Iterable, close: boolean); - static from(src: Iterable, tx: Transducer); - static from(src: Iterable, tx: Transducer, close: boolean); + static from(src: Iterable): Channel; + static from(src: Iterable, close: boolean): Channel; + static from(src: Iterable, tx: Transducer): Channel; + static from( + src: Iterable, + tx: Transducer, + close: boolean + ): Channel; static from(...args: any[]) { let close, tx; switch (args.length) { @@ -135,7 +145,7 @@ export class Channel implements IReadWriteableChannel { const _select = () => { for (let c of shuffle(chans)) { if (c.isReadable() || c.isClosed()) { - c.read().then((x) => resolve([x, c])); + c.read().then((x: any) => resolve([x, c])); return; } } @@ -256,11 +266,11 @@ export class Channel implements IReadWriteableChannel { static MAX_WRITES = 1024; static NEXT_ID = 0; - static SCHEDULE = + static SCHEDULE: Fn2, number, void> = typeof setImmediate === "function" ? setImmediate : setTimeout; private static RFN: Reducer, any> = [ - () => null, + (() => null), (acc) => acc, (acc: DCons, x) => acc.push(x) ]; @@ -341,6 +351,7 @@ export class Channel implements IReadWriteableChannel { this.tx = tx ? tx(Channel.RFN) : null; this.onerror = tx && (err || defaultErrorHandler); this.state = State.OPEN; + this.isBusy = false; } channel() { @@ -417,9 +428,9 @@ export class Channel implements IReadWriteableChannel { ); } - consume(fn: Fn = (x) => console.log(this.id, ":", x)) { + consume(fn: Fn = (x) => console.log(this.id, ":", x)) { return (async () => { - let x; + let x: T | null; while (((x = null), (x = await this.read())) !== undefined) { await fn(x); } @@ -454,19 +465,19 @@ export class Channel implements IReadWriteableChannel { })(); } - reduce(rfn: Reducer, acc?: A): Promise { + reduce(rfn: Reducer, acc?: A): Promise { return (async () => { const [init, complete, reduce] = rfn; acc = acc != null ? acc : init(); - let x; + let x: T | null; while (((x = null), (x = await this.read())) !== undefined) { - acc = reduce(acc, x); + acc = reduce(acc!, x); if (isReduced(acc)) { acc = (acc).deref(); break; } } - return unreduced(complete(acc)); + return unreduced(complete(acc!)); })(); } @@ -498,7 +509,9 @@ export class Channel implements IReadWriteableChannel { dest = new Channel(dest); } this.consume((x: T) => (>dest).write(x)) // return undefined here? - .then(() => close && (>dest).close()); + .then(() => { + close && (>dest).close(); + }); return dest; } @@ -509,13 +522,15 @@ export class Channel implements IReadWriteableChannel { close = true ) { if (!(truthy instanceof Channel)) { - truthy = new Channel(truthy); + truthy = new Channel(); } if (!(falsey instanceof Channel)) { - falsey = new Channel(falsey); + falsey = new Channel(); } - this.consume((x: T) => (pred(x) ? truthy : falsey).write(x)).then( - () => close && (truthy.close(), falsey.close()) + this.consume((x: T) => (pred(x) ? truthy! : falsey!).write(x)).then( + () => { + close && (truthy!.close(), falsey!.close()); + } ); return [truthy, falsey]; } @@ -557,17 +572,17 @@ export class Channel implements IReadWriteableChannel { if (txbuf.length) { const val = txbuf.drop(); if (val !== undefined) { - reads.drop()(val); + reads.drop()!(val); } } else { - const val = await buf.drop().value(); + const val = await buf.drop()!.value(); if (val !== undefined) { - reads.drop()(val); + reads.drop()!(val); } } } while (writes.length && !buf.isFull()) { - const put = writes.drop(); + const put = writes.drop()!; buf.push(put); put.resolve(true); } @@ -594,7 +609,7 @@ export class Channel implements IReadWriteableChannel { } protected flush() { - let op; + let op: any; while ((op = this.reads.drop())) { op(); } @@ -613,4 +628,5 @@ const defaultErrorHandler = (e: Error, chan: Channel, val?: any) => val !== undefined ? val : "" ); -const maybeBuffer = (x) => x instanceof FixedBuffer || typeof x === "number"; +const maybeBuffer = (x: any) => + x instanceof FixedBuffer || typeof x === "number"; diff --git a/packages/csp/src/mult.ts b/packages/csp/src/mult.ts index ac3b629f7a..ff42af55fe 100644 --- a/packages/csp/src/mult.ts +++ b/packages/csp/src/mult.ts @@ -61,16 +61,19 @@ export class Mult implements IWriteableChannel { if (this.src) { return this.src.write(val); } + return Promise.resolve(false); } close(flush = false) { - this.src && this.src.close(flush); + return this.src ? this.src.close(flush) : undefined; } tap(ch?: Channel | Transducer) { if (this.taps) { if (!(ch instanceof Channel)) { - ch = new Channel(this.src.id + "-tap" + this.tapID++, ch); + ch = new Channel(this.src.id + "-tap" + this.tapID++, ch!); + } else if (this.taps.find(ch)) { + return ch; } this.taps.push(ch); return ch; diff --git a/packages/csp/src/pubsub.ts b/packages/csp/src/pubsub.ts index 9d94ad5b15..0ce7ada2bb 100644 --- a/packages/csp/src/pubsub.ts +++ b/packages/csp/src/pubsub.ts @@ -8,8 +8,8 @@ import { Mult } from "./mult"; export class PubSub implements IWriteableChannel { protected static NEXT_ID = 0; - protected src: Channel; - protected fn: TopicFn; + protected src!: Channel; + protected fn!: TopicFn; protected topics: IObjectOf>; constructor(fn: TopicFn); @@ -47,10 +47,11 @@ export class PubSub implements IWriteableChannel { if (this.src) { return this.src.write(val); } + return Promise.resolve(false); } close(flush = false) { - this.src && this.src.close(flush); + return this.src ? this.src.close(flush) : undefined; } /** diff --git a/packages/csp/test/async.ts b/packages/csp/test/async.ts index 6484325722..6aafdad0f8 100644 --- a/packages/csp/test/async.ts +++ b/packages/csp/test/async.ts @@ -1,5 +1,4 @@ import * as tx from "@thi.ng/transducers"; - import { Channel, PubSub } from "../src"; async function pingpong() { @@ -43,7 +42,7 @@ async function alts() { console.log("selected", ch.id, x); } -async function throttle(d1, d2) { +async function throttle(d1: number, d2: number) { const a = Channel.range(0, 1000, 1, d1); const done = new Channel(); const t0 = Date.now(); @@ -58,13 +57,18 @@ async function throttle(d1, d2) { async function pubsub() { const pub = new PubSub( - new Channel("users", tx.map((x: string) => ({ type: x.charAt(0), val: x }))), - (x) => x.type - ), + new Channel( + "users", + tx.map((x: string) => ({ type: x.charAt(0), val: x })) + ), + (x) => x.type + ), done = new Channel(), topics = "abc"; for (let i of topics) { - pub.sub(i).consume().then(() => done.write(i)); + pub.sub(i)! + .consume() + .then(() => done.write(i)); } // pub.sub("*").consume(); await pub.channel().into(["alice", "bert", "bella", "charlie", "arthur"]); @@ -83,10 +87,9 @@ async function transducers() { ch = new Channel(tx.comp(tx.take(3), tx.partition(2, true))); ch.into([1, 2, 2, 2, 1, 5, 3, 3]); await ch.consume(); - const src = [5, 2, 8, 10, 20, 15, 12, 18, 27, 78, 35, 16, 2, 99, 123, 42] + const src = [5, 2, 8, 10, 20, 15, 12, 18, 27, 78, 35, 16, 2, 99, 123, 42]; ch = Channel.from(src, tx.delayed(100)).pipe(tx.streamSort(8)); await ch.consume(); - } async function main() { @@ -99,4 +102,3 @@ async function main() { } main(); - diff --git a/packages/csp/test/file.ts b/packages/csp/test/file.ts index 3bc5ecf7e0..621c56b879 100644 --- a/packages/csp/test/file.ts +++ b/packages/csp/test/file.ts @@ -1,6 +1,5 @@ import * as tx from "@thi.ng/transducers"; import * as fs from "fs"; - import { Channel, Mult } from "../src"; // compose transducer to split source file into words @@ -13,31 +12,30 @@ const proc: tx.Transducer = tx.comp( // define a channel which receives file paths // and resolves them with their contents const paths = new Channel( - tx.map((path: string) => - new Promise( - resolve => fs.readFile(path, (_, data) => resolve(data.toString())) - ) + tx.map( + (path: string) => + new Promise((resolve) => + fs.readFile(path, (_, data) => resolve(data.toString())) + ) ) ); // define multiplexed output channel // items in this channel will have this form: `[word, count]` -const results = new Mult("results"); +const results = new Mult<[string, number]>("results"); // tap result channel and sum word counts -const counter = results - .tap(tx.map(x => x[1])) - .reduce(tx.add()); +const counter = results.tap(tx.map((x) => x[1]))!.reduce(tx.add()); // 2nd output channel with streaming sort transducer // (using a sliding window size of 500 items) and dropping // words with < 20 occurrences const sorted = results.tap( tx.comp( - tx.streamSort(500, { key: x => x[1] }), - tx.dropWhile(x => x[1] < 20) + tx.streamSort(500, { key: (x) => x[1] }), + tx.dropWhile((x) => x[1] < 20) ) -); +)!; // define workflow: // pipe source files into a new channel and @@ -45,15 +43,16 @@ const sorted = results.tap( // finally stream the result map (word frequencies) // into the `sorted` channel // (`freqs` is a JS Map and is iterable) -paths.pipe(proc) +paths + .pipe(proc) .reduce(tx.frequencies()) - .then(freqs => results.channel().into(freqs)); + .then((freqs) => results.channel().into(freqs)); // kick off process by writing file paths into the 1st channel paths.into(["src/channel.ts", "src/mult.ts", "src/pubsub.ts"]); // start tracing sorted outputs and // wait for all to finish -Promise - .all([sorted.consume(), counter]) - .then(([_, num]) => console.log("total words:", num)); +Promise.all([sorted.consume(), counter]).then(([_, num]) => + console.log("total words:", num) +); diff --git a/packages/csp/test/graph.ts b/packages/csp/test/graph.ts index 26d13dc246..5cf0489d26 100644 --- a/packages/csp/test/graph.ts +++ b/packages/csp/test/graph.ts @@ -1,6 +1,6 @@ import * as api from "@thi.ng/api"; -// import * as tx from "@thi.ng/transducers"; import { Channel, Mult } from "../src"; +// import * as tx from "@thi.ng/transducers"; export interface Node { ins: api.IObjectOf>; @@ -10,27 +10,35 @@ export interface Node { export type NodeFn = (n: Node) => void; -export function node(id: string, ins: api.IObjectOf | Mult>, outs: string[], init: any, fn: NodeFn) { +export function node( + id: string, + ins: api.IObjectOf | Mult>, + outs: string[], + init: any, + fn: NodeFn +) { const $: Node = { ins: >>{}, outs: >>{}, - state: init || {}, + state: init || {} }; for (let k of Object.keys(ins)) { const val = ins[k]; $.ins[k] = - val instanceof Channel ? - (val.id = k, val) : - val instanceof Mult ? - val.tap(new Channel(k)) : - new Channel(k); + val instanceof Channel + ? ((val.id = k), val) + : val instanceof Mult + ? val.tap(new Channel(k))! + : new Channel(k); } for (let o of outs) { $.outs[o] = new Mult(id + "-" + o); } (async () => { while (true) { - let ports = Object.keys($.ins).map((k) => $.ins[k]).filter(x => !!x); + let ports = Object.keys($.ins) + .map((k) => $.ins[k]) + .filter((x) => !!x); let [x, c] = await Channel.select(ports); if (x === undefined) { break; @@ -51,7 +59,11 @@ export function node(id: string, ins: api.IObjectOf | Mult>, o return $; } -export function add(id: string, ins?: api.IObjectOf | Mult>, init?: any) { +export function add( + id: string, + ins?: api.IObjectOf | Mult>, + init?: any +) { return node( id, Object.assign({ a: null, b: null }, ins), @@ -63,9 +75,13 @@ export function add(id: string, ins?: api.IObjectOf | Mult>, i } } ); -}; +} -export function mul(id: string, ins?: api.IObjectOf | Mult>, init?: any) { +export function mul( + id: string, + ins?: api.IObjectOf | Mult>, + init?: any +) { return node( id, Object.assign({ a: null, b: null }, ins), @@ -77,13 +93,16 @@ export function mul(id: string, ins?: api.IObjectOf | Mult>, i } } ); -}; +} const add1 = add("add1", {}, { b: 100 }); const add2 = add("add2", { b: add1.outs.out }, { a: 1000 }); const mul1 = mul("mul1", { a: add2.outs.out, b: Channel.range(0, 10, 1, 500) }); -mul1.outs.out.tap().consume(console.log).then(() => (add1.ins.a.close(), add2.ins.a.close())); +mul1.outs.out + .tap()! + .consume(console.log) + .then(() => (add1.ins.a.close(), add2.ins.a.close())); (async () => { let i = 0; diff --git a/packages/csp/test/index.ts b/packages/csp/test/index.ts deleted file mode 100644 index 5bc2940287..0000000000 --- a/packages/csp/test/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -describe("csp", () => { - it("tests pending"); -}); diff --git a/packages/csp/test/node.ts b/packages/csp/test/node.ts index af20a74836..4c9cfc9e1c 100644 --- a/packages/csp/test/node.ts +++ b/packages/csp/test/node.ts @@ -6,7 +6,11 @@ import { Channel } from "../src/channel"; import { Mult } from "../src/mult"; // import { DCons } from "@thi.ng/dcons"; -export type NodeInput = NodeInputSpec | Channel | Mult | tx.Transducer; +export type NodeInput = + | NodeInputSpec + | Channel + | Mult + | tx.Transducer; export type NodeOutput = NodeOutputSpec | IWriteableChannel; export interface NodeInputSpec { @@ -34,12 +38,9 @@ export interface NodeSpec extends IID { close?: boolean; reset?: boolean; state?: any; -}; - -export class Node implements - IEnable, - IID { +} +export class Node implements IEnable, IID { static hasRequiredInputs(n: Node) { for (let i of n.required) { if (n.enabled[i] && n.state[i] === undefined) { @@ -60,20 +61,19 @@ export class Node implements */ static inputFromSpec(id: string, spec: NodeInputSpec) { if (spec.buf || spec.tx) { - const ch = new Channel(id, spec.buf, spec.tx); - return spec.src instanceof Channel ? - spec.src.pipe(ch) : - spec.src.tap(ch); + const ch = new Channel(id, spec.buf!, spec.tx!); + return spec.src instanceof Channel + ? spec.src.pipe(ch) + : spec.src.tap(ch); } else { - return spec.src instanceof Channel ? spec.src : spec.src.tap(); + return spec.src instanceof Channel ? spec.src : spec.src.tap()!; } } static outputFromSpec(id: string, spec: NodeOutputSpec) { - const mult = new Mult( - ((spec.buf || spec.tx) ? - new Channel(id, spec.buf, spec.tx) : - id)); + const mult = new Mult(( + (spec.buf || spec.tx ? new Channel(id, spec.buf!, spec.tx!) : id) + )); if (spec.dest) { mult.tap(spec.dest.channel()); } @@ -100,7 +100,8 @@ export class Node implements this.autoClose = spec.close !== false; this.autoReset = spec.reset !== false; this.impl = spec.impl; - this.impl.shouldUpdate = this.impl.shouldUpdate || Node.hasRequiredInputs; + this.impl.shouldUpdate = + this.impl.shouldUpdate || Node.hasRequiredInputs; for (let i of Object.keys(spec.ins)) { this.addInput(i, spec.ins[i], spec.state[i]); } @@ -112,13 +113,13 @@ export class Node implements addInput(id: string, val: NodeInput, init?: any) { this.ins[id] = - val instanceof Channel ? - (val.id = id, val) : - val instanceof Mult ? - val.tap(new Channel(id)) : - val == null || typeof val === "function" ? - new Channel(id, val) : - Node.inputFromSpec(id, val); + val instanceof Channel + ? ((val.id = id), val) + : val instanceof Mult + ? val.tap(new Channel(id))! + : val == null || typeof val === "function" + ? new Channel(id, val) + : Node.inputFromSpec(id, val)!; if (init !== undefined) { this.state[id] = init; this.enabled[id] = val != null; @@ -128,13 +129,12 @@ export class Node implements } addOutput(id: string, val: NodeOutput) { - const spec = implementsFunction(val, "channel") ? - { dest: >val } : - val; + const spec = implementsFunction(val, "channel") + ? { dest: >val } + : val; const pid = this.id + "-" + id; - this.outs[id] = spec != null ? - Node.outputFromSpec(pid, spec) : - new Mult(pid); + this.outs[id] = + spec != null ? Node.outputFromSpec(pid, spec) : new Mult(pid); } disable(id?: string) { @@ -168,7 +168,9 @@ export class Node implements let ok = true; for (let id of Object.keys(this.enabled)) { ok = ok && this.enabled[id]; - if (!ok) { break; } + if (!ok) { + break; + } } return ok; } @@ -202,7 +204,7 @@ export class Node implements } if (this.enabled[c.id]) { this.state[c.id] = x; - if (this.impl.shouldUpdate(this)) { + if (this.impl.shouldUpdate!(this)) { await this.impl.update(this); this.autoReset && this.clearState(); } @@ -220,7 +222,7 @@ export class Node implements export interface AddSpec { id: string; - ins: Partial<{ a: NodeInput, b: NodeInput }>; + ins: Partial<{ a: NodeInput; b: NodeInput }>; outs: Partial<{ out: NodeOutput }>; state: any; close: boolean; @@ -231,8 +233,10 @@ export function add(spec: Partial) { return new Node({ id: spec.id || `node-${Node.NEXT_ID++}`, state: Object.assign({}, spec.state), - ins: Object.assign({ a: null, b: null }, spec.ins), - outs: Object.assign({ out: null }, spec.outs), + ins: >( + Object.assign({ a: null, b: null }, spec.ins) + ), + outs: >Object.assign({ out: null }, spec.outs), close: spec.close, reset: spec.close, impl: { @@ -246,14 +250,22 @@ export function add(spec: Partial) { export const res = new Channel("res"); export const a = add({ id: "a", state: { b: 42 } }); -export const b = add({ id: "b", ins: { a: { src: a.outs.out, tx: tx.map(x => x * 1) } }, state: { b: 100 } }); -export const c = add({ id: "c", ins: { a: b.outs.out, b: b.outs.out }, outs: { out: res } }); +export const b = add({ + id: "b", + ins: { a: { src: a.outs.out, tx: tx.map((x) => x * 1) } }, + state: { b: 100 } +}); +export const c = add({ + id: "c", + ins: { a: b.outs.out, b: b.outs.out }, + outs: { out: res } +}); // b.disable("b"); -a.outs.out.tap().consume(); -b.outs.out.tap().consume(); -c.outs.out.tap().consume(); +a.outs.out.tap()!.consume(); +b.outs.out.tap()!.consume(); +c.outs.out.tap()!.consume(); res.consume(); Channel.range(10).pipe(a.ins.a); diff --git a/packages/dcons/CHANGELOG.md b/packages/dcons/CHANGELOG.md index 622285a013..724b7324ab 100644 --- a/packages/dcons/CHANGELOG.md +++ b/packages/dcons/CHANGELOG.md @@ -3,6 +3,23 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [2.1.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/dcons@2.0.19...@thi.ng/dcons@2.1.0) (2019-07-07) + + +### Bug Fixes + +* **dcons:** .toString() impl, use String() conv for values ([d6b1f11](https://github.com/thi-ng/umbrella/commit/d6b1f11)) + + +### Features + +* **dcons:** address TS strictNullChecks flag, minor optimizations ([cb5ad93](https://github.com/thi-ng/umbrella/commit/cb5ad93)) +* **dcons:** enable TS strict compiler flags (refactor) ([4e73667](https://github.com/thi-ng/umbrella/commit/4e73667)) + + + + + ## [2.0.19](https://github.com/thi-ng/umbrella/compare/@thi.ng/dcons@2.0.18...@thi.ng/dcons@2.0.19) (2019-05-22) **Note:** Version bump only for package @thi.ng/dcons diff --git a/packages/dcons/package.json b/packages/dcons/package.json index 51bb451e12..d81839cb45 100644 --- a/packages/dcons/package.json +++ b/packages/dcons/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/dcons", - "version": "2.0.19", + "version": "2.1.0", "description": "Comprehensive doubly linked list structure w/ iterator support", "module": "./index.js", "main": "./lib/index.js", @@ -25,19 +25,19 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/api": "^6.2.0", - "@thi.ng/checks": "^2.1.6", - "@thi.ng/compare": "^1.0.6", - "@thi.ng/equiv": "^1.0.6", - "@thi.ng/errors": "^1.0.6", - "@thi.ng/transducers": "^5.3.7" + "@thi.ng/api": "^6.3.0", + "@thi.ng/checks": "^2.2.0", + "@thi.ng/compare": "^1.0.7", + "@thi.ng/equiv": "^1.0.7", + "@thi.ng/errors": "^1.1.0", + "@thi.ng/transducers": "^5.4.0" }, "keywords": [ "datastructure", diff --git a/packages/dcons/src/index.ts b/packages/dcons/src/index.ts index 0157ac02f6..61cf0ad4bd 100644 --- a/packages/dcons/src/index.ts +++ b/packages/dcons/src/index.ts @@ -1,4 +1,5 @@ import { + assert, Comparator, Fn, ICompare, @@ -13,13 +14,13 @@ import { import { isArrayLike } from "@thi.ng/checks"; import { compare } from "@thi.ng/compare"; import { equiv } from "@thi.ng/equiv"; -import { illegalArgs, illegalState } from "@thi.ng/errors"; +import { illegalArgs } from "@thi.ng/errors"; import { IReducible, isReduced, ReductionFn } from "@thi.ng/transducers"; export interface ConsCell { value: T; - next: ConsCell; - prev: ConsCell; + next: ConsCell | undefined; + prev: ConsCell | undefined; } export class DCons @@ -32,8 +33,8 @@ export class DCons IReducible, IRelease, IStack> { - head: ConsCell; - tail: ConsCell; + head: ConsCell | undefined; + tail: ConsCell | undefined; protected _length: number = 0; constructor(src?: Iterable) { @@ -75,18 +76,21 @@ export class DCons } compare(o: DCons) { - if (this._length < o._length) { + const n = this._length; + if (n < o._length) { return -1; - } else if (this._length > o._length) { + } else if (n > o._length) { return 1; + } else if (n === 0) { + return 0; } else { let ca = this.head; let cb = o.head; let res = 0; while (ca && res == 0) { - res = compare(ca.value, cb.value); + res = compare(ca.value, cb!.value); ca = ca.next; - cb = cb.next; + cb = cb!.next; } return res; } @@ -97,12 +101,15 @@ export class DCons (o instanceof DCons || isArrayLike(o)) && this._length === o.length ) { + if (this._length === 0) { + return true; + } let cell = this.head; for (let x of o) { - if (!equiv(cell.value, x)) { + if (!equiv(cell!.value, x)) { return false; } - cell = cell.next; + cell = cell!.next; } return true; } @@ -195,7 +202,8 @@ export class DCons if (n <= 0) { return this.cons(x); } else { - return this.insertBefore(this.nthCell(n), x); + this.ensureIndex(n); + return this.insertBefore(this.nthCellUnsafe(n), x); } } @@ -206,7 +214,8 @@ export class DCons if (n >= this._length - 1) { return this.push(x); } else { - return this.insertAfter(this.nthCell(n), x); + this.ensureIndex(n); + return this.insertAfter(this.nthCellUnsafe(n), x); } } @@ -272,20 +281,21 @@ export class DCons } splice(at: ConsCell | number, del = 0, insert?: Iterable): DCons { - let cell: ConsCell; + let cell: ConsCell | undefined; if (typeof at === "number") { if (at < 0) { at += this._length; } - cell = this.nthCell(at); + this.ensureIndex(at); + cell = this.nthCellUnsafe(at); } else { cell = at; } - const res = new DCons(); + const removed = new DCons(); if (del > 0) { while (cell && del-- > 0) { this.remove(cell); - res.push(cell.value); + removed.push(cell.value); cell = cell.next; } } else if (cell) { @@ -302,7 +312,7 @@ export class DCons } } } - return res; + return removed; } remove(cell: ConsCell) { @@ -343,7 +353,9 @@ export class DCons pop() { const cell = this.tail; - !cell && illegalState("can't pop, empty"); + if (!cell) { + return; + } this.tail = cell.prev; if (this.tail) { delete this.tail.next; @@ -381,7 +393,7 @@ export class DCons setNth(n: number, v: T) { const cell = this.nthCell(n); !cell && illegalArgs(`index out of bounds: ${n}`); - cell.value = v; + cell!.value = v; return this; } @@ -397,19 +409,7 @@ export class DCons if (n < 0 || n >= this._length) { return; } - let cell, dir; - if (n <= this._length >> 1) { - cell = this.head; - dir = "next"; - } else { - cell = this.tail; - dir = "prev"; - n = this._length - n - 1; - } - while (n-- > 0 && cell) { - cell = cell[dir]; - } - return cell; + return this.nthCellUnsafe(n); } rotateLeft() { @@ -418,9 +418,9 @@ export class DCons case 1: return this; case 2: - return this.swap(this.head, this.tail); + return this.swap(this.head!, this.tail!); default: - return this.push(this.drop()); + return this.push(this.drop()!); } } @@ -430,11 +430,11 @@ export class DCons case 1: return this; case 2: - return this.swap(this.head, this.tail); + return this.swap(this.head!, this.tail!); default: const x = this.peek(); this.pop(); - return this.cons(x); + return this.cons(x!); } } @@ -472,10 +472,10 @@ export class DCons shuffle() { let n = this._length; let cell = this.tail; - while (n > 0) { + while (n > 1) { let i = Math.floor(Math.random() * n); - this.swap(this.nthCell(i), cell); - cell = cell.prev; + this.swap(this.nthCell(i)!, cell!); + cell = cell!.prev; n--; } return this; @@ -501,7 +501,7 @@ export class DCons return this; } this.remove(cell); - this.head.prev = cell; + this.head!.prev = cell; cell.next = this.head; cell.prev = undefined; this.head = cell; @@ -514,7 +514,7 @@ export class DCons return this; } this.remove(cell); - this.tail.next = cell; + this.tail!.next = cell; cell.prev = this.tail; cell.next = undefined; this.tail = cell; @@ -528,7 +528,7 @@ export class DCons while (cell) { res.push( cell.value != null - ? cell.value.toString() + ? String(cell.value) : cell.value === undefined ? "undefined" : "null" @@ -541,4 +541,24 @@ export class DCons toJSON() { return [...this]; } + + protected ensureIndex(i: number) { + assert(i >= 0 && i < this._length, `index out of range: ${i}`); + } + + protected nthCellUnsafe(n: number) { + let cell: ConsCell, dir: keyof ConsCell; + if (n <= this._length >> 1) { + cell = this.head!; + dir = "next"; + } else { + cell = this.tail!; + dir = "prev"; + n = this._length - n - 1; + } + while (n-- > 0 && cell) { + cell = cell[dir]!; + } + return cell; + } } diff --git a/packages/dcons/test/index.ts b/packages/dcons/test/index.ts index 87ea10f0dd..89206ebc7e 100644 --- a/packages/dcons/test/index.ts +++ b/packages/dcons/test/index.ts @@ -1,9 +1,9 @@ import * as assert from "assert"; - import { DCons } from "../src/index"; + describe("DCons", () => { - let a: DCons, src; + let a: DCons, src: number[]; beforeEach(() => { src = [1, 2, 3, 4, 5]; a = new DCons(src); @@ -26,4 +26,4 @@ describe("DCons", () => { it("works as stack"); it("works as queue"); -}); \ No newline at end of file +}); diff --git a/packages/defmulti/CHANGELOG.md b/packages/defmulti/CHANGELOG.md index cba3300fb4..258c6a3749 100644 --- a/packages/defmulti/CHANGELOG.md +++ b/packages/defmulti/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.1.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/defmulti@1.0.9...@thi.ng/defmulti@1.1.0) (2019-07-07) + + +### Features + +* **defmulti:** enable TS strict compiler flags (refactor) ([d51ecf9](https://github.com/thi-ng/umbrella/commit/d51ecf9)) + + + + + ## [1.0.9](https://github.com/thi-ng/umbrella/compare/@thi.ng/defmulti@1.0.8...@thi.ng/defmulti@1.0.9) (2019-05-22) **Note:** Version bump only for package @thi.ng/defmulti diff --git a/packages/defmulti/package.json b/packages/defmulti/package.json index 9309c62cac..7831d2eb79 100644 --- a/packages/defmulti/package.json +++ b/packages/defmulti/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/defmulti", - "version": "1.0.9", + "version": "1.1.0", "description": "Dynamically extensible multiple dispatch via user supplied dispatch function.", "module": "./index.js", "main": "./lib/index.js", @@ -25,15 +25,15 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/api": "^6.2.0", - "@thi.ng/errors": "^1.0.6" + "@thi.ng/api": "^6.3.0", + "@thi.ng/errors": "^1.1.0" }, "keywords": [ "ES6", diff --git a/packages/defmulti/src/index.ts b/packages/defmulti/src/index.ts index 9cabfaa801..75c6df6e56 100644 --- a/packages/defmulti/src/index.ts +++ b/packages/defmulti/src/index.ts @@ -394,7 +394,7 @@ export function defmulti(f: any, ancestors?: AncestorDefs) { const rels: IObjectOf> = ancestors ? makeRels(ancestors) : {}; - const fn: any = (...args) => { + const fn: any = (...args: any[]) => { const id = f(...args); const g = impls[id] || findImpl(impls, rels, id) || impls[DEFAULT]; return g diff --git a/packages/defmulti/test/index.ts b/packages/defmulti/test/index.ts index 9656a9e5df..7467d96970 100644 --- a/packages/defmulti/test/index.ts +++ b/packages/defmulti/test/index.ts @@ -1,10 +1,16 @@ import * as assert from "assert"; -import { DEFAULT, defmulti, defmultiN, implementations } from "../src/index"; +import { + DEFAULT, + defmulti, + defmultiN, + implementations +} from "../src/index"; +// prettier-ignore describe("defmulti", () => { it("flatten", () => { const flatten = defmulti((x) => Object.prototype.toString.call(x)); - assert(flatten.add("[object Array]", (x, acc: any[]) => (x.forEach((y) => flatten(y, acc)), acc))); + assert(flatten.add("[object Array]", (x, acc: any[]) => (x.forEach((y: any) => flatten(y, acc)), acc))); assert(flatten.add("[object Object]", (x, acc: any[]) => { for (let k in x) flatten([k, x[k]], acc); return acc; })); assert(flatten.add("[object Null]", (_, acc) => acc)); assert(flatten.add(DEFAULT, (x, acc: any[]) => (acc.push(x.toString()), acc))); @@ -17,8 +23,8 @@ describe("defmulti", () => { it("sexpr", () => { const exec = defmulti((x) => Array.isArray(x) ? x[0] : typeof x); - assert(exec.add("+", ([_, ...args]) => args.reduce((acc, n) => acc + exec(n), 0))); - assert(exec.add("*", ([_, ...args]) => args.reduce((acc, n) => acc * exec(n), 1))); + assert(exec.add("+", ([_, ...args]) => args.reduce((acc: number, n: any) => acc + exec(n), 0))); + assert(exec.add("*", ([_, ...args]) => args.reduce((acc: number, n: any) => acc * exec(n), 1))); assert(exec.add("number", (x) => x)); assert(!exec.add("number", (x) => x)); assert(exec.add(DEFAULT, (x) => { throw new Error(`invalid expr: ${x}`); })); @@ -28,7 +34,7 @@ describe("defmulti", () => { }); it("apr", () => { - const apr = defmulti( + const apr = defmulti( ({ type, balance }) => `${type}-${balance < 1e4 ? "low" : balance < 5e4 ? "med" : "high"}` ); apr.add("current-low", ({ balance }) => balance * 0.005); diff --git a/packages/dgraph/CHANGELOG.md b/packages/dgraph/CHANGELOG.md index 8c8065a5d1..da0d5aa3ee 100644 --- a/packages/dgraph/CHANGELOG.md +++ b/packages/dgraph/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.10](https://github.com/thi-ng/umbrella/compare/@thi.ng/dgraph@1.1.9...@thi.ng/dgraph@1.1.10) (2019-07-07) + +**Note:** Version bump only for package @thi.ng/dgraph + + + + + ## [1.1.9](https://github.com/thi-ng/umbrella/compare/@thi.ng/dgraph@1.1.8...@thi.ng/dgraph@1.1.9) (2019-05-22) **Note:** Version bump only for package @thi.ng/dgraph diff --git a/packages/dgraph/package.json b/packages/dgraph/package.json index 5c8f633162..6bc7b4fb93 100644 --- a/packages/dgraph/package.json +++ b/packages/dgraph/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/dgraph", - "version": "1.1.9", + "version": "1.1.10", "description": "Type-agnostic directed acyclic graph (DAG) & graph operations", "module": "./index.js", "main": "./lib/index.js", @@ -25,18 +25,18 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/api": "^6.2.0", - "@thi.ng/associative": "^2.3.0", - "@thi.ng/equiv": "^1.0.6", - "@thi.ng/errors": "^1.0.6", - "@thi.ng/transducers": "^5.3.7" + "@thi.ng/api": "^6.3.0", + "@thi.ng/associative": "^2.4.0", + "@thi.ng/equiv": "^1.0.7", + "@thi.ng/errors": "^1.1.0", + "@thi.ng/transducers": "^5.4.0" }, "keywords": [ "data structure", diff --git a/packages/dgraph/src/index.ts b/packages/dgraph/src/index.ts index 12223169a5..765202f121 100644 --- a/packages/dgraph/src/index.ts +++ b/packages/dgraph/src/index.ts @@ -121,7 +121,7 @@ export class DGraph implements Iterable, ICopy> { if (!queue.size) { return sorted.reverse(); } - const node = queue.first(); + const node = queue.first()!; queue.delete(node); for (let d of [...g.immediateDependencies(node)]) { g.removeEdge(node, d); @@ -136,11 +136,11 @@ export class DGraph implements Iterable, ICopy> { } const transitive = (nodes: EquivMap>, x: T): Set => { - const deps: ArraySet = nodes.get(x); + const deps: ArraySet = nodes.get(x)!; if (deps) { return reduce( reducer( - null, + null, (acc, k: T) => >union(acc, transitive(nodes, k)) ), deps, diff --git a/packages/diff/CHANGELOG.md b/packages/diff/CHANGELOG.md index 8aa116042d..1b05a7bb42 100644 --- a/packages/diff/CHANGELOG.md +++ b/packages/diff/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [3.2.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/diff@3.1.3...@thi.ng/diff@3.2.0) (2019-07-07) + + +### Features + +* **diff:** enable TS strict compiler flags (refactor) ([5a7d90b](https://github.com/thi-ng/umbrella/commit/5a7d90b)) + + + + + ## [3.1.3](https://github.com/thi-ng/umbrella/compare/@thi.ng/diff@3.1.2...@thi.ng/diff@3.1.3) (2019-05-22) **Note:** Version bump only for package @thi.ng/diff diff --git a/packages/diff/package.json b/packages/diff/package.json index 05c49cf135..c517ffb333 100644 --- a/packages/diff/package.json +++ b/packages/diff/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/diff", - "version": "3.1.3", + "version": "3.2.0", "description": "Array & object Diff", "module": "./index.js", "main": "./lib/index.js", @@ -25,14 +25,14 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/api": "^6.2.0", - "@thi.ng/equiv": "^1.0.6" + "@thi.ng/api": "^6.3.0", + "@thi.ng/equiv": "^1.0.7" }, "keywords": [ "additions", diff --git a/packages/diff/src/api.ts b/packages/diff/src/api.ts index 4c21df3e8e..a2f056edec 100644 --- a/packages/diff/src/api.ts +++ b/packages/diff/src/api.ts @@ -14,12 +14,14 @@ export interface ArrayDiff { adds?: DiffKeyMap; dels?: DiffKeyMap; const?: DiffKeyMap; - linear?: (number | T)[]; + linear?: EditLog; } export interface ObjectDiff { distance: number; adds?: string[]; dels?: string[]; - edits?: (PropertyKey | T)[]; + edits?: EditLog; } + +export type EditLog = (K | T)[]; diff --git a/packages/diff/src/array.ts b/packages/diff/src/array.ts index 2c5ea46287..7eded422e0 100644 --- a/packages/diff/src/array.ts +++ b/packages/diff/src/array.ts @@ -1,5 +1,10 @@ import { equiv as _equiv } from "@thi.ng/equiv"; -import { ArrayDiff, DiffMode } from "./api"; +import { + ArrayDiff, + DiffKeyMap, + DiffMode, + EditLog +} from "./api"; let _cachedFP: Int32Array; let _cachedPath: Int32Array; @@ -20,12 +25,12 @@ const cachedPath = (size: number) => const simpleDiff = ( state: ArrayDiff, src: ArrayLike, - key: keyof ArrayDiff, + key: "adds" | "dels", logDir: number, mode: DiffMode ) => { const n = src.length; - const linear = state.linear; + const linear = >state.linear; state.distance = n; if (mode !== DiffMode.ONLY_DISTANCE) { for (let i = 0, j = 0; i < n; i++, j += 3) { @@ -34,7 +39,7 @@ const simpleDiff = ( linear[j + 2] = src[i]; } if (mode === DiffMode.FULL) { - const _state = state[key]; + const _state = >state[key]; for (let i = 0; i < n; i++) { _state[i] = src[i]; } @@ -59,8 +64,8 @@ const simpleDiff = ( * @param equiv equality predicate function */ export const diffArray = ( - a: ArrayLike, - b: ArrayLike, + a: ArrayLike | undefined | null, + b: ArrayLike | undefined | null, mode = DiffMode.FULL, equiv = _equiv ) => { @@ -75,13 +80,13 @@ export const diffArray = ( if (a === b || (a == null && b == null)) { return state; } else if (a == null || a.length === 0) { - return simpleDiff(state, b, "adds", 1, mode); + return simpleDiff(state, b!, "adds", 1, mode); } else if (b == null || b.length === 0) { return simpleDiff(state, a, "dels", -1, mode); } const reverse = a.length >= b.length; - let _a, _b, na, nb; + let _a: ArrayLike, _b: ArrayLike, na: number, nb: number; if (reverse) { _a = b; @@ -104,7 +109,7 @@ export const diffArray = ( epc.length = 0; pathPos.length = 0; - const snake = (k, p, pp) => { + const snake = (k: number, p: number, pp: number) => { const koff = k + offset; let r, y; if (p > pp) { @@ -172,20 +177,23 @@ const buildFullLog = ( b: ArrayLike, reverse: boolean ) => { - const linear = state.linear; - const _const = state.const; - let i = epc.length, - px = 0, - py = 0; - let adds, dels, aID, dID; + const linear = >state.linear; + const _const = >state.const; + let i = epc.length; + let px = 0; + let py = 0; + let adds: DiffKeyMap; + let dels: DiffKeyMap; + let aID: number; + let dID: number; if (reverse) { - adds = state.dels; - dels = state.adds; + adds = >state.dels; + dels = >state.adds; aID = -1; dID = 1; } else { - adds = state.adds; - dels = state.dels; + adds = >state.adds; + dels = >state.dels; aID = 1; dID = -1; } @@ -220,7 +228,7 @@ const buildLinearLog = ( reverse: boolean, inclConst: boolean ) => { - const linear = state.linear; + const linear = >state.linear; const aID = reverse ? -1 : 1; const dID = reverse ? 1 : -1; let i = epc.length, diff --git a/packages/diff/src/object.ts b/packages/diff/src/object.ts index 6b824bce84..b599c56c88 100644 --- a/packages/diff/src/object.ts +++ b/packages/diff/src/object.ts @@ -3,22 +3,24 @@ import { equiv } from "@thi.ng/equiv"; import { DiffMode, ObjectDiff } from "./api"; export const diffObject = ( - a: IObjectOf, - b: IObjectOf, + a: IObjectOf | undefined | null, + b: IObjectOf | undefined | null, mode = DiffMode.FULL, _equiv: Predicate2 = equiv ): ObjectDiff => a === b ? { distance: 0 } : mode === DiffMode.ONLY_DISTANCE - ? diffObjectDist(a, b, _equiv) - : diffObjectFull(a, b, _equiv); + ? diffObjectDist(a, b, _equiv) + : diffObjectFull(a, b, _equiv); const diffObjectDist = ( - a: IObjectOf, - b: IObjectOf, + a: IObjectOf | undefined | null, + b: IObjectOf | undefined | null, _equiv: Predicate2 ) => { + if (!a) a = {}; + if (!b) b = {}; let d = 0; for (let k in a) { const vb = b[k]; @@ -31,10 +33,12 @@ const diffObjectDist = ( }; const diffObjectFull = ( - a: IObjectOf, - b: IObjectOf, + a: IObjectOf | undefined | null, + b: IObjectOf | undefined | null, _equiv: Predicate2 ) => { + if (!a) a = {}; + if (!b) b = {}; let d = 0; const adds = []; const dels = []; diff --git a/packages/dlogic/CHANGELOG.md b/packages/dlogic/CHANGELOG.md index af7c68616b..3190bc9289 100644 --- a/packages/dlogic/CHANGELOG.md +++ b/packages/dlogic/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.0.7](https://github.com/thi-ng/umbrella/compare/@thi.ng/dlogic@1.0.6...@thi.ng/dlogic@1.0.7) (2019-07-07) + +**Note:** Version bump only for package @thi.ng/dlogic + + + + + ## [1.0.6](https://github.com/thi-ng/umbrella/compare/@thi.ng/dlogic@1.0.5...@thi.ng/dlogic@1.0.6) (2019-04-24) **Note:** Version bump only for package @thi.ng/dlogic diff --git a/packages/dlogic/package.json b/packages/dlogic/package.json index 3e6f5ed465..5aacc6ebc9 100644 --- a/packages/dlogic/package.json +++ b/packages/dlogic/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/dlogic", - "version": "1.0.6", + "version": "1.0.7", "description": "Assorted digital logic ops / constructs.", "module": "./index.js", "main": "./lib/index.js", @@ -25,11 +25,11 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "keywords": [ "boolean", diff --git a/packages/dot/CHANGELOG.md b/packages/dot/CHANGELOG.md index 1aea6fe436..4416d40147 100644 --- a/packages/dot/CHANGELOG.md +++ b/packages/dot/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.1.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/dot@1.0.12...@thi.ng/dot@1.1.0) (2019-07-07) + + +### Features + +* **dot:** enable TS strict compiler flags (refactor) ([29e0cb4](https://github.com/thi-ng/umbrella/commit/29e0cb4)) + + + + + ## [1.0.12](https://github.com/thi-ng/umbrella/compare/@thi.ng/dot@1.0.11...@thi.ng/dot@1.0.12) (2019-05-22) **Note:** Version bump only for package @thi.ng/dot diff --git a/packages/dot/package.json b/packages/dot/package.json index 3efe7da0c6..06b7b994fa 100644 --- a/packages/dot/package.json +++ b/packages/dot/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/dot", - "version": "1.0.12", + "version": "1.1.0", "description": "Graphviz DOM abstraction as vanilla JS objects & serialization to DOT format", "module": "./index.js", "main": "./lib/index.js", @@ -25,15 +25,15 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/api": "^6.2.0", - "@thi.ng/checks": "^2.1.6" + "@thi.ng/api": "^6.3.0", + "@thi.ng/checks": "^2.2.0" }, "keywords": [ "ES6", diff --git a/packages/dot/src/serialize.ts b/packages/dot/src/serialize.ts index 622796b2a3..024498053b 100644 --- a/packages/dot/src/serialize.ts +++ b/packages/dot/src/serialize.ts @@ -1,8 +1,13 @@ import { IObjectOf } from "@thi.ng/api"; import { isArray } from "@thi.ng/checks"; -import { Edge, Graph, GraphAttribs, Node } from "./api"; +import { + Edge, + Graph, + GraphAttribs, + Node +} from "./api"; -const wrapQ = (x) => `"${x}"`; +const wrapQ = (x: any) => `"${x}"`; const escape = (x: any) => String(x) diff --git a/packages/dsp/CHANGELOG.md b/packages/dsp/CHANGELOG.md index 916ec8b601..84c7b5aad3 100644 --- a/packages/dsp/CHANGELOG.md +++ b/packages/dsp/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.0.12](https://github.com/thi-ng/umbrella/compare/@thi.ng/dsp@1.0.11...@thi.ng/dsp@1.0.12) (2019-07-07) + +**Note:** Version bump only for package @thi.ng/dsp + + + + + ## [1.0.11](https://github.com/thi-ng/umbrella/compare/@thi.ng/dsp@1.0.10...@thi.ng/dsp@1.0.11) (2019-05-22) **Note:** Version bump only for package @thi.ng/dsp diff --git a/packages/dsp/package.json b/packages/dsp/package.json index c834c4556d..1f09ac88ed 100644 --- a/packages/dsp/package.json +++ b/packages/dsp/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/dsp", - "version": "1.0.11", + "version": "1.0.12", "description": "Assorted DSP utils, oscillators etc.", "module": "./index.js", "main": "./lib/index.js", @@ -25,15 +25,15 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/api": "^6.2.0", - "@thi.ng/math": "^1.3.0" + "@thi.ng/api": "^6.3.0", + "@thi.ng/math": "^1.4.0" }, "keywords": [ "additive", diff --git a/packages/dsp/src/osc.ts b/packages/dsp/src/osc.ts index 318ff53e55..51bd884a78 100644 --- a/packages/dsp/src/osc.ts +++ b/packages/dsp/src/osc.ts @@ -45,7 +45,6 @@ export class Oscillator implements Iterable { } export class AMFMOscillator extends Oscillator { - osc: StatelessOscillator; am: Oscillator; fm: Oscillator; diff --git a/packages/ecs/CHANGELOG.md b/packages/ecs/CHANGELOG.md deleted file mode 100644 index e1f51d52a0..0000000000 --- a/packages/ecs/CHANGELOG.md +++ /dev/null @@ -1,8 +0,0 @@ -# Change Log - -All notable changes to this project will be documented in this file. -See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. - -## 0.0.2 (2019-05-22) - -**Note:** Version bump only for package @thi.ng/ecs diff --git a/packages/equiv/CHANGELOG.md b/packages/equiv/CHANGELOG.md index 27400de480..1315f3ca6b 100644 --- a/packages/equiv/CHANGELOG.md +++ b/packages/equiv/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.0.7](https://github.com/thi-ng/umbrella/compare/@thi.ng/equiv@1.0.6...@thi.ng/equiv@1.0.7) (2019-07-07) + +**Note:** Version bump only for package @thi.ng/equiv + + + + + ## [1.0.6](https://github.com/thi-ng/umbrella/compare/@thi.ng/equiv@1.0.5...@thi.ng/equiv@1.0.6) (2019-04-24) **Note:** Version bump only for package @thi.ng/equiv diff --git a/packages/equiv/package.json b/packages/equiv/package.json index 7987464180..25081deb09 100644 --- a/packages/equiv/package.json +++ b/packages/equiv/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/equiv", - "version": "1.0.6", + "version": "1.0.7", "description": "Extensible deep equivalence checking for any data types", "module": "./index.js", "main": "./lib/index.js", @@ -25,12 +25,12 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "benchmark": "^2.1.4", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "keywords": [ "deep", diff --git a/packages/equiv/test/index.ts b/packages/equiv/test/index.ts index 4ed9489fd4..4a7449b1e0 100644 --- a/packages/equiv/test/index.ts +++ b/packages/equiv/test/index.ts @@ -1,9 +1,7 @@ import * as assert from "assert"; - import { equiv } from "../src/"; describe("equiv", () => { - it("null", () => { assert.ok(equiv(null, null)); assert.ok(equiv(null, undefined)); @@ -67,11 +65,11 @@ describe("equiv", () => { it("equiv impl", () => { class A { a: any; - constructor(a) { + constructor(a: any) { this.a = a; } - equiv(b) { + equiv(b: any) { return equiv(this.a, b); } } @@ -83,8 +81,23 @@ describe("equiv", () => { assert.ok(equiv(new A(1), new A(1))); assert.ok(equiv(new A(1), 1)); assert.ok(equiv(1, new A(1))); - assert.ok(equiv(1, { equiv(x) { return x === 1; } })); - assert.ok(equiv({ equiv(x) { return x === 1; } }, 1)); + assert.ok( + equiv(1, { + equiv(x: number) { + return x === 1; + } + }) + ); + assert.ok( + equiv( + { + equiv(x: number) { + return x === 1; + } + }, + 1 + ) + ); assert.ok(!equiv(new A(1), new A(2))); assert.ok(!equiv(new A(1), 2)); }); @@ -93,7 +106,12 @@ describe("equiv", () => { const a = new Set([1, 2, 3]); assert.ok(equiv(a, a)); assert.ok(equiv(a, new Set([3, 2, 1]))); - assert.ok(equiv(new Set([{ a: 1 }, new Set([{ b: 2 }, [3]])]), new Set([new Set([[3], { b: 2 }]), { a: 1 }]))); + assert.ok( + equiv( + new Set([{ a: 1 }, new Set([{ b: 2 }, [3]])]), + new Set([new Set([[3], { b: 2 }]), { a: 1 }]) + ) + ); assert.ok(!equiv(a, new Set([3, 2, 0]))); assert.ok(!equiv(a, [3, 2, 0])); assert.ok(!equiv(a, new Map([[3, 3], [2, 2], [1, 1]]))); diff --git a/packages/errors/CHANGELOG.md b/packages/errors/CHANGELOG.md index 3bd6c0fae6..97d3c9bf64 100644 --- a/packages/errors/CHANGELOG.md +++ b/packages/errors/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.1.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/errors@1.0.6...@thi.ng/errors@1.1.0) (2019-07-07) + + +### Features + +* **errors:** enable TS strict compiler flags (refactor) ([8460aea](https://github.com/thi-ng/umbrella/commit/8460aea)) + + + + + ## [1.0.6](https://github.com/thi-ng/umbrella/compare/@thi.ng/errors@1.0.5...@thi.ng/errors@1.0.6) (2019-04-24) **Note:** Version bump only for package @thi.ng/errors diff --git a/packages/errors/package.json b/packages/errors/package.json index 7a5b003a39..46fe4cf9d6 100644 --- a/packages/errors/package.json +++ b/packages/errors/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/errors", - "version": "1.0.6", + "version": "1.1.0", "description": "Custom error types and helper fns.", "module": "./index.js", "main": "./lib/index.js", @@ -25,11 +25,11 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "keywords": [ "error", diff --git a/packages/errors/src/illegal-arity.ts b/packages/errors/src/illegal-arity.ts index 6f26ead20a..3d3d18173d 100644 --- a/packages/errors/src/illegal-arity.ts +++ b/packages/errors/src/illegal-arity.ts @@ -4,6 +4,6 @@ export class IllegalArityError extends Error { } } -export const illegalArity = (n): never => { +export const illegalArity = (n: number): never => { throw new IllegalArityError(n); }; diff --git a/packages/fsm/CHANGELOG.md b/packages/fsm/CHANGELOG.md index e7c3dcdf1d..2f71535153 100644 --- a/packages/fsm/CHANGELOG.md +++ b/packages/fsm/CHANGELOG.md @@ -3,6 +3,23 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [2.2.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/fsm@2.1.15...@thi.ng/fsm@2.2.0) (2019-07-07) + + +### Bug Fixes + +* **fsm:** callback return types ([09b047b](https://github.com/thi-ng/umbrella/commit/09b047b)) + + +### Features + +* **color:** TS strictNullChecks, update color conversion fns ([04dc356](https://github.com/thi-ng/umbrella/commit/04dc356)) +* **fsm:** enable TS strict compiler flags (refactor) ([135b838](https://github.com/thi-ng/umbrella/commit/135b838)) + + + + + ## [2.1.15](https://github.com/thi-ng/umbrella/compare/@thi.ng/fsm@2.1.14...@thi.ng/fsm@2.1.15) (2019-05-22) **Note:** Version bump only for package @thi.ng/fsm diff --git a/packages/fsm/package.json b/packages/fsm/package.json index 0b32cd8bf1..9311792559 100644 --- a/packages/fsm/package.json +++ b/packages/fsm/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/fsm", - "version": "2.1.15", + "version": "2.2.0", "description": "Composable primitives for building declarative, transducer based Finite-State machines & parsers for arbitrary data streams", "module": "./index.js", "main": "./lib/index.js", @@ -25,18 +25,18 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/api": "^6.2.0", - "@thi.ng/arrays": "^0.1.9", - "@thi.ng/equiv": "^1.0.6", - "@thi.ng/errors": "^1.0.6", - "@thi.ng/transducers": "^5.3.7" + "@thi.ng/api": "^6.3.0", + "@thi.ng/arrays": "^0.2.0", + "@thi.ng/equiv": "^1.0.7", + "@thi.ng/errors": "^1.1.0", + "@thi.ng/transducers": "^5.4.0" }, "keywords": [ "ES6", diff --git a/packages/fsm/src/alts.ts b/packages/fsm/src/alts.ts index 9055578fc5..0ec4fac8bc 100644 --- a/packages/fsm/src/alts.ts +++ b/packages/fsm/src/alts.ts @@ -34,12 +34,14 @@ export const alts = ( success?: AltCallback, fail?: AltFallback ): Matcher => () => { - const alts = opts.map((o) => o()); + const alts: (MatcherInst | null)[] = opts.map((o) => o()); const buf: T[] = []; let active = alts.length; return (ctx, x) => { for ( - let i = alts.length, a: MatcherInst, next: MatchResult; + let i = alts.length, + a: MatcherInst | null, + next: MatchResult; --i >= 0; ) { @@ -58,7 +60,7 @@ export const alts = ( return active ? RES_PARTIAL : fallback - ? result(fallback(ctx, buf)) - : result(fail && fail(ctx, buf), Match.FAIL); + ? result(fallback(ctx, buf)) + : result(fail && fail(ctx, buf), Match.FAIL); }; }; diff --git a/packages/fsm/src/api.ts b/packages/fsm/src/api.ts index 73b476193d..7523720ccd 100644 --- a/packages/fsm/src/api.ts +++ b/packages/fsm/src/api.ts @@ -32,15 +32,19 @@ export type ResultBody = [number | string, T[]?]; export type AltCallback = ( ctx: C, - next: ResultBody, + next: ResultBody | undefined, x: T[] -) => ResultBody; +) => ResultBody | undefined; -export type LitCallback = (ctx: C, x: T) => ResultBody; +export type LitCallback = (ctx: C, x: T) => ResultBody | undefined; -export type SeqCallback = (ctx: C, buf: T[]) => ResultBody; +export type SeqCallback = ( + ctx: C, + buf: T[] +) => ResultBody | undefined; export type AltFallback = SeqCallback; -export const RES_PARTIAL = Object.freeze({ type: Match.PARTIAL }); -export const RES_FAIL = Object.freeze({ type: Match.FAIL }); +// prettier-ignore +export const RES_PARTIAL: MatchResult = Object.freeze({ type: Match.PARTIAL }); +export const RES_FAIL: MatchResult = Object.freeze({ type: Match.FAIL }); diff --git a/packages/fsm/src/fsm.ts b/packages/fsm/src/fsm.ts index 614e742d11..f96a12ab53 100644 --- a/packages/fsm/src/fsm.ts +++ b/packages/fsm/src/fsm.ts @@ -13,7 +13,7 @@ import { Match, Matcher } from "./api"; /** * Finite-state machine transducer / iterator with support for single * lookahead value. Takes an object of `states` and their matchers, an - * arbitrary context object and an `initial` state ID. + * arbitrary context object and an `initial` state ID (default: "start"). * * The returned transducer consumes inputs of type `T` and produces * results of type `R`. The results are produced by callbacks of the @@ -67,7 +67,7 @@ export function fsm( let curr = states[initial] ? states[initial]() : illegalArgs(`invalid initial state: ${initial}`); - return [ + return >[ init, complete, (acc, x) => { @@ -78,7 +78,7 @@ export function fsm( if (type >= Match.FULL) { const next = body && states[body[0]]; if (next) { - currID = body[0]; + currID = body![0]; curr = next(); } else { illegalState( diff --git a/packages/fsm/src/range.ts b/packages/fsm/src/range.ts index 5a9db4447b..4fa777b62f 100644 --- a/packages/fsm/src/range.ts +++ b/packages/fsm/src/range.ts @@ -1,6 +1,11 @@ import { alts } from "./alts"; import { altsLit } from "./alts-lit"; -import { AltCallback, AltFallback, LitCallback, Matcher } from "./api"; +import { + AltCallback, + AltFallback, + LitCallback, + Matcher +} from "./api"; import { result } from "./result"; /** @@ -31,7 +36,7 @@ export const range = ( export const digit = ( success?: LitCallback, fail?: LitCallback -): Matcher => range("0", "9", success, fail); +): Matcher => range("0", "9", success, fail); /** * Matcher for single A-Z or a-z characters. @@ -43,7 +48,12 @@ export const alpha = ( success?: AltCallback, fail?: AltFallback ): Matcher => - alts([range("a", "z"), range("A", "Z")], null, success, fail); + alts( + [range("a", "z"), range("A", "Z")], + undefined, + success, + fail + ); /** * Combination of `digit()` and `alpha()`. @@ -54,7 +64,7 @@ export const alpha = ( export const alphaNum = ( success?: AltCallback, fail?: AltFallback -): Matcher => alts([alpha(), digit()], null, success, fail); +): Matcher => alts([alpha(), digit()], undefined, success, fail); const WS = new Set([" ", "\n", "\t", "\r"]); diff --git a/packages/fsm/src/result.ts b/packages/fsm/src/result.ts index 1337fafcfd..3667203091 100644 --- a/packages/fsm/src/result.ts +++ b/packages/fsm/src/result.ts @@ -1,6 +1,6 @@ import { Match, MatchResult, ResultBody } from "./api"; export const result = ( - body: ResultBody, + body?: ResultBody, type = Match.FULL ): MatchResult => ({ type, body }); diff --git a/packages/geom-accel/CHANGELOG.md b/packages/geom-accel/CHANGELOG.md index 015d8e495c..2057d99ae4 100644 --- a/packages/geom-accel/CHANGELOG.md +++ b/packages/geom-accel/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.2.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-accel@1.1.17...@thi.ng/geom-accel@1.2.0) (2019-07-07) + + +### Features + +* **geom-accel:** enable TS strict compiler flags (refactor) ([e19e6bc](https://github.com/thi-ng/umbrella/commit/e19e6bc)) + + + + + ## [1.1.17](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-accel@1.1.16...@thi.ng/geom-accel@1.1.17) (2019-05-22) **Note:** Version bump only for package @thi.ng/geom-accel diff --git a/packages/geom-accel/package.json b/packages/geom-accel/package.json index 8448ee12e1..935f727bd5 100644 --- a/packages/geom-accel/package.json +++ b/packages/geom-accel/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/geom-accel", - "version": "1.1.17", + "version": "1.2.0", "description": "nD spatial indexing data structures", "module": "./index.js", "main": "./lib/index.js", @@ -25,20 +25,20 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/api": "^6.2.0", - "@thi.ng/arrays": "^0.1.9", - "@thi.ng/geom-api": "^0.2.3", - "@thi.ng/heaps": "^1.0.10", - "@thi.ng/math": "^1.3.0", - "@thi.ng/transducers": "^5.3.7", - "@thi.ng/vectors": "^2.5.6" + "@thi.ng/api": "^6.3.0", + "@thi.ng/arrays": "^0.2.0", + "@thi.ng/geom-api": "^0.2.4", + "@thi.ng/heaps": "^1.1.0", + "@thi.ng/math": "^1.4.0", + "@thi.ng/transducers": "^5.4.0", + "@thi.ng/vectors": "^3.0.0" }, "keywords": [ "2D", diff --git a/packages/geom-accel/src/kdtree.ts b/packages/geom-accel/src/kdtree.ts index 7ef1b7fcaa..f79e45378e 100644 --- a/packages/geom-accel/src/kdtree.ts +++ b/packages/geom-accel/src/kdtree.ts @@ -5,17 +5,19 @@ import { Heap } from "@thi.ng/heaps"; import { EPS } from "@thi.ng/math"; import { distSq, ReadonlyVec, Vec } from "@thi.ng/vectors"; -const CMP = (a, b) => b[0] - a[0]; +type MaybeKdNode = KdNode | null; + +const CMP = (a: [number, any], b: [number, any]) => b[0] - a[0]; export class KdNode { - parent: KdNode; - l: KdNode; - r: KdNode; + parent: KdNode | null; + l: KdNode | null; + r: KdNode | null; d: number; k: K; v: V; - constructor(parent: KdNode, dim: number, key: K, val: V) { + constructor(parent: MaybeKdNode, dim: number, key: K, val: V) { this.parent = parent; this.d = dim; this.k = key; @@ -24,7 +26,7 @@ export class KdNode { } *[Symbol.iterator](): IterableIterator> { - let queue: KdNode[] = [this]; + let queue: MaybeKdNode[] = [this]; while (queue.length) { const n = queue.pop(); if (n) { @@ -35,7 +37,7 @@ export class KdNode { } *keys(): IterableIterator { - let queue: KdNode[] = [this]; + let queue: MaybeKdNode[] = [this]; while (queue.length) { const n = queue.pop(); if (n) { @@ -45,7 +47,7 @@ export class KdNode { } } - height() { + height(): number { return ( 1 + Math.max(this.l ? this.l.height() : 0, this.r ? this.r.height() : 0) @@ -62,7 +64,7 @@ export class KdNode { */ export class KdTree implements ICopy>, ISpatialAccel { - root: KdNode; + root: KdNode | null; dim: number; protected _length: number; @@ -92,19 +94,19 @@ export class KdTree add(p: K, v: V, eps = EPS) { eps *= eps; const search = ( - node: KdNode, - parent: KdNode - ): KdNode => + node: MaybeKdNode, + parent: MaybeKdNode + ): MaybeKdNode => node ? search(p[node.d] < node.k[node.d] ? node.l : node.r, node) : parent; - let parent: KdNode; + let parent: MaybeKdNode; if (this.root) { parent = nearest1(p, [eps * eps, null], [], this.dim, this.root)[1]; if (parent) { return false; } - parent = search(this.root, null); + parent = search(this.root, null)!; const dim = parent.d; parent[p[dim] < parent.k[dim] ? "l" : "r"] = new KdNode( parent, @@ -128,13 +130,13 @@ export class KdTree } addKey(k: Readonly, eps = EPS) { - return this.add(k, null, eps); + return this.add(k, null!, eps); } addKeys(ks: Iterable>, eps = EPS) { let ok = true; for (let k of ks) { - ok = this.add(k, null, eps) && ok; + ok = this.add(k, null!, eps) && ok; } return ok; } @@ -151,7 +153,7 @@ export class KdTree has(k: Readonly, eps = EPS) { return ( - this.root && + !!this.root && !!nearest1(k, [eps * eps, null], [], this.dim, this.root)[1] ); } @@ -224,7 +226,7 @@ export class KdTree balanceRatio() { return this._length - ? this.root.height() / (Math.log(this._length) / Math.LN2) + ? this.root!.height() / (Math.log(this._length) / Math.LN2) : 0; } @@ -233,24 +235,26 @@ export class KdTree maxNum: number, maxDist = Infinity ) { - const nodes = new Heap<[number, KdNode]>(null, { compare: CMP }); + const nodes = new Heap<[number, KdNode | null]>(null, { + compare: CMP + }); maxDist *= maxDist; - const c: [number, KdNode] = [maxDist, null]; + const c: [number, KdNode | null] = [maxDist, null]; for (let i = maxNum; --i >= 0; ) { nodes.push(c); } - nearest(q, nodes, [], this.dim, maxNum, this.root); + nearest(q, nodes, [], this.dim, maxNum, this.root!); return nodes.values.sort(CMP); } protected buildTree( points: Pair[], depth: number, - parent: KdNode + parent: KdNode | null ) { const n = points.length; if (n === 0) { - return; + return null; } this._length++; let dim = depth % this.dim; @@ -275,9 +279,9 @@ export class KdTree */ const find = ( p: K, - node: KdNode, + node: MaybeKdNode, epsSq: number -) => { +): KdNode | undefined => { if (!node) return; return distSq(p, node.k) <= epsSq ? node @@ -285,10 +289,10 @@ const find = ( }; const findMin = ( - node: KdNode, + node: MaybeKdNode, dim: number -): KdNode => { - if (!node) return; +): MaybeKdNode => { + if (!node) return null; if (node.d === dim) { return node.l ? findMin(node.l, dim) : node; } @@ -320,15 +324,15 @@ const remove = (node: KdNode) => { parent[node.k[pdim] < parent.k[pdim] ? "l" : "r"] = null; return; } - let next: KdNode; + let next: MaybeKdNode; let nextP: K; if (node.r) { - next = findMin(node.r, node.d); + next = findMin(node.r, node.d)!; nextP = next.k; remove(next); node.k = nextP; } else { - next = findMin(node.l, node.d); + next = findMin(node.l, node.d)!; nextP = next.k; remove(next); node.r = node.l; @@ -339,7 +343,7 @@ const remove = (node: KdNode) => { const nearest = ( q: K, - acc: Heap<[number, KdNode]>, + acc: Heap<[number, MaybeKdNode]>, tmp: Vec, dims: number, maxNum: number, @@ -369,7 +373,7 @@ const nearest = ( : q[ndim] < p[ndim] ? node.l : node.r; - nearest(q, acc, tmp, dims, maxNum, best); + nearest(q, acc, tmp, dims, maxNum, best!); if (!acc.length || ndist < acc.peek()[0]) { if (acc.length >= maxNum) { acc.pushPop([ndist, node]); @@ -393,11 +397,11 @@ const nearest = ( */ const nearest1 = ( q: K, - acc: [number, KdNode], + acc: [number, MaybeKdNode], tmp: Vec, dims: number, node: KdNode -): [number, KdNode] => { +): [number, MaybeKdNode] => { const p = node.k; const ndist = distSq(p, q); if (!node.l && !node.r) { @@ -419,7 +423,7 @@ const nearest1 = ( : q[ndim] < p[ndim] ? node.l : node.r; - nearest1(q, acc, tmp, dims, best); + nearest1(q, acc, tmp, dims, best!); if (ndist < acc[0]) { acc[0] = ndist; acc[1] = node; diff --git a/packages/geom-api/CHANGELOG.md b/packages/geom-api/CHANGELOG.md index fc1ba1ae09..c1f0585079 100644 --- a/packages/geom-api/CHANGELOG.md +++ b/packages/geom-api/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.2.4](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-api@0.2.3...@thi.ng/geom-api@0.2.4) (2019-07-07) + +**Note:** Version bump only for package @thi.ng/geom-api + + + + + ## [0.2.3](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-api@0.2.2...@thi.ng/geom-api@0.2.3) (2019-05-22) **Note:** Version bump only for package @thi.ng/geom-api diff --git a/packages/geom-api/package.json b/packages/geom-api/package.json index 7c751fc623..0b51598bf3 100644 --- a/packages/geom-api/package.json +++ b/packages/geom-api/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/geom-api", - "version": "0.2.3", + "version": "0.2.4", "description": "Shared type & interface declarations for @thi.ng/geom packages", "module": "./index.js", "main": "./lib/index.js", @@ -25,15 +25,15 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/api": "^6.2.0", - "@thi.ng/vectors": "^2.5.6" + "@thi.ng/api": "^6.3.0", + "@thi.ng/vectors": "^3.0.0" }, "keywords": [ "ES6", diff --git a/packages/geom-arc/CHANGELOG.md b/packages/geom-arc/CHANGELOG.md index efb5599a15..e67ff1b8b3 100644 --- a/packages/geom-arc/CHANGELOG.md +++ b/packages/geom-arc/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.2.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-arc@0.1.17...@thi.ng/geom-arc@0.2.0) (2019-07-07) + + +### Features + +* **geom-arc:** enable TS strict compiler flags (refactor) ([b9752ba](https://github.com/thi-ng/umbrella/commit/b9752ba)) + + + + + ## [0.1.17](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-arc@0.1.16...@thi.ng/geom-arc@0.1.17) (2019-05-22) **Note:** Version bump only for package @thi.ng/geom-arc diff --git a/packages/geom-arc/package.json b/packages/geom-arc/package.json index 34d3343d1e..38a359184a 100644 --- a/packages/geom-arc/package.json +++ b/packages/geom-arc/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/geom-arc", - "version": "0.1.17", + "version": "0.2.0", "description": "2D circular / elliptic arc operations", "module": "./index.js", "main": "./lib/index.js", @@ -25,18 +25,18 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/checks": "^2.1.6", - "@thi.ng/geom-api": "^0.2.3", - "@thi.ng/geom-resample": "^0.1.17", - "@thi.ng/math": "^1.3.0", - "@thi.ng/vectors": "^2.5.6" + "@thi.ng/checks": "^2.2.0", + "@thi.ng/geom-api": "^0.2.4", + "@thi.ng/geom-resample": "^0.2.0", + "@thi.ng/math": "^1.4.0", + "@thi.ng/vectors": "^3.0.0" }, "keywords": [ "2D", diff --git a/packages/geom-arc/src/bounds.ts b/packages/geom-arc/src/bounds.ts index d2cdceada4..03e8a63bb6 100644 --- a/packages/geom-arc/src/bounds.ts +++ b/packages/geom-arc/src/bounds.ts @@ -6,6 +6,7 @@ import { min2, ReadonlyVec, set2, + Vec, VecPair } from "@thi.ng/vectors"; import { pointAtTheta } from "./point-at"; @@ -19,7 +20,7 @@ export const bounds = ( ): VecPair => { const min = set2([], MAX2); const max = set2([], MIN2); - const p = []; + const p: Vec = []; const update = (theta: number) => { pointAtTheta(pos, r, axis, theta, p); min2(null, min, p); diff --git a/packages/geom-arc/src/sample.ts b/packages/geom-arc/src/sample.ts index c2eab38c99..25d416bc2a 100644 --- a/packages/geom-arc/src/sample.ts +++ b/packages/geom-arc/src/sample.ts @@ -28,7 +28,7 @@ export const sample = ( ? { num: opts, last: true } : { num: DEFAULT_SAMPLES, ...opts }; let delta = end - start; - let num = opts.theta ? Math.round(delta / opts.theta) : opts.num; + let num = opts.theta ? Math.round(delta / opts.theta) : opts.num!; delta /= num; opts.last !== false && num++; const pts: Vec[] = new Array(num); diff --git a/packages/geom-clip/CHANGELOG.md b/packages/geom-clip/CHANGELOG.md index ee85c25e57..53678fc2f9 100644 --- a/packages/geom-clip/CHANGELOG.md +++ b/packages/geom-clip/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.1.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-clip@0.0.19...@thi.ng/geom-clip@0.1.0) (2019-07-07) + + +### Features + +* **geom-clip:** enable TS strict compiler flags (refactor) ([9b6a2ae](https://github.com/thi-ng/umbrella/commit/9b6a2ae)) + + + + + ## [0.0.19](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-clip@0.0.18...@thi.ng/geom-clip@0.0.19) (2019-05-22) **Note:** Version bump only for package @thi.ng/geom-clip diff --git a/packages/geom-clip/package.json b/packages/geom-clip/package.json index 576b2a2312..d639419dfb 100644 --- a/packages/geom-clip/package.json +++ b/packages/geom-clip/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/geom-clip", - "version": "0.0.19", + "version": "0.1.0", "description": "2D line & convex polygon clipping (Liang-Barsky / Sutherland-Hodgeman)", "module": "./index.js", "main": "./lib/index.js", @@ -25,17 +25,17 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/geom-isec": "^0.2.0", - "@thi.ng/geom-poly-utils": "^0.1.17", - "@thi.ng/math": "^1.3.0", - "@thi.ng/vectors": "^2.5.6" + "@thi.ng/geom-isec": "^0.3.0", + "@thi.ng/geom-poly-utils": "^0.1.18", + "@thi.ng/math": "^1.4.0", + "@thi.ng/vectors": "^3.0.0" }, "keywords": [ "2D", diff --git a/packages/geom-clip/src/liang-barsky.ts b/packages/geom-clip/src/liang-barsky.ts index 75b0ae8160..eb1e421779 100644 --- a/packages/geom-clip/src/liang-barsky.ts +++ b/packages/geom-clip/src/liang-barsky.ts @@ -28,7 +28,7 @@ export const liangBarsky2 = ( max: Vec, ca?: Vec, cb?: Vec -): [Vec, Vec, number, number] => { +): [Vec, Vec, number, number] | undefined => { const ax = a[0]; const ay = a[1]; const dx = b[0] - ax; diff --git a/packages/geom-clip/src/sutherland-hodgeman.ts b/packages/geom-clip/src/sutherland-hodgeman.ts index 502923517e..589eccada2 100644 --- a/packages/geom-clip/src/sutherland-hodgeman.ts +++ b/packages/geom-clip/src/sutherland-hodgeman.ts @@ -1,7 +1,7 @@ import { intersectLineLine } from "@thi.ng/geom-isec"; import { centroid } from "@thi.ng/geom-poly-utils"; import { EPS } from "@thi.ng/math"; -import { corner2, ReadonlyVec } from "@thi.ng/vectors"; +import { corner2, ReadonlyVec, Vec } from "@thi.ng/vectors"; /** * Extended version of Sutherland-Hodgeman convex polygon clipping @@ -23,7 +23,7 @@ export const sutherlandHodgeman = ( ) => { bc = bc || centroid(bounds); for (let ne = bounds.length, j = ne - 1, i = 0; i < ne; j = i, i++) { - const clipped = []; + const clipped: Vec[] = []; const ca = bounds[j]; const cb = bounds[i]; const sign = corner2(ca, cb, bc, eps); @@ -33,10 +33,12 @@ export const sutherlandHodgeman = ( const cqsign = corner2(ca, cb, q, eps); if (corner2(ca, cb, p, eps) === sign) { clipped.push( - cqsign !== sign ? intersectLineLine(ca, cb, p, q).isec : q + cqsign !== sign + ? intersectLineLine(ca, cb, p, q).isec + : q ); } else if (cqsign === sign) { - clipped.push(intersectLineLine(ca, cb, p, q).isec, q); + clipped.push(intersectLineLine(ca, cb, p, q).isec, q); } } if (clipped.length < 2) { diff --git a/packages/geom-closest-point/CHANGELOG.md b/packages/geom-closest-point/CHANGELOG.md index 47f4f76e9e..53feedd876 100644 --- a/packages/geom-closest-point/CHANGELOG.md +++ b/packages/geom-closest-point/CHANGELOG.md @@ -3,6 +3,23 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.3.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-closest-point@0.2.3...@thi.ng/geom-closest-point@0.3.0) (2019-07-07) + + +### Bug Fixes + +* **geom-closest-point:** type hints (TS 3.5.2) ([fa146d7](https://github.com/thi-ng/umbrella/commit/fa146d7)) +* **geom-closest-point:** update polyline & point array fns ([c5b4757](https://github.com/thi-ng/umbrella/commit/c5b4757)) + + +### Features + +* **geom-clostest-point:** enable TS strict compiler flags (refactor) ([b6b69e6](https://github.com/thi-ng/umbrella/commit/b6b69e6)) + + + + + ## [0.2.3](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-closest-point@0.2.2...@thi.ng/geom-closest-point@0.2.3) (2019-05-22) diff --git a/packages/geom-closest-point/package.json b/packages/geom-closest-point/package.json index a7a88988a8..df63a482be 100644 --- a/packages/geom-closest-point/package.json +++ b/packages/geom-closest-point/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/geom-closest-point", - "version": "0.2.3", + "version": "0.3.0", "description": "Closest point / proximity helpers", "module": "./index.js", "main": "./lib/index.js", @@ -25,15 +25,15 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/math": "^1.3.0", - "@thi.ng/vectors": "^2.5.6" + "@thi.ng/math": "^1.4.0", + "@thi.ng/vectors": "^3.0.0" }, "keywords": [ "ES6", diff --git a/packages/geom-closest-point/src/index.ts b/packages/geom-closest-point/src/index.ts index 8c92e1ecd6..a5f35f9924 100644 --- a/packages/geom-closest-point/src/index.ts +++ b/packages/geom-closest-point/src/index.ts @@ -57,7 +57,7 @@ export const closestPointLine = ( p: ReadonlyVec, a: ReadonlyVec, b: ReadonlyVec -) => mixN([], a, b, closestT(p, a, b)); +) => mixN([], a, b, closestT(p, a, b) || 0); /** * Returns distance from `p` to closest point to infinite line `a` -> @@ -128,7 +128,8 @@ export const closestPointPolyline = ( closed = false, out: Vec = [] ) => { - const tmp = []; + if (!pts.length) return; + const tmp: Vec = []; const n = pts.length - 1; let minD = Infinity, i, @@ -172,7 +173,7 @@ export const farthestPointSegment = ( to = points.length ) => { let maxD = -1; - let maxIdx; + let maxIdx: number = -1; const tmp = empty(a); for (let i = from; i < to; i++) { const p = points[i]; @@ -185,9 +186,13 @@ export const farthestPointSegment = ( return [maxIdx, Math.sqrt(maxD)]; }; -export const closestPointArray = (p: ReadonlyVec, pts: Vec[]) => { +export const closestPointArray = ( + p: ReadonlyVec, + pts: Vec[], + out: Vec = [] +) => { let minD = Infinity; - let closest: Vec; + let closest: Vec | undefined; for (let i = pts.length; --i >= 0; ) { const d = distSq(pts[i], p); if (d < minD) { @@ -195,7 +200,7 @@ export const closestPointArray = (p: ReadonlyVec, pts: Vec[]) => { closest = pts[i]; } } - return closest; + return closest ? set(out, closest) : undefined; }; export const distToPlane = (p: ReadonlyVec, n: ReadonlyVec, w: number) => @@ -236,9 +241,9 @@ export const closestPointRect = ( minW = w; } } - return minID === 0 - ? setC2(out, minW, clamp(p[1], bmin[1], bmax[1])) - : setC2(out, clamp(p[0], bmin[0], bmax[0]), minW); + return minID! === 0 + ? setC2(out, minW!, clamp(p[1], bmin[1], bmax[1])) + : setC2(out, clamp(p[0], bmin[0], bmax[0]), minW!); }; export const closestPointAABB = ( @@ -260,24 +265,24 @@ export const closestPointAABB = ( minW = w; } } - return minID === 0 + return minID! === 0 ? setC3( out, - minW, + minW!, clamp(p[1], bmin[1], bmax[1]), clamp(p[2], bmin[2], bmax[2]) ) - : minID === 1 + : minID! === 1 ? setC3( out, clamp(p[0], bmin[0], bmax[0]), - minW, + minW!, clamp(p[2], bmin[2], bmax[2]) ) : setC3( out, clamp(p[0], bmin[0], bmax[0]), clamp(p[1], bmin[1], bmax[1]), - minW + minW! ); }; diff --git a/packages/geom-hull/CHANGELOG.md b/packages/geom-hull/CHANGELOG.md index fc6f858cd9..db462a5eb7 100644 --- a/packages/geom-hull/CHANGELOG.md +++ b/packages/geom-hull/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.0.20](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-hull@0.0.19...@thi.ng/geom-hull@0.0.20) (2019-07-07) + +**Note:** Version bump only for package @thi.ng/geom-hull + + + + + ## [0.0.19](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-hull@0.0.18...@thi.ng/geom-hull@0.0.19) (2019-05-22) **Note:** Version bump only for package @thi.ng/geom-hull diff --git a/packages/geom-hull/package.json b/packages/geom-hull/package.json index 4d4b50327d..31fae02ec9 100644 --- a/packages/geom-hull/package.json +++ b/packages/geom-hull/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/geom-hull", - "version": "0.0.19", + "version": "0.0.20", "description": "Fast 2D convex hull (Graham Scan)", "module": "./index.js", "main": "./lib/index.js", @@ -25,15 +25,15 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/math": "^1.3.0", - "@thi.ng/vectors": "^2.5.6" + "@thi.ng/math": "^1.4.0", + "@thi.ng/vectors": "^3.0.0" }, "keywords": [ "2D", diff --git a/packages/geom-isec/CHANGELOG.md b/packages/geom-isec/CHANGELOG.md index 7148413a92..cc6c174655 100644 --- a/packages/geom-isec/CHANGELOG.md +++ b/packages/geom-isec/CHANGELOG.md @@ -3,6 +3,23 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.3.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-isec@0.2.0...@thi.ng/geom-isec@0.3.0) (2019-07-07) + + +### Bug Fixes + +* **geom-isec:** add missing return type for intersectRayCircle() ([eaceb1a](https://github.com/thi-ng/umbrella/commit/eaceb1a)) +* **geom-isec:** update madd & perpendicular call sites ([#95](https://github.com/thi-ng/umbrella/issues/95)) ([d2e9969](https://github.com/thi-ng/umbrella/commit/d2e9969)) + + +### Features + +* **geom-isec:** enable TS strict compiler flags (refactor) ([4cdbd31](https://github.com/thi-ng/umbrella/commit/4cdbd31)) + + + + + # [0.2.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-isec@0.1.16...@thi.ng/geom-isec@0.2.0) (2019-05-22) diff --git a/packages/geom-isec/package.json b/packages/geom-isec/package.json index f5eaa4d98b..4783ea8778 100644 --- a/packages/geom-isec/package.json +++ b/packages/geom-isec/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/geom-isec", - "version": "0.2.0", + "version": "0.3.0", "description": "2D/3D shape intersection checks", "module": "./index.js", "main": "./lib/index.js", @@ -25,18 +25,18 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/api": "^6.2.0", - "@thi.ng/geom-api": "^0.2.3", - "@thi.ng/geom-closest-point": "^0.2.3", - "@thi.ng/math": "^1.3.0", - "@thi.ng/vectors": "^2.5.6" + "@thi.ng/api": "^6.3.0", + "@thi.ng/geom-api": "^0.2.4", + "@thi.ng/geom-closest-point": "^0.3.0", + "@thi.ng/math": "^1.4.0", + "@thi.ng/vectors": "^3.0.0" }, "keywords": [ "2D", diff --git a/packages/geom-isec/src/circle-circle.ts b/packages/geom-isec/src/circle-circle.ts index dfd0ac044f..ca42567dd8 100644 --- a/packages/geom-isec/src/circle-circle.ts +++ b/packages/geom-isec/src/circle-circle.ts @@ -6,7 +6,7 @@ import { maddN, mag, mulN, - perpendicularLeft2, + perpendicularCCW, ReadonlyVec, sub } from "@thi.ng/vectors"; @@ -27,8 +27,8 @@ export const intersectCircleCircle = ( ar *= ar; const alpha = (ar - br * br + d * d) / (2 * d); const h = Math.sqrt(ar - alpha * alpha); - const p = maddN([], a, delta, alpha / d); - const t = mulN(null, perpendicularLeft2(null, delta), h / d); + const p = maddN([], delta, alpha / d, a); + const t = mulN(null, perpendicularCCW(null, delta), h / d); return { type: IntersectionType.INTERSECT, isec: [add([], p, t), sub([], p, t)] diff --git a/packages/geom-isec/src/ray-circle.ts b/packages/geom-isec/src/ray-circle.ts index c82b54aa0b..0295a768b3 100644 --- a/packages/geom-isec/src/ray-circle.ts +++ b/packages/geom-isec/src/ray-circle.ts @@ -1,5 +1,11 @@ import { IntersectionResult, IntersectionType } from "@thi.ng/geom-api"; -import { dot, maddN, magSq, ReadonlyVec, sub } from "@thi.ng/vectors"; +import { + dot, + maddN, + magSq, + ReadonlyVec, + sub +} from "@thi.ng/vectors"; import { NONE } from "./api"; export const intersectRayCircle = ( @@ -19,12 +25,13 @@ export const intersectRayCircle = ( a >= 0 ? b >= 0 ? a > b - ? [maddN(delta, rpos, dir, b), maddN([], rpos, dir, a)] - : [maddN(delta, rpos, dir, a), maddN([], rpos, dir, b)] - : [maddN(delta, rpos, dir, a)] + ? [maddN(delta, dir, b, rpos), maddN([], dir, a, rpos)] + : [maddN(delta, dir, a, rpos), maddN([], dir, b, rpos)] + : [maddN(delta, dir, a, rpos)] : b >= 0 - ? [maddN(delta, rpos, dir, b)] - : undefined; + ? [maddN(delta, dir, b, rpos)] + : undefined; return isec ? { type: IntersectionType.INTERSECT, isec } : NONE; } + return NONE; }; diff --git a/packages/geom-isec/src/ray-line.ts b/packages/geom-isec/src/ray-line.ts index 641d6a3446..9430b43678 100644 --- a/packages/geom-isec/src/ray-line.ts +++ b/packages/geom-isec/src/ray-line.ts @@ -22,7 +22,7 @@ export const intersectRayLine = ( return t >= 0 && s >= 0 && s <= 1 ? { type: IntersectionType.INTERSECT, - isec: maddN([], rpos, dir, t), + isec: maddN([], dir, t, rpos), alpha: t } : NONE; diff --git a/packages/geom-isec/src/ray-plane.ts b/packages/geom-isec/src/ray-plane.ts index 6a1dfda2c7..a46dbd7429 100644 --- a/packages/geom-isec/src/ray-plane.ts +++ b/packages/geom-isec/src/ray-plane.ts @@ -24,7 +24,7 @@ export const intersectRayPlane = ( const alpha = dot(normal, isec) / d; return { type: IntersectionType.INTERSECT, - isec: maddN(isec, rpos, dir, alpha), + isec: maddN(isec, dir, alpha, rpos), alpha }; } diff --git a/packages/geom-isec/src/ray-poly.ts b/packages/geom-isec/src/ray-poly.ts index 233d8ba5a0..efc89f7404 100644 --- a/packages/geom-isec/src/ray-poly.ts +++ b/packages/geom-isec/src/ray-poly.ts @@ -1,5 +1,5 @@ import { IntersectionResult, IntersectionType } from "@thi.ng/geom-api"; -import { maddN2, ReadonlyVec } from "@thi.ng/vectors"; +import { maddN2, ReadonlyVec, Vec } from "@thi.ng/vectors"; import { NONE } from "./api"; import { intersectRayLine } from "./ray-line"; @@ -30,7 +30,7 @@ export const intersectRayPolyline = ( return cross > 0 ? { type: IntersectionType.INTERSECT, - isec: maddN2([], rpos, dir, minD), + isec: maddN2([], dir, minD, rpos), inside: !(cross & 1), alpha: minD } @@ -52,11 +52,11 @@ export const intersectRayPolylineAll = ( i = pts[0]; j = pts[1]; } - const res = []; + const res: [number, Vec][] = []; for (let k = 0; k <= n; i = j, j = pts[++k]) { const d = intersectRayLine(rpos, dir, i, j).alpha; if (d !== undefined) { - res.push([d, maddN2([], rpos, dir, d)]); + res.push([d, maddN2([], dir, d, rpos)]); } } return res.length diff --git a/packages/geom-isec/src/ray-rect.ts b/packages/geom-isec/src/ray-rect.ts index f7829b817c..05c36d97df 100644 --- a/packages/geom-isec/src/ray-rect.ts +++ b/packages/geom-isec/src/ray-rect.ts @@ -87,14 +87,14 @@ const intersectWith = ( ? { type: IntersectionType.INTERSECT, inside, - isec: [maddN([], rpos, dir, tmax)], + isec: [maddN([], dir, tmax, rpos)], alpha: tmax } : { type: IntersectionType.INTERSECT, isec: [ - maddN([], rpos, dir, tmin), - maddN([], rpos, dir, tmax) + maddN([], dir, tmin, rpos), + maddN([], dir, tmax, rpos) ], alpha: tmin, beta: tmax diff --git a/packages/geom-isoline/CHANGELOG.md b/packages/geom-isoline/CHANGELOG.md index e6ea904626..f8f33a181b 100644 --- a/packages/geom-isoline/CHANGELOG.md +++ b/packages/geom-isoline/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.1.18](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-isoline@0.1.17...@thi.ng/geom-isoline@0.1.18) (2019-07-07) + +**Note:** Version bump only for package @thi.ng/geom-isoline + + + + + ## [0.1.17](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-isoline@0.1.16...@thi.ng/geom-isoline@0.1.17) (2019-05-22) **Note:** Version bump only for package @thi.ng/geom-isoline diff --git a/packages/geom-isoline/package.json b/packages/geom-isoline/package.json index 339827fba9..860b9a8ebf 100644 --- a/packages/geom-isoline/package.json +++ b/packages/geom-isoline/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/geom-isoline", - "version": "0.1.17", + "version": "0.1.18", "description": "Fast 2D contour line extraction / generation", "module": "./index.js", "main": "./lib/index.js", @@ -25,15 +25,15 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/transducers": "^5.3.7", - "@thi.ng/vectors": "^2.5.6" + "@thi.ng/transducers": "^5.4.0", + "@thi.ng/vectors": "^3.0.0" }, "keywords": [ "2D", diff --git a/packages/geom-isoline/src/index.ts b/packages/geom-isoline/src/index.ts index ab1937b280..ca88d0472e 100644 --- a/packages/geom-isoline/src/index.ts +++ b/packages/geom-isoline/src/index.ts @@ -126,8 +126,8 @@ export function* isolines(src: ReadonlyVec, w: number, h: number, iso: number) { let from: number; let to = -1; let clear: number; - let x: number; - let y: number; + let x!: number; + let y!: number; const w1 = w - 1; const h1 = h - 1; const cells = range2d(h, w); @@ -158,8 +158,8 @@ export function* isolines(src: ReadonlyVec, w: number, h: number, iso: number) { ? 0 : 2 : from === 4 - ? 4 - : 6; + ? 4 + : 6; to = S10[idx]; clear = S10[idx + 1]; } else { @@ -174,7 +174,7 @@ export function* isolines(src: ReadonlyVec, w: number, h: number, iso: number) { coded[y * w + x] = clear; } if (to >= 0) { - curr.push(contourVertex(src, w, x, y, to, iso)); + curr.push(contourVertex(src, w, x, y, to, iso)!); x += NEXT_EDGES[to]; y += NEXT_EDGES[to + 1]; } else { diff --git a/packages/geom-poly-utils/CHANGELOG.md b/packages/geom-poly-utils/CHANGELOG.md index 7a9a8d19b9..43b410168e 100644 --- a/packages/geom-poly-utils/CHANGELOG.md +++ b/packages/geom-poly-utils/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.1.18](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-poly-utils@0.1.17...@thi.ng/geom-poly-utils@0.1.18) (2019-07-07) + + +### Bug Fixes + +* **geom-poly-utils:** update madd call sites ([#95](https://github.com/thi-ng/umbrella/issues/95)) ([3250c82](https://github.com/thi-ng/umbrella/commit/3250c82)) + + + + + ## [0.1.17](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-poly-utils@0.1.16...@thi.ng/geom-poly-utils@0.1.17) (2019-05-22) **Note:** Version bump only for package @thi.ng/geom-poly-utils diff --git a/packages/geom-poly-utils/package.json b/packages/geom-poly-utils/package.json index 40dd0fe88d..b8f3bb747d 100644 --- a/packages/geom-poly-utils/package.json +++ b/packages/geom-poly-utils/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/geom-poly-utils", - "version": "0.1.17", + "version": "0.1.18", "description": "Polygon / triangle analysis & processing utilities", "module": "./index.js", "main": "./lib/index.js", @@ -25,17 +25,17 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/errors": "^1.0.6", - "@thi.ng/geom-api": "^0.2.3", - "@thi.ng/math": "^1.3.0", - "@thi.ng/vectors": "^2.5.6" + "@thi.ng/errors": "^1.1.0", + "@thi.ng/geom-api": "^0.2.4", + "@thi.ng/math": "^1.4.0", + "@thi.ng/vectors": "^3.0.0" }, "keywords": [ "2D", diff --git a/packages/geom-poly-utils/src/barycentric.ts b/packages/geom-poly-utils/src/barycentric.ts index b4f43e1fb7..6f27305e92 100644 --- a/packages/geom-poly-utils/src/barycentric.ts +++ b/packages/geom-poly-utils/src/barycentric.ts @@ -34,5 +34,5 @@ export const fromBarycentric = ( b: ReadonlyVec, c: ReadonlyVec, p: ReadonlyVec, - out?: Vec + out: Vec = [] ) => addW3(out, a, b, c, p[0], p[1], p[2]); diff --git a/packages/geom-poly-utils/src/equilateral.ts b/packages/geom-poly-utils/src/equilateral.ts index 1ce8cfecac..53766a9251 100644 --- a/packages/geom-poly-utils/src/equilateral.ts +++ b/packages/geom-poly-utils/src/equilateral.ts @@ -3,7 +3,7 @@ import { maddN2, mag, normalize, - perpendicularLeft2, + perpendicularCCW, sub2, Vec } from "@thi.ng/vectors"; @@ -12,8 +12,8 @@ export const equilateralTriangle2 = (a: Vec, b: Vec) => { const dir = sub2([], b, a); const c = normalize( null, - perpendicularLeft2([], dir), + perpendicularCCW([], dir), mag(dir) * Math.sin(THIRD_PI) ); - return [a, b, maddN2(null, c, dir, 0.5)]; + return [a, b, maddN2(null, dir, 0.5, c)]; }; diff --git a/packages/geom-resample/CHANGELOG.md b/packages/geom-resample/CHANGELOG.md index 757b4b4d0f..9784037ed3 100644 --- a/packages/geom-resample/CHANGELOG.md +++ b/packages/geom-resample/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.2.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-resample@0.1.17...@thi.ng/geom-resample@0.2.0) (2019-07-07) + + +### Features + +* **geom-resample:** enable TS strict compiler flags (refactor) ([c4b0919](https://github.com/thi-ng/umbrella/commit/c4b0919)) + + + + + ## [0.1.17](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-resample@0.1.16...@thi.ng/geom-resample@0.1.17) (2019-05-22) **Note:** Version bump only for package @thi.ng/geom-resample diff --git a/packages/geom-resample/package.json b/packages/geom-resample/package.json index b2ed43052a..3a5baac7d5 100644 --- a/packages/geom-resample/package.json +++ b/packages/geom-resample/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/geom-resample", - "version": "0.1.17", + "version": "0.2.0", "description": "Customizable nD polyline interpolation, re-sampling, splitting & nearest point computation", "module": "./index.js", "main": "./lib/index.js", @@ -25,18 +25,18 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/checks": "^2.1.6", - "@thi.ng/geom-api": "^0.2.3", - "@thi.ng/geom-closest-point": "^0.2.3", - "@thi.ng/math": "^1.3.0", - "@thi.ng/vectors": "^2.5.6" + "@thi.ng/checks": "^2.2.0", + "@thi.ng/geom-api": "^0.2.4", + "@thi.ng/geom-closest-point": "^0.3.0", + "@thi.ng/math": "^1.4.0", + "@thi.ng/vectors": "^3.0.0" }, "keywords": [ "2D", diff --git a/packages/geom-resample/src/resample.ts b/packages/geom-resample/src/resample.ts index 908588c12a..87b7577396 100644 --- a/packages/geom-resample/src/resample.ts +++ b/packages/geom-resample/src/resample.ts @@ -1,11 +1,11 @@ import { isPlainObject } from "@thi.ng/checks"; -import { copyVectors, ReadonlyVec } from "@thi.ng/vectors"; import { DEFAULT_SAMPLES, SamplingOpts } from "@thi.ng/geom-api"; +import { copyVectors, ReadonlyVec } from "@thi.ng/vectors"; import { Sampler } from "./sampler"; export const resample = ( pts: ReadonlyVec[], - opts: number | Partial, + opts?: number | Partial, closed = false, copy = false ) => { @@ -15,10 +15,16 @@ export const resample = ( ? closed ? opts.dist ? sampler.sampleUniform(opts.dist, opts.last) - : sampler.sampleFixedNum(opts.num, opts.last) + : sampler.sampleFixedNum( + opts.num || DEFAULT_SAMPLES, + opts.last + ) : opts.dist - ? sampler.sampleUniform(opts.dist, opts.last !== false) - : sampler.sampleFixedNum(opts.num, opts.last !== false) + ? sampler.sampleUniform(opts.dist, opts.last !== false) + : sampler.sampleFixedNum( + opts.num || DEFAULT_SAMPLES, + opts.last !== false + ) : sampler.sampleFixedNum(opts || DEFAULT_SAMPLES, !closed); } return copy ? copyVectors(pts) : pts; diff --git a/packages/geom-resample/src/sampler.ts b/packages/geom-resample/src/sampler.ts index 644cb11278..05e78738e4 100644 --- a/packages/geom-resample/src/sampler.ts +++ b/packages/geom-resample/src/sampler.ts @@ -1,3 +1,4 @@ +import { closestPointSegment, closestT } from "@thi.ng/geom-closest-point"; import { fit01 } from "@thi.ng/math"; import { dist, @@ -11,11 +12,10 @@ import { Vec, VecPair } from "@thi.ng/vectors"; -import { closestPointSegment, closestT } from "@thi.ng/geom-closest-point"; export class Sampler { points: ReadonlyVec[]; - index: number[]; + index!: number[]; constructor(points: ReadonlyVec[], closed = false) { if (closed) { @@ -28,10 +28,11 @@ export class Sampler { } totalLength() { - return this.index[this.index.length - 1]; + const idx = this.index; + return idx ? idx[idx.length - 1] : 0; } - pointAt(t: number) { + pointAt(t: number): Vec | undefined { const pts = this.points; const n = pts.length - 1; if (n < 0) { @@ -59,8 +60,8 @@ export class Sampler { closestPoint(p: ReadonlyVec) { const pts = this.points; - const tmp = []; - const closest = []; + const tmp: Vec = []; + const closest: Vec = []; let minD = Infinity; for (let i = 0, n = pts.length - 1; i < n; i++) { if (closestPointSegment(p, pts[i], pts[i + 1], tmp)) { @@ -71,16 +72,16 @@ export class Sampler { } } } - return closest; + return minD < Infinity ? closest : undefined; } closestT(p: ReadonlyVec) { const pts = this.points; const idx = this.index; - const tmp = []; - const closest = []; + const tmp: Vec = []; + const closest: Vec = []; let minD = Infinity; - let minI; + let minI = -1; for (let i = 0, n = idx.length - 1; i < n; i++) { if (closestPointSegment(p, pts[i], pts[i + 1], tmp)) { const d = distSq(p, tmp); @@ -91,16 +92,16 @@ export class Sampler { } } } - return ( - fit01( - closestT(p, pts[minI], pts[minI + 1]), - idx[minI], - idx[minI + 1] - ) / this.totalLength() - ); + return minI >= 0 + ? fit01( + closestT(p, pts[minI], pts[minI + 1]) || 0, + idx[minI], + idx[minI + 1] + ) / this.totalLength() + : undefined; } - segmentAt(t: number): VecPair { + segmentAt(t: number): VecPair | undefined { let i = this.indexAt(t); if (i === undefined) { return; @@ -114,12 +115,13 @@ export class Sampler { return seg ? normalize(null, sub([], seg[1], seg[0]), n) : undefined; } - splitAt(t: number) { + splitAt(t: number): Vec[][] | undefined { if (t <= 0 || t >= 1) { return [this.points]; } const p = this.pointAt(t); - const i = Math.max(1, this.indexAt(t)); + if (!p) return; + const i = Math.max(1, this.indexAt(t)!); const head = this.points.slice(0, i); const tail = this.points.slice(i); if (!eqDelta(head[i - 1], p)) { @@ -132,7 +134,8 @@ export class Sampler { } splitNear(p: ReadonlyVec) { - return this.splitAt(this.closestT(p)); + const t = this.closestT(p); + return t !== undefined ? this.splitAt(t) : undefined; } indexAt(t: number) { diff --git a/packages/geom-resample/src/simplify.ts b/packages/geom-resample/src/simplify.ts index f831cc4a28..db61f9ab1b 100644 --- a/packages/geom-resample/src/simplify.ts +++ b/packages/geom-resample/src/simplify.ts @@ -31,7 +31,7 @@ export const simplify = (pts: Vec[], eps = 0, closed = false) => { from + 1, to ); - if (maxD <= eps) { + if (maxIdx < 0 || maxD <= eps) { return; } $(from, maxIdx); diff --git a/packages/geom-splines/CHANGELOG.md b/packages/geom-splines/CHANGELOG.md index 3eeb1d1c5d..a8bb7e79cd 100644 --- a/packages/geom-splines/CHANGELOG.md +++ b/packages/geom-splines/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.2.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-splines@0.1.17...@thi.ng/geom-splines@0.2.0) (2019-07-07) + + +### Features + +* **geom-splines:** enable TS strict compiler flags (refactor) ([748417b](https://github.com/thi-ng/umbrella/commit/748417b)) + + + + + ## [0.1.17](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-splines@0.1.16...@thi.ng/geom-splines@0.1.17) (2019-05-22) **Note:** Version bump only for package @thi.ng/geom-splines diff --git a/packages/geom-splines/package.json b/packages/geom-splines/package.json index cac40d7667..07adef3397 100644 --- a/packages/geom-splines/package.json +++ b/packages/geom-splines/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/geom-splines", - "version": "0.1.17", + "version": "0.2.0", "description": "nD cubic & quadratic curve analysis, conversion, interpolation, splitting", "module": "./index.js", "main": "./lib/index.js", @@ -25,19 +25,19 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/checks": "^2.1.6", - "@thi.ng/geom-api": "^0.2.3", - "@thi.ng/geom-arc": "^0.1.17", - "@thi.ng/geom-resample": "^0.1.17", - "@thi.ng/math": "^1.3.0", - "@thi.ng/vectors": "^2.5.6" + "@thi.ng/checks": "^2.2.0", + "@thi.ng/geom-api": "^0.2.4", + "@thi.ng/geom-arc": "^0.2.0", + "@thi.ng/geom-resample": "^0.2.0", + "@thi.ng/math": "^1.4.0", + "@thi.ng/vectors": "^3.0.0" }, "keywords": [ "2D", diff --git a/packages/geom-splines/src/cubic-bounds.ts b/packages/geom-splines/src/cubic-bounds.ts index 5c28e3b91d..42ac3e00a0 100644 --- a/packages/geom-splines/src/cubic-bounds.ts +++ b/packages/geom-splines/src/cubic-bounds.ts @@ -1,5 +1,5 @@ import { mixCubic } from "@thi.ng/math"; -import { ReadonlyVec, VecPair, Vec } from "@thi.ng/vectors"; +import { ReadonlyVec, Vec, VecPair } from "@thi.ng/vectors"; const axisBounds = ( min: Vec, @@ -46,8 +46,8 @@ export const cubicBounds = ( c: ReadonlyVec, d: ReadonlyVec ): VecPair => { - const min = []; - const max = []; + const min: Vec = []; + const max: Vec = []; for (let i = a.length; --i >= 0; ) { axisBounds(min, max, i, a[i], b[i], c[i], d[i]); } diff --git a/packages/geom-splines/src/cubic-sample.ts b/packages/geom-splines/src/cubic-sample.ts index c19ed370a9..a178a1de20 100644 --- a/packages/geom-splines/src/cubic-sample.ts +++ b/packages/geom-splines/src/cubic-sample.ts @@ -1,12 +1,17 @@ import { isNumber, isPlainObject } from "@thi.ng/checks"; import { DEFAULT_SAMPLES, SamplingOpts } from "@thi.ng/geom-api"; import { Sampler } from "@thi.ng/geom-resample"; -import { mixCubic, ReadonlyVec, set, Vec } from "@thi.ng/vectors"; +import { + mixCubic, + ReadonlyVec, + set, + Vec +} from "@thi.ng/vectors"; export const sampleCubic = ( pts: ReadonlyVec[], opts?: number | Partial -) => { +): Vec[] => { if (isPlainObject(opts) && (opts).dist !== undefined) { return new Sampler( sampleCubic(pts, (opts).num || DEFAULT_SAMPLES) @@ -26,8 +31,8 @@ export const sampleCubic = ( }; const res: Vec[] = []; const [a, b, c, d] = pts; - const delta = 1 / opts.num; - for (let t = 0; t < opts.num; t++) { + const delta = 1 / opts.num!; + for (let t = 0; t < opts.num!; t++) { res.push(mixCubic([], a, b, c, d, t * delta)); } opts.last && res.push(set([], d)); diff --git a/packages/geom-splines/src/quadratic-sample.ts b/packages/geom-splines/src/quadratic-sample.ts index 7c859f1440..c2266fb303 100644 --- a/packages/geom-splines/src/quadratic-sample.ts +++ b/packages/geom-splines/src/quadratic-sample.ts @@ -1,12 +1,17 @@ import { isNumber, isPlainObject } from "@thi.ng/checks"; import { DEFAULT_SAMPLES, SamplingOpts } from "@thi.ng/geom-api"; import { Sampler } from "@thi.ng/geom-resample"; -import { mixQuadratic, ReadonlyVec, set, Vec } from "@thi.ng/vectors"; +import { + mixQuadratic, + ReadonlyVec, + set, + Vec +} from "@thi.ng/vectors"; export const sampleQuadratic = ( points: ReadonlyVec[], opts?: number | Partial -) => { +): Vec[] => { if (isPlainObject(opts) && (opts).dist !== undefined) { return new Sampler( sampleQuadratic(points, (opts).num || DEFAULT_SAMPLES) @@ -25,9 +30,9 @@ export const sampleQuadratic = ( ...opts }; const res: Vec[] = []; - const delta = 1 / opts.num; + const delta = 1 / opts.num!; const [a, b, c] = points; - for (let t = 0; t < opts.num; t++) { + for (let t = 0; t < opts.num!; t++) { res.push(mixQuadratic([], a, b, c, t * delta)); } opts.last && res.push(set([], c)); diff --git a/packages/geom-subdiv-curve/CHANGELOG.md b/packages/geom-subdiv-curve/CHANGELOG.md index bb4c638b5a..e3cb5de442 100644 --- a/packages/geom-subdiv-curve/CHANGELOG.md +++ b/packages/geom-subdiv-curve/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.1.17](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-subdiv-curve@0.1.16...@thi.ng/geom-subdiv-curve@0.1.17) (2019-07-07) + +**Note:** Version bump only for package @thi.ng/geom-subdiv-curve + + + + + ## [0.1.16](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-subdiv-curve@0.1.15...@thi.ng/geom-subdiv-curve@0.1.16) (2019-05-22) **Note:** Version bump only for package @thi.ng/geom-subdiv-curve diff --git a/packages/geom-subdiv-curve/package.json b/packages/geom-subdiv-curve/package.json index 3192a3a902..b0da46cb40 100644 --- a/packages/geom-subdiv-curve/package.json +++ b/packages/geom-subdiv-curve/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/geom-subdiv-curve", - "version": "0.1.16", + "version": "0.1.17", "description": "Freely customizable, iterative subdivision curves for open / closed input geometries", "module": "./index.js", "main": "./lib/index.js", @@ -25,16 +25,16 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/geom-api": "^0.2.3", - "@thi.ng/transducers": "^5.3.7", - "@thi.ng/vectors": "^2.5.6" + "@thi.ng/geom-api": "^0.2.4", + "@thi.ng/transducers": "^5.4.0", + "@thi.ng/vectors": "^3.0.0" }, "keywords": [ "2D", diff --git a/packages/geom-tessellate/CHANGELOG.md b/packages/geom-tessellate/CHANGELOG.md index 2541f8c51c..87fd584dc3 100644 --- a/packages/geom-tessellate/CHANGELOG.md +++ b/packages/geom-tessellate/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.2.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-tessellate@0.1.17...@thi.ng/geom-tessellate@0.2.0) (2019-07-07) + + +### Features + +* **geom-tessellate:** enable TS strict compiler flags (refactor) ([8d610c3](https://github.com/thi-ng/umbrella/commit/8d610c3)) + + + + + ## [0.1.17](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-tessellate@0.1.16...@thi.ng/geom-tessellate@0.1.17) (2019-05-22) **Note:** Version bump only for package @thi.ng/geom-tessellate diff --git a/packages/geom-tessellate/package.json b/packages/geom-tessellate/package.json index d36e0c1441..9fcfc33214 100644 --- a/packages/geom-tessellate/package.json +++ b/packages/geom-tessellate/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/geom-tessellate", - "version": "0.1.17", + "version": "0.2.0", "description": "2D/3D polygon tessellators", "module": "./index.js", "main": "./lib/index.js", @@ -25,19 +25,19 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/checks": "^2.1.6", - "@thi.ng/geom-api": "^0.2.3", - "@thi.ng/geom-isec": "^0.2.0", - "@thi.ng/geom-poly-utils": "^0.1.17", - "@thi.ng/transducers": "^5.3.7", - "@thi.ng/vectors": "^2.5.6" + "@thi.ng/checks": "^2.2.0", + "@thi.ng/geom-api": "^0.2.4", + "@thi.ng/geom-isec": "^0.3.0", + "@thi.ng/geom-poly-utils": "^0.1.18", + "@thi.ng/transducers": "^5.4.0", + "@thi.ng/vectors": "^3.0.0" }, "keywords": [ "2D", diff --git a/packages/geom-tessellate/src/tessellate.ts b/packages/geom-tessellate/src/tessellate.ts index 65ca201355..6ba07304a8 100644 --- a/packages/geom-tessellate/src/tessellate.ts +++ b/packages/geom-tessellate/src/tessellate.ts @@ -20,7 +20,7 @@ export function tessellate( points: ReadonlyVec[], tessFns: Iterable ): Vec[][]; -export function tessellate(...args) { +export function tessellate(...args: any[]) { return transduce( scan( reducer( diff --git a/packages/geom-voronoi/CHANGELOG.md b/packages/geom-voronoi/CHANGELOG.md index d0dd50c8a4..8910c82ab8 100644 --- a/packages/geom-voronoi/CHANGELOG.md +++ b/packages/geom-voronoi/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.1.18](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-voronoi@0.1.17...@thi.ng/geom-voronoi@0.1.18) (2019-07-07) + +**Note:** Version bump only for package @thi.ng/geom-voronoi + + + + + ## [0.1.17](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-voronoi@0.1.16...@thi.ng/geom-voronoi@0.1.17) (2019-05-22) **Note:** Version bump only for package @thi.ng/geom-voronoi diff --git a/packages/geom-voronoi/package.json b/packages/geom-voronoi/package.json index 4e90339f3e..4b2250138d 100644 --- a/packages/geom-voronoi/package.json +++ b/packages/geom-voronoi/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/geom-voronoi", - "version": "0.1.17", + "version": "0.1.18", "description": "Fast, incremental 2D Delaunay & Voronoi mesh implementation", "module": "./index.js", "main": "./lib/index.js", @@ -25,21 +25,21 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/api": "^6.2.0", - "@thi.ng/checks": "^2.1.6", - "@thi.ng/geom-clip": "^0.0.19", - "@thi.ng/geom-isec": "^0.2.0", - "@thi.ng/geom-poly-utils": "^0.1.17", - "@thi.ng/math": "^1.3.0", - "@thi.ng/quad-edge": "^0.1.4", - "@thi.ng/vectors": "^2.5.6" + "@thi.ng/api": "^6.3.0", + "@thi.ng/checks": "^2.2.0", + "@thi.ng/geom-clip": "^0.1.0", + "@thi.ng/geom-isec": "^0.3.0", + "@thi.ng/geom-poly-utils": "^0.1.18", + "@thi.ng/math": "^1.4.0", + "@thi.ng/quad-edge": "^0.2.0", + "@thi.ng/vectors": "^3.0.0" }, "keywords": [ "2D", diff --git a/packages/geom-voronoi/src/index.ts b/packages/geom-voronoi/src/index.ts index c40b5f7722..9ab922ef24 100644 --- a/packages/geom-voronoi/src/index.ts +++ b/packages/geom-voronoi/src/index.ts @@ -92,7 +92,7 @@ export class DVMesh { addKeys(pts: Iterable, eps?: number) { for (let p of pts) { - this.add(p, null, eps); + this.add(p, undefined, eps); } this.computeDual(); } @@ -139,7 +139,7 @@ export class DVMesh { const visitedEdges: IObjectOf = {}; const visitedVerts: IObjectOf = {}; while (work.length) { - const e = work.pop(); + const e = work.pop()!; if (visitedEdges[e.id]) continue; visitedEdges[e.id] = true; if (!e.origin || !visitedVerts[e.origin.id]) { @@ -154,7 +154,7 @@ export class DVMesh { isBounds = isBounds && this.isBoundary(c); const id = this.nextID++; e.origin = { - pos: !isBounds ? circumCenter2(a, b, c) : ZERO2, + pos: !isBounds ? circumCenter2(a, b, c)! : ZERO2, id }; visitedVerts[id] = true; @@ -266,7 +266,7 @@ export class DVMesh { const visitedEdges: IObjectOf = {}; const visitedVerts: IObjectOf = {}; while (work.length) { - e = work.pop(); + e = work.pop()!; if (visitedEdges[e.id]) continue; visitedEdges[e.id] = true; if ( diff --git a/packages/geom/CHANGELOG.md b/packages/geom/CHANGELOG.md index cb85fcb24c..2e9b0cb87b 100644 --- a/packages/geom/CHANGELOG.md +++ b/packages/geom/CHANGELOG.md @@ -3,6 +3,23 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.6.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom@1.5.0...@thi.ng/geom@1.6.0) (2019-07-07) + + +### Bug Fixes + +* **geom:** update madd/maddN call sites ([#95](https://github.com/thi-ng/umbrella/issues/95)) ([a96e028](https://github.com/thi-ng/umbrella/commit/a96e028)) + + +### Features + +* **geom:** enable TS strict compiler flags (refactor) ([aa10de0](https://github.com/thi-ng/umbrella/commit/aa10de0)) +* **geom:** TS strictNullChecks, update various classes & ops ([636dea7](https://github.com/thi-ng/umbrella/commit/636dea7)) + + + + + # [1.5.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom@1.4.2...@thi.ng/geom@1.5.0) (2019-05-22) diff --git a/packages/geom/package.json b/packages/geom/package.json index 5ae93dd02c..086210c695 100644 --- a/packages/geom/package.json +++ b/packages/geom/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/geom", - "version": "1.5.0", + "version": "1.6.0", "description": "2D geometry types, polymorphic operations, SVG generation", "module": "./index.js", "main": "./lib/index.js", @@ -25,38 +25,38 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/api": "^6.2.0", - "@thi.ng/arrays": "^0.1.9", - "@thi.ng/checks": "^2.1.6", - "@thi.ng/compose": "^1.2.5", - "@thi.ng/defmulti": "^1.0.9", - "@thi.ng/equiv": "^1.0.6", - "@thi.ng/errors": "^1.0.6", - "@thi.ng/geom-api": "^0.2.3", - "@thi.ng/geom-arc": "^0.1.17", - "@thi.ng/geom-clip": "^0.0.19", - "@thi.ng/geom-closest-point": "^0.2.3", - "@thi.ng/geom-hull": "^0.0.19", - "@thi.ng/geom-isec": "^0.2.0", - "@thi.ng/geom-poly-utils": "^0.1.17", - "@thi.ng/geom-resample": "^0.1.17", - "@thi.ng/geom-splines": "^0.1.17", - "@thi.ng/geom-subdiv-curve": "^0.1.16", - "@thi.ng/geom-tessellate": "^0.1.17", - "@thi.ng/hiccup": "^3.1.9", - "@thi.ng/hiccup-svg": "^3.1.22", - "@thi.ng/math": "^1.3.0", - "@thi.ng/matrices": "^0.4.0", - "@thi.ng/random": "^1.1.7", - "@thi.ng/transducers": "^5.3.7", - "@thi.ng/vectors": "^2.5.6" + "@thi.ng/api": "^6.3.0", + "@thi.ng/arrays": "^0.2.0", + "@thi.ng/checks": "^2.2.0", + "@thi.ng/compose": "^1.3.0", + "@thi.ng/defmulti": "^1.1.0", + "@thi.ng/equiv": "^1.0.7", + "@thi.ng/errors": "^1.1.0", + "@thi.ng/geom-api": "^0.2.4", + "@thi.ng/geom-arc": "^0.2.0", + "@thi.ng/geom-clip": "^0.1.0", + "@thi.ng/geom-closest-point": "^0.3.0", + "@thi.ng/geom-hull": "^0.0.20", + "@thi.ng/geom-isec": "^0.3.0", + "@thi.ng/geom-poly-utils": "^0.1.18", + "@thi.ng/geom-resample": "^0.2.0", + "@thi.ng/geom-splines": "^0.2.0", + "@thi.ng/geom-subdiv-curve": "^0.1.17", + "@thi.ng/geom-tessellate": "^0.2.0", + "@thi.ng/hiccup": "^3.2.0", + "@thi.ng/hiccup-svg": "^3.2.0", + "@thi.ng/math": "^1.4.0", + "@thi.ng/matrices": "^0.5.0", + "@thi.ng/random": "^1.1.8", + "@thi.ng/transducers": "^5.4.0", + "@thi.ng/vectors": "^3.0.0" }, "keywords": [ "2D", diff --git a/packages/geom/src/api.ts b/packages/geom/src/api.ts index 2e56d85506..2f26b4fb16 100644 --- a/packages/geom/src/api.ts +++ b/packages/geom/src/api.ts @@ -23,10 +23,10 @@ import { export abstract class APC implements PCLike { points: Vec[]; - attribs: Attribs; + attribs?: Attribs; - constructor(points: Vec[], attribs?: Attribs) { - this.points = points; + constructor(points?: Vec[], attribs?: Attribs) { + this.points = points || []; this.attribs = attribs; } @@ -41,7 +41,7 @@ export abstract class APC implements PCLike { export class AABB implements AABBLike { pos: Vec; size: Vec; - attribs: Attribs; + attribs?: Attribs; constructor( pos: Vec = [0, 0, 0], @@ -51,7 +51,6 @@ export class AABB implements AABBLike { this.pos = pos; this.size = isNumber(size) ? [size, size, size] : size; this.attribs = attribs; - this.attribs = attribs; } get type() { @@ -77,7 +76,7 @@ export class Arc implements IHiccupShape, IHiccupPathSegment { axis: number; xl: boolean; cw: boolean; - attribs: Attribs; + attribs?: Attribs; constructor( pos: Vec, @@ -172,7 +171,7 @@ export class Arc implements IHiccupShape, IHiccupPathSegment { export class Circle implements IHiccupShape { pos: Vec; r: number; - attribs: Attribs; + attribs?: Attribs; constructor(pos: Vec = [0, 0], r = 1, attribs?: Attribs) { this.pos = pos; @@ -219,7 +218,7 @@ export class Cubic extends APC implements IHiccupPathSegment { export class Ellipse implements IHiccupShape { pos: Vec; r: Vec; - attribs: Attribs; + attribs?: Attribs; constructor( pos: Vec = [0, 0], @@ -302,7 +301,7 @@ export class Line extends APC implements IHiccupShape, IHiccupPathSegment { export class Path implements IHiccupShape { segments: PathSegment[]; closed: boolean; - attribs: Attribs; + attribs?: Attribs; constructor(segments?: PathSegment[], attribs?: Attribs) { this.segments = segments || []; @@ -340,7 +339,7 @@ export class Path implements IHiccupShape { if (n > 1) { dest.push(["M", segments[0].point]); for (let i = 1; i < n; i++) { - dest = dest.concat(segments[i].geo.toHiccupPathSegments()); + dest = dest.concat(segments[i].geo!.toHiccupPathSegments()); } if (this.closed) { dest.push(["Z"]); @@ -353,7 +352,7 @@ export class Path implements IHiccupShape { export class Plane implements IHiccupShape { normal: Vec; w: number; - attribs: Attribs; + attribs?: Attribs; constructor(normal: Vec = [0, 1, 0], w = 0, attribs?: Attribs) { this.normal = normal; @@ -477,7 +476,7 @@ export class Quadratic extends APC implements IHiccupShape, IHiccupPathSegment { export class Ray implements IHiccupShape { pos: Vec; dir: Vec; - attribs: Attribs; + attribs?: Attribs; constructor(pos: Vec, dir: Vec, attribs?: Attribs) { this.pos = pos; @@ -500,7 +499,7 @@ export class Ray implements IHiccupShape { "line", this.attribs, this.pos, - maddN2([], this.pos, this.dir, 1e6) + maddN2([], this.dir, 1e6, this.pos) ]; } } @@ -508,7 +507,7 @@ export class Ray implements IHiccupShape { export class Rect implements AABBLike, IHiccupShape { pos: Vec; size: Vec; - attribs: Attribs; + attribs?: Attribs; constructor(pos: Vec = [0, 0], size: number | Vec = 1, attribs?: Attribs) { this.pos = pos; @@ -538,7 +537,7 @@ export class Rect implements AABBLike, IHiccupShape { export class Sphere implements IHiccupShape { pos: Vec; r: number; - attribs: Attribs; + attribs?: Attribs; constructor(pos: Vec = [0, 0, 0], r = 1, attribs?: Attribs) { this.pos = pos; diff --git a/packages/geom/src/ctors/arc.ts b/packages/geom/src/ctors/arc.ts index 207b34c40d..145418b32a 100644 --- a/packages/geom/src/ctors/arc.ts +++ b/packages/geom/src/ctors/arc.ts @@ -24,14 +24,16 @@ export const arcFrom2Points = ( attribs?: Attribs ) => { const res = fromEndPoints(a, b, radii, axis, xl, cw); - return new Arc( - res.center, - res.r, - res.axis, - res.start, - res.end, - res.xl, - res.cw, - attribs - ); + return res + ? new Arc( + res.center, + res.r, + res.axis, + res.start, + res.end, + res.xl, + res.cw, + attribs + ) + : undefined; }; diff --git a/packages/geom/src/ctors/path.ts b/packages/geom/src/ctors/path.ts index 8cba6bc28c..e45a1648e1 100644 --- a/packages/geom/src/ctors/path.ts +++ b/packages/geom/src/ctors/path.ts @@ -13,7 +13,12 @@ import { Vec, zeroes } from "@thi.ng/vectors"; -import { Cubic, Line, Path, Quadratic } from "../api"; +import { + Cubic, + Line, + Path, + Quadratic +} from "../api"; import { asCubic } from "../ops/as-cubic"; import { arcFrom2Points } from "./arc"; @@ -44,7 +49,7 @@ export const roundedRect = ( attribs?: Attribs ) => { r = isNumber(r) ? [r, r] : r; - const [w, h] = maddN2([], size, r, -2); + const [w, h] = maddN2([], r, -2, size); return new PathBuilder(attribs) .moveTo([pos[0] + r[0], pos[1]]) .hlineTo(w, true) @@ -60,11 +65,11 @@ export const roundedRect = ( export class PathBuilder { paths: Path[]; - attribs: Attribs; - protected curr: Path; - protected currP: Vec; - protected bezierP: Vec; - protected startP: Vec; + attribs?: Attribs; + protected curr!: Path; + protected currP!: Vec; + protected bezierP!: Vec; + protected startP!: Vec; constructor(attribs?: Attribs) { this.paths = []; @@ -256,7 +261,7 @@ const CMD_RE = /[achlmqstvz]/i; export const pathFromSvg = (svg: string) => { const b = new PathBuilder(); try { - let cmd: string; + let cmd = ""; for (let n = svg.length, i = 0; i < n; ) { i = skipWS(svg, i); const c = svg.charAt(i); diff --git a/packages/geom/src/ctors/triangle.ts b/packages/geom/src/ctors/triangle.ts index fc0608c5f8..85daefc683 100644 --- a/packages/geom/src/ctors/triangle.ts +++ b/packages/geom/src/ctors/triangle.ts @@ -1,13 +1,6 @@ import { Attribs } from "@thi.ng/geom-api"; -import { THIRD_PI } from "@thi.ng/math"; -import { - maddN2, - mag, - normalize, - perpendicularLeft2, - sub2, - Vec -} from "@thi.ng/vectors"; +import { equilateralTriangle2 } from "@thi.ng/geom-poly-utils"; +import { Vec } from "@thi.ng/vectors"; import { Triangle } from "../api"; import { argAttribs } from "../internal/args"; @@ -18,12 +11,5 @@ export function triangle(...args: any[]) { return new Triangle(args.length === 1 ? args[0] : args, attr); } -export const equilateralTriangle = (a: Vec, b: Vec, attribs?: Attribs) => { - const dir = sub2([], b, a); - const c = normalize( - null, - perpendicularLeft2([], dir), - mag(dir) * Math.sin(THIRD_PI) - ); - return new Triangle([a, b, maddN2(null, c, dir, 0.5)], attribs); -}; +export const equilateralTriangle = (a: Vec, b: Vec, attribs?: Attribs) => + new Triangle(equilateralTriangle2(a, b), attribs); diff --git a/packages/geom/src/internal/coll-bounds.ts b/packages/geom/src/internal/coll-bounds.ts index e96f36a0d3..0e30425d0d 100644 --- a/packages/geom/src/internal/coll-bounds.ts +++ b/packages/geom/src/internal/coll-bounds.ts @@ -12,12 +12,18 @@ import { unionBounds } from "./union-bounds"; * @param shapes * @param bounds */ -export const collBounds = (shapes: IShape[], bounds: Fn) => { +export const collBounds = ( + shapes: IShape[], + bounds: Fn +) => { let n = shapes.length - 1; if (n < 0) return; - let { pos, size } = bounds(shapes[n]); + let b = bounds(shapes[n]); + if (!b) return; + let { pos, size } = b; for (; --n >= 0; ) { - const b = bounds(shapes[n]); + b = bounds(shapes[n]); + if (!b) continue; [pos, size] = unionBounds(pos, size, b.pos, b.size); } return [pos, size]; diff --git a/packages/geom/src/internal/collate.ts b/packages/geom/src/internal/collate.ts index 697a0505ca..38bc8dc014 100644 --- a/packages/geom/src/internal/collate.ts +++ b/packages/geom/src/internal/collate.ts @@ -1,4 +1,4 @@ -import { Vec, StridedVec } from "@thi.ng/vectors"; +import { StridedVec, Vec } from "@thi.ng/vectors"; export interface CollateOpts { buf: Vec; @@ -27,9 +27,9 @@ export const collateWith = ( fn: ( buf: Vec, src: Iterable>, - start, - cstride, - estride + start: number, + cstride: number, + estride: number ) => Vec, pts: StridedVec[], opts: Partial, @@ -44,15 +44,15 @@ export const collateWith = ( const { start, cstride, estride } = opts; return remap( fn( - opts.buf || new Array(start + pts.length * estride).fill(0), + opts.buf || new Array(start! + pts.length * estride!).fill(0), pts, - start, - cstride, - estride + start!, + cstride!, + estride! ), pts, - start, - cstride, - estride + start!, + cstride!, + estride! ); }; diff --git a/packages/geom/src/ops/arc-length.ts b/packages/geom/src/ops/arc-length.ts index c1773c2664..9457b5d44e 100644 --- a/packages/geom/src/ops/arc-length.ts +++ b/packages/geom/src/ops/arc-length.ts @@ -1,10 +1,19 @@ -import { defmulti, MultiFn1 } from "@thi.ng/defmulti"; +import { IObjectOf } from "@thi.ng/api"; +import { defmulti, Implementation1 } from "@thi.ng/defmulti"; import { IShape, Type } from "@thi.ng/geom-api"; import { perimeter } from "@thi.ng/geom-poly-utils"; import { PI, TAU } from "@thi.ng/math"; import { dist } from "@thi.ng/vectors"; +import { + Circle, + Ellipse, + Group, + Line, + Polygon, + Rect, + Triangle +} from "../api"; import { dispatch } from "../internal/dispatch"; -import { Circle, Ellipse, Group, Line, Polygon, Rect, Triangle } from "../api"; /** * Returns the arc length / perimeter / circumference of the given @@ -24,9 +33,9 @@ import { Circle, Ellipse, Group, Line, Polygon, Rect, Triangle } from "../api"; * - Triangle * */ -export const arcLength: MultiFn1 = defmulti(dispatch); +export const arcLength = defmulti(dispatch); -arcLength.addAll({ +arcLength.addAll(>>{ [Type.CIRCLE]: ($: Circle) => TAU * $.r, [Type.ELLIPSE]: ({ r: [a, b] }: Ellipse) => diff --git a/packages/geom/src/ops/area.ts b/packages/geom/src/ops/area.ts index c7d2dac2f9..0f01b6057c 100644 --- a/packages/geom/src/ops/area.ts +++ b/packages/geom/src/ops/area.ts @@ -1,4 +1,5 @@ -import { defmulti, MultiFn1O } from "@thi.ng/defmulti"; +import { IObjectOf } from "@thi.ng/api"; +import { defmulti, Implementation1O, MultiFn1O } from "@thi.ng/defmulti"; import { IShape, Type } from "@thi.ng/geom-api"; import { polyArea2 } from "@thi.ng/geom-poly-utils"; import { PI } from "@thi.ng/math"; @@ -51,7 +52,7 @@ import { dispatch } from "../internal/dispatch"; */ export const area: MultiFn1O = defmulti(dispatch); -area.addAll({ +area.addAll(>>{ [Type.AABB]: ({ size: [w, h, d] }: AABB) => 2 * (w * h + w * d + h * d), [Type.ARC]: diff --git a/packages/geom/src/ops/as-cubic.ts b/packages/geom/src/ops/as-cubic.ts index b32e224313..c5a19372b6 100644 --- a/packages/geom/src/ops/as-cubic.ts +++ b/packages/geom/src/ops/as-cubic.ts @@ -1,15 +1,27 @@ -import { defmulti } from "@thi.ng/defmulti"; +import { IObjectOf } from "@thi.ng/api"; +import { defmulti, Implementation1 } from "@thi.ng/defmulti"; import { IShape, Type } from "@thi.ng/geom-api"; -import { EPS, HALF_PI, roundEps, sincos } from "@thi.ng/math"; +import { + EPS, + HALF_PI, + roundEps, + sincos +} from "@thi.ng/math"; import { mapcat } from "@thi.ng/transducers"; import { add2, magSq2 } from "@thi.ng/vectors"; +import { + Arc, + Cubic, + Line, + Path, + Quadratic +} from "../api"; import { cubicFromLine, cubicFromQuadratic } from "../ctors/cubic"; import { dispatch } from "../internal/dispatch"; -import { Arc, Cubic, Line, Path, Quadratic } from "../api"; export const asCubic = defmulti(dispatch); -asCubic.addAll({ +asCubic.addAll(>>{ [Type.ARC]: ($: Arc) => { const p = $.pointAtTheta($.start); const q = $.pointAtTheta($.end); diff --git a/packages/geom/src/ops/as-polyline.ts b/packages/geom/src/ops/as-polyline.ts index 3a690f9dd2..d899688242 100644 --- a/packages/geom/src/ops/as-polyline.ts +++ b/packages/geom/src/ops/as-polyline.ts @@ -1,4 +1,5 @@ -import { defmulti, MultiFn1O } from "@thi.ng/defmulti"; +import { IObjectOf } from "@thi.ng/api"; +import { defmulti, Implementation1O, MultiFn1O } from "@thi.ng/defmulti"; import { IShape, SamplingOpts, Type } from "@thi.ng/geom-api"; import { Path, Polyline } from "../api"; import { dispatch } from "../internal/dispatch"; @@ -10,8 +11,12 @@ export const asPolyline: MultiFn1O< Polyline > = defmulti(dispatch); -asPolyline.addAll({ - [Type.POINTS]: ($, opts) => +asPolyline.addAll(< + IObjectOf< + Implementation1O, Polyline> + > +>{ + [Type.POINTS]: ($: IShape, opts) => new Polyline(vertices($, opts), { ...$.attribs }), [Type.PATH]: ($: Path, opts) => { @@ -21,7 +26,7 @@ asPolyline.addAll({ }); }, - [Type.POLYGON]: ($, opts) => { + [Type.POLYGON]: ($: IShape, opts) => { const pts = vertices($, opts); return new Polyline(pts.concat([pts[0]]), { ...$.attribs }); } diff --git a/packages/geom/src/ops/as-svg.ts b/packages/geom/src/ops/as-svg.ts index d0e13a63d2..eef38efbd6 100644 --- a/packages/geom/src/ops/as-svg.ts +++ b/packages/geom/src/ops/as-svg.ts @@ -10,7 +10,7 @@ export const asSvg = (...args: any[]) => export const svgDoc = (attribs: Attribs, ...xs: IShape[]) => { if (xs.length > 0) { if (!attribs || !attribs.viewBox) { - const [pos, size] = collBounds(xs, bounds); + const [pos, size] = collBounds(xs, bounds)!; attribs = { width: ff(size[0]), height: ff(size[1]), diff --git a/packages/geom/src/ops/bounds.ts b/packages/geom/src/ops/bounds.ts index 0488206968..8bc06e8653 100644 --- a/packages/geom/src/ops/bounds.ts +++ b/packages/geom/src/ops/bounds.ts @@ -1,9 +1,21 @@ -import { defmulti } from "@thi.ng/defmulti"; -import { AABBLike, IShape, PathSegment, PCLike, Type } from "@thi.ng/geom-api"; +import { IObjectOf } from "@thi.ng/api"; +import { defmulti, Implementation1 } from "@thi.ng/defmulti"; +import { + AABBLike, + IShape, + PathSegment, + PCLike, + Type +} from "@thi.ng/geom-api"; import { bounds as arcBounds } from "@thi.ng/geom-arc"; import { bounds as _bounds } from "@thi.ng/geom-poly-utils"; import { cubicBounds, quadraticBounds } from "@thi.ng/geom-splines"; -import { comp, filter, iterator1, map } from "@thi.ng/transducers"; +import { + comp, + filter, + iterator1, + map +} from "@thi.ng/transducers"; import { max, MAX2, @@ -15,9 +27,6 @@ import { sub2, subN2 } from "@thi.ng/vectors"; -import { rectFromMinMax } from "../ctors/rect"; -import { collBounds } from "../internal/coll-bounds"; -import { dispatch } from "../internal/dispatch"; import { Arc, Circle, @@ -29,10 +38,13 @@ import { Quadratic, Rect } from "../api"; +import { rectFromMinMax } from "../ctors/rect"; +import { collBounds } from "../internal/coll-bounds"; +import { dispatch } from "../internal/dispatch"; -export const bounds = defmulti(dispatch); +export const bounds = defmulti(dispatch); -bounds.addAll({ +bounds.addAll(>>{ [Type.ARC]: ($: Arc) => rectFromMinMax(...arcBounds($.pos, $.r, $.axis, $.start, $.end)), @@ -47,26 +59,26 @@ bounds.addAll({ [Type.ELLIPSE]: ($: Ellipse) => new Rect(sub2([], $.pos, $.r), mul2(null, [2, 2], $.r)), - [Type.GROUP]: ($: Group) => new Rect(...collBounds($.children, bounds)), + [Type.GROUP]: ($: Group) => { + const res = collBounds($.children, bounds); + return res ? new Rect(...res) : undefined; + }, [Type.LINE]: ({ points: [a, b] }: Line) => rectFromMinMax(min([], a, b), max([], a, b)), - [Type.PATH]: (path: Path) => - new Rect( - ...collBounds( - [ - ...iterator1( - comp( - map((s: PathSegment) => s.geo), - filter((s) => !!s) - ), - path.segments - ) - ], - bounds - ) - ), + [Type.PATH]: (path: Path) => { + const b = collBounds( + [ + ...iterator1( + comp(map((s: PathSegment) => s.geo!), filter((s) => !!s)), + path.segments + ) + ], + bounds + ); + return b ? new Rect(...b) : undefined; + }, [Type.POINTS]: ($: PCLike) => rectFromMinMax(..._bounds($.points, set2([], MAX2), set2([], MIN2))), diff --git a/packages/geom/src/ops/center.ts b/packages/geom/src/ops/center.ts index f912ccbf96..5323b62c21 100644 --- a/packages/geom/src/ops/center.ts +++ b/packages/geom/src/ops/center.ts @@ -1,20 +1,43 @@ -import { DEFAULT, defmulti, MultiFn1O } from "@thi.ng/defmulti"; +import { IObjectOf } from "@thi.ng/api"; +import { + DEFAULT, + defmulti, + Implementation1O, + MultiFn1O +} from "@thi.ng/defmulti"; import { IShape, Type } from "@thi.ng/geom-api"; -import { ReadonlyVec, set2, set3, submN, ZERO2, ZERO3 } from "@thi.ng/vectors"; +import { + ReadonlyVec, + set2, + set3, + submN, + ZERO2, + ZERO3 +} from "@thi.ng/vectors"; +import { + Arc, + Circle, + Ellipse, + Sphere +} from "../api"; import { dispatch } from "../internal/dispatch"; import { centroid } from "./centroid"; import { translate } from "./translate"; -import { Arc, Circle, Ellipse, Sphere } from "../api"; -export const center: MultiFn1O = defmulti( - dispatch -); +export const center: MultiFn1O< + IShape, + ReadonlyVec, + IShape | undefined +> = defmulti(dispatch); -center.add(DEFAULT, ($, origin = ZERO3) => - translate($, submN(null, centroid($), origin, -1)) -); +center.add(DEFAULT, ($, origin = ZERO3) => { + const c = centroid($); + return c ? translate($, submN(null, c, origin, -1)) : undefined; +}); -center.addAll({ +center.addAll(< + IObjectOf> +>{ [Type.ARC]: ($: Arc, origin = ZERO2) => new Arc( set2([], origin), diff --git a/packages/geom/src/ops/centroid.ts b/packages/geom/src/ops/centroid.ts index 652f413166..3461c8c286 100644 --- a/packages/geom/src/ops/centroid.ts +++ b/packages/geom/src/ops/centroid.ts @@ -1,4 +1,5 @@ -import { defmulti, MultiFn1O } from "@thi.ng/defmulti"; +import { IObjectOf } from "@thi.ng/api"; +import { defmulti, Implementation1O, MultiFn1O } from "@thi.ng/defmulti"; import { AABBLike, IShape, @@ -26,12 +27,17 @@ import { import { dispatch } from "../internal/dispatch"; import { bounds } from "./bounds"; -export const centroid: MultiFn1O = defmulti(dispatch); +export const centroid: MultiFn1O = defmulti( + dispatch +); -centroid.addAll({ +centroid.addAll(>>{ [Type.CIRCLE]: ($: Circle, out?) => set(out || [], $.pos), - [Type.GROUP]: ($: Group) => centroid(bounds($)), + [Type.GROUP]: ($: Group) => { + const b = bounds($); + return b ? centroid(b) : undefined; + }, [Type.LINE]: ({ points }: Line, out?) => mixN(out || [], points[0], points[1], 0.5), @@ -42,7 +48,7 @@ centroid.addAll({ [Type.POLYGON]: ($: Polygon, out?) => centerOfWeight2($.points, out), - [Type.RECT]: ($: AABBLike, out?) => maddN(out || [], $.pos, $.size, 0.5), + [Type.RECT]: ($: AABBLike, out?) => maddN(out || [], $.size, 0.5, $.pos), [Type.TRIANGLE]: ({ points }: Triangle, out?) => divN( diff --git a/packages/geom/src/ops/classify-point.ts b/packages/geom/src/ops/classify-point.ts index 16b087ed3d..6feabcb8de 100644 --- a/packages/geom/src/ops/classify-point.ts +++ b/packages/geom/src/ops/classify-point.ts @@ -1,4 +1,5 @@ -import { defmulti, MultiFn2O } from "@thi.ng/defmulti"; +import { IObjectOf } from "@thi.ng/api"; +import { defmulti, Implementation2O, MultiFn2O } from "@thi.ng/defmulti"; import { IShape, Type } from "@thi.ng/geom-api"; import { classifyPointInCircle, classifyPointInTriangle2 } from "@thi.ng/geom-isec"; import { EPS, sign } from "@thi.ng/math"; @@ -11,9 +12,11 @@ export const classifyPoint: MultiFn2O< ReadonlyVec, number, number -> = defmulti(dispatch); +> = defmulti(dispatch); -classifyPoint.addAll({ +classifyPoint.addAll(< + IObjectOf> +>{ [Type.CIRCLE]: ($: Circle, p, eps = EPS) => classifyPointInCircle(p, $.pos, $.r, eps), diff --git a/packages/geom/src/ops/clip-convex.ts b/packages/geom/src/ops/clip-convex.ts index 129246f240..598418c593 100644 --- a/packages/geom/src/ops/clip-convex.ts +++ b/packages/geom/src/ops/clip-convex.ts @@ -1,4 +1,5 @@ -import { defmulti } from "@thi.ng/defmulti"; +import { IObjectOf } from "@thi.ng/api"; +import { defmulti, Implementation2 } from "@thi.ng/defmulti"; import { IShape, Type } from "@thi.ng/geom-api"; import { sutherlandHodgeman } from "@thi.ng/geom-clip"; import { Polygon } from "../api"; @@ -8,7 +9,7 @@ import { vertices } from "./vertices"; export const clipConvex = defmulti(dispatch); -clipConvex.addAll({ +clipConvex.addAll(>>{ [Type.POLYGON]: ($: Polygon, boundary: IShape) => new Polygon( sutherlandHodgeman( @@ -19,7 +20,7 @@ clipConvex.addAll({ { ...$.attribs } ), - [Type.RECT]: ($, boundary: IShape) => + [Type.RECT]: ($: IShape, boundary: IShape) => new Polygon( sutherlandHodgeman( vertices($), diff --git a/packages/geom/src/ops/closest-point.ts b/packages/geom/src/ops/closest-point.ts index 5b25605b4b..8ea2e755b5 100644 --- a/packages/geom/src/ops/closest-point.ts +++ b/packages/geom/src/ops/closest-point.ts @@ -1,4 +1,5 @@ -import { defmulti, MultiFn2O } from "@thi.ng/defmulti"; +import { IObjectOf } from "@thi.ng/api"; +import { defmulti, Implementation2O, MultiFn2O } from "@thi.ng/defmulti"; import { IShape, PCLike, Type } from "@thi.ng/geom-api"; import { closestPoint as closestPointArc } from "@thi.ng/geom-arc"; import { @@ -15,7 +16,6 @@ import { add2, add3, ReadonlyVec, - set, Vec } from "@thi.ng/vectors"; import { @@ -30,42 +30,46 @@ import { } from "../api"; import { dispatch } from "../internal/dispatch"; -export const closestPoint: MultiFn2O = defmulti( - dispatch -); +export const closestPoint: MultiFn2O< + IShape, + ReadonlyVec, + Vec, + Vec | undefined +> = defmulti(dispatch); -closestPoint.addAll({ - [Type.AABB]: ($: AABB, p, out = []) => +closestPoint.addAll(< + IObjectOf> +>{ + [Type.AABB]: ($: AABB, p, out) => closestPointAABB(p, $.pos, add3([], $.pos, $.size), out), - [Type.ARC]: ($: Arc, p, out = []) => + [Type.ARC]: ($: Arc, p, out) => closestPointArc(p, $.pos, $.r, $.axis, $.start, $.end, out), - [Type.CIRCLE]: ($: Circle, p, out = []) => + [Type.CIRCLE]: ($: Circle, p, out) => closestPointCircle(p, $.pos, $.r, out), - [Type.CUBIC]: ({ points }: Cubic, p, out = []) => + [Type.CUBIC]: ({ points }: Cubic, p, out) => closestPointCubic(p, points[0], points[1], points[2], points[3], out), - [Type.LINE]: ({ points }: Line, p, out = []) => + [Type.LINE]: ({ points }: Line, p, out) => closestPointSegment(p, points[0], points[1], out), - [Type.PLANE]: ($: Plane, p, out = []) => + [Type.PLANE]: ($: Plane, p, out) => closestPointPlane(p, $.normal, $.w, out), - [Type.POINTS]: ($: PCLike, p, out) => - set(out, closestPointArray(p, $.points)), + [Type.POINTS]: ($: PCLike, p, out) => closestPointArray(p, $.points, out), - [Type.POLYGON]: ($: PCLike, p, out = []) => + [Type.POLYGON]: ($: PCLike, p, out) => closestPointPolyline(p, $.points, true, out), - [Type.POLYLINE]: ($: PCLike, p, out = []) => + [Type.POLYLINE]: ($: PCLike, p, out) => closestPointPolyline(p, $.points, false, out), - [Type.QUADRATIC]: ({ points }: Quadratic, p, out = []) => + [Type.QUADRATIC]: ({ points }: Quadratic, p, out) => closestPointQuadratic(p, points[0], points[1], points[2], out), - [Type.RECT]: ($: Rect, p, out = []) => + [Type.RECT]: ($: Rect, p, out) => closestPointRect(p, $.pos, add2([], $.pos, $.size), out) }); diff --git a/packages/geom/src/ops/convex-hull.ts b/packages/geom/src/ops/convex-hull.ts index 96d439e308..033876be71 100644 --- a/packages/geom/src/ops/convex-hull.ts +++ b/packages/geom/src/ops/convex-hull.ts @@ -1,4 +1,5 @@ -import { defmulti } from "@thi.ng/defmulti"; +import { IObjectOf } from "@thi.ng/api"; +import { defmulti, Implementation1 } from "@thi.ng/defmulti"; import { IShape, PCLike, Type } from "@thi.ng/geom-api"; import { grahamScan2 } from "@thi.ng/geom-hull"; import { Polygon } from "../api"; @@ -7,13 +8,13 @@ import { vertices } from "./vertices"; export const convexHull = defmulti(dispatch); -convexHull.addAll({ - [Type.GROUP]: ($) => new Polygon(vertices($), { ...$.attribs }), +convexHull.addAll(>>{ + [Type.GROUP]: ($: IShape) => new Polygon(vertices($), { ...$.attribs }), [Type.POINTS]: ($: PCLike) => new Polygon(grahamScan2($.points), { ...$.attribs }), - [Type.TRIANGLE]: ($) => $.copy() + [Type.TRIANGLE]: ($: IShape) => $.copy() }); convexHull.isa(Type.CIRCLE, Type.TRIANGLE); diff --git a/packages/geom/src/ops/edges.ts b/packages/geom/src/ops/edges.ts index 10455dc9a4..1de8805af5 100644 --- a/packages/geom/src/ops/edges.ts +++ b/packages/geom/src/ops/edges.ts @@ -1,4 +1,5 @@ -import { defmulti, MultiFn1O } from "@thi.ng/defmulti"; +import { IObjectOf } from "@thi.ng/api"; +import { defmulti, Implementation1O, MultiFn1O } from "@thi.ng/defmulti"; import { IShape, SamplingOpts, Type } from "@thi.ng/geom-api"; import { VecPair } from "@thi.ng/vectors"; import { Polygon, Polyline, Rect } from "../api"; @@ -12,7 +13,15 @@ export const edges: MultiFn1O< Iterable > = defmulti(dispatch); -edges.addAll({ +edges.addAll(< + IObjectOf< + Implementation1O< + unknown, + number | Partial, + Iterable + > + > +>{ [Type.POLYGON]: ($: Polygon) => edgeIterator($.points, true), [Type.POLYLINE]: ($: Polyline) => edgeIterator($.points), diff --git a/packages/geom/src/ops/fit-into-bounds.ts b/packages/geom/src/ops/fit-into-bounds.ts index 532a66c221..a332107176 100644 --- a/packages/geom/src/ops/fit-into-bounds.ts +++ b/packages/geom/src/ops/fit-into-bounds.ts @@ -1,6 +1,16 @@ import { IShape } from "@thi.ng/geom-api"; -import { concat, ReadonlyMat, scale23, translation23 } from "@thi.ng/matrices"; -import { div2, neg, ReadonlyVec } from "@thi.ng/vectors"; +import { + concat, + ReadonlyMat, + scale23, + translation23 +} from "@thi.ng/matrices"; +import { + div2, + neg, + ReadonlyVec, + Vec +} from "@thi.ng/vectors"; import { Rect } from "../api"; import { collBounds } from "../internal/coll-bounds"; import { bounds } from "./bounds"; @@ -23,29 +33,39 @@ const translateScale2 = ( export const fitIntoBounds2 = (shape: IShape, dest: Rect) => { const src = bounds(shape); + if (!src) return; + const c = centroid(src); + if (!c) return; const tscale = div2([], dest.size, src.size); const scale = Math.min(tscale[0], tscale[1]); return translateScale2( shape, - centroid(dest), - neg(null, centroid(src)), + centroid(dest)!, + neg(null, c), scale23([], scale) ); }; export const fitAllIntoBounds2 = (shapes: IShape[], dest: Rect) => { - const src = new Rect(...collBounds(shapes, bounds)); + const sbraw = collBounds(shapes, bounds); + if (!sbraw) return; + const src = new Rect(...sbraw); const [w, h] = div2([], dest.size, src.size); const s = w > 0 && h > 0 ? Math.min(w, h) : w > 0 ? w : h; const smat = scale23([], s); - const b = center(transform(src, smat), centroid(dest)); - const c1 = []; - const c2 = []; + const b = center(transform(src, smat), centroid(dest))!; + const c1: Vec = []; + const c2: Vec = []; const res: IShape[] = []; for (let i = shapes.length; --i >= 0; ) { const s = shapes[i]; - unmapPoint(b, mapPoint(src, centroid(s, c1)), c2); - res.push(translateScale2(s, c2, neg(null, c1), smat)); + const sc = centroid(s, c1); + if (sc) { + unmapPoint(b, mapPoint(src, sc), c2); + res.push(translateScale2(s, c2, neg(null, c1), smat)); + } else { + res.push(s); + } } return res; }; diff --git a/packages/geom/src/ops/flip.ts b/packages/geom/src/ops/flip.ts index ac06dbc669..e2647baf58 100644 --- a/packages/geom/src/ops/flip.ts +++ b/packages/geom/src/ops/flip.ts @@ -1,13 +1,19 @@ -import { DEFAULT, defmulti } from "@thi.ng/defmulti"; +import { IObjectOf } from "@thi.ng/api"; +import { DEFAULT, defmulti, Implementation1 } from "@thi.ng/defmulti"; import { IShape, PCLike, Type } from "@thi.ng/geom-api"; import { neg } from "@thi.ng/vectors"; -import { Arc, Group, Path, Ray } from "../api"; +import { + Arc, + Group, + Path, + Ray +} from "../api"; import { dispatch } from "../internal/dispatch"; export const flip = defmulti(dispatch); flip.add(DEFAULT, ($) => $); -flip.addAll({ +flip.addAll(>>{ [Type.ARC]: ($: Arc) => { const t = $.start; $.start = $.end; diff --git a/packages/geom/src/ops/intersects.ts b/packages/geom/src/ops/intersects.ts index be36eb5688..0503002c9c 100644 --- a/packages/geom/src/ops/intersects.ts +++ b/packages/geom/src/ops/intersects.ts @@ -1,4 +1,5 @@ -import { defmulti, MultiFn2O } from "@thi.ng/defmulti"; +import { IObjectOf } from "@thi.ng/api"; +import { defmulti, Implementation2O, MultiFn2O } from "@thi.ng/defmulti"; import { IntersectionResult, IntersectionType, @@ -36,7 +37,9 @@ export const intersects: MultiFn2O< IntersectionResult > = defmulti(dispatch2); -intersects.addAll({ +intersects.addAll(< + IObjectOf> +>{ [`${Type.CIRCLE}-${Type.CIRCLE}`]: (a: Sphere, b: Sphere) => intersectCircleCircle(a.pos, b.pos, a.r, b.r), diff --git a/packages/geom/src/ops/map-point.ts b/packages/geom/src/ops/map-point.ts index b83b3e2b9b..3142fe47bb 100644 --- a/packages/geom/src/ops/map-point.ts +++ b/packages/geom/src/ops/map-point.ts @@ -1,14 +1,20 @@ -import { defmulti, MultiFn2O } from "@thi.ng/defmulti"; +import { IObjectOf } from "@thi.ng/api"; +import { defmulti, Implementation2O, MultiFn2O } from "@thi.ng/defmulti"; import { IShape, Type } from "@thi.ng/geom-api"; -import { div, ReadonlyVec, sub, Vec } from "@thi.ng/vectors"; +import { + div, + ReadonlyVec, + sub, + Vec +} from "@thi.ng/vectors"; import { Rect } from "../api"; import { dispatch } from "../internal/dispatch"; -export const mapPoint: MultiFn2O = defmulti( - dispatch -); +export const mapPoint: MultiFn2O = defmulti(< + any +>dispatch); -mapPoint.addAll({ +mapPoint.addAll(>>{ [Type.RECT]: ($: Rect, p: ReadonlyVec, out: Vec = []) => div(null, sub(out, p, $.pos), $.size) }); diff --git a/packages/geom/src/ops/point-at.ts b/packages/geom/src/ops/point-at.ts index 367dffa9c9..f5266937a0 100644 --- a/packages/geom/src/ops/point-at.ts +++ b/packages/geom/src/ops/point-at.ts @@ -1,4 +1,5 @@ -import { defmulti } from "@thi.ng/defmulti"; +import { IObjectOf } from "@thi.ng/api"; +import { defmulti, Implementation2 } from "@thi.ng/defmulti"; import { IShape, Type } from "@thi.ng/geom-api"; import { Sampler } from "@thi.ng/geom-resample"; import { cossin, fit01, TAU } from "@thi.ng/math"; @@ -11,8 +12,6 @@ import { mixQuadratic, Vec } from "@thi.ng/vectors"; -import { dispatch } from "../internal/dispatch"; -import { vertices } from "./vertices"; import { Arc, Circle, @@ -24,10 +23,12 @@ import { Ray, Rect } from "../api"; +import { dispatch } from "../internal/dispatch"; +import { vertices } from "./vertices"; export const pointAt = defmulti(dispatch); -pointAt.addAll({ +pointAt.addAll(>>{ [Type.ARC]: ($: Arc, t: number) => $.pointAtTheta(fit01(t, $.start, $.end)), [Type.CIRCLE]: ($: Circle, t) => cartesian2(null, [$.r, TAU * t], $.pos), @@ -35,7 +36,7 @@ pointAt.addAll({ [Type.CUBIC]: ({ points }: Cubic, t) => mixCubic([], points[0], points[1], points[2], points[3], t), - [Type.ELLIPSE]: ($: Ellipse, t) => madd2([], $.pos, cossin(TAU * t), $.r), + [Type.ELLIPSE]: ($: Ellipse, t) => madd2([], cossin(TAU * t), $.r, $.pos), [Type.LINE]: ({ points }: Line, t) => mixN2([], points[0], points[1], t), @@ -46,7 +47,7 @@ pointAt.addAll({ [Type.QUADRATIC]: ({ points }: Quadratic, t) => mixQuadratic([], points[0], points[1], points[2], t), - [Type.RAY]: ($: Ray, t) => maddN([], $.pos, $.dir, t), + [Type.RAY]: ($: Ray, t) => maddN([], $.dir, t, $.pos), [Type.RECT]: ($: Rect, t) => new Sampler(vertices($), true).pointAt(t) }); diff --git a/packages/geom/src/ops/point-inside.ts b/packages/geom/src/ops/point-inside.ts index b74aba32bb..bbe7fc230c 100644 --- a/packages/geom/src/ops/point-inside.ts +++ b/packages/geom/src/ops/point-inside.ts @@ -1,4 +1,5 @@ -import { defmulti } from "@thi.ng/defmulti"; +import { IObjectOf } from "@thi.ng/api"; +import { defmulti, Implementation2 } from "@thi.ng/defmulti"; import { IShape, Type } from "@thi.ng/geom-api"; import { pointInAABB, @@ -22,7 +23,7 @@ import { dispatch } from "../internal/dispatch"; export const pointInside = defmulti(dispatch); -pointInside.addAll({ +pointInside.addAll(>>{ [Type.AABB]: ($: AABB, p: ReadonlyVec) => pointInAABB(p, $.pos, $.size), [Type.CIRCLE]: ($: Circle, p) => pointInCircle(p, $.pos, $.r), diff --git a/packages/geom/src/ops/resample.ts b/packages/geom/src/ops/resample.ts index e19c8cfc61..aedb27815c 100644 --- a/packages/geom/src/ops/resample.ts +++ b/packages/geom/src/ops/resample.ts @@ -1,5 +1,11 @@ -import { defmulti } from "@thi.ng/defmulti"; -import { IShape, PCLike, SamplingOpts, Type } from "@thi.ng/geom-api"; +import { IObjectOf } from "@thi.ng/api"; +import { defmulti, Implementation2 } from "@thi.ng/defmulti"; +import { + IShape, + PCLike, + SamplingOpts, + Type +} from "@thi.ng/geom-api"; import { resample as _resample } from "@thi.ng/geom-resample"; import { Polygon, Polyline } from "../api"; import { dispatch } from "../internal/dispatch"; @@ -11,8 +17,10 @@ export const resample = defmulti< IShape >(dispatch); -resample.addAll({ - [Type.CIRCLE]: ($, opts) => asPolygon($, opts), +resample.addAll(< + IObjectOf, IShape>> +>{ + [Type.CIRCLE]: ($: IShape, opts) => asPolygon($, opts), [Type.POLYGON]: ($: PCLike, opts) => new Polygon(_resample($.points, opts, true, true), { ...$.attribs }), diff --git a/packages/geom/src/ops/scatter.ts b/packages/geom/src/ops/scatter.ts index d2b16add6c..e2fb765841 100644 --- a/packages/geom/src/ops/scatter.ts +++ b/packages/geom/src/ops/scatter.ts @@ -11,6 +11,7 @@ export const scatter = ( out: Vec[] = [] ) => { const b = bounds(shape); + if (!b) return; const mi = b.pos; const mx = b.max(); for (; --num >= 0; ) { diff --git a/packages/geom/src/ops/simplify.ts b/packages/geom/src/ops/simplify.ts index d1e04fa941..aff8d10b85 100644 --- a/packages/geom/src/ops/simplify.ts +++ b/packages/geom/src/ops/simplify.ts @@ -1,21 +1,27 @@ +import { IObjectOf } from "@thi.ng/api"; import { peek } from "@thi.ng/arrays"; -import { defmulti } from "@thi.ng/defmulti"; -import { IShape, PathSegment, SegmentType, Type } from "@thi.ng/geom-api"; +import { defmulti, Implementation2 } from "@thi.ng/defmulti"; +import { + IShape, + PathSegment, + SegmentType, + Type +} from "@thi.ng/geom-api"; import { simplify as _simplify } from "@thi.ng/geom-resample"; import { Vec } from "@thi.ng/vectors"; +import { Path, Polygon, Polyline } from "../api"; import { dispatch } from "../internal/dispatch"; import { vertices } from "./vertices"; -import { Path, Polygon, Polyline } from "../api"; export const simplify = defmulti(dispatch); -simplify.addAll({ +simplify.addAll(>>{ [Type.PATH]: (path: Path, eps = 0.1) => { const res: PathSegment[] = []; const orig = path.segments; const n = orig.length; - let points: Vec[]; - let lastP: Vec; + let points!: Vec[] | null; + let lastP!: Vec; for (let i = 0; i < n; i++) { const s = orig[i]; if ( @@ -23,8 +29,8 @@ simplify.addAll({ s.type === SegmentType.POLYLINE ) { points = points - ? points.concat(vertices(s.geo)) - : vertices(s.geo); + ? points.concat(vertices(s.geo!)) + : vertices(s.geo!); lastP = peek(points); } else if (points) { points.push(lastP); diff --git a/packages/geom/src/ops/split-at.ts b/packages/geom/src/ops/split-at.ts index d426954458..801fe4efc4 100644 --- a/packages/geom/src/ops/split-at.ts +++ b/packages/geom/src/ops/split-at.ts @@ -1,16 +1,23 @@ -import { defmulti } from "@thi.ng/defmulti"; +import { IObjectOf } from "@thi.ng/api"; +import { defmulti, Implementation2 } from "@thi.ng/defmulti"; import { IShape, Type } from "@thi.ng/geom-api"; import { Sampler } from "@thi.ng/geom-resample"; import { cubicSplitAt, quadraticSplitAt } from "@thi.ng/geom-splines"; import { fit01 } from "@thi.ng/math"; import { copyVectors, set } from "@thi.ng/vectors"; +import { + Arc, + Cubic, + Line, + Polyline, + Quadratic +} from "../api"; import { dispatch } from "../internal/dispatch"; import { splitLine } from "../internal/split"; -import { Arc, Cubic, Line, Polyline, Quadratic } from "../api"; -export const splitAt = defmulti(dispatch); +export const splitAt = defmulti(dispatch); -splitAt.addAll({ +splitAt.addAll(>>{ [Type.ARC]: ($: Arc, t: number) => { const theta = fit01(t, $.start, $.end); return [ @@ -47,10 +54,12 @@ splitAt.addAll({ (pts) => new Line(pts, { ...attribs }) ), - [Type.POLYLINE]: ($: Polyline, t) => - new Sampler($.points) - .splitAt(t) - .map((pts) => new Polyline(copyVectors(pts), { ...$.attribs })), + [Type.POLYLINE]: ($: Polyline, t) => { + const res = new Sampler($.points).splitAt(t); + return res + ? res.map((pts) => new Polyline(copyVectors(pts), { ...$.attribs })) + : undefined; + }, [Type.QUADRATIC]: ({ attribs, points }: Quadratic, t: number) => quadraticSplitAt(points[0], points[1], points[2], t).map( diff --git a/packages/geom/src/ops/split-near.ts b/packages/geom/src/ops/split-near.ts index 73f21a147d..b6a903d1e0 100644 --- a/packages/geom/src/ops/split-near.ts +++ b/packages/geom/src/ops/split-near.ts @@ -1,14 +1,17 @@ -import { defmulti } from "@thi.ng/defmulti"; +import { IObjectOf } from "@thi.ng/api"; +import { defmulti, Implementation2 } from "@thi.ng/defmulti"; import { IShape, Type } from "@thi.ng/geom-api"; import { closestT } from "@thi.ng/geom-closest-point"; import { Sampler } from "@thi.ng/geom-resample"; -import { - quadraticSplitNearPoint, - splitCubicNearPoint -} from "@thi.ng/geom-splines"; +import { quadraticSplitNearPoint, splitCubicNearPoint } from "@thi.ng/geom-splines"; import { clamp01 } from "@thi.ng/math"; import { copyVectors, ReadonlyVec } from "@thi.ng/vectors"; -import { Cubic, Line, Polyline, Quadratic } from "../api"; +import { + Cubic, + Line, + Polyline, + Quadratic +} from "../api"; import { dispatch } from "../internal/dispatch"; import { splitLine } from "../internal/split"; @@ -29,9 +32,15 @@ import { splitLine } from "../internal/split"; * @param shape * @param p */ -export const splitNearPoint = defmulti(dispatch); +export const splitNearPoint = defmulti< + IShape, + ReadonlyVec, + IShape[] | undefined +>(dispatch); -splitNearPoint.addAll({ +splitNearPoint.addAll(< + IObjectOf> +>{ [Type.CUBIC]: ({ points, attribs }: Cubic, p) => splitCubicNearPoint(p, points[0], points[1], points[2], points[3]).map( (pts) => new Cubic(pts, { ...attribs }) @@ -44,10 +53,12 @@ splitNearPoint.addAll({ ); }, - [Type.POLYLINE]: ($: Polyline, p) => - new Sampler($.points) - .splitNear(p) - .map((pts) => new Polyline(copyVectors(pts), { ...$.attribs })), + [Type.POLYLINE]: ($: Polyline, p) => { + const res = new Sampler($.points).splitNear(p); + return res + ? res.map((pts) => new Polyline(copyVectors(pts), { ...$.attribs })) + : undefined; + }, [Type.QUADRATIC]: ({ points, attribs }: Quadratic, p) => quadraticSplitNearPoint(p, points[0], points[1], points[2]).map( diff --git a/packages/geom/src/ops/subdiv-curve.ts b/packages/geom/src/ops/subdiv-curve.ts index 4df02e9d5c..1c860e6013 100644 --- a/packages/geom/src/ops/subdiv-curve.ts +++ b/packages/geom/src/ops/subdiv-curve.ts @@ -1,4 +1,5 @@ -import { defmulti, MultiFn2O } from "@thi.ng/defmulti"; +import { IObjectOf } from "@thi.ng/api"; +import { defmulti, Implementation2O, MultiFn2O } from "@thi.ng/defmulti"; import { IShape, SubdivKernel, Type } from "@thi.ng/geom-api"; import { subdivide } from "@thi.ng/geom-subdiv-curve"; import { Polygon, Polyline } from "../api"; @@ -9,9 +10,11 @@ export const subdivCurve: MultiFn2O< SubdivKernel, number, IShape -> = defmulti(dispatch); +> = defmulti(dispatch); -subdivCurve.addAll({ +subdivCurve.addAll(< + IObjectOf> +>{ [Type.POLYGON]: (poly: Polygon, kernel, iter = 1) => new Polygon(subdivide(poly.points, kernel, iter), { ...poly.attribs }), diff --git a/packages/geom/src/ops/tangent-at.ts b/packages/geom/src/ops/tangent-at.ts index 85564a44e6..0e0b87a8cf 100644 --- a/packages/geom/src/ops/tangent-at.ts +++ b/packages/geom/src/ops/tangent-at.ts @@ -1,4 +1,5 @@ -import { defmulti } from "@thi.ng/defmulti"; +import { IObjectOf } from "@thi.ng/api"; +import { defmulti, Implementation2 } from "@thi.ng/defmulti"; import { IShape, PCLike, Type } from "@thi.ng/geom-api"; import { Sampler } from "@thi.ng/geom-resample"; import { cossin, HALF_PI, TAU } from "@thi.ng/math"; @@ -9,7 +10,7 @@ import { vertices } from "./vertices"; export const tangentAt = defmulti(dispatch); -tangentAt.addAll({ +tangentAt.addAll(>>{ [Type.CIRCLE]: (_, t) => cossin(TAU * t + HALF_PI), [Type.LINE]: ({ points }: Line) => direction([], points[0], points[1]), diff --git a/packages/geom/src/ops/transform.ts b/packages/geom/src/ops/transform.ts index 7b3a2a437a..7121327ec0 100644 --- a/packages/geom/src/ops/transform.ts +++ b/packages/geom/src/ops/transform.ts @@ -1,4 +1,5 @@ -import { defmulti } from "@thi.ng/defmulti"; +import { IObjectOf } from "@thi.ng/api"; +import { defmulti, Implementation2 } from "@thi.ng/defmulti"; import { IHiccupShape, IShape, @@ -19,10 +20,7 @@ import { Triangle } from "../api"; import { dispatch } from "../internal/dispatch"; -import { - transformedPoints, - transformPoints -} from "../internal/transform-points"; +import { transformedPoints, transformPoints } from "../internal/transform-points"; import { vertices } from "./vertices"; const tx = (ctor: PCLikeConstructor) => ($: PCLike, mat: ReadonlyMat) => @@ -30,8 +28,8 @@ const tx = (ctor: PCLikeConstructor) => ($: PCLike, mat: ReadonlyMat) => export const transform = defmulti(dispatch); -transform.addAll({ - [Type.CIRCLE]: ($, mat) => +transform.addAll(>>{ + [Type.CIRCLE]: ($: IShape, mat) => new Polygon(transformPoints(vertices($), mat), { ...$.attribs }), [Type.CUBIC]: tx(Cubic), diff --git a/packages/geom/src/ops/translate.ts b/packages/geom/src/ops/translate.ts index e33de77de3..bdbafbc60e 100644 --- a/packages/geom/src/ops/translate.ts +++ b/packages/geom/src/ops/translate.ts @@ -1,4 +1,5 @@ -import { defmulti } from "@thi.ng/defmulti"; +import { IObjectOf } from "@thi.ng/api"; +import { defmulti, Implementation2 } from "@thi.ng/defmulti"; import { IHiccupShape, IShape, @@ -6,7 +7,13 @@ import { PCLikeConstructor, Type } from "@thi.ng/geom-api"; -import { add2, add3, ReadonlyVec, set2, set3 } from "@thi.ng/vectors"; +import { + add2, + add3, + ReadonlyVec, + set2, + set3 +} from "@thi.ng/vectors"; import { AABB, Arc, @@ -32,7 +39,7 @@ const tx = (ctor: PCLikeConstructor) => ($: PCLike, mat: ReadonlyVec) => export const translate = defmulti(dispatch); -translate.addAll({ +translate.addAll(>>{ [Type.AABB]: ($: AABB, delta) => new AABB(add3([], $.pos, delta), set3([], $.size), { ...$.attribs }), @@ -58,17 +65,16 @@ translate.addAll({ [Type.PATH]: ($: Path, delta: ReadonlyVec) => new Path( - $.segments.map( - (s) => - s.geo - ? { - type: s.type, - geo: translate(s.geo, delta) - } - : { - type: s.type, - point: add2([], s.point, delta) - } + $.segments.map((s) => + s.geo + ? { + type: s.type, + geo: translate(s.geo, delta) + } + : { + type: s.type, + point: add2([], s.point!, delta) + } ), { ...$.attribs } ), diff --git a/packages/geom/src/ops/union.ts b/packages/geom/src/ops/union.ts index d97ecca1c9..ef4888efa4 100644 --- a/packages/geom/src/ops/union.ts +++ b/packages/geom/src/ops/union.ts @@ -1,4 +1,5 @@ -import { defmulti } from "@thi.ng/defmulti"; +import { IObjectOf } from "@thi.ng/api"; +import { defmulti, Implementation2 } from "@thi.ng/defmulti"; import { IShape, Type } from "@thi.ng/geom-api"; import { AABB, Rect } from "../api"; import { dispatch } from "../internal/dispatch"; @@ -6,7 +7,7 @@ import { unionBounds } from "../internal/union-bounds"; export const union = defmulti(dispatch); -union.addAll({ +union.addAll(>>{ [Type.AABB]: (a: AABB, b: AABB) => [ new AABB(...unionBounds(a.pos, a.size, b.pos, b.size)) ], diff --git a/packages/geom/src/ops/unmap-point.ts b/packages/geom/src/ops/unmap-point.ts index 46b027cfe9..2024e9501f 100644 --- a/packages/geom/src/ops/unmap-point.ts +++ b/packages/geom/src/ops/unmap-point.ts @@ -1,4 +1,5 @@ -import { defmulti, MultiFn2O } from "@thi.ng/defmulti"; +import { IObjectOf } from "@thi.ng/api"; +import { defmulti, Implementation2O, MultiFn2O } from "@thi.ng/defmulti"; import { IShape, Type } from "@thi.ng/geom-api"; import { madd, @@ -25,11 +26,11 @@ import { dispatch } from "../internal/dispatch"; * @param uv * @param out */ -export const unmapPoint: MultiFn2O = defmulti( - dispatch -); +export const unmapPoint: MultiFn2O = defmulti(< + any +>dispatch); -unmapPoint.addAll({ +unmapPoint.addAll(>>{ [Type.QUAD]: ({ points }: Quad, uv, out = []) => mixBilinear( out, @@ -42,7 +43,7 @@ unmapPoint.addAll({ ), [Type.RECT]: ($: Rect, uvw: ReadonlyVec, out = []) => - madd(out, $.pos, $.size, uvw) + madd(out, $.size, uvw, $.pos) }); unmapPoint.isa(Type.AABB, Type.RECT); diff --git a/packages/geom/src/ops/vertices.ts b/packages/geom/src/ops/vertices.ts index 0c92c37cf2..07d578ee27 100644 --- a/packages/geom/src/ops/vertices.ts +++ b/packages/geom/src/ops/vertices.ts @@ -1,5 +1,6 @@ +import { IObjectOf } from "@thi.ng/api"; import { isNumber } from "@thi.ng/checks"; -import { defmulti, MultiFn1O } from "@thi.ng/defmulti"; +import { defmulti, Implementation1O, MultiFn1O } from "@thi.ng/defmulti"; import { DEFAULT_SAMPLES, IShape, @@ -40,7 +41,9 @@ export const vertices: MultiFn1O< Vec[] > = defmulti(dispatch); -vertices.addAll({ +vertices.addAll(< + IObjectOf, Vec[]>> +>{ [Type.AABB]: ({ pos, size }: AABB) => { const [px, py, pz] = pos; const [qx, qy, qz] = add3([], pos, size); @@ -83,13 +86,13 @@ vertices.addAll({ const delta = TAU / num; last && num++; for (let i = 0; i < num; i++) { - buf[i] = madd2([], pos, cossin(i * delta), r); + buf[i] = madd2([], cossin(i * delta), r, pos); } return buf; }, [Type.GROUP]: ({ children }: Group) => - children.reduce((acc, $) => acc.concat(vertices($)), []), + children.reduce((acc, $) => acc.concat(vertices($)), []), [Type.PATH]: ($: Path, opts?: number | Partial) => { const _opts = isNumber(opts) ? { num: opts } : opts; diff --git a/packages/geom/src/ops/volume.ts b/packages/geom/src/ops/volume.ts index a76c872c50..84eb3a64a5 100644 --- a/packages/geom/src/ops/volume.ts +++ b/packages/geom/src/ops/volume.ts @@ -1,4 +1,5 @@ -import { DEFAULT, defmulti, MultiFn1 } from "@thi.ng/defmulti"; +import { IObjectOf } from "@thi.ng/api"; +import { DEFAULT, defmulti, Implementation1 } from "@thi.ng/defmulti"; import { IShape, Type } from "@thi.ng/geom-api"; import { PI } from "@thi.ng/math"; import { AABB, Sphere } from "../api"; @@ -12,10 +13,10 @@ import { dispatch } from "../internal/dispatch"; * - AABB * - Sphere */ -export const volume: MultiFn1 = defmulti(dispatch); +export const volume = defmulti(dispatch); volume.add(DEFAULT, () => 0); -volume.addAll({ +volume.addAll(>>{ [Type.AABB]: ({ size }: AABB) => size[0] * size[1] * size[2], [Type.SPHERE]: ($: Sphere) => (4 / 3) * PI * $.r ** 3 diff --git a/packages/hdom-canvas/CHANGELOG.md b/packages/hdom-canvas/CHANGELOG.md index 87a4f41934..9384f979a3 100644 --- a/packages/hdom-canvas/CHANGELOG.md +++ b/packages/hdom-canvas/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [2.1.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/hdom-canvas@2.0.18...@thi.ng/hdom-canvas@2.1.0) (2019-07-07) + + +### Features + +* **hdom-canvas:** enable TS strict compiler flags (refactor) ([998f5a1](https://github.com/thi-ng/umbrella/commit/998f5a1)) + + + + + ## [2.0.18](https://github.com/thi-ng/umbrella/compare/@thi.ng/hdom-canvas@2.0.17...@thi.ng/hdom-canvas@2.0.18) (2019-05-22) **Note:** Version bump only for package @thi.ng/hdom-canvas diff --git a/packages/hdom-canvas/package.json b/packages/hdom-canvas/package.json index 15468485bb..1d99572ba0 100644 --- a/packages/hdom-canvas/package.json +++ b/packages/hdom-canvas/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/hdom-canvas", - "version": "2.0.18", + "version": "2.1.0", "description": "Declarative canvas scenegraph & visualization for @thi.ng/hdom", "module": "./index.js", "main": "./lib/index.js", @@ -25,18 +25,18 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/api": "^6.2.0", - "@thi.ng/checks": "^2.1.6", - "@thi.ng/color": "^0.1.21", - "@thi.ng/diff": "^3.1.3", - "@thi.ng/hdom": "^7.2.8" + "@thi.ng/api": "^6.3.0", + "@thi.ng/checks": "^2.2.0", + "@thi.ng/color": "^0.2.0", + "@thi.ng/diff": "^3.2.0", + "@thi.ng/hdom": "^8.0.0" }, "keywords": [ "ES6", diff --git a/packages/hdom-canvas/src/index.ts b/packages/hdom-canvas/src/index.ts index f0ae748493..257569dec0 100644 --- a/packages/hdom-canvas/src/index.ts +++ b/packages/hdom-canvas/src/index.ts @@ -1,4 +1,4 @@ -import { IObjectOf, NO_OP } from "@thi.ng/api"; +import { assert, IObjectOf, NO_OP } from "@thi.ng/api"; import { isArray, isArrayLike, @@ -29,7 +29,7 @@ const TAU = Math.PI * 2; const FN = "function"; const STR = "string"; -const DEFAULTS = { +const DEFAULTS: any = { align: "left", alpha: 1, baseline: "alphabetic", @@ -51,7 +51,7 @@ const DEFAULTS = { stroke: "#000" }; -const CTX_ATTRIBS = { +const CTX_ATTRIBS: IObjectOf = { align: "textAlign", alpha: "globalAlpha", baseline: "textBaseline", @@ -114,7 +114,7 @@ const CTX_ATTRIBS = { * @param shapes shape components */ export const canvas = { - render(_, attribs, ...body: any[]) { + render(_: any, attribs: any, ...body: any[]) { const cattribs = { ...attribs }; delete cattribs.__diff; delete cattribs.__normalize; @@ -153,17 +153,18 @@ export const createTree = ( ) => { // console.log(Date.now(), "draw"); const ctx = canvas.getContext("2d"); + assert(!!ctx, "canvas ctx unavailable"); const attribs = tree[1]; if (attribs) { if (attribs.__skip) return; if (attribs.__clear !== false) { - ctx.clearRect(0, 0, canvas.width, canvas.height); + ctx!.clearRect(0, 0, canvas.width, canvas.height); } } - walk(ctx, tree, { attribs: {} }); + walk(ctx!, tree, { attribs: {} }); }; -export const normalizeTree = (opts: Partial, tree: any) => { +export const normalizeTree = (opts: Partial, tree: any): any => { if (tree == null) { return tree; } @@ -235,7 +236,13 @@ export const IMPL: HDOMImplementation = { hydrateTree: NO_OP, getElementById: NO_OP, createElement: NO_OP, - createTextElement: NO_OP + createTextElement: NO_OP, + replaceChild: NO_OP, + getChild: NO_OP, + removeAttribs: NO_OP, + removeChild: NO_OP, + setAttrib: NO_OP, + setContent: NO_OP }; const walk = ( @@ -336,7 +343,7 @@ const mergeState = ( state: DrawState, attribs: IObjectOf ) => { - let res: DrawState; + let res: DrawState | undefined; if (!attribs) return; if (applyTransform(ctx, attribs)) { res = { @@ -358,8 +365,8 @@ const mergeState = ( edits: [] }; } - res.attribs[id] = v; - res.edits.push(id); + res!.attribs[id] = v; + res!.edits!.push(id); setAttrib(ctx, state, id, k, v); } } @@ -403,22 +410,22 @@ const setAttrib = ( case "fill": case "stroke": case "shadowColor": - ctx[k] = resolveColor(state, val); + (ctx)[k] = resolveColor(state, val); break; case "dash": - ctx[k].call(ctx, val); + (ctx)[k].call(ctx, val); break; case "clip": break; default: - ctx[k] = val; + (ctx)[k] = val; } }; const resolveColor = (state: DrawState, v: any) => isString(v) ? v[0] === "$" - ? state.grads[v.substr(1)] + ? state.grads![v.substr(1)] : v : isArrayLike(v) ? isNumber((v).mode) @@ -777,8 +784,8 @@ const image = ( img, spos[0], spos[1], - ssize[0] || width, - ssize[1] || height, + ssize ? ssize[0] : width, + ssize ? ssize[1] : height, dpos[0], dpos[1], width, diff --git a/packages/hdom-components/CHANGELOG.md b/packages/hdom-components/CHANGELOG.md index e4eff1d24a..617f824f51 100644 --- a/packages/hdom-components/CHANGELOG.md +++ b/packages/hdom-components/CHANGELOG.md @@ -3,6 +3,22 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [3.1.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/hdom-components@3.0.20...@thi.ng/hdom-components@3.1.0) (2019-07-07) + + +### Bug Fixes + +* **hdom-components:** update CanvasHandler args ([080411f](https://github.com/thi-ng/umbrella/commit/080411f)) + + +### Features + +* **hdom-components:** enable TS strict compiler flags (refactor) ([6233ba2](https://github.com/thi-ng/umbrella/commit/6233ba2)) + + + + + ## [3.0.20](https://github.com/thi-ng/umbrella/compare/@thi.ng/hdom-components@3.0.19...@thi.ng/hdom-components@3.0.20) (2019-05-22) **Note:** Version bump only for package @thi.ng/hdom-components diff --git a/packages/hdom-components/adr/index.md b/packages/hdom-components/adr/index.md new file mode 100644 index 0000000000..4e39bf07ee --- /dev/null +++ b/packages/hdom-components/adr/index.md @@ -0,0 +1,5 @@ +# Architecture Decision Records + +* [1. Record architecture decisions](0001-record-architecture-decisions.md) +* [2. Component configuration](0002-component-configuration.md) +* [3. Component configuration via context](0003-component-configuration-via-context.md) diff --git a/packages/hdom-components/package.json b/packages/hdom-components/package.json index 0c9bfbaac4..95b08f653c 100644 --- a/packages/hdom-components/package.json +++ b/packages/hdom-components/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/hdom-components", - "version": "3.0.20", + "version": "3.1.0", "description": "Raw, skinnable UI & SVG components for @thi.ng/hdom", "module": "./index.js", "main": "./lib/index.js", @@ -25,18 +25,18 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/api": "^6.2.0", - "@thi.ng/checks": "^2.1.6", - "@thi.ng/math": "^1.3.0", - "@thi.ng/transducers": "^5.3.7", - "@thi.ng/transducers-stats": "^1.0.19", + "@thi.ng/api": "^6.3.0", + "@thi.ng/checks": "^2.2.0", + "@thi.ng/math": "^1.4.0", + "@thi.ng/transducers": "^5.4.0", + "@thi.ng/transducers-stats": "^1.1.0", "@types/webgl2": "^0.0.4" }, "keywords": [ diff --git a/packages/hdom-components/src/button-group.ts b/packages/hdom-components/src/button-group.ts index c8678276bc..f19311be5d 100644 --- a/packages/hdom-components/src/button-group.ts +++ b/packages/hdom-components/src/button-group.ts @@ -53,7 +53,7 @@ export interface ButtonGroupItem extends Array { } export type ButtonGroup = ( - _, + _: any, args: ButtonGroupArgs, ...buttons: ButtonGroupItem[] ) => any; @@ -92,7 +92,7 @@ const groupBody = ( ) => { switch (buttons.length) { case 0: - return; + return []; case 1: return [bt(opts.inner || opts.first, disabled, buttons[0])]; case 2: diff --git a/packages/hdom-components/src/button.ts b/packages/hdom-components/src/button.ts index 67d4a4efde..e4cac01c8e 100644 --- a/packages/hdom-components/src/button.ts +++ b/packages/hdom-components/src/button.ts @@ -32,12 +32,12 @@ export interface ButtonOpts { } export interface ButtonArgs { - attribs: IObjectOf; onclick: EventListener; - disabled: boolean; + attribs?: IObjectOf; + disabled?: boolean; } -export type Button = (_: any, args: Partial, ...body: any[]) => any; +export type Button = (_: any, args: ButtonArgs, ...body: any[]) => any; /** * Higher order function to create a new stateless button component, @@ -63,22 +63,22 @@ export const button = (opts?: Partial): Button => { ...opts }; !opts.attribs.role && (opts.attribs.role = "button"); - return (_: any, args: Partial, ...body: any[]) => + return (_: any, args: ButtonArgs, ...body: any[]) => args.disabled ? [ - opts.tagDisabled, + opts!.tagDisabled, { - ...mergeAttribs(opts.attribsDisabled, args.attribs), + ...mergeAttribs(opts!.attribsDisabled, args.attribs), disabled: true }, ...body ] : [ - opts.tag, + opts!.tag, { - ...mergeAttribs(opts.attribs, args.attribs), - onclick: opts.preventDefault - ? (e) => (e.preventDefault(), args.onclick(e)) + ...mergeAttribs(opts!.attribs, args.attribs), + onclick: opts!.preventDefault + ? (e: Event) => (e.preventDefault(), args.onclick(e)) : args.onclick }, ...body diff --git a/packages/hdom-components/src/canvas.ts b/packages/hdom-components/src/canvas.ts index d2c3accb87..ec0539e15f 100644 --- a/packages/hdom-components/src/canvas.ts +++ b/packages/hdom-components/src/canvas.ts @@ -20,23 +20,23 @@ export interface CanvasHandlers { /** * user init handler (called only once when canvas first) */ - init(el: HTMLCanvasElement, ctx: T, hctx?: any, ...args: any[]): void; + init(el: HTMLCanvasElement, ctx: T, hctx: any, ...args: any[]): void; /** * update handler (called for each hdom update iteration) */ update( el: HTMLCanvasElement, ctx: T, - hctx?: any, - time?: number, - frame?: number, + hctx: any, + time: number, + frame: number, ...args: any[] ): void; /** * release handler (called only once when canvas element is removed * from DOM) */ - release(el: HTMLCanvasElement, ctx: T, hctx?: any, ...args: any[]): void; + release(el: HTMLCanvasElement, ctx: T, hctx: any, ...args: any[]): void; } /** @@ -47,8 +47,13 @@ export interface CanvasHandlers { * @param handlers user handlers * @param opts canvas context creation options */ -const _canvas = (type, handlers: Partial>, opts) => { - let el, ctx; +const _canvas = ( + type: string, + handlers: Partial>, + opts: Canvas2DContextAttributes | WebGLContextAttributes | undefined +) => { + let el: HTMLCanvasElement; + let ctx: any; let frame = 0; let time = 0; return { diff --git a/packages/hdom-components/src/dropdown.ts b/packages/hdom-components/src/dropdown.ts index 8048ba2494..5bd62b100c 100644 --- a/packages/hdom-components/src/dropdown.ts +++ b/packages/hdom-components/src/dropdown.ts @@ -11,7 +11,7 @@ export interface DropDownOptionGroup extends Array { export const option = ( [value, label, disabled]: DropDownOption, - sel: string | number + sel: string | number | undefined ) => [ "option", { value, disabled: !!disabled, selected: value === sel }, diff --git a/packages/hdom-components/src/fps-counter.ts b/packages/hdom-components/src/fps-counter.ts index a281c99543..4022709ea9 100644 --- a/packages/hdom-components/src/fps-counter.ts +++ b/packages/hdom-components/src/fps-counter.ts @@ -31,15 +31,15 @@ export interface FpsCounterOpts { * * @param opts */ -export const fpsCounter = (opts?: Partial) => { - opts = { +export const fpsCounter = (_opts?: Partial) => { + const opts = { history: 25, smooth: 5, labelPeriod: 250, sparkline: {}, - ...opts + ..._opts }; - return { + return { init() { this.last = Date.now(); this.lastLabel = this.last; diff --git a/packages/hdom-components/src/link.ts b/packages/hdom-components/src/link.ts index fee613f39e..0c88b98fa9 100644 --- a/packages/hdom-components/src/link.ts +++ b/packages/hdom-components/src/link.ts @@ -6,11 +6,16 @@ export const link = (attribs: any, body: any) => [ body ]; -export const appLink = (_, attribs: any, onclick: EventListener, body: any) => [ +export const appLink = ( + _: any, + attribs: any, + onclick: EventListener, + body: any +) => [ "a", { href: "#", - onclick: (e) => { + onclick: (e: Event) => { e.preventDefault(); onclick(e); }, diff --git a/packages/hdom-components/src/notification.ts b/packages/hdom-components/src/notification.ts index ee18879902..6cafc8d7c4 100644 --- a/packages/hdom-components/src/notification.ts +++ b/packages/hdom-components/src/notification.ts @@ -55,8 +55,8 @@ export interface NotificationArgs { * * @param opts */ -export const notification = (opts?: Partial) => { - return (_, args: Partial, body: any) => [ +export const notification = (opts: Partial = {}) => { + return (_: any, args: Partial, body: any) => [ "div", { ...opts.attribs, ...args.attribs }, opts.icon, diff --git a/packages/hdom-components/src/pager.ts b/packages/hdom-components/src/pager.ts index 0c95a72ced..e1b3f737af 100644 --- a/packages/hdom-components/src/pager.ts +++ b/packages/hdom-components/src/pager.ts @@ -122,22 +122,20 @@ export interface PagerOpts { * * @param opts */ -export const pager = (opts: PagerOpts) => { - opts = Object.assign( - { - root: (_, ...body: any[]) => ["div.pager", ...body], - groupPrev: (_, ...bts: any[]) => ["div.pager-prev", ...bts], - groupNext: (_, ...bts: any[]) => ["div.pager-next", ...bts], - groupPages: (_, ...bts: any[]) => ["div.pager-pages", ...bts], - navStep: 1, - labelFirst: "<<", - labelPrev: "<", - labelNext: ">", - labelLast: ">>" - }, - opts - ); - return (_, id: number, num: number, pageLen = 10, maxBts = 5) => { +export const pager = (_opts: PagerOpts) => { + const opts = { + root: (_, ...body: any[]) => ["div.pager", ...body], + groupPrev: (_, ...bts: any[]) => ["div.pager-prev", ...bts], + groupNext: (_, ...bts: any[]) => ["div.pager-next", ...bts], + groupPages: (_, ...bts: any[]) => ["div.pager-pages", ...bts], + navStep: 1, + labelFirst: "<<", + labelPrev: "<", + labelNext: ">", + labelLast: ">>", + ..._opts + }; + return (_: any, id: number, num: number, pageLen = 10, maxBts = 5) => { const bt = opts.button; const step = opts.navStep; const maxID = Math.floor(Math.max(0, num - 1) / pageLen); @@ -147,7 +145,7 @@ export const pager = (opts: PagerOpts) => { [ opts.groupPrev, bt(0, id, maxID, opts.labelFirst, !id), - bt(Math.max(id - step, 0), id, maxID, opts.labelPrev, !id) + bt(Math.max(id - step!, 0), id, maxID, opts.labelPrev, !id) ], [ opts.groupPages, @@ -159,7 +157,7 @@ export const pager = (opts: PagerOpts) => { [ opts.groupNext, bt( - Math.min(id + step, maxID), + Math.min(id + step!, maxID), id, maxID, opts.labelNext, diff --git a/packages/hdom-components/src/sparkline.ts b/packages/hdom-components/src/sparkline.ts index 7aea0c80b1..bc2411142f 100644 --- a/packages/hdom-components/src/sparkline.ts +++ b/packages/hdom-components/src/sparkline.ts @@ -41,15 +41,19 @@ export interface SparklineOpts { * @param opts config options * @param vals data values */ -export const sparkline = (_, opts: Partial, vals: number[]) => { - opts = { +export const sparkline = ( + _: any, + _opts: Partial, + vals: number[] +) => { + const opts = { min: 0, max: 100, width: 50, height: 16, col: "red", r: 1.5, - ...opts + ..._opts }; const n = vals.length; const s = opts.width / n; diff --git a/packages/hdom-components/src/title.ts b/packages/hdom-components/src/title.ts index 8c9ddf0a0c..099a4b57a1 100644 --- a/packages/hdom-components/src/title.ts +++ b/packages/hdom-components/src/title.ts @@ -32,17 +32,15 @@ export interface TitleOpts { * * @param opts */ -export const title = (opts?: Partial) => { - opts = Object.assign( - { - element: "h1", - attribs: {}, - subElement: "small", - subAttribs: {} - }, - opts - ); - return (_, title, subtitle) => [ +export const title = (_opts?: Partial) => { + const opts = { + element: "h1", + attribs: {}, + subElement: "small", + subAttribs: {}, + ..._opts + }; + return (_: any, title: any, subtitle: any) => [ opts.element, opts.attribs, title, diff --git a/packages/hdom-mock/CHANGELOG.md b/packages/hdom-mock/CHANGELOG.md index 594ca1ce21..79bf342246 100644 --- a/packages/hdom-mock/CHANGELOG.md +++ b/packages/hdom-mock/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.1.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/hdom-mock@1.0.16...@thi.ng/hdom-mock@1.1.0) (2019-07-07) + + +### Features + +* **hdom-mock:** enable TS strict compiler flags (refactor) ([787e2d4](https://github.com/thi-ng/umbrella/commit/787e2d4)) + + + + + ## [1.0.16](https://github.com/thi-ng/umbrella/compare/@thi.ng/hdom-mock@1.0.15...@thi.ng/hdom-mock@1.0.16) (2019-05-22) **Note:** Version bump only for package @thi.ng/hdom-mock diff --git a/packages/hdom-mock/package.json b/packages/hdom-mock/package.json index 621e750fdb..d7227a989e 100644 --- a/packages/hdom-mock/package.json +++ b/packages/hdom-mock/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/hdom-mock", - "version": "1.0.16", + "version": "1.1.0", "description": "Mock base implementation for @thi.ng/hdom API", "module": "./index.js", "main": "./lib/index.js", @@ -25,16 +25,16 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/api": "^6.2.0", - "@thi.ng/checks": "^2.1.6", - "@thi.ng/hdom": "^7.2.8" + "@thi.ng/api": "^6.3.0", + "@thi.ng/checks": "^2.2.0", + "@thi.ng/hdom": "^8.0.0" }, "keywords": [ "ES6", diff --git a/packages/hdom-mock/src/index.ts b/packages/hdom-mock/src/index.ts index e86f0e0b85..3886ed144d 100644 --- a/packages/hdom-mock/src/index.ts +++ b/packages/hdom-mock/src/index.ts @@ -12,7 +12,6 @@ import { export const TEXT = Symbol(); export class HDOMNode { - parent: HDOMNode; /** * Only real child nodes */ @@ -25,12 +24,12 @@ export class HDOMNode { listeners: IObjectOf; value: any; - checked: boolean; + checked: boolean | undefined; tag: string | symbol; attribs: IObjectOf; - style: IObjectOf; - body: string; + style: IObjectOf | undefined; + body: string | undefined; constructor(tag: string | symbol, attribs = {}) { this.tag = tag; @@ -86,15 +85,17 @@ export class HDOMNode { } } - getElementById(id: string) { + getElementById(id: string): HDOMNode | null { if (this.attribs.id === id) return this; - for (let c of this.children) { + let c: HDOMNode | null; + for (c of this.children) { c = c.getElementById(id); if (c) return c; } + return null; } - toHiccup() { + toHiccup(): any { if (this.isText()) { return this.body; } @@ -122,7 +123,7 @@ export class MockHDOM implements HDOMImplementation { parent: HDOMNode, tree: any, child?: number - ) { + ): HDOMNode | HDOMNode[] { return createTree(opts, this, parent, tree, child); } @@ -172,7 +173,7 @@ export class MockHDOM implements HDOMImplementation { return el; } - getElementById(id: string): HDOMNode { + getElementById(id: string): HDOMNode | null { return this.root.getElementById(id); } @@ -183,7 +184,7 @@ export class MockHDOM implements HDOMImplementation { tree: any ) { this.removeChild(parent, child); - this.createTree(opts, parent, tree, child); + return this.createTree(opts, parent, tree, child); } getChild(parent: HDOMNode, i: number) { @@ -228,7 +229,9 @@ export class MockHDOM implements HDOMImplementation { } } } else { - el[id] != null ? (el[id] = null) : delete el.attribs[id]; + (el)[id] != null + ? ((el)[id] = null) + : delete el.attribs[id]; } return el; } @@ -243,7 +246,7 @@ export class MockHDOM implements HDOMImplementation { i >= 0 && listeners.splice(i, 1); } } else { - el[a] ? (el[a] = null) : delete el.attribs[a]; + (el)[a] ? ((el)[a] = null) : delete el.attribs[a]; } } } diff --git a/packages/hdom-mock/test/index.ts b/packages/hdom-mock/test/index.ts index 87744b74d9..d0b402a4f7 100644 --- a/packages/hdom-mock/test/index.ts +++ b/packages/hdom-mock/test/index.ts @@ -2,7 +2,6 @@ import * as assert from "assert"; import { HDOMNode, MockHDOM } from "../src/index"; describe("hdom-mock", () => { - it("node", () => { const a = new HDOMNode("div"); const impl = new MockHDOM(a); @@ -25,27 +24,52 @@ describe("hdom-mock", () => { assert.deepEqual(impl.root.toHiccup(), expected); }; - const a = impl.normalizeTree(opts, (ctx) => ["div#foo.bar", ["button", { ...ctx.button }, "hi"]]); - const b = impl.normalizeTree(opts, ["div#foo2.bar.baz", [(ctx, label) => ["button", { ...ctx.button }, label], "hello"], ["div", "extra"]]); - const c = impl.normalizeTree(opts, ["div#foo3.baz.bux", ["div", "extra"]]); + const a = impl.normalizeTree(opts, (ctx: any) => [ + "div#foo.bar", + ["button", { ...ctx.button }, "hi"] + ]); + const b = impl.normalizeTree(opts, [ + "div#foo2.bar.baz", + [ + (ctx: any, label: any) => ["button", { ...ctx.button }, label], + "hello" + ], + ["div", "extra"] + ]); + const c = impl.normalizeTree(opts, [ + "div#foo3.baz.bux", + ["div", "extra"] + ]); - step([], a, - ["root", {}, - ["div", { id: "foo", class: "bar", key: "0" }, - ["button", { class: "bt", key: "0-0" }, "hi"]]] - ); + step([], a, [ + "root", + {}, + [ + "div", + { id: "foo", class: "bar", key: "0" }, + ["button", { class: "bt", key: "0-0" }, "hi"] + ] + ]); - step(a, b, - ["root", {}, - ["div", { id: "foo2", class: "bar baz", key: "0" }, - ["button", { class: "bt", key: "0-0" }, "hello"], - ["div", { key: "0-1" }, ["span", { key: "0-1-0" }, "extra"]]]] - ); + step(a, b, [ + "root", + {}, + [ + "div", + { id: "foo2", class: "bar baz", key: "0" }, + ["button", { class: "bt", key: "0-0" }, "hello"], + ["div", { key: "0-1" }, ["span", { key: "0-1-0" }, "extra"]] + ] + ]); - step(b, c, - ["root", {}, - ["div", { id: "foo3", class: "baz bux", key: "0" }, - ["div", { key: "0-0" }, ["span", { key: "0-0-0" }, "extra"]]]] - ); + step(b, c, [ + "root", + {}, + [ + "div", + { id: "foo3", class: "baz bux", key: "0" }, + ["div", { key: "0-0" }, ["span", { key: "0-0-0" }, "extra"]] + ] + ]); }); }); diff --git a/packages/hdom/CHANGELOG.md b/packages/hdom/CHANGELOG.md index 784d04b1b0..79fb5aeea4 100644 --- a/packages/hdom/CHANGELOG.md +++ b/packages/hdom/CHANGELOG.md @@ -3,6 +3,27 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [8.0.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/hdom@7.2.8...@thi.ng/hdom@8.0.0) (2019-07-07) + + +### Code Refactoring + +* **hdom:** address TS strictNullChecks flag ([d83600a](https://github.com/thi-ng/umbrella/commit/d83600a)) + + +### Features + +* **hdom:** enable TS strict compiler flags (refactor) ([7f093b9](https://github.com/thi-ng/umbrella/commit/7f093b9)) + + +### BREAKING CHANGES + +* **hdom:** all HDOMImplementation methods now mandatory, update return types + + + + + ## [7.2.8](https://github.com/thi-ng/umbrella/compare/@thi.ng/hdom@7.2.7...@thi.ng/hdom@7.2.8) (2019-05-22) **Note:** Version bump only for package @thi.ng/hdom diff --git a/packages/hdom/package.json b/packages/hdom/package.json index 74a1095124..7a0f7e05f2 100644 --- a/packages/hdom/package.json +++ b/packages/hdom/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/hdom", - "version": "7.2.8", + "version": "8.0.0", "description": "Lightweight vanilla ES6 UI component trees with customizable branch-local behaviors", "module": "./index.js", "main": "./lib/index.js", @@ -24,21 +24,21 @@ "pub": "yarn build && yarn publish --access public" }, "devDependencies": { - "@thi.ng/atom": "^2.0.12", + "@thi.ng/atom": "^3.0.0", "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/api": "^6.2.0", - "@thi.ng/checks": "^2.1.6", - "@thi.ng/diff": "^3.1.3", - "@thi.ng/equiv": "^1.0.6", - "@thi.ng/errors": "^1.0.6", - "@thi.ng/hiccup": "^3.1.9" + "@thi.ng/api": "^6.3.0", + "@thi.ng/checks": "^2.2.0", + "@thi.ng/diff": "^3.2.0", + "@thi.ng/equiv": "^1.0.7", + "@thi.ng/errors": "^1.1.0", + "@thi.ng/hiccup": "^3.2.0" }, "keywords": [ "browser", diff --git a/packages/hdom/src/api.ts b/packages/hdom/src/api.ts index 43e42091bf..0e9abe9c86 100644 --- a/packages/hdom/src/api.ts +++ b/packages/hdom/src/api.ts @@ -9,7 +9,7 @@ export interface ILifecycle { * children have their own `init` lifecycle method, these hooks will * be executed before that of the parent. */ - init?(el: Element, ctx: any, ...args: any[]); + init?(el: Element, ctx: any, ...args: any[]): void; /** * Returns the hdom tree of this component. @@ -38,7 +38,7 @@ export interface ILifecycle { * Called when the underlying DOM of this component is removed * (or replaced). Intended for cleanup tasks. */ - release?(ctx: any, ...args: any[]); + release?(ctx: any, ...args: any[]): void; } export interface HDOMBehaviorAttribs { @@ -288,7 +288,12 @@ export interface HDOMImplementation { * @param tree * @param child */ - hydrateTree(opts: Partial, parent: T, tree: any, child?: number); + hydrateTree( + opts: Partial, + parent: T, + tree: any, + child?: number + ): void; /** * Takes an `HDOMOpts` options object, a `parent` element and two @@ -376,7 +381,7 @@ export interface HDOMImplementation { * * @param id */ - getElementById(id: string): T; + getElementById(id: string): T | null; /** * A (potentially) optimized version of these 2 operations in @@ -391,12 +396,12 @@ export interface HDOMImplementation { * @param child * @param newTree */ - replaceChild?( + replaceChild( opts: Partial, parent: T, child: number, newTree: any - ); + ): T | T[]; /** * Retrieves child of `parent` node at index `i`. @@ -404,7 +409,7 @@ export interface HDOMImplementation { * @param parent * @param i */ - getChild?(parent: T, i: number): T; + getChild(parent: T, i: number): T; /** * Removes the child of `parent` at index `i` in the target. @@ -412,7 +417,7 @@ export interface HDOMImplementation { * @param parent * @param i */ - removeChild?(parent: T, i: number); + removeChild(parent: T, i: number): void; /** * Sets the given attribute `id` to new `value`. Note: `value` @@ -426,7 +431,7 @@ export interface HDOMImplementation { * @param value * @param attribs */ - setAttrib?(element: T, id: string, value: any, attribs?: any); + setAttrib(element: T, id: string, value: any, attribs?: any): void; /** * Removes given `attribs` from target `element`. The attributes @@ -437,7 +442,7 @@ export interface HDOMImplementation { * @param attribs * @param prevAttribs */ - removeAttribs?(element: T, attribs: string[], prevAttribs: any); + removeAttribs(element: T, attribs: string[], prevAttribs: any): void; /** * Sets target `element`'s text / body content. Note: In the default @@ -450,7 +455,7 @@ export interface HDOMImplementation { * @param element * @param value */ - setContent?(element: T, value: any); + setContent(element: T, value: any): void; } export let LOGGER = NULL_LOGGER; diff --git a/packages/hdom/src/default.ts b/packages/hdom/src/default.ts index 683d67b3e1..69a6f6d315 100644 --- a/packages/hdom/src/default.ts +++ b/packages/hdom/src/default.ts @@ -1,9 +1,9 @@ import { HDOMImplementation } from "./api"; import { diffTree } from "./diff"; import { - createTree, createElement, createTextElement, + createTree, getChild, hydrateTree, removeAttribs, @@ -32,7 +32,7 @@ export const DEFAULT_IMPL: HDOMImplementation = { normalizeTree, - getElementById(id: string) { + getElementById(id: string): any | null { return document.getElementById(id); }, diff --git a/packages/hdom/src/diff.ts b/packages/hdom/src/diff.ts index a36d181e5f..f8d9dbfc56 100644 --- a/packages/hdom/src/diff.ts +++ b/packages/hdom/src/diff.ts @@ -69,13 +69,13 @@ export const diffTree = ( if (delta.distance === 0) { return; } - const edits = delta.linear; + const edits = delta.linear!; const el = impl.getChild(parent, child); let i: number; let ii: number; let j: number; let idx: number; - let k: string; + let k: any; let eq: any[]; let status: number; let val: any; @@ -164,21 +164,21 @@ export const diffAttributes = ( curr: any ) => { const delta = diffObject(prev, curr, DiffMode.FULL, _equiv); - impl.removeAttribs(el, delta.dels, prev); + impl.removeAttribs(el, delta.dels!, prev); let val = SEMAPHORE; - let i, e, edits; - for (edits = delta.edits, i = edits.length; (i -= 2) >= 0; ) { - const a = edits[i]; - if (a.indexOf("on") === 0) { - impl.removeAttribs(el, [a], prev); + let i: number, e, edits; + for (edits = delta.edits!, i = edits.length; (i -= 2) >= 0; ) { + e = edits[i]; + if (e.indexOf("on") === 0) { + impl.removeAttribs(el, [e], prev); } - if (a !== "value") { - impl.setAttrib(el, a, edits[i + 1], curr); + if (e !== "value") { + impl.setAttrib(el, e, edits[i + 1], curr); } else { val = edits[i + 1]; } } - for (edits = delta.adds, i = edits.length; --i >= 0; ) { + for (edits = delta.adds!, i = edits.length; --i >= 0; ) { e = edits[i]; if (e !== "value") { impl.setAttrib(el, e, curr[e], curr); diff --git a/packages/hdom/src/dom.ts b/packages/hdom/src/dom.ts index 8ed0a4e217..281c058e85 100644 --- a/packages/hdom/src/dom.ts +++ b/packages/hdom/src/dom.ts @@ -20,7 +20,7 @@ export const createTree = ( parent: T, tree: any, insert?: number -) => { +): any => { if (isArray(tree)) { const tag = tree[0]; if (typeof tag === "function") { @@ -194,7 +194,7 @@ export const replaceChild = ( export const cloneWithNewAttribs = (el: Element, attribs: any) => { const res = el.cloneNode(true); setAttribs(res, attribs); - el.parentNode.replaceChild(res, el); + el.parentNode!.replaceChild(res, el); return res; }; @@ -247,7 +247,7 @@ export const setAttrib = (el: Element, id: string, val: any, attribs?: any) => { case "scrollTop": case "scrollLeft": // TODO add more native attribs? - el[id] = val; + (el)[id] = val; break; default: if (isListener) { @@ -257,7 +257,7 @@ export const setAttrib = (el: Element, id: string, val: any, attribs?: any) => { } } } else { - el[id] != null ? (el[id] = null) : el.removeAttribute(id); + (el)[id] != null ? ((el)[id] = null) : el.removeAttribute(id); } return el; }; @@ -286,7 +286,7 @@ export const updateValueAttrib = (el: HTMLInputElement, v: any) => { case "week": case "month": if ((ev = el.value) !== undefined && typeof v === "string") { - const off = v.length - (ev.length - el.selectionStart); + const off = v.length - (ev.length - (el.selectionStart || 0)); el.value = v; el.selectionStart = el.selectionEnd = off; break; @@ -302,7 +302,7 @@ export const removeAttribs = (el: Element, attribs: string[], prev: any) => { if (a.indexOf("on") === 0) { removeListener(el, a.substr(2), prev[a]); } else { - el.hasAttribute(a) ? el.removeAttribute(a) : (el[a] = null); + el.hasAttribute(a) ? el.removeAttribute(a) : ((el)[a] = null); } } }; diff --git a/packages/hdom/src/normalize.ts b/packages/hdom/src/normalize.ts index 3a2d05d13d..6e9e655135 100644 --- a/packages/hdom/src/normalize.ts +++ b/packages/hdom/src/normalize.ts @@ -1,8 +1,4 @@ -import { - isArray as isa, - isNotStringAndIterable as isi, - isPlainObject as iso -} from "@thi.ng/checks"; +import { isArray as isa, isNotStringAndIterable as isi, isPlainObject as iso } from "@thi.ng/checks"; import { illegalArgs } from "@thi.ng/errors"; import { NO_SPANS, TAG_REGEXP } from "@thi.ng/hiccup"; import { HDOMOpts } from "./api"; @@ -39,22 +35,24 @@ const isPlainObject = iso; * @param keys */ export const normalizeElement = (spec: any[], keys: boolean) => { - let tag = spec[0], - hasAttribs = isPlainObject(spec[1]), - match, - id, - clazz, - attribs; + let tag = spec[0]; + let hasAttribs = isPlainObject(spec[1]); + let match: RegExpExecArray | null; + let mtag: string; + let id: string; + let clazz: string; + let attribs; if (typeof tag !== "string" || !(match = TAG_REGEXP.exec(tag))) { illegalArgs(`${tag} is not a valid tag name`); } + mtag = match![1]; // return orig if already normalized and satisfies key requirement - if (tag === match[1] && hasAttribs && (!keys || spec[1].key)) { + if (tag === mtag && hasAttribs && (!keys || spec[1].key)) { return spec; } attribs = hasAttribs ? { ...spec[1] } : {}; - id = match[2]; - clazz = match[3]; + id = match![2]; + clazz = match![3]; if (id) { attribs.id = id; } @@ -67,8 +65,8 @@ export const normalizeElement = (spec: any[], keys: boolean) => { } } return attribs.__skip && spec.length < 3 - ? [match[1], attribs, ""] - : [match[1], attribs, ...spec.slice(hasAttribs ? 2 : 1)]; + ? [mtag, attribs, ""] + : [mtag, attribs, ...spec.slice(hasAttribs ? 2 : 1)]; }; /** @@ -94,7 +92,7 @@ const _normalizeTree = ( path: number[], keys: boolean, span: boolean -) => { +): any => { if (tree == null) { return; } diff --git a/packages/hdom/src/start.ts b/packages/hdom/src/start.ts index 7efa32557c..428f10170b 100644 --- a/packages/hdom/src/start.ts +++ b/packages/hdom/src/start.ts @@ -53,7 +53,7 @@ export const start = ( impl: HDOMImplementation = DEFAULT_IMPL ) => { const _opts = { root: "app", ...opts }; - let prev = []; + let prev: any[] = []; let isActive = true; const root = resolveRoot(_opts.root, impl); const update = () => { diff --git a/packages/hdom/test/index.ts b/packages/hdom/test/index.ts index 67d343e5bb..d81b0f57ad 100644 --- a/packages/hdom/test/index.ts +++ b/packages/hdom/test/index.ts @@ -4,44 +4,21 @@ import { map, range } from "@thi.ng/iterators"; import * as assert from "assert"; import { normalizeTree } from "../src/normalize"; -const _check = - (a, b, ctx = null) => - assert.deepEqual(normalizeTree({ ctx, keys: false, span: false }, a), b); +const _check = (a: any, b: any, ctx: any = null) => + assert.deepEqual(normalizeTree({ ctx, keys: false, span: false }, a), b); -const check = - (id, a, b) => it(id, () => _check(a, b)); +const check = (id: string, a: any, b: any) => it(id, () => _check(a, b)); describe("hdom", () => { + check("undefined", undefined, undefined); - check( - "undefined", - undefined, - undefined - ); + check("null", null, undefined); - check( - "null", - null, - undefined - ); + check("empty tree", [], undefined); - check( - "empty tree", - [], - undefined - ); + check("simple div", ["div", "foo"], ["div", {}, "foo"]); - check( - "simple div", - ["div", "foo"], - ["div", {}, "foo"] - ); - - check( - "emmet id", - ["div#foo", "hi"], - ["div", { id: "foo" }, "hi"] - ); + check("emmet id", ["div#foo", "hi"], ["div", { id: "foo" }, "hi"]); check( "emmet id + id attr", @@ -66,21 +43,17 @@ describe("hdom", () => { ["div", { id: "id", class: "foo bar", extra: 23 }, "hi"] ); - check( - "root fn", - () => ["div"], - ["div", {}] - ); + check("root fn", () => ["div"], ["div", {}]); check( "tag fn w/ args", - [(_, id, body) => ["div#" + id, body], "foo", "bar"], + [(_: any, id: string, body: any) => ["div#" + id, body], "foo", "bar"], ["div", { id: "foo" }, "bar"] ); check( "child fn", - ["div", (x) => ["span", x]], + ["div", (x: any) => ["span", x]], ["div", {}, ["span", {}]] ); @@ -93,20 +66,18 @@ describe("hdom", () => { check( "iterator", ["div", map((x) => [`div#id${x}`, x], range(3))], - ["div", {}, ["div", { id: "id0" }, 0], ["div", { id: "id1" }, 1], ["div", { id: "id2" }, 2]] + [ + "div", + {}, + ["div", { id: "id0" }, 0], + ["div", { id: "id1" }, 1], + ["div", { id: "id2" }, 2] + ] ); - check( - "deref toplevel", - new Atom(["a"]), - ["a", {}] - ); + check("deref toplevel", new Atom(["a"]), ["a", {}]); - check( - "deref child", - ["a", new Atom(["b"])], - ["a", {}, ["b", {}]] - ); + check("deref child", ["a", new Atom(["b"])], ["a", {}, ["b", {}]]); it("life cycle", () => { let src: any = { render: () => ["div", "foo"] }; @@ -114,18 +85,12 @@ describe("hdom", () => { res.__this = src; res.__init = res.__release = undefined; res.__args = [null]; - assert.deepEqual( - normalizeTree({ keys: false }, [src]), - res - ); + assert.deepEqual(normalizeTree({ keys: false }, [src]), res); res = ["div", { key: "0" }, ["span", { key: "0-0" }, "foo"]]; res.__this = src; res.__init = res.__release = undefined; res.__args = [null]; - assert.deepEqual( - normalizeTree({}, [src]), - res - ); + assert.deepEqual(normalizeTree({}, [src]), res); }); it("dyn context", () => { @@ -134,7 +99,7 @@ describe("hdom", () => { { a: 23, b: new Atom(42), - c: new Atom({ foo: { bar: 66 } }).addView("foo.bar"), + c: new Atom({ foo: { bar: 66 } }).addView("foo.bar") }, ["a", "b", "c"] ), diff --git a/packages/heaps/CHANGELOG.md b/packages/heaps/CHANGELOG.md index f558f70f2b..eb4adf73d6 100644 --- a/packages/heaps/CHANGELOG.md +++ b/packages/heaps/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.1.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/heaps@1.0.10...@thi.ng/heaps@1.1.0) (2019-07-07) + + +### Features + +* **heaps:** enable TS strict compiler flags (refactor) ([86b9c9e](https://github.com/thi-ng/umbrella/commit/86b9c9e)) + + + + + ## [1.0.10](https://github.com/thi-ng/umbrella/compare/@thi.ng/heaps@1.0.9...@thi.ng/heaps@1.0.10) (2019-05-22) **Note:** Version bump only for package @thi.ng/heaps diff --git a/packages/heaps/package.json b/packages/heaps/package.json index 096c35cc1f..7efe33ca89 100644 --- a/packages/heaps/package.json +++ b/packages/heaps/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/heaps", - "version": "1.0.10", + "version": "1.1.0", "description": "Generic binary heap & d-ary heap implementations with customizable ordering", "module": "./index.js", "main": "./lib/index.js", @@ -25,15 +25,15 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/api": "^6.2.0", - "@thi.ng/compare": "^1.0.6" + "@thi.ng/api": "^6.3.0", + "@thi.ng/compare": "^1.0.7" }, "keywords": [ "data structure", diff --git a/packages/heaps/src/dheap.ts b/packages/heaps/src/dheap.ts index afe321499e..20b940fbab 100644 --- a/packages/heaps/src/dheap.ts +++ b/packages/heaps/src/dheap.ts @@ -36,8 +36,8 @@ export class DHeap extends Heap protected d: number; - constructor(values?: Iterable, opts?: Partial>) { - super(null, { compare, ...opts }); + constructor(values?: Iterable | null, opts?: Partial>) { + super(undefined, { compare, ...opts }); this.d = (opts && opts.d) || 4; this.values = []; if (values) { @@ -45,7 +45,7 @@ export class DHeap extends Heap } } - copy() { + copy(): DHeap { return >super.copy(); } diff --git a/packages/heaps/src/heap.ts b/packages/heaps/src/heap.ts index 1e5ed75023..675180a5d3 100644 --- a/packages/heaps/src/heap.ts +++ b/packages/heaps/src/heap.ts @@ -8,7 +8,6 @@ import { import { compare } from "@thi.ng/compare"; import { HeapOpts } from "./api"; - /** * Generic binary heap / priority queue with customizable ordering via * user-supplied comparator. By default, implements min-heap ordering @@ -38,7 +37,7 @@ export class Heap values: T[]; compare: Comparator; - constructor(values?: Iterable, opts?: HeapOpts) { + constructor(values?: Iterable | null, opts?: HeapOpts) { opts = Object.assign({ compare: compare }, opts); this.compare = opts.compare; this.values = []; @@ -85,10 +84,10 @@ export class Heap let res: T; if (vals.length > 0) { res = vals[0]; - vals[0] = tail; + vals[0] = tail; this.percolateDown(0); } else { - res = tail; + res = tail; } return res; } @@ -118,11 +117,11 @@ export class Heap * @param vals */ pushPopAll(vals: Iterable) { - let res: T; + let res: any; for (let v of vals) { res = this.pushPop(v); } - return res; + return res; } replaceHead(val: T) { diff --git a/packages/hiccup-carbon-icons/CHANGELOG.md b/packages/hiccup-carbon-icons/CHANGELOG.md index de62e2f84e..30c339b66a 100644 --- a/packages/hiccup-carbon-icons/CHANGELOG.md +++ b/packages/hiccup-carbon-icons/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.0.15](https://github.com/thi-ng/umbrella/compare/@thi.ng/hiccup-carbon-icons@1.0.14...@thi.ng/hiccup-carbon-icons@1.0.15) (2019-07-07) + +**Note:** Version bump only for package @thi.ng/hiccup-carbon-icons + + + + + ## [1.0.14](https://github.com/thi-ng/umbrella/compare/@thi.ng/hiccup-carbon-icons@1.0.13...@thi.ng/hiccup-carbon-icons@1.0.14) (2019-05-22) **Note:** Version bump only for package @thi.ng/hiccup-carbon-icons diff --git a/packages/hiccup-carbon-icons/package.json b/packages/hiccup-carbon-icons/package.json index c8c84a72e2..be4b48620c 100644 --- a/packages/hiccup-carbon-icons/package.json +++ b/packages/hiccup-carbon-icons/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/hiccup-carbon-icons", - "version": "1.0.14", + "version": "1.0.15", "description": "Full set of IBM's Carbon icons in hiccup format", "module": "./index.js", "main": "./lib/index.js", @@ -24,13 +24,13 @@ "pub": "yarn build && yarn publish --access public" }, "devDependencies": { - "@thi.ng/hiccup": "^3.1.9", + "@thi.ng/hiccup": "^3.2.0", "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "keywords": [ "assets", diff --git a/packages/hiccup-carbon-icons/test/contact-sheet.ts b/packages/hiccup-carbon-icons/test/contact-sheet.ts index 4e20f73c8f..4dfa3ae3d7 100644 --- a/packages/hiccup-carbon-icons/test/contact-sheet.ts +++ b/packages/hiccup-carbon-icons/test/contact-sheet.ts @@ -3,8 +3,11 @@ import { execSync } from "child_process"; import * as fs from "fs"; import * as icons from "../src/index"; -const REV = execSync("git log --pretty='%h %cI' -1").toString().trim(); +const REV = execSync("git log --pretty='%h %cI' -1") + .toString() + .trim(); +// prettier-ignore fs.writeFileSync( "contact-sheet.html", serialize( @@ -34,16 +37,16 @@ fs.writeFileSync( { style: { "font-size": "0.5rem" } }, Object .keys(icons) - .filter((id) => Array.isArray(icons[id])) + .filter((id) => Array.isArray((icons)[id])) .map((id) => { return ["div.dib.ma2", ["div.w4.h4.bg-light-gray.dark-gray.flex.items-center.tc", ["div.w-100", - icons.withSize(icons[id], "2rem"), + icons.withSize((icons)[id], "2rem"), ["div.mt3", id]]] ]; }) ] ] ] - )); \ No newline at end of file + )); diff --git a/packages/hiccup-css/CHANGELOG.md b/packages/hiccup-css/CHANGELOG.md index 0cf81cc1e0..ac58111224 100644 --- a/packages/hiccup-css/CHANGELOG.md +++ b/packages/hiccup-css/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.1.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/hiccup-css@1.0.19...@thi.ng/hiccup-css@1.1.0) (2019-07-07) + + +### Features + +* **hiccup-css:** enable TS strict compiler flags (refactor) ([1e81385](https://github.com/thi-ng/umbrella/commit/1e81385)) + + + + + ## [1.0.19](https://github.com/thi-ng/umbrella/compare/@thi.ng/hiccup-css@1.0.18...@thi.ng/hiccup-css@1.0.19) (2019-05-22) **Note:** Version bump only for package @thi.ng/hiccup-css diff --git a/packages/hiccup-css/package.json b/packages/hiccup-css/package.json index 09434db3bc..581a1194e8 100644 --- a/packages/hiccup-css/package.json +++ b/packages/hiccup-css/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/hiccup-css", - "version": "1.0.19", + "version": "1.1.0", "description": "CSS from nested JS data structures", "module": "./index.js", "main": "./lib/index.js", @@ -25,17 +25,17 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/api": "^6.2.0", - "@thi.ng/checks": "^2.1.6", - "@thi.ng/errors": "^1.0.6", - "@thi.ng/transducers": "^5.3.7" + "@thi.ng/api": "^6.3.0", + "@thi.ng/checks": "^2.2.0", + "@thi.ng/errors": "^1.1.0", + "@thi.ng/transducers": "^5.4.0" }, "keywords": [ "clojure", diff --git a/packages/hiccup-css/src/animation.ts b/packages/hiccup-css/src/animation.ts index 6cc572173b..7e7688e0ed 100644 --- a/packages/hiccup-css/src/animation.ts +++ b/packages/hiccup-css/src/animation.ts @@ -65,11 +65,13 @@ export const animation = ( ...opts }; return [ - at_keyframes.apply(null, [id, ...keyframes]), + at_keyframes.apply(null, [id, ...keyframes]), [ `.${id}`, Object.keys(opts).reduce( - (acc, k) => ((acc[`animation-${k}`] = opts[k]), acc), + (acc: any, k) => ( + (acc[`animation-${k}`] = (opts)[k]), acc + ), {} ) ] diff --git a/packages/hiccup-css/src/api.ts b/packages/hiccup-css/src/api.ts index f0a3c780f9..c20509a500 100644 --- a/packages/hiccup-css/src/api.ts +++ b/packages/hiccup-css/src/api.ts @@ -1,4 +1,4 @@ -import { IObjectOf } from "@thi.ng/api"; +import { FnAny, IObjectOf } from "@thi.ng/api"; /** * Function type used by `at_xxx()` functions or any @@ -44,7 +44,7 @@ export interface CSSOpts { * Maps keys to rule functions. * See quoted-functions.ts */ - fns: IObjectOf; + fns: IObjectOf>; /** * Array or set of properties to prefix automatically. * If given, each listed property will be prefixed diff --git a/packages/hiccup-css/src/attribs.ts b/packages/hiccup-css/src/attribs.ts index b58293831e..09977769ed 100644 --- a/packages/hiccup-css/src/attribs.ts +++ b/packages/hiccup-css/src/attribs.ts @@ -1,5 +1,8 @@ -const $ = (op) => (id: string, x: string | number, caseSensitve = false) => - `[${id}${op}="${x}"${caseSensitve ? " i" : ""}]`; +const $ = (op: string) => ( + id: string, + x: string | number, + caseSensitve = false +) => `[${id}${op}="${x}"${caseSensitve ? " i" : ""}]`; /** * Returns attrib selector: `[id]` diff --git a/packages/hiccup-css/src/css.ts b/packages/hiccup-css/src/css.ts index 4de580dd08..5c65ce78ad 100644 --- a/packages/hiccup-css/src/css.ts +++ b/packages/hiccup-css/src/css.ts @@ -26,9 +26,9 @@ export const css = (rules: any, opts?: Partial) => { rules = [...rules]; } if (isArray(rules)) { - return expand([], [], rules, opts).join(opts.format.rules); + return expand([], [], rules, opts).join(opts.format!.rules); } if (isFunction(rules)) { - return rules([], opts).join(opts.format.rules); + return rules([], opts).join(opts.format!.rules); } }; diff --git a/packages/hiccup-css/src/impl.ts b/packages/hiccup-css/src/impl.ts index f524dff213..7a2d805c8f 100644 --- a/packages/hiccup-css/src/impl.ts +++ b/packages/hiccup-css/src/impl.ts @@ -1,3 +1,4 @@ +import { FnAny } from "@thi.ng/api"; import { isArray, isFunction, @@ -16,15 +17,15 @@ import { transduce, Transducer } from "@thi.ng/transducers"; -import { CSSOpts } from "./api"; +import { CSSOpts, RuleFn } from "./api"; const EMPTY = new Set(); const NO_SPACES = ":["; -const xfSel = comp( +const xfSel = comp( flatten(), - map((x: string) => (NO_SPACES.indexOf(x.charAt(0)) >= 0 ? x : " " + x)) + map((x) => (NO_SPACES.indexOf(x.charAt(0)) >= 0 ? x : " " + x)) ); const withScope = (xf: Transducer, scope: string) => @@ -40,15 +41,16 @@ export const expand = ( const sel: string[] = []; let curr: any, isFn; - const process = (i, r) => { + const process = (i: number, r: any) => { + let rfn: FnAny | null = null; if (isArray(r)) { expand(acc, makeSelector(parent, sel), r, opts); } else if (isIterable(r) && !isString(r)) { expand(acc, makeSelector(parent, sel), [...r], opts); - } else if ((isFn = isFunction(r)) || opts.fns[r]) { + } else if ((isFn = isFunction(r)) || (rfn = opts.fns[r])) { if (!parent.length) { - if (opts.fns[r]) { - opts.fns[r].apply(null, rules.slice(i + 1))(acc, opts); + if (rfn) { + rfn.apply(null, rules.slice(i + 1))(acc, opts); return true; } r(acc, opts); @@ -127,5 +129,5 @@ export const indent = (opts: CSSOpts, d = opts.depth) => d > 1 ? [...repeat(opts.format.indent, d)].join("") : d > 0 - ? opts.format.indent - : ""; + ? opts.format.indent + : ""; diff --git a/packages/hiccup-css/test/index.ts b/packages/hiccup-css/test/index.ts index 0053f163a0..ba70a2b7a5 100644 --- a/packages/hiccup-css/test/index.ts +++ b/packages/hiccup-css/test/index.ts @@ -1,16 +1,22 @@ import * as assert from "assert"; +import { + animation, + at_import, + at_keyframes, + at_media, + css, + PRETTY +} from "../src"; -import { css, PRETTY, at_import, at_keyframes, at_media, animation } from "../src"; const rules = { a: { color: "red" }, b: { border: 0 }, c: { font: [["14px", "Inconsolata"], "monospace"] }, - f: { foo: (rules) => rules.bar, bar: 1 }, + f: { foo: (rules: any) => rules.bar, bar: 1 } }; describe("hiccup-css", () => { - it("rules only", () => { assert.equal(css("a"), undefined); assert.equal(css({}), ""); @@ -43,14 +49,11 @@ describe("hiccup-css", () => { "p a:link{color:red;}p a:visited{border:0;}" ); assert.equal( - css( - ["#id", - ["h1", {}, {}], - ["h2", "h3", - ["div", {}], - ["[attr]", - ["span", rules.a]]]] - ), + css([ + "#id", + ["h1", {}, {}], + ["h2", "h3", ["div", {}], ["[attr]", ["span", rules.a]]] + ]), "#id h1{}#id h2 div,#id h3 div{}#id h2[attr] span,#id h3[attr] span{color:red;}" ); }); @@ -58,22 +61,24 @@ describe("hiccup-css", () => { it("pretty", () => { assert.equal( css( - ["#id", + [ + "#id", ["h1", rules.a, rules.b], - ["h2", "h3", + [ + "h2", + "h3", ["div", rules.b], - ["[attr]", - ["span", rules.a]]]], - { format: PRETTY }), + ["[attr]", ["span", rules.a]] + ] + ], + { format: PRETTY } + ), "#id h1 {\n color: red;\n border: 0;\n}\n\n#id h2 div, #id h3 div {\n border: 0;\n}\n\n#id h2[attr] span, #id h3[attr] span {\n color: red;\n}\n" ); }); it("@import", () => { - assert.equal( - css(at_import("foo.css")), - "@import url(foo.css);" - ); + assert.equal(css(at_import("foo.css")), "@import url(foo.css);"); assert.equal( css([at_import("foo.css"), ["div", {}]]), "@import url(foo.css);div{}" @@ -90,7 +95,12 @@ describe("hiccup-css", () => { it("@keyframes", () => { assert.equal( - css(at_keyframes("fadein", { 0: { opacity: 0 }, 100: { opacity: 1 } })), + css( + at_keyframes("fadein", { + 0: { opacity: 0 }, + 100: { opacity: 1 } + }) + ), "@keyframes fadein{0%{opacity:0;}100%{opacity:1;}}" ); assert.equal( @@ -100,10 +110,7 @@ describe("hiccup-css", () => { }); it("@media", () => { - assert.equal( - css(at_media({ screen: true }, [])), - "@media screen{}" - ); + assert.equal(css(at_media({ screen: true }, [])), "@media screen{}"); assert.equal( css(at_media({ screen: false }, [])), "@media not screen{}" @@ -121,10 +128,17 @@ describe("hiccup-css", () => { "@media (min-width:10rem){div .foo{color:red;}}" ); assert.equal( - css(at_media({ screen: true, print: true }, [ - ["div", [".foo", rules.a]], - [at_media({ print: true, "max-width": "20rem" }, ["div", rules.b])] - ])), + css( + at_media({ screen: true, print: true }, [ + ["div", [".foo", rules.a]], + [ + at_media({ print: true, "max-width": "20rem" }, [ + "div", + rules.b + ]) + ] + ]) + ), "@media screen and print{div .foo{color:red;}@media print and (max-width:20rem){div{border:0;}}}" ); }); diff --git a/packages/hiccup-markdown/CHANGELOG.md b/packages/hiccup-markdown/CHANGELOG.md index d2501eb66e..d64f4197d7 100644 --- a/packages/hiccup-markdown/CHANGELOG.md +++ b/packages/hiccup-markdown/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.1.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/hiccup-markdown@1.0.22...@thi.ng/hiccup-markdown@1.1.0) (2019-07-07) + + +### Features + +* **hiccup-markdown:** enable TS strict compiler flags (refactor) ([36c8109](https://github.com/thi-ng/umbrella/commit/36c8109)) + + + + + ## [1.0.22](https://github.com/thi-ng/umbrella/compare/@thi.ng/hiccup-markdown@1.0.21...@thi.ng/hiccup-markdown@1.0.22) (2019-05-22) **Note:** Version bump only for package @thi.ng/hiccup-markdown diff --git a/packages/hiccup-markdown/package.json b/packages/hiccup-markdown/package.json index 09a0d3f9ec..23a5cb903f 100644 --- a/packages/hiccup-markdown/package.json +++ b/packages/hiccup-markdown/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/hiccup-markdown", - "version": "1.0.22", + "version": "1.1.0", "description": "Markdown serialization of hiccup DOM trees", "module": "./index.js", "main": "./lib/index.js", @@ -25,21 +25,21 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/arrays": "^0.1.9", - "@thi.ng/checks": "^2.1.6", - "@thi.ng/defmulti": "^1.0.9", - "@thi.ng/errors": "^1.0.6", - "@thi.ng/fsm": "^2.1.15", - "@thi.ng/hiccup": "^3.1.9", - "@thi.ng/strings": "^1.1.3", - "@thi.ng/transducers": "^5.3.7" + "@thi.ng/arrays": "^0.2.0", + "@thi.ng/checks": "^2.2.0", + "@thi.ng/defmulti": "^1.1.0", + "@thi.ng/errors": "^1.1.0", + "@thi.ng/fsm": "^2.2.0", + "@thi.ng/hiccup": "^3.2.0", + "@thi.ng/strings": "^1.2.0", + "@thi.ng/transducers": "^5.4.0" }, "keywords": [ "ES6", diff --git a/packages/hiccup-markdown/src/api.ts b/packages/hiccup-markdown/src/api.ts index 5a016f90c9..32e28e9004 100644 --- a/packages/hiccup-markdown/src/api.ts +++ b/packages/hiccup-markdown/src/api.ts @@ -3,7 +3,7 @@ export interface TagFactories { code(body: string): any[]; codeblock(lang: string, body: string): any[]; em(body: string): any[]; - heading(level, children: any[]): any[]; + heading(level: number, children: any[]): any[]; hr(): any[]; img(src: string, alt: string): any[]; li(children: any[]): any[]; diff --git a/packages/hiccup-markdown/src/parse.ts b/packages/hiccup-markdown/src/parse.ts index 1c4d82bb67..87e8ada3ab 100644 --- a/packages/hiccup-markdown/src/parse.ts +++ b/packages/hiccup-markdown/src/parse.ts @@ -1,3 +1,4 @@ +import { Fn, Fn2 } from "@thi.ng/api"; import { peek } from "@thi.ng/arrays"; import { alts, @@ -100,11 +101,14 @@ const transition = (ctx: FSMCtx, id: State): ParseResult => ( ); const push = (id: State, next: State) => (ctx: FSMCtx): ParseResult => ( - ctx.stack.push({ id, children: ctx.children.concat(ctx.body) }), + ctx.stack.push({ id, children: ctx.children!.concat(ctx.body) }), transition(ctx, next) ); -const pop = (result) => (ctx, body): ParseResult => { +const pop = (result: Fn2) => ( + ctx: FSMCtx, + body: any +): ParseResult => { const { id, children } = ctx.stack.pop(); children.push(result(ctx, body)); ctx.children = children; @@ -113,62 +117,61 @@ const pop = (result) => (ctx, body): ParseResult => { }; const collectChildren = (ctx: FSMCtx) => ( - ctx.children.push(ctx.body), ctx.children + ctx.children!.push(ctx.body), ctx.children! ); const collect = (id: State) => (ctx: FSMCtx, buf: string[]): ParseResult => ( (ctx.body += buf.join("")), [id] ); -const collectHeading = (tag: (i: number, xs: any[]) => any[]) => ( - ctx -): ParseResult => [State.START, [tag(ctx.hd, collectChildren(ctx))]]; +const collectHeading = (tag: Fn2) => ( + ctx: FSMCtx +): ParseResult => [State.START, [tag(ctx.hd!, collectChildren(ctx))]]; -const collectAndRestart = (tag: (xs: any[]) => any[]) => (ctx): ParseResult => [ - State.START, - [tag(collectChildren(ctx))] -]; +const collectAndRestart = (tag: (xs: any[]) => any[]) => ( + ctx: FSMCtx +): ParseResult => [State.START, [tag(collectChildren(ctx))]]; -const collectBlockQuote = (ctx): ParseResult => ( - ctx.children.push(ctx.body, ["br"]), (ctx.body = ""), [State.BLOCKQUOTE] +const collectBlockQuote = (ctx: FSMCtx): ParseResult => ( + ctx.children!.push(ctx.body, ["br"]), (ctx.body = ""), [State.BLOCKQUOTE] ); -const collectCodeBlock = (tag: (lang: string, body: string) => any[]) => ( - ctx, - body -): ParseResult => [State.START, [tag(ctx.lang, body)]]; +const collectCodeBlock = (tag: Fn2) => ( + ctx: FSMCtx, + body: string +): ParseResult => [State.START, [tag(ctx.lang!, body)]]; -const collectLi = (ctx: FSMCtx, tag: (xs: any[]) => any[]) => - ctx.container.push(tag(collectChildren(ctx))); +const collectLi = (ctx: FSMCtx, tag: Fn) => + ctx.container!.push(tag(collectChildren(ctx))); const collectList = ( type: string, - list: (type: string, xs: any[]) => any[], - item: (xs: any[]) => any[] -) => (ctx): ParseResult => ( - collectLi(ctx, item), [State.START, [list(type, ctx.container)]] + list: Fn2, + item: Fn +) => (ctx: FSMCtx): ParseResult => ( + collectLi(ctx, item), [State.START, [list(type, ctx.container!)]] ); -const collectTD = (tag: (i: number, xs: any[]) => any[]) => (ctx: FSMCtx) => ( - ctx.children.push(ctx.body), - ctx.container.push(tag(peek(ctx.stack).container.length, ctx.children)), +const collectTD = (tag: Fn2) => (ctx: FSMCtx) => ( + ctx.children!.push(ctx.body), + ctx.container!.push(tag(peek(ctx.stack).container.length, ctx.children!)), transition(ctx, State.TABLE) ); -const collectTR = (tag: (i: number, xs: any[]) => any[]) => (ctx: FSMCtx) => { +const collectTR = (tag: Fn2) => (ctx: FSMCtx) => { const rows = peek(ctx.stack).container; - rows.push(tag(rows.length, ctx.container)); + rows.push(tag(rows.length, ctx.container!)); ctx.container = []; return transition(ctx, State.END_TABLE); }; -const collectTable = (tag: (xs: any[]) => any) => (ctx): ParseResult => { +const collectTable = (tag: Fn) => (ctx: FSMCtx): ParseResult => { const rows = ctx.stack.pop().container; rows.splice(1, 1); return [State.START, [tag(rows)]]; }; -const collectInline = (fn: (body: string) => any[]) => +const collectInline = (fn: Fn) => pop((ctx, body: string) => fn(ctx.body + body.trim())); const heading = (ctx: FSMCtx, body: string[]): ParseResult => ( @@ -184,14 +187,20 @@ const matchInline = (id: State) => [ str(CODE, push(id, State.CODE)) ]; -const matchLink = (result: (href, body) => any[]) => +const matchLink = (result: Fn2) => seq( [ - untilStr(LINK_LABEL_END, (ctx, body) => ((ctx.title = body), null)), + untilStr( + LINK_LABEL_END, + (ctx, body) => ((ctx.title = body), undefined) + ), str(LINK_HREF), - untilStr(LINK_HREF_END, (ctx, body) => ((ctx.href = body), null)) + untilStr( + LINK_HREF_END, + (ctx, body) => ((ctx.href = body), undefined) + ) ], - pop((ctx) => result(ctx.href, ctx.title)) + pop((ctx: FSMCtx) => result(ctx.href!, ctx.title!)) ); const matchPara = (id: State, next: State) => @@ -232,8 +241,8 @@ const newTable = (ctx: FSMCtx) => ( * syntax matchers and state transition handlers. The returned parser * itself is only used in `index.ts`. */ -export const parse = (tags?: Partial) => { - tags = { ...DEFAULT_TAGS, ...tags }; +export const parse = (_tags?: Partial) => { + const tags = { ...DEFAULT_TAGS, ..._tags }; return fsm( { [State.START]: alts( @@ -247,7 +256,7 @@ export const parse = (tags?: Partial) => { seq([str(CODE), not(str(CODE))], newParaCode), str(CODEBLOCK, () => [State.START_CODEBLOCK]) ], - null, + undefined, (_, next) => next ), seq([repeat(str(HR), 3, Infinity), str(NL)], () => [ diff --git a/packages/hiccup-markdown/src/serialize.ts b/packages/hiccup-markdown/src/serialize.ts index c657bf164d..3aa4a79d38 100644 --- a/packages/hiccup-markdown/src/serialize.ts +++ b/packages/hiccup-markdown/src/serialize.ts @@ -9,10 +9,10 @@ import { illegalArgs } from "@thi.ng/errors"; import { normalize } from "@thi.ng/hiccup"; import { repeat, wrap } from "@thi.ng/strings"; -export const serialize = (tree: any, ctx) => +export const serialize = (tree: any, ctx: any) => _serialize(tree, ctx, { indent: 0, sep: "" }); -const _serialize = (tree: any, ctx, state) => { +const _serialize = (tree: any, ctx: any, state: any): string => { if (tree == null) return ""; if (Array.isArray(tree)) { if (!tree.length) { @@ -71,10 +71,11 @@ const serializeIter = (iter: Iterable, ctx: any, state: any) => { return res.join(state.sep); }; -const header = (level) => (el, ctx, state) => +const header = (level: number) => (el: any[], ctx: any, state: any) => repeat("#", level) + " " + body(el, ctx, state) + "\n\n"; -const body = (el, ctx, state) => serializeIter(el[2], ctx, state); +const body = (el: any[], ctx: any, state: any) => + serializeIter(el[2], ctx, state); export const serializeElement: MultiFn3 = defmulti( (el) => el[0] @@ -113,9 +114,8 @@ serializeElement.add( })}\n\`\`\`\n` ); -serializeElement.add( - "code", - (el, ctx, state) => (state.pre ? el[2][0] : `\`${body(el, ctx, state)}\``) +serializeElement.add("code", (el, ctx, state) => + state.pre ? el[2][0] : `\`${body(el, ctx, state)}\`` ); serializeElement.add("ul", (el, ctx, state) => { diff --git a/packages/hiccup-markdown/test/index.ts b/packages/hiccup-markdown/test/index.ts index 76a8799389..8d83331b2e 100644 --- a/packages/hiccup-markdown/test/index.ts +++ b/packages/hiccup-markdown/test/index.ts @@ -1,6 +1,96 @@ -// import * as assert from "assert"; -// import * as hm from "../src/index"; +import * as assert from "assert"; +import { serialize } from "../src/serialize"; describe("hiccup-markdown", () => { - it("tests pending"); + it("serialize", () => { + // list component + // the 1st arg is the optional user context object + // passed to `serialize()` (ignored here) + // the 2nd arg is the list tag (ul/ol) + // rest args are converted to list items + const list = (_: any, type: string, ...xs: any[]) => [ + type, + ...xs.map((x) => (Array.isArray(x) ? x : ["li", x])) + ]; + + // code block component w/ lang hint + const codeblock = (_: any, lang: string, body: any[]) => [ + "pre", + { lang }, + ["code", body] + ]; + + // link component for thi.ng URLs + const thingLink = (_: any, id: string, label: any) => [ + "a", + { href: `http://thi.ng/${id}` }, + label + ]; + + // Note: the same hiccup tree can be serialized to HTML via @thi.ng/hiccup or + // used interactively in the browser w/ @thi.ng/hdom + assert.equal( + serialize( + [ + "div", + ["h1", "Hello Markdown"], + [ + "p", + "This is a test: ", + ["strong", "I am strong and ", ["em", "italic"]], + "..." + ], + // anon component fn to demo context lookup + [(ctx: any) => ["p", `My magic number is: ${ctx.magic}`]], + // codeblock w/ language hint + [ + codeblock, + "ts", + `import { serialize } from "@thi.ng/hiccup-markdown";` + ], + // nested lists + [ + list, + "ul", + "foo", + "bar", + [list, "ol", "b1", "b2", "b3"], + "baz" + ], + ["blockquote", "So long and thanks for all the fish."], + [ + "p", + "More info ", + [thingLink, "hiccup-markdown", "here"], + "." + ] + ], + // optional context object passed to all component functions + { magic: 42 } + ), + // prettier-ignore + `# Hello Markdown + + +This is a test: **I am strong and _italic_**... + +My magic number is: 42 + +\`\`\`ts +\import { serialize } from "@thi.ng/hiccup-markdown"; +\`\`\` + +- foo +- bar + 1. b1 + 2. b2 + 3. b3 +- baz + +> So long and thanks for all the fish. + +More info [here](http://thi.ng/hiccup-markdown). +` + ); + }); }); diff --git a/packages/hiccup-svg/CHANGELOG.md b/packages/hiccup-svg/CHANGELOG.md index e6fb484118..9a95d0b1cb 100644 --- a/packages/hiccup-svg/CHANGELOG.md +++ b/packages/hiccup-svg/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [3.2.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/hiccup-svg@3.1.22...@thi.ng/hiccup-svg@3.2.0) (2019-07-07) + + +### Features + +* **hiccup-svg:** enable TS strict compiler flags (refactor) ([3143141](https://github.com/thi-ng/umbrella/commit/3143141)) + + + + + ## [3.1.22](https://github.com/thi-ng/umbrella/compare/@thi.ng/hiccup-svg@3.1.21...@thi.ng/hiccup-svg@3.1.22) (2019-05-22) **Note:** Version bump only for package @thi.ng/hiccup-svg diff --git a/packages/hiccup-svg/package.json b/packages/hiccup-svg/package.json index 65fbdddcd9..df023459f1 100644 --- a/packages/hiccup-svg/package.json +++ b/packages/hiccup-svg/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/hiccup-svg", - "version": "3.1.22", + "version": "3.2.0", "description": "SVG element functions for @thi.ng/hiccup & @thi.ng/hdom", "module": "./index.js", "main": "./lib/index.js", @@ -25,16 +25,16 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/checks": "^2.1.6", - "@thi.ng/color": "^0.1.21", - "@thi.ng/hiccup": "^3.1.9" + "@thi.ng/checks": "^2.2.0", + "@thi.ng/color": "^0.2.0", + "@thi.ng/hiccup": "^3.2.0" }, "keywords": [ "components", diff --git a/packages/hiccup-svg/src/convert.ts b/packages/hiccup-svg/src/convert.ts index df6d19fb96..dc316dc20a 100644 --- a/packages/hiccup-svg/src/convert.ts +++ b/packages/hiccup-svg/src/convert.ts @@ -12,7 +12,7 @@ import { polyline } from "./polyline"; import { roundedRect } from "./rect"; import { text } from "./text"; -const ATTRIB_ALIASES = { +const ATTRIB_ALIASES: { [id: string]: string } = { alpha: "opacity", dash: "stroke-dasharray", dashOffset: "stroke-dashoffset", @@ -22,7 +22,7 @@ const ATTRIB_ALIASES = { weight: "stroke-width" }; -const TEXT_ALIGN = { +const TEXT_ALIGN: { [id: string]: string } = { left: "start", right: "end", center: "middle", diff --git a/packages/hiccup-svg/src/gradients.ts b/packages/hiccup-svg/src/gradients.ts index 5f930c3473..70542a6839 100644 --- a/packages/hiccup-svg/src/gradients.ts +++ b/packages/hiccup-svg/src/gradients.ts @@ -13,7 +13,7 @@ const gradientStop = ([offset, col]: GradientStop) => { col = fcolor(col); // use stop-opacity attrib for safari compatibility // https://stackoverflow.com/a/26220870/294515 - let opacity: string; + let opacity: string | undefined; const parts = RE_ALPHA_COLOR.exec(col); if (parts) { col = `${parts[1]}(${parts[2]},${parts[3]},${parts[4]})`; diff --git a/packages/hiccup-svg/src/path.ts b/packages/hiccup-svg/src/path.ts index 9f7e4f8628..46cf73fd72 100644 --- a/packages/hiccup-svg/src/path.ts +++ b/packages/hiccup-svg/src/path.ts @@ -1,5 +1,10 @@ import { PathSegment } from "./api"; -import { fattribs, ff, fpoint, fpoints } from "./format"; +import { + fattribs, + ff, + fpoint, + fpoints +} from "./format"; const DEG = 180 / Math.PI; @@ -22,8 +27,8 @@ export const path = (segments: PathSegment[], attribs?: any): any[] => { // clockwise seg[5] ? 1 : 0, // target xy - ff(seg[6][0]), - ff(seg[6][1]) + ff(seg[6]![0]), + ff(seg[6]![1]) ].join(",") ); break; diff --git a/packages/hiccup/CHANGELOG.md b/packages/hiccup/CHANGELOG.md index 38dffcf1f5..471c0151bb 100644 --- a/packages/hiccup/CHANGELOG.md +++ b/packages/hiccup/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [3.2.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/hiccup@3.1.9...@thi.ng/hiccup@3.2.0) (2019-07-07) + + +### Features + +* **hiccup:** enable TS strict compiler flags (refactor) ([d0fce75](https://github.com/thi-ng/umbrella/commit/d0fce75)) + + + + + ## [3.1.9](https://github.com/thi-ng/umbrella/compare/@thi.ng/hiccup@3.1.8...@thi.ng/hiccup@3.1.9) (2019-05-22) **Note:** Version bump only for package @thi.ng/hiccup diff --git a/packages/hiccup/package.json b/packages/hiccup/package.json index e7bfc84b75..2ff8ea84e3 100644 --- a/packages/hiccup/package.json +++ b/packages/hiccup/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/hiccup", - "version": "3.1.9", + "version": "3.2.0", "description": "HTML/SVG/XML serialization of nested data structures, iterables & closures", "module": "./index.js", "main": "./lib/index.js", @@ -24,17 +24,17 @@ "pub": "yarn build && yarn publish --access public" }, "devDependencies": { - "@thi.ng/atom": "^2.0.12", + "@thi.ng/atom": "^3.0.0", "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/checks": "^2.1.6", - "@thi.ng/errors": "^1.0.6" + "@thi.ng/checks": "^2.2.0", + "@thi.ng/errors": "^1.1.0" }, "keywords": [ "clojure", diff --git a/packages/hiccup/src/api.ts b/packages/hiccup/src/api.ts index 6f1056b68c..0a5d533d30 100644 --- a/packages/hiccup/src/api.ts +++ b/packages/hiccup/src/api.ts @@ -4,7 +4,7 @@ export const XHTML_NS = "http://www.w3.org/1999/xhtml"; export const TAG_REGEXP = /^([^\s\.#]+)(?:#([^\s\.#]+))?(?:\.([^\s#]+))?$/; -export const PROC_TAGS = { +export const PROC_TAGS: { [id: string]: string } = { "?xml": "?>\n", "!DOCTYPE": ">\n", "!ENTITY": ">\n", @@ -13,16 +13,20 @@ export const PROC_TAGS = { }; // tslint:disable-next-line -export const SVG_TAGS = "animate animateColor animateMotion animateTransform circle clipPath color-profile defs desc discard ellipse feBlend feColorMatrix feComponentTransfer feComposite feConvolveMatrix feDiffuseLighting feDisplacementMap feDistantLight feDropShadow feFlood feFuncA feFuncB feFuncG feFuncR feGaussianBlur feImage feMerge feMergeNode feMorphology feOffset fePointLight feSpecularLighting feSpotLight feTile feTurbulence filter font foreignObject g image line linearGradient marker mask metadata mpath path pattern polygon polyline radialGradient rect set stop style svg switch symbol text textPath title tref tspan use view" +export const SVG_TAGS: { + [id: string]: number; +} = "animate animateColor animateMotion animateTransform circle clipPath color-profile defs desc discard ellipse feBlend feColorMatrix feComponentTransfer feComposite feConvolveMatrix feDiffuseLighting feDisplacementMap feDistantLight feDropShadow feFlood feFuncA feFuncB feFuncG feFuncR feGaussianBlur feImage feMerge feMergeNode feMorphology feOffset fePointLight feSpecularLighting feSpotLight feTile feTurbulence filter font foreignObject g image line linearGradient marker mask metadata mpath path pattern polygon polyline radialGradient rect set stop style svg switch symbol text textPath title tref tspan use view" .split(" ") - .reduce((acc, x) => ((acc[x] = 1), acc), {}); + .reduce((acc: any, x) => ((acc[x] = 1), acc), {}); // tslint:disable-next-line -export const VOID_TAGS = "area base br circle col command ellipse embed hr img input keygen line link meta param path polygon polyline rect source stop track use wbr ?xml" +export const VOID_TAGS: { + [id: string]: number; +} = "area base br circle col command ellipse embed hr img input keygen line link meta param path polygon polyline rect source stop track use wbr ?xml" .split(" ") - .reduce((acc, x) => ((acc[x] = 1), acc), {}); + .reduce((acc: any, x) => ((acc[x] = 1), acc), {}); -export const ENTITIES = { +export const ENTITIES: { [id: string]: string } = { "&": "&", "<": "<", ">": ">", @@ -32,7 +36,9 @@ export const ENTITIES = { export const COMMENT = "__COMMENT__"; -export const NO_SPANS = { +export const NO_SPANS: { + [id: string]: number; +} = { button: 1, option: 1, text: 1, diff --git a/packages/hiccup/src/deref.ts b/packages/hiccup/src/deref.ts index fca273e805..e7dea4dd25 100644 --- a/packages/hiccup/src/deref.ts +++ b/packages/hiccup/src/deref.ts @@ -9,7 +9,7 @@ import { implementsFunction } from "@thi.ng/checks"; * @param ctx * @param keys */ -export const derefContext = (ctx: any, keys: PropertyKey[]) => { +export const derefContext = (ctx: any, keys: PropertyKey[] | undefined) => { if (ctx == null || !keys || !keys.length) return ctx; const res = { ...ctx }; for (let k of keys) { diff --git a/packages/hiccup/src/serialize.ts b/packages/hiccup/src/serialize.ts index de24dd82ee..bd5af353df 100644 --- a/packages/hiccup/src/serialize.ts +++ b/packages/hiccup/src/serialize.ts @@ -6,7 +6,13 @@ import { isString } from "@thi.ng/checks"; import { illegalArgs } from "@thi.ng/errors"; -import { COMMENT, NO_SPANS, PROC_TAGS, TAG_REGEXP, VOID_TAGS } from "./api"; +import { + COMMENT, + NO_SPANS, + PROC_TAGS, + TAG_REGEXP, + VOID_TAGS +} from "./api"; import { css } from "./css"; import { escape } from "./escape"; @@ -153,7 +159,7 @@ const _serialize = ( span: boolean, keys: boolean, path: any[] -) => { +): string => { if (tree == null) { return ""; } @@ -284,15 +290,17 @@ const _serializeIter = ( export const normalize = (tag: any[]) => { let el = tag[0]; - let match, id, clazz; + let match: RegExpExecArray | null; + let id: string; + let clazz: string; const hasAttribs = isPlainObject(tag[1]); const attribs: any = hasAttribs ? { ...tag[1] } : {}; if (!isString(el) || !(match = TAG_REGEXP.exec(el))) { illegalArgs(`"${el}" is not a valid tag name`); } - el = match[1]; - id = match[2]; - clazz = match[3]; + el = match![1]; + id = match![2]; + clazz = match![3]; if (id) { attribs.id = id; } diff --git a/packages/hiccup/test/index.ts b/packages/hiccup/test/index.ts index 22b4f8de4e..0593057ee7 100644 --- a/packages/hiccup/test/index.ts +++ b/packages/hiccup/test/index.ts @@ -1,41 +1,23 @@ -import * as assert from "assert"; import { Atom } from "@thi.ng/atom"; - +import * as assert from "assert"; import { serialize } from "../src/index"; -function _check(a, b) { +function _check(a: any, b: any) { assert.equal(serialize(a), b); } -function check(id, a, b) { +function check(id: string, a: any, b: any) { it(id, () => _check(a, b)); } describe("serialize", () => { + check("null", null, ""); - check( - "null", - null, - "" - ); + check("empty tree", [], ""); - check( - "empty tree", - [], - "" - ); + check("simple div", ["div", "foo"], `
foo
`); - check( - "simple div", - ["div", "foo"], - `
foo
` - ); - - check( - "div w/ id", - ["div#foo", "foo"], - `
foo
` - ); + check("div w/ id", ["div#foo", "foo"], `
foo
`); check( "div w/ id + classes", @@ -55,23 +37,11 @@ describe("serialize", () => { `
foo
` ); - check( - "voidtag (br)", - ["br"], - `
` - ); + check("voidtag (br)", ["br"], `
`); - check( - "voidtag (link)", - ["link", { href: "#" }], - `` - ); + check("voidtag (link)", ["link", { href: "#" }], ``); - check( - "empty div", - ["div"], - `
` - ); + check("empty div", ["div"], `
`); it("
w/ body", () => { assert.throws(() => serialize(["br", "x"]), "no body"); @@ -83,23 +53,11 @@ describe("serialize", () => { `
` ); - check( - "div w/ bool attr (false)", - ["div", { bool: false }], - `
` - ); + check("div w/ bool attr (false)", ["div", { bool: false }], `
`); - check( - "empty attr", - ["div", { foo: "" }], - `
` - ); + check("empty attr", ["div", { foo: "" }], `
`); - check( - "zero attr", - ["div", { foo: 0 }], - `
` - ); + check("zero attr", ["div", { foo: 0 }], `
`); check( "attr toString", @@ -107,29 +65,17 @@ describe("serialize", () => { `
` ); - check( - "attr fn", - ["div", { foo: () => 23 }], - `
` - ); + check("attr fn", ["div", { foo: () => 23 }], `
`); check( "attr fn (derived)", - ["div", { foo: (attribs) => `${attribs.x}px`, x: 42 }], + ["div", { foo: (attribs: any) => `${attribs.x}px`, x: 42 }], `
` ); - check( - "attr fn (null)", - ["div", { foo: () => null }], - `
` - ); + check("attr fn (null)", ["div", { foo: () => {} }], `
`); - check( - "event attr fn", - ["div", { onclick: () => 1 }], - `
` - ); + check("event attr fn", ["div", { onclick: () => 1 }], `
`); check( "event attr (string)", @@ -161,15 +107,15 @@ describe("serialize", () => { `
foo
` ); - check( - "style empty", - ["div", { style: {} }, "foo"], - `
foo
` - ); + check("style empty", ["div", { style: {} }, "foo"], `
foo
`); check( "nested", - ["div", ["h1.title", "foo"], ["p", ["span.small", "hello"], ["br"], "bye"]], + [ + "div", + ["h1.title", "foo"], + ["p", ["span.small", "hello"], ["br"], "bye"] + ], `

foo

hello
bye

` ); @@ -181,7 +127,7 @@ describe("serialize", () => { check( "comp fn args", - [(_, id, body) => ["div#" + id, body], "foo", "bar"], + [(_: any, id: string, body: any) => ["div#" + id, body], "foo", "bar"], `
bar
` ); @@ -193,13 +139,25 @@ describe("serialize", () => { check( "comp fn in body w/ args", - ["div", [(_, id, body) => ["div#" + id, body], "foo", "bar"], "bar2"], + [ + "div", + [ + (_: any, id: string, body: any) => ["div#" + id, body], + "foo", + "bar" + ], + "bar2" + ], `
bar
bar2
` ); check( "comp fn in body apply", - ["div", [(_, [id, body]) => ["div#" + id, body], ["foo", "bar"]], "bar2"], + [ + "div", + [(_: any, [id, body]: any) => ["div#" + id, body], ["foo", "bar"]], + "bar2" + ], `
bar
bar2
` ); @@ -210,57 +168,61 @@ describe("serialize", () => { ); it("components nested", () => { - const dlItem = ([def, desc]) => [["dt", def], ["dd", desc]]; - const ulItem = (i) => ["li", i]; - const list = (_, f, items) => items.map(f); - const dlList = (_, attribs, items) => ["dl", attribs, [list, dlItem, items]]; - const ulList = (_, attribs, items) => ["ul", attribs, [list, ulItem, items]]; + const dlItem = ([def, desc]: any) => [["dt", def], ["dd", desc]]; + const ulItem = (i: any) => ["li", i]; + const list = (_: any, f: any, items: any[]) => items.map(f); + const dlList = (_: any, attribs: any, items: any[]) => [ + "dl", + attribs, + [list, dlItem, items] + ]; + const ulList = (_: any, attribs: any, items: any[]) => [ + "ul", + attribs, + [list, ulItem, items] + ]; const items = [["a", "foo"], ["b", "bar"]]; const widget1 = [dlList, { id: "foo" }, items]; const widget2 = [ulList, { id: "foo" }, items.map((i) => i[1])]; - _check(widget1, `
a
foo
b
bar
`); + _check( + widget1, + `
a
foo
b
bar
` + ); _check(widget2, `
  • foo
  • bar
`); }); it("comp object", () => { - const foo = (ctx, body) => ["div", ctx.foo, body]; - const bar = { render: (_, id) => [foo, id] }; + const foo = (ctx: any, body: any) => ["div", ctx.foo, body]; + const bar = { render: (_: any, id: any) => [foo, id] }; assert.equal( - serialize(["section", [bar, "a"], [bar, "b"]], { foo: { class: "foo" } }), + serialize(["section", [bar, "a"], [bar, "b"]], { + foo: { class: "foo" } + }), `
a
b
` ); }); check( "iterators", - ["ul", [(_, items) => items.map((i) => ["li", i]), ["a", "b"]]], + [ + "ul", + [(_: any, items: any[]) => items.map((i) => ["li", i]), ["a", "b"]] + ], `
  • a
  • b
` ); - check( - "deref toplevel", - new Atom(["a"]), - `
` - ); + check("deref toplevel", new Atom(["a"]), ``); - check( - "deref child", - ["a", new Atom(["b"])], - `` - ); + check("deref child", ["a", new Atom(["b"])], ``); - check( - "deref fn result", - ["a", () => new Atom(["b"])], - `` - ); + check("deref fn result", ["a", () => new Atom(["b"])], ``); check( "style fn attribs", - ["div", { style: { a: (x) => x.b, b: 2 } }], + ["div", { style: { a: (x: any) => x.b, b: 2 } }], `
` ); @@ -270,11 +232,7 @@ describe("serialize", () => { `bbb` ); - check( - "doctype", - ["!DOCTYPE", "html"], - "\n" - ); + check("doctype", ["!DOCTYPE", "html"], "\n"); check( "?xml", diff --git a/packages/iges/CHANGELOG.md b/packages/iges/CHANGELOG.md index 8a88fdeeac..a923c8242f 100644 --- a/packages/iges/CHANGELOG.md +++ b/packages/iges/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.5](https://github.com/thi-ng/umbrella/compare/@thi.ng/iges@1.1.4...@thi.ng/iges@1.1.5) (2019-07-07) + +**Note:** Version bump only for package @thi.ng/iges + + + + + ## [1.1.4](https://github.com/thi-ng/umbrella/compare/@thi.ng/iges@1.1.3...@thi.ng/iges@1.1.4) (2019-05-22) **Note:** Version bump only for package @thi.ng/iges diff --git a/packages/iges/package.json b/packages/iges/package.json index 8c032ba713..64d0fed7cb 100644 --- a/packages/iges/package.json +++ b/packages/iges/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/iges", - "version": "1.1.4", + "version": "1.1.5", "description": "IGES 5.3 serializer for (currently only) polygonal geometry, both open & closed", "module": "./index.js", "main": "./lib/index.js", @@ -25,18 +25,18 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/api": "^6.2.0", - "@thi.ng/checks": "^2.1.6", - "@thi.ng/defmulti": "^1.0.9", - "@thi.ng/strings": "^1.1.3", - "@thi.ng/transducers": "^5.3.7" + "@thi.ng/api": "^6.3.0", + "@thi.ng/checks": "^2.2.0", + "@thi.ng/defmulti": "^1.1.0", + "@thi.ng/strings": "^1.2.0", + "@thi.ng/transducers": "^5.4.0" }, "keywords": [ "CAD", diff --git a/packages/iges/src/index.ts b/packages/iges/src/index.ts index 6cd24d9262..0c30a13eff 100644 --- a/packages/iges/src/index.ts +++ b/packages/iges/src/index.ts @@ -157,7 +157,7 @@ const formatTerminate = (doc: IGESDocument) => 0 ); -const formatStatus = (s: EntityStatus) => +const formatStatus = (s: Partial) => [s.blank || 0, s.subord || 0, s.usage || 0, s.hierarchy || 0] .map($Z2) .join(""); @@ -224,7 +224,7 @@ const formatParams = ( const addEntity = ( doc: IGESDocument, type: EntityType, - entry: Partial, + entry: Partial | null, params: Param[], opts: Partial = {} ) => { diff --git a/packages/interceptors/CHANGELOG.md b/packages/interceptors/CHANGELOG.md index affc8ed65d..648de9a136 100644 --- a/packages/interceptors/CHANGELOG.md +++ b/packages/interceptors/CHANGELOG.md @@ -3,6 +3,22 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [2.1.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/interceptors@2.0.12...@thi.ng/interceptors@2.1.0) (2019-07-07) + + +### Bug Fixes + +* **interceptors:** update EventBus ctor args ([557a78f](https://github.com/thi-ng/umbrella/commit/557a78f)) + + +### Features + +* **interceptors:** enable TS strict compiler flags (refactor) ([13bea8f](https://github.com/thi-ng/umbrella/commit/13bea8f)) + + + + + ## [2.0.12](https://github.com/thi-ng/umbrella/compare/@thi.ng/interceptors@2.0.11...@thi.ng/interceptors@2.0.12) (2019-05-22) **Note:** Version bump only for package @thi.ng/interceptors diff --git a/packages/interceptors/package.json b/packages/interceptors/package.json index 7750f06f7a..9013070b6c 100644 --- a/packages/interceptors/package.json +++ b/packages/interceptors/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/interceptors", - "version": "2.0.12", + "version": "2.1.0", "description": "Interceptor based event bus, side effect & immutable state handling", "module": "./index.js", "main": "./lib/index.js", @@ -25,18 +25,18 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/api": "^6.2.0", - "@thi.ng/atom": "^2.0.12", - "@thi.ng/checks": "^2.1.6", - "@thi.ng/errors": "^1.0.6", - "@thi.ng/paths": "^2.0.9" + "@thi.ng/api": "^6.3.0", + "@thi.ng/atom": "^3.0.0", + "@thi.ng/checks": "^2.2.0", + "@thi.ng/errors": "^1.1.0", + "@thi.ng/paths": "^2.1.0" }, "keywords": [ "ES6", diff --git a/packages/interceptors/src/api.ts b/packages/interceptors/src/api.ts index 4b1b34631b..f133e69bdd 100644 --- a/packages/interceptors/src/api.ts +++ b/packages/interceptors/src/api.ts @@ -3,20 +3,20 @@ import { ReadonlyAtom } from "@thi.ng/atom"; export type InterceptorFn = ( state: any, e: Event, - bus?: IDispatch, - ctx?: InterceptorContext + bus: IDispatch, + ctx: InterceptorContext ) => InterceptorContext | void; export type InterceptorPredicate = ( state: any, e: Event, - bus?: IDispatch, - ctx?: InterceptorContext + bus: IDispatch, + ctx: InterceptorContext ) => boolean; export type SideEffect = ( x: any, - bus?: IDispatch, - ctx?: InterceptorContext + bus: IDispatch, + ctx: InterceptorContext ) => any; export type EventDef = | Interceptor @@ -63,9 +63,9 @@ export interface Event extends Array { export interface IDispatch { readonly state: ReadonlyAtom; - dispatch(...event: Event[]); - dispatchNow(...event: Event[]); - dispatchLater(event: Event, delay?: number); + dispatch(...event: Event[]): void; + dispatchNow(...event: Event[]): void; + dispatchLater(event: Event, delay?: number): void; } export interface Interceptor { diff --git a/packages/interceptors/src/event-bus.ts b/packages/interceptors/src/event-bus.ts index 11b5717c83..1dcc6bf35d 100644 --- a/packages/interceptors/src/event-bus.ts +++ b/packages/interceptors/src/event-bus.ts @@ -8,11 +8,29 @@ import { } from "@thi.ng/checks"; import { illegalArgs } from "@thi.ng/errors"; import { setIn, updateIn } from "@thi.ng/paths"; -import * as api from "./api"; - -const FX_CANCEL = api.FX_CANCEL; -const FX_DISPATCH_NOW = api.FX_DISPATCH_NOW; -const FX_STATE = api.FX_STATE; +import { + EffectDef, + EffectPriority, + EV_REDO, + EV_SET_VALUE, + EV_TOGGLE_VALUE, + EV_UNDO, + EV_UPDATE_VALUE, + Event, + EventDef, + FX_CANCEL, + FX_DELAY, + FX_DISPATCH, + FX_DISPATCH_ASYNC, + FX_DISPATCH_NOW, + FX_FETCH, + FX_STATE, + IDispatch, + Interceptor, + InterceptorContext, + InterceptorFn, + SideEffect +} from "./api"; /** * Batched event processor for using composable interceptors for event @@ -66,16 +84,16 @@ const FX_STATE = api.FX_STATE; * - side effect priorities (to control execution order) * - dynamic addition/removal of handlers & effects */ -export class StatelessEventBus implements api.IDispatch { +export class StatelessEventBus implements IDispatch { state: any; - protected eventQueue: api.Event[]; - protected currQueue: api.Event[]; - protected currCtx: api.InterceptorContext; + protected eventQueue: Event[]; + protected currQueue: Event[] | undefined; + protected currCtx: InterceptorContext | undefined; - protected handlers: IObjectOf; - protected effects: IObjectOf; - protected priorities: api.EffectPriority[]; + protected handlers: IObjectOf; + protected effects: IObjectOf; + protected priorities: EffectPriority[]; /** * Creates a new event bus instance with given handler and effect @@ -89,8 +107,8 @@ export class StatelessEventBus implements api.IDispatch { * @param effects */ constructor( - handlers?: IObjectOf, - effects?: IObjectOf + handlers?: IObjectOf, + effects?: IObjectOf ) { this.handlers = {}; this.effects = {}; @@ -165,13 +183,13 @@ export class StatelessEventBus implements api.IDispatch { */ addBuiltIns(): any { this.addEffects({ - [api.FX_DISPATCH]: [(e) => this.dispatch(e), -999], + [FX_DISPATCH]: [(e) => this.dispatch(e), -999], - [api.FX_DISPATCH_ASYNC]: [ - ([id, arg, success, err]) => { + [FX_DISPATCH_ASYNC]: [ + ([id, arg, success, err], bus, ctx) => { const fx = this.effects[id]; if (fx) { - const p = fx(arg, this); + const p = fx(arg, bus, ctx); if (isPromise(p)) { p.then((res) => this.dispatch([success, res]) @@ -186,13 +204,13 @@ export class StatelessEventBus implements api.IDispatch { -999 ], - [api.FX_DELAY]: [ + [FX_DELAY]: [ ([x, body]) => new Promise((res) => setTimeout(() => res(body), x)), 1000 ], - [api.FX_FETCH]: [ + [FX_FETCH]: [ (req) => fetch(req).then((resp) => { if (!resp.ok) { @@ -205,12 +223,12 @@ export class StatelessEventBus implements api.IDispatch { }); } - addHandler(id: string, spec: api.EventDef) { + addHandler(id: string, spec: EventDef) { const iceps = isArray(spec) ? (spec).map(asInterceptor) : isFunction(spec) - ? [{ pre: spec }] - : [spec]; + ? [{ pre: spec }] + : [spec]; if (iceps.length > 0) { if (this.handlers[id]) { this.removeHandler(id); @@ -222,19 +240,19 @@ export class StatelessEventBus implements api.IDispatch { } } - addHandlers(specs: IObjectOf) { + addHandlers(specs: IObjectOf) { for (let id in specs) { this.addHandler(id, specs[id]); } } - addEffect(id: string, fx: api.SideEffect, priority = 1) { + addEffect(id: string, fx: SideEffect, priority = 1) { if (this.effects[id]) { this.removeEffect(id); console.warn(`overriding effect for ID: ${id}`); } this.effects[id] = fx; - const p: api.EffectPriority = [id, priority]; + const p: EffectPriority = [id, priority]; const priors = this.priorities; for (let i = 0; i < priors.length; i++) { if (p[1] < priors[i][1]) { @@ -245,7 +263,7 @@ export class StatelessEventBus implements api.IDispatch { priors.push(p); } - addEffects(specs: IObjectOf) { + addEffects(specs: IObjectOf) { for (let id in specs) { const fx = specs[id]; if (isArray(fx)) { @@ -264,10 +282,7 @@ export class StatelessEventBus implements api.IDispatch { * @param inject * @param ids */ - instrumentWith( - inject: (api.Interceptor | api.InterceptorFn)[], - ids?: string[] - ) { + instrumentWith(inject: (Interceptor | InterceptorFn)[], ids?: string[]) { const iceps = inject.map(asInterceptor); const handlers = this.handlers; for (let id of ids || Object.keys(handlers)) { @@ -321,7 +336,7 @@ export class StatelessEventBus implements api.IDispatch { * * @param e */ - dispatch(...e: api.Event[]) { + dispatch(...e: Event[]) { this.eventQueue.push(...e); } @@ -334,7 +349,7 @@ export class StatelessEventBus implements api.IDispatch { * * @param e */ - dispatchNow(...e: api.Event[]) { + dispatchNow(...e: Event[]) { (this.currQueue || this.eventQueue).push(...e); } @@ -348,7 +363,7 @@ export class StatelessEventBus implements api.IDispatch { * @param e * @param delay */ - dispatchLater(e: api.Event, delay = 17) { + dispatchLater(e: Event, delay = 17) { setTimeout(() => this.dispatch(e), delay); } @@ -367,7 +382,7 @@ export class StatelessEventBus implements api.IDispatch { * * @param ctx */ - processQueue(ctx?: api.InterceptorContext) { + processQueue(ctx?: InterceptorContext) { if (this.eventQueue.length > 0) { this.currQueue = [...this.eventQueue]; this.eventQueue.length = 0; @@ -407,7 +422,7 @@ export class StatelessEventBus implements api.IDispatch { * @param ctx * @param e */ - protected processEvent(ctx: api.InterceptorContext, e: api.Event) { + protected processEvent(ctx: InterceptorContext, e: Event) { const iceps = this.handlers[e[0]]; if (!iceps) { console.warn(`missing handler for event type: ${e[0].toString()}`); @@ -439,7 +454,7 @@ export class StatelessEventBus implements api.IDispatch { * * @param ctx */ - protected processEffects(ctx: api.InterceptorContext) { + protected processEffects(ctx: InterceptorContext) { const effects = this.effects; for (let p of this.priorities) { const id = p[0]; @@ -497,7 +512,7 @@ export class StatelessEventBus implements api.IDispatch { * @param fx * @param ret */ - protected mergeEffects(ctx: api.InterceptorContext, ret: any) { + protected mergeEffects(ctx: InterceptorContext, ret: any) { if (!ret) { return; } @@ -537,7 +552,7 @@ export class StatelessEventBus implements api.IDispatch { * as the default implementation for most use cases. */ export class EventBus extends StatelessEventBus - implements IDeref, api.IDispatch { + implements IDeref, IDispatch { readonly state: IAtom; /** @@ -554,9 +569,9 @@ export class EventBus extends StatelessEventBus * @param effects */ constructor( - state?: IAtom, - handlers?: IObjectOf, - effects?: IObjectOf + state?: IAtom | null, + handlers?: IObjectOf, + effects?: IObjectOf ) { super(handlers, effects); this.state = state || new Atom({}); @@ -645,17 +660,17 @@ export class EventBus extends StatelessEventBus super.addBuiltIns(); // handlers this.addHandlers({ - [api.EV_SET_VALUE]: (state, [_, [path, val]]) => ({ + [EV_SET_VALUE]: (state, [_, [path, val]]) => ({ [FX_STATE]: setIn(state, path, val) }), - [api.EV_UPDATE_VALUE]: (state, [_, [path, fn, ...args]]) => ({ + [EV_UPDATE_VALUE]: (state, [_, [path, fn, ...args]]) => ({ [FX_STATE]: updateIn(state, path, fn, ...args) }), - [api.EV_TOGGLE_VALUE]: (state, [_, path]) => ({ + [EV_TOGGLE_VALUE]: (state, [_, path]) => ({ [FX_STATE]: updateIn(state, path, (x) => !x) }), - [api.EV_UNDO]: undoHandler("undo"), - [api.EV_REDO]: undoHandler("redo") + [EV_UNDO]: undoHandler("undo"), + [EV_REDO]: undoHandler("redo") }); // effects @@ -685,7 +700,7 @@ export class EventBus extends StatelessEventBus * bus.processQueue({ history }); * ``` */ - processQueue(ctx?: api.InterceptorContext) { + processQueue(ctx?: InterceptorContext) { if (this.eventQueue.length > 0) { const prev = this.state.deref(); this.currQueue = [...this.eventQueue]; @@ -702,10 +717,15 @@ export class EventBus extends StatelessEventBus } } -const asInterceptor = (i: api.Interceptor | api.InterceptorFn) => +const asInterceptor = (i: Interceptor | InterceptorFn) => isFunction(i) ? { pre: i } : i; -const undoHandler = (action: string) => (_, [__, ev], bus, ctx) => { +const undoHandler = (action: string): InterceptorFn => ( + _, + [__, ev], + bus, + ctx +) => { let id = ev ? ev[0] : "history"; if (implementsFunction(ctx[id], action)) { const ok = ctx[id][action](); diff --git a/packages/interceptors/src/interceptors.ts b/packages/interceptors/src/interceptors.ts index 4f01ee1515..098c31a47c 100644 --- a/packages/interceptors/src/interceptors.ts +++ b/packages/interceptors/src/interceptors.ts @@ -127,11 +127,11 @@ export const snapshot = (id = "history"): InterceptorFn => (_, __, ___, ctx) => export const ensurePred = ( pred: InterceptorPredicate, err?: InterceptorFn -): InterceptorFn => (state, e, bus) => - !pred(state, e, bus) +): InterceptorFn => (state, e, bus, ctx) => + !pred(state, e, bus, ctx) ? { [FX_CANCEL]: true, - ...(err ? err(state, e, bus) : null) + ...(err ? err(state, e, bus, ctx) : null) } : undefined; diff --git a/packages/intervals/CHANGELOG.md b/packages/intervals/CHANGELOG.md index 5a9a2338da..12357539d5 100644 --- a/packages/intervals/CHANGELOG.md +++ b/packages/intervals/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.0.10](https://github.com/thi-ng/umbrella/compare/@thi.ng/intervals@1.0.9...@thi.ng/intervals@1.0.10) (2019-07-07) + +**Note:** Version bump only for package @thi.ng/intervals + + + + + ## [1.0.9](https://github.com/thi-ng/umbrella/compare/@thi.ng/intervals@1.0.8...@thi.ng/intervals@1.0.9) (2019-05-22) **Note:** Version bump only for package @thi.ng/intervals diff --git a/packages/intervals/package.json b/packages/intervals/package.json index f35decd56e..9538cf0a08 100644 --- a/packages/intervals/package.json +++ b/packages/intervals/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/intervals", - "version": "1.0.9", + "version": "1.0.10", "description": "Closed/open/semi-open interval data type, queries & operations", "module": "./index.js", "main": "./lib/index.js", @@ -25,15 +25,15 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/api": "^6.2.0", - "@thi.ng/errors": "^1.0.6" + "@thi.ng/api": "^6.3.0", + "@thi.ng/errors": "^1.1.0" }, "keywords": [ "ES6", diff --git a/packages/iterators/CHANGELOG.md b/packages/iterators/CHANGELOG.md index ebc83f5669..022ac0ea82 100644 --- a/packages/iterators/CHANGELOG.md +++ b/packages/iterators/CHANGELOG.md @@ -3,6 +3,23 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [5.1.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/iterators@5.0.19...@thi.ng/iterators@5.1.0) (2019-07-07) + + +### Bug Fixes + +* **iterators:** update concat/mapcat, fnil args ([c51ff98](https://github.com/thi-ng/umbrella/commit/c51ff98)) + + +### Features + +* **iterators:** enable TS strict compiler flags (refactor) ([24fd9e7](https://github.com/thi-ng/umbrella/commit/24fd9e7)) +* **iterators:** TS strictNullChecks ([9f9be1d](https://github.com/thi-ng/umbrella/commit/9f9be1d)) + + + + + ## [5.0.19](https://github.com/thi-ng/umbrella/compare/@thi.ng/iterators@5.0.18...@thi.ng/iterators@5.0.19) (2019-05-22) **Note:** Version bump only for package @thi.ng/iterators diff --git a/packages/iterators/package.json b/packages/iterators/package.json index 94833229b9..9eabe9d807 100644 --- a/packages/iterators/package.json +++ b/packages/iterators/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/iterators", - "version": "5.0.19", + "version": "5.1.0", "description": "clojure.core inspired, composable ES6 iterators & generators", "module": "./index.js", "main": "./lib/index.js", @@ -25,16 +25,16 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/api": "^6.2.0", - "@thi.ng/dcons": "^2.0.19", - "@thi.ng/errors": "^1.0.6" + "@thi.ng/api": "^6.3.0", + "@thi.ng/dcons": "^2.1.0", + "@thi.ng/errors": "^1.1.0" }, "keywords": [ "clojure", diff --git a/packages/iterators/src/butlast.ts b/packages/iterators/src/butlast.ts index dbacf8df05..75d8cfc9ae 100644 --- a/packages/iterators/src/butlast.ts +++ b/packages/iterators/src/butlast.ts @@ -7,7 +7,7 @@ export function* butLast(input: Iterable) { let first = true; while (((v = iter.next()), !v.done)) { if (!first) { - yield prev; + yield prev!; } prev = v.value; first = false; diff --git a/packages/iterators/src/cached.ts b/packages/iterators/src/cached.ts index 3bcb99f3b6..28e72d748c 100644 --- a/packages/iterators/src/cached.ts +++ b/packages/iterators/src/cached.ts @@ -22,7 +22,7 @@ export const cached = (input: Iterable) => { } done = true; } - return { done, value: undefined }; + return >{ done }; } }; }; diff --git a/packages/iterators/src/concat.ts b/packages/iterators/src/concat.ts index adb3f4558d..51f26fdc84 100644 --- a/packages/iterators/src/concat.ts +++ b/packages/iterators/src/concat.ts @@ -1,9 +1,9 @@ import { ensureIterable } from "./ensure"; import { iterator } from "./iterator"; -export function* concat(...inputs: Iterable[]) { +export function* concat(...inputs: (Iterable | undefined | null)[]) { let iter = iterator(inputs); - let v: IteratorResult>; + let v: IteratorResult | undefined | null>; while (((v = iter.next()), !v.done)) { if (v.value != null) { yield* ensureIterable(v.value); diff --git a/packages/iterators/src/dedupe-with.ts b/packages/iterators/src/dedupe-with.ts index 45a6431d57..ede72032d5 100644 --- a/packages/iterators/src/dedupe-with.ts +++ b/packages/iterators/src/dedupe-with.ts @@ -4,7 +4,7 @@ import { iterator } from "./iterator"; export function* dedupeWith(equiv: Predicate2, input: Iterable) { let iter = iterator(input); let v: IteratorResult; - let prev: T; + let prev: T | undefined; while (((v = iter.next()), !v.done)) { if (prev === undefined || !equiv(prev, v.value)) { prev = v.value; diff --git a/packages/iterators/src/dedupe.ts b/packages/iterators/src/dedupe.ts index beb8c02c72..e3cedd2ea3 100644 --- a/packages/iterators/src/dedupe.ts +++ b/packages/iterators/src/dedupe.ts @@ -3,7 +3,7 @@ import { iterator } from "./iterator"; export function* dedupe(input: Iterable) { let iter = iterator(input); let v: IteratorResult; - let prev: T; + let prev: T | undefined; while (((v = iter.next()), !v.done)) { if (v.value !== prev) { prev = v.value; diff --git a/packages/iterators/src/fnil.ts b/packages/iterators/src/fnil.ts index 798cea9cb6..d1abfc3c18 100644 --- a/packages/iterators/src/fnil.ts +++ b/packages/iterators/src/fnil.ts @@ -35,6 +35,6 @@ export const fnil = (fn: FnAny, ...ctors: Fn0[]) => { return fn.apply(null, args); }; default: - illegalArity(ctors.length); + return illegalArity(ctors.length); } }; diff --git a/packages/iterators/src/fork.ts b/packages/iterators/src/fork.ts index 35e116c3c9..7dc107daf4 100644 --- a/packages/iterators/src/fork.ts +++ b/packages/iterators/src/fork.ts @@ -4,7 +4,7 @@ import { iterator } from "./iterator"; export const fork = (src: Iterable, cacheLimit = 16) => { const iter = iterator(src); const cache = new DCons(); - const forks = []; + const forks: number[] = []; let done = false; let total = 0; diff --git a/packages/iterators/src/frequencies.ts b/packages/iterators/src/frequencies.ts index 5a7abc3f54..6b6a0c6feb 100644 --- a/packages/iterators/src/frequencies.ts +++ b/packages/iterators/src/frequencies.ts @@ -1,4 +1,4 @@ -import { Fn } from "@thi.ng/api"; +import { Fn, IObjectOf } from "@thi.ng/api"; import { iterator } from "./iterator"; export interface FrequencyPair { @@ -9,8 +9,8 @@ export interface FrequencyPair { export function* frequencies( input: Iterable, key?: Fn -): IterableIterator[]> { - let freqs = {}; +): IterableIterator> { + let freqs: IObjectOf> = {}; let iter = iterator(input); let v: IteratorResult; while (((v = iter.next()), !v.done)) { diff --git a/packages/iterators/src/group-by.ts b/packages/iterators/src/group-by.ts index 62286ccd17..c8289103de 100644 --- a/packages/iterators/src/group-by.ts +++ b/packages/iterators/src/group-by.ts @@ -5,7 +5,7 @@ export const groupBy = ( key: Fn, input: Iterable ): IObjectOf => { - let groups = {}; + let groups: IObjectOf = {}; let iter = iterator(input); let v: IteratorResult; while (((v = iter.next()), !v.done)) { diff --git a/packages/iterators/src/last.ts b/packages/iterators/src/last.ts index cb8bc665a2..dea85d1bd3 100644 --- a/packages/iterators/src/last.ts +++ b/packages/iterators/src/last.ts @@ -3,7 +3,7 @@ import { iterator } from "./iterator"; export const last = (input: Iterable) => { let iter = iterator(input); let v: IteratorResult; - let prev: T; + let prev: T | undefined; while (((v = iter.next()), !v.done)) { prev = v.value; } diff --git a/packages/iterators/src/map-indexed.ts b/packages/iterators/src/map-indexed.ts index 534ff9ffed..cc99fe9202 100644 --- a/packages/iterators/src/map-indexed.ts +++ b/packages/iterators/src/map-indexed.ts @@ -4,5 +4,7 @@ import { range } from "./range"; export const mapIndexed = ( fn: (i: number, ...args: any[]) => T[], ...inputs: Iterable[] -): IterableIterator => - map.apply(null, ([fn, range()] as any[]).concat(inputs)); +) => + >( + map.apply(null, ([fn, range()]).concat(inputs)) + ); diff --git a/packages/iterators/src/mapcat.ts b/packages/iterators/src/mapcat.ts index c854d61b49..df1337b348 100644 --- a/packages/iterators/src/mapcat.ts +++ b/packages/iterators/src/mapcat.ts @@ -2,11 +2,11 @@ import { ensureIterable } from "./ensure"; import { map } from "./map"; export function* mapcat( - fn: (...args: any[]) => Iterable, + fn: (...args: any[]) => Iterable | undefined | null, ...inputs: Iterable[] ): IterableIterator { - (inputs as any[]).unshift(fn); - let iter = map.apply(null, inputs); + (inputs).unshift(fn); + let iter = >>map.apply(null, inputs); let v: IteratorResult>; while (((v = iter.next()), !v.done)) { if (v.value != null) { diff --git a/packages/iterators/src/reverse.ts b/packages/iterators/src/reverse.ts index 5e404ec93c..c355ed2ace 100644 --- a/packages/iterators/src/reverse.ts +++ b/packages/iterators/src/reverse.ts @@ -1,9 +1,9 @@ export function* reverse(input: Iterable) { - if (!(input.constructor === Array || (input as T[]).length !== undefined)) { + if (!(input.constructor === Array || (input).length !== undefined)) { input = [...input]; } - let n = (input as T[]).length; + let n = (input).length; while (--n >= 0) { - yield input[n]; + yield (input)[n]; } } diff --git a/packages/iterators/src/walk.ts b/packages/iterators/src/walk.ts index da3a3762a5..0019e63c0a 100644 --- a/packages/iterators/src/walk.ts +++ b/packages/iterators/src/walk.ts @@ -2,18 +2,18 @@ import { Fn } from "@thi.ng/api"; import { iterator, maybeIterator } from "./iterator"; import { maybeObjectIterator } from "./object-iterator"; -export const walkable = (x) => +export const walkable = (x: any) => typeof x !== "string" ? maybeIterator(x) || maybeObjectIterator(x) : undefined; -export function walk(fn: Fn, input: any, postOrder?: boolean); +export function walk(fn: Fn, input: any, postOrder?: boolean): void; export function walk( fn: Fn, children: Fn, input: any, postOrder?: boolean -); +): void; export function walk(fn: Fn, ...args: any[]) { let children: Fn; let input: any; @@ -25,7 +25,7 @@ export function walk(fn: Fn, ...args: any[]) { } else { [input, postOrder] = args; } - let inner = (iter) => { + let inner = (iter: Iterator) => { let v: IteratorResult; while (((v = iter.next()), !v.done)) { if (!postOrder) { @@ -67,7 +67,7 @@ export function walkIterator(input: any, ...args: any[]) { } else { postOrder = args[0]; } - let walk = function*(iter) { + let walk = function*(iter: Iterator): IterableIterator { let v: IteratorResult; while (((v = iter.next()), !v.done)) { if (!postOrder) { diff --git a/packages/iterators/test/index.ts b/packages/iterators/test/index.ts index c64a1760eb..aa03075d59 100644 --- a/packages/iterators/test/index.ts +++ b/packages/iterators/test/index.ts @@ -38,7 +38,7 @@ describe("iterators", function () { assert.deepEqual([...ti.concat([])], [], "empty"); assert.deepEqual([...ti.concat([], "", ti.range(0))], [], "3 args empty"); assert.deepEqual([...ti.concat([1, 2, 3], "abc", ti.range(3))], [1, 2, 3, "a", "b", "c", 0, 1, 2], "3 args any"); - assert.deepEqual([...ti.concat.apply(null, ["abc", null, [1, 2, 3]])], ["a", "b", "c", 1, 2, 3], "skip null"); + assert.deepEqual([...ti.concat.apply(null, ["abc", null, [1, 2, 3]])], ["a", "b", "c", 1, 2, 3], "skip null"); }); it("constantly", () => { const f = ti.constantly(1); @@ -58,7 +58,7 @@ describe("iterators", function () { }); it("dedupeWith", () => { let coll = [{ a: 1 }, { a: 1, b: 2 }, { a: 2, b: 2 }, { a: 2, b: 2 }, { a: 3 }]; - let eq = (a, b) => a.a === b.a; + let eq = (a:any, b:any) => a.a === b.a; assert.deepEqual([...ti.dedupeWith(eq, [])], [], "empty"); assert.deepEqual([...ti.dedupeWith(eq, coll)], [{ a: 1 }, { a: 2, b: 2 }, { a: 3 }], "array[obj]"); }); @@ -115,7 +115,7 @@ describe("iterators", function () { assert.deepEqual([...ti.flatten([{ a: 23, b: 42, c: [1, 2, 3] }], false)], [{ a: 23, b: 42, c: [1, 2, 3] }], "no obj"); }); it("flattenWith", () => { - let tx = x => typeof x == "string" ? ti.map(x => x.charCodeAt(0), x) : ti.maybeIterator(x); + let tx = (x:any) => typeof x == "string" ? ti.map(x => x.charCodeAt(0), x) : ti.maybeIterator(x); assert.deepEqual( [...ti.flattenWith(tx, ["ROOT", undefined, ["CHILD_1", null, ["CHILD_2"]]])], [82, 79, 79, 84, undefined, 67, 72, 73, 76, 68, 95, 49, null, 67, 72, 73, 76, 68, 95, 50], @@ -321,8 +321,8 @@ describe("iterators", function () { assert.deepEqual([...ti.takeLast(5, ti.range(3))], [0, 1, 2], "excess"); }); it("walk", () => { - let walk = (post) => { - let res = []; + let walk = (post:any) => { + let res: any[] = []; ti.walk((x) => res.push(x), [[1, { a: [2] }], ["3", [4]]], post); return res; }; @@ -408,7 +408,7 @@ describe("iterators", function () { { id: "ts", name: "TypeScript" } ]; assert.deepEqual(ti.zip("abcdef", ti.range()), { a: 0, b: 1, c: 2, d: 3, e: 4, f: 5 }, ""); - assert.deepEqual(ti.zip(ti.range(5, 10), ti.range(100, 200), new Uint8Array(16)), [0, 0, 0, 0, 0, 100, 101, 102, 103, 104, 0, 0, 0, 0, 0, 0], "typedarray") + assert.deepEqual(ti.zip(ti.range(5, 10), ti.range(100, 200), [...new Uint8Array(16)]), [0, 0, 0, 0, 0, 100, 101, 102, 103, 104, 0, 0, 0, 0, 0, 0], "typedarray") assert.deepEqual(ti.zip(ti.map((x) => x.id, langs), langs), { js: { id: "js", name: "JavaScript" }, clj: { id: "clj", name: "Clojure" }, ts: { id: "ts", name: "TypeScript" } }, "obj"); }); }); diff --git a/packages/leb128/.npmignore b/packages/leb128/.npmignore new file mode 100644 index 0000000000..dedee6b5ba --- /dev/null +++ b/packages/leb128/.npmignore @@ -0,0 +1,15 @@ +.meta +.nyc_output +*.html +*.tgz +*.h +*.o +*.wasm +build +coverage +dev +doc +export +src* +test +tsconfig.json diff --git a/packages/leb128/CHANGELOG.md b/packages/leb128/CHANGELOG.md new file mode 100644 index 0000000000..c1e49f8af8 --- /dev/null +++ b/packages/leb128/CHANGELOG.md @@ -0,0 +1,13 @@ +# Change Log + +All notable changes to this project will be documented in this file. +See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +# 0.1.0 (2019-07-07) + + +### Features + +* **leb128:** add READY promise to allow waiting for WASM initialization ([60c3245](https://github.com/thi-ng/umbrella/commit/60c3245)) +* **leb128:** add zig tests, move binary to sep src file for auto regen ([2a89cde](https://github.com/thi-ng/umbrella/commit/2a89cde)) +* **leb128:** import new hybrid TS/WASM/zig package, incl. readme & tests ([140b238](https://github.com/thi-ng/umbrella/commit/140b238)) diff --git a/packages/leb128/LICENSE b/packages/leb128/LICENSE new file mode 100644 index 0000000000..8dada3edaf --- /dev/null +++ b/packages/leb128/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/packages/leb128/README.md b/packages/leb128/README.md new file mode 100644 index 0000000000..ff36355d4b --- /dev/null +++ b/packages/leb128/README.md @@ -0,0 +1,112 @@ +# @thi.ng/leb128 + +[![npm (scoped)](https://img.shields.io/npm/v/@thi.ng/leb128.svg)](https://www.npmjs.com/package/@thi.ng/leb128) +![npm downloads](https://img.shields.io/npm/dm/@thi.ng/leb128.svg) +[![Twitter Follow](https://img.shields.io/twitter/follow/thing_umbrella.svg?style=flat-square&label=twitter)](https://twitter.com/thing_umbrella) + +This project is part of the +[@thi.ng/umbrella](https://github.com/thi-ng/umbrella/) monorepo. + + + +- [About](#about) +- [Installation](#installation) +- [Dependencies](#dependencies) +- [Usage examples](#usage-examples) +- [Building the binary](#building-the-binary) +- [Authors](#authors) +- [License](#license) + + + +## About + +WASM based [Little Endian Base +128](https://en.wikipedia.org/wiki/LEB128) varint encoding / decoding, +supporting (u)int64 range (however for JS purposes only up to +`MAX_SAFE_INTEGER`). + +The WASM binary (~660 bytes) is embedded as base64 string in the +TypeScript source to make it easier to use in both browser & node +environments. The source code of the actual implementation (written in +[Zig](https://ziglang.org)) is included in +[/src/leb128.zig](https://github.com/thi-ng/umbrella/tree/master/packages/leb128/src/leb128.zig) + +All public functions throw an error if the WASM module could not be +initialized. + +References: + +- https://en.wikipedia.org/wiki/LEB128 +- http://webassembly.github.io/spec/core/binary/values.html#integers + +## Installation + +```bash +yarn add @thi.ng/leb128 +``` + +## Dependencies + +- [@thi.ng/checks](https://github.com/thi-ng/umbrella/tree/master/packages/checks) +- [@thi.ng/errors](https://github.com/thi-ng/umbrella/tree/master/packages/errors) +- [@thi.ng/transducers-binary](https://github.com/thi-ng/umbrella/tree/master/packages/transducers-binary) + +## Usage examples + +```ts +import * as leb from "@thi.ng/leb128"; + +// since WASM initialization is async, need to wait until module is ready... +// if WASM is unavailable, the encode/decode functions will throw an error +leb.READY.then(()=> { + // encode unsigned int (input val up to 64 bits) + enc = leb.encodeULEB128(Number.MAX_SAFE_INTEGER); + // Uint8Array [ 255, 255, 255, 255, 255, 255, 255, 15 ] + + // decoding returns tuple of [value, bytes consumed] + leb.decodeULEB128(enc); + // [ 9007199254740991, 8 ] + + // encode signed int + enc = leb.encodeSLEB128(Number.MIN_SAFE_INTEGER) + // Uint8Array [ 129, 128, 128, 128, 128, 128, 128, 112 ] + leb.decodeSLEB128(enc) + // [ -9007199254740991, 8 ] +}); +``` + +## Building the binary + +```bash +# download latest master from https://ziglang.org/download/ + +# first run native tests +zig test packages/leb128/src/leb128.zig +# Test 1/2 min safe integer...OK +# Test 2/2 max safe integer...OK +# All tests passed. + +# compile to WASM (requires zig v0.4.0 or later) +zig build-lib -target wasm32-freestanding --release-small --strip src/leb128.zig + +# apply binaryen optimizer +wasm-opt leb128.wasm -o opt.wasm -Os + +# display as .wat text format +wasm2wat opt.wasm + +# base64 encode and generate src/binary.ts +echo "export const BINARY = \"$(base64 -i opt.wasm)\";" > src/binary.ts + +# test TS/JS version +yarn test +``` + +## Authors + +- Karsten Schmidt + +## License + +© 2019 Karsten Schmidt // Apache Software License 2.0 diff --git a/packages/ecs/package.json b/packages/leb128/package.json similarity index 74% rename from packages/ecs/package.json rename to packages/leb128/package.json index ffa2f070fa..9de7398e70 100644 --- a/packages/ecs/package.json +++ b/packages/leb128/package.json @@ -1,7 +1,7 @@ { - "name": "@thi.ng/ecs", - "version": "0.0.2", - "description": "TODO", + "name": "@thi.ng/leb128", + "version": "0.1.0", + "description": "WASM based LEB128 encoder / decoder (signed & unsigned)", "module": "./index.js", "main": "./lib/index.js", "umd:main": "./lib/index.umd.js", @@ -10,7 +10,7 @@ "type": "git", "url": "https://github.com/thi-ng/umbrella.git" }, - "homepage": "https://github.com/thi-ng/umbrella/tree/master/packages/ecs", + "homepage": "https://github.com/thi-ng/umbrella/tree/master/packages/binary", "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { @@ -25,23 +25,24 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/api": "^6.2.0", - "@thi.ng/checks": "^2.1.6", - "@thi.ng/errors": "^1.0.6", - "@thi.ng/transducers": "^5.3.7", - "@thi.ng/vectors": "^2.5.6" + "@thi.ng/checks": "^2.2.0", + "@thi.ng/errors": "^1.1.0", + "@thi.ng/transducers-binary": "^0.4.0" }, "keywords": [ - "ECS", + "LEB128", + "binary", + "conversion", "ES6", - "typescript" + "typescript", + "WASM" ], "publishConfig": { "access": "public" diff --git a/packages/leb128/src/binary.ts b/packages/leb128/src/binary.ts new file mode 100644 index 0000000000..0db82b0d27 --- /dev/null +++ b/packages/leb128/src/binary.ts @@ -0,0 +1,2 @@ +export const BINARY = + "AGFzbQEAAAABCgJgAXwBf2AAAXwDBQQAAQABBQMBAAIGFAN/AEGQiAQLfwBBiggLfwBBgAgLB38IBm1lbW9yeQIAC19faGVhcF9iYXNlAwAKX19kYXRhX2VuZAMBEmxlYjEyOF9lbmNvZGVfdV9qcwAAA2J1ZgMCEmxlYjEyOF9kZWNvZGVfdV9qcwABEmxlYjEyOF9lbmNvZGVfc19qcwACEmxlYjEyOF9kZWNvZGVfc19qcwADCoMEBHoCAn8BfgJAAkAgAEQAAAAAAADwQ2MgAEQAAAAAAAAAAGZxRQRADAELIACxIgNCgAFaDQELQYAIIAOnQf8AcToAAEEBDwsDQCABQYAIaiADpyICQf8AcSACQYABciADQgeIIgNQGzoAACABQQFqIQEgA0IAUg0ACyABC14CA38CfgJAA0AgAEEJSw0BIAFBAWohASAAQYAIaiwAACICQf8Aca0gBIYgA4QhAyAAQQFqIQAgBEIHfCEEIAJBf0wNAAtBgAggAToAACADug8LQYAIIAA6AAAgA7oLqwECBH8BfiAAmUQAAAAAAADgQ2MEfiAAsAVCgICAgICAgICAfwsiBUJAfUKAAVQEQEGACCAFQjmIp0HAAHEgBadBP3FyOgAAQQEPCwNAIAWnIgJBwABxIQMgAUGACGoCfwJAIAVCB4ciBUIAUQRAIANFDQELQQEhBCACQYB/ciADRSAFQn9Scg0BGgtBACEEIAJB/wBxCzoAACABQQFqIQEgBA0ACyABQf8BcQt6AgR/A34DQAJAIABBAWohASAFQgd8IQYgAEGACGotAAAiA0EYdEEYdSECIANB/wBxrSAFhiAEhCEEIABBCEsNACABIQAgBiEFIAJBAEgNAQsLQYAIIAE6AAAgBCAEQn8gBkI/g4aEIAJBwABxRSABQf8BcUEJS3IbuQs="; diff --git a/packages/leb128/src/index.ts b/packages/leb128/src/index.ts new file mode 100644 index 0000000000..26724d105a --- /dev/null +++ b/packages/leb128/src/index.ts @@ -0,0 +1,89 @@ +import { hasWASM } from "@thi.ng/checks"; +import { unsupported } from "@thi.ng/errors"; +import { base64Decode } from "@thi.ng/transducers-binary"; +import { BINARY } from "./binary"; + +interface LEB128 { + memory: WebAssembly.Memory; + buf: number; + leb128_encode_u_js(x: number): number; + leb128_decode_u_js(buf: number, num: number): number; + leb128_encode_s_js(x: number): number; + leb128_decode_s_js(buf: number, num: number): number; +} + +let wasm: LEB128; +let U8: Uint8Array; + +/** + * Promise indicating that the WASM module has been initialized and is + * ready to use. A `false` result means WASM isn't available at all. + */ +export let READY: Promise; + +if (hasWASM()) { + READY = WebAssembly.instantiate(new Uint8Array([...base64Decode(BINARY)])) + .then((inst) => { + wasm = inst.instance.exports; + // mapped view of the data buffer + U8 = new Uint8Array(wasm.memory.buffer, wasm.buf, 16); + }) + .then(() => true); +} else { + READY = Promise.resolve(false); +} + +const ensureWASM = () => !wasm && unsupported("WASM module unavailable"); + +const copy = (src: Uint8Array, idx: number) => + U8.set(src.subarray(idx, Math.min(idx + 10, src.length)), 0); + +/** + * Encodes signed integer `x` into LEB128 varint format and returns + * encoded bytes. + * + * @param x + */ +export const encodeSLEB128 = (x: number) => { + ensureWASM(); + return U8.slice(0, wasm.leb128_encode_s_js(x)); +}; + +/** + * Takes Uint8Array with LEB128 encoded signed varint and an optional + * start index to decode from. Returns 2-tuple of decoded value and + * number of bytes consumed. Consumes up to 10 bytes from `src`. + * + * @param src + * @param idx + */ +export const decodeSLEB128 = (src: Uint8Array, idx = 0) => { + ensureWASM(); + copy(src, idx); + return [wasm.leb128_decode_s_js(0, 0), U8[0]]; +}; + +/** + * Encodes unsigned integer `x` into LEB128 varint format and returns + * encoded bytes. Values < 0 will be encoded as zero. + * + * @param x + */ +export const encodeULEB128 = (x: number) => { + ensureWASM(); + return U8.slice(0, wasm.leb128_encode_u_js(x)); +}; + +/** + * Takes Uint8Array with LEB128 encoded unsigned varint and an optional + * start index to decode from. Returns 2-tuple of decoded value and + * number of bytes consumed. Consumes up to 10 bytes from `src`. + * + * @param src + * @param idx + */ +export const decodeULEB128 = (src: Uint8Array, idx = 0) => { + ensureWASM(); + copy(src, idx); + return [wasm.leb128_decode_u_js(0, 0), U8[0]]; +}; diff --git a/packages/leb128/src/leb128.zig b/packages/leb128/src/leb128.zig new file mode 100644 index 0000000000..5f0cd27e70 --- /dev/null +++ b/packages/leb128/src/leb128.zig @@ -0,0 +1,131 @@ +export var buf: [10]u8 = undefined; + +/// Encodes 64bit uint `src` and writes result bytes into `dest` (must +/// have at least 10 bytes capacity) +pub fn leb128_encode_u(src: u64, dest: []u8) u8 { + if (src < 0x80) { + dest[0] = @intCast(u8, src & 0x7f); + return 1; + } + var n: u8 = 0; + var x: u64 = src; + while (true) { + var byte: u8 = @intCast(u8, x & 0x7f); + x = x >> 7; + if (x != 0) { + byte |= 0x80; + } + dest[n] = byte; + n += 1; + if (x == 0) break; + } + return n; +} + +/// Decodes LEB128 bytes in `src` as u64 and writes number of bytes +/// consumed into `num`. +pub fn leb128_decode_u(src: []u8, num: *u8) u64 { + var res: u64 = 0; + var shift: u6 = 0; + var n: u8 = 0; + while (n < 10) { + var byte = src[n]; + res |= @intCast(u64, byte & 0x7f) << shift; + shift += 7; + n += 1; + if (byte < 0x80) { + break; + } + } + num.* = n; + return res; +} + +/// Like `leb128_encode_u` but for signed integers +pub fn leb128_encode_s(_x: i64, dest: []u8) u8 { + const neg: bool = _x < 0; + if (_x >= -64 and _x < 64) { + dest[0] = @intCast(u8, _x & 0x3f) | + @intCast(u8, @boolToInt(neg)) << 6; + return 1; + } + var n: u8 = 0; + var x: i64 = _x; + var more: bool = true; + while (more) { + var byte: u8 = @intCast(u8, x & 0x7f); + var sign: bool = (byte & 0x40) > 0; + x >>= 7; + if ((x == 0 and !sign) or (x == -1 and sign)) { + more = false; + } else { + byte |= 0x80; + } + dest[n] = byte; + n += 1; + } + return n; +} + +/// Like `leb128_decode_u` but for signed integers +pub fn leb128_decode_s(src: []u8, num: *u8) i64 { + var res: i64 = 0; + var shift: u6 = 0; + var n: u8 = 0; + var byte: u8 = 0; + while (true) { + byte = src[n]; + res |= @intCast(i64, byte & 0x7f) << shift; + shift += 7; + n += 1; + if ((byte & 0x80) == 0 or n > 9) { + break; + } + } + if (n < 10 and (byte & 0x40) > 0) { + res |= @intCast(i64, -1) << shift; + } + num.* = n; + return res; +} + +/// WASM only. JS interop to exchange data via f64 (for lack of i64/u64 +/// on JS side). Writes results to exported `buf` array and returns +/// number of bytes used. +export fn leb128_encode_u_js(x: f64) u8 { + return leb128_encode_u(@floatToInt(u64, x), buf[0..]); +} + +/// WASM only. JS interop to exchange data via f64 (for lack of i64/u64 +/// on JS side). Consumes bytes from the exported `buf` array and returns +/// decoded value. Writes number of bytes consumed into `buf[0]` +export fn leb128_decode_u_js() f64 { + return @intToFloat(f64, leb128_decode_u(buf[0..], &buf[0])); +} + +/// See `leb128_encode_u_js` +export fn leb128_encode_s_js(x: f64) u8 { + return leb128_encode_s(@floatToInt(i64, x), buf[0..]); +} + +/// See `leb128_decode_u_js` +export fn leb128_decode_s_js() f64 { + return @intToFloat(f64, leb128_decode_s(buf[0..], &buf[0])); +} + +const warn = @import("std").debug.warn; +const assert = @import("std").debug.assert; +const mem = @import("std").mem; + +test "min safe integer" { + assert(leb128_encode_s(-9007199254740991, buf[0..]) == 8); + assert(mem.eql(u8, buf[0..8], []u8{129, 128, 128, 128, 128, 128, 128, 112})); +} + +test "max safe integer" { + assert(leb128_encode_s(9007199254740991, buf[0..]) == 8); + assert(mem.eql(u8, buf[0..8], []u8{255, 255, 255, 255, 255, 255, 255, 15})); + + assert(leb128_encode_u(9007199254740991, buf[0..]) == 8); + assert(mem.eql(u8, buf[0..8], []u8{255, 255, 255, 255, 255, 255, 255, 15})); +} \ No newline at end of file diff --git a/packages/leb128/test/index.ts b/packages/leb128/test/index.ts new file mode 100644 index 0000000000..cd821cd836 --- /dev/null +++ b/packages/leb128/test/index.ts @@ -0,0 +1,48 @@ +import { hasWASM } from "@thi.ng/checks"; +import * as assert from "assert"; +import { + decodeSLEB128, + decodeULEB128, + encodeSLEB128, + encodeULEB128, + READY +} from "../src/index"; + +describe("leb128", () => { + if (hasWASM()) { + it("signed", async () => { + let a; + assert(await READY, "WASM not available"); + assert.deepEqual( + [...(a = encodeSLEB128(Number.MAX_SAFE_INTEGER))], + [255, 255, 255, 255, 255, 255, 255, 15] + ); + assert.deepEqual(decodeSLEB128(a), [Number.MAX_SAFE_INTEGER, 8]); + assert.deepEqual( + [...(a = encodeSLEB128(Number.MIN_SAFE_INTEGER))], + [129, 128, 128, 128, 128, 128, 128, 112] + ); + assert.deepEqual(decodeSLEB128(a), [Number.MIN_SAFE_INTEGER, 8]); + assert.deepEqual(decodeSLEB128(encodeSLEB128(64)), [64, 2]); + assert.deepEqual(decodeSLEB128(encodeSLEB128(-64)), [-64, 1]); + }); + + it("unsigned", async () => { + let a; + assert(await READY, "WASM not available"); + assert.deepEqual( + [...(a = encodeULEB128(Number.MAX_SAFE_INTEGER))], + [255, 255, 255, 255, 255, 255, 255, 15] + ); + assert.deepEqual(decodeULEB128(a), [Number.MAX_SAFE_INTEGER, 8]); + assert.deepEqual( + [...(a = encodeULEB128(Number.MIN_SAFE_INTEGER))], + [0] + ); + assert.deepEqual(decodeULEB128(a), [0, 1]); + assert.deepEqual(decodeULEB128(encodeULEB128(127)), [127, 1]); + }); + } else { + console.warn("WASM not available, skipping tests..."); + } +}); diff --git a/packages/leb128/test/tsconfig.json b/packages/leb128/test/tsconfig.json new file mode 100644 index 0000000000..f6e63560dd --- /dev/null +++ b/packages/leb128/test/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../../tsconfig.json", + "compilerOptions": { + "outDir": "../build", + "module": "commonjs" + }, + "include": [ + "./**/*.ts", + "../src/**/*.ts" + ] +} diff --git a/packages/leb128/tsconfig.json b/packages/leb128/tsconfig.json new file mode 100644 index 0000000000..893b9979c5 --- /dev/null +++ b/packages/leb128/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": ".", + "module": "es6", + "target": "es6" + }, + "include": [ + "./src/**/*.ts" + ] +} diff --git a/packages/lsys/.npmignore b/packages/lsys/.npmignore index 74ea62d1fa..1bb5fe6419 100644 --- a/packages/lsys/.npmignore +++ b/packages/lsys/.npmignore @@ -1,6 +1,7 @@ .meta .nyc_output *.html +*.svg *.tgz build coverage diff --git a/packages/lsys/CHANGELOG.md b/packages/lsys/CHANGELOG.md index 852da2fe09..1418f5292f 100644 --- a/packages/lsys/CHANGELOG.md +++ b/packages/lsys/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.2.15](https://github.com/thi-ng/umbrella/compare/@thi.ng/lsys@0.2.14...@thi.ng/lsys@0.2.15) (2019-07-07) + +**Note:** Version bump only for package @thi.ng/lsys + + + + + ## [0.2.14](https://github.com/thi-ng/umbrella/compare/@thi.ng/lsys@0.2.13...@thi.ng/lsys@0.2.14) (2019-05-22) **Note:** Version bump only for package @thi.ng/lsys diff --git a/packages/lsys/package.json b/packages/lsys/package.json index 340258035f..07ed264ac5 100644 --- a/packages/lsys/package.json +++ b/packages/lsys/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/lsys", - "version": "0.2.14", + "version": "0.2.15", "description": "Functional, extensible L-System architecture w/ support for probabilistic rules", "module": "./index.js", "main": "./lib/index.js", @@ -25,20 +25,20 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/api": "^6.2.0", - "@thi.ng/compose": "^1.2.5", - "@thi.ng/errors": "^1.0.6", - "@thi.ng/math": "^1.3.0", - "@thi.ng/random": "^1.1.7", - "@thi.ng/transducers": "^5.3.7", - "@thi.ng/vectors": "^2.5.6" + "@thi.ng/api": "^6.3.0", + "@thi.ng/compose": "^1.3.0", + "@thi.ng/errors": "^1.1.0", + "@thi.ng/math": "^1.4.0", + "@thi.ng/random": "^1.1.8", + "@thi.ng/transducers": "^5.4.0", + "@thi.ng/vectors": "^3.0.0" }, "keywords": [ "axiom", diff --git a/packages/lsys/test/examples.ts b/packages/lsys/test/examples.ts index 735ab870f6..a84759bc35 100644 --- a/packages/lsys/test/examples.ts +++ b/packages/lsys/test/examples.ts @@ -1,14 +1,31 @@ -import * as lsys from "@thi.ng/lsys"; import * as g from "@thi.ng/geom"; +import * as lsys from "@thi.ng/lsys"; import * as fs from "fs"; // example L-Systems shown above +interface Example { + rules: lsys.ProductionRules; + delta: number; + iter: number; +} -const examples = [ +const examples: Example[] = [ { rules: { s: "[f++f++f]", f: "f+f--f+f" }, delta: Math.PI / 3, iter: 5 }, - { rules: { s: "[f-f-f-f-f-f-f-f]", f: "f---f+f+f+f+f+f+f---f" }, delta: Math.PI / 4, iter: 6 }, - { rules: { s: "[x]", x: "-yf+xfx+fy-", y: "+xf-yfy-fx+" }, delta: Math.PI / 2, iter: 7 }, - { rules: { s: "[a]", a: "a-b--b+a++aa+b-", b: "+a-bb--b-a++a+b" }, delta: Math.PI / 3, iter: 5 } + { + rules: { s: "[f-f-f-f-f-f-f-f]", f: "f---f+f+f+f+f+f+f---f" }, + delta: Math.PI / 4, + iter: 6 + }, + { + rules: { s: "[x]", x: "-yf+xfx+fy-", y: "+xf-yfy-fx+" }, + delta: Math.PI / 2, + iter: 7 + }, + { + rules: { s: "[a]", a: "a-b--b+a++aa+b-", b: "+a-bb--b-a++a+b" }, + delta: Math.PI / 3, + iter: 5 + } ]; const impl = lsys.TURTLE_IMPL_2D; @@ -18,16 +35,23 @@ examples.forEach(({ rules, delta, iter }, i) => `lsys-ex${i}.svg`, g.asSvg( g.svgDoc( - { stroke: "#00f", "stroke-width": 0.25, width: 600, height: 600 }, - ...lsys.interpret( - // create turtle instance with customized delta (rot angle) - lsys.turtle2d({ delta }), - // customize implementation to process syms "a" & "b" as "f" - { ...impl, a: impl.f, b: impl.f }, - // recursively expand start rule "s" - lsys.expand(rules, "s", iter) - //convert result paths to polylines for SVG export - ).paths.map((pts) => g.polyline(pts)) + { + stroke: "#00f", + "stroke-width": 0.25, + width: 600, + height: 600 + }, + ...lsys + .interpret( + // create turtle instance with customized delta (rot angle) + lsys.turtle2d({ delta }), + // customize implementation to process syms "a" & "b" as "f" + { ...impl, a: impl.f, b: impl.f }, + // recursively expand start rule "s" + lsys.expand(rules, "s", iter) + //convert result paths to polylines for SVG export + ) + .paths.map((pts) => g.polyline(pts)) ) ) ) diff --git a/packages/malloc/CHANGELOG.md b/packages/malloc/CHANGELOG.md index c8a5d06c57..5d9c5a5278 100644 --- a/packages/malloc/CHANGELOG.md +++ b/packages/malloc/CHANGELOG.md @@ -3,6 +3,31 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [4.0.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/malloc@3.0.0...@thi.ng/malloc@4.0.0) (2019-07-07) + + +### Code Refactoring + +* **malloc:** address TS strictNullChecks flag ([e4781e3](https://github.com/thi-ng/umbrella/commit/e4781e3)) + + +### Features + +* **malloc:** enable TS strict compiler flags (refactor) ([e23e555](https://github.com/thi-ng/umbrella/commit/e23e555)) +* **malloc:** export typed array ctors, update wrap() ([3413ad7](https://github.com/thi-ng/umbrella/commit/3413ad7)) + + +### BREAKING CHANGES + +* **malloc:** update IMemPool return types + +- callocAs, mallocAs, reallocAs() now return `undefined` instead of + `null` if operation failed + + + + + # [3.0.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/malloc@2.0.10...@thi.ng/malloc@3.0.0) (2019-05-22) diff --git a/packages/malloc/package.json b/packages/malloc/package.json index f5b36ac87c..81951faf3b 100644 --- a/packages/malloc/package.json +++ b/packages/malloc/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/malloc", - "version": "3.0.0", + "version": "4.0.0", "description": "ArrayBuffer based malloc() impl for hybrid JS/WASM use cases, based on thi.ng/tinyalloc", "module": "./index.js", "main": "./lib/index.js", @@ -25,17 +25,17 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/api": "^6.2.0", - "@thi.ng/binary": "^1.0.6", - "@thi.ng/checks": "^2.1.6", - "@thi.ng/errors": "^1.0.6" + "@thi.ng/api": "^6.3.0", + "@thi.ng/binary": "^1.0.7", + "@thi.ng/checks": "^2.2.0", + "@thi.ng/errors": "^1.1.0" }, "keywords": [ "ES6", diff --git a/packages/malloc/src/api.ts b/packages/malloc/src/api.ts index 96a3fb3ab5..5ffd818038 100644 --- a/packages/malloc/src/api.ts +++ b/packages/malloc/src/api.ts @@ -3,7 +3,7 @@ import { IRelease, Type, TypedArray } from "@thi.ng/api"; export interface MemBlock { addr: number; size: number; - next: MemBlock; + next: MemBlock | null; } export interface MemPoolOpts { @@ -44,17 +44,17 @@ export interface IMemPool extends IRelease { calloc(size: number): number; - mallocAs(type: Type, num: number): TypedArray; + mallocAs(type: Type, num: number): TypedArray | undefined; - callocAs(type: Type, num: number): TypedArray; + callocAs(type: Type, num: number): TypedArray | undefined; realloc(ptr: number, size: number): number; - reallocArray(arr: TypedArray, num: number): TypedArray; + reallocArray(arr: TypedArray, num: number): TypedArray | undefined; free(ptr: number | TypedArray): boolean; - freeAll(); + freeAll(): void; stats(): MemPoolStats; } diff --git a/packages/malloc/src/pool.ts b/packages/malloc/src/pool.ts index 9df1be4e2e..8a2a426b21 100644 --- a/packages/malloc/src/pool.ts +++ b/packages/malloc/src/pool.ts @@ -18,13 +18,13 @@ export class MemPool implements IMemPool { protected doCompact: boolean; protected doSplit: boolean; protected minSplit: number; - protected _free: MemBlock; - protected _used: MemBlock; + protected _free: MemBlock | null; + protected _used: MemBlock | null; protected u8: Uint8Array; constructor(opts: Partial = {}) { - this.buf = opts.buf ? opts.buf : new ArrayBuffer(opts.size); + this.buf = opts.buf ? opts.buf : new ArrayBuffer(opts.size || 0x1000); this.u8 = new Uint8Array(this.buf); this.start = opts.start != null ? align(Math.max(opts.start, 8), 8) : 8; this.end = @@ -47,7 +47,7 @@ export class MemPool implements IMemPool { } stats(): MemPoolStats { - const listStats = (block: MemBlock) => { + const listStats = (block: MemBlock | null) => { let count = 0; let size = 0; while (block) { @@ -67,15 +67,15 @@ export class MemPool implements IMemPool { }; } - callocAs(type: Type, num: number): TypedArray { + callocAs(type: Type, num: number): TypedArray | undefined { const block = this.mallocAs(type, num); block && block.fill(0); return block; } - mallocAs(type: Type, num: number): TypedArray { + mallocAs(type: Type, num: number): TypedArray | undefined { const addr = this.malloc(num * SIZEOF[type]); - return addr ? wrap(type, this.buf, addr, num) : null; + return addr ? wrap(type, this.buf, addr, num) : undefined; } calloc(size: number): number { @@ -147,7 +147,7 @@ export class MemPool implements IMemPool { } size = align(size, 8); let block = this._used; - let blockEnd: number; + let blockEnd = 0; let newAddr = 0; while (block) { if (block.addr === addr) { @@ -195,12 +195,14 @@ export class MemPool implements IMemPool { return newAddr; } - reallocArray(ptr: TypedArray, num: number) { + reallocArray(ptr: TypedArray, num: number): TypedArray | undefined { if (ptr.buffer !== this.buf) { - return null; + return; } const addr = this.realloc(ptr.byteOffset, num * ptr.BYTES_PER_ELEMENT); - return addr ? new (ptr.constructor)(this.buf, addr, num) : null; + return addr + ? new (ptr.constructor)(this.buf, addr, num) + : undefined; } free(ptr: number | TypedArray) { @@ -214,7 +216,7 @@ export class MemPool implements IMemPool { addr = ptr; } let block = this._used; - let prev: MemBlock = null; + let prev: MemBlock | null = null; while (block) { if (block.addr === addr) { if (prev) { @@ -251,8 +253,8 @@ export class MemPool implements IMemPool { protected compact() { let block = this._free; - let prev: MemBlock; - let scan: MemBlock; + let prev: MemBlock | null = null; + let scan: MemBlock | null = null; let scanPrev: MemBlock; let res = false; while (block) { @@ -269,7 +271,7 @@ export class MemPool implements IMemPool { block.size = newSize; const next = scanPrev.next; let tmp = block.next; - while (tmp !== scanPrev.next) { + while (tmp && tmp !== scanPrev.next) { // console.log("release:", tmp.addr); const tn = tmp.next; tmp.next = null; @@ -291,7 +293,7 @@ export class MemPool implements IMemPool { protected insert(block: MemBlock) { let ptr = this._free; - let prev: MemBlock = null; + let prev: MemBlock | null = null; while (ptr) { if (block.addr <= ptr.addr) break; prev = ptr; diff --git a/packages/malloc/src/wrap.ts b/packages/malloc/src/wrap.ts index 1070ef5043..cdfe4aa251 100644 --- a/packages/malloc/src/wrap.ts +++ b/packages/malloc/src/wrap.ts @@ -1,17 +1,27 @@ import { IObjectOf, Type } from "@thi.ng/api"; -import { BlockCtor } from "./api"; -const CTORS: IObjectOf = { - [Type.U8]: (buf, addr, num) => new Uint8Array(buf, addr, num), - [Type.U8C]: (buf, addr, num) => new Uint8ClampedArray(buf, addr, num), - [Type.I8]: (buf, addr, num) => new Int8Array(buf, addr, num), - [Type.U16]: (buf, addr, num) => new Uint16Array(buf, addr, num), - [Type.I16]: (buf, addr, num) => new Int16Array(buf, addr, num), - [Type.U32]: (buf, addr, num) => new Uint32Array(buf, addr, num), - [Type.I32]: (buf, addr, num) => new Int32Array(buf, addr, num), - [Type.F32]: (buf, addr, num) => new Float32Array(buf, addr, num), - [Type.F64]: (buf, addr, num) => new Float64Array(buf, addr, num) +export type TypedArrayConstructor = + | Uint8ArrayConstructor + | Uint8ClampedArrayConstructor + | Int8ArrayConstructor + | Uint16ArrayConstructor + | Int16ArrayConstructor + | Uint32ArrayConstructor + | Int32ArrayConstructor + | Float32ArrayConstructor + | Float64ArrayConstructor; + +export const TYPEDARRAY_CTORS: IObjectOf = { + [Type.U8]: Uint8Array, + [Type.U8C]: Uint8ClampedArray, + [Type.I8]: Int8Array, + [Type.U16]: Uint16Array, + [Type.I16]: Int16Array, + [Type.U32]: Uint32Array, + [Type.I32]: Int32Array, + [Type.F32]: Float32Array, + [Type.F64]: Float64Array }; export const wrap = (type: Type, buf: ArrayBuffer, addr: number, num: number) => - CTORS[type](buf, addr, num); + new TYPEDARRAY_CTORS[type](buf, addr, num); diff --git a/packages/malloc/test/index.ts b/packages/malloc/test/index.ts index e26dd6681c..89e3255cd4 100644 --- a/packages/malloc/test/index.ts +++ b/packages/malloc/test/index.ts @@ -130,42 +130,45 @@ describe("malloc", () => { }); it("mallocAs", () => { - assert.strictEqual(pool.mallocAs(Type.U8, 257), null); - assert.strictEqual(pool.mallocAs(Type.U16, 129), null); - assert.strictEqual(pool.mallocAs(Type.U32, 65), null); - assert.strictEqual(pool.mallocAs(Type.F64, 33), null); - assert.strictEqual(pool.mallocAs(Type.U8, -1), null); + assert.deepEqual(pool.mallocAs(Type.U8, 257), null); + assert.deepEqual(pool.mallocAs(Type.U16, 129), null); + assert.deepEqual(pool.mallocAs(Type.U32, 65), null); + assert.deepEqual(pool.mallocAs(Type.F64, 33), null); + assert.deepEqual(pool.mallocAs(Type.U8, -1), null); let a = pool.mallocAs(Type.F32, 3); let b = pool.mallocAs(Type.F64, 3); assert(a instanceof Float32Array, "a type"); assert(b instanceof Float64Array, "b type"); - assert.equal(a.byteOffset, 8, "a addr"); - assert.equal(b.byteOffset, 24, "b addr"); - assert.equal(a.length, 3, "a.length"); - assert.equal(b.length, 3, "b.length"); - assert.equal(a.byteLength, 12, "a bytes"); - assert.equal(b.byteLength, 24, "b bytes"); - a.set([1, 2, 3]); - b.set([10, 20, 30]); - assert.deepEqual(new Uint32Array(pool.buf, 8, 10), [ - // a - 0x3f800000, - 0x40000000, - 0x40400000, - 0, - // b - 0, - 0x40240000, - 0, - 0x40340000, - 0, - 0x403e0000 - ]); - assert(pool.free(a), "free a"); - assert(pool.free(b), "free b"); - assert(!pool.free(a), "free a (repeat)"); - assert(!pool.free(b), "free b (repeat)"); + assert.equal(a!.byteOffset, 8, "a addr"); + assert.equal(b!.byteOffset, 24, "b addr"); + assert.equal(a!.length, 3, "a.length"); + assert.equal(b!.length, 3, "b.length"); + assert.equal(a!.byteLength, 12, "a bytes"); + assert.equal(b!.byteLength, 24, "b bytes"); + a!.set([1, 2, 3]); + b!.set([10, 20, 30]); + assert.deepEqual( + [...new Uint32Array(pool.buf, 8, 10)], + [ + // a + 0x3f800000, + 0x40000000, + 0x40400000, + 0, + // b + 0, + 0x40240000, + 0, + 0x40340000, + 0, + 0x403e0000 + ] + ); + assert(pool.free(a!), "free a"); + assert(pool.free(b!), "free b"); + assert(!pool.free(a!), "free a (repeat)"); + assert(!pool.free(b!), "free b (repeat)"); assert(!pool.free(new Uint16Array(1)), "free unmanaged"); }); @@ -173,22 +176,27 @@ describe("malloc", () => { const u8 = (pool).u8; u8.fill(0xff); let a = pool.calloc(6); - assert.deepEqual(u8.subarray(a, a + 9), [0, 0, 0, 0, 0, 0, 0, 0, 0xff]); + assert.deepEqual( + [...u8.subarray(a, a + 9)], + [0, 0, 0, 0, 0, 0, 0, 0, 0xff] + ); }); it("callocAs", () => { let a = pool.callocAs(Type.F32, 3); let b = pool.callocAs(Type.F64, 3); - a.set([1, 2, 3]); - b.set([10, 20, 30]); - assert(pool.free(a), "free a"); - assert(pool.free(b), "free b"); + assert(a instanceof Float32Array, "a type"); + assert(b instanceof Float64Array, "b type"); + a!.set([1, 2, 3]); + b!.set([10, 20, 30]); + assert(pool.free(a!), "free a"); + assert(pool.free(b!), "free b"); // returned arrays are zeroed a = pool.callocAs(Type.U32, 3); b = pool.callocAs(Type.U32, 3); const t = [0, 0, 0]; - assert.deepEqual(a, t); - assert.deepEqual(b, t); + assert.deepEqual([...a!], t); + assert.deepEqual([...b!], t); }); it("malloc top", () => { diff --git a/packages/math/CHANGELOG.md b/packages/math/CHANGELOG.md index b1c2310060..deedda345e 100644 --- a/packages/math/CHANGELOG.md +++ b/packages/math/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.4.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/math@1.3.0...@thi.ng/math@1.4.0) (2019-07-07) + + +### Features + +* **math:** add signed/unsigned int math ops ([518d79a](https://github.com/thi-ng/umbrella/commit/518d79a)) + + + + + # [1.3.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/math@1.2.3...@thi.ng/math@1.3.0) (2019-05-22) diff --git a/packages/math/package.json b/packages/math/package.json index cac18cf389..be36493e47 100644 --- a/packages/math/package.json +++ b/packages/math/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/math", - "version": "1.3.0", + "version": "1.4.0", "description": "Assorted common math functions & utilities", "module": "./index.js", "main": "./lib/index.js", @@ -25,11 +25,11 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "keywords": [ "ES6", diff --git a/packages/math/src/index.ts b/packages/math/src/index.ts index 1dc77b0c1e..eb17d7a13c 100644 --- a/packages/math/src/index.ts +++ b/packages/math/src/index.ts @@ -5,6 +5,7 @@ export * from "./crossing"; export * from "./eqdelta"; export * from "./extrema"; export * from "./fit"; +export * from "./int"; export * from "./interval"; export * from "./min-error"; export * from "./mix"; diff --git a/packages/math/src/int.ts b/packages/math/src/int.ts new file mode 100644 index 0000000000..ee92013ce0 --- /dev/null +++ b/packages/math/src/int.ts @@ -0,0 +1,96 @@ +const M8 = 0xff; +const M16 = 0xffff; + +export const signExtend8 = (a: number) => ((a &= M8), a & 0x80 ? a | ~M8 : a); + +export const signExtend16 = (a: number) => ( + (a &= M16), a & 0x8000 ? a | ~M16 : a +); + +export const addi8 = (a: number, b: number) => signExtend8((a | 0) + (b | 0)); +export const divi8 = (a: number, b: number) => signExtend8((a | 0) / (b | 0)); +export const muli8 = (a: number, b: number) => signExtend8((a | 0) * (b | 0)); +export const subi8 = (a: number, b: number) => signExtend8((a | 0) - (b | 0)); +export const andi8 = (a: number, b: number) => signExtend8((a | 0) & (b | 0)); +export const ori8 = (a: number, b: number) => signExtend8(a | 0 | (b | 0)); +export const xori8 = (a: number, b: number) => signExtend8((a | 0) ^ (b | 0)); +export const noti8 = (a: number) => signExtend8(~a); +// prettier-ignore +export const lshifti8 = (a: number, b: number) => signExtend8((a | 0) << (b | 0)); +// prettier-ignore +export const rshifti8 = (a: number, b: number) => signExtend8((a | 0) >> (b | 0)); + +export const addi16 = (a: number, b: number) => signExtend16((a | 0) + (b | 0)); +export const divi16 = (a: number, b: number) => signExtend16((a | 0) / (b | 0)); +export const muli16 = (a: number, b: number) => signExtend16((a | 0) * (b | 0)); +export const subi16 = (a: number, b: number) => signExtend16((a | 0) - (b | 0)); +export const andi16 = (a: number, b: number) => signExtend16((a | 0) & (b | 0)); +export const ori16 = (a: number, b: number) => signExtend16(a | 0 | (b | 0)); +export const xori16 = (a: number, b: number) => signExtend16((a | 0) ^ (b | 0)); +export const noti16 = (a: number) => signExtend16(~a); +// prettier-ignore +export const lshifti16 = (a: number, b: number) => signExtend16((a | 0) << (b | 0)); +// prettier-ignore +export const rshifti16 = (a: number, b: number) => signExtend16((a | 0) >> (b | 0)); + +export const addi32 = (a: number, b: number) => ((a | 0) + (b | 0)) | 0; +export const divi32 = (a: number, b: number) => ((a | 0) / (b | 0)) | 0; +export const muli32 = (a: number, b: number) => ((a | 0) * (b | 0)) | 0; +export const subi32 = (a: number, b: number) => ((a | 0) - (b | 0)) | 0; +export const andi32 = (a: number, b: number) => (a | 0) & (b | 0); +export const ori32 = (a: number, b: number) => a | 0 | (b | 0); +export const xori32 = (a: number, b: number) => (a | 0) ^ (b | 0); +export const lshifti32 = (a: number, b: number) => (a | 0) << (b | 0); +export const rshifti32 = (a: number, b: number) => (a | 0) >> (b | 0); +export const noti32 = (a: number) => ~a; + +// prettier-ignore +export const addu8 = (a: number, b: number) => ((a & M8) + (b & M8)) & M8; +// prettier-ignore +export const divu8 = (a: number, b: number) => ((a & M8) / (b & M8)) & M8; +// prettier-ignore +export const mulu8 = (a: number, b: number) => ((a & M8) * (b & M8)) & M8; +// prettier-ignore +export const subu8 = (a: number, b: number) => ((a & M8) - (b & M8)) & M8; +// prettier-ignore +export const andu8 = (a: number, b: number) => ((a & M8) & (b & M8)) & M8; +// prettier-ignore +export const oru8 = (a: number, b: number) => ((a & M8) | (b & M8)) & M8; +// prettier-ignore +export const xoru8 = (a: number, b: number) => ((a & M8) ^ (b & M8)) & M8; +export const notu8 = (a: number) => ~a & M8; +export const lshiftu8 = (a: number, b: number) => ((a & M8) << (b & M8)) & M8; +export const rshiftu8 = (a: number, b: number) => ((a & M8) >>> (b & M8)) & M8; + +// prettier-ignore +export const addu16 = (a: number, b: number) => ((a & M16) + (b & M16)) & M16; +// prettier-ignore +export const divu16 = (a: number, b: number) => ((a & M16) / (b & M16)) & M16; +// prettier-ignore +export const mulu16 = (a: number, b: number) => ((a & M16) * (b & M16)) & M16; +// prettier-ignore +export const subu16 = (a: number, b: number) => ((a & M16) - (b & M16)) & M16; +// prettier-ignore +export const andu16 = (a: number, b: number) => ((a & M16) & (b & M16)) & M16; +// prettier-ignore +export const oru16 = (a: number, b: number) => ((a & M16) | (b & M16)) & M16; +// prettier-ignore +export const xoru16 = (a: number, b: number) => ((a & M16) ^ (b & M16)) & M16; +export const notu16 = (a: number) => ~a & M16; +// prettier-ignore +export const lshiftu16 = (a: number, b: number) => ((a & M16) << (b & M16)) & M16; +// prettier-ignore +export const rshiftu16 = (a: number, b: number) => ((a & M16) >>> (b & M16)) & M16; + +export const addu32 = (a: number, b: number) => ((a >>> 0) + (b >>> 0)) >>> 0; +export const divu32 = (a: number, b: number) => ((a >>> 0) / (b >>> 0)) >>> 0; +export const mulu32 = (a: number, b: number) => ((a >>> 0) * (b >>> 0)) >>> 0; +export const subu32 = (a: number, b: number) => ((a >>> 0) - (b >>> 0)) >>> 0; +export const andu32 = (a: number, b: number) => ((a >>> 0) & (b >>> 0)) >>> 0; +export const oru32 = (a: number, b: number) => ((a >>> 0) | (b >>> 0)) >>> 0; +export const xoru32 = (a: number, b: number) => ((a >>> 0) ^ (b >>> 0)) >>> 0; +export const notu32 = (a: number) => ~a >>> 0; +// prettier-ignore +export const lshiftu32 = (a: number, b: number) => ((a >>> 0) << (b >>> 0)) >>> 0; +// prettier-ignore +export const rshiftu32 = (a: number, b: number) => ((a >>> 0) >>> (b >>> 0)) >>> 0; diff --git a/packages/matrices/CHANGELOG.md b/packages/matrices/CHANGELOG.md index 40b295ff9a..fa720909a3 100644 --- a/packages/matrices/CHANGELOG.md +++ b/packages/matrices/CHANGELOG.md @@ -3,6 +3,26 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.5.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/matrices@0.4.0...@thi.ng/matrices@0.5.0) (2019-07-07) + + +### Bug Fixes + +* **matrices:** update maddN call sites ([#95](https://github.com/thi-ng/umbrella/issues/95)) ([4a985c5](https://github.com/thi-ng/umbrella/commit/4a985c5)) + + +### Features + +* **matrices:** add isOrthagonal() ([d75305b](https://github.com/thi-ng/umbrella/commit/d75305b)) +* **matrices:** add matXXn & matXXv fns ([7a2ef82](https://github.com/thi-ng/umbrella/commit/7a2ef82)) +* **matrices:** add matXXn, matXXv, mulXXvm fns ([9359bbc](https://github.com/thi-ng/umbrella/commit/9359bbc)) +* **matrices:** enable TS strict compiler flags (refactor) ([7b1c81a](https://github.com/thi-ng/umbrella/commit/7b1c81a)) +* **matrices:** rename normal44 => normal33, add new normal44 (w/ M44 result) ([d54f746](https://github.com/thi-ng/umbrella/commit/d54f746)) + + + + + # [0.4.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/matrices@0.3.4...@thi.ng/matrices@0.4.0) (2019-05-22) diff --git a/packages/matrices/package.json b/packages/matrices/package.json index 7a3b553aba..cb03d0fefc 100644 --- a/packages/matrices/package.json +++ b/packages/matrices/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/matrices", - "version": "0.4.0", + "version": "0.5.0", "description": "Matrix & quaternion operations for 2D/3D geometry processing", "module": "./index.js", "main": "./lib/index.js", @@ -25,17 +25,17 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/api": "^6.2.0", - "@thi.ng/checks": "^2.1.6", - "@thi.ng/math": "^1.3.0", - "@thi.ng/vectors": "^2.5.6" + "@thi.ng/api": "^6.3.0", + "@thi.ng/checks": "^2.2.0", + "@thi.ng/math": "^1.4.0", + "@thi.ng/vectors": "^3.0.0" }, "keywords": [ "2D", diff --git a/packages/matrices/src/api.ts b/packages/matrices/src/api.ts index 6aaced29f8..27f76b6e5b 100644 --- a/packages/matrices/src/api.ts +++ b/packages/matrices/src/api.ts @@ -1,5 +1,10 @@ import { Tuple, TypedArray } from "@thi.ng/api"; -import { IVector, MultiVecOp, ReadonlyVec, Vec } from "@thi.ng/vectors"; +import { + IVector, + MultiVecOp, + ReadonlyVec, + Vec +} from "@thi.ng/vectors"; export type Mat = Vec; export type ReadonlyMat = ReadonlyVec; @@ -12,18 +17,20 @@ export type Mat44Like = Tuple | TypedArray; export type IMatrix = IVector; export type MultiMatOp = MultiVecOp; -export type MatOp1 = (out: Mat) => Mat; -export type MatOpM = (out: Mat, a: ReadonlyMat) => Mat; -export type MatOpN = (out: Mat, n: number) => Mat; -export type MatOpMM = (out: Mat, a: ReadonlyMat, b: ReadonlyMat) => Mat; -export type MatOpMV = (out: Vec, a: ReadonlyMat, b: ReadonlyVec) => Vec; -export type MatOpMN = (out: Mat, a: ReadonlyMat, n: number) => Mat; +export type MatOp1 = (out: Mat | null) => Mat; +export type MatOpM = (out: Mat | null, a: ReadonlyMat) => Mat; +export type MatOpMU = (out: Mat | null, a: ReadonlyMat) => Mat | undefined; +export type MatOpN = (out: Mat | null, n: number) => Mat; +export type MatOpMM = (out: Mat | null, a: ReadonlyMat, b: ReadonlyMat) => Mat; +export type MatOpMV = (out: Vec | null, a: ReadonlyMat, b: ReadonlyVec) => Vec; +export type MatOpMN = (out: Mat | null, a: ReadonlyMat, n: number) => Mat; -export type VecOpM = (out: Vec, a: ReadonlyMat) => Vec; -export type VecOpMN = (out: Vec, a: ReadonlyMat, n: number) => Vec; +export type VecOpM = (out: Vec | null, a: ReadonlyMat) => Vec; +export type VecOpMN = (out: Vec | null, a: ReadonlyMat, n: number) => Vec; export interface MultiMatOp1 extends MatOp1, MultiMatOp {} export interface MultiMatOpM extends MatOpM, MultiMatOp {} +export interface MultiMatOpMU extends MatOpMU, MultiMatOp {} export interface MultiMatOpN extends MatOpN, MultiMatOp {} export interface MultiMatOpMM extends MatOpMM, MultiMatOp {} export interface MultiMatOpMV extends MatOpMV, MultiMatOp {} @@ -32,27 +39,21 @@ export interface MultiMatOpMN extends MatOpMN, MultiMatOp {} export interface MultiVecOpM extends VecOpM, MultiMatOp {} export interface MultiVecOpMN extends VecOpMN, MultiMatOp {} -export const IDENT22 = Object.freeze([1, 0, 0, 1]); - -export const IDENT23 = Object.freeze([1, 0, 0, 1, 0, 0]); - -export const IDENT33 = Object.freeze([1, 0, 0, 0, 1, 0, 0, 0, 1]); - -export const IDENT44 = Object.freeze([ - 1, - 0, - 0, - 0, - 0, - 1, - 0, - 0, - 0, - 0, - 1, - 0, - 0, - 0, - 0, - 1 +export const IDENT22: ReadonlyMat = Object.freeze([1, 0, 0, 1]); + +export const IDENT23: ReadonlyMat = Object.freeze([1, 0, 0, 1, 0, 0]); + +//prettier-ignore +export const IDENT33: ReadonlyMat = Object.freeze([ + 1, 0, 0, + 0, 1, 0, + 0, 0, 1 +]); + +//prettier-ignore +export const IDENT44: ReadonlyMat = Object.freeze([ + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 ]); diff --git a/packages/matrices/src/concat.ts b/packages/matrices/src/concat.ts index 8d496667c0..b6deb17f7a 100644 --- a/packages/matrices/src/concat.ts +++ b/packages/matrices/src/concat.ts @@ -12,7 +12,7 @@ import { mulM } from "./mulm"; * @param xs */ export const concat = ( - out: Mat, + out: Mat | null, a: ReadonlyMat, b: ReadonlyMat, ...xs: ReadonlyMat[] diff --git a/packages/matrices/src/conjugate.ts b/packages/matrices/src/conjugate.ts index 873ccea00e..094c17bc29 100644 --- a/packages/matrices/src/conjugate.ts +++ b/packages/matrices/src/conjugate.ts @@ -1,4 +1,4 @@ import { ReadonlyVec, setC4, Vec } from "@thi.ng/vectors"; -export const conjugateQ = (out: Vec, a: ReadonlyVec) => +export const conjugateQ = (out: Vec | null, a: ReadonlyVec) => setC4(out || a, -a[0], -a[1], -a[2], a[3]); diff --git a/packages/matrices/src/frustum.ts b/packages/matrices/src/frustum.ts index f37b876d58..28ceb4e830 100644 --- a/packages/matrices/src/frustum.ts +++ b/packages/matrices/src/frustum.ts @@ -14,7 +14,7 @@ import { Mat } from "./api"; * @param far */ export const frustum = ( - out: Mat, + out: Mat | null, left: number, right: number, bottom: number, diff --git a/packages/matrices/src/index.ts b/packages/matrices/src/index.ts index bd8dedb168..bddf46264c 100644 --- a/packages/matrices/src/index.ts +++ b/packages/matrices/src/index.ts @@ -20,14 +20,18 @@ export * from "./m23-m22"; export * from "./m23-m44"; export * from "./m33-m44"; export * from "./m44-m33"; +export * from "./matn"; +export * from "./matv"; export * from "./mixq"; export * from "./mul"; export * from "./mulm"; export * from "./muln"; export * from "./mulq"; export * from "./mulv"; +export * from "./mulvm"; export * from "./normal-mat"; export * from "./ortho"; +export * from "./orthagonal"; export * from "./outer-product"; export * from "./perspective"; export * from "./project"; diff --git a/packages/matrices/src/invert.ts b/packages/matrices/src/invert.ts index 7434061576..2112601f24 100644 --- a/packages/matrices/src/invert.ts +++ b/packages/matrices/src/invert.ts @@ -9,7 +9,7 @@ import { Vec, vop } from "@thi.ng/vectors"; -import { MatOpM, MultiMatOpM } from "./api"; +import { MatOpMU, MultiMatOpMU } from "./api"; import { det44FromCoeffs, detCoeffs44 } from "./determinant"; const dp4 = dotC4; @@ -18,9 +18,9 @@ const dp6 = dotC6; /** * Matrix inversion. */ -export const invert: MultiMatOpM = vop(1); +export const invert: MultiMatOpMU = vop(1); -export const invert22: MatOpM = invert.add(4, (out, m) => { +export const invert22: MatOpMU = invert.add(4, (out, m) => { const [m00, m01, m10, m11] = m; let det = dp4(m00, m11, -m01, m10); if (det === 0) return; @@ -28,7 +28,7 @@ export const invert22: MatOpM = invert.add(4, (out, m) => { return setC4(out || m, m11 * det, -m01 * det, -m10 * det, m00 * det); }); -export const invert23: MatOpM = invert.add(6, (out, m) => { +export const invert23: MatOpMU = invert.add(6, (out, m) => { const [m00, m01, m10, m11, m20, m21] = m; let det = dp4(m00, m11, -m01, m10); if (det === 0) return; @@ -44,7 +44,7 @@ export const invert23: MatOpM = invert.add(6, (out, m) => { ); }); -export const invert33: MatOpM = invert.add(9, (out, m) => { +export const invert33: MatOpMU = invert.add(9, (out, m) => { const [m00, m01, m02, m10, m11, m12, m20, m21, m22] = m; const d01 = dp4(m22, m11, -m12, m21); const d11 = dp4(m12, m20, -m22, m10); @@ -66,7 +66,7 @@ export const invert33: MatOpM = invert.add(9, (out, m) => { ); }); -export const invert44: MatOpM = invert.add(16, (out, m) => { +export const invert44: MatOpMU = invert.add(16, (out, m) => { const coeffs = detCoeffs44(m); let det = det44FromCoeffs(coeffs); if (det === 0) return; @@ -111,7 +111,7 @@ export const invert44: MatOpM = invert.add(16, (out, m) => { ); }); -export const invertQ = (out: Vec, a: ReadonlyVec) => { +export const invertQ = (out: Vec | null, a: ReadonlyVec) => { let d = magSq4(a); d = d > 0 ? -1 / d : 0; return setC4(out || a, a[0] * d, a[1] * d, a[2] * d, a[3] * -d); diff --git a/packages/matrices/src/lookat.ts b/packages/matrices/src/lookat.ts index b2308c67b2..3c456a9bbd 100644 --- a/packages/matrices/src/lookat.ts +++ b/packages/matrices/src/lookat.ts @@ -18,7 +18,7 @@ import { Mat } from "./api"; * @param up */ export const lookAt = ( - out: Mat, + out: Mat | null, eye: ReadonlyVec, target: ReadonlyVec, up: ReadonlyVec diff --git a/packages/matrices/src/matn.ts b/packages/matrices/src/matn.ts new file mode 100644 index 0000000000..fcd0ec9717 --- /dev/null +++ b/packages/matrices/src/matn.ts @@ -0,0 +1,17 @@ +import { Mat } from "./api"; +import { + scale22, + scale23, + scale33, + scale44 +} from "./scale"; + +export const mat22n = (out: Mat | null, n: number) => scale22(out, n); + +export const mat23n = (out: Mat | null, n: number) => scale23(out, n); + +export const mat33n = (out: Mat | null, n: number) => scale33(out, n); + +export const mat44n = (out: Mat | null, n: number) => ( + (out = scale44(out, n)), (out[15] = n), out +); diff --git a/packages/matrices/src/matv.ts b/packages/matrices/src/matv.ts new file mode 100644 index 0000000000..a4f57d89af --- /dev/null +++ b/packages/matrices/src/matv.ts @@ -0,0 +1,14 @@ +import { + setVV16, + setVV4, + setVV6, + setVV9 +} from "@thi.ng/vectors"; + +export const mat22v = setVV4; + +export const mat23v = setVV6; + +export const mat33v = setVV9; + +export const mat44v = setVV16; diff --git a/packages/matrices/src/mixq.ts b/packages/matrices/src/mixq.ts index e3d0dc4f25..8486ed77d6 100644 --- a/packages/matrices/src/mixq.ts +++ b/packages/matrices/src/mixq.ts @@ -1,4 +1,11 @@ -import { dot4, maddN4, mulN4, ReadonlyVec, set4, Vec } from "@thi.ng/vectors"; +import { + dot4, + maddN4, + mulN4, + ReadonlyVec, + set4, + Vec +} from "@thi.ng/vectors"; /** * Interpolates quaternion `a` to `b` by given amount `t`, using SLERP. @@ -13,7 +20,7 @@ import { dot4, maddN4, mulN4, ReadonlyVec, set4, Vec } from "@thi.ng/vectors"; * @param eps */ export const mixQ = ( - out: Vec, + out: Vec | null, a: ReadonlyVec, b: ReadonlyVec, t: number, @@ -30,7 +37,7 @@ export const mixQ = ( u = Math.sin(theta * (1 - t)) / stheta; v = Math.sin(theta * t) / stheta; } - return maddN4(null, mulN4(out, a, u), b, v); + return maddN4(null, b, v, mulN4(out, a, u)); } return a !== out ? set4(out, a) : out; }; diff --git a/packages/matrices/src/mulq.ts b/packages/matrices/src/mulq.ts index 878c8d3a42..0abbee3139 100644 --- a/packages/matrices/src/mulq.ts +++ b/packages/matrices/src/mulq.ts @@ -1,4 +1,4 @@ -import { ReadonlyVec, setC4, Vec } from "@thi.ng/vectors"; +import { setC4, VecOpVV } from "@thi.ng/vectors"; /** * Performs quaternion multiplication of `a` and `b` and writes result @@ -8,7 +8,7 @@ import { ReadonlyVec, setC4, Vec } from "@thi.ng/vectors"; * @param a * @param b */ -export const mulQ = (out: Vec, a: ReadonlyVec, b: ReadonlyVec) => { +export const mulQ: VecOpVV = (out, a, b) => { const { 0: ax, 1: ay, 2: az, 3: aw } = a; const { 0: bx, 1: by, 2: bz, 3: bw } = b; return setC4( diff --git a/packages/matrices/src/mulv.ts b/packages/matrices/src/mulv.ts index 1cceeebbca..30a0e1667f 100644 --- a/packages/matrices/src/mulv.ts +++ b/packages/matrices/src/mulv.ts @@ -2,11 +2,10 @@ import { dotS2, dotS3, dotS4, - ReadonlyVec, setC2, setC3, setC4, - Vec, + VecOpVV, vop } from "@thi.ng/vectors"; import { MatOpMV, MultiMatOpMV } from "./api"; @@ -107,7 +106,7 @@ export const mulV344: MatOpMV = (out, m, v) => { * @param q * @param v */ -export const mulVQ = (out: Vec, q: ReadonlyVec, v: ReadonlyVec) => { +export const mulVQ: VecOpVV = (out, q, v) => { const { 0: px, 1: py, 2: pz } = v; const { 0: qx, 1: qy, 2: qz, 3: qw } = q; const ix = qw * px + qy * pz - qz * py; diff --git a/packages/matrices/src/mulvm.ts b/packages/matrices/src/mulvm.ts new file mode 100644 index 0000000000..657b375e10 --- /dev/null +++ b/packages/matrices/src/mulvm.ts @@ -0,0 +1,70 @@ +import { + dot2, + dot3, + dot4, + dotS2, + dotS3, + dotS4, + ReadonlyVec, + setC2, + setC3, + setC4, + Vec +} from "@thi.ng/vectors"; +import { ReadonlyMat } from "./api"; + +/** + * Same as: + * + * ``` + * out[0] = dot(v, column(m, 0)) + * out[1] = dot(v, column(m, 1)) + * ``` + * + * @param out + * @param v + * @param m + */ +export const mulVM22 = (out: Vec | null, v: ReadonlyVec, m: ReadonlyMat) => + setC2(out, dot2(v, m), dotS2(v, m, 0, 2)); + +export const mulVM23 = mulVM22; + +/** + * Same as: + * + * ``` + * out[0] = dot(v, column(m, 0)) + * out[1] = dot(v, column(m, 1)) + * out[2] = dot(v, column(m, 2)) + * ``` + * + * @param out + * @param v + * @param m + */ +export const mulVM33 = (out: Vec | null, v: ReadonlyVec, m: ReadonlyMat) => + setC3(out, dot3(v, m), dotS3(v, m, 0, 3), dotS3(v, m, 0, 6)); + +/** + * Same as: + * + * ``` + * out[0] = dot(v, column(m, 0)) + * out[1] = dot(v, column(m, 1)) + * out[2] = dot(v, column(m, 2)) + * out[3] = dot(v, column(m, 3)) + * ``` + * + * @param out + * @param v + * @param m + */ +export const mulVM44 = (out: Vec | null, v: ReadonlyVec, m: ReadonlyMat) => + setC4( + out, + dot4(v, m), + dotS4(v, m, 0, 4), + dotS4(v, m, 0, 8), + dotS4(v, m, 0, 12) + ); diff --git a/packages/matrices/src/normal-mat.ts b/packages/matrices/src/normal-mat.ts index c3570a5e85..39b555d925 100644 --- a/packages/matrices/src/normal-mat.ts +++ b/packages/matrices/src/normal-mat.ts @@ -1,14 +1,31 @@ -import { MatOpM } from "./api"; +import { MatOpMU } from "./api"; +import { invert33, invert44 } from "./invert"; import { mat44to33 } from "./m44-m33"; -import { invert33 } from "./invert"; -import { transpose33 } from "./transpose"; +import { transpose33, transpose44 } from "./transpose"; /** * Converts given M44 to a M33 normal matrix, i.e. the transposed - * inverted version of its upper-left 3x3 region. + * inverse of its upper-left 3x3 region. If `out` is null a new result + * matrix will be created. Returns `undefined` if matrix inversion + * fails. * * @param out * @param m */ -export const normal44: MatOpM = (out, m) => - transpose33(null, invert33(null, mat44to33(out, m))); +export const normal33: MatOpMU = (out, m) => { + out = invert33(null, mat44to33(out, m))!; + return out ? transpose33(null, out) : undefined; +}; + +/** + * Converts given M44 to a M44 normal matrix, i.e. the transposed + * inverse. Writes results to `m` if `out` is null. Returns `undefined` + * if matrix inversion fails. + * + * @param out + * @param m + */ +export const normal44: MatOpMU = (out, m) => { + out = invert44(out, m)!; + return out ? transpose44(null, out) : undefined; +}; diff --git a/packages/matrices/src/orthagonal.ts b/packages/matrices/src/orthagonal.ts new file mode 100644 index 0000000000..c7b02d34b4 --- /dev/null +++ b/packages/matrices/src/orthagonal.ts @@ -0,0 +1,32 @@ +import { EPS, eqDeltaFixed } from "@thi.ng/math"; +import { ReadonlyMat } from "./api"; + +/** + * Returns true, if given square matrix of size `n` is orthagonal, i.e. + * check if `A * AT = I`. + * + * https://en.wikipedia.org/wiki/Orthogonal_matrix + * + * @param m + * @param n + * @param eps + */ +export const isOrthagonal = (m: ReadonlyMat, n: number, eps = EPS) => { + for (let i = 0; i < n; i++) { + const ii = i * n; + for (let j = 0; j < n; j++) { + const jj = j * n; + let acc = 0; + for (let k = 0; k < n; k++) { + acc += m[ii + k] * m[jj + k]; + } + if ( + (i == j && !eqDeltaFixed(acc, 1, eps)) || + (i != j && !eqDeltaFixed(acc, 0, eps)) + ) { + return false; + } + } + } + return true; +}; diff --git a/packages/matrices/src/ortho.ts b/packages/matrices/src/ortho.ts index 3bf1301517..71464a4831 100644 --- a/packages/matrices/src/ortho.ts +++ b/packages/matrices/src/ortho.ts @@ -14,7 +14,7 @@ import { Mat } from "./api"; * @param far */ export const ortho = ( - out: Mat, + out: Mat | null, left: number, right: number, bottom: number, diff --git a/packages/matrices/src/outer-product.ts b/packages/matrices/src/outer-product.ts index 507585da05..7644ddbd00 100644 --- a/packages/matrices/src/outer-product.ts +++ b/packages/matrices/src/outer-product.ts @@ -17,13 +17,13 @@ export const outerProduct: MultiVecOpVV = vop(1); export const outerProduct2 = outerProduct.add( 2, - (out: Mat, [ux, uy]: ReadonlyVec, [vx, vy]: ReadonlyVec) => + (out: Mat | null, [ux, uy]: ReadonlyVec, [vx, vy]: ReadonlyVec) => setC4(out || [], ux * vx, uy * vx, ux * vy, uy * vy) ); export const outerProduct3 = outerProduct.add( 3, - (out: Mat, [ux, uy, uz]: ReadonlyVec, [vx, vy, vz]: ReadonlyVec) => + (out: Mat | null, [ux, uy, uz]: ReadonlyVec, [vx, vy, vz]: ReadonlyVec) => setC( out || [], ux * vx, @@ -40,7 +40,11 @@ export const outerProduct3 = outerProduct.add( export const outerProduct4 = outerProduct.add( 4, - (out: Mat, [ux, uy, uz, uw]: ReadonlyVec, [vx, vy, vz, vw]: ReadonlyVec) => + ( + out: Mat | null, + [ux, uy, uz, uw]: ReadonlyVec, + [vx, vy, vz, vw]: ReadonlyVec + ) => setC( out || [], ux * vx, diff --git a/packages/matrices/src/perspective.ts b/packages/matrices/src/perspective.ts index da652be835..4c46b80f4e 100644 --- a/packages/matrices/src/perspective.ts +++ b/packages/matrices/src/perspective.ts @@ -12,7 +12,7 @@ import { frustum, frustumBounds } from "./frustum"; * @param far */ export const perspective = ( - out: Mat, + out: Mat | null, fov: number, aspect: number, near: number, diff --git a/packages/matrices/src/project.ts b/packages/matrices/src/project.ts index afd641e147..3c7b78ec35 100644 --- a/packages/matrices/src/project.ts +++ b/packages/matrices/src/project.ts @@ -21,11 +21,14 @@ import { mulV23, mulV344, mulV44 } from "./mulv"; * @param p */ export const project = ( - out: Vec, + out: Vec | null, mvp: ReadonlyMat, view: ReadonlyMat, p: ReadonlyVec -) => mulV23(out, view, fromHomogeneous4(out, mulV44([], mvp, p))); +) => ( + !out && (out = []), + mulV23(out, view, fromHomogeneous4(out, mulV44([], mvp, p))) +); /** * Reverse operation of project. If `invert` is true (default: false), @@ -47,8 +50,11 @@ export const unproject = ( doInvert = false ) => { if (doInvert) { - mvp = invert44([], mvp); - view = invert23([], view); + const _mvp = invert44([], mvp); + const _view = invert23([], view); + if (!_mvp || !_view) return; + mvp = _mvp; + view = _view; } const q = [...mulV23([], view, p), p[2] * 2 - 1]; return divN3( diff --git a/packages/matrices/src/quat-m33.ts b/packages/matrices/src/quat-m33.ts index d471314e97..f32a704af8 100644 --- a/packages/matrices/src/quat-m33.ts +++ b/packages/matrices/src/quat-m33.ts @@ -1,4 +1,5 @@ -import { ReadonlyVec, setC, Vec } from "@thi.ng/vectors"; +import { ReadonlyVec, setC } from "@thi.ng/vectors"; +import { Mat } from "./api"; /** * Converts quaternion into M33 and writes result to `out`. @@ -6,7 +7,7 @@ import { ReadonlyVec, setC, Vec } from "@thi.ng/vectors"; * @param out * @param q */ -export const quatToMat33 = (out: Vec, q: ReadonlyVec) => { +export const quatToMat33 = (out: Mat | null, q: ReadonlyVec) => { const [x, y, z, w] = q; const x2 = x + x; const y2 = y + y; diff --git a/packages/matrices/src/quat-m44.ts b/packages/matrices/src/quat-m44.ts index 6e83784ddf..00f3a5464e 100644 --- a/packages/matrices/src/quat-m44.ts +++ b/packages/matrices/src/quat-m44.ts @@ -1,4 +1,5 @@ -import { ReadonlyVec, setC, Vec, ZERO3 } from "@thi.ng/vectors"; +import { ReadonlyVec, setC, ZERO3 } from "@thi.ng/vectors"; +import { Mat } from "./api"; /** * Converts quaternion into M44 with optional translation offset `t`, @@ -8,7 +9,7 @@ import { ReadonlyVec, setC, Vec, ZERO3 } from "@thi.ng/vectors"; * @param q */ export const quatToMat44 = ( - out: Vec, + out: Mat | null, a: ReadonlyVec, t: ReadonlyVec = ZERO3 ) => { diff --git a/packages/matrices/src/rotation-around-axis.ts b/packages/matrices/src/rotation-around-axis.ts index 6006357274..325ac17915 100644 --- a/packages/matrices/src/rotation-around-axis.ts +++ b/packages/matrices/src/rotation-around-axis.ts @@ -13,7 +13,7 @@ import { mat33to44 } from "./m33-m44"; * @param normalize */ export const rotationAroundAxis33 = ( - out: Mat, + out: Mat | null, axis: ReadonlyVec, theta: number, normalize = false @@ -47,7 +47,7 @@ export const rotationAroundAxis33 = ( * @param normalize */ export const rotationAroundAxis44 = ( - out: Mat, + out: Mat | null, axis: ReadonlyVec, theta: number, normalize = false diff --git a/packages/matrices/src/rotation.ts b/packages/matrices/src/rotation.ts index f766c4e922..a2b4b0ea0e 100644 --- a/packages/matrices/src/rotation.ts +++ b/packages/matrices/src/rotation.ts @@ -8,7 +8,7 @@ import { Mat } from "./api"; * @param out * @param theta */ -export const rotation22 = (out: Mat, theta: number) => { +export const rotation22 = (out: Mat | null, theta: number) => { const [s, c] = sincos(theta); return setC4(out || [], c, s, -s, c); }; @@ -19,7 +19,7 @@ export const rotation22 = (out: Mat, theta: number) => { * @param out * @param theta */ -export const rotation23 = (out: Mat, theta: number) => { +export const rotation23 = (out: Mat | null, theta: number) => { const [s, c] = sincos(theta); return setC6(out || [], c, s, -s, c, 0, 0); }; @@ -30,7 +30,7 @@ export const rotation23 = (out: Mat, theta: number) => { * @param out * @param theta */ -export const rotationX33 = (out: Mat, theta: number) => { +export const rotationX33 = (out: Mat | null, theta: number) => { const [s, c] = sincos(theta); return setC(out || [], 1, 0, 0, 0, c, s, 0, -s, c); }; @@ -41,7 +41,7 @@ export const rotationX33 = (out: Mat, theta: number) => { * @param out * @param theta */ -export const rotationY33 = (out: Mat, theta: number) => { +export const rotationY33 = (out: Mat | null, theta: number) => { const [s, c] = sincos(theta); return setC(out || [], c, 0, -s, 0, 1, 0, s, 0, c); }; @@ -52,7 +52,7 @@ export const rotationY33 = (out: Mat, theta: number) => { * @param out * @param theta */ -export const rotationZ33 = (out: Mat, theta: number) => { +export const rotationZ33 = (out: Mat | null, theta: number) => { const [s, c] = sincos(theta); return setC(out || [], c, s, 0, -s, c, 0, 0, 0, 1); }; @@ -63,7 +63,7 @@ export const rotationZ33 = (out: Mat, theta: number) => { * @param out * @param theta */ -export const rotationX44 = (out: Mat, theta: number) => { +export const rotationX44 = (out: Mat | null, theta: number) => { const [s, c] = sincos(theta); return setC(out || [], 1, 0, 0, 0, 0, c, s, 0, 0, -s, c, 0, 0, 0, 0, 1); }; @@ -74,7 +74,7 @@ export const rotationX44 = (out: Mat, theta: number) => { * @param out * @param theta */ -export const rotationY44 = (out: Mat, theta: number) => { +export const rotationY44 = (out: Mat | null, theta: number) => { const [s, c] = sincos(theta); return setC(out || [], c, 0, -s, 0, 0, 1, 0, 0, s, 0, c, 0, 0, 0, 0, 1); }; @@ -85,7 +85,7 @@ export const rotationY44 = (out: Mat, theta: number) => { * @param out * @param theta */ -export const rotationZ44 = (out: Mat, theta: number) => { +export const rotationZ44 = (out: Mat | null, theta: number) => { const [s, c] = sincos(theta); return setC(out || [], c, s, 0, 0, -s, c, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); }; diff --git a/packages/matrices/src/scale-center.ts b/packages/matrices/src/scale-center.ts index 6f705e5c7f..657306d2ac 100644 --- a/packages/matrices/src/scale-center.ts +++ b/packages/matrices/src/scale-center.ts @@ -12,7 +12,7 @@ import { translation23, translation44 } from "./translation"; * @param m */ export const scaleWithCenter23 = ( - m: Mat, + m: Mat | null, p: ReadonlyVec, s: number | ReadonlyVec ) => @@ -31,7 +31,7 @@ export const scaleWithCenter23 = ( * @param m */ export const scaleWithCenter44 = ( - m: Mat, + m: Mat | null, p: ReadonlyVec, s: number | ReadonlyVec ) => diff --git a/packages/matrices/src/scale.ts b/packages/matrices/src/scale.ts index eee903306d..73c0dbbc45 100644 --- a/packages/matrices/src/scale.ts +++ b/packages/matrices/src/scale.ts @@ -1,5 +1,10 @@ import { isNumber } from "@thi.ng/checks"; -import { ReadonlyVec, setC, setC4, setC6 } from "@thi.ng/vectors"; +import { + ReadonlyVec, + setC, + setC4, + setC6 +} from "@thi.ng/vectors"; import { Mat } from "./api"; /** @@ -9,7 +14,7 @@ import { Mat } from "./api"; * @param m * @param s */ -export const scale22 = (m: Mat, s: number | ReadonlyVec) => ( +export const scale22 = (m: Mat | null, s: number | ReadonlyVec) => ( (s = isNumber(s) ? [s, s] : s), setC4(m || [], s[0], 0, 0, s[1]) ); @@ -20,7 +25,7 @@ export const scale22 = (m: Mat, s: number | ReadonlyVec) => ( * @param m * @param s */ -export const scale23 = (m: Mat, s: number | ReadonlyVec) => ( +export const scale23 = (m: Mat | null, s: number | ReadonlyVec) => ( (s = isNumber(s) ? [s, s] : s), setC6(m || [], s[0], 0, 0, s[1], 0, 0) ); @@ -31,7 +36,7 @@ export const scale23 = (m: Mat, s: number | ReadonlyVec) => ( * @param m * @param s */ -export const scale33 = (m: Mat, s: number | ReadonlyVec) => ( +export const scale33 = (m: Mat | null, s: number | ReadonlyVec) => ( (s = isNumber(s) ? [s, s, s] : s), setC(m || [], s[0], 0, 0, 0, s[1], 0, 0, 0, s[2]) ); @@ -43,7 +48,7 @@ export const scale33 = (m: Mat, s: number | ReadonlyVec) => ( * @param m * @param s */ -export const scale44 = (m: Mat, s: number | ReadonlyVec) => ( +export const scale44 = (m: Mat | null, s: number | ReadonlyVec) => ( (s = isNumber(s) ? [s, s, s] : s), setC( m || [], diff --git a/packages/matrices/src/set.ts b/packages/matrices/src/set.ts index 332ebb6c2c..13fe92888e 100644 --- a/packages/matrices/src/set.ts +++ b/packages/matrices/src/set.ts @@ -1,7 +1,12 @@ -import { compile, set as _set, SET, set4 } from "@thi.ng/vectors"; +import { + compile, + set as _set, + SET, + set4 +} from "@thi.ng/vectors"; import { MatOpM } from "./api"; -const $ = (dim) => _set.add(dim, compile(dim, SET, "o,a")); +const $ = (dim: number) => _set.add(dim, compile(dim, SET, "o,a")); export const set: MatOpM = _set; export const set22: MatOpM = set4; diff --git a/packages/matrices/src/shear.ts b/packages/matrices/src/shear.ts index b837357169..bb71c8335d 100644 --- a/packages/matrices/src/shear.ts +++ b/packages/matrices/src/shear.ts @@ -1,8 +1,13 @@ import { Mat, MatOp1 } from "./api"; -import { identity33, identity44, identity23, identity22 } from "./identity"; +import { + identity22, + identity23, + identity33, + identity44 +} from "./identity"; -const $ = (f: MatOp1) => (i: number) => (m: Mat, x: number) => ( - f(m), (m[i] = x), m +const $ = (f: MatOp1) => (i: number) => (m: Mat | null, x: number) => ( + !m && (m = []), f(m), (m[i] = x), m ); const $22 = $(identity22); diff --git a/packages/matrices/src/skew.ts b/packages/matrices/src/skew.ts index 7d1d3ada5a..f868009392 100644 --- a/packages/matrices/src/skew.ts +++ b/packages/matrices/src/skew.ts @@ -18,7 +18,8 @@ import { shearZY44 } from "./shear"; -const $ = (f: MatOpN) => (m: Mat, theta: number) => f(m, Math.tan(theta)); +const $ = (f: MatOpN) => (m: Mat | null, theta: number) => + f(m, Math.tan(theta)); export const skewX22 = $(shearX22); export const skewY22 = $(shearY22); diff --git a/packages/matrices/src/transform.ts b/packages/matrices/src/transform.ts index a7e496464f..e4fe27fdfb 100644 --- a/packages/matrices/src/transform.ts +++ b/packages/matrices/src/transform.ts @@ -18,7 +18,7 @@ import { translation23 } from "./translation"; * @param scale */ export const transform23 = ( - out: Mat, + out: Mat | null, translate: ReadonlyVec, rotation: number, scale: number | ReadonlyVec @@ -42,7 +42,7 @@ export const transform23 = ( * @param scale */ export const transform44 = ( - out: Mat, + out: Mat | null, translate: ReadonlyVec, rotation: ReadonlyVec, scale: number | ReadonlyVec diff --git a/packages/matrices/src/translation.ts b/packages/matrices/src/translation.ts index fe2e436047..d5dd010783 100644 --- a/packages/matrices/src/translation.ts +++ b/packages/matrices/src/translation.ts @@ -7,7 +7,7 @@ import { Mat } from "./api"; * @param out * @param v */ -export const translation23 = (m: Mat, v: ReadonlyVec) => +export const translation23 = (m: Mat | null, v: ReadonlyVec) => setC6(m || [], 1, 0, 0, 1, v[0], v[1]); /** @@ -16,5 +16,5 @@ export const translation23 = (m: Mat, v: ReadonlyVec) => * @param out * @param v */ -export const translation44 = (m: Mat, v: ReadonlyVec) => +export const translation44 = (m: Mat | null, v: ReadonlyVec) => setC(m || [], 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, v[0], v[1], v[2], 1); diff --git a/packages/matrices/src/viewport.ts b/packages/matrices/src/viewport.ts index 36a573a633..8e09a472a6 100644 --- a/packages/matrices/src/viewport.ts +++ b/packages/matrices/src/viewport.ts @@ -14,7 +14,7 @@ import { translation23 } from "./translation"; * @param top */ export const viewport = ( - out: Mat, + out: Mat | null, left: number, right: number, bottom: number, diff --git a/packages/memoize/CHANGELOG.md b/packages/memoize/CHANGELOG.md index 38cd7719fb..2b30cbd89f 100644 --- a/packages/memoize/CHANGELOG.md +++ b/packages/memoize/CHANGELOG.md @@ -3,6 +3,22 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.1.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/memoize@1.0.9...@thi.ng/memoize@1.1.0) (2019-07-07) + + +### Bug Fixes + +* **memoize:** return type memoize1() ([c0dafb9](https://github.com/thi-ng/umbrella/commit/c0dafb9)) + + +### Features + +* **memoize:** enable TS strict compiler flags (refactor) ([a08cc69](https://github.com/thi-ng/umbrella/commit/a08cc69)) + + + + + ## [1.0.9](https://github.com/thi-ng/umbrella/compare/@thi.ng/memoize@1.0.8...@thi.ng/memoize@1.0.9) (2019-05-22) **Note:** Version bump only for package @thi.ng/memoize diff --git a/packages/memoize/package.json b/packages/memoize/package.json index 7d7a5a78a4..91c0aafc04 100644 --- a/packages/memoize/package.json +++ b/packages/memoize/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/memoize", - "version": "1.0.9", + "version": "1.1.0", "description": "Function memoization with configurable caches", "module": "./index.js", "main": "./lib/index.js", @@ -25,14 +25,14 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/api": "^6.2.0" + "@thi.ng/api": "^6.3.0" }, "keywords": [ "cache", diff --git a/packages/memoize/src/memoize.ts b/packages/memoize/src/memoize.ts index 40699f5592..ed7e89eeb3 100644 --- a/packages/memoize/src/memoize.ts +++ b/packages/memoize/src/memoize.ts @@ -1,4 +1,11 @@ -import { Fn1, Fn2, Fn3, Fn4, FnAny, MapLike } from "./api"; +import { + Fn1, + Fn2, + Fn3, + Fn4, + FnAny, + MapLike +} from "./api"; /** * Function memoization for arbitrary argument counts. Returns augmented @@ -27,7 +34,7 @@ export function memoize( fn: Fn4, cache: MapLike<[A, B, C, D], E> ): Fn4; -export function memoize(fn: FnAny, cache: Map): FnAny { +export function memoize(fn: FnAny, cache: MapLike): FnAny { return (...args: any[]) => { let res; return cache.has(args) diff --git a/packages/memoize/src/memoize1.ts b/packages/memoize/src/memoize1.ts index bbcba4ed0b..efa0fd32b6 100644 --- a/packages/memoize/src/memoize1.ts +++ b/packages/memoize/src/memoize1.ts @@ -13,8 +13,10 @@ import { Fn1, MapLike } from "./api"; */ export function memoize1(fn: Fn1, cache?: MapLike) { !cache && (cache = new Map()); - return (x: A) => { + return (x: A): B => { let res; - return cache.has(x) ? cache.get(x) : (cache.set(x, (res = fn(x))), res); + return cache!.has(x) + ? cache!.get(x)! + : (cache!.set(x, (res = fn(x))), res); }; } diff --git a/packages/memoize/src/memoizej.ts b/packages/memoize/src/memoizej.ts index 4acbd24125..8029da7c5e 100644 --- a/packages/memoize/src/memoizej.ts +++ b/packages/memoize/src/memoizej.ts @@ -1,5 +1,11 @@ import { IObjectOf } from "@thi.ng/api"; -import { Fn1, Fn2, Fn3, Fn4, FnAny } from "./api"; +import { + Fn1, + Fn2, + Fn3, + Fn4, + FnAny +} from "./api"; /** * Function memoization for arbitrary argument counts. Returns augmented @@ -31,9 +37,9 @@ export function memoizeJ(fn: FnAny, cache?: IObjectOf): FnAny { return (...args: any[]) => { const key = JSON.stringify(args); if (key !== undefined) { - return key in cache - ? cache[key] - : (cache[key] = fn.apply(null, args)); + return key in cache! + ? cache![key] + : (cache![key] = fn.apply(null, args)); } return fn.apply(null, args); }; diff --git a/packages/memoize/test/index.ts b/packages/memoize/test/index.ts index 2c3036ad2b..f1b115a902 100644 --- a/packages/memoize/test/index.ts +++ b/packages/memoize/test/index.ts @@ -1,12 +1,11 @@ -import * as assert from "assert"; import { EquivMap } from "@thi.ng/associative"; import { LRUCache } from "@thi.ng/cache"; +import * as assert from "assert"; import * as m from "../src/index"; describe("memoize", () => { - it("memoize1", () => { - const calls = []; + const calls: number[] = []; const f = m.memoize1((x) => (calls.push(x), x * 10)); assert.equal(f(1), 10); assert.equal(f(2), 20); @@ -17,7 +16,7 @@ describe("memoize", () => { }); it("memoize1 (equivmap)", () => { - const calls = []; + const calls: number[][] = []; const f = m.memoize1( (x) => (calls.push(x), x[0] + x[1]), new EquivMap() @@ -31,8 +30,11 @@ describe("memoize", () => { }); it("memoize1 (lru)", () => { - const calls = []; - const cache = new LRUCache(null, { maxlen: 3, map: () => new EquivMap() }); + const calls: number[][] = []; + const cache = new LRUCache(null, { + maxlen: 3, + map: () => new EquivMap() + }); const f = m.memoize1( (x) => (calls.push(x), x[0] + x[1]), cache diff --git a/packages/morton/CHANGELOG.md b/packages/morton/CHANGELOG.md index 2326f10489..8c95bdb219 100644 --- a/packages/morton/CHANGELOG.md +++ b/packages/morton/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.1.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/morton@1.0.9...@thi.ng/morton@1.1.0) (2019-07-07) + + +### Features + +* **morton:** enable TS strict compiler flags (refactor) ([1fc2e9a](https://github.com/thi-ng/umbrella/commit/1fc2e9a)) + + + + + ## [1.0.9](https://github.com/thi-ng/umbrella/compare/@thi.ng/morton@1.0.8...@thi.ng/morton@1.0.9) (2019-05-22) **Note:** Version bump only for package @thi.ng/morton diff --git a/packages/morton/package.json b/packages/morton/package.json index 8da72601a7..8722904236 100644 --- a/packages/morton/package.json +++ b/packages/morton/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/morton", - "version": "1.0.9", + "version": "1.1.0", "description": "Z-order-curve / Morton encoding & decoding for 1D, 2D, 3D", "module": "./index.js", "main": "./lib/index.js", @@ -25,16 +25,16 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/binary": "^1.0.6", - "@thi.ng/errors": "^1.0.6", - "@thi.ng/math": "^1.3.0" + "@thi.ng/binary": "^1.0.7", + "@thi.ng/errors": "^1.1.0", + "@thi.ng/math": "^1.4.0" }, "keywords": [ "binary", diff --git a/packages/morton/src/index.ts b/packages/morton/src/index.ts index c7370f9273..21e2628ec8 100644 --- a/packages/morton/src/index.ts +++ b/packages/morton/src/index.ts @@ -217,7 +217,7 @@ export const treeToCartesian = (t: number[], dim: number) => { }; export const cartesianToTree = (v: number[]) => { - const $ = (v: number[], half: number) => { + const $ = (v: number[], half: number): number[] => { const t = v.reduce((t, x, i) => t + (1 << i) * (x >= half), 0); return half > 1 ? [t, ...$(v.map((x) => x % half), half >>> 1)] : [t]; }; diff --git a/packages/paths/CHANGELOG.md b/packages/paths/CHANGELOG.md index 8f17a9ce2f..bccc02103f 100644 --- a/packages/paths/CHANGELOG.md +++ b/packages/paths/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [2.1.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/paths@2.0.9...@thi.ng/paths@2.1.0) (2019-07-07) + + +### Features + +* **paths:** enable TS strict compiler flags (refactor) ([55e93ee](https://github.com/thi-ng/umbrella/commit/55e93ee)) + + + + + ## [2.0.9](https://github.com/thi-ng/umbrella/compare/@thi.ng/paths@2.0.8...@thi.ng/paths@2.0.9) (2019-04-24) **Note:** Version bump only for package @thi.ng/paths diff --git a/packages/paths/package.json b/packages/paths/package.json index e5c7fb35c6..6723f53266 100644 --- a/packages/paths/package.json +++ b/packages/paths/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/paths", - "version": "2.0.9", + "version": "2.1.0", "description": "immutable, optimized path-based object property / array accessors", "module": "./index.js", "main": "./lib/index.js", @@ -25,15 +25,15 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/checks": "^2.1.6", - "@thi.ng/errors": "^1.0.6" + "@thi.ng/checks": "^2.2.0", + "@thi.ng/errors": "^1.1.0" }, "keywords": [ "accessors", diff --git a/packages/paths/src/index.ts b/packages/paths/src/index.ts index 5b887ccc73..08a10f3752 100644 --- a/packages/paths/src/index.ts +++ b/packages/paths/src/index.ts @@ -8,11 +8,12 @@ export type UpdateFn = (curr: T, ...args: any[]) => T; const isa = Array.isArray; const iss = isString; -const _copy = (s) => (isa(s) ? s.slice() : { ...s }); +const _copy = (s: any) => (isa(s) ? s.slice() : { ...s }); -const compS = (k, f) => (s, v) => ( - (s = _copy(s)), (s[k] = f ? f(s[k], v) : v), s -); +const compS = (k: PropertyKey, f: (o: any, v: any) => any) => ( + s: any, + v: any +) => ((s = _copy(s)), (s[k] = f ? f(s[k], v) : v), s); /** * Converts the given key path to canonical form (array). @@ -103,14 +104,14 @@ export const getter = (path: Path) => { let [a, b, c, d] = ks; switch (ks.length) { case 0: - return (s) => s; + return (s: any) => s; case 1: - return (s) => (s != null ? s[a] : undefined); + return (s: any) => (s != null ? s[a] : undefined); case 2: - return (s) => + return (s: any) => s != null ? ((s = s[a]) != null ? s[b] : undefined) : undefined; case 3: - return (s) => + return (s: any) => s != null ? (s = s[a]) != null ? (s = s[b]) != null @@ -119,7 +120,7 @@ export const getter = (path: Path) => { : undefined : undefined; case 4: - return (s) => + return (s: any) => s != null ? (s = s[a]) != null ? (s = s[b]) != null @@ -130,7 +131,7 @@ export const getter = (path: Path) => { : undefined : undefined; default: - return (s) => { + return (s: any) => { const n = ks.length - 1; let res = s; for (let i = 0; res != null && i <= n; i++) { @@ -230,7 +231,7 @@ export const setter = (path: Path): ((s: any, v: any) => any) => { return s; }; default: - let f; + let f: any; for (let i = ks.length; --i >= 0; ) { f = compS(ks[i], f); } @@ -310,7 +311,7 @@ export const updater = (path: Path, fn: UpdateFn) => { const g = getter(path); const s = setter(path); return (state: any, ...args: any[]) => - s(state, fn.apply(null, (args.unshift(g(state)), args))); + s(state, fn.apply(null, (args.unshift(g(state)), args))); }; /** @@ -336,7 +337,7 @@ export const updateIn = ( ) => setter(path)( state, - fn.apply(null, (args.unshift(getter(path)(state)), args)) + fn.apply(null, (args.unshift(getter(path)(state)), args)) ); /** @@ -356,7 +357,7 @@ export const updateIn = ( export const deleteIn = (state: any, path: Path) => { const ks = [...toPath(path)]; if (ks.length > 0) { - const k = ks.pop(); + const k = ks.pop(); return updateIn(state, ks, (x) => ((x = { ...x }), delete x[k], x)); } }; @@ -377,11 +378,11 @@ export const mutator = (path: Path) => { let [a, b, c, d] = ks; switch (ks.length) { case 0: - return (_, x) => x; + return (_: any, x: any) => x; case 1: - return (s, x) => (s ? ((s[a] = x), s) : undefined); + return (s: any, x: any) => (s ? ((s[a] = x), s) : undefined); case 2: - return (s, x) => { + return (s: any, x: any) => { let t; return s ? (t = s[a]) @@ -390,7 +391,7 @@ export const mutator = (path: Path) => { : undefined; }; case 3: - return (s, x) => { + return (s: any, x: any) => { let t; return s ? (t = s[a]) @@ -401,7 +402,7 @@ export const mutator = (path: Path) => { : undefined; }; case 4: - return (s, x) => { + return (s: any, x: any) => { let t; return s ? (t = s[a]) @@ -414,7 +415,7 @@ export const mutator = (path: Path) => { : undefined; }; default: - return (s, x) => { + return (s: any, x: any) => { let t = s; const n = ks.length - 1; for (let k = 0; k < n; k++) { diff --git a/packages/paths/test/index.ts b/packages/paths/test/index.ts index 32487c567d..9f6e9d3761 100644 --- a/packages/paths/test/index.ts +++ b/packages/paths/test/index.ts @@ -129,8 +129,8 @@ describe("paths", () => { }); it("exists", () => { - const a = { a: { b: null } }; - const b = { x: { y: { z: [1, 2, { u: 3, v: undefined }] } } }; + const a: any = { a: { b: null } }; + const b: any = { x: { y: { z: [1, 2, { u: 3, v: undefined }] } } }; assert.ok(!exists(null, "x.y.z"), "x.y.z"); assert.ok(!exists(0, "x.y.z"), "x.y.z"); assert.ok(exists("", "length"), "length"); diff --git a/packages/pointfree-lang/CHANGELOG.md b/packages/pointfree-lang/CHANGELOG.md index bee369698d..7ccabcf58c 100644 --- a/packages/pointfree-lang/CHANGELOG.md +++ b/packages/pointfree-lang/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.1.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/pointfree-lang@1.0.14...@thi.ng/pointfree-lang@1.1.0) (2019-07-07) + + +### Features + +* **pointfree:** enable TS strict compiler flags (refactor) ([1f9d155](https://github.com/thi-ng/umbrella/commit/1f9d155)) + + + + + ## [1.0.14](https://github.com/thi-ng/umbrella/compare/@thi.ng/pointfree-lang@1.0.13...@thi.ng/pointfree-lang@1.0.14) (2019-05-22) **Note:** Version bump only for package @thi.ng/pointfree-lang diff --git a/packages/pointfree-lang/package.json b/packages/pointfree-lang/package.json index 07c8e80cf3..3c381be50b 100644 --- a/packages/pointfree-lang/package.json +++ b/packages/pointfree-lang/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/pointfree-lang", - "version": "1.0.14", + "version": "1.1.0", "description": "Forth style syntax layer/compiler for the @thi.ng/pointfree DSL", "module": "./index.js", "main": "./lib/index.js", @@ -27,16 +27,16 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "pegjs": "^0.11.0-dev.325", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/api": "^6.2.0", - "@thi.ng/errors": "^1.0.6", - "@thi.ng/pointfree": "^1.0.14" + "@thi.ng/api": "^6.3.0", + "@thi.ng/errors": "^1.1.0", + "@thi.ng/pointfree": "^1.1.0" }, "keywords": [ "concatenative", diff --git a/packages/pointfree-lang/src/index.ts b/packages/pointfree-lang/src/index.ts index 5a5771bde7..1d04d10f40 100644 --- a/packages/pointfree-lang/src/index.ts +++ b/packages/pointfree-lang/src/index.ts @@ -9,7 +9,6 @@ import { } from "./api"; import { parse, SyntaxError } from "./parser"; - export let LOGGER = NULL_LOGGER; export const setLogger = (logger: ILogger) => (LOGGER = logger); @@ -29,8 +28,8 @@ const nodeLoc = (node: ASTNode) => * @param ctx */ const resolveSym = (node: ASTNode, ctx: pf.StackContext) => { - const id = node.id; - let w = ctx[2].__words[id] || ALIASES[id] || pf[id]; + const id = node.id!; + let w = ctx[2].__words[id] || ALIASES[id] || (pf)[id]; if (!w) { illegalArgs(`${nodeLoc(node)} unknown symbol: ${id}`); } @@ -48,7 +47,7 @@ const resolveSym = (node: ASTNode, ctx: pf.StackContext) => { * @param ctx */ const resolveVar = (node: ASTNode, ctx: pf.StackContext) => { - const id = node.id; + const id = node.id!; const v = ctx[2].__vars[id]; if (!v) { illegalArgs(`${nodeLoc(node)} unknown var: ${id}`); @@ -66,14 +65,14 @@ const resolveVar = (node: ASTNode, ctx: pf.StackContext) => { * @param node * @param ctx */ -const resolveNode = (node: ASTNode, ctx: pf.StackContext) => { +const resolveNode = (node: ASTNode, ctx: pf.StackContext): any => { switch (node.type) { case NodeType.SYM: return resolveSym(node, ctx); case NodeType.VAR_DEREF: return resolveVar(node, ctx); case NodeType.VAR_STORE: - return storevar(node.id); + return storevar(node.id!); case NodeType.ARRAY: return resolveArray(node, ctx); case NodeType.OBJ: @@ -104,7 +103,7 @@ const resolveArray = (node: ASTNode, ctx: pf.StackContext) => { * @param ctx */ const resolveObject = (node: ASTNode, ctx: pf.StackContext) => { - const res = {}; + const res: any = {}; for (let [k, v] of node.body) { res[k.type === NodeType.SYM ? k.id : resolveNode(k, ctx)] = resolveNode( v, @@ -268,7 +267,7 @@ const visitStore = ( ctx: pf.StackContext, state: VisitorState ) => { - const id = node.id; + const id = node.id!; if (state.word) { ctx[0].push(storevar(id)); return ctx; @@ -296,7 +295,7 @@ const visitWord = ( ctx: pf.StackContext, state: VisitorState ) => { - const id = node.id; + const id = node.id!; if (state.word) { illegalState( `${nodeLoc(node)}: can't define words inside quotations (${id})` @@ -346,7 +345,11 @@ const visitArray = ( state: VisitorState ) => { if (state.word) { - ctx[0].push((_ctx) => (_ctx[0].push(resolveArray(node, _ctx)), _ctx)); + ctx[0].push( + (_ctx: pf.StackContext) => ( + _ctx[0].push(resolveArray(node, _ctx)), _ctx + ) + ); } else { ctx[0].push(resolveArray(node, ctx)); } @@ -368,7 +371,11 @@ const visitObject = ( state: VisitorState ) => { if (state.word) { - ctx[0].push((_ctx) => (_ctx[0].push(resolveObject(node, _ctx)), _ctx)); + ctx[0].push( + (_ctx: pf.StackContext) => ( + _ctx[0].push(resolveObject(node, _ctx)), _ctx + ) + ); } else { ctx[0].push(resolveObject(node, ctx)); } diff --git a/packages/pointfree-lang/src/parser.ts b/packages/pointfree-lang/src/parser.ts index bb282bdea8..f2e527e88a 100644 --- a/packages/pointfree-lang/src/parser.ts +++ b/packages/pointfree-lang/src/parser.ts @@ -3,8 +3,8 @@ // Stubs for auto-generated parser module (using pegjs 0.10.+) // To rebuild the parser run either: `yarn build` or `yarn peg` export class SyntaxError { - message: string; - expected: string; + message!: string; + expected!: string; found: any; location: any; } diff --git a/packages/pointfree-lang/test/readme.ts b/packages/pointfree-lang/test/readme.ts index 8876e06daa..c124a8c57f 100644 --- a/packages/pointfree-lang/test/readme.ts +++ b/packages/pointfree-lang/test/readme.ts @@ -1,3 +1,4 @@ +import { StackContext } from "@thi.ng/pointfree/api"; import * as pf from "../src"; const src = ` @@ -18,7 +19,7 @@ const src = ` -rot [vline] [hline] bis2 [gfx.line] bia2; `; -const drawLine = (ctx) => { +const drawLine = (ctx: StackContext) => { const stack = ctx[0]; // minimum stack depth guard pf.ensureStack(stack, 2); @@ -40,9 +41,12 @@ const drawLine = (ctx) => { }; // create new environment and associate custom FFI words -const env = pf.ffi({}, { - "gfx.line": drawLine -}); +const env = pf.ffi( + {}, + { + "gfx.line": drawLine + } +); // compile / execute source code w/ given env // the compiled words will be stored in given env diff --git a/packages/pointfree/CHANGELOG.md b/packages/pointfree/CHANGELOG.md index b4140ef3dd..75b6b3470b 100644 --- a/packages/pointfree/CHANGELOG.md +++ b/packages/pointfree/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.1.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/pointfree@1.0.14...@thi.ng/pointfree@1.1.0) (2019-07-07) + + +### Features + +* **pointfree:** enable TS strict compiler flags (refactor) ([1f9d155](https://github.com/thi-ng/umbrella/commit/1f9d155)) + + + + + ## [1.0.14](https://github.com/thi-ng/umbrella/compare/@thi.ng/pointfree@1.0.13...@thi.ng/pointfree@1.0.14) (2019-05-22) diff --git a/packages/pointfree/package.json b/packages/pointfree/package.json index 23c3c7bd9f..bd5e5c5735 100644 --- a/packages/pointfree/package.json +++ b/packages/pointfree/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/pointfree", - "version": "1.0.14", + "version": "1.1.0", "description": "Pointfree functional composition / Forth style stack execution engine", "module": "./index.js", "main": "./lib/index.js", @@ -25,18 +25,18 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/api": "^6.2.0", - "@thi.ng/checks": "^2.1.6", - "@thi.ng/compose": "^1.2.5", - "@thi.ng/equiv": "^1.0.6", - "@thi.ng/errors": "^1.0.6" + "@thi.ng/api": "^6.3.0", + "@thi.ng/checks": "^2.2.0", + "@thi.ng/compose": "^1.3.0", + "@thi.ng/equiv": "^1.0.7", + "@thi.ng/errors": "^1.1.0" }, "keywords": [ "composition", diff --git a/packages/pointfree/src/index.ts b/packages/pointfree/src/index.ts index db18588d25..c85b6e7b67 100644 --- a/packages/pointfree/src/index.ts +++ b/packages/pointfree/src/index.ts @@ -100,12 +100,11 @@ const $stackFn = (f: StackProc) => (isArray(f) ? word(f) : f); const tos = (stack: Stack) => stack[stack.length - 1]; const compile = (prog: StackProgram) => - compL.apply( - null, + compL.apply(null, ( prog.map((w) => !isFunction(w) ? (ctx: StackContext) => (ctx[0].push(w), ctx) : w ) - ); + )); /** * Takes a result tuple returned by `run()` and unwraps one or more @@ -288,7 +287,7 @@ export const op2v = (f: Fn2) => ( illegalArgs("at least one arg must be an array"); } } - stack[n] = c; + stack[n] = c!; return ctx; }; @@ -599,7 +598,7 @@ export const cprd = (ctx: StackContext) => ( $(ctx[1], 1), ctx[0].push(tos(ctx[1])), ctx ); -const mov2 = (a, b) => (ctx: StackContext) => { +const mov2 = (a: number, b: number) => (ctx: StackContext) => { const src = ctx[a]; $(src, 2); const v = src.pop(); @@ -607,7 +606,7 @@ const mov2 = (a, b) => (ctx: StackContext) => { return ctx; }; -const cp2 = (a, b) => (ctx: StackContext) => { +const cp2 = (a: number, b: number) => (ctx: StackContext) => { const src = ctx[a]; const n = src.length - 2; $n(n, 0); @@ -1251,6 +1250,7 @@ export const cases = (cases: IObjectOf) => (ctx: StackContext) => { return $stackFn(cases.default)(ctx); } illegalState(`no matching case for: ${tos}`); + return ctx; }; export const casesq = (ctx: StackContext) => { diff --git a/packages/pointfree/test/index.ts b/packages/pointfree/test/index.ts index 0d3f356ada..6b8e87995b 100644 --- a/packages/pointfree/test/index.ts +++ b/packages/pointfree/test/index.ts @@ -1,7 +1,8 @@ import * as assert from "assert"; -import * as pf from "../src/index"; import { StackContext } from "../src/api"; +import * as pf from "../src/index"; +// prettier-ignore describe("pointfree", () => { const $ = pf.ctx; @@ -532,7 +533,7 @@ describe("pointfree", () => { }); it("cases", () => { - let classify = (x) => + let classify = (x:any) => pf.cases({ 0: ["zero"], 1: ["one"], diff --git a/packages/pointfree/test/loop.ts b/packages/pointfree/test/loop.ts index 34a878c65a..ca522d39e0 100644 --- a/packages/pointfree/test/loop.ts +++ b/packages/pointfree/test/loop.ts @@ -1,5 +1,5 @@ import * as pf from "../src"; -import { StackProgram, StackFn } from "../src/api"; +import { StackFn, StackProgram } from "../src/api"; /** * This higher order word defines a 2D loop construct, executing a user @@ -14,11 +14,17 @@ import { StackProgram, StackFn } from "../src/api"; * @param bodyQ */ const loop2 = (i: number, j: number, bodyQ: StackProgram) => - pf.word([0, - pf.loop([pf.dup, i, pf.lt], [0, - pf.loop([pf.dup, j, pf.lt], [pf.dup2, ...bodyQ, pf.inc]), - pf.drop, - pf.inc]), + pf.word([ + 0, + pf.loop( + [pf.dup, i, pf.lt], + [ + 0, + pf.loop([pf.dup, j, pf.lt], [pf.dup2, ...bodyQ, pf.inc]), + pf.drop, + pf.inc + ] + ), pf.drop ]); @@ -34,7 +40,7 @@ const loop2 = (i: number, j: number, bodyQ: StackProgram) => * @param j inner size * @param body user quotation */ -const grid = (i, j, body: StackProgram = [pf.tuple(2)]) => +const grid = (i: number, j: number, body: StackProgram = [pf.tuple(2)]) => pf.word([loop2(i, j, [...body, pf.invrot]), pf.tuple(i * j)]); /** @@ -49,20 +55,30 @@ const grid = (i, j, body: StackProgram = [pf.tuple(2)]) => * @param id1 outer id gen * @param id2 inner id gen */ -const makeids = (i: number, j: number, sep: string, id1: StackFn = pf.nop, id2 = id1) => - grid(i, j, [id2, pf.swap, id1, pf.swap, pf.tuple(2), pf.join(sep)]); +const makeids = ( + i: number, + j: number, + sep: string, + id1: StackFn = pf.nop, + id2 = id1 +) => grid(i, j, [id2, pf.swap, id1, pf.swap, pf.tuple(2), pf.join(sep)]); // helper word which looks up TOS in given string/array/object, i.e. to // transform a number into another value (e.g. string) -const idgen = (ids) => pf.maptos((x) => ids[x]); +const idgen = (ids: any) => pf.maptos((x) => ids[x]); console.log(pf.runU(grid(4, 4))); console.log(pf.runU(makeids(4, 4, "", idgen("abcd")))); -console.log(pf.runU(makeids(4, 4, "-", idgen(["alpha", "beta", "gamma", "delta"]), pf.nop))); +console.log( + pf.runU( + makeids(4, 4, "-", idgen(["alpha", "beta", "gamma", "delta"]), pf.nop) + ) +); console.log( pf.runU([ makeids(4, 4, "", idgen("abcd")), - pf.maptos(id => pf.runU(makeids(4, 4, "/", idgen(id)))), - pf.maptos(id => pf.runU(makeids(4, 4, "-", idgen(id)))) - ])); \ No newline at end of file + pf.maptos((id) => pf.runU(makeids(4, 4, "/", idgen(id)))), + pf.maptos((id) => pf.runU(makeids(4, 4, "-", idgen(id)))) + ]) +); diff --git a/packages/poisson/CHANGELOG.md b/packages/poisson/CHANGELOG.md index d0232dc831..65fd50ab70 100644 --- a/packages/poisson/CHANGELOG.md +++ b/packages/poisson/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.2.17](https://github.com/thi-ng/umbrella/compare/@thi.ng/poisson@0.2.16...@thi.ng/poisson@0.2.17) (2019-07-07) + +**Note:** Version bump only for package @thi.ng/poisson + + + + + ## [0.2.16](https://github.com/thi-ng/umbrella/compare/@thi.ng/poisson@0.2.15...@thi.ng/poisson@0.2.16) (2019-05-22) **Note:** Version bump only for package @thi.ng/poisson diff --git a/packages/poisson/package.json b/packages/poisson/package.json index 44d3120361..d69c915daa 100644 --- a/packages/poisson/package.json +++ b/packages/poisson/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/poisson", - "version": "0.2.16", + "version": "0.2.17", "description": "nD Poisson-disc sampling w/ support for spatial density functions and custom PRNGs", "module": "./index.js", "main": "./lib/index.js", @@ -25,17 +25,17 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/checks": "^2.1.6", - "@thi.ng/geom-api": "^0.2.3", - "@thi.ng/random": "^1.1.7", - "@thi.ng/vectors": "^2.5.6" + "@thi.ng/checks": "^2.2.0", + "@thi.ng/geom-api": "^0.2.4", + "@thi.ng/random": "^1.1.8", + "@thi.ng/vectors": "^3.0.0" }, "keywords": [ "2d", diff --git a/packages/poisson/src/index.ts b/packages/poisson/src/index.ts index 5cf125d750..ab8c075ae1 100644 --- a/packages/poisson/src/index.ts +++ b/packages/poisson/src/index.ts @@ -74,13 +74,17 @@ export interface PoissonOpts { rnd?: IRandom; } -export const samplePoisson = (opts: Partial) => { - opts = { +/** + * + * @param opts + */ +export const samplePoisson = (_opts: PoissonOpts) => { + const opts = { rnd: SYSTEM, iter: 1, jitter: 1, quality: 500, - ...opts + ..._opts }; const { points, index, rnd, jitter, quality, density: _d } = opts; const density = isNumber(_d) ? () => _d : _d; diff --git a/packages/quad-edge/CHANGELOG.md b/packages/quad-edge/CHANGELOG.md index da7ec7dee4..641d183178 100644 --- a/packages/quad-edge/CHANGELOG.md +++ b/packages/quad-edge/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.2.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/quad-edge@0.1.4...@thi.ng/quad-edge@0.2.0) (2019-07-07) + + +### Features + +* **quad-edge:** enable TS strict compiler flags (refactor) ([5a6cec1](https://github.com/thi-ng/umbrella/commit/5a6cec1)) + + + + + ## [0.1.4](https://github.com/thi-ng/umbrella/compare/@thi.ng/quad-edge@0.1.3...@thi.ng/quad-edge@0.1.4) (2019-04-24) **Note:** Version bump only for package @thi.ng/quad-edge diff --git a/packages/quad-edge/package.json b/packages/quad-edge/package.json index 003f1f5395..156e2a4da6 100644 --- a/packages/quad-edge/package.json +++ b/packages/quad-edge/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/quad-edge", - "version": "0.1.4", + "version": "0.2.0", "description": "Quadedge data structure after Guibas & Stolfi", "module": "./index.js", "main": "./lib/index.js", @@ -25,11 +25,11 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "keywords": [ "dual", diff --git a/packages/quad-edge/src/index.ts b/packages/quad-edge/src/index.ts index 0a45d56372..9c23bf9ec3 100644 --- a/packages/quad-edge/src/index.ts +++ b/packages/quad-edge/src/index.ts @@ -50,7 +50,7 @@ export class Edge { id: number; parent: QuadEdge; - origin: T; + origin!: T; constructor(parent: QuadEdge, id: number) { this.parent = parent; @@ -60,7 +60,7 @@ export class Edge { /** * Next CCW edge from this edge's origin. */ - onext: Edge; + onext!: Edge; /** * Next CW edge from this edge's origin. diff --git a/packages/random/CHANGELOG.md b/packages/random/CHANGELOG.md index b9a50a47cf..e3bb38fa24 100644 --- a/packages/random/CHANGELOG.md +++ b/packages/random/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.8](https://github.com/thi-ng/umbrella/compare/@thi.ng/random@1.1.7...@thi.ng/random@1.1.8) (2019-07-07) + +**Note:** Version bump only for package @thi.ng/random + + + + + ## [1.1.7](https://github.com/thi-ng/umbrella/compare/@thi.ng/random@1.1.6...@thi.ng/random@1.1.7) (2019-05-22) **Note:** Version bump only for package @thi.ng/random diff --git a/packages/random/package.json b/packages/random/package.json index 9f518eedeb..6c3dbd757b 100644 --- a/packages/random/package.json +++ b/packages/random/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/random", - "version": "1.1.7", + "version": "1.1.8", "description": "Pseudo-random number generators w/ unified API", "module": "./index.js", "main": "./lib/index.js", @@ -25,14 +25,14 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/api": "^6.2.0" + "@thi.ng/api": "^6.3.0" }, "keywords": [ "ES6", diff --git a/packages/range-coder/CHANGELOG.md b/packages/range-coder/CHANGELOG.md index 7cc48fd6e1..39049246e9 100644 --- a/packages/range-coder/CHANGELOG.md +++ b/packages/range-coder/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.0.20](https://github.com/thi-ng/umbrella/compare/@thi.ng/range-coder@1.0.19...@thi.ng/range-coder@1.0.20) (2019-07-07) + +**Note:** Version bump only for package @thi.ng/range-coder + + + + + ## [1.0.19](https://github.com/thi-ng/umbrella/compare/@thi.ng/range-coder@1.0.18...@thi.ng/range-coder@1.0.19) (2019-05-22) **Note:** Version bump only for package @thi.ng/range-coder diff --git a/packages/range-coder/package.json b/packages/range-coder/package.json index f2ecbeac74..1990723982 100644 --- a/packages/range-coder/package.json +++ b/packages/range-coder/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/range-coder", - "version": "1.0.19", + "version": "1.0.20", "description": "Binary data range encoder / decoder", "module": "./index.js", "main": "./lib/index.js", @@ -24,16 +24,16 @@ "pub": "yarn build && yarn publish --access public" }, "devDependencies": { - "@thi.ng/transducers": "^5.3.7", + "@thi.ng/transducers": "^5.4.0", "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/bitstream": "^1.0.6" + "@thi.ng/bitstream": "^1.1.0" }, "keywords": [ "ES6", diff --git a/packages/range-coder/test/index.ts b/packages/range-coder/test/index.ts index 3709477bdd..6e50c8017f 100644 --- a/packages/range-coder/test/index.ts +++ b/packages/range-coder/test/index.ts @@ -3,24 +3,25 @@ import * as assert from "assert"; import { decodeBytes, encodeBytes } from "../src"; describe("range-coder", () => { - it("fixed", () => { const src = new Uint8Array([10, 20, 30, 10, 10, 10]); const dest = encodeBytes(src); - assert.deepEqual(dest, [10, 10, 224, 160, 49, 91, 88]); - assert.deepEqual(src, decodeBytes(dest)); + assert.deepEqual([...dest], [10, 10, 224, 160, 49, 91, 88]); + assert.deepEqual([...src], [...decodeBytes(dest)]); }); it("fuzz", () => { for (let i = 0; i < 10; i++) { const src = randomArray(640, 1024); const dest = encodeBytes(src); - console.log(`${(dest.length / src.length * 100).toFixed(2)}%`); - assert.deepEqual(src, decodeBytes(dest)); + console.log(`${((dest.length / src.length) * 100).toFixed(2)}%`); + assert.deepEqual([...src], [...decodeBytes(dest)]); } }); }); -const randomArray = - (n: number, len: number) => - new Uint8Array([...repeatedly(() => ~~(Math.random() * 256), n), ...repeat(0, len - n)]); +const randomArray = (n: number, len: number) => + new Uint8Array([ + ...repeatedly(() => ~~(Math.random() * 256), n), + ...repeat(0, len - n) + ]); diff --git a/packages/resolve-map/CHANGELOG.md b/packages/resolve-map/CHANGELOG.md index 3e5f87e10e..a51af696a5 100644 --- a/packages/resolve-map/CHANGELOG.md +++ b/packages/resolve-map/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [4.1.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/resolve-map@4.0.12...@thi.ng/resolve-map@4.1.0) (2019-07-07) + + +### Features + +* **resolve-map:** enable TS strict compiler flags (refactor) ([7e7ff2a](https://github.com/thi-ng/umbrella/commit/7e7ff2a)) + + + + + ## [4.0.12](https://github.com/thi-ng/umbrella/compare/@thi.ng/resolve-map@4.0.11...@thi.ng/resolve-map@4.0.12) (2019-05-22) **Note:** Version bump only for package @thi.ng/resolve-map diff --git a/packages/resolve-map/package.json b/packages/resolve-map/package.json index 950ec982f6..93793dfa9a 100644 --- a/packages/resolve-map/package.json +++ b/packages/resolve-map/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/resolve-map", - "version": "4.0.12", + "version": "4.1.0", "description": "DAG resolution of vanilla objects & arrays with internally linked values", "module": "./index.js", "main": "./lib/index.js", @@ -25,16 +25,16 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/api": "^6.2.0", - "@thi.ng/checks": "^2.1.6", - "@thi.ng/errors": "^1.0.6", - "@thi.ng/paths": "^2.0.9" + "@thi.ng/api": "^6.3.0", + "@thi.ng/checks": "^2.2.0", + "@thi.ng/errors": "^1.1.0", + "@thi.ng/paths": "^2.1.0" }, "keywords": [ "configuration", diff --git a/packages/resolve-map/src/index.ts b/packages/resolve-map/src/index.ts index 6e846cc5ba..bfd2e1186e 100644 --- a/packages/resolve-map/src/index.ts +++ b/packages/resolve-map/src/index.ts @@ -1,5 +1,10 @@ import { SEMAPHORE } from "@thi.ng/api"; -import { isArray, isFunction, isPlainObject, isString } from "@thi.ng/checks"; +import { + isArray, + isFunction, + isPlainObject, + isString +} from "@thi.ng/checks"; import { illegalArgs } from "@thi.ng/errors"; import { exists, getIn, mutIn } from "@thi.ng/paths"; @@ -208,7 +213,7 @@ const resolvePath = ( v = _resolve(root, path.slice(0, i), resolved, stack); } // restore - stack.push(pathID); + stack.push(pathID!); return v; }; @@ -242,7 +247,7 @@ const resolveFunction = ( .replace(/\s/g, "") .split(/,/g) .map((k) => k.split(":")[0]) - .reduce((acc, k) => ((acc[k] = resolve(k)), acc), {}); + .reduce((acc: any, k) => ((acc[k] = resolve(k)), acc), {}); res = fn(args, resolve); } else { res = fn(resolve); diff --git a/packages/resolve-map/test/index.ts b/packages/resolve-map/test/index.ts index 9212bf7525..f4c66b8915 100644 --- a/packages/resolve-map/test/index.ts +++ b/packages/resolve-map/test/index.ts @@ -1,44 +1,49 @@ import * as tx from "@thi.ng/transducers"; import * as assert from "assert"; +import { resolve, ResolveFn } from "../src/index"; -import { resolve } from "../src/index"; describe("resolve-map", () => { - it("simple", () => { - assert.deepEqual( - resolve({ a: 1, b: "@a" }), - { a: 1, b: 1 } - ); + assert.deepEqual(resolve({ a: 1, b: "@a" }), { a: 1, b: 1 }); }); it("linked refs", () => { - assert.deepEqual( - resolve({ a: "@c", b: "@a", c: 1 }), - { a: 1, b: 1, c: 1 } - ); + assert.deepEqual(resolve({ a: "@c", b: "@a", c: 1 }), { + a: 1, + b: 1, + c: 1 + }); }); it("array refs", () => { - assert.deepEqual( - resolve({ a: "@c/1", b: "@a", c: [1, 2] }), - { a: 2, b: 2, c: [1, 2] } - ); + assert.deepEqual(resolve({ a: "@c/1", b: "@a", c: [1, 2] }), { + a: 2, + b: 2, + c: [1, 2] + }); }); it("abs vs rel refs", () => { assert.deepEqual( - resolve({ a1: { b: 1, c: "@b" }, a2: { b: 2, c: "@b" }, a3: { b: 3, c: "@/a1/b" } }), + resolve({ + a1: { b: 1, c: "@b" }, + a2: { b: 2, c: "@b" }, + a3: { b: 3, c: "@/a1/b" } + }), { a1: { b: 1, c: 1 }, a2: { b: 2, c: 2 }, a3: { b: 3, c: 1 } } ); }); it("rel parent refs", () => { assert.deepEqual( - resolve({ a: { b: { c: "@../c/d", d: "@c", e: "@/c/d" }, c: { d: 1 } }, c: { d: 10 } }), + resolve({ + a: { b: { c: "@../c/d", d: "@c", e: "@/c/d" }, c: { d: 1 } }, + c: { d: 10 } + }), { a: { b: { c: 1, d: 1, e: 10 }, c: { d: 1 } }, c: { d: 10 } } ); - }) + }); it("cycles", () => { assert.throws(() => resolve({ a: "@a" })); @@ -50,10 +55,18 @@ describe("resolve-map", () => { it("function refs", () => { assert.deepEqual( - resolve({ a: (x) => x("b/c") * 10, b: { c: "@d", d: "@/e" }, e: () => 1 }), + resolve({ + a: (x: ResolveFn) => x("b/c") * 10, + b: { c: "@d", d: "@/e" }, + e: () => 1 + }), { a: 10, b: { c: 1, d: 1 }, e: 1 } ); - const res = resolve({ a: (x) => x("b/c")() * 10, b: { c: "@d", d: "@/e" }, e: () => () => 1 }); + const res = resolve({ + a: (x: ResolveFn) => x("b/c")() * 10, + b: { c: "@d", d: "@/e" }, + e: () => () => 1 + }); assert.equal(res.a, 10); assert.strictEqual(res.b.c, res.e); assert.strictEqual(res.b.d, res.e); @@ -63,7 +76,11 @@ describe("resolve-map", () => { it("function resolves only once", () => { let n = 0; assert.deepEqual( - resolve({ a: (x) => x("b/c"), b: { c: "@d", d: "@/e" }, e: () => (n++ , 1) }), + resolve({ + a: (x: ResolveFn) => x("b/c"), + b: { c: "@d", d: "@/e" }, + e: () => (n++, 1) + }), { a: 1, b: { c: 1, d: 1 }, e: 1 } ); assert.equal(n, 1); @@ -71,7 +88,11 @@ describe("resolve-map", () => { it("deep resolve of yet unknown refs", () => { assert.deepEqual( - resolve({ a: "@b/c/d", b: ($) => ({ c: { d: { e: $("/x") } } }), x: 1 }), + resolve({ + a: "@b/c/d", + b: ($: ResolveFn) => ({ c: { d: { e: $("/x") } } }), + x: 1 + }), { a: { e: 1 }, b: { c: { d: { e: 1 } } }, x: 1 } ); }); @@ -79,29 +100,38 @@ describe("resolve-map", () => { it("destructure", () => { const stats = { // sequence average - mean: ({ src: a }) => tx.mean(a), + mean: ({ src: a }: any) => tx.mean(a), // sequence range - range: ({ min, max }) => max - min, + range: ({ min, max }: any) => max - min, // computes sequence min val - min: ({ src }) => tx.min(src), + min: ({ src }: any) => tx.min(src), // computes sequence max val - max: ({ src }) => tx.max(src), + max: ({ src }: any) => tx.max(src), // sorted copy - sorted: ({ src }) => [...src].sort((a, b) => a - b), + sorted: ({ src }: any) => [...src].sort((a, b) => a - b), // standard deviation - sd: ({ src, mean }) => + sd: ({ src, mean }: any) => Math.sqrt( - tx.transduce(tx.map((x: number) => Math.pow(x - mean, 2)), tx.add(), src) / - (src.length - 1)), + tx.transduce( + tx.map((x: number) => Math.pow(x - mean, 2)), + tx.add(), + src + ) / + (src.length - 1) + ), // compute 10th - 90th percentiles - percentiles: ({ sorted }) => { + percentiles: ({ sorted }: any) => { return tx.transduce( - tx.map((x: number) => sorted[Math.floor(x / 100 * sorted.length)]), + tx.map( + (x: number) => + sorted[Math.floor((x / 100) * sorted.length)] + ), tx.push(), tx.range(10, 100, 5) ); } }; + // prettier-ignore assert.deepEqual( resolve({ ...stats, src: () => [1, 6, 7, 2, 4, 11, -3] }), { diff --git a/packages/rle-pack/CHANGELOG.md b/packages/rle-pack/CHANGELOG.md index d3b167fd36..c9838ca323 100644 --- a/packages/rle-pack/CHANGELOG.md +++ b/packages/rle-pack/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [2.1.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/rle-pack@2.0.6...@thi.ng/rle-pack@2.1.0) (2019-07-07) + + +### Features + +* **rle-pack:** enable TS strict compiler flags (refactor) ([17c426b](https://github.com/thi-ng/umbrella/commit/17c426b)) + + + + + ## [2.0.6](https://github.com/thi-ng/umbrella/compare/@thi.ng/rle-pack@2.0.5...@thi.ng/rle-pack@2.0.6) (2019-04-24) **Note:** Version bump only for package @thi.ng/rle-pack diff --git a/packages/rle-pack/package.json b/packages/rle-pack/package.json index 13c18ef742..9f7ef662b5 100644 --- a/packages/rle-pack/package.json +++ b/packages/rle-pack/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/rle-pack", - "version": "2.0.6", + "version": "2.1.0", "description": "Binary run-length encoding packer w/ flexible repeat bit widths", "module": "./index.js", "main": "./lib/index.js", @@ -25,16 +25,16 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "benchmark": "^2.1.4", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/bitstream": "^1.0.6", - "@thi.ng/errors": "^1.0.6" + "@thi.ng/bitstream": "^1.1.0", + "@thi.ng/errors": "^1.1.0" }, "keywords": [ "binary", diff --git a/packages/rle-pack/src/index.ts b/packages/rle-pack/src/index.ts index 8415084cb5..a806655859 100644 --- a/packages/rle-pack/src/index.ts +++ b/packages/rle-pack/src/index.ts @@ -30,7 +30,7 @@ export const encode = ( const [rle0, rle1, rle2, rle3] = rleSizes.map((x) => 1 << x); const chunk: number[] = []; const n1 = num - 1; - let val; + let val: number | undefined; let tail = true; let n = 0; let i = 0; @@ -39,7 +39,7 @@ export const encode = ( out.writeBit(1); out.write(t, 2); out.write(n, rleSizes[t]); - out.write(val, wordSize); + out.write(val!, wordSize); n = 0; }; const writeChunk = () => { @@ -80,7 +80,7 @@ export const encode = ( i++; } if (chunk.length) { - chunk.push(val); + chunk.push(val!); writeChunk(); } else if (tail) { writeRLE(); diff --git a/packages/rle-pack/test/index.ts b/packages/rle-pack/test/index.ts index e5a312165b..b0e4cbb4e8 100644 --- a/packages/rle-pack/test/index.ts +++ b/packages/rle-pack/test/index.ts @@ -1,17 +1,19 @@ import * as assert from "assert"; -import { encode, decode } from "../src/index"; - -const src1k = new Uint8Array(1024); -src1k.set([1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 4, 4, 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 1], 512); +import { decode, encode } from "../src/index"; +// prettier-ignore describe("rle-pack", () => { + + const src1k = new Uint8Array(1024); + src1k.set([1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 4, 4, 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 1], 512); + it("3bit", () => { let packed = encode(src1k, src1k.length, 3); - assert.deepEqual(packed, [0, 0, 4, 0, 17, 27, 255, 1, 255, 18, 24, 212, 78, 24, 5, 134, 68, 227, 82, 30, 3, 196, 0]); + assert.deepEqual([...packed], [0, 0, 4, 0, 17, 27, 255, 1, 255, 18, 24, 212, 78, 24, 5, 134, 68, 227, 82, 30, 3, 196, 0]); let dest = decode(packed); assert.deepEqual(dest, src1k); packed = encode(src1k, src1k.length, 3, [1, 2, 4, 9]); - assert.deepEqual(packed, [0, 0, 4, 0, 16, 9, 199, 255, 140, 134, 234, 206, 96, 89, 150, 119, 89, 15, 241, 0]); + assert.deepEqual([...packed], [0, 0, 4, 0, 16, 9, 199, 255, 140, 134, 234, 206, 96, 89, 150, 119, 89, 15, 241, 0]); dest = decode(packed); assert.deepEqual(dest, src1k); }); diff --git a/packages/router/CHANGELOG.md b/packages/router/CHANGELOG.md index aba5696eac..e885a2e714 100644 --- a/packages/router/CHANGELOG.md +++ b/packages/router/CHANGELOG.md @@ -3,6 +3,30 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [2.0.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/router@1.0.12...@thi.ng/router@2.0.0) (2019-07-07) + + +### Code Refactoring + +* **router:** address TS strictNullChecks, update types, add checks ([c7ff9a4](https://github.com/thi-ng/umbrella/commit/c7ff9a4)) + + +### Features + +* **router:** enable TS strict compiler flags (refactor) ([d3ecae3](https://github.com/thi-ng/umbrella/commit/d3ecae3)) + + +### BREAKING CHANGES + +* **router:** Route & RouteMatch IDs MUST be strings now + +- update config fields from PropertyKey => string +- add initial & default route checks in ctor + + + + + ## [1.0.12](https://github.com/thi-ng/umbrella/compare/@thi.ng/router@1.0.11...@thi.ng/router@1.0.12) (2019-05-22) **Note:** Version bump only for package @thi.ng/router diff --git a/packages/router/package.json b/packages/router/package.json index ddecd24d93..684397d86b 100644 --- a/packages/router/package.json +++ b/packages/router/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/router", - "version": "1.0.12", + "version": "2.0.0", "description": "Generic router for browser & non-browser based applications", "module": "./index.js", "main": "./lib/index.js", @@ -25,17 +25,17 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/api": "^6.2.0", - "@thi.ng/checks": "^2.1.6", - "@thi.ng/equiv": "^1.0.6", - "@thi.ng/errors": "^1.0.6" + "@thi.ng/api": "^6.3.0", + "@thi.ng/checks": "^2.2.0", + "@thi.ng/equiv": "^1.0.7", + "@thi.ng/errors": "^1.1.0" }, "keywords": [ "browser", diff --git a/packages/router/src/api.ts b/packages/router/src/api.ts index 1f8ee66c5d..c74cdbc5cb 100644 --- a/packages/router/src/api.ts +++ b/packages/router/src/api.ts @@ -38,7 +38,7 @@ export interface RouteParamValidator { * authentication. Apart from `id` and `match` all other fields * are optional. */ -export interface Route extends IID { +export interface Route extends IID { /** * Array of path components. If a value is prefixed with `?` this * path component will be captured under that name. E.g. @@ -93,7 +93,7 @@ export interface Route extends IID { * `EVENT_ROUTE_CHANGE`. Contains the matched route ID and any route * params. */ -export interface RouteMatch extends IID { +export interface RouteMatch extends IID { title?: string; /** @@ -116,12 +116,12 @@ export interface RouterConfig { * defined routes could be matched against user input, e.g. a home * or error page. */ - defaultRouteID: PropertyKey; + defaultRouteID: string; /** * Optional initial route to trigger when router starts. If given, * this MUST be a route without params. */ - initialRouteID?: PropertyKey; + initialRouteID?: string; /** * Optional route authentication function. See `RouteAuthenticator` * for further details. If no authenticator is given, all matched diff --git a/packages/router/src/basic.ts b/packages/router/src/basic.ts index 72a47479a9..bd908d9120 100644 --- a/packages/router/src/basic.ts +++ b/packages/router/src/basic.ts @@ -1,4 +1,11 @@ -import { Event, INotify, INotifyMixin, IObjectOf, Listener } from "@thi.ng/api"; +import { + assert, + Event, + INotify, + INotifyMixin, + IObjectOf, + Listener +} from "@thi.ng/api"; import { isString } from "@thi.ng/checks"; import { equiv } from "@thi.ng/equiv"; import { illegalArgs, illegalArity } from "@thi.ng/errors"; @@ -12,8 +19,8 @@ import { @INotifyMixin export class BasicRouter implements INotify { - public config: RouterConfig; - public current: RouteMatch; + config: RouterConfig; + current: RouteMatch | undefined; constructor(config: RouterConfig) { config.authenticator = @@ -26,20 +33,37 @@ export class BasicRouter implements INotify { config.prefix = config.prefix === undefined ? "/" : config.prefix; config.separator = config.separator || "/"; this.config = config; + assert( + this.routeForID(this.config.defaultRouteID) !== undefined, + `missing config for default route: '${this.config.defaultRouteID}'` + ); + if (config.initialRouteID) { + const route = this.routeForID(config.initialRouteID); + assert( + route !== undefined, + `missing config for initial route: ${ + this.config.initialRouteID + }` + ); + assert( + !isParametricRoute(route!), + "initial route MUST not be parametric" + ); + } } // mixin - public addListener(_: string, __: Listener, ___?: any) { + addListener(_: string, __: Listener, ___?: any) { return false; } - public removeListener(_: string, __: Listener, ___?: any) { + removeListener(_: string, __: Listener, ___?: any) { return false; } - public notify(_: Event) {} + notify(_: Event) {} start() { if (this.config.initialRouteID) { - const route = this.routeForID(this.config.initialRouteID); + const route = this.routeForID(this.config.initialRouteID)!; this.current = { id: route.id, title: route.title, params: {} }; this.notify({ id: EVENT_ROUTE_CHANGED, value: this.current }); } @@ -53,13 +77,13 @@ export class BasicRouter implements INotify { * * @param raw route path to match */ - route(src: string): RouteMatch { + route(src: string): RouteMatch | undefined { if (src.charAt(0) === "#") { src = src.substr(1); } - src = src.substr(this.config.prefix.length); + src = src.substr(this.config.prefix!.length); const routes = this.config.routes, - curr = src.split(this.config.separator); + curr = src.split(this.config.separator!); let match; for (let i = 0, n = routes.length; i < n; i++) { const route = routes[i], @@ -73,7 +97,7 @@ export class BasicRouter implements INotify { if (!this.handleRouteFailure()) { return; } - const route = this.routeForID(this.config.defaultRouteID); + const route = this.routeForID(this.config.defaultRouteID)!; match = { id: route.id, title: route.title, params: {} }; } if (!equiv(match, this.current)) { @@ -91,7 +115,7 @@ export class BasicRouter implements INotify { * @param params * @param hash if true, prepends `#` to results */ - format(id: PropertyKey, params?: any, hash?: boolean): string; + format(id: string, params?: any, hash?: boolean): string; format(match: Partial, hash?: boolean): string; format(...args: any[]) { let [id, params, hash] = args; @@ -114,37 +138,36 @@ export class BasicRouter implements INotify { default: illegalArity(args.length); } - const route = this.routeForID(match.id); + const route = this.routeForID(match!.id!); if (route) { - const params = match.params || {}; + const params = match!.params || {}; return ( (hash ? "#" : "") + this.config.prefix + route.match - .map( - (x) => - x.charAt(0) === "?" - ? (x = params[x.substr(1)]) != null - ? x - : "NULL" - : x + .map((x) => + x.charAt(0) === "?" + ? (x = params[x.substr(1)]) != null + ? x + : "NULL" + : x ) .join(this.config.separator) ); } else { - illegalArgs(`invalid route ID: ${match.id.toString()}`); + illegalArgs(`invalid route ID: ${match!.id!}`); } } - routeForID(id: PropertyKey) { + routeForID(id: string) { return this.config.routes.find((route) => route.id === id); } - protected matchRoute(curr: string[], route: Route): RouteMatch { + protected matchRoute(curr: string[], route: Route): RouteMatch | undefined { const match = route.match, n = match.length; if (curr.length === n) { - const params = {}; + const params: any = {}; for (let i = 0; i < n; i++) { const m = match[i]; if (m.charAt(0) === "?") { @@ -160,7 +183,7 @@ export class BasicRouter implements INotify { return; } return route.auth - ? this.config.authenticator(route, curr, params) + ? this.config.authenticator!(route, curr, params) : { id: route.id, title: route.title, params }; } } @@ -187,3 +210,6 @@ export class BasicRouter implements INotify { return true; } } + +const isParametricRoute = (route: Route) => + route.match.some((p) => p.charAt(0) === "?"); diff --git a/packages/router/src/history.ts b/packages/router/src/history.ts index 4c55c96d53..5ecb1c84ec 100644 --- a/packages/router/src/history.ts +++ b/packages/router/src/history.ts @@ -1,3 +1,4 @@ +import { Fn } from "@thi.ng/api"; import { isString } from "@thi.ng/checks"; import { equiv } from "@thi.ng/equiv"; import { illegalArity } from "@thi.ng/errors"; @@ -5,15 +6,16 @@ import { HTMLRouterConfig, RouteMatch, RouterConfig } from "./api"; import { BasicRouter } from "./basic"; export class HTMLRouter extends BasicRouter { - protected currentPath: string; - protected popHandler: EventListener; - protected hashHandler: EventListener; + protected currentPath!: string; + protected popHandler!: Fn; + protected hashHandler!: Fn; protected useFragment: boolean; protected ignoreHashChange: boolean; constructor(config: HTMLRouterConfig) { super(config); this.useFragment = config.useFragment !== false; + this.ignoreHashChange = false; } start() { @@ -22,7 +24,7 @@ export class HTMLRouter extends BasicRouter { window.addEventListener("hashchange", this.handleHashChange()); } if (this.config.initialRouteID) { - const route = this.routeForID(this.config.initialRouteID); + const route = this.routeForID(this.config.initialRouteID)!; this.route( this.format({ id: route.id, @@ -51,9 +53,9 @@ export class HTMLRouter extends BasicRouter { * @param pushState */ route(src: string, pushState = true) { - const old = this.current, - route = super.route(src); - if (!equiv(route, old)) { + const old = this.current; + const route = super.route(src); + if (route && !equiv(route, old)) { this.currentPath = this.format(route); if (pushState) { history.pushState( @@ -118,7 +120,7 @@ export class HTMLRouter extends BasicRouter { protected handleRouteFailure() { this.ignoreHashChange = true; location.hash = this.format({ - id: this.routeForID(this.config.defaultRouteID).id + id: this.routeForID(this.config.defaultRouteID)!.id }); this.ignoreHashChange = false; return true; diff --git a/packages/rstream-csp/CHANGELOG.md b/packages/rstream-csp/CHANGELOG.md index c051fe2679..63bfb70104 100644 --- a/packages/rstream-csp/CHANGELOG.md +++ b/packages/rstream-csp/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.0.27](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-csp@1.0.26...@thi.ng/rstream-csp@1.0.27) (2019-07-07) + +**Note:** Version bump only for package @thi.ng/rstream-csp + + + + + ## [1.0.26](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-csp@1.0.25...@thi.ng/rstream-csp@1.0.26) (2019-05-22) **Note:** Version bump only for package @thi.ng/rstream-csp diff --git a/packages/rstream-csp/package.json b/packages/rstream-csp/package.json index 3cb86c3429..ba4c9cc223 100644 --- a/packages/rstream-csp/package.json +++ b/packages/rstream-csp/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/rstream-csp", - "version": "1.0.26", + "version": "1.0.27", "description": "@thi.ng/csp bridge module for @thi.ng/rstream", "module": "./index.js", "main": "./lib/index.js", @@ -25,15 +25,15 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/csp": "^1.0.19", - "@thi.ng/rstream": "^2.4.4" + "@thi.ng/csp": "^1.1.0", + "@thi.ng/rstream": "^2.5.0" }, "keywords": [ "bridge", diff --git a/packages/rstream-csp/test/index.ts b/packages/rstream-csp/test/index.ts index 3d32dbcc45..637e9ba614 100644 --- a/packages/rstream-csp/test/index.ts +++ b/packages/rstream-csp/test/index.ts @@ -1,15 +1,14 @@ import * as csp from "@thi.ng/csp"; import * as rs from "@thi.ng/rstream"; import * as assert from "assert"; - import { fromChannel } from "../src/index"; -describe("fromChannel", function () { +describe("fromChannel", function() { it("receives all values", (done) => { let ch = csp.Channel.range(5); let src = fromChannel(ch); - let buf = []; + let buf: number[] = []; src.subscribe({ next(x) { buf.push(x); @@ -22,5 +21,4 @@ describe("fromChannel", function () { } }); }); - }); diff --git a/packages/rstream-dot/CHANGELOG.md b/packages/rstream-dot/CHANGELOG.md index f1afcbc263..140a74ffd0 100644 --- a/packages/rstream-dot/CHANGELOG.md +++ b/packages/rstream-dot/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.1.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-dot@1.0.26...@thi.ng/rstream-dot@1.1.0) (2019-07-07) + + +### Features + +* **rstream-dot:** enable TS strict compiler flags (refactor) ([acfe75e](https://github.com/thi-ng/umbrella/commit/acfe75e)) + + + + + ## [1.0.26](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-dot@1.0.25...@thi.ng/rstream-dot@1.0.26) (2019-05-22) **Note:** Version bump only for package @thi.ng/rstream-dot diff --git a/packages/rstream-dot/package.json b/packages/rstream-dot/package.json index adbe72c68d..197898e534 100644 --- a/packages/rstream-dot/package.json +++ b/packages/rstream-dot/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/rstream-dot", - "version": "1.0.26", + "version": "1.1.0", "description": "Graphviz DOT conversion of @thi.ng/rstream dataflow graph topologies", "module": "./index.js", "main": "./lib/index.js", @@ -25,14 +25,14 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/rstream": "^2.4.4" + "@thi.ng/rstream": "^2.5.0" }, "keywords": [ "conversion", diff --git a/packages/rstream-dot/src/api.ts b/packages/rstream-dot/src/api.ts index 52ec30f602..40f8d963dd 100644 --- a/packages/rstream-dot/src/api.ts +++ b/packages/rstream-dot/src/api.ts @@ -14,9 +14,9 @@ export type NodeType = export interface Node { id: number; label: string; - type: string; - xform: boolean; - body: string; + type?: string; + xform?: boolean; + body?: string; } export interface WalkState { diff --git a/packages/rstream-dot/src/index.ts b/packages/rstream-dot/src/index.ts index f87408bbe4..fb424e5e10 100644 --- a/packages/rstream-dot/src/index.ts +++ b/packages/rstream-dot/src/index.ts @@ -4,7 +4,12 @@ import { StreamMerge, StreamSync } from "@thi.ng/rstream"; -import { DotOpts, Node, WalkState } from "./api"; +import { + DotOpts, + Node, + NodeType, + WalkState +} from "./api"; export * from "./api"; @@ -32,7 +37,7 @@ const dotNode = (s: Node, opts: DotOpts) => { } res += `", color="`; res += - (s.type && opts.color[s.type.toLowerCase()]) || + (s.type && opts.color[s.type.toLowerCase()]) || (s.label === "" ? opts.color.noid : opts.color.default); return res + `"];`; }; @@ -73,7 +78,8 @@ export const walk = ( if (children) { walk(children, opts, state); for (let c of children) { - state.rels.push([desc, state.subs.get(c)]); + const childNode = state.subs.get(c); + childNode && state.rels.push([desc, childNode]); } } } diff --git a/packages/rstream-gestures/CHANGELOG.md b/packages/rstream-gestures/CHANGELOG.md index 148125fc2b..4ee70df36a 100644 --- a/packages/rstream-gestures/CHANGELOG.md +++ b/packages/rstream-gestures/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.2.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-gestures@1.1.4...@thi.ng/rstream-gestures@1.2.0) (2019-07-07) + + +### Features + +* **rstream-gestures:** enable TS strict compiler flags (refactor) ([412dd46](https://github.com/thi-ng/umbrella/commit/412dd46)) + + + + + ## [1.1.4](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-gestures@1.1.3...@thi.ng/rstream-gestures@1.1.4) (2019-05-22) **Note:** Version bump only for package @thi.ng/rstream-gestures diff --git a/packages/rstream-gestures/package.json b/packages/rstream-gestures/package.json index b0c375278a..3fde3a16ec 100644 --- a/packages/rstream-gestures/package.json +++ b/packages/rstream-gestures/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/rstream-gestures", - "version": "1.1.4", + "version": "1.2.0", "description": "Unified mouse, mouse wheel & single-touch event stream abstraction", "module": "./index.js", "main": "./lib/index.js", @@ -25,16 +25,16 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/api": "^6.2.0", - "@thi.ng/rstream": "^2.4.4", - "@thi.ng/transducers": "^5.3.7" + "@thi.ng/api": "^6.3.0", + "@thi.ng/rstream": "^2.5.0", + "@thi.ng/transducers": "^5.4.0" }, "keywords": [ "dataflow", diff --git a/packages/rstream-gestures/src/index.ts b/packages/rstream-gestures/src/index.ts index ded580cc44..f2c1dd48a7 100644 --- a/packages/rstream-gestures/src/index.ts +++ b/packages/rstream-gestures/src/index.ts @@ -1,5 +1,5 @@ import { IID } from "@thi.ng/api"; -import { fromEvent, merge, StreamMerge } from "@thi.ng/rstream"; +import { fromDOMEvent, merge, StreamMerge } from "@thi.ng/rstream"; import { map } from "@thi.ng/transducers"; export const enum GestureType { @@ -28,6 +28,8 @@ export interface GestureEvent { [1]: GestureInfo; } +type UIEvent = MouseEvent | TouchEvent | WheelEvent; + export interface GestureStreamOpts extends IID { /** * Event listener options (see standard `addEventListener()`) @@ -107,31 +109,29 @@ export interface GestureStreamOpts extends IID { */ export const gestureStream = ( el: HTMLElement, - opts?: Partial + _opts?: Partial ): StreamMerge => { - let isDown = false, - clickPos: number[]; + let isDown = false; + let clickPos: number[] | null = null; - opts = Object.assign( - { - id: "gestures", - zoom: 1, - absZoom: true, - minZoom: 0.25, - maxZoom: 4, - smooth: 1, - eventOpts: { capture: true }, - preventDefault: true, - local: true, - scale: false - }, - opts - ); + const opts = { + id: "gestures", + zoom: 1, + absZoom: true, + minZoom: 0.25, + maxZoom: 4, + smooth: 1, + eventOpts: { capture: true }, + preventDefault: true, + local: true, + scale: false, + ..._opts + }; let zoom = Math.min(Math.max(opts.zoom, opts.minZoom), opts.maxZoom); const dpr = window.devicePixelRatio || 1; - return merge({ + return merge({ id: opts.id, src: [ "mousedown", @@ -142,26 +142,27 @@ export const gestureStream = ( "touchend", "touchcancel", "wheel" - ].map((e) => fromEvent(el, e, opts.eventOpts)), - xform: map((e: MouseEvent | TouchEvent | WheelEvent) => { - let evt, type; + ].map((e) => fromDOMEvent(el, e, opts.eventOpts)), + xform: map((e) => { + let evt: { clientX: number; clientY: number }; + let type: any; opts.preventDefault && e.preventDefault(); if ((e).touches) { - type = { + type = ({ touchstart: GestureType.START, touchmove: GestureType.DRAG, touchend: GestureType.END, touchcancel: GestureType.END - }[e.type]; + })[e.type]; evt = (e).changedTouches[0]; } else { - type = { + type = ({ mousedown: GestureType.START, mousemove: isDown ? GestureType.DRAG : GestureType.MOVE, mouseup: GestureType.END, wheel: GestureType.ZOOM - }[e.type]; - evt = e; + })[e.type]; + evt = e; } const pos = [evt.clientX | 0, evt.clientY | 0]; if (opts.local) { @@ -184,8 +185,8 @@ export const gestureStream = ( clickPos = null; break; case GestureType.DRAG: - body.click = clickPos; - body.delta = [pos[0] - clickPos[0], pos[1] - clickPos[1]]; + body.click = clickPos!; + body.delta = [pos[0] - clickPos![0], pos[1] - clickPos![1]]; break; case GestureType.ZOOM: const zdelta = (e).deltaY * opts.smooth; diff --git a/packages/rstream-graph/CHANGELOG.md b/packages/rstream-graph/CHANGELOG.md index a25da4bb6e..b9e4555aa2 100644 --- a/packages/rstream-graph/CHANGELOG.md +++ b/packages/rstream-graph/CHANGELOG.md @@ -3,6 +3,18 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [3.1.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-graph@3.0.26...@thi.ng/rstream-graph@3.1.0) (2019-07-07) + + +### Features + +* **rstream-graph:** add opt reset arg to `node()` ([310f4d3](https://github.com/thi-ng/umbrella/commit/310f4d3)) +* **rstream-graph:** enable TS strict compiler flags (refactor) ([ace51f8](https://github.com/thi-ng/umbrella/commit/ace51f8)) + + + + + ## [3.0.26](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-graph@3.0.25...@thi.ng/rstream-graph@3.0.26) (2019-05-22) **Note:** Version bump only for package @thi.ng/rstream-graph diff --git a/packages/rstream-graph/package.json b/packages/rstream-graph/package.json index 82227da34a..c6bbef2ad2 100644 --- a/packages/rstream-graph/package.json +++ b/packages/rstream-graph/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/rstream-graph", - "version": "3.0.26", + "version": "3.1.0", "description": "Declarative dataflow graph construction for @thi.ng/rstream", "module": "./index.js", "main": "./lib/index.js", @@ -25,20 +25,20 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/api": "^6.2.0", - "@thi.ng/checks": "^2.1.6", - "@thi.ng/errors": "^1.0.6", - "@thi.ng/paths": "^2.0.9", - "@thi.ng/resolve-map": "^4.0.12", - "@thi.ng/rstream": "^2.4.4", - "@thi.ng/transducers": "^5.3.7" + "@thi.ng/api": "^6.3.0", + "@thi.ng/checks": "^2.2.0", + "@thi.ng/errors": "^1.1.0", + "@thi.ng/paths": "^2.1.0", + "@thi.ng/resolve-map": "^4.1.0", + "@thi.ng/rstream": "^2.5.0", + "@thi.ng/transducers": "^5.4.0" }, "keywords": [ "compute", diff --git a/packages/rstream-graph/src/api.ts b/packages/rstream-graph/src/api.ts index 3458e3e1aa..7a7fe2112d 100644 --- a/packages/rstream-graph/src/api.ts +++ b/packages/rstream-graph/src/api.ts @@ -102,8 +102,8 @@ export interface NodeSpec { export interface NodeInputSpec { id?: string; path?: Path; - stream?: string | ((resolve) => ISubscribable); - const?: any | ((resolve) => any); + stream?: string | ((resolve: ResolveFn) => ISubscribable); + const?: any | ((resolve: ResolveFn) => any); xform?: Transducer; } diff --git a/packages/rstream-graph/src/graph.ts b/packages/rstream-graph/src/graph.ts index d429902b85..e2e7a8c38e 100644 --- a/packages/rstream-graph/src/graph.ts +++ b/packages/rstream-graph/src/graph.ts @@ -133,7 +133,7 @@ const prepareNodeInputs = ( }; const prepareNodeOutputs = ( - outs: IObjectOf, + outs: IObjectOf | undefined, node: ISubscribable, state: IAtom, nodeID: string @@ -228,17 +228,23 @@ export const stop = (graph: Graph) => { * function will throw an error if `inputIDs` is given and the object of * inputs does not contain all of them. * + * If `reset` is true (default: false), the `xform` will only re-run + * when all inputs have produced new values. See thi.ng/rstream + * `StreamSync` for further reference. + * * @param xform * @param inputIDs + * @param reset */ export const node = ( xform: Transducer, any>, - inputIDs?: string[] + inputIDs?: string[], + reset = false ): NodeFactory => ( src: IObjectOf>, id: string ): StreamSync => ( - ensureInputs(src, inputIDs, id), sync({ src, xform, id }) + ensureInputs(src, inputIDs, id), sync({ src, xform, id, reset }) ); /** @@ -256,7 +262,7 @@ export const node1 = ( id: string ): ISubscribable => ( ensureInputs(src, [inputID], id), - xform ? src[inputID].subscribe(xform, id) : src[inputID].subscribe(null, id) + xform ? src[inputID].subscribe(xform, id) : src[inputID].subscribe({}, id) ); /** @@ -269,10 +275,10 @@ export const node1 = ( */ export const ensureInputs = ( src: IObjectOf>, - inputIDs: string[], + inputIDs: string[] | undefined, nodeID: string ) => { - if (inputIDs !== undefined) { + if (inputIDs) { const missing: string[] = []; for (let i of inputIDs) { !src[i] && missing.push(i); diff --git a/packages/rstream-graph/test/index.ts b/packages/rstream-graph/test/index.ts index 1fa9786f8b..6a28cf4045 100644 --- a/packages/rstream-graph/test/index.ts +++ b/packages/rstream-graph/test/index.ts @@ -6,7 +6,7 @@ import * as rsg from "../src"; describe("rstream-graph", () => { it("basic", (done) => { - const acc = []; + const acc: number[] = []; const state = new Atom({ a: 1, b: 2 }); const graph = rsg.initGraph(state, { foo: () => ({ @@ -37,7 +37,10 @@ describe("rstream-graph", () => { c: { stream: "/bar/node" } }, outs: { - baz: (n, id) => n.subscribe({ next: (x) => state.resetIn(["foo", id], x) }) + baz: (n, id) => + n.subscribe({ + next: (x) => state.resetIn(["foo", id], x) + }) } }, res: { @@ -55,7 +58,7 @@ describe("rstream-graph", () => { }, fn: rsg.node1(), outs: { - x: "res2.x", + x: "res2.x" } } }); @@ -64,10 +67,13 @@ describe("rstream-graph", () => { state.resetIn("a", 10); // console.log(graph); assert.deepEqual(acc, [600, 1200, 1800, 7200]); - assert.deepEqual( - state.deref(), - { a: 10, b: 2, foo: { baz: 7200 }, res: { x: 7200, x2: 14400 }, res2: { x: 7200 } } - ); + assert.deepEqual(state.deref(), { + a: 10, + b: 2, + foo: { baz: 7200 }, + res: { x: 7200, x2: 14400 }, + res2: { x: 7200 } + }); done(); }, 30); }); diff --git a/packages/rstream-log-file/CHANGELOG.md b/packages/rstream-log-file/CHANGELOG.md index f5203faabe..977fc60e81 100644 --- a/packages/rstream-log-file/CHANGELOG.md +++ b/packages/rstream-log-file/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.1.15](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-log-file@0.1.14...@thi.ng/rstream-log-file@0.1.15) (2019-07-07) + +**Note:** Version bump only for package @thi.ng/rstream-log-file + + + + + ## [0.1.14](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-log-file@0.1.13...@thi.ng/rstream-log-file@0.1.14) (2019-05-22) **Note:** Version bump only for package @thi.ng/rstream-log-file diff --git a/packages/rstream-log-file/package.json b/packages/rstream-log-file/package.json index 72f088b546..2f94c65a6e 100644 --- a/packages/rstream-log-file/package.json +++ b/packages/rstream-log-file/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/rstream-log-file", - "version": "0.1.14", + "version": "0.1.15", "description": "File output handler for structured, multilevel & hierarchical loggers based on @thi.ng/rstream", "module": "./index.js", "main": "./lib/index.js", @@ -25,14 +25,14 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/rstream": "^2.4.4" + "@thi.ng/rstream": "^2.5.0" }, "keywords": [ "append", diff --git a/packages/rstream-log/CHANGELOG.md b/packages/rstream-log/CHANGELOG.md index 98c8b990e7..eaa4dd8208 100644 --- a/packages/rstream-log/CHANGELOG.md +++ b/packages/rstream-log/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [3.1.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-log@3.0.14...@thi.ng/rstream-log@3.1.0) (2019-07-07) + + +### Features + +* **rstream-log:** add maskSecrets() format xform ([481a65d](https://github.com/thi-ng/umbrella/commit/481a65d)) + + + + + ## [3.0.14](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-log@3.0.13...@thi.ng/rstream-log@3.0.14) (2019-05-22) **Note:** Version bump only for package @thi.ng/rstream-log diff --git a/packages/rstream-log/package.json b/packages/rstream-log/package.json index 454f786aa0..f60e60a5e9 100644 --- a/packages/rstream-log/package.json +++ b/packages/rstream-log/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/rstream-log", - "version": "3.0.14", + "version": "3.1.0", "description": "Structured, multilevel & hierarchical loggers based on @thi.ng/rstream", "module": "./index.js", "main": "./lib/index.js", @@ -25,18 +25,18 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/api": "^6.2.0", - "@thi.ng/checks": "^2.1.6", - "@thi.ng/errors": "^1.0.6", - "@thi.ng/rstream": "^2.4.4", - "@thi.ng/transducers": "^5.3.7" + "@thi.ng/api": "^6.3.0", + "@thi.ng/checks": "^2.2.0", + "@thi.ng/errors": "^1.1.0", + "@thi.ng/rstream": "^2.5.0", + "@thi.ng/transducers": "^5.4.0" }, "keywords": [ "ES6", diff --git a/packages/rstream-log/src/xform/format.ts b/packages/rstream-log/src/xform/format.ts index 98ef541c8d..36c1f1b50f 100644 --- a/packages/rstream-log/src/xform/format.ts +++ b/packages/rstream-log/src/xform/format.ts @@ -17,10 +17,37 @@ export const formatString = ( bodyFmt = bodyFmt || ((x) => x.toString()); return map( ([level, id, time, ...body]) => - `[${LogLevel[level]}] ${id}: ${dtFmt(time)} ${bodyFmt(body)}` + `[${LogLevel[level]}] ${id}: ${dtFmt!(time)} ${bodyFmt!(body)}` ); }; +/** + * Takes an array of regex patterns and optional `mask` string. Returns + * transducer which replaces all found pattern occurrences with `mask`. + * Intended to be used in combination / after `formatString()` to avoid + * leaking of sensitive information via logged messages. + * + * + * ``` + * logger.transform( + * formatString(), + * maskSecrets([/(?<=[A-Z0-9_]\=)\w+/g]) + * ).subscribe( + * writeConsole() + * ); + * + * logger.info("logged in USER=toxi, using TOKEN=123456"); + * // [INFO] logger-0: logged in USER=****, using TOKEN=**** + * ``` + * + * @param patterns + * @param mask + */ +export const maskSecrets = (patterns: RegExp[], mask = "****") => + map((msg: string) => + patterns.reduce((acc, pat) => acc.replace(pat, mask), msg) + ); + export const formatObject = (): Transducer => map(([level, id, time, ...body]) => ({ level, id, time, body })); @@ -32,7 +59,7 @@ export const formatJSON = ( JSON.stringify({ id, level: LogLevel[level], - time: dtfmt(time), + time: dtfmt!(time), body }) ); diff --git a/packages/rstream-query/CHANGELOG.md b/packages/rstream-query/CHANGELOG.md index 0979976cb4..3f6c398d7d 100644 --- a/packages/rstream-query/CHANGELOG.md +++ b/packages/rstream-query/CHANGELOG.md @@ -3,6 +3,22 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.1.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-query@1.0.26...@thi.ng/rstream-query@1.1.0) (2019-07-07) + + +### Bug Fixes + +* **rstream-query:** disambiguate return generics for addPatternQuery() ([7ffe25d](https://github.com/thi-ng/umbrella/commit/7ffe25d)) + + +### Features + +* **rstream-query:** enable TS strict compiler flags (refactor) ([6d35b86](https://github.com/thi-ng/umbrella/commit/6d35b86)) + + + + + ## [1.0.26](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-query@1.0.25...@thi.ng/rstream-query@1.0.26) (2019-05-22) **Note:** Version bump only for package @thi.ng/rstream-query diff --git a/packages/rstream-query/package.json b/packages/rstream-query/package.json index 8c1aa601f9..0bc673ee27 100644 --- a/packages/rstream-query/package.json +++ b/packages/rstream-query/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/rstream-query", - "version": "1.0.26", + "version": "1.1.0", "description": "@thi.ng/rstream based triple store & reactive query engine", "module": "./index.js", "main": "./lib/index.js", @@ -25,21 +25,21 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/api": "^6.2.0", - "@thi.ng/associative": "^2.3.0", - "@thi.ng/checks": "^2.1.6", - "@thi.ng/equiv": "^1.0.6", - "@thi.ng/errors": "^1.0.6", - "@thi.ng/rstream": "^2.4.4", - "@thi.ng/rstream-dot": "^1.0.26", - "@thi.ng/transducers": "^5.3.7" + "@thi.ng/api": "^6.3.0", + "@thi.ng/associative": "^2.4.0", + "@thi.ng/checks": "^2.2.0", + "@thi.ng/equiv": "^1.0.7", + "@thi.ng/errors": "^1.1.0", + "@thi.ng/rstream": "^2.5.0", + "@thi.ng/rstream-dot": "^1.1.0", + "@thi.ng/transducers": "^5.4.0" }, "keywords": [ "dataflow", diff --git a/packages/rstream-query/src/convert.ts b/packages/rstream-query/src/convert.ts index db6125176d..e499865db8 100644 --- a/packages/rstream-query/src/convert.ts +++ b/packages/rstream-query/src/convert.ts @@ -1,14 +1,14 @@ import { isArray, isPlainObject } from "@thi.ng/checks"; -import { concat, pairs, mapcat } from "@thi.ng/transducers"; +import { concat, mapcat, pairs } from "@thi.ng/transducers"; let NEXT_ID = 0; -const mapBNode = (s: any, p: any, o: any) => { +const mapBNode = (s: any, p: any, o: any): IterableIterator => { const id = `__b${NEXT_ID++}__`; return concat([[s, p, id]], asTriples(o, id)); }; -const mapSubject = (subject: any) => ([p, o]) => { +const mapSubject = (subject: any) => ([p, o]: [any, any]) => { if (isArray(o)) { return mapcat( (o) => diff --git a/packages/rstream-query/src/pattern.ts b/packages/rstream-query/src/pattern.ts index 7734658da9..dff6081ec8 100644 --- a/packages/rstream-query/src/pattern.ts +++ b/packages/rstream-query/src/pattern.ts @@ -42,7 +42,7 @@ export const resolvePathPattern = ( [s, p, o]: PathPattern, maxLen = p.length ): [Pattern[], string[]] => { - const res = []; + const res: Pattern[] = []; const avars = [...repeatedly(autoQVar, maxLen - 1)]; for (let i = 0; i < maxLen; i++) { res.push([s, p[i % p.length], (s = avars[i])]); diff --git a/packages/rstream-query/src/qvar.ts b/packages/rstream-query/src/qvar.ts index a6edaeea90..b8f16915d0 100644 --- a/packages/rstream-query/src/qvar.ts +++ b/packages/rstream-query/src/qvar.ts @@ -31,9 +31,9 @@ export const qvarResolver = ( vs: boolean, vp: boolean, vo: boolean, - s, - p, - o + s: string, + p: string, + o: string ) => { const type = ((vs) << 2) | ((vp) << 1) | (vo); let ss: any = vs && qvarName(s); diff --git a/packages/rstream-query/src/store.ts b/packages/rstream-query/src/store.ts index d06dfb811a..0e44fdd1d3 100644 --- a/packages/rstream-query/src/store.ts +++ b/packages/rstream-query/src/store.ts @@ -1,4 +1,4 @@ -import { IObjectOf } from "@thi.ng/api"; +import { assert, IObjectOf } from "@thi.ng/api"; import { intersection, join } from "@thi.ng/associative"; import { equiv } from "@thi.ng/equiv"; import { illegalArgs } from "@thi.ng/errors"; @@ -143,16 +143,16 @@ export class TripleStore implements Iterable, IToDot { let o = this.indexO.get(t[2]); const id = this.findTriple(s, p, o, t); if (id === -1) return false; - s.delete(id); - !s.size && this.indexS.delete(t[0]); - p.delete(id); - !p.size && this.indexP.delete(t[1]); - o.delete(id); - !o.size && this.indexO.delete(t[2]); + s!.delete(id); + !s!.size && this.indexS.delete(t[0]); + p!.delete(id); + !p!.size && this.indexP.delete(t[1]); + o!.delete(id); + !o!.size && this.indexO.delete(t[2]); this.allIDs.delete(id); delete this.triples[id]; this.freeIDs.push(id); - this.broadcastTriple(s, p, o, t); + this.broadcastTriple(s!, p!, o!, t); return true; } @@ -189,13 +189,18 @@ export class TripleStore implements Iterable, IToDot { addPatternQuery( pattern: Pattern, id?: string, - emitTriples?: boolean - ): ISubscribable; + emitTriples?: false + ): ISubscribable; + addPatternQuery( + pattern: Pattern, + id?: string, + emitTriples?: true + ): ISubscribable; addPatternQuery(pattern: Pattern, id?: string, emitTriples = true) { - let results: ISubscribable; + let results: ISubscribable | undefined; const [s, p, o] = pattern; if (s == null && p == null && o == null) { - results = this.streamAll; + results = >this.streamAll; } else { const key = JSON.stringify(pattern); if (!(results = this.queries.get(key))) { @@ -215,7 +220,7 @@ export class TripleStore implements Iterable, IToDot { src = { s: qs, p: qp, o: qo }; xform = intersect3; } - results = sync({ + results = >sync({ id, src, xform, @@ -260,17 +265,17 @@ export class TripleStore implements Iterable, IToDot { illegalArgs("at least 1 query variable is required in pattern"); } id || (id = `query-${nextID()}`); - const query = >( + const query = >( this.addPatternQuery( [vs ? null : s, vp ? null : p, vo ? null : o], id + "-raw" ) ); return query.transform( - map((triples) => { + map((triples: Triples) => { const res = new Set(); for (let f of triples) { - res.add(resolve(f)); + res.add(resolve!(f)); } return res; }), @@ -339,7 +344,7 @@ export class TripleStore implements Iterable, IToDot { return sync({ id, src, - xform: >comp.apply(null, xforms) + xform: >comp.apply(null, xforms) }); } @@ -351,8 +356,8 @@ export class TripleStore implements Iterable, IToDot { * @param spec */ addQueryFromSpec(spec: QuerySpec): QuerySolution { - let query: QuerySolution; - let curr: QuerySolution; + let query: QuerySolution | undefined; + let curr: QuerySolution | undefined; for (let q of spec.q) { if (isWhereQuery(q)) { curr = this.addMultiJoin(this.addParamQueries(q.where)); @@ -363,6 +368,7 @@ export class TripleStore implements Iterable, IToDot { } query = curr; } + assert(!!query, "illegal query spec"); let xforms: Transducer[] = []; if (spec.limit) { xforms.push(limitSolutions(spec.limit)); @@ -375,10 +381,10 @@ export class TripleStore implements Iterable, IToDot { } if (xforms.length) { query = >( - query.subscribe(comp.apply(null, xforms)) + query!.subscribe(comp.apply(null, xforms)) ); } - return query; + return query!; } toDot(opts?: Partial) { @@ -393,7 +399,7 @@ export class TripleStore implements Iterable, IToDot { protected nextID() { if (this.freeIDs.length) { - return this.freeIDs.pop(); + return this.freeIDs.pop()!; } return this.NEXT_ID++; } @@ -410,7 +416,12 @@ export class TripleStore implements Iterable, IToDot { this.streamO.next({ index: o, key: t[2] }); } - protected findTriple(s: TripleIds, p: TripleIds, o: TripleIds, f: Triple) { + protected findTriple( + s: TripleIds | undefined, + p: TripleIds | undefined, + o: TripleIds | undefined, + f: Triple + ) { if (s && p && o) { const triples = this.triples; const index = diff --git a/packages/rstream-query/test/example.ts b/packages/rstream-query/test/example.ts index 7cf18581d1..0e1dff487c 100644 --- a/packages/rstream-query/test/example.ts +++ b/packages/rstream-query/test/example.ts @@ -9,7 +9,7 @@ const store = new q.TripleStore([ ["portland", "part-of", "usa"], ["oregon", "type", "state"], ["usa", "type", "country"], - ["uk", "type", "country"], + ["uk", "type", "country"] ]); // alternatively, convert an object into a sequence of triples @@ -36,39 +36,41 @@ const store = new q.TripleStore([ // currently only "where" and "path" sub-queries are possible // in the near future, more query types will be supported // (e.g. optional relationships, filters etc.) -store.addQueryFromSpec({ - q: [ - { - where: [ - // first match any subject of type "city" - ["?city", "type", "city"], - // then a city's "part-of" relationships (if any) - ["?city", "partOf", "?country"], - // the matched ?country must have type = "country" - ["?country", "type", "country"] - ] - } - ], - // `bind` is an (optional) query post-processor and - // allows injection of new variables into the result set - // here we create a new var "answer" whose values are derived from - // the other two query vars - bind: { - answer: (res) => `${res.city} is located in ${res.country}` - }, - // another post-processing step, only keeps "answer" var in results - select: ["answer"] -}).subscribe(trace()) +store + .addQueryFromSpec({ + q: [ + { + where: [ + // first match any subject of type "city" + ["?city", "type", "city"], + // then a city's "part-of" relationships (if any) + ["?city", "partOf", "?country"], + // the matched ?country must have type = "country" + ["?country", "type", "country"] + ] + } + ], + // `bind` is an (optional) query post-processor and + // allows injection of new variables into the result set + // here we create a new var "answer" whose values are derived from + // the other two query vars + bind: { + answer: (res) => `${res.city} is located in ${res.country}` + }, + // another post-processing step, only keeps "answer" var in results + select: ["answer"] + }) + .subscribe(trace()); // Set { // { answer: 'london is located in uk' }, // { answer: 'portland is located in usa' } } // helper fn to insert new city relationship to the store -const addCity = (name, country) => +const addCity = (name: string, country: string) => store.into([ [name, "type", "city"], [name, "partOf", country], - [country, "type", "country"], + [country, "type", "country"] ]); addCity("berlin", "germany"); @@ -92,4 +94,3 @@ store.delete(["paris", "type", "city"]); // output for graphviz // console.log(store.toDot()); - diff --git a/packages/rstream-query/test/index.ts b/packages/rstream-query/test/index.ts index 27062ebc4a..9ed6240563 100644 --- a/packages/rstream-query/test/index.ts +++ b/packages/rstream-query/test/index.ts @@ -1,15 +1,14 @@ import * as assert from "assert"; -import { TripleStore, Triple } from "../src/index"; +import { Triple, TripleIds, TripleStore } from "../src/index"; describe("rstream-query", () => { - const triples: Triple[] = [ ["a", "type", "foo"], // 0 ["b", "type", "bar"], // 1 ["c", "type", "baz"], // 2 - ["a", "value", 0], // 3 - ["b", "value", 1], // 4 - ["c", "friend", "a"], // 5 + ["a", "value", 0], // 3 + ["b", "value", 1], // 4 + ["c", "friend", "a"] // 5 ]; let store: TripleStore; @@ -19,86 +18,122 @@ describe("rstream-query", () => { }); it("pattern query (S)", () => { - const res = []; - store.addPatternQuery(["a", null, null], "q", false).subscribe({ next: (r) => res.push(r) }); + const res: TripleIds[] = []; + store + .addPatternQuery(["a", null, null], "q", false) + .subscribe({ next: (r) => res.push(r) }); assert.deepEqual(res, [new Set([0, 3])]); }); it("pattern query (P)", () => { - const res = []; - store.addPatternQuery([null, "type", null], "q", false).subscribe({ next: (r) => res.push(r) }); + const res: TripleIds[] = []; + store + .addPatternQuery([null, "type", null], "q", false) + .subscribe({ next: (r) => res.push(r) }); assert.deepEqual(res, [new Set([0, 1, 2])]); }); it("pattern query (O)", () => { - const res = []; - store.addPatternQuery([null, null, "a"], "q", false).subscribe({ next: (r) => res.push(r) }); + const res: TripleIds[] = []; + store + .addPatternQuery([null, null, "a"], "q", false) + .subscribe({ next: (r) => res.push(r) }); assert.deepEqual(res, [new Set([5])]); }); it("pattern query (SP)", () => { - const res = []; - store.addPatternQuery(["a", "value", null], "q", false).subscribe({ next: (r) => res.push(r) }); + const res: TripleIds[] = []; + store + .addPatternQuery(["a", "value", null], "q", false) + .subscribe({ next: (r) => res.push(r) }); assert.deepEqual(res, [new Set([3])]); }); it("pattern query (PO)", () => { - const res = []; - store.addPatternQuery([null, "value", 0], "q", false).subscribe({ next: (r) => res.push(r) }); + const res: TripleIds[] = []; + store + .addPatternQuery([null, "value", 0], "q", false) + .subscribe({ next: (r) => res.push(r) }); assert.deepEqual(res, [new Set([3])]); }); it("pattern query (SO)", () => { - const res = []; - store.addPatternQuery(["b", null, "bar"], "q", false).subscribe({ next: (r) => res.push(r) }); + const res: TripleIds[] = []; + store + .addPatternQuery(["b", null, "bar"], "q", false) + .subscribe({ next: (r) => res.push(r) }); assert.deepEqual(res, [new Set([1])]); }); it("pattern query (SPO)", () => { - const res = []; - store.addPatternQuery(["c", "type", "baz"], "q", false).subscribe({ next: (r) => res.push(r) }); + const res: TripleIds[] = []; + store + .addPatternQuery(["c", "type", "baz"], "q", false) + .subscribe({ next: (r) => res.push(r) }); assert.deepEqual(res, [new Set([2])]); }); it("pattern query (all)", () => { - const res = []; - store.addPatternQuery([null, null, null], "q", false).subscribe({ next: (r) => res.push(r) }); + const res: TripleIds[] = []; + store + .addPatternQuery([null, null, null], "q", false) + .subscribe({ next: (r) => res.push(r) }); assert.deepEqual(res, [new Set([0, 1, 2, 3, 4, 5])]); }); it("param query (S)", () => { - const res = []; - store.addParamQuery(["a", "?p", "?o"]).subscribe({ next: (r) => res.push(r) }); - assert.deepEqual(res, [new Set([{ p: "type", o: "foo" }, { p: "value", o: 0 }])]); + const res: Set[] = []; + store + .addParamQuery(["a", "?p", "?o"]) + .subscribe({ next: (r) => res.push(r) }); + assert.deepEqual(res, [ + new Set([{ p: "type", o: "foo" }, { p: "value", o: 0 }]) + ]); }); it("param query (P)", () => { - const res = []; - store.addParamQuery(["?s", "type", "?o"]).subscribe({ next: (r) => res.push(r) }); - assert.deepEqual(res, [new Set([{ s: "a", o: "foo" }, { s: "b", o: "bar" }, { s: "c", o: "baz" }])]); + const res: Set[] = []; + store + .addParamQuery(["?s", "type", "?o"]) + .subscribe({ next: (r) => res.push(r) }); + assert.deepEqual(res, [ + new Set([ + { s: "a", o: "foo" }, + { s: "b", o: "bar" }, + { s: "c", o: "baz" } + ]) + ]); }); it("param query (O)", () => { - const res = []; - store.addParamQuery(["?s", "?p", "a"]).subscribe({ next: (r) => res.push(r) }); + const res: Set[] = []; + store + .addParamQuery(["?s", "?p", "a"]) + .subscribe({ next: (r) => res.push(r) }); assert.deepEqual(res, [new Set([{ s: "c", p: "friend" }])]); }); it("param query (SP)", () => { - const res = []; - store.addParamQuery(["a", "value", "?o"]).subscribe({ next: (r) => res.push(r) }); + const res: Set[] = []; + store + .addParamQuery(["a", "value", "?o"]) + .subscribe({ next: (r) => res.push(r) }); assert.deepEqual(res, [new Set([{ o: 0 }])]); }); it("param query (PO)", () => { - const res = []; - store.addParamQuery(["?s", "value", 0]).subscribe({ next: (r) => res.push(r) }); + const res: Set[] = []; + store + .addParamQuery(["?s", "value", 0]) + .subscribe({ next: (r) => res.push(r) }); assert.deepEqual(res, [new Set([{ s: "a" }])]); }); it("param query (SO)", () => { - const res = []; - store.addParamQuery(["b", "?p", "bar"]).subscribe({ next: (r) => res.push(r) }); + const res: Set[] = []; + store + .addParamQuery(["b", "?p", "bar"]) + .subscribe({ next: (r) => res.push(r) }); assert.deepEqual(res, [new Set([{ p: "type" }])]); }); @@ -107,15 +142,19 @@ describe("rstream-query", () => { }); it("param query (all)", () => { - const res = []; - store.addParamQuery(["?s", "?p", "?o"]).subscribe({ next: (r) => res.push(r) }); - assert.deepEqual(res, [new Set([ - { s: "a", p: "type", o: "foo" }, - { s: "b", p: "type", o: "bar" }, - { s: "c", p: "type", o: "baz" }, - { s: "a", p: "value", o: 0 }, - { s: "b", p: "value", o: 1 }, - { s: "c", p: "friend", o: "a" }, - ])]); + const res: Set[] = []; + store + .addParamQuery(["?s", "?p", "?o"]) + .subscribe({ next: (r) => res.push(r) }); + assert.deepEqual(res, [ + new Set([ + { s: "a", p: "type", o: "foo" }, + { s: "b", p: "type", o: "bar" }, + { s: "c", p: "type", o: "baz" }, + { s: "a", p: "value", o: 0 }, + { s: "b", p: "value", o: 1 }, + { s: "c", p: "friend", o: "a" } + ]) + ]); }); }); diff --git a/packages/rstream/CHANGELOG.md b/packages/rstream/CHANGELOG.md index 13eef121d6..546dc7d5f8 100644 --- a/packages/rstream/CHANGELOG.md +++ b/packages/rstream/CHANGELOG.md @@ -3,6 +3,24 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [2.5.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream@2.4.4...@thi.ng/rstream@2.5.0) (2019-07-07) + + +### Bug Fixes + +* **rstream:** generics & type hints (TS 3.5.2) ([eb2e18a](https://github.com/thi-ng/umbrella/commit/eb2e18a)) +* **rstream:** TS strictNullChecks, add assertions ([1aad856](https://github.com/thi-ng/umbrella/commit/1aad856)) + + +### Features + +* **rstream:** add fromDOMEvent() ([6e3fec8](https://github.com/thi-ng/umbrella/commit/6e3fec8)) +* **rstream:** enable TS strict compiler flags (refactor) ([d796e21](https://github.com/thi-ng/umbrella/commit/d796e21)) + + + + + ## [2.4.4](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream@2.4.3...@thi.ng/rstream@2.4.4) (2019-05-22) **Note:** Version bump only for package @thi.ng/rstream diff --git a/packages/rstream/package.json b/packages/rstream/package.json index f55aca1340..87ad9e7bb1 100644 --- a/packages/rstream/package.json +++ b/packages/rstream/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/rstream", - "version": "2.4.4", + "version": "2.5.0", "description": "Reactive multi-tap streams, dataflow & transformation pipeline constructs", "module": "./index.js", "main": "./lib/index.js", @@ -25,20 +25,20 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/api": "^6.2.0", - "@thi.ng/associative": "^2.3.0", - "@thi.ng/atom": "^2.0.12", - "@thi.ng/checks": "^2.1.6", - "@thi.ng/errors": "^1.0.6", - "@thi.ng/paths": "^2.0.9", - "@thi.ng/transducers": "^5.3.7" + "@thi.ng/api": "^6.3.0", + "@thi.ng/associative": "^2.4.0", + "@thi.ng/atom": "^3.0.0", + "@thi.ng/checks": "^2.2.0", + "@thi.ng/errors": "^1.1.0", + "@thi.ng/paths": "^2.1.0", + "@thi.ng/transducers": "^5.4.0" }, "keywords": [ "datastructure", diff --git a/packages/rstream/src/from/atom.ts b/packages/rstream/src/from/atom.ts index fe6b3b1611..e269da0c08 100644 --- a/packages/rstream/src/from/atom.ts +++ b/packages/rstream/src/from/atom.ts @@ -41,7 +41,7 @@ export const fromAtom = ( new Stream((stream) => { changed = changed || ((a, b) => a !== b); atom.addWatch(stream.id, (_, prev, curr) => { - if (changed(prev, curr)) { + if (changed!(prev, curr)) { stream.next(curr); } }); diff --git a/packages/rstream/src/from/event.ts b/packages/rstream/src/from/event.ts index 137f8ffe48..524ac5c5e4 100644 --- a/packages/rstream/src/from/event.ts +++ b/packages/rstream/src/from/event.ts @@ -2,7 +2,7 @@ import { Stream } from "../stream"; import { nextID } from "../utils/idgen"; /** - * Creates a new stream of DOM events attached to given element / event + * Creates a new stream of events attached to given element / event * target and using given event listener options (same as supported by * `addEventListener()`, default: false). * @@ -16,7 +16,28 @@ export const fromEvent = ( opts: boolean | AddEventListenerOptions = false ) => new Stream((stream) => { - let listener = (e) => stream.next(e); + let listener = (e: Event) => stream.next(e); src.addEventListener(name, listener, opts); return () => src.removeEventListener(name, listener, opts); }, `event-${name}-${nextID()}`); + +/** + * Same as `fromEvent`, however only supports well-known DOM event + * names. Returned stream instance will use corresponding concrete event + * type in its type signature, whereas `fromEvent` will only use the + * generic `Event`. + * + * ``` + * fromDOMEvent(document.body, "mousemove"); // Stream + * fromEvent(document.body, "mousemove"); // Stream + * ``` + * + * @param src + * @param name + * @param opts + */ +export const fromDOMEvent = ( + src: EventTarget, + name: K, + opts: boolean | AddEventListenerOptions = false +): Stream => fromEvent(src, name, opts); diff --git a/packages/rstream/src/from/iterable.ts b/packages/rstream/src/from/iterable.ts index d8b095637e..71a351b531 100644 --- a/packages/rstream/src/from/iterable.ts +++ b/packages/rstream/src/from/iterable.ts @@ -44,5 +44,4 @@ export const fromIterableSync = (src: Iterable, close = true) => stream.next(s); } close && stream.done(); - return null; }, `iterable-${nextID()}`); diff --git a/packages/rstream/src/from/worker.ts b/packages/rstream/src/from/worker.ts index d157fca476..e4792b0aa9 100644 --- a/packages/rstream/src/from/worker.ts +++ b/packages/rstream/src/from/worker.ts @@ -37,10 +37,10 @@ export const fromWorker = ( stream.error(e.data); }; _worker.addEventListener("message", ml); - _worker.addEventListener("error", el); + _worker.addEventListener("error", el); return () => { _worker.removeEventListener("message", ml); - _worker.removeEventListener("error", el); + _worker.removeEventListener("error", el); if (terminate) { LOGGER.info("terminating worker", _worker); _worker.terminate(); diff --git a/packages/rstream/src/metastream.ts b/packages/rstream/src/metastream.ts index 2f24714bc5..1a5d2fc3e8 100644 --- a/packages/rstream/src/metastream.ts +++ b/packages/rstream/src/metastream.ts @@ -1,4 +1,4 @@ -import { Fn } from "@thi.ng/api"; +import { assert, Fn } from "@thi.ng/api"; import { State } from "./api"; import { Subscription } from "./subscription"; import { nextID } from "./utils/idgen"; @@ -78,11 +78,11 @@ export const metaStream = ( export class MetaStream extends Subscription { factory: Fn>; - stream: Subscription; - sub: Subscription; + stream?: Subscription; + sub?: Subscription; constructor(factory: Fn>, id?: string) { - super(null, null, null, id || `metastram-${nextID()}`); + super(undefined, undefined, undefined, id || `metastram-${nextID()}`); this.factory = factory; } @@ -99,10 +99,10 @@ export class MetaStream extends Subscription { stream === this.stream && super.dispatch(x); }, done: () => { - this.stream.unsubscribe(this.sub); + this.stream!.unsubscribe(this.sub); if (stream === this.stream) { - this.stream = null; - this.sub = null; + this.stream = undefined; + this.sub = undefined; } }, error: (e) => super.error(e), @@ -127,7 +127,8 @@ export class MetaStream extends Subscription { } protected detach() { - this.stream.unsubscribe(this.sub); + assert(!!this.stream, "input stream already removed"); + this.stream!.unsubscribe(this.sub); delete this.stream; delete this.sub; } diff --git a/packages/rstream/src/pubsub.ts b/packages/rstream/src/pubsub.ts index 77cd614b5f..400c9fd86f 100644 --- a/packages/rstream/src/pubsub.ts +++ b/packages/rstream/src/pubsub.ts @@ -55,9 +55,14 @@ export class PubSub extends Subscription { constructor(opts?: PubSubOpts) { opts = opts || >{}; - super(null, opts.xform, null, opts.id || `pubsub-${nextID()}`); + super( + undefined, + opts.xform, + undefined, + opts.id || `pubsub-${nextID()}` + ); this.topicfn = opts.topic; - this.topics = new EquivMap>(null, { + this.topics = new EquivMap>(undefined, { equiv: opts.equiv }); } @@ -66,16 +71,14 @@ export class PubSub extends Subscription { * Unsupported. Use `subscribeTopic()` instead. */ subscribe(): Subscription { - unsupported(`use subscribeTopic() instead`); - return null; + return unsupported(`use subscribeTopic() instead`); } /** * Unsupported. Use `subscribeTopic()` instead. */ transform(): Subscription { - unsupported(`use subscribeTopic() instead`); - return null; + return unsupported(`use subscribeTopic() instead`); } subscribeTopic( @@ -121,7 +124,7 @@ export class PubSub extends Subscription { this.topics.clear(); return super.unsubscribe(); } - unsupported(); + return unsupported(); } done() { diff --git a/packages/rstream/src/stream-merge.ts b/packages/rstream/src/stream-merge.ts index 2fc7df52c5..dfd9cb46c7 100644 --- a/packages/rstream/src/stream-merge.ts +++ b/packages/rstream/src/stream-merge.ts @@ -88,7 +88,12 @@ export class StreamMerge extends Subscription { constructor(opts?: Partial>) { opts = opts || {}; - super(null, opts.xform, null, opts.id || `streammerge-${nextID()}`); + super( + undefined, + opts.xform, + undefined, + opts.id || `streammerge-${nextID()}` + ); this.sources = new Map(); this.closeMode = closeMode(opts.close); if (opts.src) { diff --git a/packages/rstream/src/stream-sync.ts b/packages/rstream/src/stream-sync.ts index 3e26d38374..c5bf9ca566 100644 --- a/packages/rstream/src/stream-sync.ts +++ b/packages/rstream/src/stream-sync.ts @@ -137,8 +137,8 @@ export class StreamSync extends Subscription { constructor(opts: Partial>) { let srcIDs = new Set(); - let xform: Transducer = comp( - partitionSync(srcIDs, { + let xform: Transducer<[string, A], any> = comp( + partitionSync(srcIDs, { key: (x) => x[0], mergeOnly: opts.mergeOnly === true, reset: opts.reset === true, @@ -149,7 +149,12 @@ export class StreamSync extends Subscription { if (opts.xform) { xform = comp(xform, opts.xform); } - super(null, xform, null, opts.id || `streamsync-${nextID()}`); + super( + undefined, + >xform, + undefined, + opts.id || `streamsync-${nextID()}` + ); this.sources = new Map(); this.realSourceIDs = new Map(); this.invRealSourceIDs = new Map(); @@ -172,7 +177,7 @@ export class StreamSync extends Subscription { src, src.subscribe( { - next: (x) => { + next: (x: any) => { if (x[1] instanceof Subscription) { this.add(x[1]); } else { @@ -195,7 +200,7 @@ export class StreamSync extends Subscription { this.sourceIDs.add(id); } for (let id in src) { - this.add(src[id], id); + this.add((src)[id], id); } } else { // pre-add all source ids for partitionSync @@ -211,7 +216,7 @@ export class StreamSync extends Subscription { remove(src: ISubscribable) { const sub = this.sources.get(src); if (sub) { - const id = this.invRealSourceIDs.get(src.id); + const id = this.invRealSourceIDs.get(src.id)!; LOGGER.info(`removing src: ${src.id} (${id})`); this.sourceIDs.delete(id); this.realSourceIDs.delete(id); @@ -234,7 +239,7 @@ export class StreamSync extends Subscription { removeAll(src: ISubscribable[]) { // pre-remove all source ids for partitionSync for (let s of src) { - this.sourceIDs.delete(this.invRealSourceIDs.get(s.id)); + this.sourceIDs.delete(this.invRealSourceIDs.get(s.id)!); } let ok = true; for (let s of src) { @@ -252,13 +257,13 @@ export class StreamSync extends Subscription { } getSourceForID(id: string) { - return this.idSources.get(this.realSourceIDs.get(id)); + return this.idSources.get(this.realSourceIDs.get(id)!); } getSources() { - const res = {}; + const res: IObjectOf> = {}; for (let [id, src] of this.idSources) { - res[this.invRealSourceIDs.get(id)] = src; + res[this.invRealSourceIDs.get(id)!] = src; } return res; } diff --git a/packages/rstream/src/stream.ts b/packages/rstream/src/stream.ts index 3617e61ca1..538aeeef53 100644 --- a/packages/rstream/src/stream.ts +++ b/packages/rstream/src/stream.ts @@ -62,16 +62,16 @@ import { nextID } from "./utils/idgen"; */ export function stream(): Stream; export function stream(id: string): Stream; -export function stream(src: StreamSource); -export function stream(src: StreamSource, id: string); -export function stream(src?, id?) { - return new Stream(src, id); +export function stream(src: StreamSource): Stream; +export function stream(src: StreamSource, id: string): Stream; +export function stream(src?: any, id?: string) { + return new Stream(src, id!); } export class Stream extends Subscription implements IStream { src: StreamSource; - protected _cancel: StreamCancel; + protected _cancel: StreamCancel | undefined; constructor(); constructor(id: string); @@ -95,7 +95,7 @@ export class Stream extends Subscription implements IStream { default: illegalArity(args.length); } - super(null, null, null, id || `stream-${nextID()}`); + super(undefined, undefined, undefined, id || `stream-${nextID()}`); this.src = src; } @@ -109,7 +109,7 @@ export class Stream extends Subscription implements IStream { subscribe(xform: Transducer, id?: string): Subscription; subscribe(sub: Partial>, id?: string): Subscription; subscribe(...args: any[]) { - const wrapped = super.subscribe.apply(this, args); + const wrapped = super.subscribe.apply(this, args); if (this.subs.length === 1) { this._cancel = (this.src && this.src(this)) || (() => void 0); } diff --git a/packages/rstream/src/subs/bisect.ts b/packages/rstream/src/subs/bisect.ts index a3e7068fdf..f2d98e2bc8 100644 --- a/packages/rstream/src/subs/bisect.ts +++ b/packages/rstream/src/subs/bisect.ts @@ -49,7 +49,7 @@ export const bisect = ( b?: ISubscriber ): PubSub => { const sub = new PubSub({ topic: pred }); - sub.subscribeTopic(true, a); - sub.subscribeTopic(false, b); + a && sub.subscribeTopic(true, a); + b && sub.subscribeTopic(false, b); return sub; }; diff --git a/packages/rstream/src/subs/post-worker.ts b/packages/rstream/src/subs/post-worker.ts index 7a924dac9e..a6e50f38d6 100644 --- a/packages/rstream/src/subs/post-worker.ts +++ b/packages/rstream/src/subs/post-worker.ts @@ -52,7 +52,7 @@ export const postWorker = ( tx = [ta ? (x).buffer : x]; } } - _worker.postMessage(x, tx); + _worker.postMessage(x, tx || []); }, done() { if (terminate > 0) { diff --git a/packages/rstream/src/subs/resolve.ts b/packages/rstream/src/subs/resolve.ts index 08453a2397..80d8cef1db 100644 --- a/packages/rstream/src/subs/resolve.ts +++ b/packages/rstream/src/subs/resolve.ts @@ -35,10 +35,15 @@ export const resolve = (opts?: Partial) => export class Resolver extends Subscription, T> { protected outstanding = 0; - protected fail: Fn; + protected fail?: Fn; constructor(opts: Partial = {}) { - super(null, null, null, opts.id || `resolve-${nextID()}`); + super( + undefined, + undefined, + undefined, + opts.id || `resolve-${nextID()}` + ); this.fail = opts.fail; } @@ -66,7 +71,7 @@ export class Resolver extends Subscription, T> { } done() { - if (this.parent.getState() === State.DONE && this.outstanding === 0) { + if (this.parent!.getState() === State.DONE && this.outstanding === 0) { super.done(); } } diff --git a/packages/rstream/src/subs/sidechain-partition.ts b/packages/rstream/src/subs/sidechain-partition.ts index bf9e95eba0..76cabb05ee 100644 --- a/packages/rstream/src/subs/sidechain-partition.ts +++ b/packages/rstream/src/subs/sidechain-partition.ts @@ -38,13 +38,13 @@ export class SidechainPartition extends Subscription { buf: A[]; constructor(side: ISubscribable, pred?: Predicate, id?: string) { - super(null, null, null, id || `sidepart-${nextID()}`); + super(undefined, undefined, undefined, id || `sidepart-${nextID()}`); this.buf = []; const $this = this; pred = pred || (() => true); this.sideSub = side.subscribe({ next(x) { - if ($this.buf.length && pred(x)) { + if ($this.buf.length && pred!(x)) { $this.dispatch($this.buf); $this.buf = []; } diff --git a/packages/rstream/src/subs/sidechain-toggle.ts b/packages/rstream/src/subs/sidechain-toggle.ts index a6096c8632..38d3510ce0 100644 --- a/packages/rstream/src/subs/sidechain-toggle.ts +++ b/packages/rstream/src/subs/sidechain-toggle.ts @@ -46,13 +46,13 @@ export class SidechainToggle extends Subscription { pred?: Predicate, id?: string ) { - super(null, null, null, id || `sidetoggle-${nextID()}`); + super(undefined, undefined, undefined, id || `sidetoggle-${nextID()}`); this.isActive = initial; const $this = this; pred = pred || (() => true); this.sideSub = side.subscribe({ next(x) { - if (pred(x)) { + if (pred!(x)) { $this.isActive = !$this.isActive; } }, diff --git a/packages/rstream/src/subs/timeout.ts b/packages/rstream/src/subs/timeout.ts index 8f9aee1d9b..5e7eafdb70 100644 --- a/packages/rstream/src/subs/timeout.ts +++ b/packages/rstream/src/subs/timeout.ts @@ -34,7 +34,7 @@ class Timeout extends Subscription { resetTimeout = false, id?: string ) { - super(null, null, null, id || `timeout-${nextID()}`); + super(undefined, undefined, undefined, id || `timeout-${nextID()}`); this.timeoutMs = timeoutMs; this.errorObj = error; this.resetTimeout = resetTimeout; diff --git a/packages/rstream/src/subs/tunnel.ts b/packages/rstream/src/subs/tunnel.ts index 183b03e831..ff56ef54e3 100644 --- a/packages/rstream/src/subs/tunnel.ts +++ b/packages/rstream/src/subs/tunnel.ts @@ -61,19 +61,19 @@ export const tunnel = (opts: TunnelOpts) => new Tunnel(opts); export class Tunnel extends Subscription { workers: Worker[]; src: Worker | Blob | string; - transferables: Fn; + transferables?: Fn; terminate: number; interrupt: boolean; index: number; constructor(opts: TunnelOpts) { - super(null, null, null, opts.id || `tunnel-${nextID()}`); + super(undefined, undefined, undefined, opts.id || `tunnel-${nextID()}`); this.src = opts.src; this.workers = new Array(opts.maxWorkers || 1); this.transferables = opts.transferables; this.terminate = opts.terminate || 1000; - this.interrupt = opts.interrupt; + this.interrupt = opts.interrupt || false; this.index = 0; } @@ -83,7 +83,7 @@ export class Tunnel extends Subscription { if (this.transferables) { tx = this.transferables(x); } - let worker = this.workers[this.index]; + let worker: Worker | null = this.workers[this.index]; if (this.interrupt && worker) { worker.terminate(); worker = null; @@ -98,7 +98,7 @@ export class Tunnel extends Subscription { this.error(e) ); } - worker.postMessage(x, tx); + worker.postMessage(x, tx || []); } } diff --git a/packages/rstream/src/subscription.ts b/packages/rstream/src/subscription.ts index c46ec82659..e170245a2e 100644 --- a/packages/rstream/src/subscription.ts +++ b/packages/rstream/src/subscription.ts @@ -62,9 +62,9 @@ export class Subscription implements IDeref, ISubscriber, ISubscribable { id: string; - protected parent: ISubscribable; + protected parent?: ISubscribable; protected subs: ISubscriber[]; - protected xform: Reducer; + protected xform?: Reducer; protected state: State = State.IDLE; protected last: any; @@ -80,7 +80,7 @@ export class Subscription this.last = SEMAPHORE; this.subs = []; if (sub) { - this.subs.push(>sub); + this.subs.push(sub); } if (xform) { this.xform = xform(push()); @@ -135,7 +135,7 @@ export class Subscription if (implementsFunction(sub, "subscribe")) { sub.parent = this; } else { - sub = subscription(sub, xform, this, id); + sub = subscription(sub, xform, this, id); } if (this.last !== SEMAPHORE) { sub.next(this.last); diff --git a/packages/rstream/src/tween.ts b/packages/rstream/src/tween.ts index 5e376dbb0c..30f6f7fc50 100644 --- a/packages/rstream/src/tween.ts +++ b/packages/rstream/src/tween.ts @@ -63,7 +63,7 @@ export const tween = ( stop?: Fn2, clock?: ISubscribable | number ) => - sync({ + sync({ src: { src, _: diff --git a/packages/rstream/src/utils/close.ts b/packages/rstream/src/utils/close.ts index 4749dbf4d6..280910d141 100644 --- a/packages/rstream/src/utils/close.ts +++ b/packages/rstream/src/utils/close.ts @@ -1,6 +1,6 @@ import { CloseMode } from "../api"; -export const closeMode = (close: boolean | CloseMode) => +export const closeMode = (close: boolean | CloseMode | undefined) => close === true || close === undefined ? CloseMode.LAST : close === false diff --git a/packages/rstream/test/bisect.ts b/packages/rstream/test/bisect.ts index 5bfaa1ddb2..dd6ff98e82 100644 --- a/packages/rstream/test/bisect.ts +++ b/packages/rstream/test/bisect.ts @@ -1,8 +1,8 @@ import * as tx from "@thi.ng/transducers"; import * as assert from "assert"; - import * as rs from "../src/index"; +// prettier-ignore describe("bisect", () => { let src: rs.Stream; @@ -11,7 +11,7 @@ describe("bisect", () => { }); it("raw subscribers", (done) => { - const odds = [], evens = []; + const odds: number[] = [], evens: number[] = []; src.subscribe( rs.bisect((x) => !!(x & 1), { next(x) { odds.push(x) } }, @@ -28,7 +28,7 @@ describe("bisect", () => { }); it("subs", (done) => { - const odds = [], evens = []; + const odds: number[] = [], evens: number[] = []; const subo = rs.subscription( { next(x) { odds.push(x) }, done() { doneCount++; } }, tx.map(x => x * 10) @@ -48,4 +48,4 @@ describe("bisect", () => { } }); }); -}); \ No newline at end of file +}); diff --git a/packages/rstream/test/config.ts b/packages/rstream/test/config.ts new file mode 100644 index 0000000000..6b8b1e0aac --- /dev/null +++ b/packages/rstream/test/config.ts @@ -0,0 +1,4 @@ +/** + * Default base delay for time based tests + */ +export const TIMEOUT = 20; diff --git a/packages/rstream/test/from-atom.ts b/packages/rstream/test/from-atom.ts index b8b852fae8..a8f41c7216 100644 --- a/packages/rstream/test/from-atom.ts +++ b/packages/rstream/test/from-atom.ts @@ -1,12 +1,12 @@ import { Atom, Cursor, History } from "@thi.ng/atom"; import * as assert from "assert"; - import { fromAtom } from "../src/from/atom"; +// prettier-ignore describe("fromAtom", () => { it("works with atom", (done) => { - let a = new Atom(null); + let a = new Atom(0); let src = fromAtom(a, false); let calledNext = false; src.subscribe({ @@ -56,7 +56,7 @@ describe("fromAtom", () => { let c = new Cursor(a, "a.b"); let h = new History(c); let src = fromAtom(h, true); - let buf = []; + let buf: any[] = []; src.subscribe({ next(x) { buf.push(x); } }); h.reset(1); h.reset(2); @@ -83,8 +83,8 @@ describe("fromAtom", () => { let c2 = new Cursor(a, "c"); let src1 = fromAtom(c1, true); let src2 = fromAtom(c2, true); - let buf1 = []; - let buf2 = []; + let buf1:any[] = []; + let buf2:any[] = []; src1.subscribe({ next(x) { buf1.push(x); } }); src2.subscribe({ next(x) { buf2.push(x); } }); h.record(); @@ -118,4 +118,4 @@ describe("fromAtom", () => { assert.deepEqual(buf2, [undefined, 10, 20, 10, 20, 10, undefined]); }); -}); \ No newline at end of file +}); diff --git a/packages/rstream/test/from-iterable.ts b/packages/rstream/test/from-iterable.ts index 4c563fb840..5bb2195455 100644 --- a/packages/rstream/test/from-iterable.ts +++ b/packages/rstream/test/from-iterable.ts @@ -1,6 +1,6 @@ import * as assert from "assert"; - import * as rs from "../src/index"; +import { TIMEOUT } from "./config"; describe("fromIterable()", () => { let src: rs.Stream; @@ -24,9 +24,11 @@ describe("fromIterable()", () => { }); it("delivers all values", (done) => { - let buf = []; + let buf: any[] = []; src.subscribe({ - next(x) { buf.push(x) }, + next(x) { + buf.push(x); + }, done() { assert.deepEqual(buf, data); done(); @@ -45,11 +47,13 @@ describe("fromIterable()", () => { }); it("works with delay", (done) => { - let buf = []; + let buf: any[] = []; let t0 = Date.now(); src = rs.fromIterable(data, 10); src.subscribe({ - next(x) { buf.push(x); }, + next(x) { + buf.push(x); + }, done() { assert.deepEqual(buf, data); assert(Date.now() - t0 >= (data.length + 1) * 10); @@ -58,20 +62,24 @@ describe("fromIterable()", () => { }); }); - it("can be cancelled", (done) => { - let buf = []; + it("can be cancelled", function(done) { + this.timeout(TIMEOUT * 5); + let buf: any[] = []; let doneCalled = false; - src = rs.fromIterable(data, 10); + src = rs.fromIterable(data, TIMEOUT); src.subscribe({ - next(x) { buf.push(x); }, - done() { doneCalled = true; } + next(x) { + buf.push(x); + }, + done() { + doneCalled = true; + } }); - setTimeout(() => src.cancel(), 10); + setTimeout(() => src.cancel(), TIMEOUT * 1.5); setTimeout(() => { assert.deepEqual(buf, [data[0]]); assert(!doneCalled); done(); - }, 50); + }, TIMEOUT * 4); }); - }); diff --git a/packages/rstream/test/from-promise.ts b/packages/rstream/test/from-promise.ts index 4f105fefa4..41735aeefa 100644 --- a/packages/rstream/test/from-promise.ts +++ b/packages/rstream/test/from-promise.ts @@ -1,9 +1,8 @@ import * as assert from "assert"; - import * as rs from "../src/index"; +import { TIMEOUT } from "./config"; describe("fromPromise()", () => { - it("resolves to sub", (done) => { let src = rs.fromPromise(Promise.resolve(23)); let called = false; @@ -39,11 +38,15 @@ describe("fromPromise()", () => { setTimeout(() => { assert(called, "not called"); done(); - }, 1); + }, TIMEOUT); }); it("passes error to sub", (done) => { - let src = rs.fromPromise(new Promise(() => { throw new Error("foo"); })); + let src = rs.fromPromise( + new Promise(() => { + throw new Error("foo"); + }) + ); let called = false; let sub = src.subscribe({ next(_) { @@ -66,22 +69,21 @@ describe("fromPromise()", () => { src.done(); assert.equal(src.getState(), rs.State.ERROR, "src not ERROR"); done(); - }, 10); + }, TIMEOUT); }); it("resolves via Resolver", (done) => { let src = rs.fromIterable([Promise.resolve(23)]); let called = false; - src.subscribe(rs.resolve()) - .subscribe({ - next(x) { - assert.equal(x, 23); - called = true; - }, - done() { - assert(called, "not called"); - done(); - } - }); + src.subscribe(rs.resolve()).subscribe({ + next(x) { + assert.equal(x, 23); + called = true; + }, + done() { + assert(called, "not called"); + done(); + } + }); }); }); diff --git a/packages/rstream/test/pubsub.ts b/packages/rstream/test/pubsub.ts index e921f6c3a9..b7e6b9b6d3 100644 --- a/packages/rstream/test/pubsub.ts +++ b/packages/rstream/test/pubsub.ts @@ -2,13 +2,14 @@ import { EquivMap } from "@thi.ng/associative"; import * as tx from "@thi.ng/transducers"; import * as assert from "assert"; import * as rs from "../src/index"; +import { TIMEOUT } from "./config"; describe("PubSub", () => { let pub: rs.PubSub; it("simple", () => { - const acc = { a: [], b: [] }; - const collect = { next: (x) => acc[x].push(x) }; + const acc: any = { a: [], b: [] }; + const collect = { next: (x: any) => acc[x].push(x) }; pub = rs.pubsub({ topic: (x) => x }); const a = pub.subscribeTopic("a", collect); const b = pub.subscribeTopic("b", collect); @@ -22,7 +23,7 @@ describe("PubSub", () => { it("complex keys", () => { const acc = new EquivMap<[string, number], [string, number][]>(); const collect = { - next: (x) => { + next: (x: any) => { let v = acc.get(x); v ? v.push(x) : acc.set(x, [x]); } @@ -50,8 +51,8 @@ describe("PubSub", () => { }); it("transducer", () => { - const acc = { a: [], b: [], c: [], d: [] }; - const collect = { next: (x) => acc[x[0]].push(x) }; + const acc: any = { a: [], b: [], c: [], d: [] }; + const collect = { next: (x: any) => acc[x[0]].push(x) }; pub = rs.pubsub({ topic: (x) => x[0], xform: tx.mapIndexed((i, x) => [x, i]) @@ -68,18 +69,25 @@ describe("PubSub", () => { assert.equal(pub.getState(), rs.State.DONE); }); - it("unsubTopic", (done) => { - const acc = { a: [], b: [] }; - const collect = { next: (x) => acc[x].push(x) }; + it("unsubTopic", function(done) { + this.timeout(TIMEOUT * 8); + const acc: any = { a: [], b: [] }; + const collect = { + next: (x: any) => { + acc[x].push(x); + } + }; pub = rs.pubsub({ topic: (x) => x }); pub.subscribeTopic("a", collect); const b = pub.subscribeTopic("b", collect); - rs.fromIterable("abcbd", 5).subscribe(pub); - setTimeout(() => pub.unsubscribeTopic("b", b), 15); + rs.fromIterable("abcbd", TIMEOUT).subscribe(pub); + setTimeout(() => { + pub.unsubscribeTopic("b", b); + }, TIMEOUT * 2.5); setTimeout(() => { assert.deepEqual(acc, { a: ["a"], b: ["b"] }); assert.equal(pub.getState(), rs.State.DONE); done(); - }, 40); + }, TIMEOUT * 7); }); }); diff --git a/packages/rstream/test/sidechain-partition.ts b/packages/rstream/test/sidechain-partition.ts index 8724b7fa81..782722947f 100644 --- a/packages/rstream/test/sidechain-partition.ts +++ b/packages/rstream/test/sidechain-partition.ts @@ -1,10 +1,8 @@ import * as assert from "assert"; - import * as rs from "../src/index"; -describe("SidechainPartition", function () { - - let src, side, buf; +describe("SidechainPartition", function() { + let src: rs.Stream, side: rs.Stream, buf: any[]; beforeEach(() => { src = rs.stream(); @@ -13,17 +11,15 @@ describe("SidechainPartition", function () { }); it("partitions (manual)", (done) => { - src.subscribe(rs.sidechainPartition(side)) - .subscribe({ - next(x) { buf.push(x); }, - done() { - assert.deepEqual( - buf, - [[1, 2], [3, 4, 5]] - ); - done(); - } - }); + src.subscribe(rs.sidechainPartition(side)).subscribe({ + next(x) { + buf.push(x); + }, + done() { + assert.deepEqual(buf, [[1, 2], [3, 4, 5]]); + done(); + } + }); src.next(1); src.next(2); side.next(1); @@ -37,17 +33,15 @@ describe("SidechainPartition", function () { }); it("partitions w/ predicate", (done) => { - src.subscribe(rs.sidechainPartition(side, (x) => x === 1)) - .subscribe({ - next(x) { buf.push(x); }, - done() { - assert.deepEqual( - buf, - [[1, 2, 3], [4, 5]] - ); - done(); - } - }); + src.subscribe(rs.sidechainPartition(side, (x) => x === 1)).subscribe({ + next(x) { + buf.push(x); + }, + done() { + assert.deepEqual(buf, [[1, 2, 3], [4, 5]]); + done(); + } + }); src.next(1); src.next(2); side.next(0); diff --git a/packages/rstream/test/sidechain-toggle.ts b/packages/rstream/test/sidechain-toggle.ts index d93f8c6e49..9d83f2758b 100644 --- a/packages/rstream/test/sidechain-toggle.ts +++ b/packages/rstream/test/sidechain-toggle.ts @@ -1,11 +1,9 @@ +import { Predicate } from "@thi.ng/api"; import * as assert from "assert"; - import * as rs from "../src/index"; describe("SidechainToggle", () => { - - - let src, side, buf; + let src: rs.Stream, side: rs.Stream, buf: any[]; beforeEach(() => { src = rs.stream(); @@ -13,17 +11,21 @@ describe("SidechainToggle", () => { buf = []; }); - let check = (initial, pred, expect, done) => { - src.subscribe(rs.sidechainToggle(side, initial, pred)) - .subscribe({ - next(x) { - buf.push(x); - }, - done() { - assert.deepEqual(buf, expect); - done(); - } - }); + let check = ( + initial: any, + pred: Predicate | undefined, + expect: any, + done: Function + ) => { + src.subscribe(rs.sidechainToggle(side, initial, pred)).subscribe({ + next(x) { + buf.push(x); + }, + done() { + assert.deepEqual(buf, expect); + done(); + } + }); src.next(1); src.next(2); side.next(0); @@ -35,11 +37,11 @@ describe("SidechainToggle", () => { }; it("toggles (initially on)", (done) => { - check(true, null, [1, 2, 5], done); + check(true, undefined, [1, 2, 5], done); }); it("toggles (initially off)", (done) => { - check(false, null, [3, 4], done); + check(false, undefined, [3, 4], done); }); it("toggles w/ predicate", (done) => { diff --git a/packages/rstream/test/stream-merge.ts b/packages/rstream/test/stream-merge.ts index c12696795a..f050ce6e03 100644 --- a/packages/rstream/test/stream-merge.ts +++ b/packages/rstream/test/stream-merge.ts @@ -1,16 +1,14 @@ import * as tx from "@thi.ng/transducers"; import * as assert from "assert"; - import * as rs from "../src/index"; describe("StreamMerge", () => { - let src: rs.StreamMerge; - let check = (expected, done) => { - let buf = []; + let check = (expected: any, done: Function) => { + let buf: any[] = []; return { - next(x) { + next(x: any) { buf.push(x); }, done() { @@ -31,9 +29,7 @@ describe("StreamMerge", () => { }); it("merges all inputs", (done) => { - src.subscribe( - check([1, 2, 10, 20, 30, 40, 100, 200, 300], done) - ); + src.subscribe(check([1, 2, 10, 20, 30, 40, 100, 200, 300], done)); }); it("merges dynamic inputs", (done) => { @@ -63,10 +59,7 @@ describe("StreamMerge", () => { it("applies transducer", (done) => { src = rs.merge({ - src: [ - rs.fromIterable([1, 2]), - rs.fromIterable([10, 20]) - ], + src: [rs.fromIterable([1, 2]), rs.fromIterable([10, 20])], xform: tx.mapcat((x: number) => [x, x + 1]) }); src.subscribe(check([1, 2, 2, 3, 10, 11, 20, 21], done)); @@ -75,19 +68,22 @@ describe("StreamMerge", () => { it("transducer streams", (done) => { const sources = [ rs.fromIterable([1, 2, 3]), - rs.fromIterable([4, 5, 6]), - ].map( - (s) => s.subscribe(tx.map(x => rs.fromIterable([x, x, x]))) - ); - const merge = rs.merge({ src: sources }); + rs.fromIterable([4, 5, 6]) + ].map((s) => s.subscribe(tx.map((x) => rs.fromIterable([x, x, x])))); + const merge = rs.merge({ src: sources }); const histogram = tx.frequencies(); let acc: any = histogram[0](); merge.subscribe({ - next(x) { acc = histogram[2](acc, x) }, + next(x) { + acc = histogram[2](acc, x); + }, done() { - assert.deepEqual(acc, new Map([[1, 3], [2, 3], [3, 3], [4, 3], [5, 3], [6, 3]])); + assert.deepEqual( + acc, + new Map([[1, 3], [2, 3], [3, 3], [4, 3], [5, 3], [6, 3]]) + ); done(); } - }) + }); }); }); diff --git a/packages/rstream/test/stream-sync.ts b/packages/rstream/test/stream-sync.ts index 79c37832c5..741a6d4040 100644 --- a/packages/rstream/test/stream-sync.ts +++ b/packages/rstream/test/stream-sync.ts @@ -5,7 +5,7 @@ import * as rs from "../src/index"; describe("StreamSync", () => { function adder() { - return tx.map((ports) => { + return tx.map((ports: any) => { let sum = 0; for (let p in ports) { sum += ports[p]; @@ -39,7 +39,7 @@ describe("StreamSync", () => { } }); const a2 = rs.sync({ - src: [a1, (c = rs.fromView(db, "a2.ins.b"))], + src: [a1, (c = rs.fromView(db, "a2.ins.b"))], xform: adder() }); const res = a2.subscribe({ @@ -82,7 +82,7 @@ describe("StreamSync", () => { b: rs.stream(), c: rs.stream() }; - const res = []; + const res: any[] = []; const sync = rs.sync({ src, mergeOnly: true }).subscribe({ next: (x) => res.push(x), done: () => { @@ -109,7 +109,7 @@ describe("StreamSync", () => { b: rs.stream(), c: rs.stream() }; - const res = []; + const res: any[] = []; const sync = rs .sync({ src, @@ -138,18 +138,18 @@ describe("StreamSync", () => { }); it("fromPromise", (done) => { - const delayed = (x, t) => + const delayed = (x: any, t: number) => new Promise((resolve) => setTimeout(() => resolve(x), t)); rs.transduce( rs.sync({ - src: { + src: { t: rs.fromInterval(5), a: rs.fromPromise(delayed("aa", 20)), b: rs.fromPromise(delayed("bb", 40)) } }), - tx.comp(tx.take(1), tx.map(({ a, b }) => ({ a, b }))), + tx.comp(tx.take(1), tx.map(({ a, b }: any) => ({ a, b }))), tx.last() ).then((res) => { assert.deepEqual(res, { a: "aa", b: "bb" }); diff --git a/packages/rstream/test/subscription.ts b/packages/rstream/test/subscription.ts index 77ca35f61d..648bde10fd 100644 --- a/packages/rstream/test/subscription.ts +++ b/packages/rstream/test/subscription.ts @@ -1,73 +1,94 @@ import * as tx from "@thi.ng/transducers"; import * as assert from "assert"; - import * as rs from "../src/index"; +import { TIMEOUT } from "./config"; describe("Subscription", () => { let src: rs.Stream; - beforeEach(() => { - }); + beforeEach(() => {}); - it("new sub receives last", (done) => { - let buf = []; - src = rs.fromIterable([1, 2, 3], 10); - src.subscribe({ next(x) { buf.push(x); } }); - setTimeout(() => - src.subscribe({ - next(x) { buf.push(x); }, - done() { - assert.deepEqual(buf, [1, 2, 2, 3, 3]); - done(); - } - }), - 25); + it("new sub receives last", function(done) { + this.timeout(TIMEOUT * 5); + let buf: any[] = []; + src = rs.fromIterable([1, 2, 3], TIMEOUT); + src.subscribe({ + next(x) { + buf.push(x); + } + }); + setTimeout( + () => + src.subscribe({ + next(x) { + buf.push(x); + }, + done() { + assert.deepEqual(buf, [1, 2, 2, 3, 3]); + done(); + } + }), + TIMEOUT * 2.5 + ); }); - it("unsub does not trigger Subscription.done()", (done) => { - let buf = []; + it("unsub does not trigger Subscription.done()", function(done) { + this.timeout(TIMEOUT * 5); + let buf: any[] = []; let called = false; - src = rs.fromIterable([1, 2, 3], 10); + src = rs.fromIterable([1, 2, 3], TIMEOUT); const sub = src.subscribe({ - next(x) { buf.push(x); }, - done() { called = true; } + next(x) { + buf.push(x); + }, + done() { + called = true; + } }); - setTimeout(() => sub.unsubscribe(), 15); + setTimeout(() => sub.unsubscribe(), TIMEOUT * 1.5); setTimeout(() => { assert.deepEqual(buf, [1]); assert.equal(src.getState(), rs.State.DONE); assert.equal((src).subs.length, 0); assert(!called); done(); - }, 30); + }, TIMEOUT * 4); }); - it("no new values after unsub", (done) => { - let buf = []; + it("no new values after unsub", function(done) { + this.timeout(TIMEOUT * 5); + + let buf: any[] = []; let called = false; - src = rs.fromIterable([1, 2, 3], 10); + src = rs.fromIterable([1, 2, 3], TIMEOUT); const sub = src.subscribe( { - next(x) { buf.push(x); }, - done() { called = true; } + next(x) { + buf.push(x); + }, + done() { + called = true; + } }, tx.partition(2, true) ); - setTimeout(() => sub.unsubscribe(), 25); + setTimeout(() => sub.unsubscribe(), TIMEOUT * 2.5); setTimeout(() => { assert.deepEqual(buf, [[1, 2]]); assert.equal(src.getState(), rs.State.DONE); assert(!called); done(); - }, 50); + }, TIMEOUT * 4); }); it("completing transducer sends all values", (done) => { - let buf = []; + let buf: any[] = []; src = rs.fromIterable([1, 2, 3], 10); src.subscribe( { - next(x) { buf.push(x); }, + next(x) { + buf.push(x); + }, done() { assert.deepEqual(buf, [[1, 2], [3]]); assert.equal(src.getState(), rs.State.DONE); diff --git a/packages/rstream/test/timeout.ts b/packages/rstream/test/timeout.ts index ab54c8d30c..89be83da1e 100644 --- a/packages/rstream/test/timeout.ts +++ b/packages/rstream/test/timeout.ts @@ -1,50 +1,61 @@ import * as assert from "assert"; import { timeout } from "../src/subs/timeout"; +import { TIMEOUT } from "./config"; describe("Timeout", () => { - it("times out", function (done) { - this.timeout(20); - - timeout(10).subscribe({ - error: () => done() - }) + it("times out", function(done) { + this.timeout(TIMEOUT * 2); + + timeout(TIMEOUT).subscribe({ + error: (e) => { + assert(e instanceof Error); + done(); + } + }); }); - it("times out with error object", function (done) { - this.timeout(20); + it("times out with error object", function(done) { + this.timeout(TIMEOUT * 2); - const error = 'error object'; + const error = "error object"; - timeout(10, error).subscribe({ - error: (err) => { assert.equal(err, error); done() } - }) + timeout(TIMEOUT, error).subscribe({ + error: (err) => { + assert.equal(err, error); + done(); + } + }); }); - it("cancels timeout in cleanup()", function (done) { - this.timeout(40); + it("cancels timeout in cleanup()", function(done) { + this.timeout(TIMEOUT * 3); - timeout(10) + timeout(TIMEOUT) .subscribe({ - error: () => assert.fail('timed out'), + error: () => assert.fail("timed out") }) .unsubscribe(); - setTimeout(() => done(), 20) + setTimeout(() => done(), TIMEOUT * 2); }); - it("resets timeout when value received", function (done) { - this.timeout(40); + it("resets timeout when value received", function(done) { + this.timeout(TIMEOUT * 4); - const res = []; - const t = timeout(10, null, true); + const res: any[] = []; + const t = timeout(TIMEOUT, null, true); t.subscribe({ - next: (x) => { res.push(x); }, - error: () => { assert.deepEqual(res, [1, 2]); } + next: (x) => { + res.push(x); + }, + error: () => { + assert.deepEqual(res, [1, 2]); + } }); - setTimeout(() => t.next(1), 7); - setTimeout(() => t.next(2), 15); - setTimeout(() => t.next(3), 29); - setTimeout(() => done(), 35); + setTimeout(() => t.next(1), TIMEOUT * 0.7); + setTimeout(() => t.next(2), TIMEOUT * 1.5); + setTimeout(() => t.next(3), TIMEOUT * 2.9); + setTimeout(() => done(), TIMEOUT * 3.5); }); }); diff --git a/packages/rstream/test/transducers.ts b/packages/rstream/test/transducers.ts index efe03e9eb0..f2c3b1e774 100644 --- a/packages/rstream/test/transducers.ts +++ b/packages/rstream/test/transducers.ts @@ -1,16 +1,17 @@ import * as tx from "@thi.ng/transducers"; import * as assert from "assert"; - import * as rs from "../src/index"; describe("transducers", () => { let src: rs.Stream; let data = [10, 20, 30]; - let check = (expected, done) => { - let buf = []; + let check = (expected: any, done: Function) => { + let buf: any[] = []; return { - next(x) { buf.push(x) }, + next(x: any) { + buf.push(x); + }, done() { assert.deepEqual(buf, expected); done(); @@ -31,42 +32,29 @@ describe("transducers", () => { it("works combined", (done) => { src.subscribe( check([101, 201, 301], done), - tx.comp( - tx.map((x: number) => x * 10), - tx.map((x: number) => x + 1) - ) + tx.comp(tx.map((x: number) => x * 10), tx.map((x: number) => x + 1)) ); }); it("does early termination", (done) => { - src.subscribe( - check([data[0], data[1]], done), - tx.take(2) - ); + src.subscribe(check([data[0], data[1]], done), tx.take(2)); }); it("emits multiple values", (done) => { src.subscribe( check([10, 10, 20], done), - tx.comp( - tx.mapcat(x => [x, x]), - tx.take(3) - ) + tx.comp(tx.mapcat((x) => [x, x]), tx.take(3)) ); }); it("filters values", (done) => { src.subscribe( check([10, 30], done), - tx.filter((x: number) => (x % 20) > 0), + tx.filter((x: number) => x % 20 > 0) ); }); it("emits remaining", (done) => { - src.subscribe( - check([[10, 20], [30]], done), - tx.partition(2, true) - ); + src.subscribe(check([[10, 20], [30]], done), tx.partition(2, true)); }); - }); diff --git a/packages/sax/CHANGELOG.md b/packages/sax/CHANGELOG.md index adb085453d..730da83ee0 100644 --- a/packages/sax/CHANGELOG.md +++ b/packages/sax/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.1.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/sax@1.0.19...@thi.ng/sax@1.1.0) (2019-07-07) + + +### Features + +* **sax:** enable TS strict compiler flags (refactor) ([eb30aaf](https://github.com/thi-ng/umbrella/commit/eb30aaf)) + + + + + ## [1.0.19](https://github.com/thi-ng/umbrella/compare/@thi.ng/sax@1.0.18...@thi.ng/sax@1.0.19) (2019-05-22) **Note:** Version bump only for package @thi.ng/sax diff --git a/packages/sax/package.json b/packages/sax/package.json index bd1f39414e..192c872923 100644 --- a/packages/sax/package.json +++ b/packages/sax/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/sax", - "version": "1.0.19", + "version": "1.1.0", "description": "Transducer-based, SAX-like, non-validating, speedy & tiny XML parser", "module": "./index.js", "main": "./lib/index.js", @@ -25,16 +25,16 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/api": "^6.2.0", - "@thi.ng/transducers": "^5.3.7", - "@thi.ng/transducers-fsm": "^1.0.19" + "@thi.ng/api": "^6.3.0", + "@thi.ng/transducers": "^5.4.0", + "@thi.ng/transducers-fsm": "^1.1.0" }, "keywords": [ "ES6", diff --git a/packages/sax/src/index.ts b/packages/sax/src/index.ts index 6364af6338..d16b02bdd1 100644 --- a/packages/sax/src/index.ts +++ b/packages/sax/src/index.ts @@ -95,16 +95,16 @@ export enum Type { interface ParseState extends FSMState { scope: any[]; - tag: string; - attribs: any; - body: string; - name: string; - val: string; pos: number; - quote: string; - phase: number; - isProc: boolean; opts: Partial; + tag?: string; + attribs?: any; + body?: string; + name?: string; + val?: string; + quote?: string; + phase?: number; + isProc?: boolean; } const enum State { @@ -130,7 +130,7 @@ const enum State { // U_CHAR, } -const ENTITIES = { +const ENTITIES: IObjectOf = { "&": "&", "<": "<", ">": ">", @@ -140,7 +140,7 @@ const ENTITIES = { const ENTITY_RE = new RegExp(`(${Object.keys(ENTITIES).join("|")})`, "g"); -const ESCAPE_SEQS = { +const ESCAPE_SEQS: IObjectOf = { n: "\n", r: "\r", t: "\t", @@ -308,7 +308,7 @@ const PARSER: FSMStateMap = { return error( state, `unmatched tag: '${state.tag}' @ pos ${state.pos - - state.tag.length - + state.tag!.length - 2}` ); } @@ -335,7 +335,7 @@ const PARSER: FSMStateMap = { [State.ELEM_BODY]: (state, ch) => { state.pos++; - let b = state.body; + let b = state.body!; if (ch === "<") { let res; const t = state.tag; @@ -401,15 +401,18 @@ const PARSER: FSMStateMap = { } else if (ch === "=") { state.state = State.ATTRIB_VAL_START; } else if (state.opts.boolean) { + if (!state.name || !state.name.length) { + return error(state, "missing attribute name"); + } if (ch === " ") { - state.attribs[state.name] = true; + state.attribs[state.name!] = true; state.state = State.MAYBE_ATTRIB; } else if (ch === "/") { - state.attribs[state.name] = true; + state.attribs[state.name!] = true; state.state = State.ELEM_SINGLE; return; } else if (ch === ">") { - state.attribs[state.name] = true; + state.attribs[state.name!] = true; return beginElementBody(state); } else { return unexpected(state, ch); @@ -431,7 +434,7 @@ const PARSER: FSMStateMap = { [State.ATTRIB_VALUE]: (state, ch) => { state.pos++; - let v = state.val; + let v = state.val!; if (v.charAt(v.length - 1) == "\\") { const e = ESCAPE_SEQS[ch]; if (e !== undefined) { @@ -448,7 +451,7 @@ const PARSER: FSMStateMap = { if (state.opts.entities) { v = replaceEntities(v); } - state.attribs[state.name] = v; + state.attribs[state.name!] = v; state.state = State.MAYBE_ATTRIB; }, @@ -482,12 +485,12 @@ const PARSER: FSMStateMap = { [State.COMMENT_BODY]: (state, ch) => { state.pos++; if (ch === ">") { - const n = state.body.length; - if (state.body.substr(n - 2) !== "--") { + const n = state.body!.length; + if (state.body!.substr(n - 2) !== "--") { return unexpected(state, ch); } state.state = State.WAIT; - let b = state.body.substr(0, n - 2); + let b = state.body!.substr(0, n - 2); if (state.opts.trim) { b = b.trim(); if (!b.length) { @@ -502,15 +505,15 @@ const PARSER: FSMStateMap = { [State.DOCTYPE]: (state, ch) => { state.pos++; - if (state.phase < 8) { - if (ch === "DOCTYPE "[state.phase]) { - state.phase++; + if (state.phase! < 8) { + if (ch === "DOCTYPE "[state.phase!]) { + state.phase!++; } else { return unexpected(state, ch); } } else if (ch === ">") { state.state = State.WAIT; - return [{ type: Type.DOCTYPE, body: state.body.trim() }]; + return [{ type: Type.DOCTYPE, body: state.body!.trim() }]; } else { state.body += ch; } @@ -518,20 +521,20 @@ const PARSER: FSMStateMap = { [State.CDATA]: (state, ch) => { state.pos++; - if (state.phase < 7) { - if (ch === "[CDATA["[state.phase]) { - state.phase++; + if (state.phase! < 7) { + if (ch === "[CDATA["[state.phase!]) { + state.phase!++; } else { return unexpected(state, ch); } } else if (ch === ">") { - const n = state.body.length; - if (state.body.substr(n - 2) !== "]]") { + const n = state.body!.length; + if (state.body!.substr(n - 2) !== "]]") { state.body += ch; return; } state.state = State.WAIT; - let b = state.body.substr(0, n - 2); + let b = state.body!.substr(0, n - 2); if (state.opts.trim) { b = b.trim(); if (!b.length) { diff --git a/packages/sax/test/index.ts b/packages/sax/test/index.ts index fe2ae9805c..b3b7d3051b 100644 --- a/packages/sax/test/index.ts +++ b/packages/sax/test/index.ts @@ -1,9 +1,7 @@ -import * as assert from "assert"; - -import { defmulti, DEFAULT } from "@thi.ng/defmulti"; +import { DEFAULT, defmulti } from "@thi.ng/defmulti"; import * as tx from "@thi.ng/transducers"; - -import * as sax from "../src/index"; +import * as assert from "assert"; +import { parse, ParseElement, Type } from "../src/index"; const svg = ` @@ -23,86 +21,110 @@ const svg = ` describe("sax", () => { it("svg parse", () => { assert.deepEqual( - [...tx.iterator( - tx.comp( - sax.parse({ children: true }), - tx.matchFirst((e) => e.type == sax.Type.ELEM_END && e.tag == "g"), - tx.mapcat((e) => e.children), - tx.filter((e) => e.tag == "circle"), - tx.map((e) => [e.tag, { - ...e.attribs, - cx: parseFloat(e.attribs.cx), - cy: parseFloat(e.attribs.cy), - r: parseFloat(e.attribs.r), - }]) - ), - svg - )], [ - ['circle', { cx: 50, cy: 150, r: 50 }], - ['circle', { cx: 250, cy: 150, r: 50 }], - ['circle', { cx: 150, cy: 150, fill: 'rgba(0,255,255,0.25)', r: 100, stroke: '#ff0000' }] + ...tx.iterator( + tx.comp( + parse({ children: true }), + tx.matchFirst( + (e) => e.type == Type.ELEM_END && e.tag == "g" + ), + tx.mapcat((e) => e.children), + tx.filter((e) => e.tag == "circle"), + tx.map((e) => [ + e.tag, + { + ...e.attribs, + cx: parseFloat(e.attribs.cx), + cy: parseFloat(e.attribs.cy), + r: parseFloat(e.attribs.r) + } + ]) + ), + svg + ) + ], + [ + ["circle", { cx: 50, cy: 150, r: 50 }], + ["circle", { cx: 250, cy: 150, r: 50 }], + [ + "circle", + { + cx: 150, + cy: 150, + fill: "rgba(0,255,255,0.25)", + r: 100, + stroke: "#ff0000" + } + ] ] ); }); it("svg parse (defmulti)", () => { - const numericAttribs = (e, ...ids: string[]) => + const numericAttribs = (e: ParseElement, ...ids: string[]) => ids.reduce( - (acc, id) => (acc[id] = parseFloat(e.attribs[id]), acc), - { ...e.attribs } + (acc, id) => ((acc[id] = parseFloat(e.attribs[id])), acc), + { ...e.attribs } ); - const parsedChildren = (e) => + const parsedChildren = (e: ParseElement) => tx.iterator( - tx.comp( - tx.map(parseElement), - tx.filter((e) => !!e), - ), + tx.comp(tx.map(parseElement), tx.filter((e: any) => !!e)), e.children ); // define multiple dispatch function, based on element tag name - const parseElement = defmulti((e) => e.tag); + const parseElement = defmulti((e) => e.tag); // implementations - parseElement.add("circle", (e) => - [e.tag, numericAttribs(e, "cx", "cy", "r")]); + parseElement.add("circle", (e) => [ + e.tag, + numericAttribs(e, "cx", "cy", "r") + ]); - parseElement.add("rect", (e) => - [e.tag, numericAttribs(e, "x", "y", "width", "height")]); + parseElement.add("rect", (e) => [ + e.tag, + numericAttribs(e, "x", "y", "width", "height") + ]); - parseElement.add("g", (e) => - [e.tag, e.attribs, ...parsedChildren(e)]); + parseElement.add("g", (e) => [e.tag, e.attribs, ...parsedChildren(e)]); - parseElement.add("svg", (e) => - [e.tag, numericAttribs(e, "width", "height"), ...parsedChildren(e)]); + parseElement.add("svg", (e) => [ + e.tag, + numericAttribs(e, "width", "height"), + ...parsedChildren(e) + ]); // implementation for unhandled elements (just return undefined) parseElement.add(DEFAULT, () => undefined); assert.deepEqual( - parseElement(tx.transduce(sax.parse(), tx.last(), svg)), - ["svg", + parseElement(tx.transduce(parse(), tx.last(), svg)), + [ + "svg", { version: "1.1", height: 300, width: 300, xmlns: "http://www.w3.org/2000/svg" }, - ["g", + [ + "g", { fill: "yellow" }, ["circle", { cx: 50, cy: 150, r: 50 }], ["circle", { cx: 250, cy: 150, r: 50 }], - ["circle", + [ + "circle", { cx: 150, cy: 150, fill: "rgba(0,255,255,0.25)", r: 100, stroke: "#ff0000" - }], - ["rect", + } + ], + [ + "rect", { x: 80, y: 80, @@ -110,21 +132,26 @@ describe("sax", () => { height: 140, fill: "none", stroke: "black" - }]], - ["g", + } + ] + ], + [ + "g", { fill: "none", stroke: "black" }, ["circle", { cx: 150, cy: 150, r: 50 }], - ["circle", { cx: 150, cy: 150, r: 25 }]]] + ["circle", { cx: 150, cy: 150, r: 25 }] + ] + ] ); }); it("errors", () => { assert.deepEqual( - [...sax.parse("a")], + [...parse("a")], [{ type: 7, body: "unexpected char: 'a' @ pos 1" }] ); assert.deepEqual( - [...sax.parse("")], + [...parse("")], [ { type: 4, tag: "a", attribs: {} }, { type: 4, tag: "b", attribs: {} }, @@ -135,20 +162,25 @@ describe("sax", () => { it("boolean attribs", () => { assert.deepEqual( - [...sax.parse({ boolean: true }, ``)], + [...parse({ boolean: true }, ``)], [ { type: 4, tag: "foo", attribs: { a: true, b: "2", c: true } }, - { type: 5, tag: "foo", attribs: { a: true, b: "2", c: true }, children: [] } + { + type: 5, + tag: "foo", + attribs: { a: true, b: "2", c: true }, + children: [] + } ], "no slash" - ) + ); assert.deepEqual( - [...sax.parse({ boolean: true }, ``)], + [...parse({ boolean: true }, ``)], [ { type: 4, tag: "foo", attribs: { a: true, b: "2", c: true } }, { type: 5, tag: "foo", attribs: { a: true, b: "2", c: true } } ], "with slash" - ) + ); }); }); diff --git a/packages/shader-ast-glsl/.npmignore b/packages/shader-ast-glsl/.npmignore new file mode 100644 index 0000000000..74ea62d1fa --- /dev/null +++ b/packages/shader-ast-glsl/.npmignore @@ -0,0 +1,12 @@ +.meta +.nyc_output +*.html +*.tgz +build +coverage +dev +doc +export +src* +test +tsconfig.json diff --git a/packages/shader-ast-glsl/CHANGELOG.md b/packages/shader-ast-glsl/CHANGELOG.md new file mode 100644 index 0000000000..1de245579d --- /dev/null +++ b/packages/shader-ast-glsl/CHANGELOG.md @@ -0,0 +1,21 @@ +# Change Log + +All notable changes to this project will be documented in this file. +See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +# 0.1.0 (2019-07-07) + + +### Bug Fixes + +* **shader-ast-glsl:** avoid extraneous semicolons ([f2ba0d6](https://github.com/thi-ng/umbrella/commit/f2ba0d6)) + + +### Features + +* **shader-ast-glsl:** add array init code gen ([afaee5f](https://github.com/thi-ng/umbrella/commit/afaee5f)) +* **shader-ast-glsl:** add global input/output var support, update GLSLOpts, add tests ([27003c9](https://github.com/thi-ng/umbrella/commit/27003c9)) +* **shader-ast-glsl:** add post-inc/dec support ([a554192](https://github.com/thi-ng/umbrella/commit/a554192)) +* **shader-ast-glsl:** add while loop, ivec support, fix bool ([882c560](https://github.com/thi-ng/umbrella/commit/882c560)) +* **shader-ast-glsl:** add/update opts, update `scope` code gen, refactor `lit` ([d1ddaf2](https://github.com/thi-ng/umbrella/commit/d1ddaf2)) +* **shader-ast-glsl:** extract GLSL codegen as separate pkg ([a1db3fc](https://github.com/thi-ng/umbrella/commit/a1db3fc)) diff --git a/packages/shader-ast-glsl/LICENSE b/packages/shader-ast-glsl/LICENSE new file mode 100644 index 0000000000..8dada3edaf --- /dev/null +++ b/packages/shader-ast-glsl/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/packages/shader-ast-glsl/README.md b/packages/shader-ast-glsl/README.md new file mode 100644 index 0000000000..1c6a57a9de --- /dev/null +++ b/packages/shader-ast-glsl/README.md @@ -0,0 +1,109 @@ +# @thi.ng/shader-ast-glsl + +[![npm (scoped)](https://img.shields.io/npm/v/@thi.ng/shader-ast-glsl.svg)](https://www.npmjs.com/package/@thi.ng/shader-ast-glsl) +![npm downloads](https://img.shields.io/npm/dm/@thi.ng/shader-ast-glsl.svg) +[![Twitter Follow](https://img.shields.io/twitter/follow/thing_umbrella.svg?style=flat-square&label=twitter)](https://twitter.com/thing_umbrella) + +This project is part of the +[@thi.ng/umbrella](https://github.com/thi-ng/umbrella/) monorepo. + + + +- [About](#about) +- [Installation](#installation) +- [Dependencies](#dependencies) +- [Usage examples](#usage-examples) +- [Authors](#authors) +- [License](#license) + + + +## About + +GLSL code generator for +[@thi.ng/shader-ast](https://github.com/thi-ng/umbrella/tree/master/packages/shader-ast). +Currently supports GLSL ES 1.00 (WebGL) & GLSL ES 3.00 (WebGL 2). + +This package is also used for shader assembly by +[@thi.ng/webgl](https://github.com/thi-ng/umbrella/tree/master/packages/webgl). + +## Installation + +```bash +yarn add @thi.ng/shader-ast-glsl +``` + +## Dependencies + +- [@thi.ng/api](https://github.com/thi-ng/umbrella/tree/master/packages/api) +- [@thi.ng/checks](https://github.com/thi-ng/umbrella/tree/master/packages/checks) +- [@thi.ng/errors](https://github.com/thi-ng/umbrella/tree/master/packages/errors) +- [@thi.ng/shader-ast](https://github.com/thi-ng/umbrella/tree/master/packages/shader-ast) + +## Usage examples + +There're are several `shader-ast` & `webgl` examples in the +[/examples](https://github.com/thi-ng/umbrella/tree/master/examples) +folder of this repo, for example... + +(Possibly non-exhaustive list, live demo links in readme's) + +- [2D SDF](https://github.com/thi-ng/umbrella/tree/master/examples/shader-ast-sdf2d) +- [Raymarching](https://github.com/thi-ng/umbrella/tree/master/examples/shader-ast-raymarch) +- [Simplex noise](https://github.com/thi-ng/umbrella/tree/master/examples/shader-ast-noise) +- [Textured tunnel](https://github.com/thi-ng/umbrella/tree/master/examples/shader-ast-tunnel) +- [Cubemap](https://github.com/thi-ng/umbrella/tree/master/examples/webgl-cubemap) +- [GPGPU basics](https://github.com/thi-ng/umbrella/tree/master/examples/webgl-gpgpu-basics) +- [MSDF font rendering](https://github.com/thi-ng/umbrella/tree/master/examples/webgl-msdf) +- [SSAO deferred rendering](https://github.com/thi-ng/umbrella/tree/master/examples/webgl-ssao) + +Basic GLSL code generation: + +```ts +import { assign, defMain, output, program, uniform, vec4 } from "@thi.ng/shader-ast"; +import { GLSLVersion, targetGLSL } from "@thi.ng/shader-ast-glsl"; + +const glsl = targetGLSL({ + // target WebGL2 + version: GLSLVersion.GLSL_300, + // emit #version pragma + versionPragma: true, + // fragment shader + type: "fs", + // custom prelude + prelude: `// custom GLSL source string injection, e.g. +#define PI 3.1415926` +}); + +let color: Vec3Symbol; +let fragColor: Vec4Symbol; + +glsl( + program([ + color = uniform("vec3", "color"), + fragColor = output("vec4", "fragColor", { loc: 0 }), + defMain(()=> [ + assign(fragColor, vec4(color, 1)) + ]) + ]) +) +``` + +```glsl +#version 300 es +// custom GLSL source string injection, e.g. +#define PI 3.1415926 +uniform vec3 color; +layout(location=0) out vec4 fragColor; +void main() { +fragColor = vec4(color, 1.0); +} +``` + +## Authors + +- Karsten Schmidt + +## License + +© 2018 Karsten Schmidt // Apache Software License 2.0 diff --git a/packages/shader-ast-glsl/package.json b/packages/shader-ast-glsl/package.json new file mode 100644 index 0000000000..35662840ce --- /dev/null +++ b/packages/shader-ast-glsl/package.json @@ -0,0 +1,55 @@ +{ + "name": "@thi.ng/shader-ast-glsl", + "version": "0.1.0", + "description": "Customizable GLSL code generator for @thi.ng/shader-ast", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", + "typings": "./index.d.ts", + "repository": { + "type": "git", + "url": "https://github.com/thi-ng/umbrella.git" + }, + "homepage": "https://github.com/thi-ng/umbrella/tree/master/packages/shader-ast-glsl", + "author": "Karsten Schmidt ", + "license": "Apache-2.0", + "scripts": { + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module", + "test": "rimraf build && tsc -p test/tsconfig.json && nyc mocha build/test/*.js", + "clean": "rimraf *.js *.d.ts .nyc_output build coverage doc lib codegen std", + "cover": "yarn test && nyc report --reporter=lcov", + "doc": "node_modules/.bin/typedoc --mode modules --out doc src", + "pub": "yarn build && yarn publish --access public" + }, + "devDependencies": { + "@types/mocha": "^5.2.6", + "@types/node": "^12.0.8", + "mocha": "^6.1.4", + "nyc": "^14.0.0", + "typedoc": "^0.14.2", + "typescript": "^3.5.2" + }, + "dependencies": { + "@thi.ng/api": "^6.3.0", + "@thi.ng/checks": "^2.2.0", + "@thi.ng/errors": "^1.1.0", + "@thi.ng/shader-ast": "^0.1.0" + }, + "keywords": [ + "AST", + "code generator", + "DSL", + "ES6", + "GLSL", + "shader", + "typescript", + "webgl", + "webgl2" + ], + "publishConfig": { + "access": "public" + }, + "sideEffects": false +} diff --git a/packages/shader-ast-glsl/src/index.ts b/packages/shader-ast-glsl/src/index.ts new file mode 100644 index 0000000000..47f352eb09 --- /dev/null +++ b/packages/shader-ast-glsl/src/index.ts @@ -0,0 +1,229 @@ +import { Fn } from "@thi.ng/api"; +import { isBoolean, isNumber } from "@thi.ng/checks"; +import { unsupported } from "@thi.ng/errors"; +import { + defTarget, + FloatSym, + FnCall, + FuncArg, + isMat, + isVec, + itemType, + Sym, + sym, + Term, + Type, + Vec2Sym, + Vec4Sym +} from "@thi.ng/shader-ast"; + +export const enum GLSLVersion { + GLES_100 = "100", + GLES_300 = "300 es" +} + +export interface GLSLOpts { + type: "vs" | "fs"; + version: GLSLVersion; + versionPragma: boolean; + prelude: string; +} + +export interface GLSLTarget extends Fn, string> { + gl_FragColor: Vec4Sym; + gl_FragCoord: Vec4Sym; + gl_FragData: Sym<"vec4[]">; + gl_FrontFacing: Sym<"bool">; + gl_PointCoord: Vec2Sym; + gl_PointSize: FloatSym; + gl_Position: Vec4Sym; +} + +const RE_SEMI = /[};]$/; + +/** + * GLSL code gen, targets GLSL ES 3.00 (WebGL2) by default. + * + * Use options object to configure shader type and GLSL version: `100` + * for WebGL, 300 for WebGL2. Currently, the only differences in terms + * of code generation, not correctness, are: + * + * - attribute, varying, uniform declarations + * - texture lookup function naming + * + * Unsupported features in GLSL 100: + * + * - Fragment shader output vars + * + * @param opts + */ +export const targetGLSL = (opts?: Partial) => { + const _opts: GLSLOpts = { + type: "fs", + version: GLSLVersion.GLES_300, + versionPragma: true, + prelude: "", + ...opts + }; + const isVS = _opts.type === "vs"; + + // TODO update once we have struct support + const $type = (t: Type) => t; + + const $list = (body: Term[], sep = ", ") => body.map(emit).join(sep); + + const $fn = (t: FnCall) => `${t.id}(${$list(t.args)})`; + + const $decl = (sym: Sym | FuncArg, arg = false) => { + const { id, type, opts, init } = >sym; + const res: string[] = []; + if (opts.type) { + let type: string; + if (_opts.version < GLSLVersion.GLES_300) { + if (isVS) { + type = ({ + in: "attribute", + out: "varying", + uni: "uniform" + })[opts.type]; + } else { + type = ({ + in: "varying", + out: null, + uni: "uniform" + })[opts.type]; + !type && + unsupported( + "GLSL 100 doesn't support fragment shader output variables" + ); + } + } else { + opts.loc != null && res.push(`layout(location=${opts.loc}) `); + type = opts.type === "uni" ? "uniform" : opts.type; + } + res.push(type + " "); + } else { + opts.const && res.push("const "); + arg && opts.q && res.push(opts.q + " "); + } + opts.prec && res.push(opts.prec + " "); + res.push($type(itemType(type)), " ", id); + opts.num && res.push(`[${opts.num}]`); + init && res.push(" = ", emit(init)); + return res.join(""); + }; + + const emit: Fn, string> = defTarget({ + arg: (t) => $decl(t, true), + + array_init: (t) => + _opts.version >= GLSLVersion.GLES_300 + ? `${t.type}(${$list(t.init)})` + : unsupported( + `array initializers not available in GLSL ${ + _opts.version + }` + ), + + assign: (t) => emit(t.l) + " = " + emit(t.r), + + ctrl: (t) => t.id, + + call: $fn, + + call_i: (t) => + t.id === "texture" && _opts.version < GLSLVersion.GLES_300 + ? `${t.id}${(>t.args[0]).type.substr(7)}(${$list( + t.args + )})` + : $fn(t), + + decl: (t) => $decl(t.id), + + fn: (t) => + `${$type(t.type)} ${t.id}(${$list(t.args)}) ${emit(t.scope)}`, + + for: (t) => + `for(${t.init ? emit(t.init) : ""}; ${emit(t.test)}; ${ + t.iter ? emit(t.iter) : "" + }) ${emit(t.scope)}`, + + idx: (t) => `${emit(t.val)}[${emit(t.id)}]`, + + if: (t) => { + const res = `if (${emit(t.test)}) ` + emit(t.t); + return t.f ? res + " else " + emit(t.f) : res; + }, + + lit: (t) => { + const v = t.val; + switch (t.type) { + case "bool": + return isBoolean(v) ? String(v) : `bool(${emit(v)})`; + case "float": + return isNumber(v) + ? v === Math.trunc(v) + ? v + ".0" + : String(v) + : `float(${emit(v)})`; + case "int": + case "uint": + return isNumber(v) ? String(v) : `${t.type}(${emit(v)})`; + default: { + if (isVec(t) || isMat(t)) { + return `${t.type}(${$list(v)})`; + } + return unsupported(`unknown type: ${t.type}`); + } + } + }, + + op1: (t) => + t.post ? `(${emit(t.val)}${t.op})` : `(${t.op}${emit(t.val)})`, + + op2: (t) => `(${emit(t.l)} ${t.op} ${emit(t.r)})`, + + ret: (t) => "return" + (t.val ? " " + emit(t.val) : ""), + + scope: (t) => { + let res = t.body + .map(emit) + .reduce( + (acc, x) => (acc.push(RE_SEMI.test(x) ? x : x + ";"), acc), + [] + ) + .join("\n"); + res += t.body.length && !RE_SEMI.test(res) ? ";" : ""; + if (!t.global) { + return `{\n${res}\n}`; + } + if (_opts.prelude) { + res = _opts.prelude + "\n" + res; + } + if (_opts.versionPragma) { + res = `#version ${_opts.version}\n` + res; + } + return res; + }, + + swizzle: (t) => `${emit(t.val)}.${t.id}`, + + sym: (t) => t.id, + + ternary: (t) => `(${emit(t.test)} ? ${emit(t.t)} : ${emit(t.f)})`, + + while: (t) => `while (${emit(t.test)}) ${emit(t.scope)}` + }); + + Object.assign(emit, { + gl_FragColor: sym("vec4", "gl_FragColor"), + gl_FragCoord: sym("vec4", "gl_FragCoord", { const: true }), + gl_FragData: sym("vec4[]", "gl_FragData", { num: 1 }), + gl_FrontFacing: sym("bool", "gl_FrontFacing", { const: true }), + gl_PointCoord: sym("vec2", "gl_PointCoord", { const: true }), + gl_PointSize: sym("float", "gl_PointSize"), + gl_Position: sym("vec4", "gl_Position") + }); + + return emit; +}; diff --git a/packages/shader-ast-glsl/test/index.ts b/packages/shader-ast-glsl/test/index.ts new file mode 100644 index 0000000000..d129f8e001 --- /dev/null +++ b/packages/shader-ast-glsl/test/index.ts @@ -0,0 +1,194 @@ +import { + $, + FALSE, + float, + input, + int, + IVec, + output, + scope, + sym, + Term, + TRUE, + uint, + uniform, + Vec, + vec2, + vec3, + vec4 +} from "@thi.ng/shader-ast"; +import * as assert from "assert"; +import { GLSLVersion, targetGLSL } from "../src"; + +const vs100 = targetGLSL({ + type: "vs", + version: GLSLVersion.GLES_100, + versionPragma: false +}); +const fs100 = targetGLSL({ + type: "fs", + version: GLSLVersion.GLES_100, + versionPragma: false +}); +const vs300 = targetGLSL({ type: "vs", versionPragma: false }); +const fs300 = targetGLSL({ type: "fs", versionPragma: false }); + +const V2 = sym("vec2", "v"); +const V3 = sym("vec3", "v"); +const V4 = sym("vec4", "v"); + +describe("shader-ast (glsl)", () => { + it("lit", () => { + assert.equal(fs300(TRUE), "true"); + assert.equal(fs300(FALSE), "false"); + assert.equal(fs300(float(0)), "0.0"); + assert.equal(fs300(float(-1)), "-1.0"); + assert.equal(fs300(float(3.1415)), "3.1415"); + assert.equal(fs300(int(0)), "0"); + assert.equal(fs300(int(-1)), "-1"); + assert.equal(fs300(int(3.1415)), "3"); + assert.equal(fs300(uint(0)), "0"); + assert.equal(fs300(uint(-1)), "4294967295"); + assert.equal(fs300(uint(3.1415)), "3"); + }); + + it("vec2", () => { + assert.equal(fs300(vec2()), "vec2(0.0)"); + assert.equal(fs300(vec2(1)), "vec2(1.0)"); + assert.equal(fs300(vec2(1, -2)), "vec2(1.0, -2.0)"); + }); + + it("vec3", () => { + assert.equal(fs300(vec3()), "vec3(0.0)"); + assert.equal(fs300(vec3(1)), "vec3(1.0)"); + assert.equal(fs300(vec3(1, -2, 3.14)), "vec3(1.0, -2.0, 3.14)"); + assert.equal( + fs300(vec3(vec2(1, -2), 3.14)), + "vec3(vec2(1.0, -2.0), 3.14)" + ); + }); + + it("vec4", () => { + assert.equal(fs300(vec4()), "vec4(0.0)"); + assert.equal(fs300(vec4(1)), "vec4(1.0)"); + assert.equal( + fs300(vec4(1, -2, 3.14, -4)), + "vec4(1.0, -2.0, 3.14, -4.0)" + ); + assert.equal( + fs300(vec4(vec2(1, -2), vec2(3.14))), + "vec4(vec2(1.0, -2.0), vec2(3.14))" + ); + assert.equal( + fs300(vec4(vec3(1, -2, 0), 3.14)), + "vec4(vec3(1.0, -2.0, 0.0), 3.14)" + ); + }); + + it("swizzle", () => { + const check = (v: Term, pat: string) => { + const res = $(v, pat); + assert.equal( + res.type, + pat.length > 1 ? "vec" + pat.length : "float", + pat + ); + assert.equal(fs300(res), "v." + pat, pat); + }; + check(V2, "y"); + check(V2, "yx"); + check(V2, "yxy"); + check(V2, "yxyx"); + check(V3, "z"); + check(V3, "zy"); + check(V3, "zyx"); + check(V3, "zyxz"); + check(V4, "w"); + check(V4, "wz"); + check(V4, "wzy"); + check(V4, "wzyx"); + }); + + it("inputs", () => { + [ + [ + input("vec3", "a"), + "attribute vec3 a;", + "in vec3 a;", + "varying vec3 a;", + "in vec3 a;" + ], + [ + input("vec3", "a", { loc: 1 }), + "attribute vec3 a;", + "layout(location=1) in vec3 a;", + "varying vec3 a;", + "layout(location=1) in vec3 a;" + ], + [ + input("vec3", "a", { loc: 1, num: 3 }), + "attribute vec3 a[3];", + "layout(location=1) in vec3 a[3];", + "varying vec3 a[3];", + "layout(location=1) in vec3 a[3];" + ] + ].forEach(([inp, v100, v300, f100, f300]: any) => { + const spec = scope([inp], true); + assert.equal(vs100(spec), v100, "vs100"); + assert.equal(vs300(spec), v300, "vs300"); + assert.equal(fs100(spec), f100, "fs100"); + assert.equal(fs300(spec), f300, "fs300"); + }); + }); + + it("uniforms", () => { + [ + [uniform("vec3", "a"), "uniform vec3 a;", "uniform vec3 a;"], + [ + uniform("vec3", "a", { loc: 1 }), + "uniform vec3 a;", + "layout(location=1) uniform vec3 a;" + ], + [ + uniform("vec3", "a", { loc: 1, num: 3 }), + "uniform vec3 a[3];", + "layout(location=1) uniform vec3 a[3];" + ] + ].forEach(([uni, gl100, gl300]: any) => { + const spec = scope([uni], true); + assert.equal(vs100(spec), gl100, "vs100"); + assert.equal(vs300(spec), gl300, "vs300"); + assert.equal(fs100(spec), gl100, "fs100"); + assert.equal(fs300(spec), gl300, "fs300"); + }); + }); + + it("outputs", () => { + [ + [ + output("vec3", "a"), + "varying vec3 a;", + "out vec3 a;", + "out vec3 a;" + ], + [ + output("vec3", "a", { loc: 1 }), + "varying vec3 a;", + "layout(location=1) out vec3 a;", + "layout(location=1) out vec3 a;" + ], + [ + output("vec3", "a", { loc: 1, num: 3 }), + "varying vec3 a[3];", + "layout(location=1) out vec3 a[3];", + "layout(location=1) out vec3 a[3];" + ] + ].forEach(([out, v100, v300, f300]: any) => { + const spec = scope([out], true); + assert.equal(vs100(spec), v100, "vs100"); + assert.equal(vs300(spec), v300, "vs300"); + assert.throws(() => fs100(spec), "fs100"); + assert.equal(fs300(spec), f300, "fs300"); + }); + }); +}); diff --git a/packages/shader-ast-glsl/test/tsconfig.json b/packages/shader-ast-glsl/test/tsconfig.json new file mode 100644 index 0000000000..f6e63560dd --- /dev/null +++ b/packages/shader-ast-glsl/test/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../../tsconfig.json", + "compilerOptions": { + "outDir": "../build", + "module": "commonjs" + }, + "include": [ + "./**/*.ts", + "../src/**/*.ts" + ] +} diff --git a/packages/shader-ast-glsl/tsconfig.json b/packages/shader-ast-glsl/tsconfig.json new file mode 100644 index 0000000000..893b9979c5 --- /dev/null +++ b/packages/shader-ast-glsl/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": ".", + "module": "es6", + "target": "es6" + }, + "include": [ + "./src/**/*.ts" + ] +} diff --git a/packages/shader-ast-js/.npmignore b/packages/shader-ast-js/.npmignore new file mode 100644 index 0000000000..74ea62d1fa --- /dev/null +++ b/packages/shader-ast-js/.npmignore @@ -0,0 +1,12 @@ +.meta +.nyc_output +*.html +*.tgz +build +coverage +dev +doc +export +src* +test +tsconfig.json diff --git a/packages/shader-ast-js/CHANGELOG.md b/packages/shader-ast-js/CHANGELOG.md new file mode 100644 index 0000000000..831175bcdb --- /dev/null +++ b/packages/shader-ast-js/CHANGELOG.md @@ -0,0 +1,26 @@ +# Change Log + +All notable changes to this project will be documented in this file. +See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +# 0.1.0 (2019-07-07) + + +### Bug Fixes + +* **shader-ast-js:** add missing faceForward, reflect, refract builtins ([c63058e](https://github.com/thi-ng/umbrella/commit/c63058e)) +* **shader-ast-js:** add/fix vec4 ops ([7f7f1f6](https://github.com/thi-ng/umbrella/commit/7f7f1f6)) +* **shader-ast-js:** avoid extraneous semicolons ([2b56c91](https://github.com/thi-ng/umbrella/commit/2b56c91)) +* **shader-ast-js:** op2 int handling, update vectors/matrices imports, update pkg ([dc54ec2](https://github.com/thi-ng/umbrella/commit/dc54ec2)) +* **shader-ast-js:** op2 type hint interpretation ([fdaac1f](https://github.com/thi-ng/umbrella/commit/fdaac1f)) + + +### Features + +* **shader-ast-js:** add % operator support ([c1b25c6](https://github.com/thi-ng/umbrella/commit/c1b25c6)) +* **shader-ast-js:** add array init, more builtin stubs, minor refactor ([fb5141e](https://github.com/thi-ng/umbrella/commit/fb5141e)) +* **shader-ast-js:** add missing texture lookup stubs ([f0370b0](https://github.com/thi-ng/umbrella/commit/f0370b0)) +* **shader-ast-js:** add post-inc/dec support, update op1 handler ([8073edd](https://github.com/thi-ng/umbrella/commit/8073edd)) +* **shader-ast-js:** add uvec ops, update imports ([5dcd39f](https://github.com/thi-ng/umbrella/commit/5dcd39f)) +* **shader-ast-js:** extract JS codegen & runtime as own pkg ([8177469](https://github.com/thi-ng/umbrella/commit/8177469)) +* **shader-ast-js:** int/uint/ivec support, while loop, fix bool ([003069e](https://github.com/thi-ng/umbrella/commit/003069e)) diff --git a/packages/shader-ast-js/LICENSE b/packages/shader-ast-js/LICENSE new file mode 100644 index 0000000000..8dada3edaf --- /dev/null +++ b/packages/shader-ast-js/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/packages/shader-ast-js/README.md b/packages/shader-ast-js/README.md new file mode 100644 index 0000000000..319f01d8e5 --- /dev/null +++ b/packages/shader-ast-js/README.md @@ -0,0 +1,104 @@ +# @thi.ng/shader-ast-js + +[![npm (scoped)](https://img.shields.io/npm/v/@thi.ng/shader-ast-js.svg)](https://www.npmjs.com/package/@thi.ng/shader-ast-js) +![npm downloads](https://img.shields.io/npm/dm/@thi.ng/shader-ast-js.svg) +[![Twitter Follow](https://img.shields.io/twitter/follow/thing_umbrella.svg?style=flat-square&label=twitter)](https://twitter.com/thing_umbrella) + +This project is part of the +[@thi.ng/umbrella](https://github.com/thi-ng/umbrella/) monorepo. + + + +- [About](#about) + - [Unsupported features](#unsupported-features) +- [Installation](#installation) +- [Dependencies](#dependencies) +- [Usage examples](#usage-examples) +- [Authors](#authors) +- [License](#license) + + + +## About + +JavaScript code generator, compiler & runtime for +[@thi.ng/shader-ast](https://github.com/thi-ng/umbrella/tree/master/packages/shader-ast). + +Due to lack of native vector operations in JS, this compile target is +much more involved than GLSL and uses a pluggable backend to perform all +math ops. The default backend delegates all ops to +[@thi.ng/vectors](https://github.com/thi-ng/umbrella/tree/master/packages/vectors) +and +[@thi.ng/matrices](https://github.com/thi-ng/umbrella/tree/master/packages/matrices), +which altogether provide ~750 optimized vector/matrix functions. + +### Unsupported features + +- texture lookups (see [texture tunnel + demo](https://github.com/thi-ng/umbrella/tree/master/examples/shader-ast-tunnel) + for a monkey-patched solution) +- derivatives (`dFdx`, `dFdy`, `fwidth`) - probably never supported in + this env +- `out` / `inout` function args (see [#96](https://github.com/thi-ng/umbrella/issues/96) for discussion) + +## Installation + +```bash +yarn add @thi.ng/shader-ast-js +``` + +## Dependencies + +- [@thi.ng/api](https://github.com/thi-ng/umbrella/tree/master/packages/api) +- [@thi.ng/checks](https://github.com/thi-ng/umbrella/tree/master/packages/checks) +- [@thi.ng/errors](https://github.com/thi-ng/umbrella/tree/master/packages/errors) +- [@thi.ng/matrices](https://github.com/thi-ng/umbrella/tree/master/packages/matrices) +- [@thi.ng/math](https://github.com/thi-ng/umbrella/tree/master/packages/math) +- [@thi.ng/shader-ast](https://github.com/thi-ng/umbrella/tree/master/packages/shader-ast) +- [@thi.ng/vectors](https://github.com/thi-ng/umbrella/tree/master/packages/vectors) + +## Usage examples + +Commented examples: + +(Possibly non-exhaustive list, live demo links in readme's) + +- [Canvas2D shader](https://github.com/thi-ng/umbrella/tree/master/examples/shader-ast-canvas2d) +- [2D SDF](https://github.com/thi-ng/umbrella/tree/master/examples/shader-ast-sdf2d) +- [Simplex noise](https://github.com/thi-ng/umbrella/tree/master/examples/shader-ast-noise) +- [Raymarching](https://github.com/thi-ng/umbrella/tree/master/examples/shader-ast-raymarch) +- [Textured tunnel](https://github.com/thi-ng/umbrella/tree/master/examples/shader-ast-tunnel) + +```ts +// AST node functions from main shader-ast pkg +import { + mul, + defn, + float, + ret, + vec3 +} from "@thi.ng/shader-ast"; + +// codegen / compiler +import { targetJS } from "@thi.ng/shader-ast-js"; + +const js = targetJS(); + +const hello = defn("vec4", "hello", [["float"]], (n) => [ + ret(vec4(mul(vec3(1, 2, 3), n), -1)) +]); + +js(hello) + +const Module = js.compile(hello); +Module.hello(10); +// [10, 20, 30, -1] +``` + +## Authors + +- Karsten Schmidt + +## License + +© 2018 Karsten Schmidt // Apache Software License 2.0 diff --git a/packages/shader-ast-js/package.json b/packages/shader-ast-js/package.json new file mode 100644 index 0000000000..20e889dd51 --- /dev/null +++ b/packages/shader-ast-js/package.json @@ -0,0 +1,59 @@ +{ + "name": "@thi.ng/shader-ast-js", + "version": "0.1.0", + "description": "Customizable JS code generator, compiler & runtime for @thi.ng/shader-ast", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", + "typings": "./index.d.ts", + "repository": { + "type": "git", + "url": "https://github.com/thi-ng/umbrella.git" + }, + "homepage": "https://github.com/thi-ng/umbrella/tree/master/packages/shader-ast-js", + "author": "Karsten Schmidt ", + "license": "Apache-2.0", + "scripts": { + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module", + "test": "rimraf build && tsc -p test/tsconfig.json && nyc mocha build/test/*.js", + "clean": "rimraf *.js *.d.ts .nyc_output build coverage doc lib codegen std", + "cover": "yarn test && nyc report --reporter=lcov", + "doc": "node_modules/.bin/typedoc --mode modules --out doc src", + "pub": "yarn build && yarn publish --access public" + }, + "devDependencies": { + "@types/mocha": "^5.2.6", + "@types/node": "^12.0.8", + "mocha": "^6.1.4", + "nyc": "^14.0.0", + "typedoc": "^0.14.2", + "typescript": "^3.5.2" + }, + "dependencies": { + "@thi.ng/api": "^6.3.0", + "@thi.ng/checks": "^2.2.0", + "@thi.ng/errors": "^1.1.0", + "@thi.ng/math": "^1.4.0", + "@thi.ng/matrices": "^0.5.0", + "@thi.ng/shader-ast": "^0.1.0", + "@thi.ng/vectors": "^3.0.0" + }, + "keywords": [ + "AST", + "crosscompiler", + "code generator", + "DSL", + "emulator", + "ES6", + "GLSL", + "shader", + "typescript", + "webgl" + ], + "publishConfig": { + "access": "public" + }, + "sideEffects": false +} diff --git a/packages/shader-ast-js/src/index.ts b/packages/shader-ast-js/src/index.ts new file mode 100644 index 0000000000..1434fa24f7 --- /dev/null +++ b/packages/shader-ast-js/src/index.ts @@ -0,0 +1,2 @@ +export * from "./runtime"; +export * from "./target"; diff --git a/packages/shader-ast-js/src/runtime.ts b/packages/shader-ast-js/src/runtime.ts new file mode 100644 index 0000000000..1acb086b1b --- /dev/null +++ b/packages/shader-ast-js/src/runtime.ts @@ -0,0 +1,32 @@ +import { Fn } from "@thi.ng/api"; +import { clamp01 } from "@thi.ng/math"; + +export interface RuntimeOpts { + canvas: HTMLCanvasElement; +} +export const initRuntime = (opts: RuntimeOpts) => { + const W = opts.canvas.width; + const H = opts.canvas.height - 1; + const ctx = opts.canvas.getContext("2d")!; + const img = ctx.getImageData(0, 0, W, H); + const u32 = new Uint32Array(img.data.buffer); + return { + update(fn: Fn) { + const frag = []; + for (let y = 0, i = 0; y <= H; y++) { + frag[1] = H - y; + for (let x = 0; x < W; x++) { + frag[0] = x; + u32[i++] = rgba2bgra(fn(frag)); + } + } + ctx.putImageData(img, 0, 0); + } + }; +}; + +const rgba2bgra = (rgba: number[]) => + ((clamp01(rgba[0]) * 0xff) << 0) | + ((clamp01(rgba[1]) * 0xff) << 8) | + ((clamp01(rgba[2]) * 0xff) << 16) | + ((clamp01(rgba[3]) * 0xff) << 24); diff --git a/packages/shader-ast-js/src/target.ts b/packages/shader-ast-js/src/target.ts new file mode 100644 index 0000000000..45cc23051c --- /dev/null +++ b/packages/shader-ast-js/src/target.ts @@ -0,0 +1,1238 @@ +import { + Fn, + Fn2, + Fn3, + Fn4, + Fn5, + Fn6 +} from "@thi.ng/api"; +import { isBoolean, isNumber } from "@thi.ng/checks"; +import { unsupported } from "@thi.ng/errors"; +import { + clamp, + deg, + fmod, + fract, + mix, + rad, + smoothStep, + step +} from "@thi.ng/math"; +import { + add22, + add33, + add44, + addN22, + addN33, + addN44, + div22, + div33, + div44, + divN22, + divN33, + divN44, + Mat, + mat22n, + mat22v, + mat33n, + mat33v, + mat44n, + mat44v, + mul22, + mul33, + mul44, + mulM22, + mulM33, + mulM44, + mulN22, + mulN33, + mulN44, + mulV22, + mulV33, + mulV44, + mulVM22, + mulVM33, + mulVM44, + sub22, + sub33, + sub44, + subN22, + subN33, + subN44 +} from "@thi.ng/matrices"; +import { + defTarget, + Func, + isBool, + isInt, + isMat, + isUint, + isVec, + Lit, + Operator, + Scope, + Swizzle, + Sym, + Term +} from "@thi.ng/shader-ast"; +import { + abs2, + abs3, + abs4, + acos2, + acos3, + acos4, + add2, + add3, + add4, + addI2, + addI3, + addI4, + addN2, + addN3, + addN4, + addNI2, + addNI3, + addNI4, + addNU2, + addNU3, + addNU4, + addU2, + addU3, + addU4, + asin2, + asin3, + asin4, + atan2, + atan3, + atan4, + bitAndI2, + bitAndI3, + bitAndI4, + bitAndU2, + bitAndU3, + bitAndU4, + bitNotI2, + bitNotI3, + bitNotI4, + bitNotU2, + bitNotU3, + bitNotU4, + bitOrI2, + bitOrI3, + bitOrI4, + bitOrU2, + bitOrU3, + bitOrU4, + bitXorI2, + bitXorI3, + bitXorI4, + bitXorU2, + bitXorU3, + bitXorU4, + ceil2, + ceil3, + ceil4, + clamp2, + clamp3, + clamp4, + cos2, + cos3, + cos4, + cross3, + degrees2, + degrees3, + degrees4, + dist, + div2, + div3, + div4, + divI2, + divI3, + divI4, + divN2, + divN3, + divN4, + divNI2, + divNI3, + divNI4, + divNU2, + divNU3, + divNU4, + divU2, + divU3, + divU4, + dot2, + dot3, + dot4, + exp_22, + exp_23, + exp_24, + exp2, + exp3, + exp4, + faceForward, + floor2, + floor3, + floor4, + fmod2, + fmod3, + fmod4, + fmodN2, + fmodN3, + fmodN4, + fract2, + fract3, + fract4, + invSqrt2, + invSqrt3, + invSqrt4, + log_22, + log_23, + log_24, + log2, + log3, + log4, + lshiftI2, + lshiftI3, + lshiftI4, + lshiftU2, + lshiftU3, + lshiftU4, + mag, + max2, + max3, + max4, + min2, + min3, + min4, + mix2, + mix3, + mix4, + mixN2, + mixN3, + mixN4, + mod2, + mod3, + mod4, + modN2, + modN3, + modN4, + mul2, + mul3, + mul4, + mulI2, + mulI3, + mulI4, + mulN2, + mulN3, + mulN4, + mulNI2, + mulNI3, + mulNI4, + mulNU2, + mulNU3, + mulNU4, + mulU2, + mulU3, + mulU4, + neg, + normalize, + pow2, + pow3, + pow4, + radians2, + radians3, + radians4, + reflect, + refract, + rshiftI2, + rshiftI3, + rshiftI4, + rshiftU2, + rshiftU3, + rshiftU4, + setSwizzle2, + setSwizzle3, + setSwizzle4, + setVN3, + setVN4, + setVV4, + sign2, + sign3, + sign4, + sin2, + sin3, + sin4, + smoothStep2, + smoothStep3, + smoothStep4, + sqrt2, + sqrt3, + sqrt4, + step2, + step3, + step4, + sub2, + sub3, + sub4, + subI2, + subI3, + subI4, + subN2, + subN3, + subN4, + subNI2, + subNI3, + subNI4, + subNU2, + subNU3, + subNU4, + subU2, + subU3, + subU4, + swizzle2, + swizzle3, + swizzle4, + tan2, + tan3, + tan4, + Vec, + vecOf, + ZERO2, + ZERO3, + ZERO4 +} from "@thi.ng/vectors"; + +export interface JSTarget extends Fn, string> { + /** + * Compiles given AST to JavaScript, using optional `env` as backend + * for various operators / builtins. If `env` is not given the + * bundled `JS_DEFAULT_ENV` is used (based on thi.ng/vectors and + * thi.ng/matrices packages). + * + * Any functions defined in the given AST will be exported using + * their defined name via the returned object. + * + * ``` + * const js = targetJS(); + * const module = js.compile( + * defn("float", "foo", [["float"]], (x)=> [ret(mul(x, float(10)))]) + * ); + * + * module.foo(42) + * // 420 + * + * module.foo.toString() + * // function foo(_sym0) { + * // return (_sym0 * 10); + * // } + * ``` + * + * @param tree + * @param env + */ + compile(tree: Term, env?: JSEnv): any; +} + +export interface JSBuiltinsCommon { + abs: Fn; + clamp: Fn3; + max: Fn2; + min: Fn2; + sign: Fn; +} + +export interface JSBuiltinsMath { + sub1: Fn; + add: Fn2; + sub: Fn2; + mul: Fn2; + div: Fn2; + inc: Fn; + dec: Fn; +} + +export interface JSBuiltinsBinary { + bitand: Fn2; + lshift: Fn2; + bitnot1: Fn2; + bitor: Fn2; + rshift: Fn2; + bitxor: Fn2; +} + +export interface JSBuiltinsFloat extends JSBuiltinsCommon { + acos: Fn; + asin: Fn; + atan: Fn; + ceil: Fn; + cos: Fn; + degrees: Fn; + dFdx: Fn; + dFdy: Fn; + exp: Fn; + exp2: Fn; + floor: Fn; + fract: Fn; + fwidth: Fn; + inversesqrt: Fn; + log: Fn; + log2: Fn; + mix: Fn3; + mixn: Fn3; + mod: Fn2; + modn: Fn2; + pow: Fn2; + radians: Fn; + sin: Fn; + smoothstep: Fn3; + sqrt: Fn; + step: Fn2; + tan: Fn; +} + +export interface JSBuiltinsInt + extends JSBuiltinsCommon, + JSBuiltinsMath, + JSBuiltinsBinary { + modi: Fn2; +} + +export interface JSBuiltinsVecScalar { + addvn: Fn2; + subvn: Fn2; + mulvn: Fn2; + divvn: Fn2; + addnv: Fn2; + subnv: Fn2; + mulnv: Fn2; + divnv: Fn2; +} + +export interface JSBuiltinsVec + extends JSBuiltinsFloat, + JSBuiltinsMath, + JSBuiltinsVecScalar { + distance: Fn2; + dot: Fn2; + faceForward: Fn3; + length: Fn; + normalize: Fn; + reflect: Fn2; + refract: Fn3; +} + +export interface JSBuiltinsVec3 extends JSBuiltinsVec { + cross: Fn2; +} + +export interface JSBuiltinsIntVec + extends JSBuiltinsInt, + JSBuiltinsVecScalar, + JSBuiltinsBinary { + modivn: Fn2; + modinv: Fn2; +} + +export interface JSBuiltinsMat + extends JSBuiltinsMath, + JSBuiltinsVecScalar { + mulm: Fn2; + mulvm: Fn2; + mulmv: Fn2; +} + +export interface JSBuiltinsSampler { + texelFetch: Fn3; + texelFetchOffset: Fn4; + texture: Fn3; + texturen: Fn3; + textureGrad: Fn4; + textureGradn: Fn4; + textureLod: Fn3; + textureLodn: Fn3; + textureOffset: Fn4; + textureOffsetn: Fn4; + textureProj: Fn3; + textureProjn: Fn3; + textureSize: Fn2; +} + +export interface JSEnv { + vec2n: Fn; + vec3n: Fn; + vec3vn: Fn2; + vec4n: Fn; + vec4vn: Fn2; + vec4vnn: Fn3; + vec4vv: Fn2; + mat2n: Fn; + mat2vv: Fn2; + mat3n: Fn; + mat3vvv: Fn3; + mat4n: Fn; + mat4vvvv: Fn4; + // swizzle1: Fn2; + swizzle2: Fn3; + swizzle3: Fn4; + swizzle4: Fn5; + // set_swizzle1: Fn3; + set_swizzle2: Fn4; + set_swizzle3: Fn5; + set_swizzle4: Fn6; + float: JSBuiltinsFloat; + int: JSBuiltinsInt; + uint: JSBuiltinsInt; + vec2: JSBuiltinsVec; + vec3: JSBuiltinsVec3; + vec4: JSBuiltinsVec; + ivec2: JSBuiltinsIntVec; + ivec3: JSBuiltinsIntVec; + ivec4: JSBuiltinsIntVec; + uvec2: JSBuiltinsIntVec; + uvec3: JSBuiltinsIntVec; + uvec4: JSBuiltinsIntVec; + mat2: JSBuiltinsMat; + mat3: JSBuiltinsMat; + mat4: JSBuiltinsMat; + sampler1D: JSBuiltinsSampler; + sampler2D: JSBuiltinsSampler; + sampler3D: JSBuiltinsSampler; + samplerCube: JSBuiltinsSampler; + sampler2DShadow: JSBuiltinsSampler; + samplerCubeShadow: JSBuiltinsSampler; +} + +// TODO texture lookups +// all texture fns currently return [0,0,0,0] or 0 +const SAMPLER_TODO: JSBuiltinsSampler = { + texelFetch: () => ZERO4, + texelFetchOffset: () => ZERO4, + texture: () => ZERO4, + texturen: () => 0, + textureGrad: () => ZERO4, + textureGradn: () => 0, + textureLod: () => ZERO4, + textureLodn: () => 0, + textureOffset: () => ZERO4, + textureOffsetn: () => 0, + textureProj: () => ZERO4, + textureProjn: () => 0, + textureSize: () => ZERO3 +}; + +const env: Partial = { + vec2n: (n) => [n, n], + vec3n: (n) => [n, n, n], + vec4n: (n) => [n, n, n, n], + vec3vn: (a, n) => setVN3([], a, n), + vec4vn: (a, n) => setVN4([], a, n), + vec4vnn: (a, z, w) => setVV4([], a, [z, w]), + vec4vv: (a, b) => setVV4([], a, b), + mat2n: (n) => mat22n([], n), + mat2vv: (a, b) => mat22v([], a, b), + mat3n: (n) => mat33n([], n), + mat3vvv: (a, b, c) => mat33v([], a, b, c), + mat4n: (n) => mat44n([], n), + mat4vvvv: (a, b, c, d) => mat44v([], a, b, c, d), + swizzle2: (a, b, c) => swizzle2([], a, b, c), + swizzle3: (a, b, c, d) => swizzle3([], a, b, c, d), + swizzle4: (a, b, c, d, e) => swizzle4([], a, b, c, d, e), + set_swizzle2: setSwizzle2, + set_swizzle3: setSwizzle3, + set_swizzle4: setSwizzle4, + float: { + abs: Math.abs, + acos: Math.acos, + asin: Math.asin, + atan: Math.atan, + ceil: Math.ceil, + clamp, + cos: Math.cos, + degrees: deg, + dFdx: () => 0, + dFdy: () => 0, + exp: Math.exp, + exp2: (x) => Math.pow(2, x), + floor: Math.floor, + fract, + fwidth: () => 0, + inversesqrt: (x) => 1 / Math.sqrt(x), + log: Math.log, + log2: Math.log2, + max: Math.max, + min: Math.min, + mix, + mixn: mix, + mod: fmod, + modn: fmod, + pow: Math.pow, + radians: rad, + sign: Math.sign, + sin: Math.sin, + smoothstep: smoothStep, + sqrt: Math.sqrt, + step, + tan: Math.tan + }, + int: { + abs: Math.abs, + add: (a, b) => (a + b) | 0, + bitand: (a, b) => a & b, + bitnot1: (a) => ~a, + bitor: (a, b) => a | b, + bitxor: (a, b) => a ^ b, + clamp, + dec: (a) => (a - 1) | 0, + div: (a, b) => (a / b) | 0, + inc: (a) => (a + 1) | 0, + lshift: (a, b) => a << b, + max: Math.max, + min: Math.min, + modi: (a, b) => a % b, + mul: (a, b) => (a * b) | 0, + rshift: (a, b) => a >> b, + sign: Math.sign, + sub: (a, b) => (a - b) | 0, + sub1: (a) => -a | 0 + }, + uint: { + abs: Math.abs, + add: (a, b) => (a + b) >>> 0, + bitand: (a, b) => (a & b) >>> 0, + bitnot1: (a) => ~a >>> 0, + bitor: (a, b) => (a | b) >>> 0, + bitxor: (a, b) => (a ^ b) >>> 0, + clamp, + dec: (a) => (a - 1) >>> 0, + div: (a, b) => (a / b) >>> 0, + inc: (a) => (a + 1) >>> 0, + lshift: (a, b) => (a << b) >>> 0, + max: Math.max, + min: Math.min, + modi: (a, b) => a % b, + mul: (a, b) => (a * b) >>> 0, + rshift: (a, b) => a >>> b, + sign: Math.sign, + sub: (a, b) => (a - b) >>> 0, + sub1: (a) => -a >>> 0 + }, + vec2: { + abs: (a) => abs2([], a), + acos: (a) => acos2([], a), + add: (a, b) => add2([], a, b), + addnv: (a, b) => addN2([], b, a), + addvn: (a, b) => addN2([], a, b), + asin: (a) => asin2([], a), + atan: (a) => atan2([], a), + ceil: (a) => ceil2([], a), + clamp: (x, a, b) => clamp2([], x, a, b), + cos: (a) => cos2([], a), + dec: (a) => subN2([], a, 1), + degrees: (a) => degrees2([], a), + dFdx: () => ZERO2, + dFdy: () => ZERO2, + distance: dist, + div: (a, b) => div2([], a, b), + divnv: (a, b) => mulN2([], b, 1 / a), + divvn: (a, b) => divN2([], a, b), + dot: (a, b) => dot2(a, b), + exp: (a) => exp2([], a), + exp2: (a) => exp_22([], a), + faceForward: (a, b, c) => faceForward([], a, b, c), + floor: (a) => floor2([], a), + fract: (a) => fract2([], a), + fwidth: () => ZERO2, + inc: (a) => addN2([], a, 1), + inversesqrt: (a) => invSqrt2([], a), + length: mag, + log: (a) => log2([], a), + log2: (a) => log_22([], a), + max: (a, b) => max2([], a, b), + min: (a, b) => min2([], a, b), + mix: (a, b, t) => mix2([], a, b, t), + mixn: (a, b, t) => mixN2([], a, b, t), + mod: (a, b) => fmod2([], a, b), + modn: (a, b) => fmodN2([], a, b), + mul: (a, b) => mul2([], a, b), + mulnv: (a, b) => mulN2([], b, a), + mulvn: (a, b) => mulN2([], a, b), + normalize: (a) => normalize([], a), + pow: (a, b) => pow2([], a, b), + radians: (a) => radians2([], a), + reflect: (a, b) => reflect([], a, b), + refract: (a, b, c) => refract([], a, b, c), + sign: (a) => sign2([], a), + sin: (a) => sin2([], a), + smoothstep: (a, b, t) => smoothStep2([], a, b, t), + sqrt: (a) => sqrt2([], a), + step: (a, b) => step2([], a, b), + sub: (a, b) => sub2([], a, b), + sub1: (a) => neg([], a), + subnv: (a, b) => sub2(null, [a, a], b), + subvn: (a, b) => subN2([], a, b), + tan: (a) => tan2([], a) + }, + vec3: { + abs: (a) => abs3([], a), + acos: (a) => acos3([], a), + add: (a, b) => add3([], a, b), + addnv: (a, b) => addN3([], b, a), + addvn: (a, b) => addN3([], a, b), + asin: (a) => asin3([], a), + atan: (a) => atan3([], a), + ceil: (a) => ceil3([], a), + clamp: (x, a, b) => clamp3([], x, a, b), + cos: (a) => cos3([], a), + cross: (a, b) => cross3([], a, b), + dec: (a) => subN3([], a, 1), + degrees: (a) => degrees3([], a), + dFdx: () => ZERO3, + dFdy: () => ZERO3, + distance: dist, + div: (a, b) => div3([], a, b), + divnv: (a, b) => mulN3([], b, 1 / a), + divvn: (a, b) => divN3([], a, b), + dot: (a, b) => dot3(a, b), + exp: (a) => exp3([], a), + exp2: (a) => exp_23([], a), + faceForward: (a, b, c) => faceForward([], a, b, c), + floor: (a) => floor3([], a), + fract: (a) => fract3([], a), + fwidth: () => ZERO3, + inc: (a) => addN3([], a, 1), + inversesqrt: (a) => invSqrt3([], a), + length: mag, + log: (a) => log3([], a), + log2: (a) => log_23([], a), + max: (a, b) => max3([], a, b), + min: (a, b) => min3([], a, b), + mix: (a, b, t) => mix3([], a, b, t), + mixn: (a, b, t) => mixN3([], a, b, t), + mod: (a, b) => fmod3([], a, b), + modn: (a, b) => fmodN3([], a, b), + mul: (a, b) => mul3([], a, b), + mulnv: (a, b) => mulN3([], b, a), + mulvn: (a, b) => mulN3([], a, b), + normalize: (a) => normalize([], a), + pow: (a, b) => pow3([], a, b), + radians: (a) => radians3([], a), + reflect: (a, b) => reflect([], a, b), + refract: (a, b, c) => refract([], a, b, c), + sign: (a) => sign3([], a), + sin: (a) => sin3([], a), + smoothstep: (a, b, t) => smoothStep3([], a, b, t), + sqrt: (a) => sqrt3([], a), + step: (a, b) => step3([], a, b), + sub: (a, b) => sub3([], a, b), + sub1: (a) => neg([], a), + subnv: (a, b) => sub3(null, [a, a, a], b), + subvn: (a, b) => subN3([], a, b), + tan: (a) => tan3([], a) + }, + vec4: { + abs: (a) => abs4([], a), + acos: (a) => acos4([], a), + add: (a, b) => add4([], a, b), + addnv: (a, b) => addN4([], b, a), + addvn: (a, b) => addN4([], a, b), + asin: (a) => asin4([], a), + atan: (a) => atan4([], a), + ceil: (a) => ceil4([], a), + clamp: (x, a, b) => clamp4([], x, a, b), + cos: (a) => cos4([], a), + dec: (a) => subN4([], a, 1), + degrees: (a) => degrees4([], a), + dFdx: () => ZERO4, + dFdy: () => ZERO4, + distance: dist, + div: (a, b) => div4([], a, b), + divnv: (a, b) => mulN4([], b, 1 / a), + divvn: (a, b) => divN4([], a, b), + dot: (a, b) => dot4(a, b), + exp: (a) => exp4([], a), + exp2: (a) => exp_24([], a), + faceForward: (a, b, c) => faceForward([], a, b, c), + floor: (a) => floor4([], a), + fract: (a) => fract4([], a), + fwidth: () => ZERO4, + inc: (a) => addN4([], a, 1), + inversesqrt: (a) => invSqrt4([], a), + length: mag, + log: (a) => log4([], a), + log2: (a) => log_24([], a), + max: (a, b) => max4([], a, b), + min: (a, b) => min4([], a, b), + mix: (a, b, t) => mix4([], a, b, t), + mixn: (a, b, t) => mixN4([], a, b, t), + mod: (a, b) => fmod4([], a, b), + modn: (a, b) => fmodN4([], a, b), + mul: (a, b) => mul4([], a, b), + mulnv: (a, b) => mulN4([], b, a), + mulvn: (a, b) => mulN4([], a, b), + normalize: (a) => normalize([], a), + pow: (a, b) => pow4([], a, b), + radians: (a) => radians4([], a), + reflect: (a, b) => reflect([], a, b), + refract: (a, b, c) => refract([], a, b, c), + sign: (a) => sign4([], a), + sin: (a) => sin4([], a), + smoothstep: (a, b, t) => smoothStep4([], a, b, t), + sqrt: (a) => sqrt4([], a), + step: (a, b) => step4([], a, b), + sub: (a, b) => sub4([], a, b), + sub1: (a) => neg([], a), + subnv: (a, b) => sub4(null, [a, a, a, a], b), + subvn: (a, b) => subN4([], a, b), + tan: (a) => tan4([], a) + }, + mat2: { + add: (a, b) => add22([], a, b), + addnv: (a, b) => addN22([], b, a), + addvn: (a, b) => addN22([], a, b), + dec: (a) => subN22([], a, 1), + div: (a, b) => div22([], a, b), + divnv: (a, b) => mulN22([], b, 1 / a), + divvn: (a, b) => divN22([], a, b), + inc: (a) => addN22([], a, 1), + mul: (a, b) => mul22([], a, b), + mulm: (a, b) => mulM22([], a, b), + mulmv: (a, b) => mulV22([], a, b), + mulnv: (a, b) => mulN22([], b, a), + mulvm: (a, b) => mulVM22([], a, b), + mulvn: (a, b) => mulN22([], a, b), + sub: (a, b) => sub22([], a, b), + sub1: (a) => neg([], a), + subnv: (a, b) => sub22(null, [a, a, a, a], b), + subvn: (a, b) => subN22([], a, b) + }, + mat3: { + add: (a, b) => add33([], a, b), + addnv: (a, b) => addN33([], b, a), + addvn: (a, b) => addN33([], a, b), + dec: (a) => subN33([], a, 1), + div: (a, b) => div33([], a, b), + divnv: (a, b) => mulN33([], b, 1 / a), + divvn: (a, b) => divN33([], a, b), + inc: (a) => addN33([], a, 1), + mul: (a, b) => mul33([], a, b), + mulm: (a, b) => mulM33([], a, b), + mulmv: (a, b) => mulV33([], a, b), + mulnv: (a, b) => mulN33([], b, a), + mulvm: (a, b) => mulVM33([], a, b), + mulvn: (a, b) => mulN33([], a, b), + sub: (a, b) => sub33([], a, b), + sub1: (a) => neg([], a), + subnv: (a, b) => sub33(null, vecOf(9, a), b), + subvn: (a, b) => subN33([], a, b) + }, + mat4: { + add: (a, b) => add44([], a, b), + addnv: (a, b) => addN44([], b, a), + addvn: (a, b) => addN44([], a, b), + dec: (a) => subN44([], a, 1), + div: (a, b) => div44([], a, b), + divnv: (a, b) => mulN44([], b, 1 / a), + divvn: (a, b) => divN44([], a, b), + inc: (a) => addN44([], a, 1), + mul: (a, b) => mul44([], a, b), + mulm: (a, b) => mulM44([], a, b), + mulmv: (a, b) => mulV44([], a, b), + mulnv: (a, b) => mulN44([], b, a), + mulvm: (a, b) => mulVM44([], a, b), + mulvn: (a, b) => mulN44([], a, b), + sub: (a, b) => sub44([], a, b), + sub1: (a) => neg([], a), + subnv: (a, b) => sub44(null, vecOf(16, a), b), + subvn: (a, b) => subN44([], a, b) + }, + sampler1D: SAMPLER_TODO, + sampler2D: SAMPLER_TODO, + sampler3D: SAMPLER_TODO, + samplerCube: SAMPLER_TODO, + sampler2DShadow: SAMPLER_TODO, + samplerCubeShadow: SAMPLER_TODO +}; + +env.ivec2 = { + ...env.vec2!, + add: (a, b) => addI2([], a, b), + addvn: (a, b) => addNI2([], a, b), + addnv: (a, b) => addNI2([], b, a), + div: (a, b) => divI2([], a, b), + divvn: (a, b) => divNI2([], a, b), + divnv: (a, b) => mulNI2([], b, 1 / a), + modi: (a, b) => mod2([], a, b), + modivn: (a, b) => modN2([], a, b), + modinv: (a, b) => mod2([], [a, a], b), + mul: (a, b) => mulI2([], a, b), + mulvn: (a, b) => mulNI2([], a, b), + mulnv: (a, b) => mulNI2([], b, a), + sub: (a, b) => subI2([], a, b), + subvn: (a, b) => subNI2([], a, b), + subnv: (a, b) => subI2([], [a, a], b), + bitand: (a, b) => bitAndI2([], a, b), + lshift: (a, b) => lshiftI2([], a, b), + bitnot1: (a) => bitNotI2([], a), + bitor: (a, b) => bitOrI2([], a, b), + rshift: (a, b) => rshiftI2([], a, b), + bitxor: (a, b) => bitXorI2([], a, b) +}; + +env.ivec3 = { + ...env.vec3!, + add: (a, b) => addI3([], a, b), + addvn: (a, b) => addNI3([], a, b), + addnv: (a, b) => addNI3([], b, a), + div: (a, b) => divI3([], a, b), + divvn: (a, b) => divNI3([], a, b), + divnv: (a, b) => mulNI3([], b, 1 / a), + modi: (a, b) => mod3([], a, b), + modivn: (a, b) => modN3([], a, b), + modinv: (a, b) => mod3([], [a, a, a], b), + mul: (a, b) => mulI3([], a, b), + mulvn: (a, b) => mulNI3([], a, b), + mulnv: (a, b) => mulNI3([], b, a), + sub: (a, b) => subI3([], a, b), + subvn: (a, b) => subNI3([], a, b), + subnv: (a, b) => subI3([], [a, a, a], b), + bitand: (a, b) => bitAndI3([], a, b), + lshift: (a, b) => lshiftI3([], a, b), + bitnot1: (a) => bitNotI3([], a), + bitor: (a, b) => bitOrI3([], a, b), + rshift: (a, b) => rshiftI3([], a, b), + bitxor: (a, b) => bitXorI3([], a, b) +}; + +env.ivec4 = { + ...env.vec4!, + add: (a, b) => addI4([], a, b), + addvn: (a, b) => addNI4([], a, b), + addnv: (a, b) => addNI4([], b, a), + div: (a, b) => divI4([], a, b), + divvn: (a, b) => divNI4([], a, b), + divnv: (a, b) => mulNI4([], b, 1 / a), + modi: (a, b) => mod4([], a, b), + modivn: (a, b) => modN4([], a, b), + modinv: (a, b) => mod4([], [a, a, a, a], b), + mul: (a, b) => mulI4([], a, b), + mulvn: (a, b) => mulNI4([], a, b), + mulnv: (a, b) => mulNI4([], b, a), + sub: (a, b) => subI4([], a, b), + subvn: (a, b) => subNI4([], a, b), + subnv: (a, b) => subI4([], [a, a, a, a], b), + bitand: (a, b) => bitAndI4([], a, b), + lshift: (a, b) => lshiftI4([], a, b), + bitnot1: (a) => bitNotI4([], a), + bitor: (a, b) => bitOrI4([], a, b), + rshift: (a, b) => rshiftI4([], a, b), + bitxor: (a, b) => bitXorI4([], a, b) +}; + +env.uvec2 = { + ...env.vec2!, + add: (a, b) => addU2([], a, b), + addvn: (a, b) => addNU2([], a, b), + addnv: (a, b) => addNU2([], b, a), + div: (a, b) => divU2([], a, b), + divvn: (a, b) => divNU2([], a, b), + divnv: (a, b) => mulNU2([], b, 1 / a), + modi: (a, b) => mod2([], a, b), + modivn: (a, b) => modN2([], a, b), + modinv: (a, b) => mod2([], [a, a], b), + mul: (a, b) => mulU2([], a, b), + mulvn: (a, b) => mulNU2([], a, b), + mulnv: (a, b) => mulNU2([], b, a), + sub: (a, b) => subU2([], a, b), + subvn: (a, b) => subNU2([], a, b), + subnv: (a, b) => subU2([], [a, a], b), + bitand: (a, b) => bitAndU2([], a, b), + lshift: (a, b) => lshiftU2([], a, b), + bitnot1: (a) => bitNotU2([], a), + bitor: (a, b) => bitOrU2([], a, b), + rshift: (a, b) => rshiftU2([], a, b), + bitxor: (a, b) => bitXorU2([], a, b) +}; + +env.uvec3 = { + ...env.vec3!, + add: (a, b) => addU3([], a, b), + addvn: (a, b) => addNU3([], a, b), + addnv: (a, b) => addNU3([], b, a), + div: (a, b) => divU3([], a, b), + divvn: (a, b) => divNU3([], a, b), + divnv: (a, b) => mulNU3([], b, 1 / a), + modi: (a, b) => mod3([], a, b), + modivn: (a, b) => modN3([], a, b), + modinv: (a, b) => mod3([], [a, a, a], b), + mul: (a, b) => mulU3([], a, b), + mulvn: (a, b) => mulNU3([], a, b), + mulnv: (a, b) => mulNU3([], b, a), + sub: (a, b) => subU3([], a, b), + subvn: (a, b) => subNU3([], a, b), + subnv: (a, b) => subU3([], [a, a, a], b), + bitand: (a, b) => bitAndU3([], a, b), + lshift: (a, b) => lshiftU3([], a, b), + bitnot1: (a) => bitNotU3([], a), + bitor: (a, b) => bitOrU3([], a, b), + rshift: (a, b) => rshiftU3([], a, b), + bitxor: (a, b) => bitXorU3([], a, b) +}; + +env.uvec4 = { + ...env.vec4!, + add: (a, b) => addU4([], a, b), + addvn: (a, b) => addNU4([], a, b), + addnv: (a, b) => addNU4([], b, a), + div: (a, b) => divU4([], a, b), + divvn: (a, b) => divNU4([], a, b), + divnv: (a, b) => mulNU4([], b, 1 / a), + modi: (a, b) => mod4([], a, b), + modivn: (a, b) => modN4([], a, b), + modinv: (a, b) => mod4([], [a, a, a, a], b), + mul: (a, b) => mulU4([], a, b), + mulvn: (a, b) => mulNU4([], a, b), + mulnv: (a, b) => mulNU4([], b, a), + sub: (a, b) => subU4([], a, b), + subvn: (a, b) => subNU4([], a, b), + subnv: (a, b) => subU4([], [a, a, a, a], b), + bitand: (a, b) => bitAndU4([], a, b), + lshift: (a, b) => lshiftU4([], a, b), + bitnot1: (a) => bitNotU4([], a), + bitor: (a, b) => bitOrU4([], a, b), + rshift: (a, b) => rshiftU4([], a, b), + bitxor: (a, b) => bitXorU4([], a, b) +}; + +export const JS_DEFAULT_ENV = env; + +export const targetJS = () => { + const CMP_OPS: Partial> = { + "!": "not", + "<": "lt", + "<=": "lte", + "==": "eq", + "!=": "neq", + ">=": "gte", + ">": "gt" + }; + const OP_IDS: Record = { + ...(CMP_OPS), + "+": "add", + "-": "sub", + "*": "mul", + "/": "div", + "%": "modi", + "++": "inc", + "--": "dec", + "||": "or", + "&&": "and", + "|": "bitor", + "&": "bitand", + "^": "bitxor", + "~": "bitnot", + "<<": "lshift", + ">>": "rshift" + }; + + const PRELUDE = + [ + "float", + "int", + "uint", + "vec2", + "vec3", + "vec4", + "ivec2", + "ivec3", + "ivec4", + "uvec2", + "uvec3", + "uvec4", + "mat2", + "mat3", + "mat4", + "sampler2D", + "sampler3D", + "samplerCube", + "sampler2DShadow", + "samplerCubeShadow" + ] + .map((x) => `const ${x} = env.${x};`) + .join("\n") + "\n"; + + const COMPS: any = { x: 0, y: 1, z: 2, w: 3 }; + + const RE_SEMI = /[};]$/; + + const $list = (body: Term[], sep = ", ") => body.map(emit).join(sep); + + const $docParam = (p: Sym) => ` * @param ${p.id} ${p.type}`; + + const $fn = (name: string, args: Term[]) => `${name}(${$list(args)})`; + + const $vec = ({ val, info, type }: Lit) => + !info ? `[${$list(val)}]` : `env.${type}${info}(${$list(val)})`; + + const $swizzle = (id: string) => [...id].map((x) => COMPS[x]).join(", "); + + const emit: Fn, string> = defTarget({ + arg: (t) => t.id, + + array_init: (t) => `[${$list(t.init)}]`, + + assign: (t) => { + if (t.l.tag === "swizzle") { + const s = >t.l; + return s.id.length > 1 + ? `env.set_swizzle${s.id.length}(${emit(s.val)}, ${emit( + t.r + )}, ${$swizzle(s.id)})` + : `(${emit(s.val)}[${$swizzle(s.id)}] = ${emit(t.r)})`; + } + return emit(t.l) + " = " + emit(t.r); + }, + + ctrl: (t) => t.id, + + call: (t) => $fn(t.id, t.args), + + call_i: (t) => $fn(`${t.args[0].type}.${t.id}${t.info || ""}`, t.args), + + decl: ({ type, id }) => { + const res: string[] = []; + res.push(id.opts.const ? "const" : "let"); + res.push(`/*${type}*/`); + res.push(id.id); + id.init + ? res.push("=", emit(id.init)) + : id.opts.num !== undefined + ? res.push("=", `new Array(${id.opts.num})`) + : undefined; + return res.join(" "); + }, + + fn: (t) => + "/**\n" + + t.args.map($docParam).join("\n") + + "\n */\n" + + `function ${t.id}(${$list(t.args)}) ${emit(t.scope)}`, + + for: (t) => + `for(${t.init ? emit(t.init) : ""}; ${emit(t.test)}; ${ + t.iter ? emit(t.iter) : "" + }) ${emit(t.scope)}`, + + idx: (t) => `${emit(t.val)}[${emit(t.id)}]`, + + if: (t) => { + const res = `if (${emit(t.test)}) ` + emit(t.t); + return t.f ? res + " else " + emit(t.f) : res; + }, + + lit: (t) => { + const v = t.val; + switch (t.type) { + case "bool": + return isBoolean(v) ? String(v) : `!!(${emit(v)})`; + case "float": + return isNumber(v) ? String(v) : emit(v); + case "int": + return isNumber(v) ? String(v) : `(${emit(v)} | 0)`; + case "uint": + return isNumber(v) ? String(v) : `(${emit(v)} >>> 0)`; + case "vec2": + case "vec3": + case "vec4": + case "ivec2": + case "ivec3": + case "ivec4": + case "mat2": + case "mat3": + case "mat4": + return $vec(t); + default: + return unsupported(`unknown type: ${t.type}`); + } + }, + + op1: (t) => { + const complex = isVec(t) || isMat(t) || isInt(t); + if (complex && t.post) { + const s = >t.val; + return `${s.id} = ${t.type}.${OP_IDS[t.op]}(${emit(s)})`; + } else { + return complex + ? `${t.type}.${OP_IDS[t.op]}1(${emit(t.val)})` + : t.post + ? `(${emit(t.val)}${t.op})` + : `${t.op}${emit(t.val)}`; + } + }, + + op2: (t) => { + const { l, r } = t; + const vec = + isVec(l) || isMat(l) + ? l.type + : isVec(r) || isMat(r) + ? r.type + : undefined; + const int = !vec + ? isInt(l) || isUint(l) || isBool(l) + ? l.type + : isInt(r) || isUint(r) || isBool(r) + ? r.type + : undefined + : undefined; + const el = emit(l); + const er = emit(r); + return vec || (int && !CMP_OPS[t.op]) + ? `${vec || int}.${OP_IDS[t.op]}${t.info || ""}(${el}, ${er})` + : `(${el} ${t.op} ${er})`; + }, + + ret: (t) => "return" + (t.val ? " " + emit(t.val) : ""), + + scope: (t) => { + let res = $list(t.body, ";\n"); + res += t.body.length && !RE_SEMI.test(res) ? ";" : ""; + return !t.global ? `{\n${res}\n}` : res; + }, + + swizzle: (t) => + t.id.length > 1 + ? `env.swizzle${t.id.length}(${emit(t.val)}, ${$swizzle(t.id)})` + : `${emit(t.val)}[${$swizzle(t.id)}]`, + + sym: (t) => t.id, + + ternary: (t) => `(${emit(t.test)} ? ${emit(t.t)} : ${emit(t.f)})`, + + while: (t) => `while (${emit(t.test)}) ${emit(t.scope)}` + }); + + Object.assign(emit, { + compile: (tree, env = JS_DEFAULT_ENV) => { + const exports = + tree.tag === "scope" + ? (tree).body + .filter((x) => x.tag === "fn") + .map( + (f) => + (>f).id + ": " + (>f).id + ) + .join(",\n") + : tree.tag === "fn" + ? `${(>tree).id}: ${(>tree).id}` + : ""; + return new Function( + "env", + PRELUDE + emit(tree) + "\nreturn {\n" + exports + "\n};" + )(env); + } + }); + + return emit; +}; diff --git a/packages/shader-ast-js/test/index.ts b/packages/shader-ast-js/test/index.ts new file mode 100644 index 0000000000..1f01c2dccb --- /dev/null +++ b/packages/shader-ast-js/test/index.ts @@ -0,0 +1,6 @@ +// import * as assert from "assert"; +// import * as saj from "../src/index"; + +describe("shader-ast-js", () => { + it("tests pending"); +}); diff --git a/packages/shader-ast-js/test/tsconfig.json b/packages/shader-ast-js/test/tsconfig.json new file mode 100644 index 0000000000..f6e63560dd --- /dev/null +++ b/packages/shader-ast-js/test/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../../tsconfig.json", + "compilerOptions": { + "outDir": "../build", + "module": "commonjs" + }, + "include": [ + "./**/*.ts", + "../src/**/*.ts" + ] +} diff --git a/packages/shader-ast-js/tsconfig.json b/packages/shader-ast-js/tsconfig.json new file mode 100644 index 0000000000..893b9979c5 --- /dev/null +++ b/packages/shader-ast-js/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": ".", + "module": "es6", + "target": "es6" + }, + "include": [ + "./src/**/*.ts" + ] +} diff --git a/packages/shader-ast-stdlib/.npmignore b/packages/shader-ast-stdlib/.npmignore new file mode 100644 index 0000000000..74ea62d1fa --- /dev/null +++ b/packages/shader-ast-stdlib/.npmignore @@ -0,0 +1,12 @@ +.meta +.nyc_output +*.html +*.tgz +build +coverage +dev +doc +export +src* +test +tsconfig.json diff --git a/packages/shader-ast-stdlib/CHANGELOG.md b/packages/shader-ast-stdlib/CHANGELOG.md new file mode 100644 index 0000000000..6ac0457092 --- /dev/null +++ b/packages/shader-ast-stdlib/CHANGELOG.md @@ -0,0 +1,27 @@ +# Change Log + +All notable changes to this project will be documented in this file. +See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +# 0.1.0 (2019-07-07) + + +### Bug Fixes + +* **shader-ast-stdlib:** fix imports ([4d9e126](https://github.com/thi-ng/umbrella/commit/4d9e126)) +* **shader-ast-stdlib:** fix rotationX4/Y4 return types ([c858dce](https://github.com/thi-ng/umbrella/commit/c858dce)) +* **shader-ast-stdlib:** update additive() fn arg type ([5d66ff2](https://github.com/thi-ng/umbrella/commit/5d66ff2)) + + +### Features + +* **shader-ast-stdlib:** add 2d worley noise & permutations ([a645c71](https://github.com/thi-ng/umbrella/commit/a645c71)) +* **shader-ast-stdlib:** add additive() HOF ([43b2223](https://github.com/thi-ng/umbrella/commit/43b2223)) +* **shader-ast-stdlib:** add indexTo*() and readIndex*() fns ([a804c28](https://github.com/thi-ng/umbrella/commit/a804c28)) +* **shader-ast-stdlib:** add more functions ([4b6e4fe](https://github.com/thi-ng/umbrella/commit/4b6e4fe)) +* **shader-ast-stdlib:** add more hash fns, update voronoise2 ([65b2a15](https://github.com/thi-ng/umbrella/commit/65b2a15)) +* **shader-ast-stdlib:** add new fns, various refactoring, add docs ([b215055](https://github.com/thi-ng/umbrella/commit/b215055)) +* **shader-ast-stdlib:** add readIndex fns, hash2, minor refactorings ([34b20f0](https://github.com/thi-ng/umbrella/commit/34b20f0)) +* **shader-ast-stdlib:** add snoise2, distance fns ([0849f8b](https://github.com/thi-ng/umbrella/commit/0849f8b)) +* **shader-ast-stdlib:** add voronoise2() & hash3() ([4bafe19](https://github.com/thi-ng/umbrella/commit/4bafe19)) +* **shader-ast-stdlib:** extract stdlib as separate pkg ([86461ed](https://github.com/thi-ng/umbrella/commit/86461ed)) diff --git a/packages/shader-ast-stdlib/LICENSE b/packages/shader-ast-stdlib/LICENSE new file mode 100644 index 0000000000..8dada3edaf --- /dev/null +++ b/packages/shader-ast-stdlib/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/packages/shader-ast-stdlib/README.md b/packages/shader-ast-stdlib/README.md new file mode 100644 index 0000000000..b607c30f0b --- /dev/null +++ b/packages/shader-ast-stdlib/README.md @@ -0,0 +1,405 @@ +# @thi.ng/shader-ast-stdlib + +[![npm (scoped)](https://img.shields.io/npm/v/@thi.ng/shader-ast-stdlib.svg)](https://www.npmjs.com/package/@thi.ng/shader-ast-stdlib) +![npm downloads](https://img.shields.io/npm/dm/@thi.ng/shader-ast-stdlib.svg) +[![Twitter Follow](https://img.shields.io/twitter/follow/thing_umbrella.svg?style=flat-square&label=twitter)](https://twitter.com/thing_umbrella) + +This project is part of the +[@thi.ng/umbrella](https://github.com/thi-ng/umbrella/) monorepo. + + + +- [About](#about) +- [Installation](#installation) +- [Dependencies](#dependencies) +- [Usage examples](#usage-examples) + - [Basic Lambert shader](#basic-lambert-shader) + - [Generated vertex shader](#generated-vertex-shader) + - [Generated fragment shader](#generated-fragment-shader) + - [Using higher order functions](#using-higher-order-functions) +- [API](#api) + - [Color](#color) + - [Fog](#fog) + - [Lighting](#lighting) + - [Math](#math) + - [Matrix operations](#matrix-operations) + - [Noise / randomness](#noise--randomness) + - [Raymarching](#raymarching) + - [Screen coordinates](#screen-coordinates) + - [Signed Distance Fields](#signed-distance-fields) + - [Texture lookups](#texture-lookups) +- [Authors](#authors) +- [License](#license) + + + +## About + +A growing collection (currently 110+) of useful functions & higher order +constructs for GPU / shader programming, acting as optional standard +library for +[@thi.ng/shader-ast](https://github.com/thi-ng/umbrella/tree/master/packages/shader-ast) +based workflows. + +These functions can be imported like normal TS/JS functions and (in TS) +are fully type checked. + +Some of the functions have been ported from GLSL: + +- Signed Distance Field primitives and operations are based on work by +Inigo Quilezles (iq). +- Hash functions (PRNGs) by Dave Hoskins +- Noise functions by Ashima Arts / Stefan Gustavson +- Various functions from thi.ng/shadergraph, thi.ng/vectors, + thi.ng/matrices, thi.ng/color + +Reference: + +- http://www.iquilezles.org/www/articles/distfunctions2d/distfunctions2d.htm +- http://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm +- https://www.shadertoy.com/view/4djSRW +- https://github.com/ashima/webgl-noise + +## Installation + +```bash +yarn add @thi.ng/shader-ast-stdlib +``` + +## Dependencies + +- [@thi.ng/shader-ast](https://github.com/thi-ng/umbrella/tree/master/packages/shader-ast) + +## Usage examples + +There're are several `shader-ast` & `webgl` examples in the +[/examples](https://github.com/thi-ng/umbrella/tree/master/examples) +folder of this repo, for example... + +(Possibly non-exhaustive list, live demo links in readme's) + +- [Canvas2D shader](https://github.com/thi-ng/umbrella/tree/master/examples/shader-ast-canvas2d) +- [2D SDF](https://github.com/thi-ng/umbrella/tree/master/examples/shader-ast-sdf2d) +- [Raymarching](https://github.com/thi-ng/umbrella/tree/master/examples/shader-ast-raymarch) +- [Simplex noise](https://github.com/thi-ng/umbrella/tree/master/examples/shader-ast-noise) +- [Textured tunnel](https://github.com/thi-ng/umbrella/tree/master/examples/shader-ast-tunnel) +- [Cubemap](https://github.com/thi-ng/umbrella/tree/master/examples/webgl-cubemap) +- [Grid instancing](https://github.com/thi-ng/umbrella/tree/master/examples/webgl-grid) +- [GPGPU basics](https://github.com/thi-ng/umbrella/tree/master/examples/webgl-gpgpu-basics) +- [MSDF font rendering](https://github.com/thi-ng/umbrella/tree/master/examples/webgl-msdf) +- [SSAO deferred rendering](https://github.com/thi-ng/umbrella/tree/master/examples/webgl-ssao) + +### Basic Lambert shader + +Below is a brief demonstration of a fully defined shader pair, +implementing basic diffuse lighting: + +```ts +import { assign, defMain, vec4 } from "@thi.ng/shader-ast"; +import { diffuseLighting, halfLambert, transformMVP } from "@thi.ng/shader-ast-stdlib"; +import { shader } from "@thi.ng/webgl"; + +// obtain WebGL/WebGL2 context +// the generated shader code will automatically target the right GLSL version +const gl = ... + +// transpile & instantiate fully working shader +const myShader = shader(gl, { + // vertex shader fn + // given args are symbolic uniforms, attribs, varyings & GL builtin vars + // here `ins` are vertex attribs and `outs` are "varying" + vs: (gl, unis, ins, outs) => [ + defMain(() => [ + assign(outs.vnormal, ins.normal), + assign(gl.gl_Position, transformMVP(ins.position, unis.model, unis.view, unis.proj)), + ]) + ], + // fragment shader fn + // here `ins` are "varying" & `outs` are output variables + fs: (gl, unis, ins, outs) => [ + defMain(() => [ + assign( + outs.fragCol, + vec4( + diffuseLighting( + halfLambert(normalize(ins.vnormal), unis.lightDir), + unis.diffuseCol, + unis.lightCol, + unis.ambientCol + ), + 1 + ) + ) + ]) + ], + // attribs w/ optional location info + attribs: { + position: ["vec3", 0], + normal: ["vec3", 1] + }, + varying: { + vnormal: "vec3" + }, + // uniforms with optional default values / functions + uniforms: { + model: "mat4", + view: "mat4", + proj: "mat4", + lightDir: ["vec3", [0, 1, 0]], + lightCol: ["vec3", [1, 1, 1]], + diffuseCol: ["vec3", [0.8, 0, 0]], + ambientCol: ["vec3", [0.1, 0.1, 0.1]] + } +}); +``` + +### Generated vertex shader + +The `#define`s are auto-injected by default, but can be disabled / +customized / replaced... + +```glsl +#version 300 es +#ifdef GL_FRAGMENT_PRECISION_HIGH +precision highp int; +precision highp float; +#else +precision mediump int; +precision mediump float; +#endif +#ifndef PI +#define PI 3.141592653589793 +#endif +#ifndef TAU +#define TAU 6.283185307179586 +#endif +#ifndef HALF_PI +#define HALF_PI 1.570796326794896 +#endif + +uniform mat4 model; +uniform mat4 view; +uniform mat4 proj; +uniform vec3 lightDir; +uniform vec3 lightCol; +uniform vec3 diffuseCol; +uniform vec3 ambientCol; +layout(location=0) in vec3 position; +layout(location=1) in vec3 normal; +out vec3 vnormal; +void main() { +vnormal = normal; +gl_Position = ((proj * (view * model)) * vec4(position, 1.0)); +} +``` + +### Generated fragment shader + +The `fragColor` output variable is auto-created by +[@thi.ng/webgl](https://github.com/thi-ng/umbrella/tree/master/packages/webgl) +if no other output vars are defined. For WebGL v1 this is defined as an +alias for `gl_FragColor`... + +```glsl +#version 300 es + +/* (omitting #define's for brevity, same as in VS) */ + +uniform mat4 model; +uniform mat4 view; +uniform mat4 proj; +uniform vec3 lightDir; +uniform vec3 lightCol; +uniform vec3 diffuseCol; +uniform vec3 ambientCol; +in vec3 vnormal; +layout(location=0) out vec4 fragColor; +void main() { +fragColor = vec4((((lightCol * ((dot(normalize(vnormal), lightDir) * 0.5) + 0.5)) * diffuseCol) + ambientCol), 1.0); +} +``` + +### Using higher order functions + +Several of the functions included here are defined as higher-order +functions, providing powerful functional compositional features not +usually seen in shader code and not easily achievable via the usual +string templating approach used by most other GLSL libraries. + +For example, the +[`additive()`](https://github.com/thi-ng/umbrella/blob/master/packages/shader-ast-stdlib/src/math/additive.ts#L21) +HOF takes a single-arg scalar function and a number of octaves. It +returns a new function which computes the summed value of `fn` over the +given number octaves, with a user defined phase shift & decay factor +(per octave). This can be used for additive wave synthesis, multi-octave +noise or any other similar use cases... + +Due to the way user defined AST functions keep track of their own call +graph, the anonymous function returned by `additive` does not need to be +pre-declared in any way and also ensures all of its own function +dependencies are resolved and emitted in the correct topological order +during later code generation. + +Below is the main shader code of the [Simplex noise +example](https://github.com/thi-ng/umbrella/tree/master/examples/shader-ast-noise). + +```ts +import { add, defn, float, ret, sym, vec2, vec3, vec4 } from "@thi.ng/shader-ast"; +import { additive, aspectCorrectedUV, fit1101, snoise2 } from "@thi.ng/shader-ast-stdlib"; + +const mainImage = defn( + "vec4", + "mainImage", + [["vec2"], ["vec2"], ["float"]], + (frag, res, time) => { + let uv; + let noise; + return [ + // compute UV coords and assign to `uv` + uv = sym(aspectCorrectedUV(frag, res)), + // dynamically create a multi-octave version of `snoise2` + // computed over 4 octaves w/ given phase shift and decay + // factor (both per octave) + noise = sym( + additive("vec2", snoise2, 4)(add(uv, time), vec2(2), float(0.5)) + ), + // `noise` is in [-1..1] interval, use fit1101 to fit to [0..1] + ret(vec4(vec3(fit1101(noise)), 1)) + ]; + } +); +``` + +Run the above-linked example and view the console to see the full +generated shader code. Also check out the raymarching demo which uses +several other HOFs from this library to drastically simplify user code. + +## API + +TODO. For now, please see doc strings in source for details... + +### Color + +[/src/color](https://github.com/thi-ng/umbrella/tree/master/packages/shader-ast-stdlib/src/color/) + +- `toLinear` +- `toSRGB` +- `luminanceRGB` + +### Fog + +[/src/fog](https://github.com/thi-ng/umbrella/tree/master/packages/shader-ast-stdlib/src/fog/) + +- `fogLinear` +- `fogExp` +- `fogExp2` + +### Lighting + +[/src/light](https://github.com/thi-ng/umbrella/tree/master/packages/shader-ast-stdlib/src/light/) + +- `lambert` +- `halfLambert` +- `diffuseLighting` +- `trilight` + +### Math + +[/src/math](https://github.com/thi-ng/umbrella/tree/master/packages/shader-ast-stdlib/src/math/) + +- `additive` +- `cartesian2` / `cartesian3` +- `clamp01` / `clamp11` +- `cross2` / `crossC2` +- `distChebyshev2` / `distChebyshev3` / `distChebyshev4` +- `distManhattan2` / `distManhattan3` / `distManhattan4` +- `fit01` / `fit11` / `fit1101` / `fit0111` +- `magSq2` / `magSq3` / `magSq4` +- `maxComp2` / `maxComp3` / `maxComp4` +- `minComp2` / `minComp3` / `minComp4` +- `perpendicularCCW` / `perpendicularCW` +- `orthogonal3` +- `polar2` / `polar3` +- `sincos` / `cossin` + +### Matrix operations + +[/src/matrix](https://github.com/thi-ng/umbrella/tree/master/packages/shader-ast-stdlib/src/matrix/) + +- `lookat` +- `transformMVP` +- `surfaceNormal` +- `rotation2` +- `rotationX3` / `rotationY3` / `rotationZ3` +- `rotationX4` / `rotationY4` / `rotationZ4` + +### Noise / randomness + +[/src/noise](https://github.com/thi-ng/umbrella/tree/master/packages/shader-ast-stdlib/src/noise/) + +- `hash2` / `hash3` +- `hash11` / `hash12` / `hash13` +- `hash21` / `hash22` / `hash23` +- `hash31` / `hash32` / `hash33` +- `hash41` / `hash42` / `hash43` / `hash44` +- `permute` / `permute3` / `permute4` +- `snoise2` +- `voronoise2` +- `worley2` / `worleyDist` / `worleyDistManhattan` + +### Raymarching + +[/src/raymarch](https://github.com/thi-ng/umbrella/tree/master/packages/shader-ast-stdlib/src/raymarch/) + +- `raymarchAO` +- `raymarchDir` +- `raymarchNormal` +- `raymarchScene` +- `rayPointAt` + +### Screen coordinates + +[/src/screen](https://github.com/thi-ng/umbrella/tree/master/packages/shader-ast-stdlib/src/screen/) + +- `aspectCorrectedUV` + +### Signed Distance Fields + +[/src/sdf](https://github.com/thi-ng/umbrella/tree/master/packages/shader-ast-stdlib/src/sdf/) + +- `sdfAnnular` +- `sdfBox2` +- `sdfBox3` +- `sdfCircle` +- `sdfCylinder` +- `sdfIntersect` +- `sdfLine2` +- `sdfLine3` +- `sdfPlane2` +- `sdfPlane3` +- `sdfRepeat2` +- `sdfRepeat3` +- `sdfRound` +- `sdfSmoothIntersect` +- `sdfSmoothSubtract` +- `sdfSmoothUnion` +- `sdfSphere` +- `sdfTorus` +- `sdfTriangle2` +- `sdfUnion` + +### Texture lookups + +[/src/tex](https://github.com/thi-ng/umbrella/tree/master/packages/shader-ast-stdlib/src/tex/) + +- `indexToCoord` / `coordToIndex` +- `indexToUV` / `uvToIndex` +- `readIndex1` / `readIndex2` / `readIndex3` / `readIndex4` + +## Authors + +- Karsten Schmidt + +## License + +© 2019 Karsten Schmidt // Apache Software License 2.0 diff --git a/packages/shader-ast-stdlib/package.json b/packages/shader-ast-stdlib/package.json new file mode 100644 index 0000000000..07529f254e --- /dev/null +++ b/packages/shader-ast-stdlib/package.json @@ -0,0 +1,63 @@ +{ + "name": "@thi.ng/shader-ast-stdlib", + "version": "0.1.0", + "description": "Useful functions for GPGPU / shader programming w/ @thi.ng/shader-ast", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", + "typings": "./index.d.ts", + "repository": { + "type": "git", + "url": "https://github.com/thi-ng/umbrella.git" + }, + "homepage": "https://github.com/thi-ng/umbrella/tree/master/packages/shader-ast-stdlib", + "author": "Karsten Schmidt ", + "license": "Apache-2.0", + "scripts": { + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module", + "test": "rimraf build && tsc -p test/tsconfig.json && nyc mocha build/test/*.js", + "clean": "rimraf *.js *.d.ts .nyc_output build coverage doc lib color fog lighting math matrix noise raymarch screen sdf tex", + "cover": "yarn test && nyc report --reporter=lcov", + "doc": "node_modules/.bin/typedoc --mode modules --out doc src", + "pub": "yarn build && yarn publish --access public" + }, + "devDependencies": { + "@types/mocha": "^5.2.6", + "@types/node": "^12.0.8", + "mocha": "^6.1.4", + "nyc": "^14.0.0", + "typedoc": "^0.14.2", + "typescript": "^3.5.2" + }, + "dependencies": { + "@thi.ng/shader-ast": "^0.1.0" + }, + "keywords": [ + "AST", + "DSL", + "ES6", + "fog", + "functional", + "higher order", + "inline", + "GLSL", + "GPGPU", + "math", + "matrix", + "noise", + "raymarch", + "random", + "sdf", + "shader", + "texture", + "typescript", + "webgl", + "webgl2" + ], + "publishConfig": { + "access": "public" + }, + "sideEffects": false +} diff --git a/packages/shader-ast-stdlib/src/api.ts b/packages/shader-ast-stdlib/src/api.ts new file mode 100644 index 0000000000..b49253d798 --- /dev/null +++ b/packages/shader-ast-stdlib/src/api.ts @@ -0,0 +1,31 @@ +import { TaggedFn1 } from "@thi.ng/shader-ast"; + +export type RaymarchScene = TaggedFn1<"vec3", "vec2">; + +export interface RaymarchOpts { + /** + * Name of generated function. Default: "raymarch" + */ + name: string; + /** + * Near clipping plane. Default: 0.1 + */ + near: number; + /** + * Far clipping plane: Default: 10 + */ + far: number; + /** + * Max. iteration steps. Default: 100 + */ + steps: number; + /** + * Surface tolerance, i.e. search stops once distance returned from + * `scene` function is less than this value. Default: 0.01 + */ + eps: number; + /** + * March step distance falloff / decay factor. Default: 0.7 + */ + bias: number; +} diff --git a/packages/shader-ast-stdlib/src/color/linear-srgb.ts b/packages/shader-ast-stdlib/src/color/linear-srgb.ts new file mode 100644 index 0000000000..b42b3f321a --- /dev/null +++ b/packages/shader-ast-stdlib/src/color/linear-srgb.ts @@ -0,0 +1,24 @@ +import { + float, + FloatTerm, + pow, + Prim, + Term, + vec2, + vec3, + vec4 +} from "@thi.ng/shader-ast"; + +const GAMMA = float(2.2); +const INV_GAMMA = float(1 / 2.2); + +const $ = (t: Term, x: FloatTerm): Term => { + float: x, + vec2: vec2(x), + vec3: vec3(x), + vec4: vec4(x, x, x, 1) + }[t.type]; + +export const toLinear = (x: Term) => pow(x, $(x, GAMMA)); + +export const toSRGB = (x: Term) => pow(x, $(x, INV_GAMMA)); diff --git a/packages/shader-ast-stdlib/src/color/luminance.ts b/packages/shader-ast-stdlib/src/color/luminance.ts new file mode 100644 index 0000000000..6362706816 --- /dev/null +++ b/packages/shader-ast-stdlib/src/color/luminance.ts @@ -0,0 +1,9 @@ +import { dot, vec3, Vec3Term } from "@thi.ng/shader-ast"; + +/** + * Inline function. Computes luminance of given RGB color + * + * @param rgb + */ +export const luminanceRGB = (rgb: Vec3Term) => + dot(rgb, vec3(0.299, 0.587, 0.114)); diff --git a/packages/shader-ast-stdlib/src/fog/exp.ts b/packages/shader-ast-stdlib/src/fog/exp.ts new file mode 100644 index 0000000000..1099fa26cf --- /dev/null +++ b/packages/shader-ast-stdlib/src/fog/exp.ts @@ -0,0 +1,21 @@ +import { + defn, + exp, + FLOAT1, + mul, + neg, + ret, + sub +} from "@thi.ng/shader-ast"; +import { clamp01 } from "../math/clamp"; + +/** + * @param dist float + * @param density float + */ +export const fogExp = defn( + "float", + "fogExp", + [["float"], ["float"]], + (dist, density) => [ret(sub(FLOAT1, clamp01(exp(mul(neg(density), dist)))))] +); diff --git a/packages/shader-ast-stdlib/src/fog/exp2.ts b/packages/shader-ast-stdlib/src/fog/exp2.ts new file mode 100644 index 0000000000..4f35f0d9f4 --- /dev/null +++ b/packages/shader-ast-stdlib/src/fog/exp2.ts @@ -0,0 +1,24 @@ +import { + assign, + defn, + exp2, + FLOAT1, + mul, + ret, + sub +} from "@thi.ng/shader-ast"; +import { clamp01 } from "../math/clamp"; + +/** + * @param dist float + * @param density float + */ +export const fogExp2 = defn( + "float", + "fogExp2", + [["float"], ["float"]], + (dist, density) => [ + assign(density, mul(density, dist)), + ret(sub(FLOAT1, clamp01(exp2(mul(mul(density, density), -Math.LOG2E))))) + ] +); diff --git a/packages/shader-ast-stdlib/src/fog/linear.ts b/packages/shader-ast-stdlib/src/fog/linear.ts new file mode 100644 index 0000000000..c10da9f2b0 --- /dev/null +++ b/packages/shader-ast-stdlib/src/fog/linear.ts @@ -0,0 +1,23 @@ +import { + defn, + div, + FLOAT1, + ret, + sub +} from "@thi.ng/shader-ast"; +import { clamp01 } from "../math/clamp"; + +/** + * @param dist float + * @param start float + * @param end float + * + */ +export const fogLinear = defn( + "float", + "fogLinear", + [["float"], ["float"], ["float"]], + (dist, start, end) => [ + ret(sub(FLOAT1, clamp01(div(sub(end, dist), sub(end, start))))) + ] +); diff --git a/packages/shader-ast-stdlib/src/index.ts b/packages/shader-ast-stdlib/src/index.ts new file mode 100644 index 0000000000..552c93779f --- /dev/null +++ b/packages/shader-ast-stdlib/src/index.ts @@ -0,0 +1,64 @@ +export * from "./api"; + +export * from "./color/linear-srgb"; +export * from "./color/luminance"; + +export * from "./fog/exp"; +export * from "./fog/exp2"; +export * from "./fog/linear"; + +export * from "./light/lambert"; +export * from "./light/trilight"; + +export * from "./math/additive"; +export * from "./math/cartesian"; +export * from "./math/clamp"; +export * from "./math/cross2"; +export * from "./math/dist-chebyshev"; +export * from "./math/dist-manhattan"; +export * from "./math/fit"; +export * from "./math/magsq"; +export * from "./math/maxcomp"; +export * from "./math/mincomp"; +export * from "./math/orthogonal"; +export * from "./math/polar"; +export * from "./math/sincos"; + +export * from "./matrix/lookat"; +export * from "./matrix/mvp"; +export * from "./matrix/normal"; +export * from "./matrix/rotation"; + +export * from "./noise/hash"; +export * from "./noise/permute"; +export * from "./noise/simplex2"; +export * from "./noise/voronoi2"; +export * from "./noise/worley2"; + +export * from "./raymarch/ao"; +export * from "./raymarch/direction"; +export * from "./raymarch/normal"; +export * from "./raymarch/point-at"; +export * from "./raymarch/scene"; + +export * from "./screen/uv"; + +export * from "./sdf/annular"; +export * from "./sdf/box"; +export * from "./sdf/cylinder"; +export * from "./sdf/isec"; +export * from "./sdf/line"; +export * from "./sdf/plane"; +export * from "./sdf/repeat"; +export * from "./sdf/round"; +export * from "./sdf/smooth-isec"; +export * from "./sdf/smooth-sub"; +export * from "./sdf/smooth-union"; +export * from "./sdf/sphere"; +export * from "./sdf/torus"; +export * from "./sdf/tri"; +export * from "./sdf/union"; + +export * from "./tex/index-coord"; +export * from "./tex/index-uv"; +export * from "./tex/read-index"; diff --git a/packages/shader-ast-stdlib/src/light/lambert.ts b/packages/shader-ast-stdlib/src/light/lambert.ts new file mode 100644 index 0000000000..d7750fe91e --- /dev/null +++ b/packages/shader-ast-stdlib/src/light/lambert.ts @@ -0,0 +1,49 @@ +import { + dot, + FLOAT0, + FloatTerm, + madd, + max, + mul, + Vec3Term +} from "@thi.ng/shader-ast"; +import { fit1101 } from "../math/fit"; + +/** + * Inline function. Computes Lambert term, i.e. `max(dot(n, l), 0)`. + * Both vectors must be pre-normalized. + * + * @param surfNormal vec3 + * @param lightDir vec3 + */ +export const lambert = (n: Vec3Term, ldir: Vec3Term) => + max(dot(n, ldir), FLOAT0); + +/** + * Inline function. Computes Half-Lambertian term. Both vectors must be + * pre-normalized. + * + * https://developer.valvesoftware.com/wiki/Half_Lambert + * + * @param n + * @param ldir + */ +export const halfLambert = (n: Vec3Term, ldir: Vec3Term) => + fit1101(dot(n, ldir)); + +/** + * Inline function. Computes: + * + * col = lambert * lightCol * diffuseCol + ambientCol + * + * @param lambertian float + * @param diffuseCol vec3 + * @param lightCol vec3 + * @param ambientCol vec3 + */ +export const diffuseLighting = ( + lambertian: FloatTerm, + diffuse: Vec3Term, + light: Vec3Term, + ambient: Vec3Term +) => madd(mul(light, lambertian), diffuse, ambient); diff --git a/packages/shader-ast-stdlib/src/light/trilight.ts b/packages/shader-ast-stdlib/src/light/trilight.ts new file mode 100644 index 0000000000..24fd3e1886 --- /dev/null +++ b/packages/shader-ast-stdlib/src/light/trilight.ts @@ -0,0 +1,44 @@ +import { + abs, + add, + defn, + dot, + FLOAT0, + FLOAT1, + FloatSym, + max, + mul, + neg, + ret, + sub, + sym +} from "@thi.ng/shader-ast"; + +/** + * Tom Forsyth's Trilight lighting model. + * + * https://tomforsyth1000.github.io/papers/trilight/trilight.html + * + * @param surfNormal vec3 + * @param lightDir vec3 + * @param col1 vec3 + * @param col2 vec3 + * @param col3 vec3 + */ +export const trilight = defn( + "vec3", + "trilight", + [["vec3"], ["vec3"], ["vec3"], ["vec3"], ["vec3"]], + (n, l, c1, c2, c3) => { + let d: FloatSym; + return [ + (d = sym(dot(n, l))), + ret( + add( + add(mul(c1, max(d, FLOAT0)), mul(c2, sub(FLOAT1, abs(d)))), + mul(c3, max(dot(neg(n), l), FLOAT0)) + ) + ) + ]; + } +); diff --git a/packages/shader-ast-stdlib/src/math/additive.ts b/packages/shader-ast-stdlib/src/math/additive.ts new file mode 100644 index 0000000000..21ef762686 --- /dev/null +++ b/packages/shader-ast-stdlib/src/math/additive.ts @@ -0,0 +1,70 @@ +import { Fn } from "@thi.ng/api"; +import { + add, + assign, + defn, + float, + FLOAT0, + FLOAT05, + FloatSym, + FloatTerm, + forLoop, + inc, + lt, + mul, + Prim, + ret, + sym, + Term +} from "@thi.ng/shader-ast"; + +/** + * Higher order function. Takes an AST type ID, a single-arg scalar + * function `fn`, number of octaves (default: 4) and an optional + * function name. Returns a new function which computes the summed value + * of `fn` over the given number octaves and accepts 3 args: + * + * - position (float) + * - octave shift (float) + * - octave decay (usually 0.5) + * + * For each octave `i` [0..oct), the function is (in principle) + * evaluated as: + * + * n += decay / exp2(i) * fn(pos * exp2(i) + i * shift) + * + * @param fn + * @param oct + * @param name + */ +export const additive = ( + type: T, + fn: Fn, FloatTerm>, + oct = 4, + name = "additive" +) => + defn("float", name, [[type], [type], ["float"]], (pos, shift, decay) => { + let n: FloatSym; + let amp: FloatSym; + return [ + (n = sym(FLOAT0)), + (amp = sym(FLOAT05)), + forLoop( + sym("float", float(0)), + (i) => lt(i, float(oct)), + inc, + (i) => [ + assign( + n, + add( + n, + mul(amp, fn(add(pos, mul(i, shift)))) + ) + ), + assign(amp, mul(amp, decay)), + assign(pos, mul(pos, 2)) + ] + ), + ret(n) + ]; + }); diff --git a/packages/shader-ast-stdlib/src/math/cartesian.ts b/packages/shader-ast-stdlib/src/math/cartesian.ts new file mode 100644 index 0000000000..6f7a6ad8db --- /dev/null +++ b/packages/shader-ast-stdlib/src/math/cartesian.ts @@ -0,0 +1,41 @@ +import { + $x, + $y, + $z, + defn, + FloatSym, + mul, + ret, + sym, + vec2, + Vec2Sym, + Vec2Term, + vec3 +} from "@thi.ng/shader-ast"; +import { cossin } from "./sincos"; + +/** + * Converts 2D polar vector `v` to cartesian coordinates. See `polar2()` + * for reverse operation. + * + * @param v + */ +export const cartesian2 = (v: Vec2Term) => mul(cossin($y(v)), vec2($x(v))); + +/** + * Converts 3D polar vector `v` to cartesian coordinates. See `polar3()` + * for reverse operation. + * + * @param v + */ +export const cartesian3 = defn("vec3", "cartesian3", [["vec3"]], (v) => { + let r: FloatSym; + let t: Vec2Sym; + let p: Vec2Sym; + return [ + (r = sym($x(v))), + (t = sym(cossin($y(v)))), + (p = sym(cossin($z(v)))), + ret(vec3(mul(mul(r, $x(t)), $x(p)))) + ]; +}); diff --git a/packages/shader-ast-stdlib/src/math/clamp.ts b/packages/shader-ast-stdlib/src/math/clamp.ts new file mode 100644 index 0000000000..8f088fcc63 --- /dev/null +++ b/packages/shader-ast-stdlib/src/math/clamp.ts @@ -0,0 +1,47 @@ +import { + clamp, + float, + FLOAT0, + FLOAT1, + FloatTerm, + Prim, + Term, + vec2, + Vec2Term, + vec3, + Vec3Term, + vec4, + Vec4Term +} from "@thi.ng/shader-ast"; + +/** + * Inline function, expands to equivalent of `clamp(x, 0, 1)`. + * + * @param x + */ +export const clamp01 = (x: Term): Term => + >( + (x.type === "float" + ? clamp(x, FLOAT0, FLOAT1) + : x.type === "vec2" + ? clamp(x, vec2(), vec2(1)) + : x.type === "vec3" + ? clamp(x, vec3(), vec3(1)) + : clamp(x, vec4(), vec4(1))) + ); + +/** + * Inline function, expands to equivalent of `clamp(x, -1, 1)`. + * + * @param x + */ +export const clamp11 = (x: Term): Term => + >( + (x.type === "float" + ? clamp(x, float(-1), FLOAT1) + : x.type === "vec2" + ? clamp(x, vec2(-1), vec2(1)) + : x.type === "vec3" + ? clamp(x, vec3(-1), vec3(1)) + : clamp(x, vec4(-1), vec4(1))) + ); diff --git a/packages/shader-ast-stdlib/src/math/cross2.ts b/packages/shader-ast-stdlib/src/math/cross2.ts new file mode 100644 index 0000000000..06cf61451e --- /dev/null +++ b/packages/shader-ast-stdlib/src/math/cross2.ts @@ -0,0 +1,35 @@ +import { + $x, + $y, + FloatTerm, + mul, + sub, + Vec2Term +} from "@thi.ng/shader-ast"; + +/** + * Inline function. Computes 2D cross product of given vectors. + * + * @see crossC2 + * + * @param a + * @param b + */ +export const cross2 = (a: Vec2Term, b: Vec2Term) => + crossC2($x(a), $y(a), $x(b), $y(b)); + +/** + * Inline function. Computes 2D cross product of given individual + * components: ax * by - ay * bx + * + * @param ax + * @param ay + * @param bx + * @param by + */ +export const crossC2 = ( + ax: FloatTerm, + ay: FloatTerm, + bx: FloatTerm, + by: FloatTerm +) => sub(mul(ax, by), mul(ay, bx)); diff --git a/packages/shader-ast-stdlib/src/math/dist-chebyshev.ts b/packages/shader-ast-stdlib/src/math/dist-chebyshev.ts new file mode 100644 index 0000000000..8c5e506998 --- /dev/null +++ b/packages/shader-ast-stdlib/src/math/dist-chebyshev.ts @@ -0,0 +1,25 @@ +import { + $w, + $x, + $y, + $z, + abs, + max, + sub, + Vec2Term, + Vec3Term, + Vec4Term +} from "@thi.ng/shader-ast"; + +export const distChebyshev2 = ( + a: Vec2Term | Vec3Term | Vec4Term, + b: Vec2Term | Vec3Term | Vec4Term +) => max(abs(sub($x(a), $x(b))), abs(sub($y(a), $y(b)))); + +export const distChebyshev3 = ( + a: Vec3Term | Vec4Term, + b: Vec3Term | Vec4Term +) => max(distChebyshev2(a, b), abs(sub($z(a), $z(b)))); + +export const distChebyshev4 = (a: Vec4Term, b: Vec4Term) => + max(distChebyshev3(a, b), abs(sub($w(a), $w(b)))); diff --git a/packages/shader-ast-stdlib/src/math/dist-manhattan.ts b/packages/shader-ast-stdlib/src/math/dist-manhattan.ts new file mode 100644 index 0000000000..617d01c2dc --- /dev/null +++ b/packages/shader-ast-stdlib/src/math/dist-manhattan.ts @@ -0,0 +1,25 @@ +import { + $w, + $x, + $y, + $z, + abs, + add, + sub, + Vec2Term, + Vec3Term, + Vec4Term +} from "@thi.ng/shader-ast"; + +export const distManhattan2 = ( + a: Vec2Term | Vec3Term | Vec4Term, + b: Vec2Term | Vec3Term | Vec4Term +) => add(abs(sub($x(a), $x(b))), abs(sub($y(a), $y(b)))); + +export const distManhattan3 = ( + a: Vec3Term | Vec4Term, + b: Vec3Term | Vec4Term +) => add(distManhattan2(a, b), abs(sub($z(a), $z(b)))); + +export const distManhattan4 = (a: Vec4Term, b: Vec4Term) => + add(distManhattan3(a, b), abs(sub($w(a), $w(b)))); diff --git a/packages/shader-ast-stdlib/src/math/fit.ts b/packages/shader-ast-stdlib/src/math/fit.ts new file mode 100644 index 0000000000..74d875cf61 --- /dev/null +++ b/packages/shader-ast-stdlib/src/math/fit.ts @@ -0,0 +1,44 @@ +import { + add, + FLOAT05, + FLOAT1, + FLOAT2, + mix, + mul, + Op2, + Prim, + sub, + Term +} from "@thi.ng/shader-ast"; + +/** + * Inline function. Fits value `a` in [0..1] interval to new interval + * [b..c]. No clamping performed. Same as `mix(b, c, a)` + * + * @param a + * @param b + * @param c + */ +export const fit01 = ( + a: Term, + b: Term, + c: Term +) => mix(b, c, a); + +/** + * Inline function. Fits value `x` in [-1..+1] interval to [0..1] + * interval. No clamping performed. + * + * @param x + */ +export const fit1101 = (x: Term): Op2 => + add(mul(x, FLOAT05), FLOAT05); + +/** + * Inline function. Fits value `x` in [0..1] interval to [-1..+1] + * interval. No clamping performed. + * + * @param x + */ +export const fit0111 = (x: Term): Op2 => + sub(mul(x, FLOAT2), FLOAT1); diff --git a/packages/shader-ast-stdlib/src/math/magsq.ts b/packages/shader-ast-stdlib/src/math/magsq.ts new file mode 100644 index 0000000000..a99dffc7f8 --- /dev/null +++ b/packages/shader-ast-stdlib/src/math/magsq.ts @@ -0,0 +1,13 @@ +import { defn, dot, ret } from "@thi.ng/shader-ast"; + +export const magSq2 = defn("float", "magSq2", [["vec2"]], (v) => [ + ret(dot(v, v)) +]); + +export const magSq3 = defn("float", "magSq3", [["vec3"]], (v) => [ + ret(dot(v, v)) +]); + +export const magSq4 = defn("float", "magSq4", [["vec4"]], (v) => [ + ret(dot(v, v)) +]); diff --git a/packages/shader-ast-stdlib/src/math/maxcomp.ts b/packages/shader-ast-stdlib/src/math/maxcomp.ts new file mode 100644 index 0000000000..20bf944766 --- /dev/null +++ b/packages/shader-ast-stdlib/src/math/maxcomp.ts @@ -0,0 +1,31 @@ +import { + $w, + $x, + $y, + $z, + max, + Vec2Sym, + Vec3Sym, + Vec4Sym +} from "@thi.ng/shader-ast"; + +/** + * Inline function. Returns max(v.x, v.y) + * + * @param v + */ +export const maxComp2 = (v: Vec2Sym | Vec3Sym | Vec4Sym) => max($x(v), $y(v)); + +/** + * Inline function. Returns max(v.x, v.y, v.z) + * + * @param v + */ +export const maxComp3 = (v: Vec3Sym | Vec4Sym) => max(maxComp2(v), $z(v)); + +/** + * Inline function. Returns max(v.x, v.y, v.z, v.w) + * + * @param v + */ +export const maxComp4 = (v: Vec4Sym) => max(maxComp3(v), $w(v)); diff --git a/packages/shader-ast-stdlib/src/math/mincomp.ts b/packages/shader-ast-stdlib/src/math/mincomp.ts new file mode 100644 index 0000000000..965f28120f --- /dev/null +++ b/packages/shader-ast-stdlib/src/math/mincomp.ts @@ -0,0 +1,31 @@ +import { + $w, + $x, + $y, + $z, + min, + Vec2Sym, + Vec3Sym, + Vec4Sym +} from "@thi.ng/shader-ast"; + +/** + * Inline function. Returns min(v.x, v.y) + * + * @param v + */ +export const minComp2 = (v: Vec2Sym | Vec3Sym | Vec4Sym) => min($x(v), $y(v)); + +/** + * Inline function. Returns min(v.x, v.y, v.z) + * + * @param v + */ +export const minComp3 = (v: Vec3Sym | Vec4Sym) => min(minComp2(v), $z(v)); + +/** + * Inline function. Returns min(v.x, v.y, v.z, v.w) + * + * @param v + */ +export const minComp4 = (v: Vec4Sym) => min(minComp3(v), $w(v)); diff --git a/packages/shader-ast-stdlib/src/math/orthogonal.ts b/packages/shader-ast-stdlib/src/math/orthogonal.ts new file mode 100644 index 0000000000..3aeec9fb74 --- /dev/null +++ b/packages/shader-ast-stdlib/src/math/orthogonal.ts @@ -0,0 +1,45 @@ +import { + $x, + $y, + $z, + abs, + defn, + gt, + neg, + ret, + ternary, + vec2, + Vec2Term, + vec3 +} from "@thi.ng/shader-ast"; + +/** + * Inline function. Returns counter-clockwise perpendicular vector + * (assuming Y-up). [-y, x] + * + * @param v + */ +export const perpendicularCCW = (v: Vec2Term) => vec2(neg($y(v)), $x(v)); + +/** + * Inline function. Returns clockwise perpendicular vector (assuming + * Y-up). [y,-x] + * + * @param v + */ +export const perpendicularCW = (v: Vec2Term) => vec2($y(v), neg($x(v))); + +/** + * Returns an orthogonal vector to `v`. + * + * http://lolengine.net/blog/2013/09/21/picking-orthogonal-vector-combing-coconuts + */ +export const orthogonal3 = defn("vec3", "orthogonal3", [["vec3"]], (v) => [ + ret( + ternary( + gt(abs($x(v)), abs($z(v))), + vec3(neg($y(v)), $x(v), 0), + vec3(0, neg($z(v)), $y(v)) + ) + ) +]); diff --git a/packages/shader-ast-stdlib/src/math/polar.ts b/packages/shader-ast-stdlib/src/math/polar.ts new file mode 100644 index 0000000000..fae7cf6b97 --- /dev/null +++ b/packages/shader-ast-stdlib/src/math/polar.ts @@ -0,0 +1,40 @@ +import { + $x, + $y, + $z, + asin, + atan, + defn, + div, + FloatSym, + length, + ret, + sym, + vec2, + vec3 +} from "@thi.ng/shader-ast"; + +/** + * Converts 2D cartesian vector `v` to polar coordinates, i.e. `[r,θ]` + * (angle in radians). See `cartesian2()` for reverse operation. + * + * @param v + */ +export const polar2 = defn("vec2", "polar2", [["vec2"]], (v) => [ + ret(vec2(length(v), atan(div($y(v), $x(v))))) +]); + +/** + * Converts 3D cartesian vector `v` to spherical coordinates, i.e. + * `[r,θ,Ï•]` (angles in radians). See `cartesian3()` for reverse + * operation. + * + * @param v + */ +export const polar3 = defn("vec3", "polar3", [["vec3"]], (v) => { + let r: FloatSym; + return [ + (r = sym(length(v))), + ret(vec3(r, asin(div($z(v), r)), atan(div($y(v), $x(v))))) + ]; +}); diff --git a/packages/shader-ast-stdlib/src/math/sincos.ts b/packages/shader-ast-stdlib/src/math/sincos.ts new file mode 100644 index 0000000000..8a144578ce --- /dev/null +++ b/packages/shader-ast-stdlib/src/math/sincos.ts @@ -0,0 +1,20 @@ +import { + cos, + FloatTerm, + sin, + vec2 +} from "@thi.ng/shader-ast"; + +/** + * Inline function. Returns vec2(sin(x), cos(x)). + * + * @param x + */ +export const sincos = (x: FloatTerm) => vec2(sin(x), cos(x)); + +/** + * Inline function. Returns vec2(cos(x), sin(x)). + * + * @param x + */ +export const cossin = (x: FloatTerm) => vec2(cos(x), sin(x)); diff --git a/packages/shader-ast-stdlib/src/matrix/lookat.ts b/packages/shader-ast-stdlib/src/matrix/lookat.ts new file mode 100644 index 0000000000..17eaa787a8 --- /dev/null +++ b/packages/shader-ast-stdlib/src/matrix/lookat.ts @@ -0,0 +1,45 @@ +import { + cross, + defn, + dot, + mat4, + neg, + normalize, + ret, + sub, + sym, + Vec3Sym, + vec4 +} from "@thi.ng/shader-ast"; + +/** + * Creates a mat4 view matrix from given `eyePos`, `target` and `up` + * vector. + * + * @param eye vec3 + * @param target vec3 + * @param up vec3 + */ +export const lookat = defn( + "mat4", + "lookat", + [["vec3"], ["vec3"], ["vec3"]], + (eye, target, up) => { + let x: Vec3Sym; + let y: Vec3Sym; + let z: Vec3Sym; + return [ + (z = sym(normalize(sub(eye, target)))), + (x = sym(normalize(cross(up, z)))), + (y = sym(normalize(cross(z, x)))), + ret( + mat4( + vec4(x, neg(dot(eye, x))), + vec4(up, neg(dot(eye, y))), + vec4(z, neg(dot(eye, z))), + vec4(0, 0, 0, 1) + ) + ) + ]; + } +); diff --git a/packages/shader-ast-stdlib/src/matrix/mvp.ts b/packages/shader-ast-stdlib/src/matrix/mvp.ts new file mode 100644 index 0000000000..9422178da3 --- /dev/null +++ b/packages/shader-ast-stdlib/src/matrix/mvp.ts @@ -0,0 +1,23 @@ +import { + FLOAT1, + Mat4Term, + mul, + Vec3Term, + vec4 +} from "@thi.ng/shader-ast"; + +/** + * Inline function. Multiplies `pos` with given model, view & projection + * matrices (in order). `p` is extended to a vec4. + * + * @param p + * @param model + * @param view + * @param proj + */ +export const transformMVP = ( + p: Vec3Term, + model: Mat4Term, + view: Mat4Term, + proj: Mat4Term +) => mul(mul(proj, mul(view, model)), vec4(p, FLOAT1)); diff --git a/packages/shader-ast-stdlib/src/matrix/normal.ts b/packages/shader-ast-stdlib/src/matrix/normal.ts new file mode 100644 index 0000000000..e5528db0a5 --- /dev/null +++ b/packages/shader-ast-stdlib/src/matrix/normal.ts @@ -0,0 +1,18 @@ +import { + $xyz, + Mat4Term, + mul, + normalize, + Vec3Term, + vec4 +} from "@thi.ng/shader-ast"; + +/** + * Inline function. Multiplies `normal` with given 4x4 normal matrix + * (e.g. transpose inverse of view * model). + * + * @param n + * @param normalMat + */ +export const surfaceNormal = (n: Vec3Term, normalMat: Mat4Term) => + normalize($xyz(mul(normalMat, vec4(n, 0)))); diff --git a/packages/shader-ast-stdlib/src/matrix/rotation.ts b/packages/shader-ast-stdlib/src/matrix/rotation.ts new file mode 100644 index 0000000000..b0e1d232b5 --- /dev/null +++ b/packages/shader-ast-stdlib/src/matrix/rotation.ts @@ -0,0 +1,124 @@ +import { + $x, + $y, + defn, + mat2, + mat3, + mat4, + neg, + ret, + sym, + Vec2Term +} from "@thi.ng/shader-ast"; +import { perpendicularCCW } from "../math/orthogonal"; +import { cossin } from "../math/sincos"; + +export const rotation2 = defn("mat2", "rotation2", [["float"]], (theta) => { + let cs: Vec2Term; + return [(cs = sym(cossin(theta))), ret(mat2(cs, perpendicularCCW(cs)))]; +}); + +export const rotationX3 = defn("mat3", "rotationX3", [["float"]], (theta) => { + let cs: Vec2Term; + return [ + (cs = sym(cossin(theta))), + ret(mat3(1, 0, 0, 0, $x(cs), $y(cs), 0, neg($y(cs)), $x(cs))) + ]; +}); + +export const rotationY3 = defn("mat3", "rotationY3", [["float"]], (theta) => { + let cs: Vec2Term; + return [ + (cs = sym(cossin(theta))), + ret(mat3($x(cs), 0, neg($y(cs)), 0, 1, 0, $y(cs), 0, $x(cs))) + ]; +}); + +export const rotationZ3 = defn("mat3", "rotationZ3", [["float"]], (theta) => { + let cs: Vec2Term; + return [ + (cs = sym(cossin(theta))), + ret(mat3($x(cs), $y(cs), 0, neg($y(cs)), $x(cs), 0, 0, 0, 1)) + ]; +}); + +export const rotationX4 = defn("mat4", "rotationX4", [["float"]], (theta) => { + let cs: Vec2Term; + return [ + (cs = sym(cossin(theta))), + ret( + mat4( + 1, + 0, + 0, + 0, + 0, + $x(cs), + $y(cs), + 0, + 0, + neg($y(cs)), + $x(cs), + 0, + 0, + 0, + 0, + 1 + ) + ) + ]; +}); + +export const rotationY4 = defn("mat4", "rotationY4", [["float"]], (theta) => { + let cs: Vec2Term; + return [ + (cs = sym(cossin(theta))), + ret( + mat4( + $x(cs), + 0, + neg($y(cs)), + 0, + 0, + 1, + 0, + 0, + $y(cs), + 0, + $x(cs), + 0, + 0, + 0, + 0, + 1 + ) + ) + ]; +}); + +export const rotationZ4 = defn("mat4", "rotationZ4", [["float"]], (theta) => { + let cs: Vec2Term; + return [ + (cs = sym(cossin(theta))), + ret( + mat4( + $x(cs), + $y(cs), + 0, + 0, + neg($y(cs)), + $x(cs), + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1 + ) + ) + ]; +}); diff --git a/packages/shader-ast-stdlib/src/noise/hash.ts b/packages/shader-ast-stdlib/src/noise/hash.ts new file mode 100644 index 0000000000..41e4b2c82f --- /dev/null +++ b/packages/shader-ast-stdlib/src/noise/hash.ts @@ -0,0 +1,265 @@ +import { + $, + $x, + $y, + $z, + add, + assign, + defn, + dot, + FloatSym, + fract, + mat2, + mul, + ret, + sin, + sym, + vec2, + vec3, + Vec3Sym, + vec4, + Vec4Sym +} from "@thi.ng/shader-ast"; + +/** + * iq's hash PRNG producing 2D results. + * + * @param p + */ +export const hash2 = defn("vec2", "hash2", [["vec2"]], (p) => [ + ret(fract(mul(sin(mul(p, mat2(127.1, 311.7, 269.5, 183.3))), 43758.5453))) +]); + +/** + * iq's hash PRNG producing 3D results. + * + * @param p + */ +export const hash3 = defn("vec3", "hash3", [["vec2"]], (p) => [ + ret( + fract( + mul( + sin( + vec3( + dot(p, vec2(127.1, 311.7)), + dot(p, vec2(269.5, 183.3)), + dot(p, vec2(419.2, 371.9)) + ) + ), + 43758.5453 + ) + ) + ) +]); + +const H = vec3(0.1031, 0.103, 0.0973); +const H4 = vec4(0.1031, 0.103, 0.0973, 0.1099); + +/** + * 1D hash. + * + * Dave Hoskins (https://www.shadertoy.com/view/4djSRW) + * + * @param p + */ +export const hash11 = defn("float", "hash11", [["float"]], (p) => { + let x: FloatSym; + return [ + (x = sym(fract(mul(p, 0.1031)))), + assign(x, mul(x, add(x, 19.19))), + assign(x, mul(x, add(x, x))), + ret(fract(x)) + ]; +}); + +/** + * 2D -> 1D hash. + * + * Dave Hoskins (https://www.shadertoy.com/view/4djSRW) + * + * @param p + */ +export const hash12 = defn("float", "hash12", [["vec2"]], (p) => { + let x: Vec3Sym; + return [ + (x = sym(fract(mul($(p, "xyx"), 0.1031)))), + assign(x, add(x, dot(x, add($(x, "yzx"), 19.19)))), + ret(fract(mul(add($x(x), $y(x)), $z(x)))) + ]; +}); + +/** + * 3D -> 1D hash. + * + * Dave Hoskins (https://www.shadertoy.com/view/4djSRW) + * + * @param p + */ +export const hash13 = defn("float", "hash13", [["vec3"]], (p) => { + let x: Vec3Sym; + return [ + (x = sym(fract(mul($(p, "xyx"), 0.1031)))), + assign(x, add(x, dot(x, add($(x, "yzx"), 19.19)))), + ret(fract(mul(add($x(x), $y(x)), $z(x)))) + ]; +}); + +/** + * 1D -> 2D hash. + * + * Dave Hoskins (https://www.shadertoy.com/view/4djSRW) + * + * @param p + */ +export const hash21 = defn("vec2", "hash21", [["float"]], (p) => { + let x: Vec3Sym; + return [ + (x = sym(fract(mul(vec3(p), H)))), + assign(x, add(x, dot(x, add($(x, "yzx"), 19.19)))), + ret(fract(mul(add($(x, "xx"), $(x, "yz")), $(x, "zy")))) + ]; +}); + +/** + * 2D -> 2D hash. + * + * Dave Hoskins (https://www.shadertoy.com/view/4djSRW) + * + * @param p + */ +export const hash22 = defn("vec2", "hash22", [["vec2"]], (p) => { + let x: Vec3Sym; + return [ + (x = sym(fract(mul($(p, "xyx"), H)))), + assign(x, add(x, dot(x, add($(x, "yzx"), 19.19)))), + ret(fract(mul(add($(x, "xx"), $(x, "yz")), $(x, "zy")))) + ]; +}); + +/** + * 3D -> 2D hash. + * + * Dave Hoskins (https://www.shadertoy.com/view/4djSRW) + * + * @param p + */ +export const hash23 = defn("vec2", "hash23", [["vec3"]], (p) => { + let x: Vec3Sym; + return [ + (x = sym(fract(mul(p, H)))), + assign(x, add(x, dot(x, add($(x, "yzx"), 19.19)))), + ret(fract(mul(add($(x, "xx"), $(x, "yz")), $(x, "zy")))) + ]; +}); + +/** + * 1D -> 3D hash. + * + * Dave Hoskins (https://www.shadertoy.com/view/4djSRW) + * + * @param p + */ +export const hash31 = defn("vec3", "hash31", [["float"]], (p) => { + let x: Vec3Sym; + return [ + (x = sym(fract(mul(p, H)))), + assign(x, add(x, dot(x, add($(x, "yzx"), 19.19)))), + ret(fract(mul(add($(x, "xxy"), $(x, "yzz")), $(x, "zyx")))) + ]; +}); + +/** + * 2D -> 3D hash. + * + * Dave Hoskins (https://www.shadertoy.com/view/4djSRW) + * + * @param p + */ +export const hash32 = defn("vec3", "hash32", [["vec2"]], (p) => { + let x: Vec3Sym; + return [ + (x = sym(fract(mul($(p, "xyx"), H)))), + assign(x, add(x, dot(x, add($(x, "yzx"), 19.19)))), + ret(fract(mul(add($(x, "xxy"), $(x, "yzz")), $(x, "zyx")))) + ]; +}); + +/** + * 3D -> 3D hash. + * + * Dave Hoskins (https://www.shadertoy.com/view/4djSRW) + * + * @param p + */ +export const hash33 = defn("vec3", "hash33", [["vec3"]], (p) => { + let x: Vec3Sym; + return [ + (x = sym(fract(mul(p, H)))), + assign(x, add(x, dot(x, add($(x, "yzx"), 19.19)))), + ret(fract(mul(add($(x, "xxy"), $(x, "yzz")), $(x, "zyx")))) + ]; +}); + +/** + * 1D -> 4D hash. + * + * Dave Hoskins (https://www.shadertoy.com/view/4djSRW) + * + * @param p + */ +export const hash41 = defn("vec4", "hash41", [["float"]], (p) => { + let x: Vec4Sym; + return [ + (x = sym(fract(mul(p, H4)))), + assign(x, add(x, dot(x, add($(x, "wzxy"), 19.19)))), + ret(fract(mul(add($(x, "xxyz"), $(x, "yzzw")), $(x, "zywx")))) + ]; +}); + +/** + * 2D -> 4D hash. + * + * Dave Hoskins (https://www.shadertoy.com/view/4djSRW) + * + * @param p + */ +export const hash42 = defn("vec4", "hash42", [["vec2"]], (p) => { + let x: Vec4Sym; + return [ + (x = sym(fract(mul($(p, "xyxy"), H4)))), + assign(x, add(x, dot(x, add($(x, "wzxy"), 19.19)))), + ret(fract(mul(add($(x, "xxyz"), $(x, "yzzw")), $(x, "zywx")))) + ]; +}); + +/** + * 3D -> 4D hash. + * + * Dave Hoskins (https://www.shadertoy.com/view/4djSRW) + * + * @param p + */ +export const hash43 = defn("vec4", "hash43", [["vec3"]], (p) => { + let x: Vec4Sym; + return [ + (x = sym(fract(mul($(p, "xyzx"), H4)))), + assign(x, add(x, dot(x, add($(x, "wzxy"), 19.19)))), + ret(fract(mul(add($(x, "xxyz"), $(x, "yzzw")), $(x, "zywx")))) + ]; +}); + +/** + * 4D -> 4D hash. + * + * Dave Hoskins (https://www.shadertoy.com/view/4djSRW) + * + * @param p + */ +export const hash44 = defn("vec4", "hash44", [["vec4"]], (p) => { + let x: Vec4Sym; + return [ + (x = sym(fract(mul(p, H4)))), + assign(x, add(x, dot(x, add($(x, "wzxy"), 19.19)))), + ret(fract(mul(add($(x, "xxyz"), $(x, "yzzw")), $(x, "zywx")))) + ]; +}); diff --git a/packages/shader-ast-stdlib/src/noise/permute.ts b/packages/shader-ast-stdlib/src/noise/permute.ts new file mode 100644 index 0000000000..d6a2d44905 --- /dev/null +++ b/packages/shader-ast-stdlib/src/noise/permute.ts @@ -0,0 +1,25 @@ +import { + add, + defn, + float, + FLOAT1, + mod, + mul, + ret +} from "@thi.ng/shader-ast"; + +export const permute = defn("float", "permute", [["float"]], (v) => [ + ret(mod(mul(v, add(mul(v, float(34)), FLOAT1)), float(289))) +]); + +export const permute2 = defn("vec2", "permute2", [["vec2"]], (v) => [ + ret(mod(mul(v, add(mul(v, float(34)), FLOAT1)), float(289))) +]); + +export const permute3 = defn("vec3", "permute3", [["vec3"]], (v) => [ + ret(mod(mul(v, add(mul(v, float(34)), FLOAT1)), float(289))) +]); + +export const permute4 = defn("vec4", "permute4", [["vec4"]], (v) => [ + ret(mod(mul(v, add(mul(v, float(34)), FLOAT1)), float(289))) +]); diff --git a/packages/shader-ast-stdlib/src/noise/simplex2.ts b/packages/shader-ast-stdlib/src/noise/simplex2.ts new file mode 100644 index 0000000000..5e127c08c7 --- /dev/null +++ b/packages/shader-ast-stdlib/src/noise/simplex2.ts @@ -0,0 +1,107 @@ +import { + $, + $x, + $xy, + $y, + abs, + add, + assign, + defn, + dot, + float, + FLOAT05, + FLOAT1, + floor, + fract, + gt, + max, + mod, + mul, + ret, + sub, + sym, + ternary, + vec2, + Vec2Sym, + vec3, + Vec3Sym, + vec4, + Vec4Sym +} from "@thi.ng/shader-ast"; +import { magSq2 } from "../math/magsq"; +import { permute3 } from "./permute"; + +/** + * Array and textureless GLSL 2D simplex noise function. Ported from + * original GLSL implementation by Ian McEwan & Ashima Arts. + * + * https://github.com/ashima/webgl-noise + */ +export const snoise2 = defn("float", "snoise2", [["vec2"]], (v) => { + let C: Vec4Sym; + let i: Vec2Sym; + let i1: Vec2Sym; + let x0: Vec2Sym; + let x12: Vec4Sym; + let p: Vec3Sym; + let m: Vec3Sym; + let x: Vec3Sym; + let h: Vec3Sym; + let ox: Vec3Sym; + let a0: Vec3Sym; + let g: Vec3Sym; + return [ + (C = sym( + vec4( + 0.211324865405187, + 0.366025403784439, + -0.577350269189626, + 0.024390243902439 + ) + )), + (i = sym(floor(add(v, dot(v, $(C, "yy")))))), + (x0 = sym(add(sub(v, i), dot(i, $(C, "xx"))))), + (i1 = sym(ternary(gt($x(x0), $y(x0)), vec2(1, 0), vec2(0, 1)))), + (x12 = sym(sub(add($(x0, "xyxy"), $(C, "xxzz")), vec4(i1, 0, 0)))), + assign(i, mod(i, float(289))), + (p = sym( + permute3( + add( + permute3(add(vec3(0, $y(i1), 1), $y(i))), + add(vec3(0, $x(i1), 1), $x(i)) + ) + ) + )), + (m = sym( + max( + sub( + FLOAT05, + vec3(magSq2(x0), magSq2($xy(x12)), magSq2($(x12, "zw"))) + ), + vec3() + ) + )), + assign(m, mul(m, m)), + assign(m, mul(m, m)), + (x = sym(sub(mul(2, fract(mul(p, $(C, "www")))), FLOAT1))), + (h = sym(sub(abs(x), FLOAT05))), + (ox = sym(floor(add(x, FLOAT05)))), + (a0 = sym(sub(x, ox))), + assign( + m, + mul( + m, + sub( + 1.79284291400159, + mul(0.85373472095314, add(mul(a0, a0), mul(h, h))) + ) + ) + ), + (g = sym(vec3(add(mul($x(a0), $x(x0)), mul($x(h), $y(x0)))))), + assign( + $(g, "yz"), + add(mul($(a0, "yz"), $(x12, "xz")), mul($(h, "yz"), $(x12, "yw"))) + ), + ret(mul(130, dot(m, g))) + ]; +}); diff --git a/packages/shader-ast-stdlib/src/noise/voronoi2.ts b/packages/shader-ast-stdlib/src/noise/voronoi2.ts new file mode 100644 index 0000000000..047212cc38 --- /dev/null +++ b/packages/shader-ast-stdlib/src/noise/voronoi2.ts @@ -0,0 +1,92 @@ +import { + $xy, + $z, + add, + assign, + defn, + div, + dot, + float, + FLOAT0, + FloatSym, + floor, + forLoop, + fract, + inc, + int, + lte, + madd, + mul, + pow, + ret, + smoothstep, + sqrt, + SQRT2, + sub, + sym, + vec2, + Vec2Sym, + vec3, + Vec3Sym +} from "@thi.ng/shader-ast"; +import { hash32 } from "./hash"; + +/** + * IQ's parametric 2D voronoise. Depending on `u` and `v`, this function + * produces 4 different noise types + * + * - cell noise (0,0) + * - voronoi (1,0) + * - perlin noise (0,1) + * - voronoise (1,1) + * + * http://www.iquilezles.org/www/articles/voronoise/voronoise.htm + * + * Note: This implementation uses the improved `hash32` by Dave Hoskins + * instead of iq's original `hash3`. + * + * @param p + * @param u + * @param v + */ +export const voronoise2 = defn( + "float", + "voronoise2", + [["vec2"], ["float"], ["float"]], + (x, u, v) => { + let p: Vec2Sym; + let f: Vec2Sym; + let coeff: Vec3Sym; + let k: FloatSym; + let va: FloatSym; + let wt: FloatSym; + let g: Vec2Sym; + let o: Vec3Sym; + let r: Vec2Sym; + let w: FloatSym; + return [ + (p = sym(floor(x))), + (f = sym(fract(x))), + (coeff = sym(vec3(u, u, 1))), + (k = sym(add(1, mul(63, pow(sub(1, v), float(4)))))), + (va = sym(FLOAT0)), + (wt = sym(FLOAT0)), + forLoop(sym(int(-2)), (i) => lte(i, int(2)), inc, (i) => [ + forLoop(sym(int(-2)), (j) => lte(j, int(2)), inc, (j) => [ + (g = sym(vec2(float(i), float(j)))), + (o = sym(mul(hash32(add(p, g)), coeff))), + (r = sym(add(sub(g, f), $xy(o)))), + (w = sym( + pow( + sub(1, smoothstep(FLOAT0, SQRT2, sqrt(dot(r, r)))), + k + ) + )), + assign(va, madd(w, $z(o), va)), + assign(wt, add(wt, w)) + ]) + ]), + ret(div(va, wt)) + ]; + } +); diff --git a/packages/shader-ast-stdlib/src/noise/worley2.ts b/packages/shader-ast-stdlib/src/noise/worley2.ts new file mode 100644 index 0000000000..b075fa6505 --- /dev/null +++ b/packages/shader-ast-stdlib/src/noise/worley2.ts @@ -0,0 +1,108 @@ +import { + $, + $x, + $xy, + $y, + $z, + abs, + add, + assign, + defn, + float, + floor, + fract, + Func2, + lt, + max, + min, + mod, + mul, + ret, + sqrt, + sub, + sym, + ternary, + Vec2Sym, + vec3, + Vec3Sym +} from "@thi.ng/shader-ast"; +import { permute3 } from "./permute"; + +export const worleyDist = defn( + "vec3", + "worleyDist", + [["vec3"], ["vec3"]], + (a, b) => [ret(add(mul(a, a), mul(b, b)))] +); + +export const worleyDistManhattan = defn( + "vec3", + "worleyDistManhatten", + [["vec3"], ["vec3"]], + (a, b) => [ret(add(abs(a), abs(b)))] +); + +/** + * Higher order function. Computes 2D Worley noise using provided + * distance function. The returned function takes 2 args: position and + * jitter amount, the latter in [0..1] interval. Returns noise + * components as vec2, with the x component containing the distance from + * closest simplex center and y the noise value. The vector components + * can be used individually or combined (e.g. `noise.y - noise.x`)... + * + * Based on implementation by Stefan Gustavson: + * http://webstaff.itn.liu.se/~stegu/GLSL-cellular/GLSL-cellular-notes.pdf + * + * @param distFn + */ +export const worley2 = (distFn: Func2<"vec3", "vec3", "vec3">) => + defn("vec2", "worley2", [["vec2"], ["float"]], (P, jitter) => { + const K = float(1 / 7); + const Ko = float(3 / 7); + const oI = sym(vec3(-1, 0, 1)); + const oF = sym(vec3(-0.5, 0.5, 1.5)); + let pI: Vec2Sym; + let pF: Vec2Sym; + let px: Vec3Sym; + let p: Vec3Sym; + let d1: Vec3Sym; + let d2: Vec3Sym; + let d3: Vec3Sym; + let d1a: Vec3Sym; + const $dist = (x: number) => + distFn( + add(add($x(pF), x), mul(sub(fract(mul(p, K)), Ko), jitter)), + add( + sub($y(pF), oF), + mul( + sub(mul(mod(floor(mul(p, K)), float(7)), K), Ko), + jitter + ) + ) + ); + return [ + oI, + oF, + (pI = sym(mod(floor(P), float(289)))), + (pF = sym(fract(P))), + (px = sym(permute3(add(oI, $x(pI))))), + (p = sym(permute3(add(add(oI, $y(pI)), $x(px))))), + (d1 = sym($dist(0.5))), + assign(p, permute3(add(oI, add($y(pI), $y(px))))), + (d2 = sym($dist(-0.5))), + assign(p, permute3(add(oI, add($y(pI), $z(px))))), + (d3 = sym($dist(-1.5))), + (d1a = sym(min(d1, d2))), + assign(d2, min(max(d1, d2), d3)), + assign(d1, min(d1a, d2)), + assign(d2, max(d1a, d2)), + assign($xy(d1), ternary(lt($x(d1), $y(d1)), $xy(d1), $(d1, "yx"))), + assign( + $(d1, "xz"), + ternary(lt($x(d1), $z(d1)), $(d1, "xz"), $(d1, "zx")) + ), + assign($(d1, "yz"), min($(d1, "yz"), $(d2, "yz"))), + assign($y(d1), min(min($y(d1), $z(d1)), $x(d2))), + ret(sqrt($xy(d1))) + ]; + }); diff --git a/packages/shader-ast-stdlib/src/raymarch/ao.ts b/packages/shader-ast-stdlib/src/raymarch/ao.ts new file mode 100644 index 0000000000..230dab4c41 --- /dev/null +++ b/packages/shader-ast-stdlib/src/raymarch/ao.ts @@ -0,0 +1,54 @@ +import { + $x, + add, + assign, + defn, + float, + FLOAT0, + FLOAT05, + FLOAT1, + FloatSym, + forLoop, + inc, + lte, + mul, + ret, + sub, + sym +} from "@thi.ng/shader-ast"; +import { RaymarchScene } from "../api"; +import { clamp01 } from "../math/clamp"; + +/** + * Higher order function returning an function to compute the Ambient + * Occlusion term / shadow factor for given SDF scene function. The + * returned function takes 2 arguments: surface pos and normal. It + * returns a float in [0..1] interval (zero = fully occluded). + * + * @param scene + * @param numSamples + */ +export const raymarchAO = (scene: RaymarchScene, numSamples = 5) => + defn("float", "raymarchAO", [["vec3"], ["vec3"]], (p, n) => { + let r: FloatSym; + let w: FloatSym; + let d0: FloatSym; + return [ + (r = sym(FLOAT0)), + (w = sym(FLOAT1)), + forLoop( + sym("float", float(1)), + (i) => lte(i, float(numSamples)), + (i) => inc(i), + (i) => [ + (d0 = sym(mul(i, 1 / numSamples))), + assign( + r, + add(r, mul(w, sub(d0, $x(scene(add(p, mul(n, d0))))))) + ), + assign(w, mul(w, FLOAT05)) + ] + ), + ret(sub(FLOAT1, clamp01(r))) + ]; + }); diff --git a/packages/shader-ast-stdlib/src/raymarch/direction.ts b/packages/shader-ast-stdlib/src/raymarch/direction.ts new file mode 100644 index 0000000000..612bd93afd --- /dev/null +++ b/packages/shader-ast-stdlib/src/raymarch/direction.ts @@ -0,0 +1,37 @@ +import { + $y, + defn, + div, + FLOAT2, + neg, + normalize, + radians, + ret, + sub, + sym, + tan, + Vec2Sym, + vec3 +} from "@thi.ng/shader-ast"; + +/** + * @param fragCoord vec2 + * @param res vec2 + * @param fov float vertical FOV (in degrees) + */ +export const raymarchDir = defn( + "vec3", + "raymarchDir", + [["vec2"], ["vec2"], ["float"]], + (frag, res, fov) => { + let uv: Vec2Sym; + return [ + (uv = sym(sub(frag, div(res, FLOAT2)))), + ret( + normalize( + vec3(uv, neg(div($y(res), tan(div(radians(fov), FLOAT2))))) + ) + ) + ]; + } +); diff --git a/packages/shader-ast-stdlib/src/raymarch/normal.ts b/packages/shader-ast-stdlib/src/raymarch/normal.ts new file mode 100644 index 0000000000..c727df7a77 --- /dev/null +++ b/packages/shader-ast-stdlib/src/raymarch/normal.ts @@ -0,0 +1,35 @@ +import { + $, + $x, + add, + defn, + normalize, + ret, + sub, + Swizzle2_3, + sym, + vec2, + Vec2Sym, + vec3 +} from "@thi.ng/shader-ast"; +import { RaymarchScene } from "../api"; + +/** + * Higher order function producing a function to compute the raymarched + * scene normal for a given scene function and intersection position. + * Like `raymarch()`, this function takes an existing scene function as + * argument. + * + * @param scene + * @param name + */ +export const raymarchNormal = (scene: RaymarchScene, name = "raymarchNormal") => + defn("vec3", name, [["vec3"], ["float"]], (p, smooth) => { + let dn: Vec2Sym; + const comp = (id: Swizzle2_3) => + sub($x(scene(add(p, $(dn, id)))), $x(scene(sub(p, $(dn, id))))); + return [ + (dn = sym(vec2(smooth, 0))), + ret(normalize(vec3(comp("xyy"), comp("yxy"), comp("yyx")))) + ]; + }); diff --git a/packages/shader-ast-stdlib/src/raymarch/point-at.ts b/packages/shader-ast-stdlib/src/raymarch/point-at.ts new file mode 100644 index 0000000000..79a93f0797 --- /dev/null +++ b/packages/shader-ast-stdlib/src/raymarch/point-at.ts @@ -0,0 +1,25 @@ +import { + add, + FloatTerm, + mul, + normalize, + Term, + Vec +} from "@thi.ng/shader-ast"; + +/** + * Inline function. Returns point on ray (`p`, `dir`) at distance `t`. + * Unless `norm` is true (default false), `dir` must be already + * normalized. + * + * @param p + * @param dir + * @param t + * @param normalize + */ +export const rayPointAt = ( + p: Term, + dir: Term, + t: FloatTerm, + norm = false +) => add(p, mul(norm ? normalize(dir) : dir, t)); diff --git a/packages/shader-ast-stdlib/src/raymarch/scene.ts b/packages/shader-ast-stdlib/src/raymarch/scene.ts new file mode 100644 index 0000000000..74f064cb6e --- /dev/null +++ b/packages/shader-ast-stdlib/src/raymarch/scene.ts @@ -0,0 +1,76 @@ +import { + $x, + $y, + assign, + brk, + defn, + float, + FloatSym, + forLoop, + gt, + ifThen, + inc, + int, + lt, + madd, + ret, + sym, + vec2, + Vec2Sym +} from "@thi.ng/shader-ast"; +import { RaymarchOpts, RaymarchScene } from "../api"; +import { rayPointAt } from "./point-at"; + +/** + * Higher order function producing a function to perform a raymarch + * using the provided `scene` function and options to configure the + * raymarch process itself. + * + * Returns an AST function which takes 2 args: ray origin, normalized + * ray direction and returning a 2D vector of: + * + * - x = the signed distance to the `scene` defined SDF surface + * - y = user data provided by `scene` (e.g. material ID) + * + * The `scene` function itself takes a 3D point as input and returns a + * vec2 with the same component meaning as above. + * + * @param scene + * @param _opts + */ +export const raymarchScene = ( + scene: RaymarchScene, + _opts?: Partial +) => { + const opts: RaymarchOpts = { + name: "raymarchScene", + near: 0.1, + far: 10, + steps: 100, + eps: 0.01, + bias: 0.7, + ..._opts + }; + return defn("vec2", opts.name, [["vec3"], ["vec3"]], (pos, dir) => { + let total: FloatSym; + let res: Vec2Sym; + return [ + (total = sym(float(opts.near))), + (res = sym("vec2")), + forLoop( + sym("int", int(0)), + (i) => lt(i, int(opts.steps)), + (i) => inc(i), + () => [ + assign(res, scene(rayPointAt(pos, dir, total))), + ifThen(lt($x(res), float(opts.eps)), [ + ret(vec2(total, $y(res))) + ]), + assign(total, madd($x(res), float(opts.bias), total)), + ifThen(gt(total, float(opts.far)), [brk]) + ] + ), + ret(vec2(opts.far, 0)) + ]; + }); +}; diff --git a/packages/shader-ast-stdlib/src/screen/uv.ts b/packages/shader-ast-stdlib/src/screen/uv.ts new file mode 100644 index 0000000000..0e33c13347 --- /dev/null +++ b/packages/shader-ast-stdlib/src/screen/uv.ts @@ -0,0 +1,34 @@ +import { + $x, + $y, + assign, + defn, + div, + mul, + ret, + sym, + Vec2Sym +} from "@thi.ng/shader-ast"; +import { fit0111 } from "../math/fit"; + +/** + * Takes `pos`, a screen coord (e.g. gl_FragCoord) and viewport + * resolution `res`, returns aspect corrected uv, with uv.y in [-1..1] + * interval. + * + * @param fragCoord vec2 + * @param res vec2 + */ +export const aspectCorrectedUV = defn( + "vec2", + "aspectCorrectedUV", + [["vec2"], ["vec2"]], + (pos, res) => { + let uv: Vec2Sym; + return [ + (uv = sym("vec2", fit0111(div(pos, res)))), + assign($x(uv), mul($x(uv), div($x(res), $y(res)))), + ret(uv) + ]; + } +); diff --git a/packages/shader-ast-stdlib/src/sdf/annular.ts b/packages/shader-ast-stdlib/src/sdf/annular.ts new file mode 100644 index 0000000000..5965e60b40 --- /dev/null +++ b/packages/shader-ast-stdlib/src/sdf/annular.ts @@ -0,0 +1,9 @@ +import { abs, FloatTerm, sub } from "@thi.ng/shader-ast"; + +/** + * Inline function. Bi-directional offset to create ring like shapes. + * + * @param d + * @param r + */ +export const sdfAnnular = (d: FloatTerm, r: FloatTerm) => sub(abs(d), r); diff --git a/packages/shader-ast-stdlib/src/sdf/box.ts b/packages/shader-ast-stdlib/src/sdf/box.ts new file mode 100644 index 0000000000..30ca4cc4b3 --- /dev/null +++ b/packages/shader-ast-stdlib/src/sdf/box.ts @@ -0,0 +1,55 @@ +import { + abs, + add, + defn, + FLOAT0, + length, + max, + min, + ret, + sub, + sym, + vec2, + Vec2Sym, + vec3, + Vec3Sym +} from "@thi.ng/shader-ast"; +import { maxComp2, maxComp3 } from "../math/maxcomp"; + +/** + * Returns signed distance from `p` to centered AABB of `size`. + * + * @param p vec2 + * @param size vec2 + */ +export const sdfBox2 = defn( + "float", + "sdRect", + [["vec2"], ["vec2"]], + (p, size) => { + let d: Vec2Sym; + return [ + (d = sym(sub(abs(p), size))), + ret(add(min(maxComp2(d), FLOAT0), length(max(d, vec2())))) + ]; + } +); + +/** + * Returns signed distance from `p` to centered AABB of `size`. + * + * @param p vec3 + * @param size vec3 + */ +export const sdfBox3 = defn( + "float", + "sdAABB", + [["vec3"], ["vec3"]], + (p, size) => { + let d: Vec3Sym; + return [ + (d = sym(sub(abs(p), size))), + ret(add(min(maxComp3(d), FLOAT0), length(max(d, vec3())))) + ]; + } +); diff --git a/packages/shader-ast-stdlib/src/sdf/cylinder.ts b/packages/shader-ast-stdlib/src/sdf/cylinder.ts new file mode 100644 index 0000000000..423d1444b7 --- /dev/null +++ b/packages/shader-ast-stdlib/src/sdf/cylinder.ts @@ -0,0 +1,38 @@ +import { + $, + $y, + abs, + add, + defn, + FLOAT0, + length, + max, + min, + ret, + sub, + sym, + vec2, + Vec2Sym +} from "@thi.ng/shader-ast"; +import { maxComp2 } from "../math/maxcomp"; + +/** + * Returns signed distance from `p` to cylinder centered around Y-axis + * with height `h` and radius `r`. + * + * @param p vec3 + * @param h float + * @param r float + */ +export const sdfCylinder = defn( + "float", + "sdCylinder", + [["vec3"], ["float"], ["float"]], + (p, h, r) => { + let d: Vec2Sym; + return [ + (d = sym(sub(abs(vec2(length($(p, "xz")), $y(p))), vec2(h, r)))), + ret(add(min(maxComp2(d), FLOAT0), length(max(d, vec2())))) + ]; + } +); diff --git a/packages/shader-ast-stdlib/src/sdf/isec.ts b/packages/shader-ast-stdlib/src/sdf/isec.ts new file mode 100644 index 0000000000..b2572d64c2 --- /dev/null +++ b/packages/shader-ast-stdlib/src/sdf/isec.ts @@ -0,0 +1,9 @@ +import { FloatTerm, max } from "@thi.ng/shader-ast"; + +/** + * Inline function. SDF shape intersection (a & b). + * + * @param a float + * @param b float + */ +export const sdfIntersect = (a: FloatTerm, b: FloatTerm) => max(b, a); diff --git a/packages/shader-ast-stdlib/src/sdf/line.ts b/packages/shader-ast-stdlib/src/sdf/line.ts new file mode 100644 index 0000000000..4c4ddd9b68 --- /dev/null +++ b/packages/shader-ast-stdlib/src/sdf/line.ts @@ -0,0 +1,54 @@ +import { + defn, + div, + dot, + length, + mul, + ret, + sub, + Sym, + sym, + Vec +} from "@thi.ng/shader-ast"; +import { clamp01 } from "../math/clamp"; + +/** + * Shared impl for sdLine2/3 + * + * @param p + * @param a + * @param b + */ +const line = (p: Sym, a: Sym, b: Sym) => { + let pa: Sym, ba: Sym; + return [ + (pa = sym(sub(p, a))), + (ba = sym(sub(b, a))), + ret(length(sub(pa, mul(ba, clamp01(div(dot(pa, ba), dot(ba, ba))))))) + ]; +}; + +/** + * Returns signed distance from `p` to centered circle of radius `r`. + * + * @param p vec2 + * @param r float + */ +export const sdfLine2 = defn( + "float", + "sdLine2", + [["vec2"], ["vec2"], ["vec2"]], + line +); + +/** + * @param p vec3 + * @param a vec3 + * @param b vec3 + */ +export const sdfLine3 = defn( + "float", + "sdLine3", + [["vec3"], ["vec3"], ["vec3"]], + line +); diff --git a/packages/shader-ast-stdlib/src/sdf/plane.ts b/packages/shader-ast-stdlib/src/sdf/plane.ts new file mode 100644 index 0000000000..5e6f69ded8 --- /dev/null +++ b/packages/shader-ast-stdlib/src/sdf/plane.ts @@ -0,0 +1,34 @@ +import { + add, + defn, + dot, + ret +} from "@thi.ng/shader-ast"; + +/** + * Returns signed distance from `p` to plane defined by `normal` and `w`. + * + * @param p vec2 + * @param normal vec2 + * @param w float + */ +export const sdfPlane2 = defn( + "float", + "sdPlane", + [["vec2"], ["vec2"], ["float"]], + (p, n, w) => [ret(add(dot(p, n), w))] +); + +/** + * Returns signed distance from `p` to plane defined by `normal` and `w`. + * + * @param p vec3 + * @param normal vec3 + * @param w float + */ +export const sdfPlane3 = defn( + "float", + "sdPlane", + [["vec3"], ["vec3"], ["float"]], + (p, n, w) => [ret(add(dot(p, n), w))] +); diff --git a/packages/shader-ast-stdlib/src/sdf/repeat.ts b/packages/shader-ast-stdlib/src/sdf/repeat.ts new file mode 100644 index 0000000000..81b3adf4d6 --- /dev/null +++ b/packages/shader-ast-stdlib/src/sdf/repeat.ts @@ -0,0 +1,34 @@ +import { + defn, + FLOAT05, + mod, + mul, + ret, + sub +} from "@thi.ng/shader-ast"; + +/** + * Domain repetition by wrapping position `p` into period `c`. + * + * @param p vec2 + * @param c vec2 + */ +export const sdfRepeat2 = defn( + "vec2", + "sdTxRepeat3", + [["vec2"], ["vec2"]], + (p, c) => [ret(sub(mod(p, c), mul(c, FLOAT05)))] +); + +/** + * Domain repetition by wrapping position `p` into period `c`. + * + * @param p vec3 + * @param c vec3 + */ +export const sdfRepeat3 = defn( + "vec3", + "sdTxRepeat3", + [["vec3"], ["vec3"]], + (p, c) => [ret(sub(mod(p, c), mul(c, FLOAT05)))] +); diff --git a/packages/shader-ast-stdlib/src/sdf/round.ts b/packages/shader-ast-stdlib/src/sdf/round.ts new file mode 100644 index 0000000000..54f3eabcc9 --- /dev/null +++ b/packages/shader-ast-stdlib/src/sdf/round.ts @@ -0,0 +1,12 @@ +import { FloatTerm, sub } from "@thi.ng/shader-ast"; + +/** + * Inline function. Essentially an isoline offset to create: + * + * - `r > 0`: rounded/thicker shapes + * - `r < 0`: sharper/thinner shapes + * + * @param d + * @param r + */ +export const sdfRound = (d: FloatTerm, r: FloatTerm) => sub(d, r); diff --git a/packages/shader-ast-stdlib/src/sdf/smooth-isec.ts b/packages/shader-ast-stdlib/src/sdf/smooth-isec.ts new file mode 100644 index 0000000000..2cf8ea3772 --- /dev/null +++ b/packages/shader-ast-stdlib/src/sdf/smooth-isec.ts @@ -0,0 +1,31 @@ +import { + add, + defn, + div, + FLOAT1, + FloatSym, + mix, + mul, + ret, + sub, + sym +} from "@thi.ng/shader-ast"; +import { clamp01 } from "../math/clamp"; +import { fit1101 } from "../math/fit"; + +/** + * @param d1 float + * @param d2 float + */ +export const sdfSmoothIntersect = defn( + "float", + "sdOpSmoothIntersect", + [["float"], ["float"], ["float"]], + (a, b, k) => { + let h: FloatSym; + return [ + (h = sym(clamp01(fit1101(div(sub(b, a), k))))), + ret(add(mix(b, a, h), mul(mul(k, h), sub(FLOAT1, h)))) + ]; + } +); diff --git a/packages/shader-ast-stdlib/src/sdf/smooth-sub.ts b/packages/shader-ast-stdlib/src/sdf/smooth-sub.ts new file mode 100644 index 0000000000..23417af025 --- /dev/null +++ b/packages/shader-ast-stdlib/src/sdf/smooth-sub.ts @@ -0,0 +1,32 @@ +import { + add, + defn, + div, + FLOAT1, + FloatSym, + mix, + mul, + neg, + ret, + sub, + sym +} from "@thi.ng/shader-ast"; +import { clamp01 } from "../math/clamp"; +import { fit1101 } from "../math/fit"; + +/** + * @param d1 float + * @param d2 float + */ +export const sdfSmoothSubtract = defn( + "float", + "sdOpSmoothSubtract", + [["float"], ["float"], ["float"]], + (a, b, k) => { + let h: FloatSym; + return [ + (h = sym(clamp01(fit1101(div(add(b, a), k))))), + ret(add(mix(b, neg(a), h), mul(mul(k, h), sub(FLOAT1, h)))) + ]; + } +); diff --git a/packages/shader-ast-stdlib/src/sdf/smooth-union.ts b/packages/shader-ast-stdlib/src/sdf/smooth-union.ts new file mode 100644 index 0000000000..4d4def8423 --- /dev/null +++ b/packages/shader-ast-stdlib/src/sdf/smooth-union.ts @@ -0,0 +1,30 @@ +import { + defn, + div, + FLOAT1, + FloatSym, + mix, + mul, + ret, + sub, + sym +} from "@thi.ng/shader-ast"; +import { clamp01 } from "../math/clamp"; +import { fit1101 } from "../math/fit"; + +/** + * @param d1 float + * @param d2 float + */ +export const sdfSmoothUnion = defn( + "float", + "sdOpSmoothUnion", + [["float"], ["float"], ["float"]], + (a, b, k) => { + let h: FloatSym; + return [ + (h = sym(clamp01(fit1101(div(sub(b, a), k))))), + ret(sub(mix(b, a, h), mul(mul(k, h), sub(FLOAT1, h)))) + ]; + } +); diff --git a/packages/shader-ast-stdlib/src/sdf/sphere.ts b/packages/shader-ast-stdlib/src/sdf/sphere.ts new file mode 100644 index 0000000000..480728b8ba --- /dev/null +++ b/packages/shader-ast-stdlib/src/sdf/sphere.ts @@ -0,0 +1,32 @@ +import { + defn, + length, + ret, + sub +} from "@thi.ng/shader-ast"; + +/** + * Returns signed distance from `p` to centered circle of radius `r`. + * + * @param p vec2 + * @param r float + */ +export const sdfCircle = defn( + "float", + "sdCircle", + [["vec2"], ["float"]], + (p, r) => [ret(sub(length(p), r))] +); + +/** + * Returns signed distance from `p` to centered sphere of radius `r`. + * + * @param p vec3 + * @param r float + */ +export const sdfSphere = defn( + "float", + "sdSphere", + [["vec3"], ["float"]], + (p, r) => [ret(sub(length(p), r))] +); diff --git a/packages/shader-ast-stdlib/src/sdf/sub.ts b/packages/shader-ast-stdlib/src/sdf/sub.ts new file mode 100644 index 0000000000..073919a7c7 --- /dev/null +++ b/packages/shader-ast-stdlib/src/sdf/sub.ts @@ -0,0 +1,9 @@ +import { FloatTerm, max, neg } from "@thi.ng/shader-ast"; + +/** + * Inline function. SDF shape subtraction (a - b). + * + * @param a float + * @param b float + */ +export const sdfSubtract = (a: FloatTerm, b: FloatTerm) => max(neg(b), a); diff --git a/packages/shader-ast-stdlib/src/sdf/torus.ts b/packages/shader-ast-stdlib/src/sdf/torus.ts new file mode 100644 index 0000000000..6324a3e805 --- /dev/null +++ b/packages/shader-ast-stdlib/src/sdf/torus.ts @@ -0,0 +1,26 @@ +import { + $, + $y, + defn, + length, + ret, + sub, + vec2 +} from "@thi.ng/shader-ast"; + +/** + * Returns signed distance from `p` to torus centered around Y-axis with + * radii `r1`, `r2`. + * + * @param p vec3 + * @param r1 float + * @param r2 float + */ +export const sdfTorus = defn( + "float", + "sdTorus", + [["vec3"], ["float"], ["float"]], + (p, r1, r2) => [ + ret(sub(length(vec2(sub(length($(p, "xz")), r2), $y(p))), r1)) + ] +); diff --git a/packages/shader-ast-stdlib/src/sdf/tri.ts b/packages/shader-ast-stdlib/src/sdf/tri.ts new file mode 100644 index 0000000000..2bab477cb8 --- /dev/null +++ b/packages/shader-ast-stdlib/src/sdf/tri.ts @@ -0,0 +1,65 @@ +import { + $x, + $y, + defn, + div, + dot, + FloatSym, + min, + mul, + neg, + ret, + sign, + sqrt, + sub, + sym, + vec2, + Vec2Sym +} from "@thi.ng/shader-ast"; +import { clamp01 } from "../math/clamp"; +import { cross2 } from "../math/cross2"; + +/** + * @param p vec2 + * @param a vec2 + * @param b vec2 + * @param c vec2 + */ +export const sdfTriangle2 = defn( + "float", + "sdTriangle", + [["vec2"], ["vec2"], ["vec2"], ["vec2"]], + (p, a, b, c) => { + let e0: Vec2Sym, e1: Vec2Sym, e2: Vec2Sym; + let v0: Vec2Sym, v1: Vec2Sym, v2: Vec2Sym; + let pq0: Vec2Sym, pq1: Vec2Sym, pq2: Vec2Sym; + let s: FloatSym; + let d: Vec2Sym; + + const $pq = (v: Vec2Sym, e: Vec2Sym) => + sub(v, mul(e, clamp01(div(dot(v, e), dot(e, e))))); + + return [ + (e0 = sym(sub(b, a))), + (e1 = sym(sub(c, b))), + (e2 = sym(sub(a, c))), + (v0 = sym(sub(p, a))), + (v1 = sym(sub(p, b))), + (v2 = sym(sub(p, c))), + (pq0 = sym($pq(v0, e0))), + (pq1 = sym($pq(v1, e1))), + (pq2 = sym($pq(v2, e2))), + (s = sym(sign(cross2(e0, e2)))), + (d = sym( + min( + min( + vec2(dot(pq0, pq0), mul(s, cross2(v0, e0))), + vec2(dot(pq1, pq1), mul(s, cross2(v1, e1))) + ), + vec2(dot(pq2, pq2), mul(s, cross2(v2, e2))) + ) + )), + ret(mul(neg(sqrt($x(d))), sign($y(d)))) + ]; + } +); diff --git a/packages/shader-ast-stdlib/src/sdf/union.ts b/packages/shader-ast-stdlib/src/sdf/union.ts new file mode 100644 index 0000000000..f015cfc666 --- /dev/null +++ b/packages/shader-ast-stdlib/src/sdf/union.ts @@ -0,0 +1,9 @@ +import { FloatTerm, min } from "@thi.ng/shader-ast"; + +/** + * Inline function. SDF shape union (a || b). + * + * @param a float + * @param b float + */ +export const sdfUnion = (a: FloatTerm, b: FloatTerm) => min(a, b); diff --git a/packages/shader-ast-stdlib/src/tex/index-coord.ts b/packages/shader-ast-stdlib/src/tex/index-coord.ts new file mode 100644 index 0000000000..d1cddc3d06 --- /dev/null +++ b/packages/shader-ast-stdlib/src/tex/index-coord.ts @@ -0,0 +1,30 @@ +import { + $x, + $y, + div, + madd, + modi, + UintTerm, + uvec2, + UVec2Term +} from "@thi.ng/shader-ast"; + +/** + * Inline function. Similar to `indexToUV()`, but returns uvec2 in pixel + * coords. Not compatible with WebGL1. + * + * @param i + * @param width + */ +export const indexToCoord = (i: UintTerm, width: UintTerm) => + uvec2(modi(i, width), div(i, width)); + +/** + * Inline function. Reverse op to `indexToCoord()`. Not compatible with + * WebGL1. + * + * @param coord + * @param width + */ +export const coordToIndex = (coord: UVec2Term, width: UintTerm) => + madd($y(coord), width, $x(coord)); diff --git a/packages/shader-ast-stdlib/src/tex/index-uv.ts b/packages/shader-ast-stdlib/src/tex/index-uv.ts new file mode 100644 index 0000000000..f99a390db2 --- /dev/null +++ b/packages/shader-ast-stdlib/src/tex/index-uv.ts @@ -0,0 +1,55 @@ +import { + $x, + $y, + add, + defn, + div, + float, + int, + modi, + mul, + ret, + vec2 +} from "@thi.ng/shader-ast"; + +/** + * Converts linearized 2D index `i` into a vec2 UV coord, based on given + * texture `size` (in pixels). + * + * @param i + * @param size + */ +export const indexToUV = defn( + "vec2", + "indexToUV", + [["int", "i", { prec: "highp" }], ["ivec2"]], + (i, size) => [ + ret( + vec2( + div(float(modi(i, $x(size))), float($x(size))), + div(float(div(i, $x(size))), float($y(size))) + ) + ) + ] +); + +/** + * Inverse operation of `indexToUV()`. Converts vec2 UV coord into + * linearized 2D index, based on given texture `width` (in pixels). + * + * @param i + * @param width + */ +export const uvToIndex = defn( + "int", + "uvToIndex", + [["vec2"], ["int", "width", { prec: "highp" }]], + (uv, width) => [ + ret( + add( + int(mul($x(uv), float(width))), + int(mul($y(uv), float(mul(width, width)))) + ) + ) + ] +); diff --git a/packages/shader-ast-stdlib/src/tex/read-index.ts b/packages/shader-ast-stdlib/src/tex/read-index.ts new file mode 100644 index 0000000000..698dc7099e --- /dev/null +++ b/packages/shader-ast-stdlib/src/tex/read-index.ts @@ -0,0 +1,50 @@ +import { + $x, + $xy, + $xyz, + IntTerm, + IVec2Term, + Sampler2DTerm, + texture +} from "@thi.ng/shader-ast"; +import { indexToUV } from "./index-uv"; + +/** + * Inline function. Returns x component at index `i` in `tex`. + * + * @param tex + * @param i + * @param size + */ +export const readIndex1 = (tex: Sampler2DTerm, i: IntTerm, size: IVec2Term) => + $x(texture(tex, indexToUV(i, size))); + +/** + * Inline function. Returns vec2 (x,y components) at index `i` in `tex`. + * + * @param tex + * @param i + * @param size + */ +export const readIndex2 = (tex: Sampler2DTerm, i: IntTerm, size: IVec2Term) => + $xy(texture(tex, indexToUV(i, size))); + +/** + * Inline function. Returns vec3 (x,y,z components) at index `i` in `tex`. + * + * @param tex + * @param i + * @param size + */ +export const readIndex3 = (tex: Sampler2DTerm, i: IntTerm, size: IVec2Term) => + $xyz(texture(tex, indexToUV(i, size))); + +/** + * Inline function. Returns vec4 at index `i` in `tex`. + * + * @param tex + * @param i + * @param size + */ +export const readIndex4 = (tex: Sampler2DTerm, i: IntTerm, size: IVec2Term) => + texture(tex, indexToUV(i, size)); diff --git a/packages/shader-ast-stdlib/test/index.ts b/packages/shader-ast-stdlib/test/index.ts new file mode 100644 index 0000000000..236f7ed1ed --- /dev/null +++ b/packages/shader-ast-stdlib/test/index.ts @@ -0,0 +1,6 @@ +// import * as assert from "assert"; +// import * as sas from "../src/index"; + +describe("shader-ast-stdlib", () => { + it("tests pending"); +}); diff --git a/packages/shader-ast-stdlib/test/tsconfig.json b/packages/shader-ast-stdlib/test/tsconfig.json new file mode 100644 index 0000000000..f6e63560dd --- /dev/null +++ b/packages/shader-ast-stdlib/test/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../../tsconfig.json", + "compilerOptions": { + "outDir": "../build", + "module": "commonjs" + }, + "include": [ + "./**/*.ts", + "../src/**/*.ts" + ] +} diff --git a/packages/shader-ast-stdlib/tsconfig.json b/packages/shader-ast-stdlib/tsconfig.json new file mode 100644 index 0000000000..893b9979c5 --- /dev/null +++ b/packages/shader-ast-stdlib/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": ".", + "module": "es6", + "target": "es6" + }, + "include": [ + "./src/**/*.ts" + ] +} diff --git a/packages/shader-ast/.npmignore b/packages/shader-ast/.npmignore new file mode 100644 index 0000000000..74ea62d1fa --- /dev/null +++ b/packages/shader-ast/.npmignore @@ -0,0 +1,12 @@ +.meta +.nyc_output +*.html +*.tgz +build +coverage +dev +doc +export +src* +test +tsconfig.json diff --git a/packages/shader-ast/CHANGELOG.md b/packages/shader-ast/CHANGELOG.md new file mode 100644 index 0000000000..03a80630ef --- /dev/null +++ b/packages/shader-ast/CHANGELOG.md @@ -0,0 +1,60 @@ +# Change Log + +All notable changes to this project will be documented in this file. +See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +# 0.1.0 (2019-07-07) + + +### Bug Fixes + +* **shader-ast:** allChildren() (while loop support) ([3a559cf](https://github.com/thi-ng/umbrella/commit/3a559cf)) +* **shader-ast:** buildCallGraph zero-dep fn handling ([2f9da96](https://github.com/thi-ng/umbrella/commit/2f9da96)) +* **shader-ast:** fix op2(), update Tag, general cleanup ([46bcb04](https://github.com/thi-ng/umbrella/commit/46bcb04)) +* **shader-ast:** mod() type inference ([1412f71](https://github.com/thi-ng/umbrella/commit/1412f71)) +* **shader-ast:** update allChildren() ([1711064](https://github.com/thi-ng/umbrella/commit/1711064)) +* **shader-ast:** use GLSL style mod in JS codegen ([b4ca8e4](https://github.com/thi-ng/umbrella/commit/b4ca8e4)) +* **shader-ast:** use JS op2 info hints to delegate ([162c1ae](https://github.com/thi-ng/umbrella/commit/162c1ae)) + + +### Features + +* **shader-ast:** add % modulo operator as modi() ([e7ace59](https://github.com/thi-ng/umbrella/commit/e7ace59)) +* **shader-ast:** add $xy, $xyz swizzle sugar ([ff0ed9e](https://github.com/thi-ng/umbrella/commit/ff0ed9e)) +* **shader-ast:** add arraySym(), update op2 to accept plain numbers ([dc4dc15](https://github.com/thi-ng/umbrella/commit/dc4dc15)) +* **shader-ast:** add assignments, re-org types, update vec ctors ([7dc32d1](https://github.com/thi-ng/umbrella/commit/7dc32d1)) +* **shader-ast:** add AST node types, builtins, major refactor ([f8caed5](https://github.com/thi-ng/umbrella/commit/f8caed5)) +* **shader-ast:** add buildCallGraph(), add deps ([4017284](https://github.com/thi-ng/umbrella/commit/4017284)) +* **shader-ast:** add builtins, `discard`, add/refactor ControlFlow node type ([663e992](https://github.com/thi-ng/umbrella/commit/663e992)) +* **shader-ast:** add builtins, update codegens, sym/lit opts, matrices ([3caede4](https://github.com/thi-ng/umbrella/commit/3caede4)) +* **shader-ast:** add defMain, allow null values in scope bodies ([de0a3da](https://github.com/thi-ng/umbrella/commit/de0a3da)) +* **shader-ast:** add forLoop(), ternary(), fix float/int casts, docs ([474e320](https://github.com/thi-ng/umbrella/commit/474e320)) +* **shader-ast:** add input(), output(), uniform(), update SymOpts ([1307b3f](https://github.com/thi-ng/umbrella/commit/1307b3f)) +* **shader-ast:** add isBool() helper, update gensym() to use base36 ids ([2b23b83](https://github.com/thi-ng/umbrella/commit/2b23b83)) +* **shader-ast:** add ivec / uvec support, bitwise ops, update types ([4f7ca39](https://github.com/thi-ng/umbrella/commit/4f7ca39)) +* **shader-ast:** add JS target, re-org ([c4a35e1](https://github.com/thi-ng/umbrella/commit/c4a35e1)) +* **shader-ast:** add op2 info, fix result type, make var names optional ([9cc13ab](https://github.com/thi-ng/umbrella/commit/9cc13ab)) +* **shader-ast:** add post-increment/decrement, update op1() ([c809af1](https://github.com/thi-ng/umbrella/commit/c809af1)) +* **shader-ast:** add powf(), update matchingPrimFor() ([ac179a3](https://github.com/thi-ng/umbrella/commit/ac179a3)) +* **shader-ast:** add program(), add docs ([fd1fca9](https://github.com/thi-ng/umbrella/commit/fd1fca9)) +* **shader-ast:** add single component swizzle fns ([8b36527](https://github.com/thi-ng/umbrella/commit/8b36527)) +* **shader-ast:** add support for (iu)sampler types, add textureGrad() ([f8f245b](https://github.com/thi-ng/umbrella/commit/f8f245b)) +* **shader-ast:** add sym() fn overrides, args ([02d62a2](https://github.com/thi-ng/umbrella/commit/02d62a2)) +* **shader-ast:** add texture built-ins ([42ffed9](https://github.com/thi-ng/umbrella/commit/42ffed9)) +* **shader-ast:** add trilight lighting model ([0705e9d](https://github.com/thi-ng/umbrella/commit/0705e9d)) +* **shader-ast:** add type aliases, update all uses, minor additions ([0914c56](https://github.com/thi-ng/umbrella/commit/0914c56)) +* **shader-ast:** add WASM target basics & C runtime ([ef06c74](https://github.com/thi-ng/umbrella/commit/ef06c74)) +* **shader-ast:** add/update sdf fns, fix fogExp2, update readme ([d5115ff](https://github.com/thi-ng/umbrella/commit/d5115ff)) +* **shader-ast:** add/update stdlib functions & docs ([e36c5b8](https://github.com/thi-ng/umbrella/commit/e36c5b8)) +* **shader-ast:** initial pkg import w/ updated deps & readme ([30efebe](https://github.com/thi-ng/umbrella/commit/30efebe)) +* **shader-ast:** major update JS codegen, implement most builtin fns, fixes ([7da1738](https://github.com/thi-ng/umbrella/commit/7da1738)) +* **shader-ast:** major updates ([51d42b4](https://github.com/thi-ng/umbrella/commit/51d42b4)) +* **shader-ast:** more fn arities, add defTarget(), add/update types ([fdceb65](https://github.com/thi-ng/umbrella/commit/fdceb65)) +* **shader-ast:** rename swizzle() => $(), add break/continue ([5db7d1c](https://github.com/thi-ng/umbrella/commit/5db7d1c)) +* **shader-ast:** simplify fn dep/call graph handling, fix allChildren() ([6ee63ea](https://github.com/thi-ng/umbrella/commit/6ee63ea)) +* **shader-ast:** update GLSL & JS targets to support texture fns ([10782e2](https://github.com/thi-ng/umbrella/commit/10782e2)) +* **shader-ast:** update JS codegen ([1d4cc58](https://github.com/thi-ng/umbrella/commit/1d4cc58)) +* **shader-ast:** update numeric ctors/casts, update swizzles, add uvec/bvec ctors ([423fd84](https://github.com/thi-ng/umbrella/commit/423fd84)) +* **shader-ast:** update program() to accept global syms & fns, add/update docs ([95524fb](https://github.com/thi-ng/umbrella/commit/95524fb)) +* **shader-ast:** update texture builtins, add texelFetchOffset ([a0af395](https://github.com/thi-ng/umbrella/commit/a0af395)) +* **shader-ast:** update/rename targetGLSL() ([2e405f8](https://github.com/thi-ng/umbrella/commit/2e405f8)) diff --git a/packages/shader-ast/LICENSE b/packages/shader-ast/LICENSE new file mode 100644 index 0000000000..8dada3edaf --- /dev/null +++ b/packages/shader-ast/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/packages/shader-ast/README.md b/packages/shader-ast/README.md new file mode 100644 index 0000000000..1fa3aa6c8c --- /dev/null +++ b/packages/shader-ast/README.md @@ -0,0 +1,502 @@ +# @thi.ng/shader-ast + +[![npm (scoped)](https://img.shields.io/npm/v/@thi.ng/shader-ast.svg)](https://www.npmjs.com/package/@thi.ng/shader-ast) +![npm downloads](https://img.shields.io/npm/dm/@thi.ng/shader-ast.svg) +[![Twitter Follow](https://img.shields.io/twitter/follow/thing_umbrella.svg?style=flat-square&label=twitter)](https://twitter.com/thing_umbrella) + +This project is part of the +[@thi.ng/umbrella](https://github.com/thi-ng/umbrella/) monorepo. + + + +- [About](#about) + - [Standard library of common, higher level operations](#standard-library-of-common-higher-level-operations) + - [Benefits](#benefits) + - [Language specific code generators](#language-specific-code-generators) + - [Higher level building blocks](#higher-level-building-blocks) + - [Prior art / influences](#prior-art--influences) + - [Future goals](#future-goals) +- [Installation](#installation) +- [Dependencies](#dependencies) +- [Usage examples](#usage-examples) +- [API](#api) + - [Supported types](#supported-types) + - [Operators](#operators) + - [Symbol definitions / assignments](#symbol-definitions--assignments) + - [Control flow](#control-flow) + - [Built-in functions](#built-in-functions) + - [User defined functions](#user-defined-functions) + - [Global scope](#global-scope) + - [Code generation](#code-generation) + - [Compilation & execution](#compilation--execution) + - [AST tooling & traversal](#ast-tooling--traversal) +- [Authors](#authors) +- [License](#license) + + + +## About + +![screenshot](https://raw.githubusercontent.com/thi-ng/umbrella/master/assets/screenshots/shader-ast-01.jpg) +Example shader running in plain JS & Canvas 2D context, +cross-compiled JS/GLSL outputs shown on the right + +Both an [embedded +DSL](https://en.wikipedia.org/wiki/Domain-specific_language) and [IR +format](https://en.wikipedia.org/wiki/Intermediate_representation) to +encourage and define *modular* shader code directly in TypeScript and +then cross-compile to different languages. Using GLSL types and +semantics as starting point, the DSL is used as an assembly language to +define a partially (as much as possible / feasible) type checked AST, +incl. custom, user defined functions, higher-order functions, inline +functions, automatic vector-scalar overrides, most of GLSL ES 3.0 +built-ins, arg checking, and function return type inference. + +Code generation can be done for individual expressions or entire shader +programs, incl. call graph analysis and topological re-ordering of all +transitively called functions (other than built-ins). Currently only +GLSL & JS are supported as target (see code gen packages below), but +custom code generators can be easily added. Once more details have been +ironed out, we aim to support [Houdini +VEX](http://www.sidefx.com/docs/houdini/vex/index.html) (in-progress), +[WASM](https://webassembly.org), [WHLSL for +WebGPU](https://github.com/gpuweb/WHLSL) in the near future as well. + +![webgl/canvas2d comparison](https://raw.githubusercontent.com/thi-ng/umbrella/master/assets/screenshots/shader-ast-raymarch-compare.jpg) + +Comparison of the raymarch shader example (link further below), cross +compiled to both GLSL/WebGL and JavaScript w/ Canvas2D API and showing +the difference image of both results. + +![VEX plane displacement](https://raw.githubusercontent.com/thi-ng/umbrella/master/assets/screenshots/shader-ast-raymarch-vex-sm.gif) + +The same raymarching example compiled to Houdini VEX and used as "Point +Wrangle" to displace a grid geometry (using only the depth value of the +raymarching step). [Larger +version](https://twitter.com/thing_umbrella/status/1146109598274924544) + +### Standard library of common, higher level operations + +In addition to the code generation aspects, this package also provides a +form of "standard library", pure functions for common shader & GPGPU use +cases and which can be used as syntax sugar and / or higher level +building blocks for your own shaders. So far, this includes various math +utils, lighting models, fog equations, SDF primitives / operators, +raymarching helpers etc. [These functions are distributed in as separate +package](https://github.com/thi-ng/umbrella/tree/master/packages/shader-ast-stdlib). + +### Benefits + +- **no more copy & pasting, string interpolation / templating**: use + standard TS/JS tooling & full IDE integration to create shaders (e.g. + docs strings, packaging, 3rd party dependencies etc.) +- **all non-builtin functions keep track of their transitive dependencies**, + enabling call graph analysis, dead code elimination, topologically + correct code output ordering etc. - all without manual user intervention +- **improve general re-use**, especially once more target codegens are + available (see [future goals](#future-goals)). +- **higher-order function composition & customization** (e.g. see + [raymarch.ts](https://github.com/thi-ng/umbrella/tree/master/packages/shader-ast-stdlib/src/raymarch/scene.ts), + or + [additive.ts](https://github.com/thi-ng/umbrella/tree/master/packages/shader-ast-stdlib/src/math/additive.ts)) +- **cross compilation** to different graphics environments +- shader functions can be called like standard TS/JS functions (incl. + automatically type checked args via TS mapped types) +- type checking (at authoring time & compile time) + and type annotations of all AST nodes catches many issues early on +- avoids complex GLSL parsing as done by other transpilers +- shader code will be fully minimized along with main app code in + production builds as part of standard bundling processes / tool + chains, no extra plugins needed +- small run time & file size overhead (depending on output target impl) + +### Language specific code generators + +- [@thi.ng/shader-ast-glsl](https://github.com/thi-ng/umbrella/tree/master/packages/shader-ast-glsl) - GLSL 100 / 300 (WebGL1 / 2) +- [@thi.ng/shader-ast-js](https://github.com/thi-ng/umbrella/tree/master/packages/shader-ast-js) - plain JavaScript (incl. runtime) +- [@thi.ng/shader-ast-vex](https://github.com/thi-ng/umbrella/tree/master/packages/shader-ast-vex) - Houdini VEX + +### Higher level building blocks + +- [@thi.ng/shader-ast-stdlib](https://github.com/thi-ng/umbrella/tree/master/packages/shader-ast-stdlib) + +### Prior art / influences + +- [Hypergiant](http://alex-charlton.com/posts/Prototype_to_polish_Making_games_in_CHICKEN_Scheme_with_Hypergiant) +- [Lux](https://github.com/cscheid/lux/tree/master/src/shade) +- [Penumbra](https://github.com/ztellman/penumbra) +- [gamma](https://github.com/kovasb/gamma/) +- [thi.ng/shader-graph](http://thi.ng/shader-graph) +- [LLVM](http://llvm.org) + +### Future goals + +See the [project +dashboard](https://github.com/thi-ng/umbrella/projects/2) for current +status. The TL;DR list... + +- [ ] documentation +- [ ] struct support +- [ ] uniform blocks +- [ ] more code gens (JS ✅, WASM, WHLSL, OpenCL, Houdini VEX (WIP)) +- [ ] JS runtime improvements / features (non-GPU / vanilla JS shader execution) +- [ ] Integration w/ a GLSL parser (new or existing) +- [ ] AST transformations (optimizers, e.g. [constant + folding ✅](https://github.com/thi-ng/umbrella/tree/master/packages/shader-ast/src/optimize.ts)) + +## Installation + +```bash +yarn add @thi.ng/shader-ast +``` + +## Dependencies + +- [@thi.ng/api](https://github.com/thi-ng/umbrella/tree/master/packages/api) +- [@thi.ng/checks](https://github.com/thi-ng/umbrella/tree/master/packages/checks) +- [@thi.ng/defmulti](https://github.com/thi-ng/umbrella/tree/master/packages/defmulti) +- [@thi.ng/dgraph](https://github.com/thi-ng/umbrella/tree/master/packages/dgraph) +- [@thi.ng/errors](https://github.com/thi-ng/umbrella/tree/master/packages/errors) + +## Usage examples + +(Possibly non-exhaustive list, live demo links in readme's) + +- [Canvas2D shader](https://github.com/thi-ng/umbrella/tree/master/examples/shader-ast-canvas2d) +- [2D SDF](https://github.com/thi-ng/umbrella/tree/master/examples/shader-ast-sdf2d) +- [Raymarching](https://github.com/thi-ng/umbrella/tree/master/examples/shader-ast-raymarch) +- [Simplex noise](https://github.com/thi-ng/umbrella/tree/master/examples/shader-ast-noise) +- [Textured tunnel](https://github.com/thi-ng/umbrella/tree/master/examples/shader-ast-tunnel) +- [Cubemap](https://github.com/thi-ng/umbrella/tree/master/examples/webgl-cubemap) +- [Grid instancing](https://github.com/thi-ng/umbrella/tree/master/examples/webgl-grid) +- [GPGPU basics](https://github.com/thi-ng/umbrella/tree/master/examples/webgl-gpgpu-basics) +- [MSDF font rendering](https://github.com/thi-ng/umbrella/tree/master/examples/webgl-msdf) +- [SSAO deferred rendering](https://github.com/thi-ng/umbrella/tree/master/examples/webgl-ssao) + +## API + +**TODO** - docs forthcoming + +### Supported types + +- `float` (32 bit) +- `int` (signed 32bit) +- `uint` (unsigned 32bit) +- `bool` +- `vec2` (f32) +- `vec3` (f32) +- `vec4` (f32) +- `ivec2` (i32) +- `ivec3` (i32) +- `ivec4` (i32) +- `uvec2` (u32) +- `uvec3` (u32) +- `uvec4` (u32) +- `bvec2` (bool) +- `bvec3` (bool) +- `bvec4` (bool) +- `mat2` (2x2, f32) +- `mat3` (3x3, f32) +- `mat4` (4x4, f32) +- `sampler2D` +- `sampler3D` +- `samplerCube` +- `sampler2DShadow` +- `samplerCubeShadow` +- `isampler2D` +- `isampler3D` +- `isamplerCube` +- `usampler2D` +- `usampler3D` +- `usamplerCube` + +### Operators + +The following operators are all applied componentwise, take 2 arguments +and support mixed vector / scalar args. One of the operands can also be +a plain JS number, but not both. The resulting AST nodes will contain +type hints to simplify later code generation tasks: + +- `add` +- `div` +- `mul` +- `sub` + +If one of the operands is a vector or matrix and the other scalar, the +result will be vector/matrix. + +If a plain (unwrapped) JS number value is given for one of the operands, +it will be automatically wrapped in a suitable type, based on that of +the other operand. E.g. In `add(vec2(1), 10)`, the `10` will be cast to +`float(10)`. In `add(ivec2(1), 10)`, it will be cast to `int(10)`... + +`mul` has exceptional semantics for `matrix * matrix`, `matrix * +vector` and `vector * matrix` operands (all perform correct linear +algebraic multiplications). See GLSL ES language reference. + +#### Comparison + +All comparisons result in a `bool` term (i.e. `Term<"bool">`) + +| AST | GLSL | +|-------|------| +| `lt` | `<` | +| `lte` | `<=` | +| `eq` | `==` | +| `neq` | `!=` | +| `gte` | `>=` | +| `gt` | `>` | + +#### Logic + +| AST | GLSL | +|-------|------| +| `and` | `&&` | +| `or` | `||` | +| `not` | `!` | + +#### Bitwise + +| AST | GLSL | +|----------|------| +| `bitand` | `&` | +| `bitor` | `|` | +| `bitxor` | `^` | +| `bitnot` | `~` | + +#### Swizzling + +Only available for vector types - to extract, , optionally reordered, +components and / or to expand, shorten vectors. If only one component is +selected, the result will be a scalar, else a vector of the specified +length. + +- `$(vec3(1,2,3), "zyx")` => `vec3(3,2,1)` + +Syntax sugar for single component lookups: + +- `$x(v)` (same as `$(v, "x")`) +- `$y(v)` +- `$z(v)` +- `$w(v)` +- `$xy(v)` +- `$xyz(v)` + +Swizzle patterns are type checked in the editor (and at compile time), i.e. + +- `$(vec2(1,2), "xyx")` => ok (results in equivalent of `vec3(1,2,1)`) +- `$(vec2(1,2), "xyz")` => **illegal** (since `z` is not available in a `vec2`) + +#### Array index lookups + +- `index` +- `indexMat` + +### Symbol definitions / assignments + +- `sym` +- `arraySym` +- `assign` +- `input` +- `output` +- `uniform` + +### Control flow + +- `brk` +- `cont` +- `discard` + +#### If-Then-Else + +- `ifThen(test, truthy, falsy)` + +#### Ternary operator + +- `ternary(test, truthy, falsy)` + +#### For-loop + +- `forLoop(sym, testFn, iterFn, bodyFn)` + +#### While-loop + +- `whileLoop(test, body)` + +### Built-in functions + +The most common set of GLSL ES 3.0 builtins are supported. See +[builtins.ts](https://github.com/thi-ng/umbrella/tree/master/packages/shader-ast/src/builtins.ts) +for reference. + +### User defined functions + +Functions can be created via `defn` and can accept 0-8 typed +arguments. Functions declared in this manner can be called like any +other TS/JS function and will return a function call AST node with the +supplied args. + +```ts +// example from @thi.ng/shader-ast-stdlib + +/** + * Computes Lambert term, optionally using Half-Lambertian, + * if `half` is true. + * + * https://developer.valvesoftware.com/wiki/Half_Lambert + * + * @param surfNormal vec3 + * @param lightDir vec3 + * @param half bool + */ +const lambert = defn( + // return type + "float", + // function name + "lambert", + // args (incl. optional name and other opts) + [["vec3"], ["vec3"], ["bool"]], + // function body + (n, ldir, bidir) => { + // pre-declare local var + let d: FloatSym; + // function body is array of AST nodes + return [ + // initialize local using expr given to `sym()` + (d = sym(dot(n, ldir))), + // return statement + ret( + ternary( + bidir, + fit1101(d), + // also see clamp01() in stdlib + clamp(d, float(0), float(1)) + ) + ) + ]; + } +); +``` + +When `defn` is called, the function body will be checked for correct +return types. Additionally a call graph for the function is generated to +ensure the code generator later emits all dependent functions in the +correct order. + +Since `defn` returns a standard TS/JS function, all arguments will be +automatically type checked at call sites (in TypeScript only). + +#### Inline functions + +If no function local variables are required and/or inlining is desired, +vanilla TS/JS functions can be used to produce a partial AST, which is +then inserted at the call site: + +```ts +/** + * Inline function. Computes sinc(kx). + * + * https://en.wikipedia.org/wiki/Sinc_function + * + * @param x + * @param k + */ +const sinc = (x: FloatTerm, k: FloatTerm) => + div(sin(mul(k,x)), mul(k, x)); +``` + +### Global scope + +#### Input / output variables / declarations + +- `input` +- `output` +- `uniform` + +#### Program definition + +- `program([...decls, ...functions])` + +### Code generation + +Currently, an AST can be compiled into the following languages: + +#### GLSL (ES) + +See +[@thi.ng/shader-ast-glsl](https://github.com/thi-ng/umbrella/tree/master/packages/shader-ast-glsl) +for further details. + +```ts +import { GLSLVersion, targetGLSL } from "@thi.ng/shader-ast-glsl"; + +// create codegen w/ options (defaults shown) +const glsl = targetGLSL({ + version: GLSLVersion.GLES_300, + versionPragma: true, + type: "fs" +}); + +console.log(glsl(lambert)) +``` + +#### JavaScript + +See +[@thi.ng/shader-ast-js](https://github.com/thi-ng/umbrella/tree/master/packages/shader-ast-js) +for further details. + +```ts +import { targetJS } from "@thi.ng/shader-ast-js"; + +const js = targetJS(); + +console.log(js(lambert)) +``` + +### Compilation & execution + +### AST tooling & traversal + +#### Tree traversals + +- `walk` +- `allChildren` +- `scopeChildren` + +#### Constant folding + +Currently only works for scalars and primitive math ops: + +```ts +import { constantFolding } from "@thi.ng/shader-ast"; + +const ast = mul(float(10), add(float(1), float(2))); + +// { +// tag: 'op2', +// type: 'float', +// info: undefined, +// op: '*', +// l: { tag: 'lit', type: 'float', info: undefined, val: 10 }, +// r: { +// tag: 'op2', +// type: 'float', +// info: undefined, +// op: '+', +// l: { tag: 'lit', type: 'float', info: undefined, val: 1 }, +// r: { tag: 'lit', type: 'float', info: undefined, val: 2 } +// } +// } + +constantFolding(ast) +// { tag: 'lit', type: 'float', info: undefined, val: 30 } +``` + +## Authors + +- Karsten Schmidt + +## License + +© 2019 Karsten Schmidt // Apache Software License 2.0 diff --git a/packages/shader-ast/package.json b/packages/shader-ast/package.json new file mode 100644 index 0000000000..72b0242f73 --- /dev/null +++ b/packages/shader-ast/package.json @@ -0,0 +1,59 @@ +{ + "name": "@thi.ng/shader-ast", + "version": "0.1.0", + "description": "DSL to define shader code in TypeScript and cross-compile to GLSL, JS and other targets", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", + "typings": "./index.d.ts", + "repository": { + "type": "git", + "url": "https://github.com/thi-ng/umbrella.git" + }, + "homepage": "https://github.com/thi-ng/umbrella/tree/master/packages/shader-ast", + "author": "Karsten Schmidt ", + "license": "Apache-2.0", + "scripts": { + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module", + "test": "rimraf build && tsc -p test/tsconfig.json && nyc mocha build/test/*.js", + "clean": "rimraf *.js *.d.ts .nyc_output build coverage doc lib std", + "cover": "yarn test && nyc report --reporter=lcov", + "doc": "node_modules/.bin/typedoc --mode modules --out doc src", + "pub": "yarn build && yarn publish --access public" + }, + "devDependencies": { + "@types/mocha": "^5.2.6", + "@types/node": "^12.0.8", + "mocha": "^6.1.4", + "nyc": "^14.0.0", + "typedoc": "^0.14.2", + "typescript": "^3.5.2" + }, + "dependencies": { + "@thi.ng/api": "^6.3.0", + "@thi.ng/checks": "^2.2.0", + "@thi.ng/defmulti": "^1.1.0", + "@thi.ng/dgraph": "^1.1.10", + "@thi.ng/errors": "^1.1.0" + }, + "keywords": [ + "AST", + "crosscompiler", + "code generator", + "DSL", + "ES6", + "GPGPU", + "GLSL", + "shader", + "typecheck", + "typescript", + "webgl", + "x-platform" + ], + "publishConfig": { + "access": "public" + }, + "sideEffects": false +} diff --git a/packages/shader-ast/src/api.ts b/packages/shader-ast/src/api.ts new file mode 100644 index 0000000000..e1961fa4ed --- /dev/null +++ b/packages/shader-ast/src/api.ts @@ -0,0 +1,736 @@ +import { + Fn, + Fn0, + Fn2, + Fn3, + Fn4, + Fn5, + Fn6, + Fn7, + Fn8 +} from "@thi.ng/api"; + +export type Tag = + | "arg" + | "array_init" + | "assign" + | "call" + | "call_i" + | "ctrl" + | "decl" + | "fn" + | "for" + | "idx" + | "if" + | "lit" + | "op1" + | "op2" + | "ret" + | "scope" + | "swizzle" + | "sym" + | "ternary" + | "while"; + +export type Type = + | "void" + | "bool" + | "bool[]" + | "float" + | "float[]" + | "int" + | "int[]" + | "uint" + | "uint[]" + | "vec2" + | "vec2[]" + | "vec3" + | "vec3[]" + | "vec4" + | "vec4[]" + | "ivec2" + | "ivec2[]" + | "ivec3" + | "ivec3[]" + | "ivec4" + | "ivec4[]" + | "uvec2" + | "uvec2[]" + | "uvec3" + | "uvec3[]" + | "uvec4" + | "uvec4[]" + | "bvec2" + | "bvec2[]" + | "bvec3" + | "bvec3[]" + | "bvec4" + | "bvec4[]" + | "mat2" + | "mat2[]" + | "mat3" + | "mat3[]" + | "mat4" + | "mat4[]" + | "sampler2D" + | "sampler2D[]" + | "sampler3D" + | "sampler3D[]" + | "samplerCube" + | "samplerCube[]" + | "sampler2DShadow" + | "sampler2DShadow[]" + | "samplerCubeShadow" + | "samplerCubeShadow[]" + | "isampler2D" + | "isampler2D[]" + | "isampler3D" + | "isampler3D[]" + | "isamplerCube" + | "isamplerCube[]" + | "usampler2D" + | "usampler2D[]" + | "usampler3D" + | "usampler3D[]" + | "usamplerCube" + | "usamplerCube[]"; + +export interface ArrayTypeMap { + bool: "bool[]"; + float: "float[]"; + int: "int[]"; + uint: "uint[]"; + vec2: "vec2[]"; + vec3: "vec3[]"; + vec4: "vec4[]"; + ivec2: "ivec2[]"; + ivec3: "ivec3[]"; + ivec4: "ivec4[]"; + uvec2: "uvec2[]"; + uvec3: "uvec3[]"; + uvec4: "uvec4[]"; + bvec2: "bvec2[]"; + bvec3: "bvec3[]"; + bvec4: "bvec4[]"; + mat2: "mat2[]"; + mat3: "mat3[]"; + mat4: "mat4[]"; + sampler2D: "sampler2D[]"; + sampler3D: "sampler3D[]"; + samplerCube: "samplerCube[]"; + sampler2DShadow: "sampler2DShadow[]"; + samplerCubeShadow: "samplerCubeShadow[]"; + isampler2D: "isampler2D[]"; + isampler3D: "isampler3D[]"; + isamplerCube: "isamplerCube[]"; + usampler2D: "usampler2D[]"; + usampler3D: "usampler3D[]"; + usamplerCube: "usamplerCube[]"; +} + +export interface IndexTypeMap { + "bool[]": "bool"; + "float[]": "float"; + "int[]": "int"; + "uint[]": "uint"; + "vec2[]": "vec2"; + "vec3[]": "vec3"; + "vec4[]": "vec4"; + "ivec2[]": "ivec2"; + "ivec3[]": "ivec3"; + "ivec4[]": "ivec4"; + "uvec2[]": "uvec2"; + "uvec3[]": "uvec3"; + "uvec4[]": "uvec4"; + "bvec2[]": "bvec2"; + "bvec3[]": "bvec3"; + "bvec4[]": "bvec4"; +} + +export type BoolTerm = Term<"bool">; +export type FloatTerm = Term<"float">; +export type IntTerm = Term<"int">; +export type UintTerm = Term<"uint">; +export type Vec2Term = Term<"vec2">; +export type Vec3Term = Term<"vec3">; +export type Vec4Term = Term<"vec4">; +export type IVec2Term = Term<"ivec2">; +export type IVec3Term = Term<"ivec3">; +export type IVec4Term = Term<"ivec4">; +export type UVec2Term = Term<"uvec2">; +export type UVec3Term = Term<"uvec3">; +export type UVec4Term = Term<"uvec4">; +export type BVec2Term = Term<"bvec2">; +export type BVec3Term = Term<"bvec3">; +export type BVec4Term = Term<"bvec4">; +export type Mat2Term = Term<"mat2">; +export type Mat3Term = Term<"mat3">; +export type Mat4Term = Term<"mat4">; +export type Sampler2DTerm = Term<"sampler2D">; +export type Sampler3DTerm = Term<"sampler3D">; +export type SamplerCubeTerm = Term<"samplerCube">; +export type ISampler2DTerm = Term<"isampler2D">; +export type ISampler3DTerm = Term<"isampler3D">; +export type ISamplerCubeTerm = Term<"isamplerCube">; +export type USampler2DTerm = Term<"usampler2D">; +export type USampler3DTerm = Term<"usampler3D">; +export type USamplerCubeTerm = Term<"usamplerCube">; + +export type BoolSym = Sym<"bool">; +export type FloatSym = Sym<"float">; +export type IntSym = Sym<"int">; +export type UintSym = Sym<"uint">; +export type Vec2Sym = Sym<"vec2">; +export type Vec3Sym = Sym<"vec3">; +export type Vec4Sym = Sym<"vec4">; +export type IVec2Sym = Sym<"ivec2">; +export type IVec3Sym = Sym<"ivec3">; +export type IVec4Sym = Sym<"ivec4">; +export type UVec2Sym = Sym<"uvec2">; +export type UVec3Sym = Sym<"uvec3">; +export type UVec4Sym = Sym<"uvec4">; +export type BVec2Sym = Sym<"bvec2">; +export type BVec3Sym = Sym<"bvec3">; +export type BVec4Sym = Sym<"bvec4">; +export type Mat2Sym = Sym<"mat2">; +export type Mat3Sym = Sym<"mat3">; +export type Mat4Sym = Sym<"mat4">; +export type Sampler2DSym = Sym<"sampler2D">; +export type Sampler3DSym = Sym<"sampler3D">; +export type SamplerCubeSym = Sym<"samplerCube">; +export type ISampler2DSym = Sym<"isampler2D">; +export type ISampler3DSym = Sym<"isampler3D">; +export type ISamplerCubeSym = Sym<"isamplerCube">; +export type USampler2DSym = Sym<"usampler2D">; +export type USampler3DSym = Sym<"usampler3D">; +export type USamplerCubeSym = Sym<"usamplerCube">; + +export interface MatIndexTypeMap { + mat2: "vec2"; + mat3: "vec3"; + mat4: "vec4"; +} + +export type Indexable = keyof IndexTypeMap; + +export type Vec = "vec2" | "vec3" | "vec4"; +export type IVec = "ivec2" | "ivec3" | "ivec4"; +export type UVec = "uvec2" | "uvec3" | "uvec4"; +export type BVec = "bvec2" | "bvec3" | "bvec4"; +export type Mat = "mat2" | "mat3" | "mat4"; +export type Sampler = + | "sampler2D" + | "sampler3D" + | "samplerCube" + | "sampler2DShadow" + | "samplerCubeShadow" + | "isampler2D" + | "isampler3D" + | "isamplerCube" + | "usampler2D" + | "usampler3D" + | "usamplerCube"; + +export type Prim = "float" | Vec; +export type Int = "int" | "uint"; +export type Comparable = "float" | Int; +export type Numeric = number | FloatTerm | IntTerm | UintTerm; +export type NumericF = number | FloatTerm; +export type NumericI = number | IntTerm; +export type NumericU = number | UintTerm; +export type NumericB = boolean | Numeric; + +export type Assignable = Sym | Swizzle | Index; + +export type MathOperator = "+" | "-" | "*" | "/" | "%" | "++" | "--"; +export type LogicOperator = "!" | "||" | "&&"; +export type ComparisonOperator = "<" | "<=" | "==" | "!=" | ">=" | ">"; +export type BitOperator = "<<" | ">>" | "|" | "&" | "^" | "~"; +export type Operator = + | MathOperator + | LogicOperator + | ComparisonOperator + | BitOperator; + +// swizzle gen: +// console.log([...permutations("xyz","xyz")].map((x) =>`"${x.join("")}"`).join(" | ")) + +export type Swizzle2_1 = "x" | "y"; +export type Swizzle2_2 = "xx" | "xy" | "yx" | "yy"; +// prettier-ignore +export type Swizzle2_3 = "xxx" | "xxy" | "xyx" | "xyy" | "yxx" | "yxy" | "yyx" | "yyy"; +// prettier-ignore +export type Swizzle2_4 = "xxxx" | "xxxy" | "xxyx" | "xxyy" | "xyxx" | "xyxy" | "xyyx" | "xyyy" | "yxxx" | "yxxy" | "yxyx" | "yxyy" | "yyxx" | "yyxy" | "yyyx" | "yyyy"; + +export type Swizzle3_1 = "x" | "y" | "z"; +// prettier-ignore +export type Swizzle3_2 = "xx" | "xy" | "xz" | "yx" | "yy" | "yz" | "zx" | "zy" | "zz"; +// prettier-ignore +export type Swizzle3_3 = "xxx" | "xxy" | "xxz" | "xyx" | "xyy" | "xyz" | "xzx" | "xzy" | "xzz" | "yxx" | "yxy" | "yxz" | "yyx" | "yyy" | "yyz" | "yzx" | "yzy" | "yzz" | "zxx" | "zxy" | "zxz" | "zyx" | "zyy" | "zyz" | "zzx" | "zzy" | "zzz"; +// prettier-ignore +export type Swizzle3_4 = "xxxx" | "xxxy" | "xxxz" | "xxyx" | "xxyy" | "xxyz" | "xxzx" | "xxzy" | "xxzz" | "xyxx" | "xyxy" | "xyxz" | "xyyx" | "xyyy" | "xyyz" | "xyzx" | "xyzy" | "xyzz" | "xzxx" | "xzxy" | "xzxz" | "xzyx" | "xzyy" | "xzyz" | "xzzx" | "xzzy" | "xzzz" | "yxxx" | "yxxy" | "yxxz" | "yxyx" | "yxyy" | "yxyz" | "yxzx" | "yxzy" | "yxzz" | "yyxx" | "yyxy" | "yyxz" | "yyyx" | "yyyy" | "yyyz" | "yyzx" | "yyzy" | "yyzz" | "yzxx" | "yzxy" | "yzxz" | "yzyx" | "yzyy" | "yzyz" | "yzzx" | "yzzy" | "yzzz" | "zxxx" | "zxxy" | "zxxz" | "zxyx" | "zxyy" | "zxyz" | "zxzx" | "zxzy" | "zxzz" | "zyxx" | "zyxy" | "zyxz" | "zyyx" | "zyyy" | "zyyz" | "zyzx" | "zyzy" | "zyzz" | "zzxx" | "zzxy" | "zzxz" | "zzyx" | "zzyy" | "zzyz" | "zzzx" | "zzzy" | "zzzz"; + +export type Swizzle4_1 = "x" | "y" | "z" | "w"; +// prettier-ignore +export type Swizzle4_2 = "xx" | "xy" | "xz" | "xw" | "yx" | "yy" | "yz" | "yw" | "zx" | "zy" | "zz" | "zw" | "wx" | "wy" | "wz" | "ww"; +// prettier-ignore +export type Swizzle4_3 = "xxx" | "xxy" | "xxz" | "xxw" | "xyx" | "xyy" | "xyz" | "xyw" | "xzx" | "xzy" | "xzz" | "xzw" | "xwx" | "xwy" | "xwz" | "xww" | "yxx" | "yxy" | "yxz" | "yxw" | "yyx" | "yyy" | "yyz" | "yyw" | "yzx" | "yzy" | "yzz" | "yzw" | "ywx" | "ywy" | "ywz" | "yww" | "zxx" | "zxy" | "zxz" | "zxw" | "zyx" | "zyy" | "zyz" | "zyw" | "zzx" | "zzy" | "zzz" | "zzw" | "zwx" | "zwy" | "zwz" | "zww" | "wxx" | "wxy" | "wxz" | "wxw" | "wyx" | "wyy" | "wyz" | "wyw" | "wzx" | "wzy" | "wzz" | "wzw" | "wwx" | "wwy" | "wwz" | "www"; +// prettier-ignore +export type Swizzle4_4 = "xxxx" | "xxxy" | "xxxz" | "xxxw" | "xxyx" | "xxyy" | "xxyz" | "xxyw" | "xxzx" | "xxzy" | "xxzz" | "xxzw" | "xxwx" | "xxwy" | "xxwz" | "xxww" | "xyxx" | "xyxy" | "xyxz" | "xyxw" | "xyyx" | "xyyy" | "xyyz" | "xyyw" | "xyzx" | "xyzy" | "xyzz" | "xyzw" | "xywx" | "xywy" | "xywz" | "xyww" | "xzxx" | "xzxy" | "xzxz" | "xzxw" | "xzyx" | "xzyy" | "xzyz" | "xzyw" | "xzzx" | "xzzy" | "xzzz" | "xzzw" | "xzwx" | "xzwy" | "xzwz" | "xzww" | "xwxx" | "xwxy" | "xwxz" | "xwxw" | "xwyx" | "xwyy" | "xwyz" | "xwyw" | "xwzx" | "xwzy" | "xwzz" | "xwzw" | "xwwx" | "xwwy" | "xwwz" | "xwww" | "yxxx" | "yxxy" | "yxxz" | "yxxw" | "yxyx" | "yxyy" | "yxyz" | "yxyw" | "yxzx" | "yxzy" | "yxzz" | "yxzw" | "yxwx" | "yxwy" | "yxwz" | "yxww" | "yyxx" | "yyxy" | "yyxz" | "yyxw" | "yyyx" | "yyyy" | "yyyz" | "yyyw" | "yyzx" | "yyzy" | "yyzz" | "yyzw" | "yywx" | "yywy" | "yywz" | "yyww" | "yzxx" | "yzxy" | "yzxz" | "yzxw" | "yzyx" | "yzyy" | "yzyz" | "yzyw" | "yzzx" | "yzzy" | "yzzz" | "yzzw" | "yzwx" | "yzwy" | "yzwz" | "yzww" | "ywxx" | "ywxy" | "ywxz" | "ywxw" | "ywyx" | "ywyy" | "ywyz" | "ywyw" | "ywzx" | "ywzy" | "ywzz" | "ywzw" | "ywwx" | "ywwy" | "ywwz" | "ywww" | "zxxx" | "zxxy" | "zxxz" | "zxxw" | "zxyx" | "zxyy" | "zxyz" | "zxyw" | "zxzx" | "zxzy" | "zxzz" | "zxzw" | "zxwx" | "zxwy" | "zxwz" | "zxww" | "zyxx" | "zyxy" | "zyxz" | "zyxw" | "zyyx" | "zyyy" | "zyyz" | "zyyw" | "zyzx" | "zyzy" | "zyzz" | "zyzw" | "zywx" | "zywy" | "zywz" | "zyww" | "zzxx" | "zzxy" | "zzxz" | "zzxw" | "zzyx" | "zzyy" | "zzyz" | "zzyw" | "zzzx" | "zzzy" | "zzzz" | "zzzw" | "zzwx" | "zzwy" | "zzwz" | "zzww" | "zwxx" | "zwxy" | "zwxz" | "zwxw" | "zwyx" | "zwyy" | "zwyz" | "zwyw" | "zwzx" | "zwzy" | "zwzz" | "zwzw" | "zwwx" | "zwwy" | "zwwz" | "zwww" | "wxxx" | "wxxy" | "wxxz" | "wxxw" | "wxyx" | "wxyy" | "wxyz" | "wxyw" | "wxzx" | "wxzy" | "wxzz" | "wxzw" | "wxwx" | "wxwy" | "wxwz" | "wxww" | "wyxx" | "wyxy" | "wyxz" | "wyxw" | "wyyx" | "wyyy" | "wyyz" | "wyyw" | "wyzx" | "wyzy" | "wyzz" | "wyzw" | "wywx" | "wywy" | "wywz" | "wyww" | "wzxx" | "wzxy" | "wzxz" | "wzxw" | "wzyx" | "wzyy" | "wzyz" | "wzyw" | "wzzx" | "wzzy" | "wzzz" | "wzzw" | "wzwx" | "wzwy" | "wzwz" | "wzww" | "wwxx" | "wwxy" | "wwxz" | "wwxw" | "wwyx" | "wwyy" | "wwyz" | "wwyw" | "wwzx" | "wwzy" | "wwzz" | "wwzw" | "wwwx" | "wwwy" | "wwwz" | "wwww"; + +export type Swizzle2 = Swizzle2_1 | Swizzle2_2 | Swizzle2_3 | Swizzle2_4; +export type Swizzle3 = Swizzle3_1 | Swizzle3_2 | Swizzle3_3 | Swizzle3_4; +export type Swizzle4 = Swizzle4_1 | Swizzle4_2 | Swizzle4_3 | Swizzle4_4; + +export type Arg = [A, string?, SymOpts?]; +export type Arg1 = [Arg]; +export type Arg2 = [Arg, Arg]; +export type Arg3 = [ + Arg, + Arg, + Arg +]; +export type Arg4< + A extends Type, + B extends Type, + C extends Type, + D extends Type +> = [Arg, Arg, Arg, Arg]; +export type Arg5< + A extends Type, + B extends Type, + C extends Type, + D extends Type, + E extends Type +> = [Arg, Arg, Arg, Arg, Arg]; +export type Arg6< + A extends Type, + B extends Type, + C extends Type, + D extends Type, + E extends Type, + F extends Type +> = [Arg, Arg, Arg, Arg, Arg, Arg]; +export type Arg7< + A extends Type, + B extends Type, + C extends Type, + D extends Type, + E extends Type, + F extends Type, + G extends Type +> = [Arg, Arg, Arg, Arg, Arg, Arg, Arg]; +export type Arg8< + A extends Type, + B extends Type, + C extends Type, + D extends Type, + E extends Type, + F extends Type, + G extends Type, + H extends Type +> = [Arg, Arg, Arg, Arg, Arg, Arg, Arg, Arg]; + +export type FnBody0 = Fn0; +export type FnBody1 = Fn, ScopeBody>; +export type FnBody2 = Fn2< + Sym, + Sym, + ScopeBody +>; +export type FnBody3 = Fn3< + Sym, + Sym, + Sym, + ScopeBody +>; +export type FnBody4< + A extends Type, + B extends Type, + C extends Type, + D extends Type +> = Fn4, Sym, Sym, Sym, ScopeBody>; +export type FnBody5< + A extends Type, + B extends Type, + C extends Type, + D extends Type, + E extends Type +> = Fn5, Sym, Sym, Sym, Sym, ScopeBody>; +export type FnBody6< + A extends Type, + B extends Type, + C extends Type, + D extends Type, + E extends Type, + F extends Type +> = Fn6, Sym, Sym, Sym, Sym, Sym, ScopeBody>; +export type FnBody7< + A extends Type, + B extends Type, + C extends Type, + D extends Type, + E extends Type, + F extends Type, + G extends Type +> = Fn7, Sym, Sym, Sym, Sym, Sym, Sym, ScopeBody>; +export type FnBody8< + A extends Type, + B extends Type, + C extends Type, + D extends Type, + E extends Type, + F extends Type, + G extends Type, + H extends Type +> = Fn8< + Sym, + Sym, + Sym, + Sym, + Sym, + Sym, + Sym, + Sym, + ScopeBody +>; + +export type Func0 = Fn0>; +export type Func1 = Fn, FnCall>; +export type Func2 = Fn2< + Term, + Term, + FnCall +>; +export type Func3< + A extends Type, + B extends Type, + C extends Type, + T extends Type +> = Fn3, Term, Term, FnCall>; +export type Func4< + A extends Type, + B extends Type, + C extends Type, + D extends Type, + T extends Type +> = Fn4, Term, Term, Term, FnCall>; +export type Func5< + A extends Type, + B extends Type, + C extends Type, + D extends Type, + E extends Type, + T extends Type +> = Fn5, Term, Term, Term, Term, FnCall>; +export type Func6< + A extends Type, + B extends Type, + C extends Type, + D extends Type, + E extends Type, + F extends Type, + T extends Type +> = Fn6, Term, Term, Term, Term, Term, FnCall>; +export type Func7< + A extends Type, + B extends Type, + C extends Type, + D extends Type, + E extends Type, + F extends Type, + G extends Type, + T extends Type +> = Fn7< + Term, + Term, + Term, + Term, + Term, + Term, + Term, + FnCall +>; +export type Func8< + A extends Type, + B extends Type, + C extends Type, + D extends Type, + E extends Type, + F extends Type, + G extends Type, + H extends Type, + T extends Type +> = Fn8< + Term, + Term, + Term, + Term, + Term, + Term, + Term, + Term, + FnCall +>; + +export type SymQualifier = "in" | "out" | "inout"; + +export type SymType = "in" | "out" | "uni"; + +export type Precision = "lowp" | "mediump" | "highp"; + +export type ScopeBody = (Term | null | undefined)[]; + +export interface Term { + tag: Tag; + type: T; +} + +export interface Scoped { + scope: Scope; +} + +export interface Lit extends Term { + val: any; + info?: string; +} + +export interface Sym extends Term { + id: string; + opts: SymOpts; + init?: Term; +} + +export interface SymOpts { + /** + * If in global scope, used for: + * + * - `in` => attribute (in VS), varying (in FS) + * - `out` => varying (in VS), output (in FS) + * + * For parameters / fn args: + * + * - `in` => passed into a function + * - `out` => passed back out of a function, but not initialized + * - `inout` => passed both into and out of a function + */ + q?: SymQualifier; + /** + * Symbol type, only used for global scope in/out vars, e.g. + * attribute, varying, uniform. + */ + type?: SymType; + /** + * Const symbol + */ + const?: boolean; + /** + * Precision qualifier + */ + prec?: Precision; + /** + * Arrays only. Length + */ + num?: number; + /** + * Layout location + */ + loc?: number; +} + +export interface ArrayInit extends Term { + init: (Sym | Lit)[]; +} + +export interface Decl extends Term { + id: Sym; +} + +export interface Swizzle extends Term { + id: string; + val: Term; +} + +export interface Index extends Term { + id: Term<"int"> | Term<"uint">; + val: Term; +} + +export interface Assign extends Term { + l: Assignable; + r: Term; +} + +export interface Op1 extends Term { + op: Operator; + val: Term; + post?: boolean; +} + +export interface Op2 extends Term { + info?: string; + op: Operator; + l: Term; + r: Term; +} + +export interface Scope extends Term<"void"> { + body: Term[]; + global: boolean; +} + +export interface Branch extends Term<"void"> { + test: BoolTerm; + t: Scope; + f?: Scope; +} + +export interface Ternary extends Term { + test: BoolTerm; + t: Term; + f: Term; +} + +export interface ControlFlow extends Term<"void"> { + tag: "ctrl"; + id: string; +} + +export interface FuncReturn extends Term { + val?: Term; +} + +export interface FuncArg extends Term { + id: string; + opts: SymOpts; +} + +export interface Func extends Term, Scoped { + id: string; + args: Sym[]; + deps: Func[]; +} + +export interface TaggedFn0 extends Func0, Func { + args: []; +} + +export interface TaggedFn1 + extends Func1, + Func { + args: [Sym]; +} + +export interface TaggedFn2 + extends Func2, + Func { + args: [Sym, Sym]; +} + +export interface TaggedFn3< + A extends Type, + B extends Type, + C extends Type, + T extends Type +> extends Func3, Func { + args: [Sym, Sym, Sym]; +} + +export interface TaggedFn4< + A extends Type, + B extends Type, + C extends Type, + D extends Type, + T extends Type +> extends Func4, Func { + args: [Sym, Sym, Sym, Sym]; +} + +export interface TaggedFn5< + A extends Type, + B extends Type, + C extends Type, + D extends Type, + E extends Type, + T extends Type +> extends Func5, Func { + args: [Sym, Sym, Sym, Sym, Sym]; +} + +export interface TaggedFn6< + A extends Type, + B extends Type, + C extends Type, + D extends Type, + E extends Type, + F extends Type, + T extends Type +> extends Func6, Func { + args: [Sym, Sym, Sym, Sym, Sym, Sym]; +} + +export interface TaggedFn7< + A extends Type, + B extends Type, + C extends Type, + D extends Type, + E extends Type, + F extends Type, + G extends Type, + T extends Type +> extends Func7, Func { + args: [Sym, Sym, Sym, Sym, Sym, Sym, Sym]; +} + +export interface TaggedFn8< + A extends Type, + B extends Type, + C extends Type, + D extends Type, + E extends Type, + F extends Type, + G extends Type, + H extends Type, + T extends Type +> extends Func8, Func { + args: [Sym, Sym, Sym, Sym, Sym, Sym, Sym, Sym]; +} + +export interface FnCall extends Term { + id: string; + args: Term[]; + info?: string; + fn?: Func; +} + +export interface ForLoop extends Term<"void">, Scoped { + init?: Decl; + test: BoolTerm; + iter?: Term; +} + +export interface WhileLoop extends Term<"void">, Scoped { + test: BoolTerm; +} + +export interface TargetImpl extends Record> { + arg: Fn, T>; + array_init: Fn, T>; + assign: Fn, T>; + call: Fn, T>; + call_i: Fn, T>; + decl: Fn, T>; + fn: Fn, T>; + for: Fn; + idx: Fn, T>; + if: Fn; + lit: Fn, T>; + op1: Fn, T>; + op2: Fn, T>; + ret: Fn, T>; + scope: Fn; + swizzle: Fn, T>; + sym: Fn, T>; + ternary: Fn, T>; + while: Fn; +} diff --git a/packages/shader-ast/src/ast.ts b/packages/shader-ast/src/ast.ts new file mode 100644 index 0000000000..f16e7d39d8 --- /dev/null +++ b/packages/shader-ast/src/ast.ts @@ -0,0 +1,1415 @@ +import { + assert, + Fn, + Fn2, + IObjectOf, + Select4 +} from "@thi.ng/api"; +import { + isArray, + isBoolean, + isNumber, + isString +} from "@thi.ng/checks"; +import { DGraph } from "@thi.ng/dgraph"; +import { illegalArgs } from "@thi.ng/errors"; +import { + Arg, + Arg1, + Arg2, + Arg3, + Arg4, + Arg5, + Arg6, + Arg7, + Arg8, + ArrayTypeMap, + Assign, + Assignable, + BoolTerm, + Branch, + BVec, + BVec2Term, + BVec3Term, + BVec4Term, + Comparable, + ComparisonOperator, + ControlFlow, + Decl, + FloatTerm, + FnBody0, + FnBody1, + FnBody2, + FnBody3, + FnBody4, + FnBody5, + FnBody6, + FnBody7, + FnBody8, + FnCall, + ForLoop, + Func, + FuncArg, + FuncReturn, + Index, + Indexable, + IndexTypeMap, + Int, + IntTerm, + IVec, + IVec2Term, + IVec3Term, + IVec4Term, + Lit, + Mat, + Mat2Term, + Mat3Term, + Mat4Term, + MatIndexTypeMap, + Numeric, + NumericB, + NumericF, + NumericI, + NumericU, + Op1, + Op2, + Operator, + Prim, + Scope, + ScopeBody, + Swizzle, + Swizzle2, + Swizzle2_1, + Swizzle2_2, + Swizzle2_3, + Swizzle3, + Swizzle3_1, + Swizzle3_2, + Swizzle3_3, + Swizzle4, + Swizzle4_1, + Swizzle4_2, + Swizzle4_3, + Sym, + SymOpts, + TaggedFn0, + TaggedFn1, + TaggedFn2, + TaggedFn3, + TaggedFn4, + TaggedFn5, + TaggedFn6, + TaggedFn7, + TaggedFn8, + Term, + Ternary, + Type, + UintTerm, + UVec, + UVec2Term, + UVec3Term, + UVec4Term, + Vec, + Vec2Term, + Vec3Term, + Vec4Term, + WhileLoop +} from "./api"; + +let symID = 0; + +const RE_VEC = /^[iub]?vec[234]$/; +const RE_MAT = /^mat[234]$/; + +/** + * Helper for deterministic code generation / testing. Resets sym ID + * counter. + */ +export const resetSymID = () => (symID = 0); + +/** + * Generates a new symbol name, e.g. `_sa2`. Uses base36 for counter to + * keep names short. + */ +export const gensym = () => `_s${(symID++).toString(36)}`; + +/** + * Returns true, if given term evaluates to a boolean value. + */ +export const isBool = (t: Term) => t.type === "bool"; + +/** + * Returns true, if given term evaluates to a float value. + */ +export const isFloat = (t: Term) => t.type === "float"; + +/** + * Returns true, if given term evaluates to a signed integer value. + */ +export const isInt = (t: Term) => t.type === "int"; + +/** + * Returns true, if given term evaluates to an unsigned integer value. + */ +export const isUint = (t: Term) => t.type === "uint"; + +/** + * Returns true, if given term is a literal. + */ +export const isLit = (t: Term) => t.tag === "lit"; + +/** + * Returns true, if given term is a float literal. + */ +export const isLitFloat = (t: Term) => isLit(t) && isFloat(t); + +/** + * Returns true, if given term is a signed integer literal. + */ +export const isLitInt = (t: Term) => isLit(t) && isInt(t); + +/** + * Returns true, if given term is a numeric literal (float, int, uint). + */ +export const isLitNumeric = (t: Term) => + isLit(t) && (isFloat(t) || isInt(t) || isUint(t)); + +/** + * Returns true, if given term evaluates to a vector value (vec, ivec, bvec). + */ +export const isVec = (t: Term) => RE_VEC.test(t.type); + +/** + * Returns true, if given term evaluates to a matrix value. + */ +export const isMat = (t: Term) => RE_MAT.test(t.type); + +/** + * Returns base type for given term. Used for array ops. + * + * ``` + * itemType("vec2[]") => "vec2" + * ``` + */ +export const itemType = (type: Type) => type.replace("[]", ""); + +/** + * Takes a numeric term and a plain number, returns number wrapped in + * typed literal compatible with term. + * + * @param t + * @param x + */ +export const numberWithMatchingType = (t: Term, x: number) => { + const id = t.type[0]; + return id === "i" + ? int(x) + : id === "u" + ? uint(x) + : id === "b" + ? bool(x) + : float(x); +}; + +export const matchingPrimFor = ( + t: Term, + x: FloatTerm +): Term => { + const ctor = ({ vec2, vec3, vec4 })[t.type]; + return ctor ? ctor(x) : x; +}; + +/** + * Helper function for `walk()`. Returns child nodes for any control + * flow nodes containing a child scope. + * + * @see allChildren + */ +export const scopedChildren = (t: Term) => + t.tag === "fn" || t.tag === "for" || t.tag == "while" + ? (>t).scope.body + : t.tag === "if" + ? (t).f + ? (t).t.body.concat((t).f!.body) + : (t).t.body + : undefined; + +/** + * Helper function for `walk()`. Returns an array of all child nodes for + * a given term (if any). + * + * @see scopedChildren + */ +export const allChildren = (t: Term) => + t.tag === "scope" + ? (t).body + : t.tag === "fn" || t.tag === "for" || t.tag == "while" + ? (>t).scope.body + : t.tag === "if" + ? (t).f + ? (t).t.body.concat((t).f!.body) + : (t).t.body + : t.tag === "ternary" + ? [(>t).t, (>t).f] + : t.tag === "ret" + ? [(>t).val] + : t.tag === "call" || t.tag === "call_i" + ? (>t).args + : t.tag === "sym" && (>t).init + ? [(>t).init] + : t.tag === "decl" + ? [(>t).id] + : t.tag === "op1" || t.tag === "swizzle" + ? [(>t).val] + : t.tag === "op2" + ? [(>t).l, (>t).r] + : t.tag === "assign" + ? [(>t).r] + : isVec(t) || isMat(t) + ? (>t).val + : undefined; + +/** + * Traverses given AST in depth-first order and applies `visit` and + * `children` fns to each node. Descends only further if `children` + * returns an array of child nodes. The `visit` function must accept 2 + * args: the accumulator (`acc`) given to `walk` and a tree node. The + * return value of `visit` becomes the new `acc` value, much like in a + * reduce operation. `walk` itself returns the final `acc`. + * + * If `pre` is true (default), the `visit` function will be called prior + * to visiting a node's children. If false, the visitor is called on the + * way back up. + * + * @param visit + * @param children + * @param acc + * @param tree + * @param pre + */ +export const walk = ( + visit: Fn2, T>, + children: Fn, Term[] | undefined>, + acc: T, + tree: Term | Term[], + pre = true +) => { + if (isArray(tree)) { + tree.forEach((x) => (acc = walk(visit, children, acc, x, pre))); + } else { + pre && (acc = visit(acc, tree)); + const c = children(tree); + c && (acc = walk(visit, children, acc, c, pre)); + !pre && (acc = visit(acc, tree)); + } + return acc; +}; + +/** + * Builds dependency graph of given function, by recursively adding all + * function dependencies. Returns graph. + * + * @param fn + * @param graph + */ +export const buildCallGraph = ( + fn: Func, + graph: DGraph> = new DGraph() +): DGraph> => + fn.deps && fn.deps.length + ? fn.deps.reduce( + (graph, d) => buildCallGraph(d, graph.addDependency(fn, d)), + graph + ) + : graph.addNode(fn); + +export const lit = ( + type: T, + val: any, + info?: string +): Lit => ({ + tag: "lit", + type, + info, + val +}); + +export const bool = (x: Numeric | boolean) => + lit("bool", isNumber(x) ? !!x : x); + +export const float = (x: Numeric | boolean) => + lit("float", isBoolean(x) ? (x ? 1 : 0) : x); + +export const int = (x: Numeric | boolean) => + lit("int", isBoolean(x) ? (x ? 1 : 0) : isNumber(x) ? x | 0 : x); + +export const uint = (x: Numeric | boolean) => + lit("uint", isBoolean(x) ? (x ? 1 : 0) : isNumber(x) ? x >>> 0 : x); + +export const TRUE = lit("bool", true); +export const FALSE = lit("bool", false); + +export const FLOAT0: FloatTerm = float(0); +export const FLOAT1: FloatTerm = float(1); +export const FLOAT2: FloatTerm = float(2); +export const FLOAT05: FloatTerm = float(0.5); + +export const INT0: IntTerm = int(0); +export const INT1: IntTerm = int(1); + +export const UINT0: UintTerm = uint(0); +export const UINT1: UintTerm = uint(1); + +export const PI: FloatTerm = float(Math.PI); +export const TAU: FloatTerm = float(Math.PI * 2); +export const HALF_PI: FloatTerm = float(Math.PI / 2); +export const SQRT2: FloatTerm = float(Math.SQRT2); + +const wrap = (type: T, ctor: Fn>) => ( + x?: any +): Term | undefined => + isNumber(x) + ? ctor(x) + : x !== undefined && !isVec(x) && x.type !== type + ? ctor(x) + : x; + +/** + * Takes a plain number or numeric term and wraps it as float literal if + * needed. + * + * @param x + */ +export const wrapFloat = wrap("float", float); + +/** + * Takes a plain number or numeric term and wraps it as signed integer + * literal if needed. + * + * @param x + */ +export const wrapInt = wrap("int", int); + +/** + * Takes a plain number or numeric term and wraps it as unsigned integer + * literal if needed. + * + * @param x + */ +export const wrapUint = wrap("uint", uint); + +/** + * Takes a plain number or numeric term and wraps it as boolean literal + * if needed. + * + * @param x + */ +export const wrapBool = wrap("bool", bool); + +export function sym(init: Term): Sym; +export function sym(type: T): Sym; +export function sym(type: T, opts: SymOpts): Sym; +export function sym(type: T, init: Term): Sym; +export function sym(type: T, id: string): Sym; +// prettier-ignore +export function sym(type: T, id: string, opts: SymOpts): Sym; +// prettier-ignore +export function sym(type: T, opts: SymOpts, init: Term): Sym; +// prettier-ignore +export function sym(type: T, id: string, opts: SymOpts, init: Term): Sym; +export function sym(type: any, ...xs: any[]): Sym { + let id: string; + let opts: SymOpts; + let init: Term; + switch (xs.length) { + case 0: + if (!isString(type)) { + init = type; + type = init.type; + } + break; + case 1: + if (isString(xs[0])) { + id = xs[0]; + } else if (xs[0].tag) { + init = xs[0]; + } else { + opts = xs[0]; + } + break; + case 2: + if (isString(xs[0])) { + [id, opts] = xs; + } else { + [opts, init] = xs; + } + break; + case 3: + [id, opts, init] = xs; + break; + default: + illegalArgs(); + } + return { + tag: "sym", + type, + id: id! || gensym(), + opts: opts! || {}, + init: init! + }; +} + +export const constSym = ( + type: T, + id?: string, + opts?: SymOpts, + init?: Term +) => sym(type, id || gensym(), { const: true, ...opts }, init!); + +/** + * Defines a new symbol with optional initial array values. + * + * Important: Array initializers are UNSUPPORTED in GLSL ES v1 (WebGL), + * any code using such initializers will only work under WebGL2 or other + * targets. + */ +export const arraySym = ( + type: T, + id?: string, + opts: SymOpts = {}, + init?: (Lit | Sym)[] +): Sym => { + if (init && opts.num == null) { + opts.num = init.length; + } + assert(opts.num != null, "missing array length"); + init && + assert( + opts.num === init.length, + `expected ${opts.num} items in array, but got ${init.length}` + ); + const atype = (type + "[]"); + return { + tag: "sym", + type: atype, + id: id || gensym(), + opts, + init: init + ? { + tag: "array_init", + type: atype, + init + } + : undefined + }; +}; + +export const input = (type: T, id: string, opts?: SymOpts) => + sym(type, id, { q: "in", type: "in", ...opts }); + +export const output = (type: T, id: string, opts?: SymOpts) => + sym(type, id, { q: "out", type: "out", ...opts }); + +export const uniform = (type: T, id: string, opts?: SymOpts) => + sym(type, id, { q: "in", type: "uni", ...opts }); + +const decl = (id: Sym): Decl => ({ + tag: "decl", + type: id.type, + id +}); + +// prettier-ignore +export function $(a: Vec2Term, id: T): Swizzle>; +// prettier-ignore +export function $(a: Vec3Term, id: T): Swizzle>; +// prettier-ignore +export function $(a: Vec4Term, id: T): Swizzle>; +// prettier-ignore +export function $(a: IVec2Term, id: T): Swizzle>; +// prettier-ignore +export function $(a: IVec3Term, id: T): Swizzle>; +// prettier-ignore +export function $(a: IVec4Term, id: T): Swizzle>; +// prettier-ignore +export function $(a: UVec2Term, id: T): Swizzle>; +// prettier-ignore +export function $(a: UVec3Term, id: T): Swizzle>; +// prettier-ignore +export function $(a: UVec4Term, id: T): Swizzle>; +// prettier-ignore +export function $(a: BVec2Term, id: T): Swizzle>; +// prettier-ignore +export function $(a: BVec3Term, id: T): Swizzle>; +// prettier-ignore +export function $(a: BVec4Term, id: T): Swizzle>; +export function $(val: Term, id: string): Swizzle { + const type = val.type[0]; + const rtype = (a: Type, b: string) => + id.length === 1 ? a : (b + id.length); + return { + tag: "swizzle", + type: + type === "i" + ? rtype("int", "ivec") + : type === "u" + ? rtype("uint", "uvec") + : type === "b" + ? rtype("bool", "bvec") + : rtype("float", "vec"), + val, + id + }; +} + +export const $x = ( + val: Term +): Swizzle> => + $(val, "x"); + +export const $y = ( + val: Term +): Swizzle> => + $(val, "y"); + +export const $z = < + T extends + | "vec3" + | "vec4" + | "ivec3" + | "ivec4" + | "uvec3" + | "uvec4" + | "bvec3" + | "bvec4" +>( + val: Term +): Swizzle> => + $(val, "z"); + +export const $w = ( + val: Term +): Swizzle> => + $(val, "w"); + +export function $xy(val: Term): Swizzle<"vec2">; +export function $xy(val: Term): Swizzle<"ivec2">; +export function $xy(val: Term): Swizzle<"uvec2">; +export function $xy(val: Term): Swizzle<"bvec2">; +export function $xy(val: any): Swizzle { + return $(val, "xy"); +} + +export function $xyz(val: Term<"vec3" | "vec4">): Swizzle<"vec3">; +export function $xyz(val: Term<"ivec3" | "ivec4">): Swizzle<"ivec3">; +export function $xyz(val: Term<"uvec3" | "uvec4">): Swizzle<"uvec3">; +export function $xyz(val: Term<"bvec3" | "bvec4">): Swizzle<"bvec3">; +export function $xyz(val: any): Swizzle { + return $(val, "xyz"); +} + +export const index = ( + val: Sym, + id: NumericI | UintTerm +): Index => ({ + tag: "idx", + type: val.type.substr(0, val.type.length - 2), + id: isNumber(id) ? int(id) : id, + val +}); + +// prettier-ignore +export function indexMat(m: Sym, id: number): Index; +// prettier-ignore +export function indexMat(m: Sym, a: number, b: number): Index<"float">; +export function indexMat(m: Sym, a: number, b?: number): Index { + const idx: any = { + tag: "idx", + type: m.type.replace("mat", "vec"), + id: int(a), + val: m + }; + return b !== undefined + ? { tag: "idx", type: "float", id: int(b), val: idx } + : idx; +} + +export const assign = ( + l: Assignable, + r: Term +): Assign => { + assert( + l.tag !== "swizzle" || (>l).val.tag === "sym", + "can't assign to non-symbol swizzle" + ); + return { + tag: "assign", + type: l.type, + l, + r + }; +}; + +const $vec = (xs: any[], init = FLOAT0) => [ + xs[0] === undefined ? init : wrapFloat(xs[0]), + ...xs.slice(1).map(wrapFloat) +]; + +const $ivec = (xs: any[], init = INT0) => [ + xs[0] === undefined ? init : wrapInt(xs[0]), + ...xs.slice(1).map(wrapInt) +]; + +const $uvec = (xs: any[], init = UINT0) => [ + xs[0] === undefined ? init : wrapUint(xs[0]), + ...xs.slice(1).map(wrapUint) +]; + +const $bvec = (xs: any[], init = FALSE) => [ + xs[0] === undefined ? init : wrapBool(xs[0]), + ...xs.slice(1).map(wrapBool) +]; + +const $mat = (xs: any[], init = FLOAT0) => [ + xs[0] === undefined ? init : wrapFloat(xs[0]), + ...xs.slice(1).map(wrapInt) +]; + +export function vec2(): Lit<"vec2">; +export function vec2(x: NumericF): Lit<"vec2">; +// export function vec2(x: Term): Lit<"vec2">; +// prettier-ignore +export function vec2(x: NumericF, y: NumericF): Lit<"vec2">; +// prettier-ignore +export function vec2(...xs: any[]): Lit<"vec2"> { + xs = $vec(xs); + return lit("vec2", xs, ["n","n"][xs.length]); +} + +export function vec3(): Lit<"vec3">; +export function vec3(x: NumericF): Lit<"vec3">; +export function vec3(x: Vec2Term, y: NumericF): Lit<"vec3">; +// prettier-ignore +export function vec3(x: NumericF, y: NumericF, z: NumericF): Lit<"vec3">; +export function vec3(...xs: any[]): Lit<"vec3"> { + xs = $vec(xs); + return lit("vec3", xs, ["n", "n", "vn"][xs.length]); +} + +export function vec4(): Lit<"vec4">; +export function vec4(x: NumericF): Lit<"vec4">; +export function vec4(x: Vec3Term, y: NumericF): Lit<"vec4">; +export function vec4(x: Vec2Term, y: Vec2Term): Lit<"vec4">; +// prettier-ignore +export function vec4(x: Vec2Term, y: NumericF, z: NumericF): Lit<"vec4">; +// prettier-ignore +export function vec4(x: NumericF, y: NumericF, z: NumericF, w: NumericF): Lit<"vec4">; +export function vec4(...xs: any[]): Lit<"vec4"> { + xs = $vec(xs); + return lit( + "vec4", + xs, + xs.length === 2 + ? isVec(xs[1]) + ? "vv" + : "vn" + : ["n", "n", , "vnn"][xs.length] + ); +} + +export function ivec2(): Lit<"ivec2">; +export function ivec2(x: NumericI): Lit<"ivec2">; +// prettier-ignore +export function ivec2(x: NumericI, y: NumericI): Lit<"ivec2">; +// prettier-ignore +export function ivec2(...xs: any[]): Lit<"ivec2"> { + return lit("ivec2", $ivec(xs), ["n","n"][xs.length]); +} + +export function ivec3(): Lit<"ivec3">; +export function ivec3(x: NumericI): Lit<"ivec3">; +export function ivec3(x: Vec2Term, y: NumericI): Lit<"ivec3">; +// prettier-ignore +export function ivec3(x: NumericI, y: NumericI, z: NumericI): Lit<"ivec3">; +export function ivec3(...xs: any[]): Lit<"ivec3"> { + return lit("ivec3", (xs = $ivec(xs)), ["n", "n", "vn"][xs.length]); +} + +export function ivec4(): Lit<"ivec4">; +export function ivec4(x: NumericI): Lit<"ivec4">; +export function ivec4(x: Vec3Term, y: NumericI): Lit<"ivec4">; +export function ivec4(x: Vec2Term, y: Vec2Term): Lit<"ivec4">; +// prettier-ignore +export function ivec4(x: Vec2Term, y: NumericI, z: NumericI): Lit<"ivec4">; +// prettier-ignore +export function ivec4(x: NumericI, y: NumericI, z: NumericI, w: NumericI): Lit<"ivec4">; +export function ivec4(...xs: any[]): Lit<"ivec4"> { + return lit( + "ivec4", + (xs = $ivec(xs)), + xs.length === 2 + ? isVec(xs[1]) + ? "vv" + : "vn" + : ["n", "n", , "vnn"][xs.length] + ); +} + +export function uvec2(): Lit<"uvec2">; +export function uvec2(x: NumericU): Lit<"uvec2">; +// prettier-ignore +export function uvec2(x: NumericU, y: NumericU): Lit<"uvec2">; +// prettier-ignore +export function uvec2(...xs: any[]): Lit<"uvec2"> { + return lit("uvec2", $uvec(xs), ["n","n"][xs.length]); +} + +export function uvec3(): Lit<"uvec3">; +export function uvec3(x: NumericU): Lit<"uvec3">; +export function uvec3(x: Vec2Term, y: NumericU): Lit<"uvec3">; +// prettier-ignore +export function uvec3(x: NumericU, y: NumericU, z: NumericU): Lit<"uvec3">; +export function uvec3(...xs: any[]): Lit<"uvec3"> { + return lit("uvec3", (xs = $uvec(xs)), ["n", "n", "vn"][xs.length]); +} + +export function uvec4(): Lit<"uvec4">; +export function uvec4(x: NumericU): Lit<"uvec4">; +export function uvec4(x: Vec3Term, y: NumericU): Lit<"uvec4">; +export function uvec4(x: Vec2Term, y: Vec2Term): Lit<"uvec4">; +// prettier-ignore +export function uvec4(x: Vec2Term, y: NumericU, z: NumericU): Lit<"uvec4">; +// prettier-ignore +export function uvec4(x: NumericU, y: NumericU, z: NumericU, w: NumericU): Lit<"uvec4">; +export function uvec4(...xs: any[]): Lit<"uvec4"> { + return lit( + "uvec4", + (xs = $uvec(xs)), + xs.length === 2 + ? isVec(xs[1]) + ? "vv" + : "vn" + : ["n", "n", , "vnn"][xs.length] + ); +} + +export function bvec2(): Lit<"bvec2">; +export function bvec2(x: NumericB): Lit<"bvec2">; +// prettier-ignore +export function bvec2(x: NumericB, y: NumericB): Lit<"bvec2">; +// prettier-ignore +export function bvec2(...xs: any[]): Lit<"bvec2"> { + return lit("bvec2", $bvec(xs), ["n","n"][xs.length]); +} + +export function bvec3(): Lit<"bvec3">; +export function bvec3(x: NumericB): Lit<"bvec3">; +export function bvec3(x: Vec2Term, y: NumericB): Lit<"bvec3">; +// prettier-ignore +export function bvec3(x: NumericB, y: NumericB, z: NumericB): Lit<"bvec3">; +export function bvec3(...xs: any[]): Lit<"bvec3"> { + return lit("bvec3", (xs = $bvec(xs)), ["n", "n", "vn"][xs.length]); +} + +export function bvec4(): Lit<"bvec4">; +export function bvec4(x: NumericB): Lit<"bvec4">; +export function bvec4(x: Vec3Term, y: NumericB): Lit<"bvec4">; +export function bvec4(x: Vec2Term, y: Vec2Term): Lit<"bvec4">; +// prettier-ignore +export function bvec4(x: Vec2Term, y: NumericB, z: NumericB): Lit<"bvec4">; +// prettier-ignore +export function bvec4(x: NumericB, y: NumericB, z: NumericB, w: NumericB): Lit<"bvec4">; +export function bvec4(...xs: any[]): Lit<"bvec4"> { + return lit( + "bvec4", + (xs = $bvec(xs)), + xs.length === 2 + ? isVec(xs[1]) + ? "vv" + : "vn" + : ["n", "n", , "vnn"][xs.length] + ); +} + +export function mat2(): Lit<"mat2">; +export function mat2(x: NumericF): Lit<"mat2">; +export function mat2(x: Vec2Term, y: Vec2Term): Lit<"mat2">; +// prettier-ignore +export function mat2(a: NumericF, b: NumericF, c: NumericF, d: NumericF): Lit<"mat2">; +export function mat2(...xs: any[]): Lit<"mat2"> { + return lit("mat2", (xs = $mat(xs, FLOAT1)), ["n", "n", "vv"][xs.length]); +} + +export function mat3(): Lit<"mat3">; +export function mat3(x: NumericF): Lit<"mat3">; +// prettier-ignore +export function mat3(x: Vec3Term, y: Vec3Term, z: Vec3Term): Lit<"mat3">; +// prettier-ignore +export function mat3(a: NumericF, b: NumericF, c: NumericF, d: NumericF, e: NumericF, f: NumericF, g: NumericF, h: NumericF, i: NumericF): Lit<"mat3">; +export function mat3(...xs: any[]): Lit<"mat3"> { + return lit("mat3", (xs = $mat(xs, FLOAT1)), ["n", "n", , "vvv"][xs.length]); +} + +export function mat4(): Lit<"mat4">; +export function mat4(x: NumericF): Lit<"mat4">; +// prettier-ignore +export function mat4(x: Vec4Term, y: Vec4Term, z: Vec4Term, w: Vec4Term): Lit<"mat4">; +// prettier-ignore +export function mat4(a: NumericF, b: NumericF, c: NumericF, d: NumericF, e: NumericF, f: NumericF, g: NumericF, h: NumericF, i: NumericF, j: NumericF, k: NumericF, l: NumericF, m: NumericF, n: NumericF, o: NumericF, p: NumericF): Lit<"mat4">; +export function mat4(...xs: any[]): Lit<"mat4"> { + return lit( + "mat4", + (xs = $mat(xs, FLOAT1)), + ["n", "n", , , "vvvv"][xs.length] + ); +} + +export const op1 = ( + op: Operator, + val: Term, + post = false +): Op1 => ({ + tag: "op1", + type: val.type, + op, + val, + post +}); + +const OP_INFO: IObjectOf = { + mave: "mv", + vema: "vm", + vefl: "vn", + mafl: "vn", + flve: "nv", + flma: "nv", + ivin: "vn", + iniv: "nv", + uvui: "vn", + uiuv: "nv" +}; + +export const op2 = ( + op: Operator, + _l: Term | number, + _r: Term | number, + rtype?: Type, + info?: string +): Op2 => { + const nl = isNumber(_l); + const nr = isNumber(_r); + let type: Type; + let l: Term; + let r: Term; + if (nl) { + if (nr) { + // (number, number) + l = float(_l); + r = float(_r); + type = "float"; + } else { + // (number, term) + r = >_r; + l = numberWithMatchingType(r, _l); + type = r.type; + } + } else if (nr) { + // (term, number) + l = >_l; + r = numberWithMatchingType(l, _r); + type = l.type; + } else { + // (term, term) + l = >_l; + r = >_r; + type = + rtype || + (isVec(l) + ? l.type + : isVec(r) + ? r.type + : isMat(r) + ? r.type + : l.type); + } + return { + tag: "op2", + type: rtype || type!, + info: info || OP_INFO[l!.type.substr(0, 2) + r!.type.substr(0, 2)], + op, + l: l!, + r: r! + }; +}; + +export const inc = (t: Sym): Op1 => + op1("++", t, true); + +export const dec = (t: Sym): Op1 => + op1("--", t, true); + +// prettier-ignore +export function add(l: Term, r: Term): Op2; +export function add(l: number, r: Term): Op2; +export function add(l: Term, r: number): Op2; +// prettier-ignore +export function add(l: FloatTerm | number, r: Term): Op2; +// prettier-ignore +export function add(l: Term, r: FloatTerm | number): Op2; +// prettier-ignore +export function add(l: IntTerm | number, r: Term): Op2; +// prettier-ignore +export function add(l: Term, r: IntTerm | number): Op2; +// prettier-ignore +export function add(l: Term | number, r: Term | number): Op2 { + return op2("+", l, r); +} + +// prettier-ignore +export function sub(l: Term, r: Term): Op2; +export function sub(l: number, r: Term): Op2; +export function sub(l: Term, r: number): Op2; +// prettier-ignore +export function sub(l: FloatTerm | number, r: Term): Op2; +// prettier-ignore +export function sub(l: Term, r: FloatTerm | number): Op2; +// prettier-ignore +export function sub(l: IntTerm | number, r: Term): Op2; +// prettier-ignore +export function sub(l: Term, r: IntTerm| number): Op2; +export function sub(l: Term | number, r: Term | number): Op2 { + return op2("-", l, r); +} + +// prettier-ignore +export function mul(l: Term, r: Term): Op2; +export function mul(l: number, r: Term): Op2; +export function mul(l: Term, r: number): Op2; +// prettier-ignore +export function mul(l: FloatTerm | number, r: Term): Op2; +// prettier-ignore +export function mul(l: Term, r: FloatTerm | number): Op2; +// prettier-ignore +export function mul(l: IntTerm | number, r: Term): Op2; +// prettier-ignore +export function mul(l: Term, r: IntTerm | number): Op2; +export function mul(l: Mat2Term, r: Vec2Term): Op2<"vec2">; +export function mul(l: Mat3Term, r: Vec3Term): Op2<"vec3">; +export function mul(l: Mat4Term, r: Vec4Term): Op2<"vec4">; +export function mul(l: Vec2Term, r: Mat2Term): Op2<"vec2">; +export function mul(l: Vec3Term, r: Mat3Term): Op2<"vec3">; +export function mul(l: Vec4Term, r: Mat4Term): Op2<"vec4">; +export function mul(l: Term | number, r: Term | number): Op2 { + return op2( + "*", + l, + r, + !isNumber(l) && !isNumber(r) && isMat(l) && isVec(r) + ? r.type + : undefined + ); +} + +// prettier-ignore +export function div(l: Term, r: Term): Op2; +export function div(l: number, r: Term): Op2; +export function div(l: Term, r: number): Op2; +// prettier-ignore +export function div(l: FloatTerm | number, r: Term): Op2; +// prettier-ignore +export function div(l: Term, r: FloatTerm | number): Op2; +// prettier-ignore +export function div(l: IntTerm | number, r: Term): Op2; +// prettier-ignore +export function div(l: Term, r: IntTerm | number): Op2; +export function div(l: Term | number, r: Term | number): Op2 { + return op2("/", l, r); +} + +/** + * Integer % (modulo) operator + * + * @param l + * @param b + */ +// prettier-ignore +export function modi(l: Term, r: Term): Op2; +// prettier-ignore +export function modi(l: IntTerm | number, r: Term): Op2; +// prettier-ignore +export function modi(l: Term, r: IntTerm | number): Op2; +// prettier-ignore +export function modi(l: UintTerm | number, r: Term): Op2; +// prettier-ignore +export function modi(l: Term, r: UintTerm | number): Op2; +export function modi(l: Term | number, r: Term | number): Op2 { + return op2( + "%", + isNumber(l) ? numberWithMatchingType(>r, l) : l, + isNumber(r) ? numberWithMatchingType(>l, r) : r + ); +} + +export const neg = (val: Term) => + op1("-", val); + +/** + * Multiply-add: a * b + c. All must be of same type. + * + * @param a + * @param b + * @param c + */ +export const madd = < + A extends Prim | IVec | UVec | "int" | "uint", + B extends A, + C extends B +>( + a: Term, + b: Term, + c: Term +): Term => add(mul(>a, b), c); + +/** + * Add-multiply: (a + b) * c. All must be of same type. + * + * @param a + * @param b + * @param c + */ +export const addm = ( + a: Term, + b: Term, + c: Term +): Term => mul(add(>a, b), c); + +export const not = (val: BoolTerm) => op1("!", val); +export const or = (a: BoolTerm, b: BoolTerm) => op2("||", a, b); +export const and = (a: BoolTerm, b: BoolTerm) => op2("&&", a, b); + +const cmp = (op: ComparisonOperator) => ( + a: Term, + b: Term +): BoolTerm => op2(op, a, b, "bool"); + +export const eq = cmp("=="); +export const neq = cmp("!="); +export const lt = cmp("<"); +export const lte = cmp("<="); +export const gt = cmp(">"); +export const gte = cmp(">="); + +export const bitnot = | Term>( + val: T +) => op1("~", val); + +// prettier-ignore +export function bitand(l: Term, r: Term): Term; +// prettier-ignore +export function bitand(l: Term, r: IntTerm | number): Term; +// prettier-ignore +export function bitand(l: IntTerm | number, r: Term): Term; +// prettier-ignore +export function bitand(l: Term, r: UintTerm | number): Term; +// prettier-ignore +export function bitand(l: UintTerm | number, r: Term): Term; +// prettier-ignore +export function bitand(l: Term | number, r: Term | number): Op2 { + return op2("&", l, r, undefined); +} + +// prettier-ignore +export function bitor(l: Term, r: Term): Term; +// prettier-ignore +export function bitor(l: Term, r: IntTerm | number): Term; +// prettier-ignore +export function bitor(l: IntTerm | number, r: Term): Term; +// prettier-ignore +export function bitor(l: Term, r: UintTerm | number): Term; +// prettier-ignore +export function bitor(l: UintTerm | number, r: Term): Term; +// prettier-ignore +export function bitor(l: Term | number, r: Term | number): Op2 { + return op2("|", l, r, undefined); +} + +// prettier-ignore +export function bitxor(l: Term, r: Term): Term; +// prettier-ignore +export function bitxor(l: Term, r: IntTerm | number): Term; +// prettier-ignore +export function bitxor(l: IntTerm | number, r: Term): Term; +// prettier-ignore +export function bitxor(l: Term, r: UintTerm | number): Term; +// prettier-ignore +export function bitxor(l: UintTerm | number, r: Term): Term; +// prettier-ignore +export function bitxor(l: Term | number, r: Term | number): Op2 { + return op2("^", l, r, undefined); +} + +/** + * Wraps the given AST node array in `scope` node, optionally as global + * scope (default false). The interpretation of the global flag is + * dependent on the target code gen. I.e. for GLSL / JS, the flag + * disables wrapping the scope's body in `{}`, but else has no + * difference. In general this node type only serves as internal + * mechanism for various control flow AST nodes and should not need to + * be used directly from user land code (though might be useful to + * create custom / higher level control flow nodes). + * + * @param body + * @param global + */ +export const scope = (body: (Term | null)[], global = false): Scope => ({ + tag: "scope", + type: "void", + body: []>( + body + .filter((x) => x != null) + .map((x) => (x!.tag === "sym" ? decl(>x) : x)) + ), + global +}); + +/** + * Takes an array of global sym/var definitions (`input()`, `output()`, + * `uniform()`) and functions defined via `defn()`. Constructs the call + * graph of all transitively used functions and bundles everything in + * topological order within a global scope object, which is then + * returned to the user and can be passed to a target codegen for full + * program output. + * + * @see scope + * @see input + * @see output + * @see uniform + * + * @param body + */ +export const program = (body: (Sym | Func)[]) => { + const syms = body.filter((x) => x.tag !== "fn"); + const g = body.reduce( + (acc, x) => (x.tag === "fn" ? buildCallGraph(>x, acc) : acc), + new DGraph>() + ); + return scope(syms.concat(g.sort()), true); +}; + +const defArg = ([type, id, opts]: Arg): FuncArg => ({ + tag: "arg", + type, + id: id || gensym(), + opts: { q: "in", ...opts } +}); + +/** + * Defines a new function with up to 8 typed checked arguments. + * + * @param type return type + * @param name function name + * @param args arg types / names / opts + * @param body function body closure + * @param deps array of userland functions called from this function + */ +// prettier-ignore +export function defn(type: T, name: string, args: [], body: FnBody0): TaggedFn0; +// prettier-ignore +export function defn(type: T, name: string, args: Arg1, body: FnBody1): TaggedFn1; +// prettier-ignore +export function defn(type: T, name: string, args: Arg2, body: FnBody2): TaggedFn2; +// prettier-ignore +export function defn(type: T, name: string, args: Arg3, body: FnBody3): TaggedFn3; +// prettier-ignore +export function defn(type: T, name: string, args: Arg4, body: FnBody4): TaggedFn4; +// prettier-ignore +export function defn(type: T, name: string, args: Arg5, body: FnBody5): TaggedFn5; +// prettier-ignore +export function defn(type: T, name: string, args: Arg6, body: FnBody6): TaggedFn6; +// prettier-ignore +export function defn(type: T, name: string, args: Arg7, body: FnBody7): TaggedFn7; +// prettier-ignore +export function defn(type: T, name: string, args: Arg8, body: FnBody8): TaggedFn8; +// prettier-ignore +export function defn(type: Type, id: string, _args: Arg[], _body: (...xs: Sym[]) => ScopeBody): Func { + const args = _args.map(defArg); + const body = []>( + _body(...args.map((x) => sym(x.type, x.id, x.opts))).filter( + (x) => x != null + ) + ); + // count & check returns + const returns = walk( + (n, t) => { + if (t.tag === "ret") { + assert( + t.type === type, + `wrong return type for function '${id}', expected ${type}, got ${ + t.type + }` + ); + n++; + } + return n; + }, + scopedChildren, + 0, + body + ); + if (type !== "void" && !returns) { + throw new Error(`function '${id}' must return a value of type ${type}`); + } + // verify all non-builtin functions called are also + // provided as deps to ensure complete call graph later + const deps = walk( + (acc, t) => { + if (t.tag === "call" && (>t).fn) { + acc.push((>t).fn!); + } + return acc; + }, + allChildren, + []>[], + body + ); + const $: any = (...xs: any[]) => (funcall)($, ...xs); + return Object.assign($, >{ + tag: "fn", + type, + id, + args, + deps, + scope: scope(body) + }); +} + +/** + * Syntax sugar for defining `void main()` functions. + * + * @param body + */ +export const defMain = (body: FnBody0) => defn("void", "main", [], body); + +export function ret(): FuncReturn<"void">; +export function ret(val: Term): FuncReturn; +export function ret(val?: Term): FuncReturn { + return { + tag: "ret", + type: val ? val.type : "void", + val + }; +} + +// prettier-ignore +export function funcall(fn: string, type: T, ...args: Term[]): FnCall; +export function funcall(fn: TaggedFn0): FnCall; +// prettier-ignore +export function funcall(fn: TaggedFn1, a: Term): FnCall; +// prettier-ignore +export function funcall(fn: TaggedFn2, a: Term, b: Term): FnCall; +// prettier-ignore +export function funcall(fn: TaggedFn3, a: Term, b: Term, c: Term): FnCall; +// prettier-ignore +export function funcall(fn: TaggedFn4, a: Term, b: Term, c: Term, d: Term): FnCall; +// prettier-ignore +export function funcall(fn: TaggedFn5, a: Term, b: Term, c: Term, d: Term, e: Term): FnCall; +// prettier-ignore +export function funcall(fn: TaggedFn6, a: Term, b: Term, c: Term, d: Term, e: Term, f: Term): FnCall; +// prettier-ignore +export function funcall(fn: TaggedFn7, a: Term, b: Term, c: Term, d: Term, e: Term, f: Term, g: Term): FnCall; +// prettier-ignore +export function funcall(fn: TaggedFn8, a: Term, b: Term, c: Term, d: Term, e: Term, f: Term, g: Term, h: Term): FnCall; +// prettier-ignore +export function funcall(fn: string | Func, ...args: Term[]): FnCall { + return isString(fn) + ? { + tag: "call", + type: args[0], + id: fn, + args: args.slice(1) + } + : { + tag: "call", + type: fn.type, + id: fn.id, + args, + fn + }; +} + +export const builtinCall = ( + id: string, + type: T, + ...args: Term[] +): FnCall => ({ + tag: "call_i", + type, + id, + args +}); + +export const ifThen = ( + test: BoolTerm, + truthy: Term[], + falsey?: Term[] +): Branch => ({ + tag: "if", + type: "void", + test, + t: scope(truthy), + f: falsey ? scope(falsey) : undefined +}); + +export const ternary = ( + test: BoolTerm, + t: Term, + f: Term +): Ternary => ({ + tag: "ternary", + type: t.type, + test, + t, + f +}); + +// prettier-ignore +export function forLoop(test: Fn, BoolTerm>, body: FnBody1): ForLoop; +// prettier-ignore +export function forLoop(init: Sym | undefined, test: Fn, BoolTerm>, body: FnBody1): ForLoop; +// prettier-ignore +export function forLoop(init: Sym | undefined, test: Fn, BoolTerm>, iter: Fn, Term>, body: FnBody1): ForLoop; +export function forLoop(...xs: any[]): ForLoop { + const [init, test, iter, body] = + xs.length === 2 + ? [, xs[0], , xs[1]] + : xs.length === 3 + ? [xs[0], xs[1], , xs[2]] + : xs; + return { + tag: "for", + type: "void", + init: init ? decl(init) : undefined, + test: test(init!), + iter: iter ? iter(init!) : undefined, + scope: scope(body(init!)) + }; +} + +export const whileLoop = (test: BoolTerm, body: Term[]): WhileLoop => ({ + tag: "while", + type: "void", + test, + scope: scope(body) +}); + +const ctrl = (id: string): ControlFlow => ({ + tag: "ctrl", + type: "void", + id +}); + +export const brk = ctrl("break"); + +export const cont = ctrl("continue"); + +export const discard = ctrl("discard"); diff --git a/packages/shader-ast/src/builtins.ts b/packages/shader-ast/src/builtins.ts new file mode 100644 index 0000000000..2f36896dae --- /dev/null +++ b/packages/shader-ast/src/builtins.ts @@ -0,0 +1,482 @@ +import { illegalArgs } from "@thi.ng/errors"; +import { + BVec, + FloatTerm, + FnCall, + IntTerm, + ISampler2DTerm, + ISampler3DTerm, + ISamplerCubeTerm, + IVec, + IVec2Term, + IVec3Term, + Mat, + Prim, + Sampler, + Sampler2DTerm, + Sampler3DTerm, + SamplerCubeTerm, + Sym, + Term, + USampler2DTerm, + USampler3DTerm, + USamplerCubeTerm, + Vec, + Vec2Term, + Vec3Term, + Vec4Term +} from "./api"; +import { + builtinCall, + FLOAT0, + INT0, + isVec, + matchingPrimFor +} from "./ast"; + +const primOp1 = (name: string) => (a: Term) => + builtinCall(name, a.type, a); + +const primOp2 = (name: string) => ( + a: Term, + b: Term +) => builtinCall(name, a.type, a, b); + +const primOp3 = (name: string) => ( + a: Term, + b: Term, + c: Term +) => builtinCall(name, a.type, a, b, c); + +const $bvec = (t: string) => ("bvec" + t[t.length - 1]); + +/** + * Returns normalized version of given vector. + * + * @param v + */ +export const normalize = (v: Term) => + builtinCall("normalize", v.type, v); + +/** + * Returns length / magnitude of given vector. + * + * @param v + */ +export const length = (v: Term) => + builtinCall("length", "float", v); + +export const distance = (a: Term, b: Term) => + builtinCall("distance", "float", a, b); + +/** + * Returns dot product of given vectors. + * + * @param a + * @param b + */ +export const dot = (a: Term, b: Term) => + builtinCall("dot", "float", a, b); + +/** + * Returns cross product of given 3D vectors. + * + * @param a + * @param b + */ +export const cross = (a: Vec3Term, b: Vec3Term) => + builtinCall("cross", a.type, a, b); + +export const reflect = (i: Term, n: Term) => + builtinCall("reflect", i.type, i, n); + +export const refract = ( + i: Term, + n: Term, + ior: FloatTerm +) => builtinCall("refract", i.type, i, n, ior); + +export const faceForward = ( + i: Term, + n: Term, + nref: Term +) => builtinCall("faceForward", i.type, i, n, nref); + +export const min = primOp2("min"); +export const max = primOp2("max"); +export const clamp = primOp3("clamp"); + +export const step = primOp2("step"); +export const smoothstep = primOp3("smoothstep"); + +export const radians = primOp1("radians"); +export const degrees = primOp1("degrees"); + +export const cos = primOp1("cos"); +export const sin = primOp1("sin"); +export const tan = primOp1("tan"); +export const acos = primOp1("acos"); +export const asin = primOp1("asin"); +export const atan = primOp1("atan"); + +export const pow = primOp2("pow"); +export const exp = primOp1("exp"); +export const log = primOp1("log"); +export const exp2 = primOp1("exp2"); +export const log2 = primOp1("log2"); +export const sqrt = primOp1("sqrt"); +export const inversesqrt = primOp1("inversesqrt"); + +export const abs = primOp1("abs"); +export const sign = primOp1("sign"); +export const floor = primOp1("floor"); +export const ceil = primOp1("ceil"); +export const fract = primOp1("fract"); + +export const powf = (x: Term, y: FloatTerm) => + pow(x, matchingPrimFor(x, y)); + +// prettier-ignore +export function mod(a: Term, b: Term): FnCall; +export function mod(a: Term, b: FloatTerm): FnCall; +export function mod(a: Term, b: Term): FnCall { + const f = builtinCall("mod", a.type, a, b); + b.type === "float" && (f.info = "n"); + return f; +} + +// prettier-ignore +export function mix(a: Term, b: Term, c: Term): FnCall; +// prettier-ignore +export function mix(a: Term, b: Term, c: FloatTerm): FnCall; +export function mix(a: Term, b: Term, c: Term): FnCall { + const f = builtinCall("mix", a.type, a, b, c); + c.type === "float" && (f.info = "n"); + return f; +} + +// prettier-ignore +export const matrixCompMult = (a: Term, b: Term) => + builtinCall("matrixCompMult", a.type, a, b); + +// prettier-ignore +export function lessThan(a: Term, b: Term): FnCall<"bvec2">; +// prettier-ignore +export function lessThan(a: Term, b: Term): FnCall<"bvec3">; +// prettier-ignore +export function lessThan(a: Term, b: Term): FnCall<"bvec4">; +export function lessThan(a: Term, b: Term) { + return builtinCall("lessThan", $bvec(a.type), a, b); +} + +// prettier-ignore +export function lessThanEqual(a: Term, b: Term): FnCall<"bvec2">; +// prettier-ignore +export function lessThanEqual(a: Term, b: Term): FnCall<"bvec3">; +// prettier-ignore +export function lessThanEqual(a: Term, b: Term): FnCall<"bvec4">; +export function lessThanEqual(a: Term, b: Term) { + return builtinCall("lessThanEqual", $bvec(a.type), a, b); +} + +// prettier-ignore +export function greaterThan(a: Term, b: Term): FnCall<"bvec2">; +// prettier-ignore +export function greaterThan(a: Term, b: Term): FnCall<"bvec3">; +// prettier-ignore +export function greaterThan(a: Term, b: Term): FnCall<"bvec4">; +export function greaterThan(a: Term, b: Term) { + return builtinCall("greaterThan", $bvec(a.type), a, b); +} + +// prettier-ignore +export function greaterThanEqual(a: Term, b: Term): FnCall<"bvec2">; +// prettier-ignore +export function greaterThanEqual(a: Term, b: Term): FnCall<"bvec3">; +// prettier-ignore +export function greaterThanEqual(a: Term, b: Term): FnCall<"bvec4">; +export function greaterThanEqual(a: Term, b: Term) { + return builtinCall("greaterThanEqual", $bvec(a.type), a, b); +} + +// prettier-ignore +export function equal(a: Term, b: Term): FnCall<"bvec2">; +// prettier-ignore +export function equal(a: Term, b: Term): FnCall<"bvec3">; +// prettier-ignore +export function equal(a: Term, b: Term): FnCall<"bvec4">; +export function equal(a: Term, b: Term) { + return builtinCall("equal", $bvec(a.type), a, b); +} + +// prettier-ignore +export function notEqual(a: Term, b: Term): FnCall<"bvec2">; +// prettier-ignore +export function notEqual(a: Term, b: Term): FnCall<"bvec3">; +// prettier-ignore +export function notEqual(a: Term, b: Term): FnCall<"bvec4">; +export function notEqual(a: Term, b: Term) { + return builtinCall("notEqual", $bvec(a.type), a, b); +} + +export const _any = (v: Term): FnCall<"bool"> => + builtinCall("any", "bool", v); + +export const all = (v: Term): FnCall<"bool"> => + builtinCall("all", "bool", v); + +export const _not = (v: Term) => + builtinCall("all", v.type, v); + +const texRetType = (sampler: Term) => { + const t = sampler.type[0]; + const shadow = sampler.type.indexOf("Shadow") > 0; + return t === "s" + ? shadow + ? "float" + : "vec4" + : t === "i" + ? shadow + ? "int" + : "ivec4" + : t === "u" + ? shadow + ? "uint" + : "uvec4" + : illegalArgs(`unknown sampler type ${sampler.type}`); +}; + +// prettier-ignore +export function textureSize(sampler: Sampler2DTerm, lod: IntTerm): FnCall<"ivec2">; +// prettier-ignore +export function textureSize(sampler: Sampler3DTerm, lod: IntTerm): FnCall<"ivec3">; +// prettier-ignore +export function textureSize(sampler: SamplerCubeTerm, lod: IntTerm): FnCall<"ivec2">; +// prettier-ignore +export function textureSize(sampler: Term<"sampler2DShadow">, lod: IntTerm): FnCall<"ivec2">; +// prettier-ignore +export function textureSize(sampler: Term<"samplerCubeShadow">, lod: IntTerm): FnCall<"ivec2">; +// prettier-ignore +export function textureSize(sampler: Term, lod: IntTerm): FnCall { + return builtinCall( + "textureSize", + /(3D|Array)/.test(sampler.type) ? "ivec3" : "ivec2", + sampler, + lod + ); +} + +// prettier-ignore +export function texture(sampler: Sampler2DTerm, uv: Vec2Term, bias?: FloatTerm): FnCall<"vec4">; +// prettier-ignore +export function texture(sampler: Sampler3DTerm, uvw: Vec3Term, bias?: FloatTerm): FnCall<"vec4">; +// prettier-ignore +export function texture(sampler: SamplerCubeTerm, uvw: Vec3Term, bias?: FloatTerm): FnCall<"vec4">; +// prettier-ignore +export function texture(sampler: ISampler2DTerm, uv: Vec2Term, bias?: FloatTerm): FnCall<"ivec4">; +// prettier-ignore +export function texture(sampler: ISampler3DTerm, uvw: Vec3Term, bias?: FloatTerm): FnCall<"ivec4">; +// prettier-ignore +export function texture(sampler: ISamplerCubeTerm, uvw: Vec3Term, bias?: FloatTerm): FnCall<"ivec4">; +// prettier-ignore +export function texture(sampler: USampler2DTerm, uv: Vec2Term, bias?: FloatTerm): FnCall<"uvec4">; +// prettier-ignore +export function texture(sampler: USampler3DTerm, uvw: Vec3Term, bias?: FloatTerm): FnCall<"uvec4">; +// prettier-ignore +export function texture(sampler: USamplerCubeTerm, uvw: Vec3Term, bias?: FloatTerm): FnCall<"uvec4">; +// prettier-ignore +export function texture(sampler: Term<"sampler2DShadow">, uvw: Vec3Term, bias?: FloatTerm): FnCall<"float">; +// prettier-ignore +export function texture(sampler: Term<"samplerCubeShadow">, uvw: Vec4Term, bias?: FloatTerm): FnCall<"float">; +// prettier-ignore +export function texture(sampler: Term, uv: Term, bias?: FloatTerm): FnCall { + const f = builtinCall( + "texture", + texRetType(sampler), + sampler, + uv, + bias || FLOAT0 + ); + !isVec(f) && (f.info = "n"); + return f; +} + +// prettier-ignore +export function textureProj(sampler: Sampler2DTerm, uvw: Term<"vec3" | "vec4">, bias?: FloatTerm): FnCall<"vec4">; +// prettier-ignore +export function textureProj(sampler: Sampler3DTerm, uvw: Vec4Term, bias?: FloatTerm): FnCall<"vec4">; +// prettier-ignore +export function textureProj(sampler: ISampler2DTerm, uvw: Term<"vec3" | "vec4">, bias?: FloatTerm): FnCall<"ivec4">; +// prettier-ignore +export function textureProj(sampler: ISampler3DTerm, uvw: Vec4Term, bias?: FloatTerm): FnCall<"ivec4">; +// prettier-ignore +export function textureProj(sampler: USampler2DTerm, uvw: Term<"vec3" | "vec4">, bias?: FloatTerm): FnCall<"uvec4">; +// prettier-ignore +export function textureProj(sampler: USampler3DTerm, uvw: Vec4Term, bias?: FloatTerm): FnCall<"uvec4">; +// prettier-ignore +export function textureProj(sampler: Term<"sampler2DShadow">, uvw: Vec4Term, bias?: FloatTerm): FnCall<"float">; +// prettier-ignore +export function textureProj(sampler: Term, uv: Term, bias?: FloatTerm): FnCall { + const f = builtinCall( + "textureProj", + texRetType(sampler), + sampler, + uv, + bias || FLOAT0 + ); + !isVec(f) && (f.info = "n"); + return f; +} + +// prettier-ignore +export function textureLod(sampler: Sampler2DTerm, uv: Vec2Term, bias?: FloatTerm): FnCall<"vec4">; +// prettier-ignore +export function textureLod(sampler: Sampler3DTerm, uvw: Vec3Term, bias?: FloatTerm): FnCall<"vec4">; +// prettier-ignore +export function textureLod(sampler: SamplerCubeTerm, uvw: Vec3Term, bias?: FloatTerm): FnCall<"vec4">; +// prettier-ignore +export function textureLod(sampler: ISampler2DTerm, uv: Vec2Term, bias?: FloatTerm): FnCall<"ivec4">; +// prettier-ignore +export function textureLod(sampler: ISampler3DTerm, uvw: Vec3Term, bias?: FloatTerm): FnCall<"ivec4">; +// prettier-ignore +export function textureLod(sampler: ISamplerCubeTerm, uvw: Vec3Term, bias?: FloatTerm): FnCall<"ivec4">; +// prettier-ignore +export function textureLod(sampler: USampler2DTerm, uv: Vec2Term, bias?: FloatTerm): FnCall<"uvec4">; +// prettier-ignore +export function textureLod(sampler: USampler3DTerm, uvw: Vec3Term, bias?: FloatTerm): FnCall<"uvec4">; +// prettier-ignore +export function textureLod(sampler: USamplerCubeTerm, uvw: Vec3Term, bias?: FloatTerm): FnCall<"uvec4">; +// prettier-ignore +export function textureLod(sampler: Term<"sampler2DShadow">, uvw: Vec3Term, bias?: FloatTerm): FnCall<"float">; +// prettier-ignore +export function textureLod(sampler: Term, uv: Term, bias?: FloatTerm): FnCall { + const f = builtinCall( + "textureLod", + texRetType(sampler), + sampler, + uv, + bias || FLOAT0 + ); + !isVec(f) && (f.info = "n"); + return f; +} + +// prettier-ignore +export function textureOffset(sampler: Sampler2DTerm, uvw: Vec2Term, off: IVec2Term, bias?: FloatTerm): FnCall<"vec4">; +// prettier-ignore +export function textureOffset(sampler: Sampler3DTerm, uvw: Vec3Term, off: IVec3Term, bias?: FloatTerm): FnCall<"vec4">; +// prettier-ignore +export function textureOffset(sampler: ISampler2DTerm, uvw: Vec2Term, off: IVec2Term, bias?: FloatTerm): FnCall<"ivec4">; +// prettier-ignore +export function textureOffset(sampler: ISampler3DTerm, uvw: Vec3Term, off: IVec3Term, bias?: FloatTerm): FnCall<"ivec4">; +// prettier-ignore +export function textureOffset(sampler: USampler2DTerm, uvw: Vec2Term, off: IVec2Term, bias?: FloatTerm): FnCall<"uvec4">; +// prettier-ignore +export function textureOffset(sampler: USampler3DTerm, uvw: Vec3Term, off: IVec3Term, bias?: FloatTerm): FnCall<"uvec4">; +// prettier-ignore +export function textureOffset(sampler: Term<"sampler2DShadow">, uvw: Vec3Term, off: IVec2Term, bias?: FloatTerm): FnCall<"float">; +// prettier-ignore +export function textureOffset(sampler: Term, uv: Term, off: Term, bias?: FloatTerm): FnCall { + const f = builtinCall( + "textureOffset", + texRetType(sampler), + sampler, + uv, + off, + bias || FLOAT0 + ); + !isVec(f) && (f.info = "n"); + return f; +} + +// prettier-ignore +export function texelFetch(sampler: Sampler2DTerm, uv: IVec2Term, lod?: IntTerm): FnCall<"vec4">; +// prettier-ignore +export function texelFetch(sampler: Sampler3DTerm, uvw: IVec3Term, lod?: IntTerm): FnCall<"vec4">; +// prettier-ignore +export function texelFetch(sampler: ISampler2DTerm, uv: IVec2Term, lod?: IntTerm): FnCall<"ivec4">; +// prettier-ignore +export function texelFetch(sampler: ISampler3DTerm, uvw: IVec3Term, lod?: IntTerm): FnCall<"ivec4">; +// prettier-ignore +export function texelFetch(sampler: USampler2DTerm, uv: IVec2Term, lod?: IntTerm): FnCall<"uvec4">; +// prettier-ignore +export function texelFetch(sampler: USampler3DTerm, uvw: IVec3Term, lod?: IntTerm): FnCall<"uvec4">; +// prettier-ignore +export function texelFetch(sampler: Term, uv: Term, lod?: IntTerm): FnCall { + return builtinCall( + "texelFetch", + texRetType(sampler), + sampler, + uv, + lod || INT0 + ); +} + +// prettier-ignore +export function texelFetchOffset(sampler: Sampler2DTerm, uv: IVec2Term, lod: IntTerm, offset: IVec2Term): FnCall<"vec4">; +// prettier-ignore +export function texelFetchOffset(sampler: Sampler3DTerm, uvw: IVec3Term, lod: IntTerm, offset: IVec3Term): FnCall<"vec4">; +// prettier-ignore +export function texelFetchOffset(sampler: ISampler2DTerm, uv: IVec2Term, lod: IntTerm, offset: IVec2Term): FnCall<"ivec4">; +// prettier-ignore +export function texelFetchOffset(sampler: ISampler3DTerm, uvw: IVec3Term, lod: IntTerm, offset: IVec3Term): FnCall<"ivec4">; +// prettier-ignore +export function texelFetchOffset(sampler: USampler2DTerm, uv: IVec2Term, lod: IntTerm, offset: IVec2Term): FnCall<"uvec4">; +// prettier-ignore +export function texelFetchOffset(sampler: USampler3DTerm, uvw: IVec3Term, lod: IntTerm, offset: IVec3Term): FnCall<"uvec4">; +// prettier-ignore +export function texelFetchOffset(sampler: Term, uv: Term, lod: IntTerm, offset: Term): FnCall { + return builtinCall( + "texelFetchOffset", + texRetType(sampler), + sampler, + uv, + lod, + offset + ); +} + +// prettier-ignore +export function textureGrad(sampler: Sampler2DTerm, uv: Vec2Term, dx: Vec2Term, dy: Vec2Term): FnCall<"vec4">; +// prettier-ignore +export function textureGrad(sampler: Sampler3DTerm, uvw: Vec3Term, dx: Vec3Term, dy: Vec3Term): FnCall<"vec4">; +// prettier-ignore +export function textureGrad(sampler: SamplerCubeTerm, uvw: Vec3Term, dx: Vec3Term, dy: Vec3Term): FnCall<"vec4">; +// prettier-ignore +export function textureGrad(sampler: ISampler2DTerm, uv: Vec2Term, dx: Vec2Term, dy: Vec2Term): FnCall<"ivec4">; +// prettier-ignore +export function textureGrad(sampler: ISampler3DTerm, uvw: Vec3Term, dx: Vec3Term, dy: Vec3Term): FnCall<"ivec4">; +// prettier-ignore +export function textureGrad(sampler: ISamplerCubeTerm, uvw: Vec3Term, dx: Vec3Term, dy: Vec3Term): FnCall<"ivec4">; +// prettier-ignore +export function textureGrad(sampler: USampler2DTerm, uv: Vec2Term, dx: Vec2Term, dy: Vec2Term): FnCall<"uvec4">; +// prettier-ignore +export function textureGrad(sampler: USampler3DTerm, uvw: Vec3Term, dx: Vec3Term, dy: Vec3Term): FnCall<"uvec4">; +// prettier-ignore +export function textureGrad(sampler: USamplerCubeTerm, uvw: Vec3Term, dx: Vec3Term, dy: Vec3Term): FnCall<"uvec4">; +// prettier-ignore +export function textureGrad(sampler: Term<"sampler2DShadow">, uvw: Vec3Term, dx: Vec3Term, dy: Vec3Term): FnCall<"float">; +// prettier-ignore +export function textureGrad(sampler: Term<"samplerCubeShadow">, uvw: Vec3Term, dx: Vec3Term, dy: Vec3Term): FnCall<"float">; +// prettier-ignore +export function textureGrad(sampler: Term, uvw: Term, dx: Term, dy: Term): FnCall { + const f = builtinCall( + "textureGrad", + texRetType(sampler), + sampler, + uvw, + dx, + dy + ); + !isVec(f) && (f.info = "n"); + return f; +} + +export const dFdx = (sym: Sym) => + builtinCall("dFdx", sym.type, sym); + +export const dFdy = (sym: Sym) => + builtinCall("dFdy", sym.type, sym); + +export const fwidth = (sym: Sym) => + builtinCall("fwidth", sym.type, sym); diff --git a/packages/shader-ast/src/index.ts b/packages/shader-ast/src/index.ts new file mode 100644 index 0000000000..fd3cf2858b --- /dev/null +++ b/packages/shader-ast/src/index.ts @@ -0,0 +1,5 @@ +export * from "./api"; +export * from "./ast"; +export * from "./builtins"; +export * from "./optimize"; +export * from "./target"; diff --git a/packages/shader-ast/src/optimize.ts b/packages/shader-ast/src/optimize.ts new file mode 100644 index 0000000000..0205a08b75 --- /dev/null +++ b/packages/shader-ast/src/optimize.ts @@ -0,0 +1,96 @@ +import { + Lit, + Op1, + Op2, + Term +} from "./api"; +import { + allChildren, + isLitNumeric, + lit, + walk +} from "./ast"; + +const replaceNode = (node: any, next: any) => { + for (let k in node) { + !next.hasOwnProperty(k) && delete node[k]; + } + return Object.assign(node, next); +}; + +/** + * Traverses given AST and applies constant folding optimizations where + * possible. Returns possibly updated tree (mutates original). + * Currently, only scalar operations are supported / considered. + * + * ``` + * const foo = defn("float", "foo", [["float"]], (x) => [ + * ret(mul(x, add(neg(float(10)), float(42))))] + * ) + * + * const prog = scope([foo, foo(add(float(1), float(2)))], true); + * + * // serialized (GLSL) + * glsl(prog); + * + * // float foo(in float _sym0) { + * // return (_sym0 * (-10.0 + 42.0)); + * // }; + * // foo((1.0 + 2.0)); + * + * // with constant folding + * glsl(constantFolding(prog)) + * + * // float foo(in float _sym0) { + * // return (_sym0 * 32.0); + * // }; + * // foo(3.0); + * ``` + * + * @param tree + */ +export const constantFolding = (tree: Term) => { + walk( + (_, node) => { + switch (node.tag) { + case "op1": { + const n = >node; + if (n.op == "-" && isLitNumeric(n.val)) { + replaceNode(node, >n.val); + (n).val = -(n).val; + } + break; + } + case "op2": { + const n = >node; + if (isLitNumeric(n.l) && isLitNumeric(n.r)) { + const vl = (>n.l).val; + const vr = (>n.r).val; + let res = + n.op === "+" + ? vl + vr + : n.op === "-" + ? vl - vr + : n.op === "*" + ? vl * vr + : n.op === "/" + ? vl / vr + : undefined; + if (res !== undefined) { + n.type === "int" && (res |= 0); + n.type === "uint" && (res >>>= 0); + replaceNode(node, lit(n.type, res)); + } + } + break; + } + default: + } + }, + allChildren, + null, + tree, + false + ); + return tree; +}; diff --git a/packages/shader-ast/src/target.ts b/packages/shader-ast/src/target.ts new file mode 100644 index 0000000000..018f629ae1 --- /dev/null +++ b/packages/shader-ast/src/target.ts @@ -0,0 +1,22 @@ +import { Fn } from "@thi.ng/api"; +import { DEFAULT, defmulti } from "@thi.ng/defmulti"; +import { unsupported } from "@thi.ng/errors"; +import { TargetImpl, Term } from "./api"; + +/** + * Takes an object of code generator functions and returns a new code + * generator / compile target function which serializes a given AST + * using the provided node type implementations. + * + * @param impls + * + * @see targetGLSL + */ +export const defTarget = (impls: TargetImpl): Fn, T> => { + const emit = defmulti, T>((x) => x.tag); + emit.add(DEFAULT, (t) => + unsupported(`no impl for AST node type: '${t.tag}'`) + ); + emit.addAll(impls); + return emit; +}; diff --git a/packages/shader-ast/test/index.ts b/packages/shader-ast/test/index.ts new file mode 100644 index 0000000000..2ca6ec1a27 --- /dev/null +++ b/packages/shader-ast/test/index.ts @@ -0,0 +1,57 @@ +import * as assert from "assert"; +import { mul, vec2 } from "../src"; + +describe("shader-ast", () => { + it("op2 type infer mulvv", () => { + assert.deepEqual(mul(vec2(), vec2()), { + tag: "op2", + type: "vec2", + info: undefined, + op: "*", + l: { + tag: "lit", + type: "vec2", + info: "n", + val: [{ tag: "lit", type: "float", info: undefined, val: 0 }] + }, + r: { + tag: "lit", + type: "vec2", + info: "n", + val: [{ tag: "lit", type: "float", info: undefined, val: 0 }] + } + }); + }); + + it("op2 type infer mulnv", () => { + assert.deepEqual(mul(1, vec2()), { + tag: "op2", + type: "vec2", + info: "nv", + op: "*", + l: { tag: "lit", type: "float", info: undefined, val: 1 }, + r: { + tag: "lit", + type: "vec2", + info: "n", + val: [{ tag: "lit", type: "float", info: undefined, val: 0 }] + } + }); + }); + + it("op2 type infer mulvn", () => { + assert.deepEqual(mul(vec2(), 1), { + tag: "op2", + type: "vec2", + info: "vn", + op: "*", + l: { + tag: "lit", + type: "vec2", + info: "n", + val: [{ tag: "lit", type: "float", info: undefined, val: 0 }] + }, + r: { tag: "lit", type: "float", info: undefined, val: 1 } + }); + }); +}); diff --git a/packages/shader-ast/test/tsconfig.json b/packages/shader-ast/test/tsconfig.json new file mode 100644 index 0000000000..f6e63560dd --- /dev/null +++ b/packages/shader-ast/test/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../../tsconfig.json", + "compilerOptions": { + "outDir": "../build", + "module": "commonjs" + }, + "include": [ + "./**/*.ts", + "../src/**/*.ts" + ] +} diff --git a/packages/shader-ast/tsconfig.json b/packages/shader-ast/tsconfig.json new file mode 100644 index 0000000000..893b9979c5 --- /dev/null +++ b/packages/shader-ast/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": ".", + "module": "es6", + "target": "es6" + }, + "include": [ + "./src/**/*.ts" + ] +} diff --git a/packages/sparse/CHANGELOG.md b/packages/sparse/CHANGELOG.md index 5b5040150a..6b69e281df 100644 --- a/packages/sparse/CHANGELOG.md +++ b/packages/sparse/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.1.16](https://github.com/thi-ng/umbrella/compare/@thi.ng/sparse@0.1.15...@thi.ng/sparse@0.1.16) (2019-07-07) + +**Note:** Version bump only for package @thi.ng/sparse + + + + + ## [0.1.15](https://github.com/thi-ng/umbrella/compare/@thi.ng/sparse@0.1.14...@thi.ng/sparse@0.1.15) (2019-05-22) **Note:** Version bump only for package @thi.ng/sparse diff --git a/packages/sparse/package.json b/packages/sparse/package.json index 4739312009..a96c2013ab 100644 --- a/packages/sparse/package.json +++ b/packages/sparse/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/sparse", - "version": "0.1.15", + "version": "0.1.16", "description": "Sparse vector & matrix implementations", "module": "./index.js", "main": "./lib/index.js", @@ -25,15 +25,15 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/api": "^6.2.0", - "@thi.ng/transducers": "^5.3.7" + "@thi.ng/api": "^6.3.0", + "@thi.ng/transducers": "^5.4.0" }, "keywords": [ "adjacency", diff --git a/packages/strings/CHANGELOG.md b/packages/strings/CHANGELOG.md index 6e72303b1c..4b84f000b9 100644 --- a/packages/strings/CHANGELOG.md +++ b/packages/strings/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.2.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/strings@1.1.3...@thi.ng/strings@1.2.0) (2019-07-07) + + +### Features + +* **strings:** enable TS strict compiler flags (refactor) ([76cecb8](https://github.com/thi-ng/umbrella/commit/76cecb8)) + + + + + ## [1.1.3](https://github.com/thi-ng/umbrella/compare/@thi.ng/strings@1.1.2...@thi.ng/strings@1.1.3) (2019-05-22) **Note:** Version bump only for package @thi.ng/strings diff --git a/packages/strings/package.json b/packages/strings/package.json index 5d8f2b959a..e38aa7b2be 100644 --- a/packages/strings/package.json +++ b/packages/strings/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/strings", - "version": "1.1.3", + "version": "1.2.0", "description": "Various string formatting & utility functions", "module": "./index.js", "main": "./lib/index.js", @@ -25,15 +25,15 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/errors": "^1.0.6", - "@thi.ng/memoize": "^1.0.9" + "@thi.ng/errors": "^1.1.0", + "@thi.ng/memoize": "^1.1.0" }, "keywords": [ "composition", diff --git a/packages/strings/src/center.ts b/packages/strings/src/center.ts index 6db9fd799c..215ea2b879 100644 --- a/packages/strings/src/center.ts +++ b/packages/strings/src/center.ts @@ -1,5 +1,4 @@ import { memoizeJ } from "@thi.ng/memoize"; - import { Stringer } from "./api"; import { repeat } from "./repeat"; import { truncate } from "./truncate"; @@ -25,8 +24,12 @@ import { truncate } from "./truncate"; export const center: ( lineWidth: number, pad?: string | number -) => Stringer = memoizeJ>((n, pad = " ") => { - const buf = repeat(pad, n); +) => Stringer = memoizeJ< + number, + string | number | undefined, + Stringer +>((n, pad = " ") => { + const buf = repeat(String(pad), n); return (x: any) => { if (x == null) return buf; x = x.toString(); diff --git a/packages/strings/src/pad-left.ts b/packages/strings/src/pad-left.ts index 4cf2863457..f3073f7daa 100644 --- a/packages/strings/src/pad-left.ts +++ b/packages/strings/src/pad-left.ts @@ -1,5 +1,4 @@ import { memoizeJ } from "@thi.ng/memoize"; - import { Stringer } from "./api"; import { repeat } from "./repeat"; @@ -10,8 +9,12 @@ import { repeat } from "./repeat"; export const padLeft: ( n: number, ch?: string | number -) => Stringer = memoizeJ>((n, ch = " ") => { - const buf = repeat(ch, n); +) => Stringer = memoizeJ< + number, + string | number | undefined, + Stringer +>((n, ch = " ") => { + const buf = repeat(String(ch), n); return (x: any) => x != null ? ((x = x.toString()), x.length < n ? buf.substr(x.length) + x : x) diff --git a/packages/strings/src/pad-right.ts b/packages/strings/src/pad-right.ts index 3659326578..d770e65dd5 100644 --- a/packages/strings/src/pad-right.ts +++ b/packages/strings/src/pad-right.ts @@ -1,5 +1,4 @@ import { memoizeJ } from "@thi.ng/memoize"; - import { Stringer } from "./api"; import { repeat } from "./repeat"; @@ -10,8 +9,12 @@ import { repeat } from "./repeat"; export const padRight: ( n: number, ch?: string | number -) => Stringer = memoizeJ>((n, ch = " ") => { - const buf = repeat(ch, n); +) => Stringer = memoizeJ< + number, + string | number | undefined, + Stringer +>((n, ch = " ") => { + const buf = repeat(String(ch), n); return (x: any) => x != null ? ((x = x.toString()), x.length < n ? x + buf.substr(x.length) : x) diff --git a/packages/strings/src/radix.ts b/packages/strings/src/radix.ts index 51ea24c775..c7e7808a5f 100644 --- a/packages/strings/src/radix.ts +++ b/packages/strings/src/radix.ts @@ -14,13 +14,15 @@ export const radix: ( radix: number, len: number, prefix?: string -) => Stringer = memoizeJ((radix: number, n: number, prefix = "") => { - const buf = repeat("0", n); - return (x: any) => { - x = (x >>> 0).toString(radix); - return prefix + (x.length < n ? buf.substr(x.length) + x : x); - }; -}); +) => Stringer = memoizeJ( + (radix: number, n: number, prefix: string = "") => { + const buf = repeat("0", n); + return (x: any) => { + x = (x >>> 0).toString(radix); + return prefix + (x.length < n ? buf.substr(x.length) + x : x); + }; + } +); /** * 8bit binary conversion preset. diff --git a/packages/strings/src/units.ts b/packages/strings/src/units.ts index 6ac69959b8..01bcdd0b4c 100644 --- a/packages/strings/src/units.ts +++ b/packages/strings/src/units.ts @@ -1,13 +1,27 @@ import { memoizeJ } from "@thi.ng/memoize"; import { Stringer } from "./api"; +type UnitDefs = [number, string, number?][]; + export const units: ( - exp: [number, string, number?][], + exp: UnitDefs, base: string, prec?: number -) => Stringer = memoizeJ((exp, base: string, prec = 2) => { +) => Stringer = memoizeJ< + UnitDefs, + string, + number | undefined, + Stringer +>((exp: UnitDefs, base: string, prec: number = 2) => { const groups = exp - .map((x) => [x[0], x[2] != null ? x[2] : prec, x[1]]) + .map( + (x) => + <[number, number, string]>[ + x[0], + x[2] != null ? x[2] : prec, + x[1] + ] + ) .sort((a, b) => a[0] - b[0]); return (x: number) => { if (x === 0) { @@ -20,6 +34,7 @@ export const units: ( return (x / g[0]).toFixed(g[1]) + g[2]; } } + return ""; }; }); diff --git a/packages/transducers-binary/CHANGELOG.md b/packages/transducers-binary/CHANGELOG.md index c6d819675e..649ba29070 100644 --- a/packages/transducers-binary/CHANGELOG.md +++ b/packages/transducers-binary/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.4.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/transducers-binary@0.3.12...@thi.ng/transducers-binary@0.4.0) (2019-07-07) + + +### Features + +* **transducers-binary:** enable TS strict compiler flags (refactor) ([8d86ac6](https://github.com/thi-ng/umbrella/commit/8d86ac6)) + + + + + ## [0.3.12](https://github.com/thi-ng/umbrella/compare/@thi.ng/transducers-binary@0.3.11...@thi.ng/transducers-binary@0.3.12) (2019-05-22) **Note:** Version bump only for package @thi.ng/transducers-binary diff --git a/packages/transducers-binary/package.json b/packages/transducers-binary/package.json index bb73c348a3..35a89ef68e 100644 --- a/packages/transducers-binary/package.json +++ b/packages/transducers-binary/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/transducers-binary", - "version": "0.3.12", + "version": "0.4.0", "description": "Binary data related transducers & reducers", "module": "./index.js", "main": "./lib/index.js", @@ -25,17 +25,17 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/compose": "^1.2.5", - "@thi.ng/random": "^1.1.7", - "@thi.ng/strings": "^1.1.3", - "@thi.ng/transducers": "^5.3.7" + "@thi.ng/compose": "^1.3.0", + "@thi.ng/random": "^1.1.8", + "@thi.ng/strings": "^1.2.0", + "@thi.ng/transducers": "^5.4.0" }, "keywords": [ "base64", diff --git a/packages/transducers-binary/src/base64.ts b/packages/transducers-binary/src/base64.ts index 20535a5903..85563277bf 100644 --- a/packages/transducers-binary/src/base64.ts +++ b/packages/transducers-binary/src/base64.ts @@ -83,7 +83,7 @@ export function base64Encode(...args: any[]): any { const opts = { safe: false, buffer: 1024, ...args[0] }; const chars = opts.safe ? B64_SAFE : B64_CHARS; const buf: string[] = []; - return [ + return >[ init, (acc) => { switch (state) { @@ -106,7 +106,7 @@ export function base64Encode(...args: any[]): any { default: } while (buf.length && !isReduced(acc)) { - acc = reduce(acc, buf.shift()); + acc = reduce(acc, buf.shift()!); } return complete(acc); }, diff --git a/packages/transducers-binary/src/utf8.ts b/packages/transducers-binary/src/utf8.ts index 185caabda9..87f7638272 100644 --- a/packages/transducers-binary/src/utf8.ts +++ b/packages/transducers-binary/src/utf8.ts @@ -18,12 +18,12 @@ export function utf8Decode(src?: Iterable): any { ? [...iterator1(utf8Decode(), src)].join("") : (rfn: Reducer) => { const r = rfn[2]; - let state = 0, - u0, - u1, - u2, - u3, - u4; + let state = 0; + let u0: number; + let u1: number; + let u2: number; + let u3: number; + let u4: number; return compR(rfn, (acc, x: number) => { switch (state) { case 0: @@ -187,7 +187,7 @@ export function utf8Encode(src?: string): any { }; } -const codePoint = (x) => +const codePoint = (x: number) => x < 0x10000 ? String.fromCharCode(x) : ((x -= 0x10000), diff --git a/packages/transducers-fsm/CHANGELOG.md b/packages/transducers-fsm/CHANGELOG.md index 75f4c8bc1c..6238925864 100644 --- a/packages/transducers-fsm/CHANGELOG.md +++ b/packages/transducers-fsm/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.1.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/transducers-fsm@1.0.19...@thi.ng/transducers-fsm@1.1.0) (2019-07-07) + + +### Features + +* **transducers-fsm:** enable TS strict compiler flags (refactor) ([734103d](https://github.com/thi-ng/umbrella/commit/734103d)) + + + + + ## [1.0.19](https://github.com/thi-ng/umbrella/compare/@thi.ng/transducers-fsm@1.0.18...@thi.ng/transducers-fsm@1.0.19) (2019-05-22) **Note:** Version bump only for package @thi.ng/transducers-fsm diff --git a/packages/transducers-fsm/package.json b/packages/transducers-fsm/package.json index 4cceba8ae2..ba1d2d710c 100644 --- a/packages/transducers-fsm/package.json +++ b/packages/transducers-fsm/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/transducers-fsm", - "version": "1.0.19", + "version": "1.1.0", "description": "Transducer-based Finite State Machine transformer", "module": "./index.js", "main": "./lib/index.js", @@ -25,15 +25,15 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/api": "^6.2.0", - "@thi.ng/transducers": "^5.3.7" + "@thi.ng/api": "^6.3.0", + "@thi.ng/transducers": "^5.4.0" }, "keywords": [ "ES6", diff --git a/packages/transducers-fsm/src/index.ts b/packages/transducers-fsm/src/index.ts index f7247b1893..94ec93c8b6 100644 --- a/packages/transducers-fsm/src/index.ts +++ b/packages/transducers-fsm/src/index.ts @@ -1,6 +1,5 @@ import { Fn0, IObjectOf } from "@thi.ng/api"; import { - comp, compR, ensureReduced, isReduced, @@ -103,24 +102,23 @@ export interface FSMOpts { */ export const fsm = ( opts: FSMOpts -): Transducer => - comp((rfn: Reducer) => { - const states = opts.states; - const state = opts.init(); - const r = rfn[2]; - return compR(rfn, (acc, x) => { - const res = states[state.state](state, x); - if (res != null) { - for (let i = 0, n = (res).length; i < n; i++) { - acc = r(acc, res[i]); - if (isReduced(acc)) { - break; - } +): Transducer => (rfn: Reducer) => { + const states = opts.states; + const state = opts.init(); + const r = rfn[2]; + return compR(rfn, (acc, x) => { + const res: any = states[state.state](state, x); + if (res != null) { + for (let i = 0, n = (res).length; i < n; i++) { + acc = r(acc, res[i]); + if (isReduced(acc)) { + break; } } - if (state.state === opts.terminate) { - return ensureReduced(acc); - } - return acc; - }); + } + if (state.state === opts.terminate) { + return ensureReduced(acc); + } + return acc; }); +}; diff --git a/packages/transducers-fsm/test/index.ts b/packages/transducers-fsm/test/index.ts index 83054b548a..eef860a970 100644 --- a/packages/transducers-fsm/test/index.ts +++ b/packages/transducers-fsm/test/index.ts @@ -1,10 +1,10 @@ -import * as assert from "assert"; import * as tx from "@thi.ng/transducers"; +import * as assert from "assert"; import { fsm } from "../src/index"; describe("transducers-fsm", () => { it("readme example", () => { - const testFSM = fsm({ + const testFSM = fsm({ states: { skip: (state, x) => { if (x < 20) { @@ -29,7 +29,7 @@ describe("transducers-fsm", () => { state.state = "done"; } }, - done: () => { }, + done: () => {} }, terminate: "done", init: () => ({ state: "skip", count: 0 }) @@ -43,7 +43,12 @@ describe("transducers-fsm", () => { [10, 12, 14, 16, 18] ); assert.deepEqual( - [...tx.iterator(tx.comp(testFSM, tx.map((x: number) => x * 10)), tx.range(100))], + [ + ...tx.iterator( + tx.comp(testFSM, tx.map((x: number) => x * 10)), + tx.range(100) + ) + ], [50, 60, 70, 80, 90, 150, 160, 170, 180, 190] ); }); diff --git a/packages/transducers-hdom/CHANGELOG.md b/packages/transducers-hdom/CHANGELOG.md index 31b95f1902..3206a27bb5 100644 --- a/packages/transducers-hdom/CHANGELOG.md +++ b/packages/transducers-hdom/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [2.0.24](https://github.com/thi-ng/umbrella/compare/@thi.ng/transducers-hdom@2.0.23...@thi.ng/transducers-hdom@2.0.24) (2019-07-07) + +**Note:** Version bump only for package @thi.ng/transducers-hdom + + + + + ## [2.0.23](https://github.com/thi-ng/umbrella/compare/@thi.ng/transducers-hdom@2.0.22...@thi.ng/transducers-hdom@2.0.23) (2019-05-22) **Note:** Version bump only for package @thi.ng/transducers-hdom diff --git a/packages/transducers-hdom/package.json b/packages/transducers-hdom/package.json index 967e6bfc4b..9faf52e627 100644 --- a/packages/transducers-hdom/package.json +++ b/packages/transducers-hdom/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/transducers-hdom", - "version": "2.0.23", + "version": "2.0.24", "description": "Transducer based UI updater for @thi.ng/hdom", "module": "./index.js", "main": "./lib/index.js", @@ -25,16 +25,16 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/hdom": "^7.2.8", - "@thi.ng/hiccup": "^3.1.9", - "@thi.ng/transducers": "^5.3.7" + "@thi.ng/hdom": "^8.0.0", + "@thi.ng/hiccup": "^3.2.0", + "@thi.ng/transducers": "^5.4.0" }, "keywords": [ "diff", diff --git a/packages/transducers-stats/CHANGELOG.md b/packages/transducers-stats/CHANGELOG.md index afc7bd488f..d14b8bec25 100644 --- a/packages/transducers-stats/CHANGELOG.md +++ b/packages/transducers-stats/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.1.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/transducers-stats@1.0.19...@thi.ng/transducers-stats@1.1.0) (2019-07-07) + + +### Features + +* **transducers-stats:** enable TS strict compiler flags (refactor) ([33daa7f](https://github.com/thi-ng/umbrella/commit/33daa7f)) + + + + + ## [1.0.19](https://github.com/thi-ng/umbrella/compare/@thi.ng/transducers-stats@1.0.18...@thi.ng/transducers-stats@1.0.19) (2019-05-22) **Note:** Version bump only for package @thi.ng/transducers-stats diff --git a/packages/transducers-stats/package.json b/packages/transducers-stats/package.json index b46512507f..5412aadb1c 100644 --- a/packages/transducers-stats/package.json +++ b/packages/transducers-stats/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/transducers-stats", - "version": "1.0.19", + "version": "1.1.0", "description": "Transducers for statistical / technical analysis", "module": "./index.js", "main": "./lib/index.js", @@ -25,17 +25,17 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/checks": "^2.1.6", - "@thi.ng/dcons": "^2.0.19", - "@thi.ng/errors": "^1.0.6", - "@thi.ng/transducers": "^5.3.7" + "@thi.ng/checks": "^2.2.0", + "@thi.ng/dcons": "^2.1.0", + "@thi.ng/errors": "^1.1.0", + "@thi.ng/transducers": "^5.4.0" }, "keywords": [ "ES6", diff --git a/packages/transducers-stats/src/donchian.ts b/packages/transducers-stats/src/donchian.ts index 91e12b916c..3c20d25e41 100644 --- a/packages/transducers-stats/src/donchian.ts +++ b/packages/transducers-stats/src/donchian.ts @@ -26,5 +26,5 @@ export function donchian( export function donchian(period: number, src?: Iterable): any { return src ? iterator(donchian(period), src) - : comp(partition(period, 1), map(bounds)); + : comp(partition(period, 1), map(bounds)); } diff --git a/packages/transducers-stats/src/ema.ts b/packages/transducers-stats/src/ema.ts index 3c19f7834b..d7026b51cf 100644 --- a/packages/transducers-stats/src/ema.ts +++ b/packages/transducers-stats/src/ema.ts @@ -1,5 +1,10 @@ import { illegalArgs } from "@thi.ng/errors"; -import { compR, iterator1, Reducer, Transducer } from "@thi.ng/transducers"; +import { + compR, + iterator1, + Reducer, + Transducer +} from "@thi.ng/transducers"; /** * https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average @@ -23,17 +28,17 @@ export function ema(period: number, src?: Iterable): any { const k = 2 / (period + 1); return (rfn: Reducer) => { const reduce = rfn[2]; - let window = []; + let window: number[] | null = []; + let ema: number | null; let sum = 0; - let ema: number; return compR(rfn, (acc, x: number) => { if (ema != null) { ema += (x - ema) * k; return rfn[2](acc, ema); } else { - window.push(x); + window!.push(x); sum += x; - if (window.length == period) { + if (window!.length == period) { ema = sum / period; window = null; return reduce(acc, ema); diff --git a/packages/transducers-stats/src/momentum.ts b/packages/transducers-stats/src/momentum.ts index 4d8d689e40..69db16ccd4 100644 --- a/packages/transducers-stats/src/momentum.ts +++ b/packages/transducers-stats/src/momentum.ts @@ -1,6 +1,11 @@ import { DCons } from "@thi.ng/dcons"; import { illegalArgs } from "@thi.ng/errors"; -import { compR, iterator1, Reducer, Transducer } from "@thi.ng/transducers"; +import { + compR, + iterator1, + Reducer, + Transducer +} from "@thi.ng/transducers"; /** * https://en.wikipedia.org/wiki/Momentum_(technical_analysis) @@ -29,7 +34,7 @@ export function momentum(period: number, src?: Iterable): any { if (window.length <= period) { return acc; } - const prev = window.drop(); + const prev = window.drop()!; return reduce(acc, x - prev); }); }; diff --git a/packages/transducers-stats/src/roc.ts b/packages/transducers-stats/src/roc.ts index 97117ba346..96abc4cb02 100644 --- a/packages/transducers-stats/src/roc.ts +++ b/packages/transducers-stats/src/roc.ts @@ -1,6 +1,11 @@ import { DCons } from "@thi.ng/dcons"; import { illegalArgs } from "@thi.ng/errors"; -import { compR, iterator1, Reducer, Transducer } from "@thi.ng/transducers"; +import { + compR, + iterator1, + Reducer, + Transducer +} from "@thi.ng/transducers"; /** * Rate of change. @@ -31,7 +36,7 @@ export function roc(period: number, src?: Iterable): any { if (window.length <= period) { return acc; } - const prev = window.drop(); + const prev = window.drop()!; return reduce(acc, (x - prev) / prev); }); }; diff --git a/packages/transducers-stats/src/sma.ts b/packages/transducers-stats/src/sma.ts index 980d2cde57..282db9f252 100644 --- a/packages/transducers-stats/src/sma.ts +++ b/packages/transducers-stats/src/sma.ts @@ -1,6 +1,11 @@ import { DCons } from "@thi.ng/dcons"; import { illegalArgs } from "@thi.ng/errors"; -import { compR, iterator1, Reducer, Transducer } from "@thi.ng/transducers"; +import { + compR, + iterator1, + Reducer, + Transducer +} from "@thi.ng/transducers"; /** * Like @thi.ng/transducers `movingAverage`, but using more efficient @@ -30,7 +35,7 @@ export function sma(period: number, src?: Iterable): any { window.push(x); const n = window.length; sum += x; - n > period && (sum -= window.drop()); + n > period && (sum -= window.drop()!); return n >= period ? reduce(acc, sum / period) : acc; }); }; diff --git a/packages/transducers-stats/src/wma.ts b/packages/transducers-stats/src/wma.ts index ec45ee2fad..5ba615cd8d 100644 --- a/packages/transducers-stats/src/wma.ts +++ b/packages/transducers-stats/src/wma.ts @@ -26,7 +26,7 @@ export function wma(weights: number | number[], src?: Iterable): any { if (src) { return iterator1(wma(weights), src); } - let period, wsum; + let period: number, wsum: number; if (isNumber(weights)) { period = weights | 0; weights = [...range(1, period + 1)]; @@ -35,8 +35,8 @@ export function wma(weights: number | number[], src?: Iterable): any { period = weights.length; wsum = weights.reduce((acc, x) => acc + x, 0); } - return comp( + return comp( partition(period, 1), - map((window: number[]) => dot(window, weights) / wsum) + map((window) => dot(window, weights) / wsum) ); } diff --git a/packages/transducers/CHANGELOG.md b/packages/transducers/CHANGELOG.md index b61e62a5b3..a275d2fca1 100644 --- a/packages/transducers/CHANGELOG.md +++ b/packages/transducers/CHANGELOG.md @@ -3,6 +3,22 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [5.4.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/transducers@5.3.7...@thi.ng/transducers@5.4.0) (2019-07-07) + + +### Bug Fixes + +* **transducers:** fix cat/mapcat arg types ([0d9b7cb](https://github.com/thi-ng/umbrella/commit/0d9b7cb)) + + +### Features + +* **transducers:** enable TS strict compiler flags (refactor) ([2f8ec89](https://github.com/thi-ng/umbrella/commit/2f8ec89)) + + + + + ## [5.3.7](https://github.com/thi-ng/umbrella/compare/@thi.ng/transducers@5.3.6...@thi.ng/transducers@5.3.7) (2019-05-22) **Note:** Version bump only for package @thi.ng/transducers diff --git a/packages/transducers/package.json b/packages/transducers/package.json index 48ce8342f1..576f5a16b5 100644 --- a/packages/transducers/package.json +++ b/packages/transducers/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/transducers", - "version": "5.3.7", + "version": "5.4.0", "description": "Lightweight transducer implementations for ES6 / TypeScript", "module": "./index.js", "main": "./lib/index.js", @@ -25,22 +25,22 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/api": "^6.2.0", - "@thi.ng/arrays": "^0.1.9", - "@thi.ng/checks": "^2.1.6", - "@thi.ng/compare": "^1.0.6", - "@thi.ng/compose": "^1.2.5", - "@thi.ng/equiv": "^1.0.6", - "@thi.ng/errors": "^1.0.6", - "@thi.ng/random": "^1.1.7", - "@thi.ng/strings": "^1.1.3" + "@thi.ng/api": "^6.3.0", + "@thi.ng/arrays": "^0.2.0", + "@thi.ng/checks": "^2.2.0", + "@thi.ng/compare": "^1.0.7", + "@thi.ng/compose": "^1.3.0", + "@thi.ng/equiv": "^1.0.7", + "@thi.ng/errors": "^1.1.0", + "@thi.ng/random": "^1.1.8", + "@thi.ng/strings": "^1.2.0" }, "keywords": [ "array", diff --git a/packages/transducers/src/func/comp.ts b/packages/transducers/src/func/comp.ts index 0da7820f7c..b83c9fbd9d 100644 --- a/packages/transducers/src/func/comp.ts +++ b/packages/transducers/src/func/comp.ts @@ -88,5 +88,5 @@ export function comp( ...fns: Transducer[] ): Transducer; export function comp(...fns: any[]) { - return _comp.apply(null, fns); + return _comp.apply(null, fns); } diff --git a/packages/transducers/src/func/deep-transform.ts b/packages/transducers/src/func/deep-transform.ts index 8fca9d54dc..d159e030ad 100644 --- a/packages/transducers/src/func/deep-transform.ts +++ b/packages/transducers/src/func/deep-transform.ts @@ -67,7 +67,7 @@ export const deepTransform = (spec: TransformSpec): ((x: any) => any) => { return spec; } const mapfns = Object.keys(spec[1] || {}).reduce( - (acc, k) => ((acc[k] = deepTransform((spec)[1][k])), acc), + (acc: any, k) => ((acc[k] = deepTransform((spec)[1][k])), acc), {} ); return (x) => { diff --git a/packages/transducers/src/func/juxtr.ts b/packages/transducers/src/func/juxtr.ts index 6b28f077ac..7165aa6e81 100644 --- a/packages/transducers/src/func/juxtr.ts +++ b/packages/transducers/src/func/juxtr.ts @@ -1,5 +1,5 @@ import { Reducer } from "../api"; -import { isReduced, unreduced, reduced } from "../reduced"; +import { isReduced, reduced, unreduced } from "../reduced"; /** * Composes a new reducer from the ones given, in order to produce @@ -31,13 +31,13 @@ export function juxtR( r3: Reducer, ...rs: Reducer[] ): Reducer; -export function juxtR(...rs: Reducer[]) { +export function juxtR(...rs: Reducer[]): any { let [a, b, c] = rs; const n = rs.length; switch (n) { case 1: { const r = a[2]; - return [ + return >[ () => [a[0]()], (acc) => [a[1](acc[0])], (acc, x) => { @@ -52,7 +52,7 @@ export function juxtR(...rs: Reducer[]) { case 2: { const ra = a[2]; const rb = b[2]; - return [ + return >[ () => [a[0](), b[0]()], (acc) => [a[1](acc[0]), b[1](acc[1])], (acc, x) => { @@ -69,7 +69,7 @@ export function juxtR(...rs: Reducer[]) { const ra = a[2]; const rb = b[2]; const rc = c[2]; - return [ + return >[ () => [a[0](), b[0](), c[0]()], (acc) => [a[1](acc[0]), b[1](acc[1]), c[1](acc[2])], (acc, x) => { @@ -88,7 +88,7 @@ export function juxtR(...rs: Reducer[]) { ]; } default: - return [ + return >[ () => rs.map((r) => r[0]()), (acc) => rs.map((r, i) => r[1](acc[i])), (acc, x) => { diff --git a/packages/transducers/src/func/key-selector.ts b/packages/transducers/src/func/key-selector.ts index 25ef1497f2..7c48e31df3 100644 --- a/packages/transducers/src/func/key-selector.ts +++ b/packages/transducers/src/func/key-selector.ts @@ -1,4 +1,4 @@ import { renamer } from "./renamer"; export const keySelector = (keys: PropertyKey[]) => - renamer(keys.reduce((acc, x) => ((acc[x] = x), acc), {})); + renamer(keys.reduce((acc: any, x) => ((acc[x] = x), acc), {})); diff --git a/packages/transducers/src/func/renamer.ts b/packages/transducers/src/func/renamer.ts index d58d8b68b0..b2b9f83273 100644 --- a/packages/transducers/src/func/renamer.ts +++ b/packages/transducers/src/func/renamer.ts @@ -6,7 +6,7 @@ export const renamer = (kmap: IObjectOf) => { const [a1, b1, c1] = ks.map((k) => kmap[k]); switch (ks.length) { case 3: - return (x) => { + return (x: any) => { const res: any = {}; let v; (v = x[c1]), v !== undefined && (res[c2] = v); @@ -15,7 +15,7 @@ export const renamer = (kmap: IObjectOf) => { return res; }; case 2: - return (x) => { + return (x: any) => { const res: any = {}; let v; (v = x[b1]), v !== undefined && (res[b2] = v); @@ -23,14 +23,14 @@ export const renamer = (kmap: IObjectOf) => { return res; }; case 1: - return (x) => { + return (x: any) => { const res: any = {}; let v = x[a1]; v !== undefined && (res[a2] = v); return res; }; default: - return (x) => { + return (x: any) => { let k, v; const res: any = {}; for (let i = ks.length - 1; i >= 0; i--) { diff --git a/packages/transducers/src/iter/range.ts b/packages/transducers/src/iter/range.ts index dd13061a60..ee62420ece 100644 --- a/packages/transducers/src/iter/range.ts +++ b/packages/transducers/src/iter/range.ts @@ -1,12 +1,12 @@ -import { isReduced, Reduced } from "../reduced"; import { IReducible, ReductionFn } from "../api"; +import { isReduced, Reduced } from "../reduced"; export function range(): Range; export function range(to: number): Range; export function range(from: number, to: number): Range; export function range(from: number, to: number, step: number): Range; export function range(from?: number, to?: number, step?: number) { - return new Range(from, to, step); + return new Range(from!, to!, step!); } /** diff --git a/packages/transducers/src/iter/range2d.ts b/packages/transducers/src/iter/range2d.ts index 5dd54791f1..1d98555080 100644 --- a/packages/transducers/src/iter/range2d.ts +++ b/packages/transducers/src/iter/range2d.ts @@ -20,7 +20,8 @@ export function range2d( stepY: number ): IterableIterator<[number, number]>; export function* range2d(...args: number[]) { - let fromX, toX, fromY, toY, stepX, stepY; + let fromX!: number, toX!: number, stepX!: number; + let fromY!: number, toY!: number, stepY!: number; switch (args.length) { case 6: stepX = args[4]; diff --git a/packages/transducers/src/iter/range3d.ts b/packages/transducers/src/iter/range3d.ts index db63019dbf..52beeca337 100644 --- a/packages/transducers/src/iter/range3d.ts +++ b/packages/transducers/src/iter/range3d.ts @@ -26,7 +26,9 @@ export function range3d( stepZ: number ): IterableIterator<[number, number, number]>; export function* range3d(...args: number[]) { - let fromX, toX, fromY, toY, fromZ, toZ, stepX, stepY, stepZ; + let fromX!: number, toX!: number, stepX!: number; + let fromY!: number, toY!: number, stepY!: number; + let fromZ!: number, toZ!: number, stepZ!: number; switch (args.length) { case 9: stepX = args[6]; diff --git a/packages/transducers/src/iterator.ts b/packages/transducers/src/iterator.ts index 3f244d4d99..f19b3292f4 100644 --- a/packages/transducers/src/iterator.ts +++ b/packages/transducers/src/iterator.ts @@ -1,10 +1,9 @@ -import { FnAny, SEMAPHORE } from "@thi.ng/api"; +import { FnAny, NO_OP, SEMAPHORE } from "@thi.ng/api"; import { isIterable } from "@thi.ng/checks"; import { Reducer, Transducer } from "./api"; import { isReduced, unreduced } from "./reduced"; import { push } from "./rfn/push"; - /** * Takes a transducer and input iterable. Returns iterator of * transformed results. @@ -46,7 +45,7 @@ export function* iterator1( xform: Transducer, xs: Iterable ): IterableIterator { - const reduce = (>xform([null, null, (_, x) => x]))[2]; + const reduce = (>xform([NO_OP, NO_OP, (_, x) => x]))[2]; for (let x of xs) { let y = reduce(SEMAPHORE, x); if (isReduced(y)) { diff --git a/packages/transducers/src/reduce.ts b/packages/transducers/src/reduce.ts index 9a169bac1b..c9a608d44c 100644 --- a/packages/transducers/src/reduce.ts +++ b/packages/transducers/src/reduce.ts @@ -13,7 +13,7 @@ export function reduce( xs: IReducible ): A; export function reduce(...args: any[]): A { - let acc: A, xs: Iterable | IReducible; + let acc!: A, xs!: Iterable | IReducible; switch (args.length) { case 3: xs = args[2]; diff --git a/packages/transducers/src/rfn/assoc-map.ts b/packages/transducers/src/rfn/assoc-map.ts index 972f9240f6..169bb39046 100644 --- a/packages/transducers/src/rfn/assoc-map.ts +++ b/packages/transducers/src/rfn/assoc-map.ts @@ -11,5 +11,8 @@ export function assocMap(xs: Iterable>): Map; export function assocMap(xs?: Iterable>): any { return xs ? reduce(assocMap(), xs) - : reducer(() => new Map(), (acc, [k, v]) => acc.set(k, v)); + : reducer, Pair>( + () => new Map(), + (acc, [k, v]) => acc.set(k, v) + ); } diff --git a/packages/transducers/src/rfn/assoc-obj.ts b/packages/transducers/src/rfn/assoc-obj.ts index 3c2ec114d2..03e2862157 100644 --- a/packages/transducers/src/rfn/assoc-obj.ts +++ b/packages/transducers/src/rfn/assoc-obj.ts @@ -11,8 +11,8 @@ export function assocObj(xs: Iterable>): IObjectOf; export function assocObj(xs?: Iterable>): any { return xs ? reduce(assocObj(), xs) - : reducer( - () => new Object(), - (acc, [k, v]) => ((acc[k] = v), acc) + : reducer, Pair>( + () => ({}), + (acc, [k, v]) => ((acc[k] = v), acc) ); } diff --git a/packages/transducers/src/rfn/fill.ts b/packages/transducers/src/rfn/fill.ts index 079c4ea4e2..d0efa23dd2 100644 --- a/packages/transducers/src/rfn/fill.ts +++ b/packages/transducers/src/rfn/fill.ts @@ -12,13 +12,13 @@ import { $$reduce, reducer } from "../reduce"; export function fill(start?: number): Reducer; export function fill(xs: Iterable): T[]; export function fill(start: number, xs: Iterable): T[]; -export function fill(...args: any[]): any { +export function fill(...args: any[]): any { const res = $$reduce(fill, args); if (res !== undefined) { return res; } let start = args[0] || 0; - return reducer(() => [], (acc, x) => ((acc[start++] = x), acc)); + return reducer(() => [], (acc, x) => ((acc[start++] = x), acc)); } /** diff --git a/packages/transducers/src/rfn/group-by-map.ts b/packages/transducers/src/rfn/group-by-map.ts index 27d1c173a6..b60be89279 100644 --- a/packages/transducers/src/rfn/group-by-map.ts +++ b/packages/transducers/src/rfn/group-by-map.ts @@ -30,7 +30,7 @@ export function groupByMap(...args: any[]): any { return acc.set( k, acc.has(k) - ? reduce(acc.get(k), x) + ? reduce(acc.get(k)!, x) : reduce(init(), x) ); } diff --git a/packages/transducers/src/rfn/group-by-obj.ts b/packages/transducers/src/rfn/group-by-obj.ts index a29696f9e0..883406f445 100644 --- a/packages/transducers/src/rfn/group-by-obj.ts +++ b/packages/transducers/src/rfn/group-by-obj.ts @@ -24,7 +24,7 @@ export function groupByObj(...args: any[]): any { }; const [_init, _, _reduce] = _opts.group; _; - return reducer( + return reducer, SRC>( () => ({}), (acc, x: SRC) => { const k: any = _opts.key(x); diff --git a/packages/transducers/src/rfn/last.ts b/packages/transducers/src/rfn/last.ts index 9af88ff81f..e6733fe814 100644 --- a/packages/transducers/src/rfn/last.ts +++ b/packages/transducers/src/rfn/last.ts @@ -1,8 +1,9 @@ +import { NO_OP } from "@thi.ng/api"; import { Reducer } from "../api"; import { reduce, reducer } from "../reduce"; export function last(): Reducer; export function last(xs: Iterable): T; export function last(xs?: Iterable): any { - return xs ? reduce(last(), xs) : reducer(() => undefined, (_, x) => x); + return xs ? reduce(last(), xs) : reducer(NO_OP, (_, x) => x); } diff --git a/packages/transducers/src/rfn/mean.ts b/packages/transducers/src/rfn/mean.ts index cbfe9cccf2..ac8e58ee14 100644 --- a/packages/transducers/src/rfn/mean.ts +++ b/packages/transducers/src/rfn/mean.ts @@ -11,7 +11,7 @@ export function mean(xs?: Iterable): any { let n = 0; return xs ? reduce(mean(), xs) - : [ + : >[ () => 0, (acc) => (n > 1 ? acc / n : acc), (acc, x) => (n++, acc + x) diff --git a/packages/transducers/src/rfn/push-copy.ts b/packages/transducers/src/rfn/push-copy.ts index b00d76ee5b..be189cd987 100644 --- a/packages/transducers/src/rfn/push-copy.ts +++ b/packages/transducers/src/rfn/push-copy.ts @@ -2,4 +2,4 @@ import { Reducer } from "../api"; import { reducer } from "../reduce"; export const pushCopy = (): Reducer => - reducer(() => [], (acc, x) => ((acc = acc.slice()).push(x), acc)); + reducer(() => [], (acc, x) => ((acc = acc.slice()).push(x), acc)); diff --git a/packages/transducers/src/rfn/push.ts b/packages/transducers/src/rfn/push.ts index 21040efbc1..ee73bdc205 100644 --- a/packages/transducers/src/rfn/push.ts +++ b/packages/transducers/src/rfn/push.ts @@ -4,5 +4,7 @@ import { reducer } from "../reduce"; export function push(): Reducer; export function push(xs: Iterable): T[]; export function push(xs?: Iterable): any { - return xs ? [...xs] : reducer(() => [], (acc, x) => (acc.push(x), acc)); + return xs + ? [...xs] + : reducer(() => [], (acc, x) => (acc.push(x), acc)); } diff --git a/packages/transducers/src/rfn/reductions.ts b/packages/transducers/src/rfn/reductions.ts index 91e3e2b5d7..c8e4f7547b 100644 --- a/packages/transducers/src/rfn/reductions.ts +++ b/packages/transducers/src/rfn/reductions.ts @@ -8,7 +8,7 @@ export function reductions(rfn: Reducer, xs?: Iterable): any { const [init, complete, _reduce] = rfn; return xs ? reduce(reductions(rfn), xs) - : [ + : >[ () => [init()], (acc) => ( (acc[acc.length - 1] = complete(acc[acc.length - 1])), acc diff --git a/packages/transducers/src/xform/cat.ts b/packages/transducers/src/xform/cat.ts index 81688910a0..a5bf704d0b 100644 --- a/packages/transducers/src/xform/cat.ts +++ b/packages/transducers/src/xform/cat.ts @@ -1,6 +1,6 @@ import { Reducer, Transducer } from "../api"; import { compR } from "../func/compr"; -import { isReduced, unreduced, ensureReduced } from "../reduced"; +import { ensureReduced, isReduced, unreduced } from "../reduced"; /** * Transducer to concatenate iterable values. Iterates over each input @@ -32,11 +32,11 @@ import { isReduced, unreduced, ensureReduced } from "../reduced"; * @see thi.ng/transducers/iter/concat * @see thi.ng/transducers/xform/mapcat */ -export const cat = (): Transducer, T> => ( +export const cat = (): Transducer | null | undefined, T> => ( rfn: Reducer ) => { const r = rfn[2]; - return compR(rfn, (acc, x: Iterable) => { + return compR(rfn, (acc, x: Iterable | null | undefined) => { if (x) { for (let y of unreduced(x)) { acc = r(acc, y); diff --git a/packages/transducers/src/xform/convolve.ts b/packages/transducers/src/xform/convolve.ts index 08c4c37843..8568e72cc9 100644 --- a/packages/transducers/src/xform/convolve.ts +++ b/packages/transducers/src/xform/convolve.ts @@ -1,4 +1,4 @@ -import { Fn0 } from "@thi.ng/api"; +import { Fn, Fn0 } from "@thi.ng/api"; import { illegalArgs } from "@thi.ng/errors"; import { Reducer, Transducer } from "../api"; import { range } from "../iter/range"; @@ -83,7 +83,7 @@ const kernelLookup1d = ( width: number, wrap: boolean, border: number -) => +): Fn<[number, number], number> => wrap ? ([w, ox]) => { const xx = @@ -102,7 +102,7 @@ const kernelLookup2d = ( height: number, wrap: boolean, border: number -) => +): Fn<[number, [number, number]], number> => wrap ? ([w, [ox, oy]]) => { const xx = @@ -138,13 +138,13 @@ export function convolve1d( let kernel = opts.kernel; if (!kernel) { !(opts.weights && opts.kwidth) && kernelError(); - kernel = buildKernel1d(opts.weights, opts.kwidth); + kernel = buildKernel1d(opts.weights!, opts.kwidth!); } return map((p: number) => transduce( map(kernelLookup1d(src, p, width, wrap, border)), rfn(), - kernel + kernel! ) ); } @@ -170,13 +170,13 @@ export function convolve2d( let kernel = opts.kernel; if (!kernel) { !(opts.weights && opts.kwidth && opts.kheight) && kernelError(); - kernel = buildKernel2d(opts.weights, opts.kwidth, opts.kheight); + kernel = buildKernel2d(opts.weights!, opts.kwidth!, opts.kheight!); } return map((p: number[]) => transduce( map(kernelLookup2d(src, p[0], p[1], width, height, wrap, border)), rfn(), - kernel + kernel! ) ); } diff --git a/packages/transducers/src/xform/delayed.ts b/packages/transducers/src/xform/delayed.ts index 2aff1fa2c3..d6a8ea899b 100644 --- a/packages/transducers/src/xform/delayed.ts +++ b/packages/transducers/src/xform/delayed.ts @@ -1,5 +1,5 @@ -import { Transducer } from "../api"; import { delayed as _delayed } from "@thi.ng/compose"; +import { Transducer } from "../api"; import { map } from "./map"; /** @@ -12,4 +12,4 @@ import { map } from "./map"; * @param t */ export const delayed = (t: number): Transducer> => - map((x) => _delayed(x, t)); + map((x) => _delayed(x, t)); diff --git a/packages/transducers/src/xform/flatten-with.ts b/packages/transducers/src/xform/flatten-with.ts index 09bce57e27..72f2f6a824 100644 --- a/packages/transducers/src/xform/flatten-with.ts +++ b/packages/transducers/src/xform/flatten-with.ts @@ -19,7 +19,7 @@ export function flattenWith( ? iterator(flattenWith(fn), src) : (rfn: Reducer) => { const reduce = rfn[2]; - const flatten = (acc, x) => { + const flatten = (acc: any, x: any) => { const xx = fn(x); if (xx) { for (let y of xx) { diff --git a/packages/transducers/src/xform/flatten.ts b/packages/transducers/src/xform/flatten.ts index ffe4c013d0..bb477bdad1 100644 --- a/packages/transducers/src/xform/flatten.ts +++ b/packages/transducers/src/xform/flatten.ts @@ -5,10 +5,10 @@ export function flatten(): Transducer, T>; export function flatten(src: Iterable>): IterableIterator; export function flatten(src?: Iterable>): any { return flattenWith( - (x) => + (x: any) => x != null && x[Symbol.iterator] && typeof x !== "string" ? x : undefined, - src + src! ); } diff --git a/packages/transducers/src/xform/map-keys.ts b/packages/transducers/src/xform/map-keys.ts index 87e5460372..9ff68ca66f 100644 --- a/packages/transducers/src/xform/map-keys.ts +++ b/packages/transducers/src/xform/map-keys.ts @@ -45,8 +45,8 @@ export function mapKeys(...args: any[]): any { } const keys: IObjectOf<(x: any) => any> = args[0]; const copy = args[1] !== false; - return map((x) => { - const res = copy ? Object.assign({}, x) : x; + return map((x: any) => { + const res: any = copy ? Object.assign({}, x) : x; for (let k in keys) { res[k] = keys[k](x[k]); } diff --git a/packages/transducers/src/xform/map-nth.ts b/packages/transducers/src/xform/map-nth.ts index 9786067877..201d934b78 100644 --- a/packages/transducers/src/xform/map-nth.ts +++ b/packages/transducers/src/xform/map-nth.ts @@ -43,9 +43,9 @@ export function mapNth(...args: any[]): any { if (iter) { return iter; } - let n = args[0] - 1, - offset, - fn; + let n = args[0] - 1; + let offset: number; + let fn: Fn; if (typeof args[1] === "number") { offset = args[1]; fn = args[2]; diff --git a/packages/transducers/src/xform/map-vals.ts b/packages/transducers/src/xform/map-vals.ts index c967318a15..369c095762 100644 --- a/packages/transducers/src/xform/map-vals.ts +++ b/packages/transducers/src/xform/map-vals.ts @@ -38,7 +38,7 @@ export function mapVals(...args: any[]): any { } const fn: Fn = args[0]; const copy = args[1] !== false; - return map((x) => { + return map((x: any) => { const res: any = copy ? {} : x; for (let k in x) { res[k] = fn(x[k]); diff --git a/packages/transducers/src/xform/mapcat.ts b/packages/transducers/src/xform/mapcat.ts index 55d98bbdc2..aa0ebff304 100644 --- a/packages/transducers/src/xform/mapcat.ts +++ b/packages/transducers/src/xform/mapcat.ts @@ -22,11 +22,16 @@ import { map } from "./map"; * * @param fn mapping function */ -export function mapcat(fn: Fn>): Transducer; export function mapcat( - fn: Fn>, + fn: Fn | null | undefined> +): Transducer; +export function mapcat( + fn: Fn | null | undefined>, src: Iterable ): IterableIterator; -export function mapcat(fn: Fn>, src?: Iterable): any { +export function mapcat( + fn: Fn | null | undefined>, + src?: Iterable +): any { return src ? iterator(mapcat(fn), src) : comp(map(fn), cat()); } diff --git a/packages/transducers/src/xform/moving-average.ts b/packages/transducers/src/xform/moving-average.ts index b0e96eecd1..d9dc216068 100644 --- a/packages/transducers/src/xform/moving-average.ts +++ b/packages/transducers/src/xform/moving-average.ts @@ -29,12 +29,12 @@ export function movingAverage(period: number, src?: Iterable): any { period |= 0; period < 2 && illegalArgs("period must be >= 2"); const reduce = rfn[2]; - const window = []; + const window: number[] = []; let sum = 0; return compR(rfn, (acc, x: number) => { const n = window.push(x); sum += x; - n > period && (sum -= window.shift()); + n > period && (sum -= window.shift()!); return n >= period ? reduce(acc, sum / period) : acc; }); }; diff --git a/packages/transducers/src/xform/moving-median.ts b/packages/transducers/src/xform/moving-median.ts index 4ce9b6aade..1c86b70c6c 100644 --- a/packages/transducers/src/xform/moving-median.ts +++ b/packages/transducers/src/xform/moving-median.ts @@ -41,7 +41,7 @@ export function movingMedian(...args: any[]): any { }; const n = args[0]; const m = n >> 1; - return comp( + return comp( partition(n, 1, true), map( (window: A[]) => diff --git a/packages/transducers/src/xform/multiplex-obj.ts b/packages/transducers/src/xform/multiplex-obj.ts index 18e3299d9d..9712e2f007 100644 --- a/packages/transducers/src/xform/multiplex-obj.ts +++ b/packages/transducers/src/xform/multiplex-obj.ts @@ -49,7 +49,7 @@ export function multiplexObj(...args: any[]): any { const [xforms, rfn] = args; const ks = Object.keys(xforms); return comp( - multiplex.apply(null, ks.map((k) => xforms[k])), + multiplex.apply(null, ks.map((k) => xforms[k])), rename(ks, rfn) ); } diff --git a/packages/transducers/src/xform/multiplex.ts b/packages/transducers/src/xform/multiplex.ts index 18123a6144..5b8f229dad 100644 --- a/packages/transducers/src/xform/multiplex.ts +++ b/packages/transducers/src/xform/multiplex.ts @@ -75,5 +75,5 @@ export function multiplex( h: Transducer ): Transducer; export function multiplex(...args: any[]) { - return map(juxt.apply(null, args.map(step))); + return map(juxt.apply(null, args.map(step))); } diff --git a/packages/transducers/src/xform/pad-last.ts b/packages/transducers/src/xform/pad-last.ts index 83c84c0e5a..764a177dcc 100644 --- a/packages/transducers/src/xform/pad-last.ts +++ b/packages/transducers/src/xform/pad-last.ts @@ -41,7 +41,7 @@ export function padLast(n: number, fill: T, src?: Iterable): any { ? iterator(padLast(n, fill), src) : ([init, complete, reduce]: Reducer) => { let m = 0; - return [ + return >[ init, (acc) => { let rem = m % n; diff --git a/packages/transducers/src/xform/partition-by.ts b/packages/transducers/src/xform/partition-by.ts index 9180e10dd5..9715263be9 100644 --- a/packages/transducers/src/xform/partition-by.ts +++ b/packages/transducers/src/xform/partition-by.ts @@ -1,5 +1,5 @@ import { Fn, SEMAPHORE } from "@thi.ng/api"; -import { Transducer } from "../api"; +import { Reducer, Transducer } from "../api"; import { $iter, iterator } from "../iterator"; import { isReduced } from "../reduced"; @@ -32,12 +32,12 @@ export function partitionBy( export function partitionBy(...args: any[]): any { return ( $iter(partitionBy, args, iterator) || - (([init, complete, reduce]) => { + (([init, complete, reduce]: Reducer) => { const fn: Fn | (() => Fn) = args[0]; const f = args[1] === true ? (<() => Fn>fn)() : fn; - let prev: any = SEMAPHORE, - chunk; - return [ + let prev: any = SEMAPHORE; + let chunk: T[] | null; + return >[ init, (acc) => { if (chunk && chunk.length) { @@ -52,7 +52,7 @@ export function partitionBy(...args: any[]): any { prev = curr; chunk = [x]; } else if (curr === prev) { - chunk.push(x); + chunk!.push(x); } else { chunk && (acc = reduce(acc, chunk)); chunk = isReduced(acc) ? null : [x]; diff --git a/packages/transducers/src/xform/partition-sort.ts b/packages/transducers/src/xform/partition-sort.ts index 25ae9ee871..12af29d595 100644 --- a/packages/transducers/src/xform/partition-sort.ts +++ b/packages/transducers/src/xform/partition-sort.ts @@ -55,7 +55,7 @@ export function partitionSort(...args: any[]): any { compare: cmp, ...args[1] }; - return comp( + return comp( partition(args[0], true), mapcat((window: A[]) => window.slice().sort((a, b) => compare(key(a), key(b))) diff --git a/packages/transducers/src/xform/partition-sync.ts b/packages/transducers/src/xform/partition-sync.ts index f9c92777d2..c424f78b14 100644 --- a/packages/transducers/src/xform/partition-sync.ts +++ b/packages/transducers/src/xform/partition-sync.ts @@ -95,7 +95,7 @@ export function partitionSync(...args: any[]): any { return ( $iter(partitionSync, args, iterator) || (([init, complete, reduce]: Reducer>) => { - let curr = {}; + let curr: any = {}; let first = true; const currKeys = new Set(); const { key, mergeOnly, reset, all } = >{ @@ -108,7 +108,7 @@ export function partitionSync(...args: any[]): any { const ks: Set = isArray(args[0]) ? new Set(args[0]) : args[0]; - return [ + return >[ init, (acc) => { if ( diff --git a/packages/transducers/src/xform/partition.ts b/packages/transducers/src/xform/partition.ts index f74c425ac3..de386fe9ad 100644 --- a/packages/transducers/src/xform/partition.ts +++ b/packages/transducers/src/xform/partition.ts @@ -62,8 +62,8 @@ export function partition(...args: any[]): any { return iter; } let size = args[0], - all, - step; + all: boolean, + step: number; if (typeof args[1] == "number") { step = args[1]; all = args[2]; @@ -74,7 +74,7 @@ export function partition(...args: any[]): any { return ([init, complete, reduce]: Reducer) => { let buf: T[] = []; let skip = 0; - return [ + return >[ init, (acc) => { if (all && buf.length > 0) { diff --git a/packages/transducers/src/xform/pluck.ts b/packages/transducers/src/xform/pluck.ts index a7fb3d2bc4..88ade06eb3 100644 --- a/packages/transducers/src/xform/pluck.ts +++ b/packages/transducers/src/xform/pluck.ts @@ -19,5 +19,5 @@ export function pluck( src: Iterable ): IterableIterator; export function pluck(key: PropertyKey, src?: Iterable): any { - return src ? iterator1(pluck(key), src) : map((x: A) => x[key]); + return src ? iterator1(pluck(key), src) : map((x: any) => x[key]); } diff --git a/packages/transducers/src/xform/rename.ts b/packages/transducers/src/xform/rename.ts index bde5a69c50..b9b7bf1353 100644 --- a/packages/transducers/src/xform/rename.ts +++ b/packages/transducers/src/xform/rename.ts @@ -28,7 +28,7 @@ export function rename(...args: any[]): any { } if (args[1]) { const ks = Object.keys(kmap); - return map((y) => + return map((y: any) => transduce( comp( map((k: PropertyKey) => [k, y[kmap[k]]]), diff --git a/packages/transducers/src/xform/scan.ts b/packages/transducers/src/xform/scan.ts index 2be8313176..a0251998f1 100644 --- a/packages/transducers/src/xform/scan.ts +++ b/packages/transducers/src/xform/scan.ts @@ -34,7 +34,7 @@ export function scan(...args: any[]): any { (([inito, completeo, reduceo]: Reducer) => { const [initi, completei, reducei]: Reducer = args[0]; let acc: B = args.length > 1 && args[1] != null ? args[1] : initi(); - return [ + return >[ inito, (_acc) => { let a = completei(acc); diff --git a/packages/transducers/src/xform/stream-shuffle.ts b/packages/transducers/src/xform/stream-shuffle.ts index 2e25fb72f1..d9a9906cd2 100644 --- a/packages/transducers/src/xform/stream-shuffle.ts +++ b/packages/transducers/src/xform/stream-shuffle.ts @@ -37,12 +37,12 @@ export function streamShuffle(...args: any[]): any { const n: number = args[0]; const maxSwaps: number = args[1] || n; const buf: T[] = []; - return [ + return >[ init, (acc) => { while (buf.length && !isReduced(acc)) { shuffle(buf, maxSwaps); - acc = reduce(acc, buf.shift()); + acc = reduce(acc, buf.shift()!); } acc = complete(acc); return acc; @@ -51,7 +51,7 @@ export function streamShuffle(...args: any[]): any { buf.push(x); shuffle(buf, maxSwaps); if (buf.length === n) { - acc = reduce(acc, buf.shift()); + acc = reduce(acc, buf.shift()!); } return acc; } diff --git a/packages/transducers/src/xform/stream-sort.ts b/packages/transducers/src/xform/stream-sort.ts index 4cdd83755a..e9822ee722 100644 --- a/packages/transducers/src/xform/stream-sort.ts +++ b/packages/transducers/src/xform/stream-sort.ts @@ -45,11 +45,11 @@ export function streamSort(...args: any[]): any { const n = args[0]; return ([init, complete, reduce]: Reducer) => { const buf: A[] = []; - return [ + return >[ init, (acc) => { while (buf.length && !isReduced(acc)) { - acc = reduce(acc, buf.shift()); + acc = reduce(acc, buf.shift()!); } return complete(acc); }, @@ -57,7 +57,7 @@ export function streamSort(...args: any[]): any { const idx = binarySearch(buf, x, key, compare); buf.splice(idx < 0 ? -(idx + 1) : idx, 0, x); if (buf.length === n) { - acc = reduce(acc, buf.shift()); + acc = reduce(acc, buf.shift()!); } return acc; } diff --git a/packages/transducers/src/xform/struct.ts b/packages/transducers/src/xform/struct.ts index f09d9c7f6c..b81c26b436 100644 --- a/packages/transducers/src/xform/struct.ts +++ b/packages/transducers/src/xform/struct.ts @@ -53,7 +53,7 @@ export function struct(fields: StructField[], src?: Iterable): any { rename(fields.map((f) => f[0])), mapKeys( fields.reduce( - (acc, f) => (f[2] ? ((acc[f[0]] = f[2]), acc) : acc), + (acc: any, f) => (f[2] ? ((acc[f[0]] = f[2]), acc) : acc), {} ), false diff --git a/packages/transducers/src/xform/take-last.ts b/packages/transducers/src/xform/take-last.ts index 6fc6450e74..c4e0f7f026 100644 --- a/packages/transducers/src/xform/take-last.ts +++ b/packages/transducers/src/xform/take-last.ts @@ -21,11 +21,11 @@ export function takeLast(n: number, src?: Iterable): any { ? iterator(takeLast(n), src) : ([init, complete, reduce]: Reducer) => { const buf: T[] = []; - return [ + return >[ init, (acc) => { while (buf.length && !isReduced(acc)) { - acc = reduce(acc, buf.shift()); + acc = reduce(acc, buf.shift()!); } return complete(acc); }, diff --git a/packages/transducers/src/xform/toggle.ts b/packages/transducers/src/xform/toggle.ts index 6648564e45..c993e3b2c8 100644 --- a/packages/transducers/src/xform/toggle.ts +++ b/packages/transducers/src/xform/toggle.ts @@ -38,7 +38,7 @@ export function toggle( return [ init, complete, - (acc) => reduce(acc, (state = !state) ? on : off) + (acc: any) => reduce(acc, (state = !state) ? on : off) ]; }; } diff --git a/packages/transducers/test/partition-sync.ts b/packages/transducers/test/partition-sync.ts index 9a8e2ed973..c86e7db4e9 100644 --- a/packages/transducers/test/partition-sync.ts +++ b/packages/transducers/test/partition-sync.ts @@ -43,7 +43,7 @@ describe("partitionSync", () => { const keys = new Set(["a", "b", "t"]); const f = step( partitionSync(keys, { - key: (x) => x[0], + key: (x: any) => x[0], reset: false }) ); diff --git a/packages/unionstruct/CHANGELOG.md b/packages/unionstruct/CHANGELOG.md index 83ac4807a3..c169a667da 100644 --- a/packages/unionstruct/CHANGELOG.md +++ b/packages/unionstruct/CHANGELOG.md @@ -3,6 +3,23 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.1.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/unionstruct@1.0.6...@thi.ng/unionstruct@1.1.0) (2019-07-07) + + +### Bug Fixes + +* **unionstruct:** allow undefined/null args ([9636495](https://github.com/thi-ng/umbrella/commit/9636495)) +* **unionstruct:** FieldType typo ([02beff9](https://github.com/thi-ng/umbrella/commit/02beff9)) + + +### Features + +* **unionstruct:** enable TS strict compiler flags (refactor) ([eb639fe](https://github.com/thi-ng/umbrella/commit/eb639fe)) + + + + + ## [1.0.6](https://github.com/thi-ng/umbrella/compare/@thi.ng/unionstruct@1.0.5...@thi.ng/unionstruct@1.0.6) (2019-04-24) **Note:** Version bump only for package @thi.ng/unionstruct diff --git a/packages/unionstruct/package.json b/packages/unionstruct/package.json index 2618b3e02c..55a5fffccb 100644 --- a/packages/unionstruct/package.json +++ b/packages/unionstruct/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/unionstruct", - "version": "1.0.6", + "version": "1.1.0", "description": "C-style struct, union and bitfield views of ArrayBuffers", "module": "./index.js", "main": "./lib/index.js", @@ -25,11 +25,11 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "keywords": [ "align", diff --git a/packages/unionstruct/src/index.ts b/packages/unionstruct/src/index.ts index 200ce82861..583d82f681 100644 --- a/packages/unionstruct/src/index.ts +++ b/packages/unionstruct/src/index.ts @@ -3,7 +3,7 @@ export type FieldType = | "f32" | "u32" | "u16" - | " u8" + | "u8" | "i32" | "i16" | "i8" @@ -16,7 +16,7 @@ export interface Field extends Array { [2]?: any; } -const TYPES = { +const TYPES: { [id: string]: [number, string, boolean] } = { f64: [64, "Float", false], f32: [32, "Float", false], u32: [32, "Uint", false], @@ -33,7 +33,11 @@ const STRUCT = "struct"; const isBitField = (f: Field) => typeof f[2] === "number" && /^(u|i)\d+$/.test(f[1]); -const align = (bitOffset: number, type: string, spec: any) => { +const align = ( + bitOffset: number, + type: keyof typeof TYPES | "union" | "struct", + spec: any +): number => { if (type === UNION) { spec = spec.__spec || spec; let a = 0, @@ -124,7 +128,7 @@ const bitWriter = ( let m = bit < 32 ? ~((1 << bit) - 1) : 0; if (b >= 0) { m |= (1 << b) - 1; - return (x) => { + return (x: number) => { dv.setUint32( byteOffset, (dv.getUint32(byteOffset, false) & m) | ((x << b) & ~m), @@ -133,7 +137,7 @@ const bitWriter = ( }; } else { let bb = 32 + b; - return (x) => { + return (x: number) => { dv.setUint32( byteOffset, (dv.getUint32(byteOffset, false) & m) | ((x >>> -b) & ~m), @@ -180,7 +184,7 @@ const makeField = ( } else { let [dsize, typeid, signed] = TYPES[type]; let shift = 32 - size; - let get, set, read, write; + let get, set, read: any, write: any; if (isBF) { byteOffset &= -4; let bitPos = 32 - (bitOffset & 0x1f); @@ -189,8 +193,8 @@ const makeField = ( set = bitWriter(dv, byteOffset, bitPos, size); bitOffset += size; } else { - read = dv[`get${typeid}${dsize}`]; - write = dv[`set${typeid}${dsize}`]; + read = (dv)[`get${typeid}${dsize}`]; + write = (dv)[`set${typeid}${dsize}`]; get = signed ? () => (read.call(dv, byteOffset, le) << shift) >> shift : () => read.call(dv, byteOffset, le); @@ -213,7 +217,7 @@ const makeField = ( export const typedef = ( spec: Field[], struct: boolean, - buf?: ArrayBuffer, + buf?: ArrayBuffer | null, offset = 0, doAlign = true, le = false @@ -242,7 +246,7 @@ export const typedef = ( export const union = ( spec: Field[], - buf?: ArrayBuffer, + buf?: ArrayBuffer | null, offset?: number, doAlign?: boolean, le?: boolean @@ -252,7 +256,7 @@ export const union = ( export const struct = ( spec: Field[], - buf?: ArrayBuffer, + buf?: ArrayBuffer | null, offset?: number, doAlign?: boolean, le?: boolean diff --git a/packages/vector-pools/CHANGELOG.md b/packages/vector-pools/CHANGELOG.md index 65cf416ed0..8d0cf50e23 100644 --- a/packages/vector-pools/CHANGELOG.md +++ b/packages/vector-pools/CHANGELOG.md @@ -3,6 +3,32 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.0.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/vector-pools@0.2.16...@thi.ng/vector-pools@1.0.0) (2019-07-07) + + +### Code Refactoring + +* **vector-pools:** address TS strictNullChecks flag ([981b5ce](https://github.com/thi-ng/umbrella/commit/981b5ce)) + + +### Features + +* **vector-pools:** add AttribPool.attribArray(), add tests ([285022a](https://github.com/thi-ng/umbrella/commit/285022a)) +* **vector-pools:** enable TS strict compiler flags (refactor) ([1af6f78](https://github.com/thi-ng/umbrella/commit/1af6f78)) +* **vector-pools:** update AttribPool, add tests, update readme ([33109d0](https://github.com/thi-ng/umbrella/commit/33109d0)) + + +### BREAKING CHANGES + +* **vector-pools:** update return types of various class methods + +- some AList, ArrayList, LinkedList, VecPool methods now return + `undefined` if operation failed + + + + + ## [0.2.16](https://github.com/thi-ng/umbrella/compare/@thi.ng/vector-pools@0.2.15...@thi.ng/vector-pools@0.2.16) (2019-05-22) **Note:** Version bump only for package @thi.ng/vector-pools diff --git a/packages/vector-pools/README.md b/packages/vector-pools/README.md index fe0b6d7bee..9535a6bcee 100644 --- a/packages/vector-pools/README.md +++ b/packages/vector-pools/README.md @@ -54,34 +54,37 @@ import * as v from "@thi.ng/vectors"; import * as tx from "@thi.ng/transducers"; // create an interleaved (AOS layout) attribute buffer w/ default values -const geo = new AttribPool( +const geo = new AttribPool({ // initial size in bytes (or provide ArrayBuffer or @thi.ng/malloc/MemPool) - 0x200, + mem: { size: 0x200 }, // num elements - 4, + num: 4, // attrib specs (data mapping layout) - { - pos: { type: GLType.F32, size: 3, default: [0, 0, 0], byteOffset: 0 }, - uv: { type: GLType.F32, size: 2, default: [0, 0], byteOffset: 12 }, + attribs: { + pos: { type: GLType.F32, size: 3, byteOffset: 0 }, + uv: { type: GLType.F32, size: 2, byteOffset: 12 }, col: { type: GLType.F32, size: 3, default: [1, 1, 1], byteOffset: 20 }, - id: { type: GLType.U16, size: 1, default: 0, byteOffset: 32 } + id: { type: GLType.U16, size: 1, byteOffset: 32 } } -); +}); // computed overall stride length geo.byteStride // 36 // set attrib values -geo.setAttribValues("pos", [[-5, 0, 0], [5, 0, 0], [5, 5, 0], [-5, 5, 0]]); -geo.setAttribValues("uv", [[0, 0], [1, 0], [1, 1], [0, 1]]); +geo.setAttribs({ + pos: { data: [[-5, 0, 0], [5, 0, 0], [5, 5, 0], [-5, 5, 0]]}, + uv: { data: [[0, 0], [1, 0], [1, 1], [0, 1]] } +}); +// ...or individually geo.setAttribValues("id", [0, 1, 2, 3]); // get view of individual attrib val geo.attribValue("pos", 3) // Float32Array [ -5, 5, 0 ] -// zero-copy direct manipulation of attrib val +// zero-copy direct manipulation of mapped attrib val v.mulN(null, geo.attribValue("pos", 3), 2); // Float32Array [ -10, 10, 0 ] @@ -95,7 +98,7 @@ v.mulN(null, geo.attribValue("pos", 3), 2); // use with transducers, e.g. to map positions to colors tx.run( tx.map(([pos, col]) => v.maddN(col, [0.5, 0.5, 0.5], v.normalize(col, pos), 0.5)), - tx.tuples(geo.attribValues("pos"), geo.attribValues("col")) + tx.zip(geo.attribValues("pos"), geo.attribValues("col")) ); // updated colors @@ -140,7 +143,6 @@ const initAttrib = (gl, loc, attrib) => { initAttrib(gl, attribLocPosition, geo.specs.pos); initAttrib(gl, attribLocNormal, geo.specs.normal); initAttrib(gl, attribLocUV, geo.specs.uv); -initAttrib(gl, attribLocID, geo.specs.id); ``` ### WASM interop diff --git a/packages/vector-pools/package.json b/packages/vector-pools/package.json index f79804506c..eb1fa6b3bc 100644 --- a/packages/vector-pools/package.json +++ b/packages/vector-pools/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/vector-pools", - "version": "0.2.16", + "version": "1.0.0", "description": "Data structures for managing & working with strided, memory mapped vectors", "module": "./index.js", "main": "./lib/index.js", @@ -25,16 +25,19 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/api": "^6.2.0", - "@thi.ng/malloc": "^3.0.0", - "@thi.ng/vectors": "^2.5.6" + "@thi.ng/api": "^6.3.0", + "@thi.ng/binary": "^1.0.7", + "@thi.ng/checks": "^2.2.0", + "@thi.ng/malloc": "^4.0.0", + "@thi.ng/transducers": "^5.4.0", + "@thi.ng/vectors": "^3.0.0" }, "keywords": [ "ES6", diff --git a/packages/vector-pools/src/alist.ts b/packages/vector-pools/src/alist.ts index 5dd0e2addd..e69e6758cc 100644 --- a/packages/vector-pools/src/alist.ts +++ b/packages/vector-pools/src/alist.ts @@ -48,15 +48,15 @@ export abstract class AVecList { abstract get length(): number; - abstract add(): T; + abstract add(): T | undefined; - abstract insert(i: number): T; + abstract insert(i: number): T | undefined; abstract remove(v: T): boolean; abstract has(v: T): boolean; - abstract nth(n: number): T; + abstract nth(n: number): T | undefined; indices(res: Vec = [], i = 0, local = true) { const start = this.start; @@ -76,7 +76,7 @@ export abstract class AVecList { protected alloc() { let idx: number; if (this.freeIDs.length > 0) { - idx = this.freeIDs.pop(); + idx = this.freeIDs.pop()!; } else if (this.length >= this.capacity) { return; } else { diff --git a/packages/vector-pools/src/api.ts b/packages/vector-pools/src/api.ts index 42db350b9e..d6a0b7dccd 100644 --- a/packages/vector-pools/src/api.ts +++ b/packages/vector-pools/src/api.ts @@ -10,9 +10,11 @@ import { ReadonlyVec, StridedVec, Vec } from "@thi.ng/vectors"; export interface AttribSpec { type: GLType | Type; size: number; - default?: number | ReadonlyVec; byteOffset: number; stride?: number; + default?: number | ReadonlyVec; + data?: ReadonlyVec | ReadonlyVec[]; + index?: number; } export interface AttribPoolOpts { @@ -23,13 +25,13 @@ export interface AttribPoolOpts { } export interface IVecPool extends IRelease { - malloc(size: number, type?: GLType | Type): TypedArray; + malloc(size: number, type?: GLType | Type): TypedArray | undefined; mallocWrapped( size: number, stride?: number, type?: GLType | Type - ): StridedVec; + ): StridedVec | undefined; mallocArray( num: number, @@ -37,11 +39,11 @@ export interface IVecPool extends IRelease { cstride?: number, estride?: number, type?: GLType | Type - ): StridedVec[]; + ): StridedVec[] | undefined; free(vec: StridedVec | TypedArray): boolean; - freeAll(); + freeAll(): void; } export type VecFactory = ( @@ -72,7 +74,7 @@ export const enum GLType { /** * Conversion from `GLType` to `Type`. */ -export const GL2TYPE = { +export const GL2TYPE: { [id: number]: Type } = { [GLType.I8]: Type.I8, [GLType.U8]: Type.U8, [GLType.I16]: Type.I16, @@ -86,7 +88,7 @@ export const GL2TYPE = { /** * Conversion from `Type` to `GLType`. */ -export const TYPE2GL = { +export const TYPE2GL: { [id: number]: GLType } = { [Type.I8]: GLType.I8, [Type.U8]: GLType.U8, [Type.I16]: GLType.I16, diff --git a/packages/vector-pools/src/array-list.ts b/packages/vector-pools/src/array-list.ts index 913aa8bf64..66f92f1e3b 100644 --- a/packages/vector-pools/src/array-list.ts +++ b/packages/vector-pools/src/array-list.ts @@ -36,7 +36,7 @@ export class VecArrayList extends AVecList { } add() { - const v: T = this.alloc(); + const v: T | undefined = this.alloc(); if (v) { this.items.push(v); } @@ -45,7 +45,7 @@ export class VecArrayList extends AVecList { insert(i: number) { if (!this.length && i !== 0) return; - const v: T = this.alloc(); + const v: T | undefined = this.alloc(); if (v) { this.items.splice(i, 0, v); } @@ -59,6 +59,7 @@ export class VecArrayList extends AVecList { this.items.splice(idx, 1); return true; } + return false; } has(v: T) { diff --git a/packages/vector-pools/src/attrib-pool.ts b/packages/vector-pools/src/attrib-pool.ts index 8e97e8254b..f4186c2d48 100644 --- a/packages/vector-pools/src/attrib-pool.ts +++ b/packages/vector-pools/src/attrib-pool.ts @@ -6,27 +6,29 @@ import { TypedArray } from "@thi.ng/api"; import { align, Pow2 } from "@thi.ng/binary"; -import { MemPool, wrap } from "@thi.ng/malloc"; +import { MemPool, TYPEDARRAY_CTORS, wrap } from "@thi.ng/malloc"; import { range } from "@thi.ng/transducers"; import { ReadonlyVec, Vec, zeroes } from "@thi.ng/vectors"; import { AttribPoolOpts, AttribSpec } from "./api"; import { asNativeType } from "./convert"; /* + * 0x00 0x08 0x10 0x18 + * ^ ^ ^ ^ * WASM mem : 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ... * typedarr : 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ... global offset = 4 (bytes) * pos (f32) : X X X X Y Y Y Y X ... offset = 0 (bytes), size = 2 (f32) * uv (f32) : U U U U V V V V ... offset = 8 (bytes), size = 2 (f32) * col (u16) : R R G G B B A A ... offset = 16 (bytes), size = 4 (u16) * - * global stride: 24 + * stride : 24 */ export class AttribPool implements IRelease { attribs: IObjectOf; order: string[]; specs: IObjectOf; pool: MemPool; - addr: number; + addr!: number; capacity: number; byteStride: number; @@ -42,7 +44,7 @@ export class AttribPool implements IRelease { ? new MemPool(opts.mem) : opts.mem; this.capacity = opts.num; - this.resizable = opts.resizable; + this.resizable = !!opts.resizable; this.specs = {}; this.attribs = {}; this.order = []; @@ -83,23 +85,24 @@ export class AttribPool implements IRelease { this.addr = addr; } this.initDefaults(specs); + this.setAttribs(specs); } - attribValue(id: string, i: number): number | Vec { + attribValue(id: string, i: number): number | Vec | undefined { const spec = this.specs[id]; assert(!!spec, `invalid attrib: ${id}`); if (i >= this.capacity) return; - i *= spec.stride; + i *= spec.stride!; return spec.size > 1 ? this.attribs[id].subarray(i, i + spec.size) : this.attribs[id][i]; } *attribValues(id: string) { - const buf = this.attribs[id]; - assert(!!buf, `invalid attrib: ${id}`); const spec = this.specs[id]; - const stride = spec.stride; + assert(!!spec, `invalid attrib: ${id}`); + const buf = this.attribs[id]; + const stride = spec.stride!; const size = spec.size; if (size > 1) { for (let i = 0, j = 0, n = this.capacity; i < n; i++, j += stride) { @@ -112,12 +115,32 @@ export class AttribPool implements IRelease { } } + attribArray(id: string) { + const spec = this.specs[id]; + assert(!!spec, `invalid attrib: ${id}`); + const n = this.capacity; + const size = spec.size; + const stride = spec.stride!; + const src = this.attribs[id]; + const dest = new TYPEDARRAY_CTORS[(asNativeType(spec.type))](n * size); + if (size > 1) { + for (let i = 0, j = 0; i < n; i++, j += stride) { + dest.set(src.subarray(j, j + size), i * size); + } + } else { + for (let i = 0; i < n; i++) { + dest[i] = src[i * stride]; + } + } + return dest; + } + setAttribValue(id: string, index: number, v: number | ReadonlyVec) { const spec = this.specs[id]; assert(!!spec, `invalid attrib: ${id}`); this.ensure(index + 1); const buf = this.attribs[id]; - index *= spec.stride; + index *= spec.stride!; const isNum = typeof v === "number"; assert( () => (!isNum && spec.size > 1) || (isNum && spec.size === 1), @@ -137,17 +160,17 @@ export class AttribPool implements IRelease { return this; } - setAttribValues(id: string, vals: (number | ReadonlyVec)[]) { + setAttribValues(id: string, vals: ReadonlyVec | ReadonlyVec[], index = 0) { const spec = this.specs[id]; assert(!!spec, `invalid attrib: ${id}`); const n = vals.length; - const v = vals[0]; - const stride = spec.stride; - this.ensure(n); + this.ensure(index + n); + const stride = spec.stride!; const buf = this.attribs[id]; + const v = vals[0]; const isNum = typeof v === "number"; assert( - () => (!isNum && spec.size > 1) || (isNum && spec.size === 1), + (!isNum && spec.size > 1) || (isNum && spec.size === 1), `incompatible value(s) for attrib: ${id}` ); if (!isNum) { @@ -157,16 +180,27 @@ export class AttribPool implements IRelease { (v).length }` ); - for (let i = 0; i < n; i++) { - buf.set(vals[i], i * stride); + for (let i = 0, j = index * stride; i < n; i++, j += stride) { + buf.set(vals[i], j); } } else { - for (let i = 0; i < n; i++) { - buf[i * stride] = vals[i]; + for (let i = 0, j = index * stride; i < n; i++, j += stride) { + buf[j] = vals[i]; } } } + setAttribs( + specs: IObjectOf< + Partial<{ data: ReadonlyVec | ReadonlyVec[]; index: number }> + > + ) { + for (let id in specs) { + const spec = specs[id]; + spec.data && this.setAttribValues(id, spec.data, spec.index || 0); + } + } + removeAttrib(id: string) { if (!this.attribs[id]) return false; delete this.attribs[id]; @@ -191,7 +225,7 @@ export class AttribPool implements IRelease { asNativeType(a.type), this.pool.buf, newAddr + (a.byteOffset || 0), - (newCapacity - 1) * a.stride + a.size + (newCapacity - 1) * a.stride! + a.size ); buf.set(this.attribs[id]); this.attribs[id] = buf; @@ -261,7 +295,7 @@ export class AttribPool implements IRelease { asNativeType(a.type), this.pool.buf, this.addr + (a.byteOffset || 0), - (this.capacity - 1) * a.stride + a.size + (this.capacity - 1) * a.stride! + a.size ); } this.setDefaults(specs, start, end); @@ -276,7 +310,7 @@ export class AttribPool implements IRelease { const a = specs[id]; if (a.default == null) continue; const buf = this.attribs[id]; - const s = a.stride; + const s = a.stride!; const v = a.default; if (typeof v === "number") { for (let i = start; i < end; i++) { @@ -334,7 +368,7 @@ export class AttribPool implements IRelease { // ...in offset order to avoid successor attrib vals for (let id of order) { const a = specs[id]; - const sStride = a.stride; + const sStride = a.stride!; const src = attribs[id]; const [dest, dStride] = newAttribs[id]; if (typeof a.default === "number") { diff --git a/packages/vector-pools/src/convert.ts b/packages/vector-pools/src/convert.ts index fa136c76d6..7b03f0863c 100644 --- a/packages/vector-pools/src/convert.ts +++ b/packages/vector-pools/src/convert.ts @@ -14,10 +14,10 @@ import { GL2TYPE, GLType, TYPE2GL } from "./api"; */ export const asNativeType = (type: GLType | Type): Type => { const t = GL2TYPE[type]; - return t !== undefined ? t : type; + return t !== undefined ? t : type; }; export const asGLType = (type: GLType | Type): GLType => { const t = TYPE2GL[type]; - return t !== undefined ? t : type; + return t !== undefined ? t : type; }; diff --git a/packages/vector-pools/src/linked-list.ts b/packages/vector-pools/src/linked-list.ts index b515f52bdd..96bbb4d333 100644 --- a/packages/vector-pools/src/linked-list.ts +++ b/packages/vector-pools/src/linked-list.ts @@ -2,9 +2,16 @@ import { StridedVec, Vec } from "@thi.ng/vectors"; import { AVecList } from "./alist"; import { VecFactory } from "./api"; +interface Cell { + prev: CellVec | null; + next: CellVec | null; +} + +type CellVec = T & Cell; + export class VecLinkedList extends AVecList { - head: T; - tail: T; + head: CellVec | null; + tail: CellVec | null; readonly closed: boolean; protected _length: number; @@ -39,11 +46,11 @@ export class VecLinkedList extends AVecList { *[Symbol.iterator]() { if (this._length) { - let v: any = this.head; + let v = this.head; const first = v; do { - yield v; - v = v.next; + yield v!; + v = v!.next; } while (v && v !== first); } } @@ -53,15 +60,15 @@ export class VecLinkedList extends AVecList { } add(): T { - const v: any = this.alloc(); + const v = >this.alloc(); if (v) { if (this.tail) { v.prev = this.tail; - (this.tail).next = v; + this.tail.next = v; this.tail = v; if (this.closed) { v.next = this.head; - (this.head).prev = v; + this.head!.prev = v; } this._length++; } else { @@ -73,13 +80,13 @@ export class VecLinkedList extends AVecList { return v; } - insert(i: number): T { + insert(i: number): T | undefined { if (!this._length) { return i === 0 ? this.add() : undefined; } - const q: any = this.nth(i); + const q = >this.nth(i); if (!q) return; - const v: any = this.alloc(); + const v = >this.alloc(); if (v) { if (this.head === q) { this.head = v; @@ -99,7 +106,7 @@ export class VecLinkedList extends AVecList { if (this.has(vec)) { this._length--; this.freeIDs.push(vec.offset); - const v: any = vec; + const v = >vec; if (v.prev) { v.prev.next = v.next; } @@ -116,21 +123,22 @@ export class VecLinkedList extends AVecList { delete v.next; return true; } + return false; } has(value: T) { - let v: any = this.head; + let v = this.head; const first = v; do { if (v === value) { return true; } - v = v.next; + v = v!.next; } while (v && v !== first); return false; } - nth(n: number): T { + nth(n: number): T | undefined { if (n < 0) { n += this._length; } @@ -150,6 +158,6 @@ export class VecLinkedList extends AVecList { v = v.prev; } } - return v; + return v!; } } diff --git a/packages/vector-pools/src/vec-pool.ts b/packages/vector-pools/src/vec-pool.ts index 47c221aa5e..22ffce9c1b 100644 --- a/packages/vector-pools/src/vec-pool.ts +++ b/packages/vector-pools/src/vec-pool.ts @@ -1,7 +1,7 @@ import { Type, TypedArray } from "@thi.ng/api"; import { isTypedArray } from "@thi.ng/checks"; import { MemPool, MemPoolOpts, MemPoolStats } from "@thi.ng/malloc"; -import { IVector } from "@thi.ng/vectors"; +import { StridedVec } from "@thi.ng/vectors"; import { GLType, IVecPool } from "./api"; import { asNativeType } from "./convert"; import { wrap } from "./wrap"; @@ -19,7 +19,10 @@ export class VecPool implements IVecPool { return this.pool.stats(); } - malloc(size: number, type: GLType | Type = Type.F32): TypedArray { + malloc( + size: number, + type: GLType | Type = Type.F32 + ): TypedArray | undefined { return this.pool.callocAs(asNativeType(type), size); } @@ -27,9 +30,9 @@ export class VecPool implements IVecPool { size: number, stride = 1, type: GLType | Type = Type.F32 - ): IVector { + ): StridedVec | undefined { const buf = this.pool.callocAs(asNativeType(type), size * stride); - return wrap(buf, size, 0, stride); + return buf ? wrap(buf, size, 0, stride) : undefined; } /** @@ -62,20 +65,20 @@ export class VecPool implements IVecPool { cstride = 1, estride = size, type: GLType | Type = Type.F32 - ): IVector[] { + ): StridedVec[] | undefined { const buf = this.malloc( Math.max(cstride, estride, size) * num, asNativeType(type) ); if (!buf) return; - const res: IVector[] = []; + const res: StridedVec[] = []; for (let i = 0; i < num; i += estride) { res.push(wrap(buf, size, i, cstride)); } return res; } - free(vec: IVector | TypedArray) { + free(vec: StridedVec | TypedArray) { const buf = (vec).buf; return buf ? isTypedArray(buf) diff --git a/packages/vector-pools/test/attribs.ts b/packages/vector-pools/test/attribs.ts index de7275e318..5115a76708 100644 --- a/packages/vector-pools/test/attribs.ts +++ b/packages/vector-pools/test/attribs.ts @@ -1,6 +1,7 @@ import { Type } from "@thi.ng/api"; +import { equiv } from "@thi.ng/equiv"; +import * as assert from "assert"; import { AttribPool } from "../src/attrib-pool"; -// import * as assert from "assert"; describe("vector-pools", () => { it("attribs", () => { @@ -10,27 +11,66 @@ describe("vector-pools", () => { attribs: { pos: { type: Type.F32, - default: [0, 0], - size: 2, - byteOffset: 0 + size: 2, // 8 bytes + byteOffset: 0, + data: [[1, 2], [3, 4]] + }, + id: { + type: Type.U32, + size: 1, // 4 bytes + byteOffset: 8, + data: [1, 2], + index: 4 + }, + index: { + type: Type.U16, + size: 1, // 2 bytes + byteOffset: 12, + data: [10, 20] }, - id: { type: Type.U32, default: 0, size: 1, byteOffset: 8 }, - index: { type: Type.U16, default: 0, size: 1, byteOffset: 12 }, col: { - type: Type.I8, - default: [0, 0, 0, 0], - size: 4, - byteOffset: 14 + type: Type.U8, + size: 4, // 4 bytes + byteOffset: 14, + data: [[128, 129, 130, 131], [255, 254, 253, 252]], + index: 6 } } }); - pool.setAttribValue("pos", 0, [1, 2]); - pool.setAttribValue("id", 0, 1); - pool.setAttribValue("index", 0, 10); - pool.setAttribValue("col", 0, [128, 129, 130, 131]); - pool.setAttribValue("pos", 1, [3, 4]); - pool.setAttribValue("id", 1, 2); - pool.setAttribValue("index", 1, 20); - pool.setAttribValue("col", 1, [255, 254, 253, 252]); + assert( + equiv( + [...pool.attribValues("pos")], + [[1, 2], [3, 4], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0]] + ) + ); + assert(equiv([...pool.attribValues("id")], [0, 0, 0, 0, 1, 2, 0, 0])); + assert( + equiv([...pool.attribValues("index")], [10, 20, 0, 0, 0, 0, 0, 0]) + ); + assert( + equiv( + [...pool.attribValues("col")], + [ + [0, 0, 0, 0], + [0, 0, 0, 0], + [0, 0, 0, 0], + [0, 0, 0, 0], + [0, 0, 0, 0], + [0, 0, 0, 0], + [128, 129, 130, 131], + [255, 254, 253, 252] + ] + ) + ); + // prettier-ignore + assert( + equiv(pool.attribArray("pos"), + [1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) + ); + // prettier-ignore + assert( + equiv(pool.attribArray("index"), + [10, 20, 0, 0, 0, 0, 0, 0]) + ); }); }); diff --git a/packages/vector-pools/test/index.ts b/packages/vector-pools/test/index.ts deleted file mode 100644 index b8c58a8837..0000000000 --- a/packages/vector-pools/test/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -// import * as assert from "assert"; -// import * as vp from "../src/index"; - -describe("vector-pools", () => { - it("tests pending"); -}); diff --git a/packages/vectors/CHANGELOG.md b/packages/vectors/CHANGELOG.md index 9ead7b81cd..fa70205459 100644 --- a/packages/vectors/CHANGELOG.md +++ b/packages/vectors/CHANGELOG.md @@ -3,6 +3,47 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [3.0.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/vectors@2.5.6...@thi.ng/vectors@3.0.0) (2019-07-07) + + +### Bug Fixes + +* **vectors:** update arg types ([6d213bd](https://github.com/thi-ng/umbrella/commit/6d213bd)) + + +### Code Refactoring + +* **vectors:** fix [#95](https://github.com/thi-ng/umbrella/issues/95), update madd/maddN arg order, bug fixes ([020b4c8](https://github.com/thi-ng/umbrella/commit/020b4c8)) + + +### Features + +* **vectors:** add atan, exp_2, log_2, setVN, setVV, minor type fixes ([8683c19](https://github.com/thi-ng/umbrella/commit/8683c19)) +* **vectors:** add bitwise int vec ops (signed/unsigned versions) ([a364f1f](https://github.com/thi-ng/umbrella/commit/a364f1f)) +* **vectors:** add bvec types, componentwise logic & comparison ops ([7b9f03d](https://github.com/thi-ng/umbrella/commit/7b9f03d)) +* **vectors:** add degrees(), radians(), add fitXX type hints ([b313a56](https://github.com/thi-ng/umbrella/commit/b313a56)) +* **vectors:** add fmod/fmodN fns (GLSL style mod op) ([928b95b](https://github.com/thi-ng/umbrella/commit/928b95b)) +* **vectors:** add integer math ops (signed/unsigned) ([c8a997f](https://github.com/thi-ng/umbrella/commit/c8a997f)) +* **vectors:** add swizzle setters ([114003c](https://github.com/thi-ng/umbrella/commit/114003c)) +* **vectors:** add vecOf() ctor fn ([25feeee](https://github.com/thi-ng/umbrella/commit/25feeee)) +* **vectors:** enable TS strict compiler flags (refactor) ([94715ff](https://github.com/thi-ng/umbrella/commit/94715ff)) + + +### BREAKING CHANGES + +* **vectors:** update madd/maddN arg order, rename functions + +- madd & maddN args now OpenCL/CUDA compatible, i.e. + - madd(a,b,c) => a * b + c + - maddN(a,n,b) => a * n + b +- rename perpendicularLeft/Right => perpendicularCCW/CW +- rename normalLeft/Right => normalCCW/CW +- fix output vec handling in addW fns + + + + + ## [2.5.6](https://github.com/thi-ng/umbrella/compare/@thi.ng/vectors@2.5.5...@thi.ng/vectors@2.5.6) (2019-05-22) **Note:** Version bump only for package @thi.ng/vectors diff --git a/packages/vectors/README.md b/packages/vectors/README.md index b9f3104bc5..744343ac6b 100644 --- a/packages/vectors/README.md +++ b/packages/vectors/README.md @@ -16,6 +16,8 @@ This project is part of the - [Dependencies](#dependencies) - [Usage examples](#usage-examples) - [API](#api) + - [Breaking changes in v3.0.0](#breaking-changes-in-v300) + - [Naming conventions](#naming-conventions) - [Constants](#constants) - [Component setters & copying](#component-setters--copying) - [Component swizzling](#component-swizzling) @@ -35,6 +37,9 @@ This project is part of the - [Unary vector math ops](#unary-vector-math-ops) - [Vector array batch processing](#vector-array-batch-processing) - [Comparison / equality](#comparison--equality) + - [Bitwise operations (int / uint vec)](#bitwise-operations-int--uint-vec) + - [Boolean vector logic](#boolean-vector-logic) + - [Componentwise comparisons](#componentwise-comparisons) - [Hashing](#hashing) - [Code generator](#code-generator) - [Authors](#authors) @@ -44,17 +49,24 @@ This project is part of the ## About -This package provides 350+ largely code generated functions & supporting -types to perform vector operations on fixed and arbitrary-length -vectors, both packed and strided (i.e. where individual vector -components are not successive array elements, for example in SOA -layouts). +Likely the most comprehensive vector library for TypeScript / JavaScript +currently available. + +This package provides **600+ largely code generated functions** and +supporting types to perform vector operations on fixed and +arbitrary-length vectors, both packed and strided (i.e. where individual +vector components are not successive array elements, for example in SOA +memory layouts). + +Includes componentwise logic operations for boolean vectors, +componentwise comparisons for numeric vectors and componentwise binary +ops for signed & unsigned integer vectors. ### Features -- Small & fast: The vast majority of these functions are code generated - with fixed-sized versions not using any loops. Minified + gzipped, the - entire package is ~7.6KB. +- Small & fast: The vast majority of functions are code generated with + fixed-sized versions not using any loops. Minified + gzipped, the + entire package is ~9.2KB. - Unified API: Any `ArrayLike` type can be used as vector containers (e.g. JS arrays, typed arrays, custom impls). Most functions are implemented as multi-methods, dispatching to any potentially optimized @@ -96,6 +108,7 @@ layouts). - [@thi.ng/color](https://github.com/thi-ng/umbrella/tree/master/packages/color) - vector based color operations / conversions - [@thi.ng/geom](https://github.com/thi-ng/umbrella/tree/master/packages/geom) - 2D/3D geometry types & operations - [@thi.ng/matrices](https://github.com/thi-ng/umbrella/tree/master/packages/matrices) - 2x2, 2x3, 3x3, 4x4 matrix & quaternion ops +- [@thi.ng/shader-ast](https://github.com/thi-ng/umbrella/tree/master/packages/shader-ast) - [@thi.ng/vector-pools](https://github.com/thi-ng/umbrella/tree/master/packages/vector-pools) - operations on memory mapped data ## Installation @@ -128,12 +141,12 @@ a = [1, 2, 3]; v.add(null, a, a); // [2, 4, 6] -// multiply-add (o = a + b * c) -v.madd([], [1, 2], [10, 20], [0.5, 0.25]); +// multiply-add (o = a * b + c) +v.madd([], [10, 20], [0.5, 0.25], [1, 2]); // [6, 7] -// multiply-add w/ scalar (o = a + b * n) -v.maddN([], [1, 2], [10, 20], 0.5); +// multiply-add w/ scalar (o = a * n + b) +v.maddN([], [10, 20], 0.5, [1, 2]); // [6, 12] // scalar addition w/ arbitrary length & strided vector @@ -164,6 +177,60 @@ v.hash([1, 2, 3]) ## API +### Breaking changes in v3.0.0 + +- to avoid confusion, the arg order of `madd` and `maddN` functions has + been updated to be compatible with the OpenCL `mad` function + - `madd([], a, b, c)`: before `a + b * c`, now: `a * b + c` + - `maddN([], a, b, n)` => `maddN([], a, n, b)` (i.e. `a * n + b`) +- rename `perpendicularLeft2` => `perpendicularCCW` +- rename `perpendicularRight2` => `perpendicularCW` +- rename `normalLeft2`/ `normalRight2` => `normalCCW` / `normalCW` + +### Naming conventions + +Wherever possible, each operation comes in different variations. All +fixed size versions use optimized, loop-free implementations. + +| Suffix | Description | Example | +|-----------------|----------------------------------------|---------------------------------------------------| +| none | arbitrary length vector arg(s) | `add([], [1,2], [10,20])` | +| | | => `[11,22]` | +| 2 | 2d vector arg(s) | `add2([], [1,2], [10,20])` | +| | | => `[11,22]` | +| 3 | 3d vector arg(s) | `add3([], [1,2,3], [10,20,30])` | +| | | => `[11,22,33]` | +| 4 | 4d vector arg(s) | `add4([], [1,2,3,4], [10,20,30,40])` | +| | | => `[11,22,33,44]` | +| N2 | 2d vector & scalar | `addN2([], [1,2], 10)` | +| | | => `[11,12]` | +| N3 | 3d vector & scalar | `addN3([], [1,2,3], 10)` | +| | | => `[11,12,13]` | +| N4 | 4d vector & scalar | `addN4([], [1,2,3,4], 10)` | +| | | => `[11,12,13,14]` | +| I | arbitrary len, signed int vec | `addI([], [-1,2], [10,-20])` | +| | | => `[9,-18]` | +| U | arbitrary len, unsigned int vec | `addU([], [1,2], [10,20])` | +| | | => `[11,22]` | +| I2 / I3 / I4 | fixed size signed int vec | `bitnotI3([], [10,-20,30], [7,7,7])` | +| | | => `[-11,19,-31]` | +| U2 / U3 / U4 | fixed size signed int vec | `bitnotU3([], [10,20,30], [7,7,7])` | +| | | => `[4294967285,4294967275,4294967265]` | +| NI / NU | arbitrary len, signed int vec & scalar | `addNI([], [1,-2,3], 10)` | +| | | => `[11,8,13]` | +| NI2 / NI3 / NI4 | fixed size signed int vec & scalar | `addNI3([], [1,-2,3], 10)` | +| | | => `[11,8,13]` | +| NU2 / NU3 / NU4 | fixed size unsigned int vec & scalar | `addNU3([], [1,2,3], 10)` | +| | | => `[11,12,13]` | +| S2 / S3 / S4 | fixed size strided vec into unstrided | `addS2([], [0,1,0,2], [10,0,20,0], 0,1,0, 1,2,2)` | +| | | => `[11,22]` | +| SN2 / SN3 / SN4 | fixed size strided vec & scalar | `setSN2([0,0,0,0], 10, 1, 2)` | +| | | => `[0,10,0,10]` | +| C | arbitrary len vec, component wise args | `setC([], 1,2,3,4)` | +| | | => `[1,2,3,4]` | +| C2 / C3 / C4 | fixed size vec, component wise args | `setC4([], 1,2,3,4)` | +| | | => `[1,2,3,4]` | + ### Constants - `MAX2` / `MAX3` / `MAX4` - each component `+Infinity` @@ -190,11 +257,12 @@ v.hash([1, 2, 3]) ### Component swizzling - `swizzle2` / `swizzle3` / `swizzle4` +- `setSwizzle1` / `setSwizzle2` / `setSwizzle3` / `setSwizzle4` - `swapXY` / `swapXZ` / `swapYZ` ### Vector creation -Functions to create wrapped vector instances: +Functions to create wrapped (strided) vector instances: - `vec2` / `vec2n` - `vec3` / `vec3n` @@ -209,6 +277,9 @@ Vanilla vector (array) factories: - `ones` - `zeroes` +- `vecOf` +- `setVN3` / `setVN4` +- `setVV4` / `setVV6` / `setVV9` / `setVV16` ### Basic vector math @@ -220,9 +291,21 @@ Component wise op with 2 input vectors: - `div` / `div2` / `div3` / `div4` - `mul` / `mul2` / `mul3` / `mul4` - `sub` / `sub2` / `sub3` / `sub4` -- `mod` / `mod2` / `mod3` / `mod4` +- `fmod` / `fmod2` / `fmod3` / `fmod4` (GLSL behavior) +- `mod` / `mod2` / `mod3` / `mod4` (JS modulo) - `pow` / `pow2` / `pow3` / `pow4` +#### Integer vector + +- `addI` / `addI2` / `addI3` / `addI4` +- `addU` / `addU2` / `addU3` / `addU4` +- `divI` / `divI2` / `divI3` / `divI4` +- `divU` / `divU2` / `divU3` / `divU4` +- `mulI` / `mulI2` / `mulI3` / `mulI4` +- `mulU` / `mulU2` / `mulU3` / `mulU4` +- `subI` / `subI2` / `subI3` / `subI4` +- `subU` / `subU2` / `subU3` / `subU4` + #### Vector / scalar Component wise op with one input vector and single scalar: @@ -232,9 +315,21 @@ Component wise op with one input vector and single scalar: - `mulN` / `mulN2` / `mulN3` / `mulN4` - `subN` / `subN2` / `subN3` / `subN4` - `neg` - same as `mulN(out, v, -1)` -- `modN` / `modN2` / `modN3` / `modN4` +- `fmodN` / `fmodN2` / `fmodN3` / `fmodN4` (GLSL behavior) +- `modN` / `modN2` / `modN3` / `modN4` (JS modulo) - `powN` / `powN2` / `powN3` / `powN4` +#### Integer vector / scalar + +- `addNI` / `addNI2` / `addNI3` / `addNI4` +- `addNU` / `addNU2` / `addNU3` / `addNU4` +- `divNI` / `divNI2` / `divNI3` / `divNI4` +- `divNU` / `divNU2` / `divNU3` / `divNU4` +- `mulNI` / `mulNI2` / `mulNI3` / `mulNI4` +- `mulNU` / `mulNU2` / `mulNU3` / `mulNU4` +- `subNI` / `subNI2` / `subNI3` / `subNI4` +- `subNU` / `subNU2` / `subNU3` / `subNU4` + #### Strided vectors Functions for memory mapped, strided vectors (without requiring wrappers): @@ -310,6 +405,7 @@ Functions for memory mapped, strided vectors (without requiring wrappers): - `angleBetween2` / `angleBetween3` - `angleRatio` - `bisect2` +- `degrees` / `degrees2` / `degrees3` / `degrees4` - `direction` - `faceForward` - `heading` / `headingXY` / `headingXZ` / `headingYZ` @@ -317,6 +413,7 @@ Functions for memory mapped, strided vectors (without requiring wrappers): - `normalLeft2` / `normalRight2` - `perpendicularLeft2` / `perpendicularRight2` - `project` +- `radians` / `radians2` / `radians3` / `radians4` - `reflect` - `refract` @@ -350,11 +447,13 @@ All ops support custom PRNG impls based on the - `abs` / `abs2` / `abs3` / `abs4` - `acos` / `acos2` / `acos3` / `acos4` - `asin` / `asin2` / `asin3` / `asin4` +- `atan` / `atan2` / `atan3` / `atan4` - `ceil` / `ceil2` / `ceil3` / `ceil4` - `cos` / `cos2` / `cos3` / `cos4` - `cosh` / `cosh2` / `cosh3` / `cosh4` - `exp` / `exp2` / `exp3` / `exp4` - `floor` / `floor2` / `floor3` / `floor4` +- `fmod` / `fmod2` / `fmod3` / `fmod4` (C / GLSL modulo) - `fract` / `fract2` / `fract3` / `fract4` - `fromHomogeneous` / `fromHomogeneous3` / `fromHomogeneous4` - `invert` / `invert2` / `invert3` / `invert4` @@ -362,6 +461,7 @@ All ops support custom PRNG impls based on the - `log` / `log2` / `log3` / `log4` - `major` / `major2` / `major3` / `major4` - `minor` / `minor2` / `minor3` / `minor4` +- `mod` / `mod2` / `mod3` / `mod4` (JS modulo) - `round` / `round2` / `round3` / `round4` - `sign` / `sign2` / `sign3` / `sign4` - `sin` / `sin2` / `sin3` / `sin4` @@ -386,6 +486,47 @@ Functions to transform flat / strided buffers w/ vector operations: - `eqDeltaS` - `eqDeltaArray` +### Bitwise operations (int / uint vec) + +Arguments are assumed to be signed / unsigned ints. Results will be +forced accordingly. + +- `bitAndI` / `bitAndI2` / `bitAndI3` / `bitAndI4` +- `bitAndU` / `bitAndU2` / `bitAndU3` / `bitAndU4` +- `bitAndNI` / `bitAndNI2` / `bitAndNI3` / `bitAndNI4` +- `bitAndNU` / `bitAndNU2` / `bitAndNU3` / `bitAndNU4` +- `bitNotI` / `bitNotI2` / `bitNotI3` / `bitNotI4` (unary) +- `bitNotU` / `bitNotU2` / `bitNotU3` / `bitNotU4` (unary) +- `bitOrI` / `bitOrI2` / `bitOrI3` / `bitOrI4` +- `bitOrU` / `bitOrU2` / `bitOrU3` / `bitOrU4` +- `bitOrNI` / `bitOrNI2` / `bitOrNI3` / `bitOrNI4` +- `bitOrNU` / `bitOrNU2` / `bitOrNU3` / `bitOrNU4` +- `bitXorI` / `bitXorI2` / `bitXorI3` / `bitXorI4` +- `bitXorU` / `bitXorU2` / `bitXorU3` / `bitXorU4` +- `bitXorNI` / `bitXorNI2` / `bitXorNI3` / `bitXorNI4` +- `bitXorNU` / `bitXorNU2` / `bitXorNU3` / `bitXorNU4` +- `lshiftI` / `lshiftI4` /`lshiftI4` / `lshiftI4` +- `lshiftU` / `lshiftU4` /`lshiftU4` / `lshiftU4` +- `rshiftI` / `rshiftI2` /`rshiftI3` / `rshiftI4` +- `rshiftU` / `rshiftU2` /`rshiftU3` / `rshiftU4` + +### Boolean vector logic + +- `logicAnd` / `logicAnd2` / `logicAnd3` / `logicAnd4` +- `logicOr` / `logicOr2` / `logicOr3` / `logicOr4` +- `logicNot` / `logicNot2` / `logicNot3` / `logicNot4` + +### Componentwise comparisons + +All resulting in boolean vectors: + +- `lt` / `lt2` / `lt3`/ `lt4` +- `lte` / `lte2` / `lte3`/ `lte4` +- `gt` / `gt2` / `gt3`/ `gt4` +- `gte` / `gte2` / `gte3`/ `gte4` +- `eq` / `eq2` / `eq3`/ `eq4` +- `neq` / `neq2` / `neq3`/ `neq4` + ### Hashing - `hash` diff --git a/packages/vectors/package.json b/packages/vectors/package.json index cd1fc1dc8c..db13921454 100644 --- a/packages/vectors/package.json +++ b/packages/vectors/package.json @@ -1,6 +1,6 @@ { "name": "@thi.ng/vectors", - "version": "2.5.6", + "version": "3.0.0", "description": "Optimized 2d/3d/4d and arbitrary length vector operations", "module": "./index.js", "main": "./lib/index.js", @@ -25,22 +25,22 @@ }, "devDependencies": { "@types/mocha": "^5.2.6", - "@types/node": "^11.13.7", + "@types/node": "^12.0.8", "mocha": "^6.1.4", "nyc": "^14.0.0", "typedoc": "^0.14.2", - "typescript": "^3.4.5" + "typescript": "^3.5.2" }, "dependencies": { - "@thi.ng/api": "^6.2.0", - "@thi.ng/binary": "^1.0.6", - "@thi.ng/checks": "^2.1.6", - "@thi.ng/equiv": "^1.0.6", - "@thi.ng/errors": "^1.0.6", - "@thi.ng/math": "^1.3.0", - "@thi.ng/memoize": "^1.0.9", - "@thi.ng/random": "^1.1.7", - "@thi.ng/transducers": "^5.3.7" + "@thi.ng/api": "^6.3.0", + "@thi.ng/binary": "^1.0.7", + "@thi.ng/checks": "^2.2.0", + "@thi.ng/equiv": "^1.0.7", + "@thi.ng/errors": "^1.1.0", + "@thi.ng/math": "^1.4.0", + "@thi.ng/memoize": "^1.1.0", + "@thi.ng/random": "^1.1.8", + "@thi.ng/transducers": "^5.4.0" }, "keywords": [ "2D", diff --git a/packages/vectors/src/addi.ts b/packages/vectors/src/addi.ts new file mode 100644 index 0000000000..c7658b71c5 --- /dev/null +++ b/packages/vectors/src/addi.ts @@ -0,0 +1,9 @@ +import { defBitOp, defBitOpN } from "./internal/codegen"; + +export const [addI, addI2, addI3, addI4] = defBitOp("+", true); + +export const [addU, addU2, addU3, addU4] = defBitOp("+"); + +export const [addNI, addNI2, addNI3, addNI4] = defBitOpN("+", true); + +export const [addNU, addNU2, addNU3, addNU4] = defBitOpN("+"); diff --git a/packages/vectors/src/addm.ts b/packages/vectors/src/addm.ts index 02374b306e..5dbb43a2e2 100644 --- a/packages/vectors/src/addm.ts +++ b/packages/vectors/src/addm.ts @@ -6,6 +6,7 @@ import { ADDM } from "./internal/templates"; * Returns `out = (a + b) * c`. * * @see madd + * @see subm */ export const [addm, addm2, addm3, addm4] = defOp( ADDM, diff --git a/packages/vectors/src/addn.ts b/packages/vectors/src/addn.ts index 9c4c98b0fa..b0ea2a2e0b 100644 --- a/packages/vectors/src/addn.ts +++ b/packages/vectors/src/addn.ts @@ -1,3 +1,3 @@ -import { defMathNOp } from "./internal/codegen"; +import { defMathOpN } from "./internal/codegen"; -export const [addN, addN2, addN3, addN4] = defMathNOp("+"); +export const [addN, addN2, addN3, addN4] = defMathOpN("+"); diff --git a/packages/vectors/src/addw.ts b/packages/vectors/src/addw.ts index d49e85ccf9..23199ad2b4 100644 --- a/packages/vectors/src/addw.ts +++ b/packages/vectors/src/addw.ts @@ -3,25 +3,27 @@ import { maddN } from "./maddn"; import { mulN } from "./muln"; export const addW2 = ( - out: Vec, + out: Vec | null, a: ReadonlyVec, b: ReadonlyVec, wa: number, wb: number -) => maddN(out, mulN(out, a, wa), b, wb); +) => (!out && (out = a), maddN(out, b, wb, mulN(out, a, wa))); export const addW3 = ( - out: Vec, + out: Vec | null, a: ReadonlyVec, b: ReadonlyVec, c: ReadonlyVec, wa: number, wb: number, wc: number -) => maddN(out, maddN(out, mulN(out, a, wa), b, wb), c, wc); +) => ( + !out && (out = a), maddN(out, c, wc, maddN(out, b, wb, mulN(out, a, wa))) +); export const addW4 = ( - out: Vec, + out: Vec | null, a: ReadonlyVec, b: ReadonlyVec, c: ReadonlyVec, @@ -30,10 +32,13 @@ export const addW4 = ( wb: number, wc: number, wd: number -) => maddN(out, maddN(out, maddN(out, mulN(out, a, wa), b, wb), c, wc), d, wd); +) => ( + !out && (out = a), + maddN(out, d, wd, maddN(out, c, wc, maddN(out, b, wb, mulN(out, a, wa)))) +); export const addW5 = ( - out: Vec, + out: Vec | null, a: ReadonlyVec, b: ReadonlyVec, c: ReadonlyVec, @@ -44,15 +49,17 @@ export const addW5 = ( wc: number, wd: number, we: number -) => +) => ( + !out && (out = a), maddN( out, + e, + we, maddN( out, - maddN(out, maddN(out, mulN(out, a, wa), b, wb), c, wc), d, - wd - ), - e, - we - ); + wd, + maddN(out, c, wc, maddN(out, b, wb, mulN(out, a, wa))) + ) + ) +); diff --git a/packages/vectors/src/api.ts b/packages/vectors/src/api.ts index bfb7f622dc..1773d9a605 100644 --- a/packages/vectors/src/api.ts +++ b/packages/vectors/src/api.ts @@ -17,11 +17,19 @@ export interface Vec extends Iterable, ILength { [id: number]: number; } +export interface BVec extends Iterable, ILength { + [id: number]: boolean; +} + export type ReadonlyVec = ArrayLikeIterable; +export type ReadonlyBVec = ArrayLikeIterable; export type Vec2Like = Tuple | TypedArray; export type Vec3Like = Tuple | TypedArray; export type Vec4Like = Tuple | TypedArray; +export type BVec2Like = Tuple; +export type BVec3Like = Tuple; +export type BVec4Like = Tuple; export interface StridedVec { buf: Vec; @@ -52,15 +60,22 @@ export interface MultiVecOp { export type VecPair = [Vec, Vec]; -export type VecOpV = Fn2; -export type VecOpN = Fn2; -export type VecOpVV = Fn3; -export type VecOpVN = Fn3; -export type VecOpVVV = Fn4; -export type VecOpVVN = Fn4; -export type VecOpVNN = Fn4; +export type VecOpV = Fn2; +export type VecOpN = Fn2; +export type VecOpVV = Fn3; +export type VecOpVN = Fn3; +export type VecOpVVV = Fn4< + Vec | null, + ReadonlyVec, + ReadonlyVec, + ReadonlyVec, + Vec +>; +export type VecOpVVN = Fn4; +export type VecOpVNV = Fn4; +export type VecOpVNN = Fn4; export type VecOpVVVVNN = Fn7< - Vec, + Vec | null, ReadonlyVec, ReadonlyVec, ReadonlyVec, @@ -70,17 +85,17 @@ export type VecOpVVVVNN = Fn7< Vec >; -export type VecOpVO = (out: Vec, a: ReadonlyVec, b?: T) => Vec; -export type VecOpOO = (out: Vec, a?: A, b?: B) => Vec; -export type VecOpOOO = (out: Vec, a?: A, b?: B, c?: C) => Vec; -export type VecOpNNO = (out: Vec, a: number, b: number, c?: T) => Vec; +export type VecOpVO = (out: Vec | null, a: ReadonlyVec, b?: T) => Vec; +export type VecOpOO = (out: Vec | null, a?: A, b?: B) => Vec; +export type VecOpOOO = (out: Vec | null, a?: A, b?: B, c?: C) => Vec; +export type VecOpNNO = (out: Vec | null, a: number, b: number, c?: T) => Vec; export type VecOpRoV = Fn; export type VecOpRoVV = Fn2; export type VecOpRoVVO = (a: ReadonlyVec, b: ReadonlyVec, c?: O) => T; export type VecOpSV = ( - out: Vec, + out: Vec | null, a: ReadonlyVec, io?: number, ia?: number, @@ -88,7 +103,7 @@ export type VecOpSV = ( sa?: number ) => Vec; export type VecOpSVV = ( - out: Vec, + out: Vec | null, a: ReadonlyVec, b: ReadonlyVec, io?: number, @@ -113,6 +128,7 @@ export interface MultiVecOpVV extends VecOpVV, MultiVecOp {} export interface MultiVecOpVN extends VecOpVN, MultiVecOp {} export interface MultiVecOpVVV extends VecOpVVV, MultiVecOp {} export interface MultiVecOpVVN extends VecOpVVN, MultiVecOp {} +export interface MultiVecOpVNV extends VecOpVNV, MultiVecOp {} export interface MultiVecOpVNN extends VecOpVNN, MultiVecOp {} export interface MultiVecOpVVVVNN extends VecOpVVVVNN, @@ -139,29 +155,40 @@ export interface MultiVecOpRoVVO extends VecOpRoVVO, MultiVecOp> {} +export type BVecOpV = Fn2; +export type BVecOpVV = Fn3; + +export type CompareOp = Fn3; + +export interface MultiBVecOpV extends BVecOpV, MultiVecOp {} +export interface MultiBVecOpVV extends BVecOpVV, MultiVecOp {} +export interface MultiCompareOp extends CompareOp, MultiVecOp {} + const mi = -Infinity; const mx = Infinity; -export const MIN2 = Object.freeze([mi, mi]); -export const MAX2 = Object.freeze([mx, mx]); -export const ONE2 = Object.freeze([1, 1]); -export const ZERO2 = Object.freeze([0, 0]); -export const X2 = Object.freeze([1, 0]); -export const Y2 = Object.freeze([0, 1]); - -export const MIN3 = Object.freeze([mi, mi, mi]); -export const MAX3 = Object.freeze([mx, mx, mx]); -export const ONE3 = Object.freeze([1, 1, 1]); -export const ZERO3 = Object.freeze([0, 0, 0]); -export const X3 = Object.freeze([1, 0, 0]); -export const Y3 = Object.freeze([0, 1, 0]); -export const Z3 = Object.freeze([0, 0, 1]); - -export const MIN4 = Object.freeze([mi, mi, mi, mi]); -export const MAX4 = Object.freeze([mx, mx, mx, mx]); -export const ONE4 = Object.freeze([1, 1, 1, 1]); -export const ZERO4 = Object.freeze([0, 0, 0, 0]); -export const X4 = Object.freeze([1, 0, 0, 0]); -export const Y4 = Object.freeze([0, 1, 0, 0]); -export const Z4 = Object.freeze([0, 0, 1, 0]); -export const W4 = Object.freeze([0, 0, 0, 1]); +export const MIN2: ReadonlyVec = Object.freeze([mi, mi]); +export const MAX2: ReadonlyVec = Object.freeze([mx, mx]); +export const ONE2: ReadonlyVec = Object.freeze([1, 1]); +export const ZERO2: ReadonlyVec = Object.freeze([0, 0]); +export const X2: ReadonlyVec = Object.freeze([1, 0]); +export const Y2: ReadonlyVec = Object.freeze([0, 1]); + +export const MIN3: ReadonlyVec = Object.freeze([mi, mi, mi]); +export const MAX3: ReadonlyVec = Object.freeze([mx, mx, mx]); +export const ONE3: ReadonlyVec = Object.freeze([1, 1, 1]); +export const ZERO3: ReadonlyVec = Object.freeze([0, 0, 0]); +export const X3: ReadonlyVec = Object.freeze([1, 0, 0]); +export const Y3: ReadonlyVec = Object.freeze([0, 1, 0]); +export const Z3: ReadonlyVec = Object.freeze([0, 0, 1]); + +export const MIN4: ReadonlyVec = Object.freeze([mi, mi, mi, mi]); +export const MAX4: ReadonlyVec = Object.freeze([mx, mx, mx, mx]); +export const ONE4: ReadonlyVec = Object.freeze([1, 1, 1, 1]); +export const ZERO4: ReadonlyVec = Object.freeze([0, 0, 0, 0]); +export const X4: ReadonlyVec = Object.freeze([1, 0, 0, 0]); +export const Y4: ReadonlyVec = Object.freeze([0, 1, 0, 0]); +export const Z4: ReadonlyVec = Object.freeze([0, 0, 1, 0]); +export const W4: ReadonlyVec = Object.freeze([0, 0, 0, 1]); + +export type Template = (syms: string[], i?: number) => string; diff --git a/packages/vectors/src/atan.ts b/packages/vectors/src/atan.ts new file mode 100644 index 0000000000..690649bef4 --- /dev/null +++ b/packages/vectors/src/atan.ts @@ -0,0 +1,6 @@ +import { MultiVecOpV, VecOpV } from "./api"; +import { defFnOp } from "./internal/codegen"; + +export const [atan, atan2, atan3, atan4] = defFnOp( + "Math.atan" +); diff --git a/packages/vectors/src/bit-and.ts b/packages/vectors/src/bit-and.ts new file mode 100644 index 0000000000..de955dc42c --- /dev/null +++ b/packages/vectors/src/bit-and.ts @@ -0,0 +1,9 @@ +import { defBitOp, defBitOpN } from "./internal/codegen"; + +export const [bitAndI, bitAndI2, bitAndI3, bitAndI4] = defBitOp("&", true); + +export const [bitAndU, bitAndU2, bitAndU3, bitAndU4] = defBitOp("&"); + +export const [bitAndNI, bitAndNI2, bitAndNI3, bitAndNI4] = defBitOpN("&", true); + +export const [bitAndNU, bitAndNU2, bitAndNU3, bitAndNU4] = defBitOpN("&"); diff --git a/packages/vectors/src/bit-not.ts b/packages/vectors/src/bit-not.ts new file mode 100644 index 0000000000..dc1f155dd3 --- /dev/null +++ b/packages/vectors/src/bit-not.ts @@ -0,0 +1,11 @@ +import { MultiVecOpV, VecOpV } from "./api"; +import { ARGS_V, defOp } from "./internal/codegen"; + +export const [bitNotI, bitNotI2, bitNotI3, bitNotI4] = defOp< + MultiVecOpV, + VecOpV +>(([o, a]) => `${o}=(~${a})|0;`, ARGS_V); +export const [bitNotU, bitNotU2, bitNotU3, bitNotU4] = defOp< + MultiVecOpV, + VecOpV +>(([o, a]) => `${o}=(~${a})>>>0;`, ARGS_V); diff --git a/packages/vectors/src/bit-or.ts b/packages/vectors/src/bit-or.ts new file mode 100644 index 0000000000..fb3d5f5bd1 --- /dev/null +++ b/packages/vectors/src/bit-or.ts @@ -0,0 +1,9 @@ +import { defBitOp, defBitOpN } from "./internal/codegen"; + +export const [bitOrI, bitOrI2, bitOrI3, bitOrI4] = defBitOp("|", true); + +export const [bitOrU, bitOrU2, bitOrU3, bitOrU4] = defBitOp("|"); + +export const [bitOrNI, bitOrNI2, bitOrNI3, bitOrNI4] = defBitOpN("|", true); + +export const [bitOrNU, bitOrNU2, bitOrNU3, bitOrNU4] = defBitOpN("|"); diff --git a/packages/vectors/src/bit-xor.ts b/packages/vectors/src/bit-xor.ts new file mode 100644 index 0000000000..8fa58cc993 --- /dev/null +++ b/packages/vectors/src/bit-xor.ts @@ -0,0 +1,9 @@ +import { defBitOp, defBitOpN } from "./internal/codegen"; + +export const [bitXorI, bitXorI2, bitXorI3, bitXorI4] = defBitOp("^", true); + +export const [bitXorU, bitXorU2, bitXorU3, bitXorU4] = defBitOp("^"); + +export const [bitXorNI, bitXorNI2, bitXorNI3, bitXorNI4] = defBitOpN("^", true); + +export const [bitXorNU, bitXorNU2, bitXorNU3, bitXorNU4] = defBitOpN("^"); diff --git a/packages/vectors/src/cartesian.ts b/packages/vectors/src/cartesian.ts index 05e1a18241..3c80cd44c2 100644 --- a/packages/vectors/src/cartesian.ts +++ b/packages/vectors/src/cartesian.ts @@ -1,5 +1,10 @@ import { cossin } from "@thi.ng/math"; -import { MultiVecOpVO, ReadonlyVec, ZERO2, ZERO3 } from "./api"; +import { + MultiVecOpVO, + ReadonlyVec, + ZERO2, + ZERO3 +} from "./api"; import { vop } from "./internal/vop"; import { maddN2 } from "./maddn"; import { setC3 } from "./setc"; @@ -28,7 +33,7 @@ export const cartesian: MultiVecOpVO = vop(1); * @param offset */ export const cartesian2 = cartesian.add(2, (out, a, b = ZERO2) => - maddN2(out || a, b, cossin(a[1]), a[0]) + maddN2(out || a, cossin(a[1]), a[0], b) ); /** diff --git a/packages/vectors/src/clamp.ts b/packages/vectors/src/clamp.ts index 1594435728..db37df63cf 100644 --- a/packages/vectors/src/clamp.ts +++ b/packages/vectors/src/clamp.ts @@ -1,23 +1,19 @@ -import { - clamp as _clamp, - clamp01 as _clamp01, - clamp11 as _clamp11 -} from "@thi.ng/math"; +import { clamp as _clamp, clamp01 as _clamp01, clamp11 as _clamp11 } from "@thi.ng/math"; import { MultiVecOpVVV, VecOpVVV } from "./api"; import { ARGS_VVV, defHofOp } from "./internal/codegen"; -import { HOF_VVV } from "./internal/templates"; +import { FN3 } from "./internal/templates"; export const [clamp, clamp2, clamp3, clamp4] = defHofOp< MultiVecOpVVV, VecOpVVV ->(_clamp, HOF_VVV, ARGS_VVV); +>(_clamp, FN3(), ARGS_VVV); export const [clamp01, clamp01_2, clamp01_3, clamp01_4] = defHofOp< MultiVecOpVVV, VecOpVVV ->(_clamp01, HOF_VVV, ARGS_VVV); +>(_clamp01, FN3(), ARGS_VVV); export const [clamp11, clamp11_2, clamp11_3, clamp11_4] = defHofOp< MultiVecOpVVV, VecOpVVV ->(_clamp11, HOF_VVV, ARGS_VVV); +>(_clamp11, FN3(), ARGS_VVV); diff --git a/packages/vectors/src/cross.ts b/packages/vectors/src/cross.ts index 641e66a651..3e3f6f96b8 100644 --- a/packages/vectors/src/cross.ts +++ b/packages/vectors/src/cross.ts @@ -4,7 +4,7 @@ import { setC3 } from "./setc"; export const cross2 = (a: ReadonlyVec, b: ReadonlyVec) => a[0] * b[1] - a[1] * b[0]; -export const cross3 = (out: Vec, a: ReadonlyVec, b: ReadonlyVec) => +export const cross3 = (out: Vec | null, a: ReadonlyVec, b: ReadonlyVec) => setC3( out || a, a[1] * b[2] - a[2] * b[1], diff --git a/packages/vectors/src/degrees.ts b/packages/vectors/src/degrees.ts new file mode 100644 index 0000000000..a04c7d0375 --- /dev/null +++ b/packages/vectors/src/degrees.ts @@ -0,0 +1,11 @@ +import { deg } from "@thi.ng/math"; +import { MultiVecOpV, VecOpV } from "./api"; +import { defHofOp } from "./internal/codegen"; +import { FN } from "./internal/templates"; + +export const [degrees, degrees2, degrees3, degrees4]: [ + MultiVecOpV, + VecOpV, + VecOpV, + VecOpV +] = defHofOp(deg, FN("op")); diff --git a/packages/vectors/src/direction.ts b/packages/vectors/src/direction.ts index 577af5e55a..3af041ff53 100644 --- a/packages/vectors/src/direction.ts +++ b/packages/vectors/src/direction.ts @@ -10,5 +10,9 @@ import { sub } from "./sub"; * @param b * @param n */ -export const direction = (out: Vec, a: ReadonlyVec, b: ReadonlyVec, n = 1) => - normalize(null, sub(out || a, b, a), n); +export const direction = ( + out: Vec | null, + a: ReadonlyVec, + b: ReadonlyVec, + n = 1 +) => normalize(null, sub(out || a, b, a), n); diff --git a/packages/vectors/src/dist-chebyshev.ts b/packages/vectors/src/dist-chebyshev.ts index f1c72cde98..01df14ea89 100644 --- a/packages/vectors/src/dist-chebyshev.ts +++ b/packages/vectors/src/dist-chebyshev.ts @@ -10,7 +10,7 @@ const $ = (dim: number) => ([a, b]) => `Math.abs(${a}-${b})`, "a,b", undefined, - null, + "", ",", "return Math.max(", ");" diff --git a/packages/vectors/src/dist-manhattan.ts b/packages/vectors/src/dist-manhattan.ts index 62ee55eb89..b5919a4ac0 100644 --- a/packages/vectors/src/dist-manhattan.ts +++ b/packages/vectors/src/dist-manhattan.ts @@ -10,7 +10,7 @@ const $ = (dim: number) => ([a, b]) => `Math.abs(${a}-${b})`, "a,b", undefined, - null, + "", "+", "return ", ";" diff --git a/packages/vectors/src/distsq.ts b/packages/vectors/src/distsq.ts index 0d554ce904..99ef397b74 100644 --- a/packages/vectors/src/distsq.ts +++ b/packages/vectors/src/distsq.ts @@ -1,8 +1,8 @@ -import { MultiVecOpRoVV } from "./api"; +import { MultiVecOpRoVV, Template } from "./api"; import { compile, compileG } from "./internal/codegen"; import { vop } from "./internal/vop"; -const tpl = ([a, b]) => `t=${a}-${b};s+=t*t;`; +const tpl: Template = ([a, b]) => `t=${a}-${b};s+=t*t;`; const pre = "let t,s=0;"; const $ = (dim: number) => diff --git a/packages/vectors/src/divi.ts b/packages/vectors/src/divi.ts new file mode 100644 index 0000000000..dee0279eeb --- /dev/null +++ b/packages/vectors/src/divi.ts @@ -0,0 +1,9 @@ +import { defBitOp, defBitOpN } from "./internal/codegen"; + +export const [divI, divI2, divI3, divI4] = defBitOp("/", true); + +export const [divU, divU2, divU3, divU4] = defBitOp("/"); + +export const [divNI, divNI2, divNI3, divNI4] = defBitOpN("/", true); + +export const [divNU, divNU2, divNU3, divNU4] = defBitOpN("/"); diff --git a/packages/vectors/src/divn.ts b/packages/vectors/src/divn.ts index 4ba8f37dbb..4d3c1454d6 100644 --- a/packages/vectors/src/divn.ts +++ b/packages/vectors/src/divn.ts @@ -1,3 +1,3 @@ -import { defMathNOp } from "./internal/codegen"; +import { defMathOpN } from "./internal/codegen"; -export const [divN, divN2, divN3, divN4] = defMathNOp("/"); +export const [divN, divN2, divN3, divN4] = defMathOpN("/"); diff --git a/packages/vectors/src/dot.ts b/packages/vectors/src/dot.ts index 5505778c5c..18d2ac6c42 100644 --- a/packages/vectors/src/dot.ts +++ b/packages/vectors/src/dot.ts @@ -4,10 +4,7 @@ import { DOT, DOT_G } from "./internal/templates"; import { vop } from "./internal/vop"; const $ = (dim: number) => - dot.add( - dim, - compile(dim, DOT, "a,b", undefined, null, "+", "return ", ";") - ); + dot.add(dim, compile(dim, DOT, "a,b", undefined, "", "+", "return ", ";")); export const dot: MultiVecOpRoVV = vop(); diff --git a/packages/vectors/src/dots.ts b/packages/vectors/src/dots.ts index df74cb375f..8b58a23229 100644 --- a/packages/vectors/src/dots.ts +++ b/packages/vectors/src/dots.ts @@ -3,7 +3,7 @@ import { compile, SARGS_V } from "./internal/codegen"; import { DOT } from "./internal/templates"; const $ = (dim: number): VecOpSRoVV => - compile(dim, DOT, `o,a,${SARGS_V}`, "o,a", null, "+", "return ", ";", true); + compile(dim, DOT, `o,a,${SARGS_V}`, "o,a", "", "+", "return ", ";", true); export const dotS2 = $(2); export const dotS3 = $(3); diff --git a/packages/vectors/src/eq.ts b/packages/vectors/src/eq.ts new file mode 100644 index 0000000000..ef02f9190d --- /dev/null +++ b/packages/vectors/src/eq.ts @@ -0,0 +1,7 @@ +import { CompareOp, MultiCompareOp } from "./api"; +import { defOp } from "./internal/codegen"; +import { MATH } from "./internal/templates"; + +export const [eq, eq2, eq3, eq4] = defOp( + MATH("===") +); diff --git a/packages/vectors/src/eqdelta.ts b/packages/vectors/src/eqdelta.ts index 8b779cce71..e46876a2d3 100644 --- a/packages/vectors/src/eqdelta.ts +++ b/packages/vectors/src/eqdelta.ts @@ -4,7 +4,7 @@ import { MultiVecOpRoVVO, ReadonlyVec } from "./api"; import { compileHOF } from "./internal/codegen"; import { vop } from "./internal/vop"; -const $ = (dim) => +const $ = (dim: number) => eqDelta.add( dim, compileHOF( @@ -14,7 +14,7 @@ const $ = (dim) => "eq,_eps", "a,b,eps=_eps", "a,b", - null, + "", "&&", "return a.length === b.length && ", ";" diff --git a/packages/vectors/src/exp_2.ts b/packages/vectors/src/exp_2.ts new file mode 100644 index 0000000000..e18879f4a7 --- /dev/null +++ b/packages/vectors/src/exp_2.ts @@ -0,0 +1,10 @@ +import { MultiVecOpV, VecOpV } from "./api"; +import { ARGS_V, defOp } from "./internal/codegen"; + +/** + * Componentwise 2^x + */ +export const [exp_2, exp_22, exp_23, exp_24] = defOp( + ([o, a]) => `${o}=Math.pow(2,${a});`, + ARGS_V +); diff --git a/packages/vectors/src/fit.ts b/packages/vectors/src/fit.ts index e5d6894bfc..84e2e92b55 100644 --- a/packages/vectors/src/fit.ts +++ b/packages/vectors/src/fit.ts @@ -1,17 +1,20 @@ import { fit as _fit, fit01 as _fit01, fit11 as _fit11 } from "@thi.ng/math"; +import { MultiVecOpVVV, VecOpVVV } from "./api"; import { ARGS_VVV, defHofOp } from "./internal/codegen"; -import { HOF_VVV, HOF_VVVVV } from "./internal/templates"; +import { FN3, FN5 } from "./internal/templates"; -export const [fit, fit2, fit3, fit4] = defHofOp(_fit, HOF_VVVVV, "o,a,b,c,d,e"); +export const [fit, fit2, fit3, fit4] = defHofOp(_fit, FN5(), "o,a,b,c,d,e"); -export const [fit01, fit01_2, fit01_3, fit01_4] = defHofOp( - _fit01, - HOF_VVV, - ARGS_VVV -); +export const [fit01, fit01_2, fit01_3, fit01_4]: [ + MultiVecOpVVV, + VecOpVVV, + VecOpVVV, + VecOpVVV +] = defHofOp(_fit01, FN3(), ARGS_VVV); -export const [fit11, fit11_2, fit11_3, fit11_4] = defHofOp( - _fit11, - HOF_VVV, - ARGS_VVV -); +export const [fit11, fit11_2, fit11_3, fit11_4]: [ + MultiVecOpVVV, + VecOpVVV, + VecOpVVV, + VecOpVVV +] = defHofOp(_fit11, FN3(), ARGS_VVV); diff --git a/packages/vectors/src/fmod.ts b/packages/vectors/src/fmod.ts new file mode 100644 index 0000000000..9c5a9f984e --- /dev/null +++ b/packages/vectors/src/fmod.ts @@ -0,0 +1,13 @@ +import { fmod as _fmod } from "@thi.ng/math"; +import { ARGS_VV, defHofOp } from "./internal/codegen"; +import { FN2 } from "./internal/templates"; + +/** + * This version of mod uses the same logic as in GLSL, whereas `mod` + * merely uses JavaScript's `%` modulo operator, yielding different + * results for negative values. + * + * `a - b * floor(a/b)` + * + */ +export const [fmod, fmod2, fmod3, fmod4] = defHofOp(_fmod, FN2("op"), ARGS_VV); diff --git a/packages/vectors/src/fmodn.ts b/packages/vectors/src/fmodn.ts new file mode 100644 index 0000000000..66c4847a90 --- /dev/null +++ b/packages/vectors/src/fmodn.ts @@ -0,0 +1,14 @@ +import { fmod as _fmod } from "@thi.ng/math"; +import { ARGS_V, ARGS_VN, defHofOp } from "./internal/codegen"; +import { FN_N } from "./internal/templates"; + +/** + * Same as `fmod`, but 2nd operand is a single scalar (uniform domain + * for all vector components). + */ +export const [fmodN, fmodN2, fmodN3, fmodN4] = defHofOp( + _fmod, + FN_N("op"), + ARGS_VN, + ARGS_V +); diff --git a/packages/vectors/src/gt.ts b/packages/vectors/src/gt.ts new file mode 100644 index 0000000000..fd1ff2f3b2 --- /dev/null +++ b/packages/vectors/src/gt.ts @@ -0,0 +1,5 @@ +import { CompareOp, MultiCompareOp } from "./api"; +import { defOp } from "./internal/codegen"; +import { MATH } from "./internal/templates"; + +export const [gt, gt2, gt3, gt4] = defOp(MATH(">")); diff --git a/packages/vectors/src/gte.ts b/packages/vectors/src/gte.ts new file mode 100644 index 0000000000..67193bf287 --- /dev/null +++ b/packages/vectors/src/gte.ts @@ -0,0 +1,7 @@ +import { CompareOp, MultiCompareOp } from "./api"; +import { defOp } from "./internal/codegen"; +import { MATH } from "./internal/templates"; + +export const [gte, gte2, gte3, gte4] = defOp( + MATH(">=") +); diff --git a/packages/vectors/src/gvec.ts b/packages/vectors/src/gvec.ts index adddd1edf2..c89100af82 100644 --- a/packages/vectors/src/gvec.ts +++ b/packages/vectors/src/gvec.ts @@ -123,7 +123,7 @@ export const gvec = ( case SYM_EMPTY: return () => zeroes(size); case SYM_EQD: - return (o, eps = EPS) => + return (o: any, eps: number = EPS) => eqDeltaS(buf, o, size, eps, offset, 0, stride, 1); case SYM_STR: return () => diff --git a/packages/vectors/src/index.ts b/packages/vectors/src/index.ts index cf586f0776..2f86b069de 100644 --- a/packages/vectors/src/index.ts +++ b/packages/vectors/src/index.ts @@ -14,13 +14,19 @@ export * from "./abs"; export * from "./acos"; export * from "./addw"; export * from "./add"; +export * from "./addi"; export * from "./addm"; export * from "./addmn"; export * from "./addn"; export * from "./adds"; export * from "./angle-between"; export * from "./asin"; +export * from "./atan"; export * from "./bisect"; +export * from "./bit-and"; +export * from "./bit-not"; +export * from "./bit-or"; +export * from "./bit-xor"; export * from "./cartesian"; export * from "./ceil"; export * from "./clamp"; @@ -31,12 +37,14 @@ export * from "./copy"; export * from "./cos"; export * from "./cosh"; export * from "./cross"; +export * from "./degrees"; export * from "./direction"; export * from "./dist"; export * from "./dist-chebyshev"; export * from "./dist-manhattan"; export * from "./distsq"; export * from "./div"; +export * from "./divi"; export * from "./divn"; export * from "./divs"; export * from "./dot"; @@ -45,9 +53,12 @@ export * from "./dots"; export * from "./empty"; export * from "./eqdelta"; export * from "./exp"; +export * from "./exp_2"; export * from "./face-forward"; export * from "./fit"; export * from "./floor"; +export * from "./fmod"; +export * from "./fmodn"; export * from "./fract"; export * from "./gvec"; export * from "./hash"; @@ -59,6 +70,11 @@ export * from "./invsqrt"; export * from "./jitter"; export * from "./limit"; export * from "./log"; +export * from "./log_2"; +export * from "./logic-and"; +export * from "./logic-not"; +export * from "./logic-or"; +export * from "./lshift"; export * from "./madd"; export * from "./maddn"; export * from "./mag"; @@ -76,6 +92,7 @@ export * from "./mixn"; export * from "./mod"; export * from "./modn"; export * from "./mul"; +export * from "./muli"; export * from "./muln"; export * from "./muls"; export * from "./neg"; @@ -87,6 +104,7 @@ export * from "./polar"; export * from "./pow"; export * from "./pown"; export * from "./project"; +export * from "./radians"; export * from "./random"; export * from "./reflect"; export * from "./refract"; @@ -94,11 +112,14 @@ export * from "./rotate-around-axis"; export * from "./rotate-around-point"; export * from "./rotate"; export * from "./round"; +export * from "./rshift"; export * from "./set"; export * from "./setc"; export * from "./setn"; export * from "./sets"; export * from "./setsn"; +export * from "./setvn"; +export * from "./setvv"; export * from "./sign"; export * from "./signed-area"; export * from "./sin"; @@ -107,6 +128,7 @@ export * from "./sqrt"; export * from "./step"; export * from "./smoothstep"; export * from "./sub"; +export * from "./subi"; export * from "./subm"; export * from "./submn"; export * from "./subn"; @@ -116,4 +138,12 @@ export * from "./swizzle"; export * from "./tan"; export * from "./tanh"; export * from "./trunc"; +export * from "./vec-of"; export * from "./wrap"; + +export * from "./eq"; +export * from "./neq"; +export * from "./gt"; +export * from "./gte"; +export * from "./lt"; +export * from "./lte"; diff --git a/packages/vectors/src/internal/codegen.ts b/packages/vectors/src/internal/codegen.ts index 87f5fafbe2..058c755e3f 100644 --- a/packages/vectors/src/internal/codegen.ts +++ b/packages/vectors/src/internal/codegen.ts @@ -8,14 +8,29 @@ import { transduce, zip } from "@thi.ng/transducers"; -import { MultiVecOpVN, MultiVecOpVV, VecOpVN, VecOpVV } from "../api"; -import { FN, MATH, MATH_N } from "./templates"; +import { + MultiVecOpVN, + MultiVecOpVV, + Template, + VecOpVN, + VecOpVV +} from "../api"; +import { + FN, + MATH, + MATH_N, + SIGNED, + SIGNED_N, + UNSIGNED, + UNSIGNED_N +} from "./templates"; import { vop } from "./vop"; export const ARGS_V = "o,a"; export const ARGS_VV = "o,a,b"; export const ARGS_VVV = "o,a,b,c"; export const ARGS_VN = "o,a,n"; +export const ARGS_VNV = "o,a,n,b"; export const ARGS_VVN = "o,a,b,n"; export const SARGS_V = "io=0,ia=0,so=1,sa=1"; @@ -25,8 +40,6 @@ export const SARGS_VVV = "io=0,ia=0,ib=0,ic=0,so=1,sa=1,sb=1,sc=1"; export const DEFAULT_OUT = "!o&&(o=a);"; export const NEW_OUT = "!o&&(o=[]);"; -export type Template = (syms: string[], i?: number) => string; - /** * HOF array index lookup gen to provide optimized versions of: * @@ -38,12 +51,12 @@ export type Template = (syms: string[], i?: number) => string; * * @param sym */ -const lookup = (sym: string) => (i) => +const lookup = (sym: string) => (i: number) => i > 1 ? `${sym}[i${sym}+${i}*s${sym}]` : i == 1 - ? `${sym}[i${sym}+s${sym}]` - : `${sym}[i${sym}]`; + ? `${sym}[i${sym}+s${sym}]` + : `${sym}[i${sym}]`; /** * Infinite iterator of strided index lookups for `sym`. @@ -97,12 +110,19 @@ const assemble = ( ) => [ pre, transduce( - comp(take(dim), mapIndexed((i, x: string[]) => tpl(x, i))), + comp( + take(dim), + mapIndexed((i, x) => tpl(x, i)) + ), str(opJoin), - zip.apply(null, syms.split(",").map(strided ? indicesStrided : indices)) + >( + zip.apply(null, ( + syms.split(",").map(strided ? indicesStrided : indices) + )) + ) ), post, - ret !== null ? `return ${ret};` : "" + ret !== "" ? `return ${ret};` : "" ]; const assembleG = ( @@ -226,7 +246,8 @@ export const defOp = ( syms = syms || args; pre = pre != null ? pre : defaultOut(ret, args); const fn: any = vop(dispatch); - const $ = (dim) => fn.add(dim, compile(dim, tpl, args, syms, ret, "", pre)); + const $ = (dim: number) => + fn.add(dim, compile(dim, tpl, args, syms, ret, "", pre)); fn.default(compileG(tpl, args, syms, ret, pre)); return [fn, $(2), $(3), $(4)]; }; @@ -234,7 +255,7 @@ export const defOp = ( export const defFnOp = (op: string) => defOp(FN(op), ARGS_V); export const defHofOp = ( - op, + op: any, tpl?: Template, args = ARGS_V, syms?: string, @@ -242,13 +263,13 @@ export const defHofOp = ( dispatch = 1, pre?: string ): [M, V, V, V] => { - tpl = tpl || FN("op"); + const _tpl = tpl || FN("op"); syms = syms || args; pre = pre != null ? pre : defaultOut(ret, args); - const $ = (dim) => - compileHOF(dim, [op], tpl, "op", args, syms, ret, "", pre); + const $ = (dim: number) => + compileHOF(dim, [op], _tpl, "op", args, syms, ret, "", pre); const fn: any = vop(dispatch); - fn.default(compileGHOF([op], tpl, "op", args, syms, ret, pre)); + fn.default(compileGHOF([op], _tpl, "op", args, syms, ret, pre)); return [fn, $(2), $(3), $(4)]; }; @@ -276,5 +297,11 @@ export const defOpS = ( export const defMathOp = (op: string) => defOp(MATH(op)); -export const defMathNOp = (op: string) => +export const defMathOpN = (op: string) => defOp(MATH_N(op), ARGS_VN); + +export const defBitOp = (op: string, signed = false) => + defOp((signed ? SIGNED : UNSIGNED)(op)); + +export const defBitOpN = (op: string, signed = false) => + defOp((signed ? SIGNED_N : UNSIGNED_N)(op), ARGS_VN); diff --git a/packages/vectors/src/internal/templates.ts b/packages/vectors/src/internal/templates.ts index 706b204d45..38b010ee65 100644 --- a/packages/vectors/src/internal/templates.ts +++ b/packages/vectors/src/internal/templates.ts @@ -1,23 +1,38 @@ -export const MATH = (op: string) => ([o, a, b]) => `${o}=${a}${op}${b};`; -export const MATH_N = (op: string) => ([o, a]) => `${o}=${a}${op}n;`; -export const FN = (op: string) => ([o, a]) => `${o}=${op}(${a});`; -export const FN2 = (op: string) => ([o, a, b]) => `${o}=${op}(${a},${b});`; -export const FN_N = (op: string) => ([o, a]) => `${o}=${op}(${a},n);`; +import { Template } from "../api"; -export const DOT = ([a, b]) => `${a}*${b}`; -export const DOT_G = ([a, b]) => `s+=${a}*${b};`; -export const SET = ([o, a]) => `${o}=${a};`; -export const SET_N = ([a]) => `${a}=n;`; +// prettier-ignore +export const MATH = (op: string): Template => ([o, a, b]) => `${o}=${a}${op}${b};`; +// prettier-ignore +export const MATH_N = (op: string): Template => ([o, a]) => `${o}=${a}${op}n;`; +// prettier-ignore +export const SIGNED = (op: string): Template => ([o, a, b]) => `${o}=(${a}${op}${b})|0;`; +// prettier-ignore +export const UNSIGNED = (op: string): Template => ([o, a, b]) => `${o}=(${a}${op}${b})>>>0;`; +// prettier-ignore +export const SIGNED_N = (op: string): Template => ([o, a]) => `${o}=(${a}${op}n)|0;`; +// prettier-ignore +export const UNSIGNED_N = (op: string): Template => ([o, a]) => `${o}=(${a}${op}n)>>>0;`; +// prettier-ignore +export const FN = (op="op"): Template => ([o, a]) => `${o}=${op}(${a});`; +// prettier-ignore +export const FN2 = (op="op"): Template => ([o, a, b]) => `${o}=${op}(${a},${b});`; +// prettier-ignore +export const FN3 = (op="op"): Template => ([o, a, b, c]) => `${o}=${op}(${a},${b},${c});`; +// prettier-ignore +export const FN5 = (op = "op"): Template => ([o, a, b, c, d, e]) => `${o}=${op}(${a},${b},${c},${d},${e});`; +// prettier-ignore +export const FN_N = (op="op"): Template => ([o, a]) => `${o}=${op}(${a},n);`; -export const HOF_VVV = ([o, a, b, c]) => `${o}=op(${a},${b},${c});`; -export const HOF_VVVVV = ([o, a, b, c, d, e]) => - `${o}=op(${a},${b},${c},${d},${e});`; +export const DOT: Template = ([a, b]) => `${a}*${b}`; +export const DOT_G: Template = ([a, b]) => `s+=${a}*${b};`; +export const SET: Template = ([o, a]) => `${o}=${a};`; +export const SET_N: Template = ([a]) => `${a}=n;`; -export const ADDM = ([o, a, b, c]) => `${o}=(${a}+${b})*${c};`; -export const ADDM_N = ([o, a, b]) => `${o}=(${a}+${b})*n;`; -export const MADD = ([o, a, b, c]) => `${o}=${a}+${b}*${c};`; -export const MADD_N = ([o, a, b]) => `${o}=${a}+${b}*n;`; -export const MIX = ([o, a, b, c]) => `${o}=${a}+(${b}-${a})*${c};`; -export const MIX_N = ([o, a, b]) => `${o}=${a}+(${b}-${a})*n;`; -export const SUBM = ([o, a, b, c]) => `${o}=(${a}-${b})*${c};`; -export const SUBM_N = ([o, a, b]) => `${o}=(${a}-${b})*n;`; +export const ADDM: Template = ([o, a, b, c]) => `${o}=(${a}+${b})*${c};`; +export const ADDM_N: Template = ([o, a, b]) => `${o}=(${a}+${b})*n;`; +export const MADD: Template = ([o, a, b, c]) => `${o}=${a}*${b}+${c};`; +export const MADD_N: Template = ([o, a, b]) => `${o}=${a}*n+${b};`; +export const MIX: Template = ([o, a, b, c]) => `${o}=${a}+(${b}-${a})*${c};`; +export const MIX_N: Template = ([o, a, b]) => `${o}=${a}+(${b}-${a})*n;`; +export const SUBM: Template = ([o, a, b, c]) => `${o}=(${a}-${b})*${c};`; +export const SUBM_N: Template = ([o, a, b]) => `${o}=(${a}-${b})*n;`; diff --git a/packages/vectors/src/internal/vop.ts b/packages/vectors/src/internal/vop.ts index 05d0b6519e..f2a0c6e28d 100644 --- a/packages/vectors/src/internal/vop.ts +++ b/packages/vectors/src/internal/vop.ts @@ -7,17 +7,17 @@ import { unsupported } from "@thi.ng/errors"; * * @param dispatch arg index */ -export const vop = (dispatch = 0) => { +export const vop = (dispatch = 0) => { const impls = new Array(5); - let fallback; + let fallback: T; const fn = (...args: any[]) => { const g = impls[args[dispatch].length] || fallback; return g ? g(...args) : unsupported(`no impl for vec size ${args[dispatch].length}`); }; - fn.add = (dim: number, fn) => (impls[dim] = fn); - fn.default = (fn) => (fallback = fn); + fn.add = (dim: number, fn: T) => (impls[dim] = fn); + fn.default = (fn: T) => (fallback = fn); // fn.impls = impls; return fn; }; diff --git a/packages/vectors/src/jitter.ts b/packages/vectors/src/jitter.ts index ed5519b350..a85022066d 100644 --- a/packages/vectors/src/jitter.ts +++ b/packages/vectors/src/jitter.ts @@ -4,7 +4,7 @@ import { ReadonlyVec, Vec } from "./api"; import { randNorm } from "./random"; export const jitter = ( - out: Vec, + out: Vec | null, a: ReadonlyVec, n = 1, rnd: IRandom = SYSTEM diff --git a/packages/vectors/src/log_2.ts b/packages/vectors/src/log_2.ts new file mode 100644 index 0000000000..ee9f6ead75 --- /dev/null +++ b/packages/vectors/src/log_2.ts @@ -0,0 +1,9 @@ +import { MultiVecOpV, VecOpV } from "./api"; +import { defFnOp } from "./internal/codegen"; + +/** + * Componentwise Math.log2 + */ +export const [log_2, log_22, log_23, log_24] = defFnOp( + "Math.log2" +); diff --git a/packages/vectors/src/logic-and.ts b/packages/vectors/src/logic-and.ts new file mode 100644 index 0000000000..4b0da9e389 --- /dev/null +++ b/packages/vectors/src/logic-and.ts @@ -0,0 +1,8 @@ +import { BVecOpVV, MultiBVecOpVV } from "./api"; +import { defOp } from "./internal/codegen"; +import { MATH } from "./internal/templates"; + +export const [logicAnd, logicAnd2, logicAnd3, logicAnd4] = defOp< + MultiBVecOpVV, + BVecOpVV +>(MATH("&&")); diff --git a/packages/vectors/src/logic-not.ts b/packages/vectors/src/logic-not.ts new file mode 100644 index 0000000000..e3e4e1adad --- /dev/null +++ b/packages/vectors/src/logic-not.ts @@ -0,0 +1,7 @@ +import { BVecOpV, MultiBVecOpV } from "./api"; +import { defFnOp } from "./internal/codegen"; + +export const [logicNot, logicNot2, logicNot3, logicNot4] = defFnOp< + MultiBVecOpV, + BVecOpV +>("!"); diff --git a/packages/vectors/src/logic-or.ts b/packages/vectors/src/logic-or.ts new file mode 100644 index 0000000000..641d7253c0 --- /dev/null +++ b/packages/vectors/src/logic-or.ts @@ -0,0 +1,8 @@ +import { BVecOpVV, MultiBVecOpVV } from "./api"; +import { defOp } from "./internal/codegen"; +import { MATH } from "./internal/templates"; + +export const [logicOr, logicOr2, logicOr3, logicOr4] = defOp< + MultiBVecOpVV, + BVecOpVV +>(MATH("||")); diff --git a/packages/vectors/src/lshift.ts b/packages/vectors/src/lshift.ts new file mode 100644 index 0000000000..44edfdaf06 --- /dev/null +++ b/packages/vectors/src/lshift.ts @@ -0,0 +1,10 @@ +import { defBitOp, defBitOpN } from "./internal/codegen"; + +export const [lshiftI, lshiftI2, lshiftI3, lshiftI4] = defBitOp("<<", true); + +export const [lshiftU, lshiftU2, lshiftU3, lshiftU4] = defBitOp("<<"); + +// prettier-ignore +export const [lshiftNI, lshiftNI2, lshiftNI3, lshiftNI4] = defBitOpN("<<", true); + +export const [lshiftNU, lshiftNU2, lshiftNU3, lshiftNU4] = defBitOpN("<<"); diff --git a/packages/vectors/src/lt.ts b/packages/vectors/src/lt.ts new file mode 100644 index 0000000000..411a28d8ff --- /dev/null +++ b/packages/vectors/src/lt.ts @@ -0,0 +1,5 @@ +import { CompareOp, MultiCompareOp } from "./api"; +import { defOp } from "./internal/codegen"; +import { MATH } from "./internal/templates"; + +export const [lt, lt2, lt3, lt4] = defOp(MATH("<")); diff --git a/packages/vectors/src/lte.ts b/packages/vectors/src/lte.ts new file mode 100644 index 0000000000..09b156484b --- /dev/null +++ b/packages/vectors/src/lte.ts @@ -0,0 +1,7 @@ +import { CompareOp, MultiCompareOp } from "./api"; +import { defOp } from "./internal/codegen"; +import { MATH } from "./internal/templates"; + +export const [lte, lte2, lte3, lte4] = defOp( + MATH("<=") +); diff --git a/packages/vectors/src/madd.ts b/packages/vectors/src/madd.ts index a2ab83b7ae..dff87dff41 100644 --- a/packages/vectors/src/madd.ts +++ b/packages/vectors/src/madd.ts @@ -3,9 +3,15 @@ import { ARGS_VVV, defOp } from "./internal/codegen"; import { MADD } from "./internal/templates"; /** - * Returns `out = a + b * c`. + * Returns `out = a * b + c`. * * @see addm + * @see maddN + * + * @param out + * @param a + * @param b + * @param c */ export const [madd, madd2, madd3, madd4] = defOp( MADD, diff --git a/packages/vectors/src/maddn.ts b/packages/vectors/src/maddn.ts index dd85c8a518..44d21a6ffa 100644 --- a/packages/vectors/src/maddn.ts +++ b/packages/vectors/src/maddn.ts @@ -1,11 +1,17 @@ -import { MultiVecOpVVN, VecOpVVN } from "./api"; -import { ARGS_VVN, defOp } from "./internal/codegen"; +import { MultiVecOpVNV, VecOpVNV } from "./api"; +import { ARGS_VNV, ARGS_VV, defOp } from "./internal/codegen"; import { MADD_N } from "./internal/templates"; /** - * Returns `out = a + b * n`. + * Returns `out = a * n + b`. + * + * @param out vec + * @param a vec + * @param n scalar + * @param b vec */ -export const [maddN, maddN2, maddN3, maddN4] = defOp( +export const [maddN, maddN2, maddN3, maddN4] = defOp( MADD_N, - ARGS_VVN + ARGS_VNV, + ARGS_VV ); diff --git a/packages/vectors/src/magsq.ts b/packages/vectors/src/magsq.ts index 3292ae2c15..449596e18a 100644 --- a/packages/vectors/src/magsq.ts +++ b/packages/vectors/src/magsq.ts @@ -5,7 +5,7 @@ import { vop } from "./internal/vop"; const $ = (dim: number) => magSq.add( dim, - compile(dim, ([a]) => `${a}*${a}`, "a", "a", null, "+", "return ", ";") + compile(dim, ([a]) => `${a}*${a}`, "a", "a", "", "+", "return ", ";") ); export const magSq: MultiVecOpRoV = vop(); diff --git a/packages/vectors/src/major.ts b/packages/vectors/src/major.ts index 979de0886a..b4910b6605 100644 --- a/packages/vectors/src/major.ts +++ b/packages/vectors/src/major.ts @@ -13,8 +13,8 @@ const abs = Math.abs; export const major: MultiVecOpRoV = vop(); major.default((a) => { - let id, - max = -Infinity; + let id = -1; + let max = -Infinity; for (let i = a.length; --i >= 0; ) { const x = abs(a[i]); if (x > max) { diff --git a/packages/vectors/src/minor.ts b/packages/vectors/src/minor.ts index aea76a958c..a355fd16f8 100644 --- a/packages/vectors/src/minor.ts +++ b/packages/vectors/src/minor.ts @@ -13,8 +13,8 @@ const abs = Math.abs; export const minor: MultiVecOpRoV = vop(); minor.default((a) => { - let id, - min = Infinity; + let id = -1; + let min = Infinity; for (let i = a.length; --i >= 0; ) { const x = abs(a[i]); if (x < min) { diff --git a/packages/vectors/src/modn.ts b/packages/vectors/src/modn.ts index 3ce1a88e85..292c7ad803 100644 --- a/packages/vectors/src/modn.ts +++ b/packages/vectors/src/modn.ts @@ -1,3 +1,3 @@ -import { defMathNOp } from "./internal/codegen"; +import { defMathOpN } from "./internal/codegen"; -export const [modN, modN2, modN3, modN4] = defMathNOp("%"); +export const [modN, modN2, modN3, modN4] = defMathOpN("%"); diff --git a/packages/vectors/src/muli.ts b/packages/vectors/src/muli.ts new file mode 100644 index 0000000000..9a262a282f --- /dev/null +++ b/packages/vectors/src/muli.ts @@ -0,0 +1,9 @@ +import { defBitOp, defBitOpN } from "./internal/codegen"; + +export const [mulI, mulI2, mulI3, mulI4] = defBitOp("*", true); + +export const [mulU, mulU2, mulU3, mulU4] = defBitOp("*"); + +export const [mulNI, mulNI2, mulNI3, mulNI4] = defBitOpN("*", true); + +export const [mulNU, mulNU2, mulNU3, mulNU4] = defBitOpN("*"); diff --git a/packages/vectors/src/muln.ts b/packages/vectors/src/muln.ts index f7019a269a..378f94d920 100644 --- a/packages/vectors/src/muln.ts +++ b/packages/vectors/src/muln.ts @@ -1,3 +1,3 @@ -import { defMathNOp } from "./internal/codegen"; +import { defMathOpN } from "./internal/codegen"; -export const [mulN, mulN2, mulN3, mulN4] = defMathNOp("*"); +export const [mulN, mulN2, mulN3, mulN4] = defMathOpN("*"); diff --git a/packages/vectors/src/neg.ts b/packages/vectors/src/neg.ts index 4a13fee887..6671281900 100644 --- a/packages/vectors/src/neg.ts +++ b/packages/vectors/src/neg.ts @@ -1,4 +1,5 @@ import { ReadonlyVec, Vec, VecOpV } from "./api"; import { mulN } from "./muln"; -export const neg: VecOpV = (out: Vec, v: ReadonlyVec) => mulN(out, v, -1); +export const neg: VecOpV = (out: Vec | null, v: ReadonlyVec) => + mulN(out, v, -1); diff --git a/packages/vectors/src/neq.ts b/packages/vectors/src/neq.ts new file mode 100644 index 0000000000..976802bf2e --- /dev/null +++ b/packages/vectors/src/neq.ts @@ -0,0 +1,7 @@ +import { CompareOp, MultiCompareOp } from "./api"; +import { defOp } from "./internal/codegen"; +import { MATH } from "./internal/templates"; + +export const [neq, neq2, neq3, neq4] = defOp( + MATH("!==") +); diff --git a/packages/vectors/src/normal.ts b/packages/vectors/src/normal.ts index f6484be254..ac4584cd7c 100644 --- a/packages/vectors/src/normal.ts +++ b/packages/vectors/src/normal.ts @@ -1,6 +1,6 @@ import { ReadonlyVec, Vec } from "./api"; import { direction } from "./direction"; -import { perpendicularLeft2, perpendicularRight2 } from "./perpendicular"; +import { perpendicularCCW, perpendicularCW } from "./perpendicular"; /** * Computes 2D normal by rotating direction vector `a` -> `b`, 90 deg @@ -12,8 +12,8 @@ import { perpendicularLeft2, perpendicularRight2 } from "./perpendicular"; * @param b * @param n */ -export const normalLeft2 = (out: Vec, a: ReadonlyVec, b: ReadonlyVec, n = 1) => - perpendicularLeft2(null, direction(out || [], a, b, n)); +export const normalCCW = (out: Vec, a: ReadonlyVec, b: ReadonlyVec, n = 1) => + perpendicularCCW(null, direction(out || [], a, b, n)); /** * Computes 2D normal by rotating direction vector `a` -> `b`, 90 deg @@ -25,5 +25,5 @@ export const normalLeft2 = (out: Vec, a: ReadonlyVec, b: ReadonlyVec, n = 1) => * @param b * @param n */ -export const normalRight2 = (out: Vec, a: ReadonlyVec, b: ReadonlyVec, n = 1) => - perpendicularRight2(null, direction(out || [], a, b, n)); +export const normalCW = (out: Vec, a: ReadonlyVec, b: ReadonlyVec, n = 1) => + perpendicularCW(null, direction(out || [], a, b, n)); diff --git a/packages/vectors/src/ortho-normal.ts b/packages/vectors/src/ortho-normal.ts index d3a1f55596..4c7cd513db 100644 --- a/packages/vectors/src/ortho-normal.ts +++ b/packages/vectors/src/ortho-normal.ts @@ -1,7 +1,7 @@ +import { ReadonlyVec, Vec } from "./api"; import { cross3 } from "./cross"; -import { sub3 } from "./sub"; import { normalize } from "./normalize"; -import { Vec, ReadonlyVec } from "./api"; +import { sub3 } from "./sub"; /** * Produces a vector which is perpendicular/normal to the plane spanned @@ -9,8 +9,8 @@ import { Vec, ReadonlyVec } from "./api"; * result vector will be normalized. * * ``` - * orthoNormal3([], [0,0,0], [1,0,0], [0,1,0]) - * // [0,0,1] + * orthoNormal3([], [0, 0, 0], [1, 0, 0], [0, 1, 0]) + * // [0, 0, 1] * ``` * * @param out @@ -20,7 +20,7 @@ import { Vec, ReadonlyVec } from "./api"; * @param normalize */ export const orthoNormal3 = ( - out: Vec, + out: Vec | null, a: ReadonlyVec, b: ReadonlyVec, c: ReadonlyVec, diff --git a/packages/vectors/src/perpendicular.ts b/packages/vectors/src/perpendicular.ts index 52544c6c56..58b18b8052 100644 --- a/packages/vectors/src/perpendicular.ts +++ b/packages/vectors/src/perpendicular.ts @@ -2,19 +2,20 @@ import { VecOpV } from "./api"; import { setC2 } from "./setc"; /** - * Produces a perpendicular vector to `v`, i.e. `[-y,x]`. + * 2D only. Produces a perpendicular vector to `v`, i.e. `[-y,x]`. + * Assumes positive Y-up. * * @param out * @param v */ -export const perpendicularLeft2: VecOpV = (out, a) => +export const perpendicularCCW: VecOpV = (out, a) => setC2(out || a, -a[1], a[0]); /** - * Produces a perpendicular vector to `v`, i.e. `[y,-x]`. + * 2D only. Produces a clockwise perpendicular vector to `v`, i.e. + * `[y,-x]`. Assumes positive Y-up. * * @param out * @param v */ -export const perpendicularRight2: VecOpV = (out, a) => - setC2(out || a, a[1], -a[0]); +export const perpendicularCW: VecOpV = (out, a) => setC2(out || a, a[1], -a[0]); diff --git a/packages/vectors/src/radians.ts b/packages/vectors/src/radians.ts new file mode 100644 index 0000000000..0ebff87973 --- /dev/null +++ b/packages/vectors/src/radians.ts @@ -0,0 +1,11 @@ +import { rad } from "@thi.ng/math"; +import { MultiVecOpV, VecOpV } from "./api"; +import { defHofOp } from "./internal/codegen"; +import { FN } from "./internal/templates"; + +export const [radians, radians2, radians3, radians4]: [ + MultiVecOpV, + VecOpV, + VecOpV, + VecOpV +] = defHofOp(rad, FN("op")); diff --git a/packages/vectors/src/random.ts b/packages/vectors/src/random.ts index eccdffa3f1..b3848e8534 100644 --- a/packages/vectors/src/random.ts +++ b/packages/vectors/src/random.ts @@ -1,5 +1,10 @@ import { IRandom, SYSTEM } from "@thi.ng/random"; -import { MultiVecOpOOO, ReadonlyVec, Vec, VecOpOOO } from "./api"; +import { + MultiVecOpOOO, + ReadonlyVec, + Vec, + VecOpOOO +} from "./api"; import { defHofOp } from "./internal/codegen"; import { normalize } from "./normalize"; @@ -33,7 +38,7 @@ export const [random, random2, random3, random4] = defHofOp< * @param n * @param rnd */ -export const randNorm = (v: Vec, n = 1, rnd: IRandom = SYSTEM) => { +export const randNorm = (v: Vec | null, n = 1, rnd: IRandom = SYSTEM) => { v = random(v, -1, 1, rnd); return normalize(v, v, n); }; diff --git a/packages/vectors/src/reflect.ts b/packages/vectors/src/reflect.ts index 8b0596db0b..5b7d295b1e 100644 --- a/packages/vectors/src/reflect.ts +++ b/packages/vectors/src/reflect.ts @@ -2,4 +2,4 @@ import { VecOpVV } from "./api"; import { dot } from "./dot"; import { maddN } from "./maddn"; -export const reflect: VecOpVV = (out, a, b) => maddN(out, a, b, -2 * dot(a, b)); +export const reflect: VecOpVV = (out, a, b) => maddN(out, b, -2 * dot(a, b), a); diff --git a/packages/vectors/src/refract.ts b/packages/vectors/src/refract.ts index 7dcd86d353..3670d3064f 100644 --- a/packages/vectors/src/refract.ts +++ b/packages/vectors/src/refract.ts @@ -10,5 +10,5 @@ export const refract: VecOpVVN = (out, a, n, eta) => { const k = 1 - eta * eta * (1 - d * d); return k < 0 ? zero(out) - : maddN(out, mulN(out, a, eta), n, -(eta * d + Math.sqrt(k))); + : maddN(out, n, -(eta * d + Math.sqrt(k)), mulN(out, a, eta)); }; diff --git a/packages/vectors/src/rshift.ts b/packages/vectors/src/rshift.ts new file mode 100644 index 0000000000..fb3819dcf5 --- /dev/null +++ b/packages/vectors/src/rshift.ts @@ -0,0 +1,10 @@ +import { defBitOp, defBitOpN } from "./internal/codegen"; + +export const [rshiftI, rshiftI2, rshiftI3, rshiftI4] = defBitOp(">>", true); + +export const [rshiftU, rshiftU2, rshiftU3, rshiftU4] = defBitOp(">>>"); + +// prettier-ignore +export const [rshiftNI, rshiftNI2, rshiftNI3, rshiftNI4] = defBitOpN(">>", true); + +export const [rshiftNU, rshiftNU2, rshiftNU3, rshiftNU4] = defBitOpN(">>>"); diff --git a/packages/vectors/src/setc.ts b/packages/vectors/src/setc.ts index 2def0dc115..9b7478e3eb 100644 --- a/packages/vectors/src/setc.ts +++ b/packages/vectors/src/setc.ts @@ -1,14 +1,20 @@ import { Vec } from "./api"; -export const setC2 = (out: Vec, x: number, y: number) => ( +export const setC2 = (out: Vec | null, x: number, y: number) => ( !out && (out = []), (out[0] = x), (out[1] = y), out ); -export const setC3 = (out: Vec, x: number, y: number, z: number) => ( +export const setC3 = (out: Vec | null, x: number, y: number, z: number) => ( !out && (out = []), (out[0] = x), (out[1] = y), (out[2] = z), out ); -export const setC4 = (out: Vec, x: number, y: number, z: number, w: number) => ( +export const setC4 = ( + out: Vec | null, + x: number, + y: number, + z: number, + w: number +) => ( !out && (out = []), (out[0] = x), (out[1] = y), @@ -18,7 +24,7 @@ export const setC4 = (out: Vec, x: number, y: number, z: number, w: number) => ( ); export const setC6 = ( - out: Vec, + out: Vec | null, a: number, b: number, c: number, @@ -36,7 +42,7 @@ export const setC6 = ( out ); -export const setC = (out: Vec, ...xs: number[]) => { +export const setC = (out: Vec | null, ...xs: number[]) => { !out && (out = []); for (let i = 0, n = xs.length; i < n; i++) { out[i] = xs[i]; diff --git a/packages/vectors/src/setvn.ts b/packages/vectors/src/setvn.ts new file mode 100644 index 0000000000..08ac86b716 --- /dev/null +++ b/packages/vectors/src/setvn.ts @@ -0,0 +1,20 @@ +import { VecOpVN } from "./api"; +import { setC3, setC4 } from "./setc"; + +/** + * Sets `out` to `[a.x, a.y, n]` + * + * @param out + * @param a + * @param n + */ +export const setVN3: VecOpVN = (out, a, n) => setC3(out, a[0], a[1], n); + +/** + * Sets `out` to `[a.x, a.y, a.z, n]` + * + * @param out + * @param a + * @param n + */ +export const setVN4: VecOpVN = (out, a, n) => setC4(out, a[0], a[1], a[2], n); diff --git a/packages/vectors/src/setvv.ts b/packages/vectors/src/setvv.ts new file mode 100644 index 0000000000..41ed164207 --- /dev/null +++ b/packages/vectors/src/setvv.ts @@ -0,0 +1,80 @@ +import { + ReadonlyVec, + Vec, + VecOpVV, + VecOpVVV +} from "./api"; +import { setC, setC4, setC6 } from "./setc"; + +/** + * Sets `out` to `[a.x, a.y, b.x, b.y]` + * + * @param out + * @param a + * @param b + */ +export const setVV4: VecOpVV = (out, a, b) => + setC4(out, a[0], a[1], b[0], b[1]); + +/** + * Sets `out` to `[a.x, a.y, b.x, b.y, c.x, c.y]` + * + * @param out + * @param a + * @param b + * @param c + */ +export const setVV6: VecOpVVV = (out, a, b, c) => + setC6(out, a[0], a[1], b[0], b[1], c[0], c[1]); + +/** + * Sets `out` to: + * `[a.x, a.y, a.z, b.x, b.y, b.z, c.x, c.y, c.z]` + * + * @param out + * @param a + * @param b + * @param c + */ +export const setVV9: VecOpVVV = (out, a, b, c) => + setC(out, a[0], a[1], a[2], b[0], b[1], b[2], c[0], c[1], c[2]); + +/** + * Sets `out` to: + * + * ``` + * [a.x, a.y, a.z, a.w, b.x, b.y, b.z, b.w, + * c.x, c.y, c.z, c.w, d.x, d.y, d.z, d.w] + * ``` + * + * @param out + * @param a + * @param b + * @param c + */ +export const setVV16 = ( + out: Vec | null, + a: ReadonlyVec, + b: ReadonlyVec, + c: ReadonlyVec, + d: ReadonlyVec +) => + setC( + out, + a[0], + a[1], + a[2], + a[3], + b[0], + b[1], + b[2], + b[3], + c[0], + c[1], + c[2], + c[3], + d[0], + d[1], + d[2], + d[3] + ); diff --git a/packages/vectors/src/smoothstep.ts b/packages/vectors/src/smoothstep.ts index 893a0437c5..0363d69620 100644 --- a/packages/vectors/src/smoothstep.ts +++ b/packages/vectors/src/smoothstep.ts @@ -1,7 +1,7 @@ import { smoothStep as _step } from "@thi.ng/math"; -import { MultiVecOpV, VecOpV } from "./api"; +import { MultiVecOpVVV, VecOpVVV } from "./api"; import { DEFAULT_OUT, defHofOp } from "./internal/codegen"; -import { HOF_VVV } from "./internal/templates"; +import { FN3 } from "./internal/templates"; /** * Like GLSL `smoothstep()` @@ -12,6 +12,6 @@ import { HOF_VVV } from "./internal/templates"; * @param v */ export const [smoothStep, smoothStep2, smoothStep3, smoothStep4] = defHofOp< - MultiVecOpV, - VecOpV ->(_step, HOF_VVV, "o,e1,e2,a", undefined, "o", 3, DEFAULT_OUT); + MultiVecOpVVV, + VecOpVVV +>(_step, FN3(), "o,e1,e2,a", undefined, "o", 3, DEFAULT_OUT); diff --git a/packages/vectors/src/step.ts b/packages/vectors/src/step.ts index 77fc8a17ac..008aff92b0 100644 --- a/packages/vectors/src/step.ts +++ b/packages/vectors/src/step.ts @@ -1,5 +1,5 @@ import { step as _step } from "@thi.ng/math"; -import { MultiVecOpV, VecOpV } from "./api"; +import { MultiVecOpVV, VecOpVV } from "./api"; import { DEFAULT_OUT, defHofOp } from "./internal/codegen"; import { FN2 } from "./internal/templates"; @@ -10,7 +10,7 @@ import { FN2 } from "./internal/templates"; * @param e * @param v */ -export const [step, step2, step3, step4] = defHofOp( +export const [step, step2, step3, step4] = defHofOp( _step, FN2("op"), "o,e,a", diff --git a/packages/vectors/src/subi.ts b/packages/vectors/src/subi.ts new file mode 100644 index 0000000000..b5209f75ba --- /dev/null +++ b/packages/vectors/src/subi.ts @@ -0,0 +1,9 @@ +import { defBitOp, defBitOpN } from "./internal/codegen"; + +export const [subI, subI2, subI3, subI4] = defBitOp("-", true); + +export const [subU, subU2, subU3, subU4] = defBitOp("-"); + +export const [subNI, subNI2, subNI3, subNI4] = defBitOpN("-", true); + +export const [subNU, subNU2, subNU3, subNU4] = defBitOpN("-"); diff --git a/packages/vectors/src/subm.ts b/packages/vectors/src/subm.ts index 8c23173c01..fe2d8a46a0 100644 --- a/packages/vectors/src/subm.ts +++ b/packages/vectors/src/subm.ts @@ -3,9 +3,10 @@ import { ARGS_VVV, defOp } from "./internal/codegen"; import { SUBM } from "./internal/templates"; /** - * Returns `out = (a + b) * c`. + * Returns `out = (a - b) * c`. * * @see madd + * @see addm */ export const [subm, subm2, subm3, subm4] = defOp( SUBM, diff --git a/packages/vectors/src/subn.ts b/packages/vectors/src/subn.ts index e8f49e9235..5322e24d96 100644 --- a/packages/vectors/src/subn.ts +++ b/packages/vectors/src/subn.ts @@ -1,3 +1,3 @@ -import { defMathNOp } from "./internal/codegen"; +import { defMathOpN } from "./internal/codegen"; -export const [subN, subN2, subN3, subN4] = defMathNOp("-"); +export const [subN, subN2, subN3, subN4] = defMathOpN("-"); diff --git a/packages/vectors/src/sum.ts b/packages/vectors/src/sum.ts index 33ebd10d7f..97109942bc 100644 --- a/packages/vectors/src/sum.ts +++ b/packages/vectors/src/sum.ts @@ -7,7 +7,7 @@ import { vop } from "./internal/vop"; * * @param v */ -export const sum: MultiVecOpRoV = vop(0); +export const sum: MultiVecOpRoV = vop(); sum.default((v) => reduce(add(), v)); diff --git a/packages/vectors/src/swizzle.ts b/packages/vectors/src/swizzle.ts index eb88f08eef..095c4eb538 100644 --- a/packages/vectors/src/swizzle.ts +++ b/packages/vectors/src/swizzle.ts @@ -10,8 +10,12 @@ import { setC2, setC3, setC4 } from "./setc"; * @param x new x coord index * @param y new y coord index */ -export const swizzle2 = (out: Vec, a: ReadonlyVec, x: number, y: number) => - setC2(out || a, a[x] || 0, a[y] || 0); +export const swizzle2 = ( + out: Vec | null, + a: ReadonlyVec, + x: number, + y: number +) => setC2(out || a, a[x] || 0, a[y] || 0); /** * Places a re-ordered 3D version of vector `a` into `out`. The given @@ -24,7 +28,7 @@ export const swizzle2 = (out: Vec, a: ReadonlyVec, x: number, y: number) => * @param z new z coord index */ export const swizzle3 = ( - out: Vec, + out: Vec | null, a: ReadonlyVec, x: number, y: number, @@ -43,7 +47,7 @@ export const swizzle3 = ( * @param w new w coord index */ export const swizzle4 = ( - out: Vec, + out: Vec | null, a: ReadonlyVec, x: number, y: number, @@ -56,3 +60,64 @@ export const swapXY: VecOpV = (out, v) => swizzle3(out, v, 1, 0, 2); export const swapXZ: VecOpV = (out, v) => swizzle3(out, v, 2, 1, 0); export const swapYZ: VecOpV = (out, v) => swizzle3(out, v, 0, 2, 1); + +/** + * Sets `out[a] = n`, returns `out`. + * + * @param out + * @param n + * @param a + */ +export const setSwizzle1 = (out: Vec, n: number, a: number) => ( + (out[a] = n), out +); + +/** + * Sets `out[a] = v.x, out[b] = v.y`, returns `out`. + * + * @param out + * @param v + * @param a + * @param b + */ +export const setSwizzle2 = (out: Vec, v: ReadonlyVec, a: number, b: number) => ( + ((out[a] = v[0]), (out[b] = v[1])), out +); + +/** + * Sets `out[a] = v.x, out[b] = v.y, out[c] = v.z`, returns `out`. + * + * @param out + * @param v + * @param a + * @param b + * @param c + */ +export const setSwizzle3 = ( + out: Vec, + v: ReadonlyVec, + a: number, + b: number, + c: number +) => (((out[a] = v[0]), (out[b] = v[1]), (out[c] = v[2])), out); + +/** + * Sets `out[a] = v.x, out[b] = v.y, out[c] = v.z, out[d]=v.w`, returns `out`. + * + * @param out + * @param v + * @param a + * @param b + * @param c + * @param d + */ +export const setSwizzle4 = ( + out: Vec, + v: ReadonlyVec, + a: number, + b: number, + c: number, + d: number +) => ( + ((out[a] = v[0]), (out[b] = v[1]), (out[c] = v[2]), (out[d] = v[3])), out +); diff --git a/packages/vectors/src/vec-of.ts b/packages/vectors/src/vec-of.ts new file mode 100644 index 0000000000..8aaedfc539 --- /dev/null +++ b/packages/vectors/src/vec-of.ts @@ -0,0 +1,7 @@ +/** + * Returns new vector of `size` with all components set to `n`. + * + * @param size + * @param n + */ +export const vecOf = (size: number, n = 0) => new Array(size).fill(n); diff --git a/packages/vectors/src/vec2.ts b/packages/vectors/src/vec2.ts index a6fb2a9910..a9a7f01097 100644 --- a/packages/vectors/src/vec2.ts +++ b/packages/vectors/src/vec2.ts @@ -89,8 +89,8 @@ export class Vec2 extends AVec implements IHash, IVector { static readonly ZERO = new Vec2(ZERO2); static readonly ONE = new Vec2(ONE2); - x: number; - y: number; + x!: number; + y!: number; [id: number]: number; constructor(buf?: Vec, offset = 0, stride = 1) { diff --git a/packages/vectors/src/vec3.ts b/packages/vectors/src/vec3.ts index a5dba6795a..e379eeea7a 100644 --- a/packages/vectors/src/vec3.ts +++ b/packages/vectors/src/vec3.ts @@ -91,9 +91,9 @@ export class Vec3 extends AVec implements IHash, IVector { static readonly ZERO = new Vec3(ZERO3); static readonly ONE = new Vec3(ONE3); - x: number; - y: number; - z: number; + x!: number; + y!: number; + z!: number; [id: number]: number; constructor(buf?: Vec, offset = 0, stride = 1) { diff --git a/packages/vectors/src/vec4.ts b/packages/vectors/src/vec4.ts index b4c6022e7c..37b26f6fd5 100644 --- a/packages/vectors/src/vec4.ts +++ b/packages/vectors/src/vec4.ts @@ -91,10 +91,10 @@ export class Vec4 extends AVec implements IHash, IVector { static readonly ZERO = new Vec4(ZERO4); static readonly ONE = new Vec4(ONE4); - x: number; - y: number; - z: number; - w: number; + x!: number; + y!: number; + z!: number; + w!: number; [id: number]: number; constructor(buf?: Vec, offset = 0, stride = 1) { diff --git a/packages/vectors/src/wrap.ts b/packages/vectors/src/wrap.ts index 097f9792f3..e66c771910 100644 --- a/packages/vectors/src/wrap.ts +++ b/packages/vectors/src/wrap.ts @@ -1,10 +1,10 @@ import { wrap as _wrap } from "@thi.ng/math"; import { MultiVecOpVVV, VecOpVVV } from "./api"; import { ARGS_VVV, defHofOp } from "./internal/codegen"; -import { HOF_VVV } from "./internal/templates"; +import { FN3 } from "./internal/templates"; export const [wrap, wrap2, wrap3, wrap4] = defHofOp( _wrap, - HOF_VVV, + FN3(), ARGS_VVV ); diff --git a/packages/vectors/test/tsconfig.json b/packages/vectors/test/tsconfig.json index 2c9c12a650..6818db18c0 100644 --- a/packages/vectors/test/tsconfig.json +++ b/packages/vectors/test/tsconfig.json @@ -3,9 +3,7 @@ "compilerOptions": { "outDir": "../build", "module": "commonjs", + "noImplicitThis": false }, - "include": [ - "./**/*.ts", - "../src/**/*.ts" - ] -} \ No newline at end of file + "include": ["./**/*.ts", "../src/**/*.ts"] +} diff --git a/packages/vectors/tsconfig.json b/packages/vectors/tsconfig.json index bcf03f18b4..1402f79691 100644 --- a/packages/vectors/tsconfig.json +++ b/packages/vectors/tsconfig.json @@ -3,9 +3,8 @@ "compilerOptions": { "outDir": ".", "module": "es6", - "target": "es6" + "target": "es6", + "noImplicitThis": false }, - "include": [ - "./src/**/*.ts" - ] -} \ No newline at end of file + "include": ["./src/**/*.ts"] +} diff --git a/packages/webgl-msdf/.npmignore b/packages/webgl-msdf/.npmignore new file mode 100644 index 0000000000..74ea62d1fa --- /dev/null +++ b/packages/webgl-msdf/.npmignore @@ -0,0 +1,12 @@ +.meta +.nyc_output +*.html +*.tgz +build +coverage +dev +doc +export +src* +test +tsconfig.json diff --git a/packages/webgl-msdf/CHANGELOG.md b/packages/webgl-msdf/CHANGELOG.md new file mode 100644 index 0000000000..62955ab839 --- /dev/null +++ b/packages/webgl-msdf/CHANGELOG.md @@ -0,0 +1,20 @@ +# Change Log + +All notable changes to this project will be documented in this file. +See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +# 0.1.0 (2019-07-07) + + +### Bug Fixes + +* **webgl-msdf:** update madd call sites ([#95](https://github.com/thi-ng/umbrella/issues/95)) ([5c6fa50](https://github.com/thi-ng/umbrella/commit/5c6fa50)) +* **webgl-msdf:** update shader (remove prefixes) ([33731e9](https://github.com/thi-ng/umbrella/commit/33731e9)) +* **webgl-msdf:** update textWidth & align fns ([dd6f752](https://github.com/thi-ng/umbrella/commit/dd6f752)) + + +### Features + +* **webgl:** initial integration of shader-ast ([73faffd](https://github.com/thi-ng/umbrella/commit/73faffd)) +* **webgl-msdf:** add more TextOpts, update TextAlign fns ([4602883](https://github.com/thi-ng/umbrella/commit/4602883)) +* **webgl-msdf:** initial import MSDF font rendering pkg ([22bcc24](https://github.com/thi-ng/umbrella/commit/22bcc24)) diff --git a/packages/webgl-msdf/LICENSE b/packages/webgl-msdf/LICENSE new file mode 100644 index 0000000000..8dada3edaf --- /dev/null +++ b/packages/webgl-msdf/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/packages/webgl-msdf/README.md b/packages/webgl-msdf/README.md new file mode 100644 index 0000000000..71a5fb59ae --- /dev/null +++ b/packages/webgl-msdf/README.md @@ -0,0 +1,66 @@ +# @thi.ng/webgl-msdf + +[![npm (scoped)](https://img.shields.io/npm/v/@thi.ng/webgl-msdf.svg)](https://www.npmjs.com/package/@thi.ng/webgl-msdf) +![npm downloads](https://img.shields.io/npm/dm/@thi.ng/webgl-msdf.svg) +[![Twitter Follow](https://img.shields.io/twitter/follow/thing_umbrella.svg?style=flat-square&label=twitter)](https://twitter.com/thing_umbrella) + +This project is part of the +[@thi.ng/umbrella](https://github.com/thi-ng/umbrella/) monorepo. + + + +- [About](#about) +- [Installation](#installation) +- [Dependencies](#dependencies) +- [Usage examples](#usage-examples) +- [Authors](#authors) +- [License](#license) + + + +## About + +This package provides [multi-channel SDF font +rendering](https://github.com/Chlumsky/msdfgen) capabilities for +[@thi.ng/webgl](https://github.com/thi-ng/umbrella/tree/master/packages/webgl), +incl. optional support for basic text alignment, vertex colors (e.g. for +multi-color text), and shader options to draw outlines for each +character. Furthermore, the key GLSL functions are provided as shader +snippets to embed this functionality in custom shaders without having to +resort to copy & paste. + +There're different versions of MSDF font generators. The format +supported by this module is based on [Don +McCurdy's](https://msdf-bmfont.donmccurdy.com/). + +## Installation + +```bash +yarn add @thi.ng/webgl-msdf +``` + +## Dependencies + +- [@thi.ng/api](https://github.com/thi-ng/umbrella/tree/master/packages/api) +- [@thi.ng/transducers](https://github.com/thi-ng/umbrella/tree/master/packages/transducers) +- [@thi.ng/vectors](https://github.com/thi-ng/umbrella/tree/master/packages/vectors) +- [@thi.ng/vector-pools](https://github.com/thi-ng/umbrella/tree/master/packages/vector-pools) +- [@thi.ng/webgl](https://github.com/thi-ng/umbrella/tree/master/packages/webgl) + +## Usage examples + +See the bundled [webgl-msdf +example](https://github.com/thi-ng/umbrella/tree/master/examples/webgl-msdf) +for reference... + +```ts +import * as msdf from "@thi.ng/webgl-msdf"; +``` + +## Authors + +- Karsten Schmidt + +## License + +© 2019 Karsten Schmidt // Apache Software License 2.0 diff --git a/packages/webgl-msdf/package.json b/packages/webgl-msdf/package.json new file mode 100644 index 0000000000..08c0037361 --- /dev/null +++ b/packages/webgl-msdf/package.json @@ -0,0 +1,56 @@ +{ + "name": "@thi.ng/webgl-msdf", + "version": "0.1.0", + "description": "TODO", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", + "typings": "./index.d.ts", + "repository": { + "type": "git", + "url": "https://github.com/thi-ng/umbrella.git" + }, + "homepage": "https://github.com/thi-ng/umbrella/tree/master/packages/webgl-msdf", + "author": "Karsten Schmidt ", + "license": "Apache-2.0", + "scripts": { + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module", + "test": "rimraf build && tsc -p test/tsconfig.json && nyc mocha build/test/*.js", + "clean": "rimraf *.js *.d.ts .nyc_output build coverage doc lib", + "cover": "yarn test && nyc report --reporter=lcov", + "doc": "node_modules/.bin/typedoc --mode modules --out doc src", + "pub": "yarn build && yarn publish --access public" + }, + "devDependencies": { + "@types/mocha": "^5.2.6", + "@types/node": "^12.0.8", + "mocha": "^6.1.4", + "nyc": "^14.0.0", + "typedoc": "^0.14.2", + "typescript": "^3.5.2" + }, + "dependencies": { + "@thi.ng/api": "^6.3.0", + "@thi.ng/shader-ast": "^0.1.0", + "@thi.ng/transducers": "^5.4.0", + "@thi.ng/vector-pools": "^1.0.0", + "@thi.ng/vectors": "^3.0.0", + "@thi.ng/webgl": "^0.1.0" + }, + "keywords": [ + "ES6", + "font", + "MSDF", + "shader", + "text", + "typescript", + "typography", + "webgl" + ], + "publishConfig": { + "access": "public" + }, + "sideEffects": false +} diff --git a/packages/webgl-msdf/src/api.ts b/packages/webgl-msdf/src/api.ts new file mode 100644 index 0000000000..cb7f18e4c5 --- /dev/null +++ b/packages/webgl-msdf/src/api.ts @@ -0,0 +1,85 @@ +import { Fn3, IObjectOf } from "@thi.ng/api"; +import { ReadonlyVec } from "@thi.ng/vectors"; +import { GLVec4 } from "@thi.ng/webgl"; + +export interface RawGlyphs { + pages: string[]; + info: { + face: string; + size: number; + }; + common: { + scaleW: number; + scaleH: number; + lineHeight: number; + base: number; + }; + chars: { + id: number; + x: number; + y: number; + xoffset: number; + yoffset: number; + width: number; + height: number; + xadvance: number; + }[]; +} + +export interface MSDFFont { + fontFace: string; + fontSize: number; + tex: string; + size: ReadonlyVec; + lineHeight: number; + baseLine: number; + chars: IObjectOf<{ + pos: ReadonlyVec; + size: ReadonlyVec; + offset: ReadonlyVec; + step: number; + }>; +} + +/** + * Alignment function for a single line of text. + * + * @param font + * @param dir + * @param line + */ +export type TextAlign = Fn3, string, number>; + +export interface TextOpts { + /** + * Text alignment function (individual per line). + * Default: `alignLeft` + */ + align: TextAlign; + /** + * Horizontal spacing multiplier. Default: 1.0 + */ + spacing: number; + /** + * Leading (line height multiplier). Default: 1.0 + */ + leading: number; + /** + * X direction. Default: 1 + */ + dirX: 1 | -1; + /** + * Y direction. Default: 1 + */ + dirY: 1 | -1; + /** + * If true, `text()` will produce color attributes. + */ + useColor: boolean; + /** + * Default RGBA color, only used if `useColor = true`. + */ + color: GLVec4; +} + +export type ColorString = [GLVec4, string]; diff --git a/packages/webgl-msdf/src/convert.ts b/packages/webgl-msdf/src/convert.ts new file mode 100644 index 0000000000..042d5d85aa --- /dev/null +++ b/packages/webgl-msdf/src/convert.ts @@ -0,0 +1,27 @@ +import { MSDFFont, RawGlyphs } from "./api"; + +/** + * Takes a JSON spec produced by the MSDF font generator at + * https://github.com/donmccurdy/msdf-bmfont-web and transforms it into + * a filtered, more compact glyph spec used by the functions of this + * module. + * + * @param raw + */ +export const convertGlyphs = (raw: RawGlyphs): MSDFFont => ({ + fontFace: raw.info.face, + fontSize: raw.info.size, + lineHeight: raw.common.lineHeight, + baseLine: raw.common.base, + tex: raw.pages[0], + size: [raw.common.scaleW, raw.common.scaleH], + chars: raw.chars.reduce((acc: any, ch) => { + acc[String.fromCharCode(ch.id)] = { + pos: [ch.x, ch.y], + offset: [ch.xoffset, ch.yoffset], + size: [ch.width, ch.height], + step: ch.xadvance + }; + return acc; + }, {}) +}); diff --git a/packages/webgl-msdf/src/index.ts b/packages/webgl-msdf/src/index.ts new file mode 100644 index 0000000000..89c6e12fd4 --- /dev/null +++ b/packages/webgl-msdf/src/index.ts @@ -0,0 +1,4 @@ +export * from "./api"; +export * from "./convert"; +export * from "./shader"; +export * from "./text"; diff --git a/packages/webgl-msdf/src/shader.ts b/packages/webgl-msdf/src/shader.ts new file mode 100644 index 0000000000..40cec5d80d --- /dev/null +++ b/packages/webgl-msdf/src/shader.ts @@ -0,0 +1,106 @@ +import { + $, + $x, + $y, + $z, + add, + assign, + clamp, + defMain, + defn, + discard, + div, + FLOAT0, + FLOAT05, + FLOAT1, + FloatSym, + fwidth, + ifThen, + lt, + max, + min, + mix, + mul, + ret, + sub, + sym, + texture, + vec2, + Vec2Sym, + vec4 +} from "@thi.ng/shader-ast"; +import { ONE4, ZERO4 } from "@thi.ng/vectors"; +import { DEFAULT_BLEND, GLVec4, ShaderSpec } from "@thi.ng/webgl"; + +export interface MSDFShaderOpts { + color: boolean; +} + +export const median3 = defn("float", "median3", [["vec3"]], (v) => [ + ret(max(min($x(v), $y(v)), min(max($x(v), $y(v)), $z(v)))) +]); + +export const msdfSample = defn( + "vec2", + "msdfSample", + [["sampler2D"], ["vec2"]], + (tex, uv) => { + let sd: FloatSym; + let w: FloatSym; + return [ + (sd = sym(sub(median3($(texture(tex, uv), "xyz")), FLOAT05))), + (w = sym(clamp(add(div(sd, fwidth(sd)), FLOAT05), FLOAT0, FLOAT1))), + ret(vec2(sd, w)) + ]; + } +); + +export const msdfShader = (opts: Partial = {}): ShaderSpec => ({ + vs: (gl, unis, ins, outs) => [ + defMain(() => [ + assign(outs.vuv, ins.uv), + opts.color ? assign(outs.vcolor, ins.color) : null, + assign( + gl.gl_Position, + mul(mul(unis.proj, unis.modelview), vec4(ins.position, 1)) + ) + ]) + ], + fs: (_, unis, ins, outs) => [ + defMain(() => { + let w: Vec2Sym; + return [ + (w = sym(msdfSample(unis.tex, ins.vuv))), + assign( + outs.fragColor, + mix(unis.bg, opts.color ? ins.vcolor : unis.fg, $y(w)) + ), + ifThen(lt($x(w), unis.thresh), [discard]) + ]; + }) + ], + ext: { + OES_standard_derivatives: true + }, + attribs: { + position: "vec3", + uv: "vec2", + ...(opts.color ? { color: "vec4" } : null) + }, + varying: { + vuv: "vec2", + ...(opts.color ? { vcolor: "vec4" } : null) + }, + uniforms: { + modelview: "mat4", + proj: "mat4", + tex: "sampler2D", + thresh: ["float", 1e-3], + bg: ["vec4", ZERO4], + ...(!opts.color ? { fg: ["vec4", ONE4] } : null) + }, + state: { + blend: true, + blendFn: DEFAULT_BLEND + } +}); diff --git a/packages/webgl-msdf/src/text.ts b/packages/webgl-msdf/src/text.ts new file mode 100644 index 0000000000..a19d532714 --- /dev/null +++ b/packages/webgl-msdf/src/text.ts @@ -0,0 +1,119 @@ +import { + add, + map, + mapcat, + range, + transduce +} from "@thi.ng/transducers"; +import { AttribPool, GLType } from "@thi.ng/vector-pools"; +import { + add2, + div2, + madd2, + mul2, + ONE4 +} from "@thi.ng/vectors"; +import { GLVec4, ModelSpec } from "@thi.ng/webgl"; +import { MSDFFont, TextAlign, TextOpts } from "./api"; + +export const text = ( + glyphs: MSDFFont, + txt: string, + opts?: Partial +) => { + opts = { + align: alignLeft, + spacing: 1, + leading: 1, + dirX: 1, + dirY: 1, + color: ONE4, + ...opts + }; + const dir: number[] = [opts.dirX!, opts.dirY!]; + const lineHeight = glyphs.lineHeight * opts.leading! * opts.dirY!; + const len = txt.replace("\n", "").length; + const attribs = new AttribPool({ + attribs: { + position: { type: GLType.F32, size: 3, byteOffset: 0 }, + uv: { type: GLType.F32, size: 2, byteOffset: 12 }, + ...(opts.useColor + ? { + color: { + type: GLType.F32, + default: opts.color, + size: 4, + byteOffset: 20 + } + } + : null) + }, + num: len * 4, + mem: { + size: len * 4 * (opts.useColor ? 36 : 20) + 8 + } + }); + const lines = txt.split("\n"); + for (let i = 0, yy = 0, id = 0; i < lines.length; i++) { + const line = lines[i]; + let xx = opts.align!(glyphs, opts, line); + for (let j = 0; j < line.length; j++, id++) { + const g = glyphs.chars[line[j]]; + const [sx, sy] = mul2([], g.size, dir); + const [x, y] = madd2([], g.offset, dir, [xx, yy]); + attribs.setAttribValues( + "position", + [ + [x, y, 0], + [x + sx, y, 0], + [x + sx, y + sy, 0], + [x, y + sy, 0] + ], + id * 4 + ); + attribs.setAttribValues( + "uv", + [ + div2([], g.pos, glyphs.size), + div2([], [g.pos[0] + g.size[0], g.pos[1]], glyphs.size), + div2([], add2([], g.pos, g.size), glyphs.size), + div2([], [g.pos[0], g.pos[1] + g.size[1]], glyphs.size) + ], + id * 4 + ); + xx += g.step * opts.dirX! * opts.spacing!; + } + yy += lineHeight; + } + return { + attribPool: attribs, + indices: { + data: new Uint16Array([ + ...mapcat( + (i) => [i, i + 1, i + 2, i, i + 2, i + 3], + range(0, len * 4, 4) + ) + ]) + }, + uniforms: {}, + num: len * 6, + mode: 4 // TRIANGLES + }; +}; + +export const textWidth = ( + font: MSDFFont, + opts: Partial, + txt: string +) => { + const s = opts.spacing !== undefined ? opts.spacing : 1; + return transduce(map((x) => font.chars[x].step * s), add(), txt); +}; + +export const alignLeft: TextAlign = () => 0; + +export const alignRight: TextAlign = (font, opts, line) => + -(opts.dirX || 1) * textWidth(font, opts, line); + +export const alignCenter: TextAlign = (font, opts, line) => + (-(opts.dirX || 1) * textWidth(font, opts, line)) / 2; diff --git a/packages/webgl-msdf/test/index.ts b/packages/webgl-msdf/test/index.ts new file mode 100644 index 0000000000..908abfd690 --- /dev/null +++ b/packages/webgl-msdf/test/index.ts @@ -0,0 +1,6 @@ +// import * as assert from "assert"; +// import * as wm from "../src/index"; + +describe("webgl-msdf", () => { + it("tests pending"); +}); diff --git a/packages/webgl-msdf/test/tsconfig.json b/packages/webgl-msdf/test/tsconfig.json new file mode 100644 index 0000000000..f6e63560dd --- /dev/null +++ b/packages/webgl-msdf/test/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../../tsconfig.json", + "compilerOptions": { + "outDir": "../build", + "module": "commonjs" + }, + "include": [ + "./**/*.ts", + "../src/**/*.ts" + ] +} diff --git a/packages/webgl-msdf/tsconfig.json b/packages/webgl-msdf/tsconfig.json new file mode 100644 index 0000000000..893b9979c5 --- /dev/null +++ b/packages/webgl-msdf/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": ".", + "module": "es6", + "target": "es6" + }, + "include": [ + "./src/**/*.ts" + ] +} diff --git a/packages/webgl/.npmignore b/packages/webgl/.npmignore new file mode 100644 index 0000000000..74ea62d1fa --- /dev/null +++ b/packages/webgl/.npmignore @@ -0,0 +1,12 @@ +.meta +.nyc_output +*.html +*.tgz +build +coverage +dev +doc +export +src* +test +tsconfig.json diff --git a/packages/webgl/CHANGELOG.md b/packages/webgl/CHANGELOG.md new file mode 100644 index 0000000000..ce881f2ac6 --- /dev/null +++ b/packages/webgl/CHANGELOG.md @@ -0,0 +1,51 @@ +# Change Log + +All notable changes to this project will be documented in this file. +See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +# 0.1.0 (2019-07-07) + + +### Bug Fixes + +* **webgl:** also disable prefixes in prepareShaderSource() ([18ca4b5](https://github.com/thi-ng/umbrella/commit/18ca4b5)) +* **webgl:** apply ModelSpec mode in compileModel, fix/simplify draw fns ([67334a6](https://github.com/thi-ng/umbrella/commit/67334a6)) +* **webgl:** EXPORT_FRAGCOL webgl2 default out ([684e7fc](https://github.com/thi-ng/umbrella/commit/684e7fc)) +* **webgl:** gl2 texStorage2D() levels ([3d36527](https://github.com/thi-ng/umbrella/commit/3d36527)) +* **webgl:** uniform array & output var handling ([7e559a1](https://github.com/thi-ng/umbrella/commit/7e559a1)) +* **webgl:** update GPGPU texture & shader handling ([ce286ad](https://github.com/thi-ng/umbrella/commit/ce286ad)) +* **webgl:** update lambert shader preset ([2fea507](https://github.com/thi-ng/umbrella/commit/2fea507)) +* **webgl:** update texture mipmap config & handling ([2a5b87f](https://github.com/thi-ng/umbrella/commit/2a5b87f)) + + +### Features + +* **webgl:** add (incomplete) texture format specs ([cf7c408](https://github.com/thi-ng/umbrella/commit/cf7c408)) +* **webgl:** add ALIAS_TEXTURE GLSL macro ([4640ce4](https://github.com/thi-ng/umbrella/commit/4640ce4)) +* **webgl:** add AttribPool support, update shader ext handling, add screen2d() ([f8081f2](https://github.com/thi-ng/umbrella/commit/f8081f2)) +* **webgl:** add cube modelspec factory ([29791fd](https://github.com/thi-ng/umbrella/commit/29791fd)) +* **webgl:** add cubemap support & cubeMap() factory fn ([ad43a1c](https://github.com/thi-ng/umbrella/commit/ad43a1c)) +* **webgl:** add glCanvas() extension support ([07edcd0](https://github.com/thi-ng/umbrella/commit/07edcd0)) +* **webgl:** add glCanvas() factory fn & WebGLCanvasOpts ([a60eb2e](https://github.com/thi-ng/umbrella/commit/a60eb2e)) +* **webgl:** add gpgpu skeleton ([582b57a](https://github.com/thi-ng/umbrella/commit/582b57a)) +* **webgl:** add GPGPU texture config support ([393e04e](https://github.com/thi-ng/umbrella/commit/393e04e)) +* **webgl:** add IDeref support for uniform values ([d7679d6](https://github.com/thi-ng/umbrella/commit/d7679d6)) +* **webgl:** add initial AttribPool & VAO support, update ModelSpec & draw fns ([41cf85f](https://github.com/thi-ng/umbrella/commit/41cf85f)) +* **webgl:** add more GLSL/WebGL2 types ([648ed52](https://github.com/thi-ng/umbrella/commit/648ed52)) +* **webgl:** add option to throw error if missing GL extension ([b5da3b2](https://github.com/thi-ng/umbrella/commit/b5da3b2)) +* **webgl:** add screen2d() arity to extract screen size from gl ctx ([7f38f10](https://github.com/thi-ng/umbrella/commit/7f38f10)) +* **webgl:** add texture format consts / decls, GLSL types ([b243ebb](https://github.com/thi-ng/umbrella/commit/b243ebb)) +* **webgl:** add texture gens, add opt uv support for lambert shader ([4a1a5b9](https://github.com/thi-ng/umbrella/commit/4a1a5b9)) +* **webgl:** add texture lookup shader snippets ([8af4943](https://github.com/thi-ng/umbrella/commit/8af4943)) +* **webgl:** add webgl resource factory fns, update buffer() arg order ([131e551](https://github.com/thi-ng/umbrella/commit/131e551)) +* **webgl:** add WebGL2 support for FBO/Texture, add floatTexture() ctor fn ([8941d82](https://github.com/thi-ng/umbrella/commit/8941d82)) +* **webgl:** allow depth textures as fbo depth buffer, various refactorings ([d72ca70](https://github.com/thi-ng/umbrella/commit/d72ca70)) +* **webgl:** convert fullscreen quad into fn, uv's optional ([610f37b](https://github.com/thi-ng/umbrella/commit/610f37b)) +* **webgl:** import webgl pkg, ported & updated from CLJ thi.ng/geom ([f4c0634](https://github.com/thi-ng/umbrella/commit/f4c0634)) +* **webgl:** initial integration of shader-ast ([73faffd](https://github.com/thi-ng/umbrella/commit/73faffd)) +* **webgl:** TS strictNullChecks, assertions, minor type updates ([ad672c7](https://github.com/thi-ng/umbrella/commit/ad672c7)) +* **webgl:** update GLSL syntax impls, migrate Shader.fromSpec() ([02f94d7](https://github.com/thi-ng/umbrella/commit/02f94d7)) +* **webgl:** update GLSL_HEADER & LAMBERT shader preset ([05f5059](https://github.com/thi-ng/umbrella/commit/05f5059)) +* **webgl:** update shaderSourceFromAST(), update shader presets, remove prefixes ([6aa5715](https://github.com/thi-ng/umbrella/commit/6aa5715)) +* **webgl:** update uniform setters, update deps ([2be6a23](https://github.com/thi-ng/umbrella/commit/2be6a23)) +* **webgl:** update/add array type UniformDecl's ([1f19196](https://github.com/thi-ng/umbrella/commit/1f19196)) diff --git a/packages/webgl/LICENSE b/packages/webgl/LICENSE new file mode 100644 index 0000000000..8dada3edaf --- /dev/null +++ b/packages/webgl/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/packages/webgl/README.md b/packages/webgl/README.md new file mode 100644 index 0000000000..2f181ba81c --- /dev/null +++ b/packages/webgl/README.md @@ -0,0 +1,101 @@ +# @thi.ng/webgl + +[![npm (scoped)](https://img.shields.io/npm/v/@thi.ng/webgl.svg)](https://www.npmjs.com/package/@thi.ng/webgl) +![npm downloads](https://img.shields.io/npm/dm/@thi.ng/webgl.svg) +[![Twitter Follow](https://img.shields.io/twitter/follow/thing_umbrella.svg?style=flat-square&label=twitter)](https://twitter.com/thing_umbrella) + +This project is part of the +[@thi.ng/umbrella](https://github.com/thi-ng/umbrella/) monorepo. + + + +- [About](#about) + - [Features](#features) +- [Installation](#installation) +- [Dependencies](#dependencies) +- [Support packages](#support-packages) +- [Usage examples](#usage-examples) +- [Authors](#authors) +- [License](#license) + + + +## About + +Declarative WebGL 1.0 / 2.0 abstraction layer, partially ported & +updated from Clojure/ClojureScript versions of +[thi.ng/geom](http://thi.ng/geom). + +### Features + +- Extensive set of WebGL related types & interfaces +- Declarative shader definition + - option to fully define shaders in TypeScript and transpile to GLSL (via + [@thi.ng/shader-ast](https://github.com/thi-ng/umbrella/tree/master/packages/shader-ast)) + - attribute, varying, uniform & output type declarations via a simple config object + - GLSL code generation of data type declarations + - automatic support for GLSL ES 1.0 & 3.0 + - optional layout attrib layout support for GLES 3 (WebGL2) + - automatic & typed uniform setters + - pre-declared desired GL draw state flags / settings + - customizable shader presets +- Declarative geometry, attribute & index buffer specs +- Declarative instancing (always available in WebGL2, or via ANGLE ext in WebGL1) + - also supported by bundled shader presets +- Texture wrapper & declarative config +- FBO support with multiple attachments & render buffers +- GPGPU job utilities +- Geometry & texture generators +- WebGL extension helpers +- WebGL canvas creation / setup + +Status: Alpha / WIP + +## Installation + +```bash +yarn add @thi.ng/webgl +``` + +## Dependencies + +- [@thi.ng/api](https://github.com/thi-ng/umbrella/tree/master/packages/api) +- [@thi.ng/associative](https://github.com/thi-ng/umbrella/tree/master/packages/associative) +- [@thi.ng/binary](https://github.com/thi-ng/umbrella/tree/master/packages/binary) +- [@thi.ng/checks](https://github.com/thi-ng/umbrella/tree/master/packages/checks) +- [@thi.ng/errors](https://github.com/thi-ng/umbrella/tree/master/packages/errors) +- [@thi.ng/matrices](https://github.com/thi-ng/umbrella/tree/master/packages/matrices) +- [@thi.ng/shader-ast](https://github.com/thi-ng/umbrella/tree/master/packages/shader-ast) +- [@thi.ng/shader-ast-glsl](https://github.com/thi-ng/umbrella/tree/master/packages/shader-ast-glsl) +- [@thi.ng/shader-ast-stdlib](https://github.com/thi-ng/umbrella/tree/master/packages/shader-ast-stdlib) +- [@thi.ng/transducers](https://github.com/thi-ng/umbrella/tree/master/packages/transducers) +- [@thi.ng/vector-pools](https://github.com/thi-ng/umbrella/tree/master/packages/vector-pools) +- [@thi.ng/vectors](https://github.com/thi-ng/umbrella/tree/master/packages/vectors) + +## Support packages + +- [@thi.ng/shader-ast-stdlib](https://github.com/thi-ng/umbrella/tree/master/packages/shader-ast-stdlib) (also see readme for reference) +- [@thi.ng/webgl-msdf](https://github.com/thi-ng/umbrella/tree/master/packages/webgl-msdf) + +## Usage examples + +Several examples are included in the [/examples](https://github.com/thi-ng/umbrella/tree/master/examples) +folder of this repo... + +- [2D SDF](https://github.com/thi-ng/umbrella/tree/master/examples/shader-ast-sdf2d) +- [Raymarching](https://github.com/thi-ng/umbrella/tree/master/examples/shader-ast-raymarch) +- [Simplex noise](https://github.com/thi-ng/umbrella/tree/master/examples/shader-ast-noise) +- [Textured tunnel](https://github.com/thi-ng/umbrella/tree/master/examples/shader-ast-tunnel) +- [Cubemap](https://github.com/thi-ng/umbrella/tree/master/examples/webgl-cubemap) +- [Grid instancing](https://github.com/thi-ng/umbrella/tree/master/examples/webgl-grid) +- [GPGPU basics](https://github.com/thi-ng/umbrella/tree/master/examples/webgl-gpgpu-basics) +- [MSDF font rendering](https://github.com/thi-ng/umbrella/tree/master/examples/webgl-msdf) +- [SSAO deferred rendering](https://github.com/thi-ng/umbrella/tree/master/examples/webgl-ssao) + +## Authors + +- Karsten Schmidt + +## License + +© 2014 - 2019 Karsten Schmidt // Apache Software License 2.0 diff --git a/packages/webgl/package.json b/packages/webgl/package.json new file mode 100644 index 0000000000..a73379dcb3 --- /dev/null +++ b/packages/webgl/package.json @@ -0,0 +1,65 @@ +{ + "name": "@thi.ng/webgl", + "version": "0.1.0", + "description": "WebGL abstraction layer", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", + "typings": "./index.d.ts", + "repository": { + "type": "git", + "url": "https://github.com/thi-ng/umbrella.git" + }, + "homepage": "https://github.com/thi-ng/umbrella/tree/master/packages/webgl", + "author": "Karsten Schmidt ", + "license": "Apache-2.0", + "scripts": { + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module", + "test": "rimraf build && tsc -p test/tsconfig.json && nyc mocha build/test/*.js", + "clean": "rimraf *.js *.d.ts .nyc_output build coverage doc lib geo shaders textures", + "cover": "yarn test && nyc report --reporter=lcov", + "doc": "node_modules/.bin/typedoc --mode modules --out doc src", + "pub": "yarn build && yarn publish --access public" + }, + "devDependencies": { + "@types/mocha": "^5.2.6", + "@types/node": "^12.0.8", + "mocha": "^6.1.4", + "nyc": "^14.0.0", + "typedoc": "^0.14.2", + "typescript": "^3.5.2" + }, + "dependencies": { + "@thi.ng/api": "^6.3.0", + "@thi.ng/associative": "^2.4.0", + "@thi.ng/binary": "^1.0.7", + "@thi.ng/checks": "^2.2.0", + "@thi.ng/equiv": "^1.0.7", + "@thi.ng/errors": "^1.1.0", + "@thi.ng/matrices": "^0.5.0", + "@thi.ng/shader-ast": "^0.1.0", + "@thi.ng/shader-ast-glsl": "^0.1.0", + "@thi.ng/shader-ast-stdlib": "^0.1.0", + "@thi.ng/transducers": "^5.4.0", + "@thi.ng/vector-pools": "^1.0.0", + "@thi.ng/vectors": "^3.0.0" + }, + "keywords": [ + "declarative", + "ES6", + "FBO", + "GPGPU", + "graphics", + "shader", + "texture", + "typescript", + "webgl", + "webgl2" + ], + "publishConfig": { + "access": "public" + }, + "sideEffects": false +} diff --git a/packages/webgl/src/api.ts b/packages/webgl/src/api.ts new file mode 100644 index 0000000000..57de6c98b7 --- /dev/null +++ b/packages/webgl/src/api.ts @@ -0,0 +1,1153 @@ +import { + Fn, + Fn2, + Fn3, + Fn4, + IBind, + IDeref, + IObjectOf, + IRelease, + Tuple, + TypedArray +} from "@thi.ng/api"; +import { Func, Sym, Type } from "@thi.ng/shader-ast"; +import { GLSLTarget } from "@thi.ng/shader-ast-glsl"; +import { AttribPool } from "@thi.ng/vector-pools"; +import { ReadonlyVec } from "@thi.ng/vectors"; + +export const enum TextureFormat { + ALPHA = 0x1906, + DEPTH_COMPONENT = 0x1902, + DEPTH_COMPONENT16 = 0x81a5, + DEPTH_COMPONENT24 = 0x81a6, + DEPTH_COMPONENT32F = 0x8cac, + DEPTH_STENCIL = 0x84f9, + DEPTH24_STENCIL8 = 0x88f0, + DEPTH32F_STENCIL8 = 0x8cad, + LUMINANCE = 0x1909, + LUMINANCE_ALPHA = 0x190a, + R11F_G11F_B10F = 0x8c3a, + R16F = 0x822d, + R16I = 0x8233, + R16UI = 0x8234, + R32F = 0x822e, + R32I = 0x8235, + R32UI = 0x8236, + R8 = 0x8229, + R8_SNORM = 0x8f94, + R8I = 0x8231, + R8UI = 0x8232, + RED = 0x1903, + RED_INTEGER = 0x8d94, + RG = 0x8227, + RG_INTEGER = 0x8228, + RG16F = 0x822f, + RG16I = 0x8239, + RG16UI = 0x823a, + RG32F = 0x8230, + RG32I = 0x823b, + RG32UI = 0x823c, + RG8 = 0x822b, + RG8_SNORM = 0x8f95, + RG8I = 0x8237, + RG8UI = 0x8238, + RGB = 0x1907, + RGB_INTEGER = 0x8d98, + RGB10_A2 = 0x8059, + RGB10_A2UI = 0x906f, + RGB16F = 0x881b, + RGB16I = 0x8d89, + RGB16UI = 0x8d77, + RGB32F = 0x8815, + RGB32I = 0x8d83, + RGB32UI = 0x8d71, + RGB5_A1 = 0x8057, + RGB565 = 0x8d62, + RGB8 = 0x8051, + RGB8_SNORM = 0x8f96, + RGB8I = 0x8d8f, + RGB8UI = 0x8d7d, + RGB9_E5 = 0x8c3d, + RGBA = 0x1908, + RGBA_INTEGER = 0x8d99, + RGBA16F = 0x881a, + RGBA16I = 0x8d88, + RGBA16UI = 0x8d76, + RGBA32F = 0x8814, + RGBA32I = 0x8d82, + RGBA32UI = 0x8d70, + RGBA4 = 0x8056, + RGBA8 = 0x8058, + RGBA8_SNORM = 0x8f97, + RGBA8I = 0x8d8e, + RGBA8UI = 0x8d7c, + SRGB8 = 0x8c41, + SRGB8_ALPHA8 = 0x8c43 +} + +export const enum TextureType { + BYTE = 0x1400, + UNSIGNED_BYTE, + SHORT, + UNSIGNED_SHORT, + INT, + UNSIGNED_INT, + FLOAT, + HALF_FLOAT = 0x140b, + UNSIGNED_SHORT_4_4_4_4 = 0x8033, + UNSIGNED_SHORT_5_5_5_1 = 0x8034, + UNSIGNED_SHORT_5_6_5 = 0x8363, + UNSIGNED_INT_2_10_10_10_REV = 0x8368, + UNSIGNED_INT_24_8 = 0x84fa, + UNSIGNED_INT_10F_11F_11F_REV = 0x8c3b, + UNSIGNED_INT_5_9_9_9_REV = 0x8c3e, + HALF_FLOAT_OES = 0x8d61, + FLOAT_32_UNSIGNED_INT_24_8_REV = 0x8dad +} + +export interface TextureFormatDecl { + /** + * Base format + */ + format: TextureFormat; + /** + * Acceptable types and their byte sizes + */ + types: { [id: number]: number }; + /** + * Number of color components + */ + num: number; + /** + * Format is renderable + */ + render?: boolean; + /** + * Format is filterable (other than GL_NEAREST) + */ + filter?: boolean; + /** + * WebGL 2 only + */ + gl2?: boolean; +} + +export const TEX_FORMATS: IObjectOf = { + [TextureFormat.ALPHA]: { + format: TextureFormat.ALPHA, + render: true, + filter: true, + num: 1, + types: { + [TextureType.UNSIGNED_BYTE]: 1, + [TextureType.HALF_FLOAT]: 2, + [TextureType.HALF_FLOAT_OES]: 2, + [TextureType.FLOAT]: 4 + } + }, + [TextureFormat.DEPTH_COMPONENT16]: { + format: TextureFormat.DEPTH_COMPONENT, + render: true, + num: 1, + types: { + [TextureType.UNSIGNED_SHORT]: 2, + [TextureType.UNSIGNED_INT]: 4 + } + }, + [TextureFormat.DEPTH_COMPONENT24]: { + format: TextureFormat.DEPTH_COMPONENT, + render: true, + num: 1, + types: { [TextureType.UNSIGNED_INT]: 4 } + }, + [TextureFormat.DEPTH_COMPONENT32F]: { + format: TextureFormat.DEPTH_COMPONENT, + render: true, + num: 1, + types: { [TextureType.FLOAT]: 4 } + }, + [TextureFormat.DEPTH24_STENCIL8]: { + format: TextureFormat.DEPTH_STENCIL, + render: true, + num: 1, + types: { [TextureType.UNSIGNED_INT_24_8]: 4 } + }, + [TextureFormat.DEPTH32F_STENCIL8]: { + format: TextureFormat.DEPTH_STENCIL, + render: true, + num: 1, + types: { [TextureType.FLOAT_32_UNSIGNED_INT_24_8_REV]: 4 } + }, + [TextureFormat.LUMINANCE_ALPHA]: { + format: TextureFormat.LUMINANCE_ALPHA, + render: true, + filter: true, + num: 2, + types: { + [TextureType.UNSIGNED_BYTE]: 2, + [TextureType.HALF_FLOAT]: 4, + [TextureType.HALF_FLOAT_OES]: 4, + [TextureType.FLOAT]: 8 + } + }, + [TextureFormat.LUMINANCE]: { + format: TextureFormat.LUMINANCE, + render: true, + filter: true, + num: 1, + types: { + [TextureType.UNSIGNED_BYTE]: 1, + [TextureType.HALF_FLOAT]: 2, + [TextureType.HALF_FLOAT_OES]: 2, + [TextureType.FLOAT]: 4 + } + }, + [TextureFormat.R11F_G11F_B10F]: { + format: TextureFormat.RGB, + filter: true, + num: 3, + types: { + [TextureType.FLOAT]: 12, + [TextureType.HALF_FLOAT]: 6, + [TextureType.UNSIGNED_INT_10F_11F_11F_REV]: 4 + } + }, + [TextureFormat.R16F]: { + format: TextureFormat.RED, + filter: true, + num: 1, + types: { [TextureType.FLOAT]: 4, [TextureType.HALF_FLOAT]: 2 } + }, + [TextureFormat.R16I]: { + format: TextureFormat.RED_INTEGER, + render: true, + num: 1, + types: { [TextureType.SHORT]: 2 } + }, + [TextureFormat.R16UI]: { + format: TextureFormat.RED_INTEGER, + render: true, + num: 1, + types: { [TextureType.UNSIGNED_SHORT]: 2 } + }, + [TextureFormat.R32F]: { + format: TextureFormat.RED, + num: 1, + types: { [TextureType.FLOAT]: 4 } + }, + [TextureFormat.R32I]: { + format: TextureFormat.RED_INTEGER, + render: true, + num: 1, + types: { [TextureType.INT]: 4 } + }, + [TextureFormat.R32UI]: { + format: TextureFormat.RED_INTEGER, + render: true, + num: 1, + types: { [TextureType.UNSIGNED_INT]: 4 } + }, + [TextureFormat.R8_SNORM]: { + format: TextureFormat.RED, + filter: true, + num: 1, + types: { [TextureType.BYTE]: 1 } + }, + [TextureFormat.R8]: { + format: TextureFormat.RED, + render: true, + filter: true, + num: 1, + types: { [TextureType.UNSIGNED_BYTE]: 1 } + }, + [TextureFormat.R8I]: { + format: TextureFormat.RED_INTEGER, + render: true, + num: 1, + types: { [TextureType.BYTE]: 1 } + }, + [TextureFormat.R8UI]: { + format: TextureFormat.RED_INTEGER, + render: true, + num: 1, + types: { [TextureType.UNSIGNED_BYTE]: 1 } + }, + [TextureFormat.RG16F]: { + format: TextureFormat.RG, + filter: true, + num: 2, + types: { [TextureType.FLOAT]: 8, [TextureType.HALF_FLOAT]: 4 } + }, + [TextureFormat.RG16I]: { + format: TextureFormat.RG_INTEGER, + render: true, + num: 2, + types: { [TextureType.SHORT]: 4 } + }, + [TextureFormat.RG16UI]: { + format: TextureFormat.RG_INTEGER, + render: true, + num: 2, + types: { [TextureType.UNSIGNED_SHORT]: 4 } + }, + [TextureFormat.RG32F]: { + format: TextureFormat.RG, + num: 2, + types: { [TextureType.FLOAT]: 8 } + }, + [TextureFormat.RG32I]: { + format: TextureFormat.RG_INTEGER, + render: true, + num: 2, + types: { [TextureType.INT]: 8 } + }, + [TextureFormat.RG32UI]: { + format: TextureFormat.RG_INTEGER, + render: true, + num: 2, + types: { [TextureType.UNSIGNED_INT]: 8 } + }, + [TextureFormat.RG8_SNORM]: { + format: TextureFormat.RG, + filter: true, + num: 2, + types: { [TextureType.BYTE]: 2 } + }, + [TextureFormat.RG8]: { + format: TextureFormat.RG, + render: true, + filter: true, + num: 2, + types: { [TextureType.UNSIGNED_BYTE]: 2 } + }, + [TextureFormat.RG8I]: { + format: TextureFormat.RG_INTEGER, + render: true, + num: 2, + types: { [TextureType.BYTE]: 2 } + }, + [TextureFormat.RG8UI]: { + format: TextureFormat.RG_INTEGER, + render: true, + num: 2, + types: { [TextureType.UNSIGNED_BYTE]: 2 } + }, + [TextureFormat.RGB]: { + format: TextureFormat.RGB, + render: true, + filter: true, + num: 3, + types: { + [TextureType.UNSIGNED_BYTE]: 3, + [TextureType.HALF_FLOAT]: 6, + [TextureType.HALF_FLOAT_OES]: 6, + [TextureType.FLOAT]: 12, + [TextureType.UNSIGNED_SHORT_5_6_5]: 2 + } + }, + [TextureFormat.RGB10_A2]: { + format: TextureFormat.RGBA, + render: true, + filter: true, + num: 4, + types: { [TextureType.UNSIGNED_INT_2_10_10_10_REV]: 4 } + }, + [TextureFormat.RGB10_A2UI]: { + format: TextureFormat.RGBA_INTEGER, + render: true, + num: 4, + types: { [TextureType.UNSIGNED_INT_2_10_10_10_REV]: 4 } + }, + [TextureFormat.RGB16F]: { + format: TextureFormat.RGB, + filter: true, + num: 3, + types: { [TextureType.FLOAT]: 12, [TextureType.HALF_FLOAT]: 6 } + }, + [TextureFormat.RGB16I]: { + format: TextureFormat.RGB_INTEGER, + num: 3, + types: { [TextureType.SHORT]: 6 } + }, + [TextureFormat.RGB16UI]: { + format: TextureFormat.RGB_INTEGER, + num: 3, + types: { [TextureType.UNSIGNED_SHORT]: 6 } + }, + [TextureFormat.RGB32F]: { + format: TextureFormat.RGB, + num: 3, + types: { [TextureType.FLOAT]: 12 } + }, + [TextureFormat.RGB32I]: { + format: TextureFormat.RGB_INTEGER, + num: 3, + types: { [TextureType.INT]: 12 } + }, + [TextureFormat.RGB32UI]: { + format: TextureFormat.RGB_INTEGER, + num: 3, + types: { [TextureType.UNSIGNED_INT]: 12 } + }, + [TextureFormat.RGB5_A1]: { + format: TextureFormat.RGBA, + render: true, + filter: true, + num: 4, + types: { + [TextureType.UNSIGNED_BYTE]: 4, + [TextureType.UNSIGNED_SHORT_5_5_5_1]: 2, + [TextureType.UNSIGNED_INT_2_10_10_10_REV]: 4 + } + }, + [TextureFormat.RGB565]: { + format: TextureFormat.RGB, + render: true, + filter: true, + num: 3, + types: { + [TextureType.UNSIGNED_BYTE]: 3, + [TextureType.UNSIGNED_SHORT_5_6_5]: 2 + } + }, + [TextureFormat.RGB8_SNORM]: { + format: TextureFormat.RGB, + filter: true, + num: 3, + types: { [TextureType.BYTE]: 3 } + }, + [TextureFormat.RGB8]: { + format: TextureFormat.RGB, + render: true, + filter: true, + num: 3, + types: { [TextureType.UNSIGNED_BYTE]: 3 } + }, + [TextureFormat.RGB8I]: { + format: TextureFormat.RGB_INTEGER, + num: 3, + types: { [TextureType.BYTE]: 3 } + }, + [TextureFormat.RGB8UI]: { + format: TextureFormat.RGB_INTEGER, + num: 3, + types: { [TextureType.UNSIGNED_BYTE]: 3 } + }, + [TextureFormat.RGB9_E5]: { + format: TextureFormat.RGB, + filter: true, + num: 3, + types: { + [TextureType.FLOAT]: 12, + [TextureType.HALF_FLOAT]: 6, + [TextureType.UNSIGNED_INT_5_9_9_9_REV]: 4 + } + }, + [TextureFormat.RGBA]: { + format: TextureFormat.RGBA, + render: true, + filter: true, + num: 4, + types: { + [TextureType.UNSIGNED_BYTE]: 4, + [TextureType.HALF_FLOAT]: 8, + [TextureType.HALF_FLOAT_OES]: 8, + [TextureType.FLOAT]: 16, + [TextureType.UNSIGNED_SHORT_4_4_4_4]: 2, + [TextureType.UNSIGNED_SHORT_5_5_5_1]: 2 + } + }, + [TextureFormat.RGBA16F]: { + format: TextureFormat.RGBA, + filter: true, + num: 4, + types: { [TextureType.FLOAT]: 16, [TextureType.HALF_FLOAT]: 8 } + }, + [TextureFormat.RGBA16I]: { + format: TextureFormat.RGBA_INTEGER, + render: true, + num: 4, + types: { [TextureType.SHORT]: 8 } + }, + [TextureFormat.RGBA16UI]: { + format: TextureFormat.RGBA_INTEGER, + render: true, + num: 4, + types: { [TextureType.UNSIGNED_SHORT]: 8 } + }, + [TextureFormat.RGBA32F]: { + format: TextureFormat.RGBA, + num: 4, + types: { [TextureType.FLOAT]: 16 } + }, + [TextureFormat.RGBA32I]: { + format: TextureFormat.RGBA_INTEGER, + render: true, + num: 4, + types: { [TextureType.INT]: 16 } + }, + [TextureFormat.RGBA32UI]: { + format: TextureFormat.RGBA_INTEGER, + render: true, + num: 4, + types: { [TextureType.UNSIGNED_INT]: 16 } + }, + [TextureFormat.RGBA4]: { + format: TextureFormat.RGBA, + render: true, + filter: true, + num: 4, + types: { + [TextureType.UNSIGNED_BYTE]: 4, + [TextureType.UNSIGNED_SHORT_4_4_4_4]: 2 + } + }, + [TextureFormat.RGBA8_SNORM]: { + format: TextureFormat.RGBA, + filter: true, + num: 4, + types: { [TextureType.BYTE]: 4 } + }, + [TextureFormat.RGBA8]: { + format: TextureFormat.RGBA, + render: true, + filter: true, + num: 4, + types: { [TextureType.UNSIGNED_BYTE]: 4 } + }, + [TextureFormat.RGBA8I]: { + format: TextureFormat.RGBA_INTEGER, + render: true, + num: 4, + types: { [TextureType.BYTE]: 4 } + }, + [TextureFormat.RGBA8UI]: { + format: TextureFormat.RGBA_INTEGER, + render: true, + num: 4, + types: { [TextureType.UNSIGNED_BYTE]: 4 } + }, + [TextureFormat.SRGB8_ALPHA8]: { + format: TextureFormat.RGBA, + render: true, + filter: true, + num: 4, + types: { [TextureType.UNSIGNED_BYTE]: 4 } + }, + [TextureFormat.SRGB8]: { + format: TextureFormat.RGB, + filter: true, + num: 3, + types: { + [TextureType.UNSIGNED_BYTE]: 3 + } + } +}; + +export type GLSL = Type; + +export type GLVec = number[] | Float32Array; +export type GLVec2 = Tuple | Float32Array; +export type GLVec3 = Tuple | Float32Array; +export type GLVec4 = Tuple | Float32Array; + +export type GLIntVec = number[] | Int32Array; +export type GLUintVec = number[] | Uint32Array; +export type GLIntVec2 = Tuple | Int32Array; +export type GLIntVec3 = Tuple | Int32Array; +export type GLIntVec4 = Tuple | Int32Array; + +export type GLMat2 = Tuple | Float32Array; +export type GLMat3 = Tuple | Float32Array; +export type GLMat4 = Tuple | Float32Array; +export type GLMat23 = Tuple | Float32Array; +export type GLMat24 = Tuple | Float32Array; +export type GLMat34 = Tuple | Float32Array; + +export type AttribType = "bool" | "float" | "int" | "vec2" | "vec3" | "vec4"; + +export type AttribBufferData = + | Int8Array + | Uint8Array + | Uint8ClampedArray + | Int16Array + | Uint16Array + | Float32Array; + +export type IndexBufferData = Uint16Array | Uint32Array; + +export type ModelAttributeSpecs = IObjectOf; + +export type UniformValue = number | number[] | TypedArray; + +export type UniformValues = IObjectOf< + UniformValue | Fn2 | IDeref +>; + +export type ShaderType = "vs" | "fs"; + +export type GLSLScalarType = + | "bool" + | "float" + | "int" + | "uint" + | "sampler2D" + | "samplerCube"; + +export type GLSLArrayType = + | "bool[]" + | "int[]" + | "uint[]" + | "float[]" + | "bvec2[]" + | "bvec3[]" + | "bvec4[]" + | "ivec2[]" + | "ivec3[]" + | "ivec4[]" + | "uvec2[]" + | "uvec3[]" + | "uvec4[]" + | "vec2[]" + | "vec3[]" + | "vec4[]" + | "mat2[]" + | "mat3[]" + | "mat4[]" + // | "mat2x3[]" + // | "mat2x4[]" + // | "mat3x2[]" + // | "mat3x4[]" + // | "mat4x2[]" + // | "mat4x3[]" + | "sampler2D[]" + | "sampler3D[]" + | "samplerCube[]"; + +export type UniformDefault = + | T + | Fn2, T>; + +export type UniformDecl = + | GLSL + | [GLSLScalarType, UniformDefault] + | ["bvec2", UniformDefault] + | ["bvec3", UniformDefault] + | ["bvec4", UniformDefault] + | ["ivec2", UniformDefault] + | ["ivec3", UniformDefault] + | ["ivec4", UniformDefault] + | ["vec2", UniformDefault] + | ["vec3", UniformDefault] + | ["vec4", UniformDefault] + | ["mat2", UniformDefault] + | ["mat3", UniformDefault] + | ["mat4", UniformDefault] + // | ["mat2x3", UniformDefault] + // | ["mat2x4", UniformDefault] + // | ["mat3x2", UniformDefault] + // | ["mat3x4", UniformDefault] + // | ["mat4x2", UniformDefault] + // | ["mat4x3", UniformDefault] + | ["bool[]", number, UniformDefault?] + | ["int[]", number, UniformDefault?] + | ["uint[]", number, UniformDefault?] + | ["float[]", number, UniformDefault?] + | ["bvec2[]", number, UniformDefault?] + | ["bvec3[]", number, UniformDefault?] + | ["bvec4[]", number, UniformDefault?] + | ["ivec2[]", number, UniformDefault?] + | ["ivec3[]", number, UniformDefault?] + | ["ivec4[]", number, UniformDefault?] + | ["uvec2[]", number, UniformDefault?] + | ["uvec3[]", number, UniformDefault?] + | ["uvec4[]", number, UniformDefault?] + | ["vec2[]", number, UniformDefault?] + | ["vec3[]", number, UniformDefault?] + | ["vec4[]", number, UniformDefault?] + | ["mat2[]", number, UniformDefault?] + | ["mat3[]", number, UniformDefault?] + | ["mat4[]", number, UniformDefault?] + // | ["mat2x3[]", number, UniformDefault?] + // | ["mat2x4[]", number, UniformDefault?] + // | ["mat3x2[]", number, UniformDefault?] + // | ["mat3x4[]", number, UniformDefault?] + // | ["mat4x2[]", number, UniformDefault?] + // | ["mat4x3[]", number, UniformDefault?] + | ["sampler2D[]", number, UniformDefault?] + | ["sampler3D[]", number, UniformDefault?] + | ["samplerCube[]", number, UniformDefault?]; + +/** + * Object of attribute types w/ optional locations. + */ +export type ShaderAttribSpecs = IObjectOf; + +export type ShaderAttribSpec = AttribType | [AttribType, number]; + +/** + * Object of instantiated shader attributes. + */ +export type ShaderAttribs = IObjectOf; + +export interface ShaderAttrib { + type: AttribType; + loc: number; +} + +export type ShaderVaryingSpecs = IObjectOf; + +export type ShaderVaryingSpec = GLSL | [GLSLArrayType, number]; + +export type ShaderUniformSpecs = IObjectOf; + +export type ShaderUniforms = IObjectOf; + +export type ShaderOutputSpecs = IObjectOf; + +export type ShaderOutputSpec = GLSL | [GLSL, number]; + +export interface ShaderUniform { + type: GLSL; + loc: WebGLUniformLocation; + setter: Fn; + defaultFn?: (shaderUnis: any, specUnis: any) => UniformValue; + defaultVal?: UniformValue; +} + +export interface GLSLSyntax { + number: number; + attrib: Fn3; + uniform: Fn3; + varying: Record< + ShaderType, + Fn3 + >; + output: Fn3; +} + +export interface GLSLDeclPrefixes { + a: string; + v: string; + u: string; + o: string; +} + +export type GLSLExtensionBehavior = "require" | "warn" | boolean; + +export interface ShaderSnippet { + /** + * Array of dependent snippets. + */ + deps?: ShaderSnippet[]; + /** + * Snippet source code. + */ + src: string; +} + +export const DEFAULT_OUTPUT: ShaderOutputSpecs = { fragColor: ["vec4", 0] }; + +export type ShaderFn = Fn4< + GLSLTarget, + IObjectOf>, // uni + IObjectOf>, // attribs + IObjectOf>, // vary + (Sym | Func)[] +>; + +export interface ShaderSpec { + /** + * Vertex shader GLSL source code. + */ + vs: string | ShaderFn; + /** + * Fragment shader GLSL source code. + */ + fs: string | ShaderFn; + /** + * Attribute type declarations. + */ + attribs: ShaderAttribSpecs; + /** + * Varying type declarations. + */ + varying?: ShaderVaryingSpecs; + /** + * Uniform type declarations with optional defaults. + */ + uniforms?: ShaderUniformSpecs; + /** + * WebGL2 only. Fragment shader output variable type declarations. + * Default: `{ fragColor: GLSL.vec4 }` + */ + outputs?: ShaderOutputSpecs; + /** + * Flag to indicate code generation for attribs, varying, uniforms + * and outputs. Default: true. + */ + generateDecls?: boolean; + /** + * Variable naming convention variable prefixes for GLSL code gen. + * + * Defaults: + * + * - Attributes: `a_` + * - Varying: `v_` + * - Uniforms: `u_` + * - Outputs: `o_` + */ + declPrefixes?: Partial; + /** + * Optional prelude source, prepended before main shader code, the + * default prelude (unless disabled) and any other generated code. + */ + pre?: string; + /** + * Optional source code to be appended after main shader code. + */ + post?: string; + /** + * If true, disables default prelude. Default: false + */ + replacePrelude?: boolean; + /** + * Optional shader drawing state flags. Default: none. + */ + state?: Partial; + /** + * WebGL extension config for code generation. Keys in this object + * are extension names and their values specify the desired + * behavior. Boolean values will be translated in "enable" / + * "disable". + */ + ext?: IObjectOf; +} + +export interface ShaderState { + /** + * Enable depth test + */ + depth: boolean; + /** + * Cull faces + */ + cull: boolean; + /** + * Cull mode + */ + cullMode: GLenum; + /** + * Enable blending + */ + blend: boolean; + /** + * 2-element array of glBlendFunction coefficients + * (default: `[gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA]`) + */ + blendFn: Tuple; + /** + * glBlendEquation mode + */ + blendEq: GLenum; + /** + * Enable stencil test + */ + stencil: boolean; + /** + * glStencilFn params + */ + stencilFn: Tuple; + /** + * glStencilOp params + */ + stencilOp: Tuple; + /** + * glStencilMask arg + */ + stencilMask: GLenum; +} + +export interface ShaderOpts { + instancePos: string; + instanceColor: string; + color: string; + uv: string; + material: Partial; + state: Partial; +} + +export interface IShader extends IBind, IRelease { + gl: WebGLRenderingContext; + attribs: IObjectOf; + uniforms: ShaderUniforms; + + bindAttribs(specAttribs: ModelAttributeSpecs): void; + bindUniforms(specUnis: UniformValues): void; + prepareState(state?: Partial): void; +} + +export interface IWebGLBuffer extends IBind, IRelease { + set(data: T, mode?: GLenum): void; + setChunk(data: T, offset: number): void; +} + +export interface IConfigure { + configure(opts: T): boolean; +} + +export interface ITexture + extends IBind, + IConfigure>, + IRelease { + tex: WebGLTexture; +} + +export interface IFbo + extends IBind, + IConfigure>, + IRelease {} + +export interface IRenderBuffer extends IBind, IRelease { + buffer: WebGLRenderbuffer; + format: GLenum; + width: number; + height: number; +} + +export interface ModelSpec { + /** + * Initialized `IShader` instance + */ + shader: IShader; + /** + * GLSL attribute declarations + */ + attribs: ModelAttributeSpecs; + /** + * Geometry attributes given as `AttribPool` instance. + */ + attribPool?: AttribPool; + /** + * GLSL uniform value overrides + */ + uniforms?: UniformValues; + /** + * Buffer spec for indexed geometry + */ + indices?: IndexBufferSpec; + /** + * Array of initialized `ITexture` instances. + * Each non-null item will be auto-bound to its respective texture unit, + * each time the model is drawn via `draw()` + */ + textures?: ITexture[]; + /** + * Extra configuration for instanced geometry + */ + instances?: InstancingSpec; + /** + * WebGL draw mode. Defaults to `TRIANGLES` + */ + mode?: GLenum; + /** + * Number of vertices/indices to draw + */ + num: number; +} + +/** + * Data specification of a single WebGL attribute + */ +export interface ModelAttributeSpec { + /** + * Backing `WebGLArrayBuffer` instance. Usually this will be + * auto-initialized by `compileBuffers()` + */ + buffer?: IWebGLBuffer; + /** + * Raw attribute data from which `buffer` will be initialized + */ + data?: AttribBufferData; + /** + * Attribute element size (in component values, not bytes). + * Default: 3 + */ + size?: number; + /** + * Auto-normalization flag when writing buffer data. + * Default: false + */ + normalized?: boolean; + /** + * Byte offset of 1st attrib component. + * Default: 0 + */ + offset?: number; + /** + * Attribute stride in bytes. + * Default: 0 = densely packed + */ + stride?: number; + /** + * Attribute's WebGL data type. + * Default: gl.FLOAT + */ + type?: GLenum; + /** + * Only used for instanced attributes. + * See: https://www.khronos.org/registry/OpenGL/extensions/ANGLE/ANGLE_instanced_arrays.txt + */ + divisor?: number; +} + +export interface IndexBufferSpec { + /** + * Backing `WebGLBuffer` instance. Usually this will be + * auto-initialized by `makeBuffersInSpec()` + */ + buffer?: IWebGLBuffer; + /** + * Raw attribute data from which `buffer` will be initialized + */ + data: IndexBufferData; +} + +export interface InstancingSpec { + attribs: IObjectOf; + num: number; +} + +export interface TextureOpts { + image: ArrayBufferView | TexImageSource | null; + target: GLenum; + type: GLenum; + filter: GLenum | [GLenum, GLenum?]; + wrap: GLenum | [GLenum, GLenum?, GLenum?]; + lod: [GLenum, GLenum?]; + minMaxLevel: [GLenum, GLenum]; + level: GLenum; + format: GLenum; + internalFormat: GLenum; + width: number; + height: number; + mipmap: boolean; + flip: boolean; + premultiply: boolean; + sub: boolean; + pos: number[]; +} + +export interface FboOpts { + /** + * Array of Texture instances to be used as color attachments. + * Multiple attachments are only allowed if the `webgl_draw_buffers` + * extension is available. The texture at `[0]` will be mapped to + * `COLOR_ATTACHMENT0` (or `COLOR_ATTACHMENT0_WEBGL`), other indices + * are mapped to their respective attachment IDs. + */ + tex: ITexture[]; + /** + * Optional pre-instantiated `RenderBuffer` to be used as depth + * buffer for this FBO. + */ + depth?: ITexture | IRenderBuffer; +} + +export interface RboOpts { + format?: number; + width: number; + height: number; +} + +export interface Material { + ambientCol: GLVec3; + diffuseCol: GLVec3; + specularCol: GLVec3; +} + +export interface WeblGLCanvasOpts { + canvas: string | HTMLCanvasElement; + parent: HTMLElement; + opts: Partial; + version: 1 | 2; + width: number; + height: number; + autoScale: boolean; + onContextLost: EventListener; + ext: (keyof WebGLExtensionMap)[]; +} + +export interface GPGPUOpts { + size: number; + inputs?: number | GPGPUTextureConfig[]; + outputs?: number | GPGPUTextureConfig[]; + gl?: WebGLRenderingContext; + version?: 1 | 2; +} + +export interface GPGPUTextureConfig + extends Partial< + Pick + > { + stride: number; +} + +export interface GPGPUJobConfig { + shader: ShaderSpec; + src: string | ShaderFn; + uniforms: ShaderUniformSpecs; + inputs: number; + outputs?: number; +} + +export interface GPGPUJobExecOpts { + inputs: (ITexture | TypedArray)[]; + outputs?: number[]; + uniforms?: UniformValues; +} + +export const GL_COLOR_ATTACHMENT0_WEBGL = 0x8ce0; +export const GL_MAX_COLOR_ATTACHMENTS_WEBGL = 0x8cdf; +export const GL_RGBA = 0x1908; +export const GL_RGBA32F = 0x8814; + +// [SRC_ALPHA, ONE_MINUS_SRC_ALPHA] +export const DEFAULT_BLEND: Tuple = [0x302, 0x303]; + +export const GL_EXT_INFO = { + WEBGL_draw_buffers: { + gl: true, + alias: "GL_EXT_draw_buffers" + }, + OES_standard_derivatives: { + gl: true, + alias: "GL_OES_standard_derivatives" + } +}; + +export interface WebGLExtensionMap { + EXT_blend_minmax: EXT_blend_minmax; + EXT_color_buffer_float: WEBGL_color_buffer_float; + EXT_texture_filter_anisotropic: EXT_texture_filter_anisotropic; + EXT_frag_depth: EXT_frag_depth; + EXT_shader_texture_lod: EXT_shader_texture_lod; + EXT_sRGB: EXT_sRGB; + OES_vertex_array_object: OES_vertex_array_object; + WEBGL_color_buffer_float: WEBGL_color_buffer_float; + WEBGL_compressed_texture_astc: WEBGL_compressed_texture_astc; + WEBGL_compressed_texture_s3tc_srgb: WEBGL_compressed_texture_s3tc_srgb; + WEBGL_debug_shaders: WEBGL_debug_shaders; + WEBGL_draw_buffers: WEBGL_draw_buffers; + WEBGL_lose_context: WEBGL_lose_context; + WEBGL_depth_texture: WEBGL_depth_texture; + WEBGL_debug_renderer_info: WEBGL_debug_renderer_info; + WEBGL_compressed_texture_s3tc: WEBGL_compressed_texture_s3tc; + OES_texture_half_float_linear: OES_texture_half_float_linear; + OES_texture_half_float: OES_texture_half_float; + OES_texture_float_linear: OES_texture_float_linear; + OES_texture_float: OES_texture_float; + OES_standard_derivatives: OES_standard_derivatives; + OES_element_index_uint: OES_element_index_uint; + ANGLE_instanced_arrays: ANGLE_instanced_arrays; +} diff --git a/packages/webgl/src/buffer.ts b/packages/webgl/src/buffer.ts new file mode 100644 index 0000000000..336362bcfa --- /dev/null +++ b/packages/webgl/src/buffer.ts @@ -0,0 +1,184 @@ +import { TypedArray } from "@thi.ng/api"; +import { AttribPool } from "@thi.ng/vector-pools"; +import { + IndexBufferSpec, + IWebGLBuffer, + ModelAttributeSpecs, + ModelSpec +} from "./api"; +import { error } from "./error"; +import { isGL2Context } from "./utils"; + +export class WebGLArrayBuffer implements IWebGLBuffer { + gl: WebGLRenderingContext; + buffer: WebGLBuffer; + target: number; + mode: number; + + constructor( + gl: WebGLRenderingContext, + data?: T, + target = gl.ARRAY_BUFFER, + mode = gl.STATIC_DRAW + ) { + this.gl = gl; + this.buffer = gl.createBuffer() || error("error creating WebGL buffer"); + this.target = target; + this.mode = mode; + data && this.set(data); + } + + bind() { + this.gl.bindBuffer(this.target, this.buffer); + return true; + } + + unbind() { + this.gl.bindBuffer(this.target, null); + return true; + } + + release() { + if (this.buffer) { + this.gl.deleteBuffer(this.buffer); + delete this.buffer; + } + return true; + } + + set(data: T, mode = this.mode) { + this.bind(); + this.gl.bufferData(this.target, data, mode); + } + + setChunk(data: T, offset = 0) { + this.bind(); + this.gl.bufferSubData(this.target, offset, data); + } +} + +export const buffer = ( + gl: WebGLRenderingContext, + data?: TypedArray, + target = gl.ARRAY_BUFFER, + mode = gl.STATIC_DRAW +) => new WebGLArrayBuffer(gl, data, target, mode); + +export const compileModel = ( + gl: WebGLRenderingContext, + spec: ModelSpec, + mode = gl.STATIC_DRAW +) => { + if (spec.attribPool) { + spec.attribs = compileAttribPool( + gl, + spec.attribPool, + undefined, + gl.ARRAY_BUFFER, + mode + ); + } else { + compileAttribs(gl, spec.attribs, mode); + } + spec.instances && compileAttribs(gl, spec.instances.attribs, mode); + compileIndices(gl, spec.indices, mode); + spec.mode == null && (spec.mode = gl.TRIANGLES); + // TODO auto-create VAO & inject into model spec? + return spec; +}; + +const compileAttribs = ( + gl: WebGLRenderingContext, + attribs: ModelAttributeSpecs, + mode: GLenum +) => { + if (attribs) { + for (let id in attribs) { + if (attribs.hasOwnProperty(id)) { + const attr = attribs[id]; + if (attr.buffer) { + attr.data && attr.buffer.set(attr.data); + } else { + attr.buffer = new WebGLArrayBuffer( + gl, + attr.data, + gl.ARRAY_BUFFER, + mode + ); + } + } + } + } + return attribs; +}; + +export const compileIndices = ( + gl: WebGLRenderingContext, + index: IndexBufferSpec | undefined, + mode: GLenum = gl.STATIC_DRAW +) => { + if (index) { + if (index.buffer) { + index.data && index.buffer.set(index.data); + } else { + index.buffer = new WebGLArrayBuffer( + gl, + index.data, + gl.ELEMENT_ARRAY_BUFFER, + mode + ); + } + } + return index; +}; + +export const compileVAO = (gl: WebGLRenderingContext, spec: ModelSpec) => { + if (spec.shader) { + const isGL2 = isGL2Context(gl); + const ext = !isGL2 ? gl.getExtension("OES_vertex_array_object") : null; + if (isGL2 || ext) { + let vao: WebGLVertexArrayObject; + if (isGL2) { + vao = (gl).createVertexArray()!; + (gl).bindVertexArray(vao); + } else { + vao = ext!.createVertexArrayOES()!; + ext!.bindVertexArrayOES(vao); + } + !!vao && error("error creating VAO"); + spec.shader.bindAttribs(spec.attribs); + if (spec.indices!) { + spec.indices!.buffer!.bind(); + } + spec.shader.unbind(null); + if (isGL2) { + (gl).bindVertexArray(null); + } else { + ext!.bindVertexArrayOES(null); + } + return vao; + } + } +}; + +export const compileAttribPool = ( + gl: WebGLRenderingContext, + pool: AttribPool, + ids?: string[], + target = gl.ARRAY_BUFFER, + mode = gl.STATIC_DRAW +) => { + const buf = buffer(gl, pool.bytes(), target, mode); + const spec = {}; + for (let id of ids || Object.keys(pool.specs)) { + const attr = pool.specs[id]; + spec[id] = { + buffer: buf, + size: attr.size, + type: attr.type, + stride: pool.byteStride, + offset: attr.byteOffset + }; + } + return spec; +}; diff --git a/packages/webgl/src/canvas.ts b/packages/webgl/src/canvas.ts new file mode 100644 index 0000000000..46d5ebb7bb --- /dev/null +++ b/packages/webgl/src/canvas.ts @@ -0,0 +1,80 @@ +import { isString } from "@thi.ng/checks"; +import { WebGLExtensionMap, WeblGLCanvasOpts } from "./api"; +import { error } from "./error"; + +const defaultOpts: WebGLContextAttributes = { + alpha: true, + antialias: true, + depth: true, + premultipliedAlpha: true, + preserveDrawingBuffer: false, + stencil: false +}; + +export const glCanvas = (opts: Partial = {}) => { + const canvas = opts.canvas + ? isString(opts.canvas) + ? document.getElementById(opts.canvas) + : opts.canvas + : document.createElement("canvas"); + opts.width && (canvas.width = opts.width); + opts.height && (canvas.height = opts.height); + opts.autoScale !== false && adaptDPI(canvas, canvas.width, canvas.height); + opts.parent && opts.parent.appendChild(canvas); + const gl = canvas.getContext( + opts.version === 2 ? "webgl2" : "webgl", + { + ...defaultOpts, + ...opts.opts + } + ); + if (!gl) { + error("WebGL unavailable"); + } + opts.onContextLost && + canvas.addEventListener("webglcontextlost", opts.onContextLost); + return { + canvas, + gl, + ext: getExtensions(gl, opts.ext!) + }; +}; + +export const getExtensions = ( + gl: WebGLRenderingContext, + ids: K[], + required = true +): Pick => { + const ext: any = {}; + if (ids) { + for (let id of ids) { + ext[id] = gl.getExtension(id); + required && !ext[id] && error(`extension ${id} not available`); + } + } + return ext; +}; + +/** + * Sets the canvas size to given `width` & `height` and adjusts style to + * compensate for HDPI devices. Note: For 2D canvases, this will + * automatically clear any prior canvas content. + * + * @param canvas + * @param width uncompensated pixel width + * @param height uncompensated pixel height + */ +export const adaptDPI = ( + canvas: HTMLCanvasElement, + width: number, + height: number +) => { + const dpr = window.devicePixelRatio || 1; + if (dpr != 1) { + canvas.style.width = `${width}px`; + canvas.style.height = `${height}px`; + } + canvas.width = width * dpr; + canvas.height = height * dpr; + return dpr; +}; diff --git a/packages/webgl/src/draw.ts b/packages/webgl/src/draw.ts new file mode 100644 index 0000000000..231ae20945 --- /dev/null +++ b/packages/webgl/src/draw.ts @@ -0,0 +1,107 @@ +import { isArray } from "@thi.ng/checks"; +import { ModelSpec } from "./api"; +import { error } from "./error"; +import { bindTextures } from "./texture"; +import { isGL2Context } from "./utils"; + +export const draw = (specs: ModelSpec | ModelSpec[]) => { + const _specs = isArray(specs) ? specs : [specs]; + for (let i = 0, n = _specs.length; i < n; i++) { + const spec = _specs[i]; + const indices = spec.indices; + const gl = spec.shader.gl; + spec.textures && bindTextures(spec.textures); + spec.shader.prepareState(); + spec.shader.bind(spec); + if (indices && indices.buffer) { + indices.buffer.bind(); + if (spec.instances) { + drawInstanced(gl, spec); + } else { + gl.drawElements( + spec.mode!, + spec.num, + indices.data instanceof Uint32Array + ? gl.UNSIGNED_INT + : gl.UNSIGNED_SHORT, + 0 + ); + } + } else { + if (spec.instances) { + drawInstanced(gl, spec); + } else { + gl.drawArrays(spec.mode!, 0, spec.num); + } + } + spec.shader.unbind(null); + } +}; + +const drawInstanced = (gl: WebGLRenderingContext, spec: ModelSpec) => { + const isGL2 = isGL2Context(gl); + const ext = !isGL2 ? gl.getExtension("ANGLE_instanced_arrays") : undefined; + if (!(isGL2 || ext)) { + error("instancing not supported"); + } + const sattribs = spec.shader.attribs; + const iattribs = spec.instances!.attribs; + spec.shader.bindAttribs(iattribs); + for (let id in iattribs) { + const attr = sattribs[id]; + if (attr) { + let div = iattribs[id].divisor; + div = div !== undefined ? div : 1; + isGL2 + ? (gl).vertexAttribDivisor( + attr.loc, + div + ) + : ext!.vertexAttribDivisorANGLE(attr.loc, div); + } + } + if (spec.indices) { + const type = + spec.indices.data instanceof Uint32Array + ? gl.UNSIGNED_INT + : gl.UNSIGNED_SHORT; + isGL2 + ? (gl).drawElementsInstanced( + spec.mode!, + spec.num, + type, + 0, + spec.instances!.num + ) + : ext!.drawElementsInstancedANGLE( + spec.mode!, + spec.num, + type, + 0, + spec.instances!.num + ); + } else { + isGL2 + ? (gl).drawArraysInstanced( + spec.mode!, + 0, + spec.num, + spec.instances!.num + ) + : ext!.drawArraysInstancedANGLE( + spec.mode!, + 0, + spec.num, + spec.instances!.num + ); + } + // reset attrib divisors to allow non-instanced draws later on + for (let id in iattribs) { + const attr = sattribs[id]; + attr && + (isGL2 + ? (gl).vertexAttribDivisor(attr.loc, 0) + : ext!.vertexAttribDivisorANGLE(attr.loc, 0)); + } + spec.shader.unbind(null); +}; diff --git a/packages/webgl/src/error.ts b/packages/webgl/src/error.ts new file mode 100644 index 0000000000..4df70f8b6e --- /dev/null +++ b/packages/webgl/src/error.ts @@ -0,0 +1,9 @@ +export class WebGLError extends Error { + constructor(msg?: string) { + super(`WebGL error ${msg ? ": " + msg : ""}`); + } +} + +export const error = (msg?: string) => { + throw new WebGLError(msg); +}; diff --git a/packages/webgl/src/fbo.ts b/packages/webgl/src/fbo.ts new file mode 100644 index 0000000000..f979c52301 --- /dev/null +++ b/packages/webgl/src/fbo.ts @@ -0,0 +1,128 @@ +import { assert } from "@thi.ng/api"; +import { + FboOpts, + GL_COLOR_ATTACHMENT0_WEBGL, + GL_MAX_COLOR_ATTACHMENTS_WEBGL, + IFbo, + ITexture +} from "./api"; +import { error } from "./error"; +import { RBO } from "./rbo"; +import { isGL2Context } from "./utils"; + +/** + * WebGL framebuffer wrapper w/ automatic detection & support for + * multiple render targets (color attachments) and optional depth + * buffer. Multiple targets are only supported if the + * `WEBGL_draw_buffers` extension is available. The max. number of + * attachments can be obtained via the `maxAttachments` property of the + * FBO instance. + * + * ``` + * // create FBO w/ 2 render targets + * fbo = new FBO(gl, { tex: [tex1, tex2] }); + * ``` + * + * https://developer.mozilla.org/en-US/docs/Web/API/WEBGL_draw_buffers + */ +export class FBO implements IFbo { + gl: WebGLRenderingContext; + fbo: WebGLFramebuffer; + ext?: WEBGL_draw_buffers; + maxAttachments: number; + + constructor(gl: WebGLRenderingContext, opts?: Partial) { + this.gl = gl; + this.fbo = gl.createFramebuffer() || error("error creating FBO"); + this.ext = !isGL2Context(gl) + ? gl.getExtension("WEBGL_draw_buffers") || + error("missing WEBGL_draw_buffers ext") + : undefined; + this.maxAttachments = gl.getParameter(GL_MAX_COLOR_ATTACHMENTS_WEBGL); + opts && this.configure(opts); + } + + bind() { + this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, this.fbo); + return true; + } + + unbind() { + this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, null); + return true; + } + + release() { + this.gl.deleteFramebuffer(this.fbo); + delete this.fbo; + delete this.ext; + return true; + } + + configure(opts: Partial) { + const gl = this.gl; + this.bind(); + if (opts.tex) { + assert( + opts.tex.length < this.maxAttachments, + `too many attachments (max. ${this.maxAttachments})` + ); + const attachments: number[] = []; + for (let i = 0; i < opts.tex.length; i++) { + const attach = GL_COLOR_ATTACHMENT0_WEBGL + i; + gl.framebufferTexture2D( + gl.FRAMEBUFFER, + attach, + gl.TEXTURE_2D, + opts.tex[i].tex, + 0 + ); + attachments[i] = attach; + } + if (this.ext) { + this.ext.drawBuffersWEBGL(attachments); + } else if (isGL2Context(gl)) { + gl.drawBuffers(attachments); + } + } + if (opts.depth) { + opts.depth instanceof RBO + ? gl.framebufferRenderbuffer( + gl.FRAMEBUFFER, + gl.DEPTH_ATTACHMENT, + gl.RENDERBUFFER, + opts.depth.buffer + ) + : gl.framebufferTexture2D( + gl.FRAMEBUFFER, + gl.DEPTH_ATTACHMENT, + gl.TEXTURE_2D, + (opts.depth).tex, + 0 + ); + } + return this.validate(); + } + + validate() { + const gl = this.gl; + const err = gl.checkFramebufferStatus(gl.FRAMEBUFFER); + switch (err) { + case gl.FRAMEBUFFER_COMPLETE: + return true; + case gl.FRAMEBUFFER_UNSUPPORTED: + error("FBO unsupported"); + case gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT: + error("FBO incomplete attachment"); + case gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS: + error("FBO incomplete dimensions"); + case gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: + error("FBO incomplete missing attachment"); + default: + return error(`FBO error: ${err}`); + } + } +} + +export const fbo = (gl: WebGLRenderingContext, opts?: Partial) => + new FBO(gl, opts); diff --git a/packages/webgl/src/geo/cube.ts b/packages/webgl/src/geo/cube.ts new file mode 100644 index 0000000000..9fe00b1bc7 --- /dev/null +++ b/packages/webgl/src/geo/cube.ts @@ -0,0 +1,34 @@ +import { ModelSpec } from "../api"; + +export interface CubeOpts { + size: number; + normal: boolean; + uv: boolean; +} + +// prettier-ignore +export const cube = (opts?: Partial) => { + opts = { size: 1, normal: true, uv: true, ...opts}; + const s = opts.size!; + const spec: ModelSpec = { + attribs: { + position: { + data: new Float32Array([s, s, -s, s, s, s, s, -s, s, s, -s, -s, -s, s, s, -s, s, -s, -s, -s, -s, -s, -s, s, -s, s, s, s, s, s, s, s, -s, -s, s, -s, -s, -s, -s, s, -s, -s, s, -s, s, -s, -s, s, s, s, s, -s, s, s, -s, -s, s, s, -s, s, -s, s, -s, s, s, -s, s, -s, -s, -s, -s, -s]) + }, + }, + indices:{ + data: new Uint16Array([0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, 8, 9, 10, 8, 10, 11, 12, 13, 14, 12, 14, 15, 16, 17, 18, 16, 18, 19, 20, 21, 22, 20, 22, 23]) + }, + uniforms: {}, + shader: null, + num: 36 + }; + opts.normal && (spec.attribs.normal = { + data: new Float32Array([1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1]) + }); + opts.uv && (spec.attribs.uv = { + data: new Float32Array([1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1]), + size: 2 + }); + return spec; +}; diff --git a/packages/webgl/src/geo/quad.ts b/packages/webgl/src/geo/quad.ts new file mode 100644 index 0000000000..bae6ee1423 --- /dev/null +++ b/packages/webgl/src/geo/quad.ts @@ -0,0 +1,22 @@ +import { ModelSpec } from "../api"; + +export const quad = (uv = true): ModelSpec => ({ + attribs: { + position: { + data: new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]), + size: 2 + }, + ...(uv + ? { + uv: { + data: new Float32Array([0, 0, 1, 0, 0, 1, 1, 1]), + size: 2 + } + } + : null) + }, + uniforms: {}, + shader: null, + mode: 5, // TRIANGLE_STRIP, + num: 4 +}); diff --git a/packages/webgl/src/gpgpu.ts b/packages/webgl/src/gpgpu.ts new file mode 100644 index 0000000000..20bb105ce0 --- /dev/null +++ b/packages/webgl/src/gpgpu.ts @@ -0,0 +1,282 @@ +import { assert, IRelease } from "@thi.ng/api"; +import { mergeDeepObj } from "@thi.ng/associative"; +import { ceilPow2 } from "@thi.ng/binary"; +import { isNumber, isTypedArray } from "@thi.ng/checks"; +import { illegalArgs } from "@thi.ng/errors"; +import { + assocObj, + map, + range, + transduce +} from "@thi.ng/transducers"; +import { + GL_RGBA, + GL_RGBA32F, + GPGPUJobConfig, + GPGPUJobExecOpts, + GPGPUOpts, + GPGPUTextureConfig, + ITexture, + ModelSpec, + ShaderSpec +} from "./api"; +import { compileModel } from "./buffer"; +import { getExtensions, glCanvas } from "./canvas"; +import { draw } from "./draw"; +import { FBO } from "./fbo"; +import { quad } from "./geo/quad"; +import { FX_SHADER_SPEC } from "./pipeline"; +import { shader } from "./shader"; +import { floatTexture, texture } from "./texture"; +import { isGL2Context } from "./utils"; + +export const gpgpu = (opts: GPGPUOpts) => new GPGPU(opts); + +interface GPGPUIO { + tex: ITexture; + opts: GPGPUTextureConfig; +} + +export class GPGPU implements IRelease { + canvas?: HTMLCanvasElement; + gl: WebGLRenderingContext; + fbo: FBO; + inputs: GPGPUIO[]; + outputs: GPGPUIO[]; + spec: ModelSpec; + opts: GPGPUOpts; + width: number; + size: number; + + constructor(opts: GPGPUOpts) { + opts = { version: 1, inputs: 1, outputs: 1, ...opts }; + const width = ceilPow2(Math.ceil(Math.sqrt(opts.size / 4))); + let gl; + if (opts.gl) { + gl = opts.gl; + opts.version = isGL2Context(gl) ? 2 : 1; + } else { + const res = glCanvas({ + opts: { antialias: false, alpha: false, depth: false }, + width: 1, + height: 1, + autoScale: false, + version: opts.version + }); + this.canvas = res.canvas; + gl = res.gl; + } + getExtensions( + gl, + opts.version === 1 + ? ["WEBGL_color_buffer_float", "OES_texture_float"] + : ["EXT_color_buffer_float"] + ); + this.gl = gl; + this.opts = opts; + this.width = width; + this.size = width * width; + // let tmp = new Float32Array(this.size); + this.inputs = this.initTextures(opts.inputs!); + this.outputs = this.initTextures(opts.outputs!); + // tmp = null; + this.fbo = new FBO(gl); + this.spec = compileModel(gl, { + ...quad(), + textures: this.inputs.map((t) => t.tex) + }); + } + + inputSize(id: number) { + return this.inputs[id].opts.stride * this.size; + } + + outputSize(id: number) { + return this.outputs[id].opts.stride * this.size; + } + + newJob(opts: Partial) { + return new GPGPUJob(this, opts); + } + + release() { + this.fbo.release(); + for (let t of this.inputs) { + t.tex.release(); + } + for (let t of this.outputs) { + t.tex.release(); + } + delete this.inputs; + delete this.outputs; + delete this.spec; + delete this.canvas; + delete this.gl; + delete this.fbo; + delete this.opts; + return true; + } + + protected initTextures(specs: number | GPGPUTextureConfig[]) { + const gl = this.gl; + const width = this.width; + if (isNumber(specs)) { + return [ + ...map( + () => + { + tex: floatTexture(gl, null, width, width), + opts: { stride: 4 } + }, + range(specs) + ) + ]; + } else { + return specs.map( + (opts) => + { + tex: texture(gl, { + image: null, + width: width, + height: width, + filter: gl.NEAREST, + wrap: gl.CLAMP_TO_EDGE, + ...opts + }), + opts + } + ); + } + } +} + +export class GPGPUJob implements IRelease { + ctx: GPGPU; + spec: ModelSpec; + opts: GPGPUJobConfig; + + constructor(ctx: GPGPU, opts: Partial) { + opts = { + inputs: 1, + outputs: 1, + ...opts + }; + assert( + opts.inputs! <= ctx.opts.inputs!, + `context only supports max. ${ctx.opts.inputs} inputs` + ); + assert( + opts.outputs! <= ctx.opts.outputs!, + `context only supports max. ${ctx.opts.outputs} outputs` + ); + this.ctx = ctx; + this.opts = opts; + this.spec = this.buildSpec(); + } + + run(runOpts: GPGPUJobExecOpts) { + const inputs = runOpts.inputs; + const outputs = runOpts.outputs || [...range(this.opts.outputs!)]; + assert(inputs.length <= this.opts.inputs, "too many inputs"); + assert(outputs.length <= this.opts.outputs!, "too many outputs"); + const ctx = this.ctx; + const gl = ctx.gl; + const width = ctx.width; + const internalFormat = ctx.opts.version === 2 ? GL_RGBA32F : GL_RGBA; + const spec = this.spec; + for (let i = 0; i < inputs.length; i++) { + let tex = inputs[i]; + if (isTypedArray(tex)) { + const expectedSize = ctx.inputSize(i); + assert( + tex.length >= expectedSize, + `input #${i} too small (got ${ + tex.length + }, expected ${expectedSize})` + ); + const input = ctx.inputs[i]; + input.tex.configure({ + image: tex, + type: input.opts.type || gl.FLOAT, + internalFormat: input.opts.internalFormat || internalFormat, + format: input.opts.format || GL_RGBA, + filter: gl.NEAREST, + wrap: gl.CLAMP_TO_EDGE, + height: width, + width + }); + tex = input.tex; + } + spec.textures![i] = tex; + } + spec.uniforms = { ...spec.uniforms, ...runOpts.uniforms }; + ctx.fbo.configure({ tex: outputs.map((i) => ctx.outputs[i].tex) }); + gl.viewport(0, 0, width, width); + draw(spec); + return this; + } + + result(out?: Float32Array | null, id = 0) { + const ctx = this.ctx; + const width = ctx.width; + const gl = ctx.gl; + const output = ctx.outputs[id]; + const opts = output.opts; + const fbo = new FBO(gl, { tex: [output.tex] }); + out = out || new Float32Array(ctx.outputSize(id)); + gl.readPixels( + 0, + 0, + width, + width, + opts.format || gl.RGBA, + opts.type || gl.FLOAT, + out + ); + fbo.release(); + return out; + } + + release() { + this.spec.shader.release(); + delete this.spec; + delete this.ctx; + return true; + } + + protected buildSpec() { + const opts = this.opts; + const ctx = this.ctx; + const spec: ModelSpec = mergeDeepObj({}, ctx.spec); + let shaderSpec: ShaderSpec; + if (opts.src) { + shaderSpec = { + ...FX_SHADER_SPEC, + pre: `#define WIDTH (${ctx.width})\n#define SIZE (ivec2(${ + ctx.width + }))`, + fs: opts.src, + uniforms: { ...opts.uniforms }, + outputs: transduce( + map((i) => [`output${i}`, ["vec4", i]]), + assocObj(), + range(opts.outputs!) + ) + }; + } else if (opts.shader) { + shaderSpec = opts.shader; + shaderSpec.uniforms = shaderSpec.uniforms || {}; + shaderSpec.ext = shaderSpec.ext || {}; + } else { + return illegalArgs("require either `src` or `shader` option"); + } + shaderSpec.uniforms!.inputs = ["sampler2D[]", opts.inputs]; + if (ctx.opts.version === 1 && opts.outputs! > 1) { + shaderSpec.ext!.WEBGL_draw_buffers = "require"; + } + spec.uniforms!.inputs = [...range(opts.inputs)]; + spec.textures = ctx.inputs.slice(0, opts.inputs).map((t) => t.tex); + spec.shader = shader(ctx.gl, shaderSpec); + return spec; + } +} diff --git a/packages/webgl/src/index.ts b/packages/webgl/src/index.ts new file mode 100644 index 0000000000..51f39e20c0 --- /dev/null +++ b/packages/webgl/src/index.ts @@ -0,0 +1,24 @@ +export * from "./api"; +export * from "./buffer"; +export * from "./canvas"; +export * from "./draw"; +export * from "./error"; +export * from "./fbo"; +export * from "./gpgpu"; +export * from "./material"; +export * from "./matrices"; +export * from "./pipeline"; +export * from "./rbo"; +export * from "./shader"; +export * from "./syntax"; +export * from "./texture"; +export * from "./utils"; + +export * from "./shaders/lambert"; +export * from "./shaders/phong"; + +export * from "./textures/checkerboard"; +export * from "./textures/stripes"; + +export * from "./geo/cube"; +export * from "./geo/quad"; diff --git a/packages/webgl/src/material.ts b/packages/webgl/src/material.ts new file mode 100644 index 0000000000..e09ac7a6d9 --- /dev/null +++ b/packages/webgl/src/material.ts @@ -0,0 +1,24 @@ +import { GLSL, Material, ShaderUniformSpecs } from "./api"; + +export const DEFAULT_MATERIAL: Material = { + ambientCol: [0.1, 0.1, 0.1], + diffuseCol: [0.8, 0.8, 0.8], + specularCol: [1, 1, 1] +}; + +const TYPES: Record = { + ambientCol: "vec3", + diffuseCol: "vec3", + specularCol: "vec3" +}; + +export const defMaterial = ( + mat: Partial = {}, + flags: Partial> = {}, + base = DEFAULT_MATERIAL +): ShaderUniformSpecs => + Object.keys(base).reduce((acc: any, id) => { + (flags)[id] !== false && + (acc[id] = [(TYPES)[id], (mat)[id] || (base)[id]]); + return acc; + }, {}); diff --git a/packages/webgl/src/matrices.ts b/packages/webgl/src/matrices.ts new file mode 100644 index 0000000000..680c4a2788 --- /dev/null +++ b/packages/webgl/src/matrices.ts @@ -0,0 +1,58 @@ +import { IObjectOf } from "@thi.ng/api"; +import { isNumber } from "@thi.ng/checks"; +import { + IDENT44, + mulM44, + normal44, + ortho +} from "@thi.ng/matrices"; +import { ReadonlyVec } from "@thi.ng/vectors"; +import { GLMat4, ShaderUniforms } from "./api"; + +const $ = (a: any, b: any, id: string) => a[id] || b[id].defaultVal || IDENT44; + +/** + * Computes the inverse transpose of given 4x4 matrix uniform, i.e. + * `transpose(invert(m))`. + * + * @param model + */ +export const autoNormalMatrix1 = (model = "model") => ( + shaderU: ShaderUniforms, + specU: IObjectOf +) => normal44([], $(specU, shaderU, model)); + +/** + * Computes the inverse transpose of the matrix product of given 4x4 + * matrix uniforms, i.e. `transpose(invert(view * model))`. + * + * @param model + * @param view + */ +export const autoNormalMatrix2 = (model = "model", view = "view") => ( + shaderU: ShaderUniforms, + specU: IObjectOf +) => + ( + normal44( + null, + mulM44([], $(specU, shaderU, view), $(specU, shaderU, model)) + ) + ); + +/** + * Constructs a orthographic projection matrix for using 2D screen + * coords, with origin in the top-left corner of the viewport. If a + * WebGL context is given, the its `drawingBufferWidth` & + * `drawingBufferHeight` values are used. + * + * @param width + * @param height + */ +export function screen2d(width: number, height: number): GLMat4; +export function screen2d(gl: WebGLRenderingContext): GLMat4; +export function screen2d(a: WebGLRenderingContext | number, b?: number) { + return isNumber(a) + ? ortho([], 0, a, b!, 0, -1, 1) + : ortho([], 0, a.drawingBufferWidth, a.drawingBufferHeight, 0, -1, 1); +} diff --git a/packages/webgl/src/pipeline.ts b/packages/webgl/src/pipeline.ts new file mode 100644 index 0000000000..2de1748f84 --- /dev/null +++ b/packages/webgl/src/pipeline.ts @@ -0,0 +1,30 @@ +import { + assign, + defMain, + FLOAT0, + FLOAT1, + texture, + vec4 +} from "@thi.ng/shader-ast"; +import { ShaderFn, ShaderSpec } from "./api"; + +export const PASSTHROUGH_VS: ShaderFn = (gl, _, ins, outs) => [ + defMain(() => [ + assign(outs.v_uv, ins.uv), + assign(gl.gl_Position, vec4(ins.position, FLOAT0, FLOAT1)) + ]) +]; + +export const PASSTHROUGH_FS: ShaderFn = (_, unis, ins, outs) => [ + defMain(() => [assign(outs.fragColor, texture(unis.tex, ins.v_uv))]) +]; + +export const FX_SHADER_SPEC: ShaderSpec = { + vs: PASSTHROUGH_VS, + fs: PASSTHROUGH_FS, + attribs: { position: "vec2", uv: "vec2" }, + varying: { v_uv: "vec2" }, + uniforms: { tex: "sampler2D" }, + state: { depth: false }, + ext: {} +}; diff --git a/packages/webgl/src/rbo.ts b/packages/webgl/src/rbo.ts new file mode 100644 index 0000000000..2cb991afba --- /dev/null +++ b/packages/webgl/src/rbo.ts @@ -0,0 +1,51 @@ +import { IRenderBuffer, RboOpts } from "./api"; +import { error } from "./error"; + +export class RBO implements IRenderBuffer { + gl: WebGLRenderingContext; + buffer: WebGLRenderbuffer; + format!: number; + width!: number; + height!: number; + + constructor(gl: WebGLRenderingContext, opts: RboOpts) { + this.gl = gl; + this.buffer = gl.createRenderbuffer() || error("error creating RBO"); + this.configure(opts); + } + + bind() { + this.gl.bindRenderbuffer(this.gl.RENDERBUFFER, this.buffer); + return true; + } + + unbind() { + this.gl.bindRenderbuffer(this.gl.RENDERBUFFER, null); + return true; + } + + release() { + this.gl.deleteRenderbuffer(this.buffer); + delete this.buffer; + return true; + } + + configure(opts: RboOpts) { + const gl = this.gl; + this.bind(); + this.format = opts.format || gl.DEPTH_COMPONENT16; + this.width = opts.width; + this.height = opts.height; + gl.renderbufferStorage( + gl.RENDERBUFFER, + opts.format || gl.DEPTH_COMPONENT16, + opts.width, + opts.height + ); + this.unbind(); + return true; + } +} + +export const rbo = (gl: WebGLRenderingContext, opts: RboOpts) => + new RBO(gl, opts); diff --git a/packages/webgl/src/shader.ts b/packages/webgl/src/shader.ts new file mode 100644 index 0000000000..81f8c6aed4 --- /dev/null +++ b/packages/webgl/src/shader.ts @@ -0,0 +1,485 @@ +import { Fn3, IDeref, IObjectOf } from "@thi.ng/api"; +import { + existsAndNotNull, + implementsFunction, + isArray, + isBoolean, + isFunction +} from "@thi.ng/checks"; +import { unsupported } from "@thi.ng/errors"; +import { + input, + output, + program, + Sym, + sym, + uniform +} from "@thi.ng/shader-ast"; +import { GLSLVersion, targetGLSL } from "@thi.ng/shader-ast-glsl"; +import { vals } from "@thi.ng/transducers"; +import { + DEFAULT_OUTPUT, + GL_EXT_INFO, + GLSL, + GLSLDeclPrefixes, + GLSLExtensionBehavior, + IShader, + ModelAttributeSpecs, + ModelSpec, + ShaderAttrib, + ShaderAttribSpecs, + ShaderFn, + ShaderSpec, + ShaderState, + ShaderType, + ShaderUniform, + ShaderUniforms, + ShaderUniformSpecs, + UniformValue, + UniformValues +} from "./api"; +import { getExtensions } from "./canvas"; +import { error } from "./error"; +import { GLSL_HEADER, NO_PREFIXES, SYNTAX } from "./syntax"; +import { UNIFORM_SETTERS } from "./uniforms"; +import { isGL2Context } from "./utils"; + +const ERROR_REGEXP = /ERROR: \d+:(\d+): (.*)/; + +export class Shader implements IShader { + gl: WebGLRenderingContext; + program: WebGLProgram; + attribs: IObjectOf; + uniforms: ShaderUniforms; + state: Partial; + + constructor( + gl: WebGLRenderingContext, + program: WebGLProgram, + attribs: IObjectOf, + uniforms: ShaderUniforms, + state?: Partial + ) { + this.gl = gl; + this.program = program; + this.attribs = attribs; + this.uniforms = uniforms; + this.state = state || {}; + } + + bind(spec: ModelSpec) { + if (this.program) { + this.gl.useProgram(this.program); + this.bindAttribs(spec.attribs); + this.bindUniforms(spec.uniforms); + return true; + } + return false; + } + + unbind() { + this.gl.useProgram(null); + return true; + } + + release() { + if (this.program) { + this.gl.deleteProgram(this.program); + delete this.program; + return true; + } + return false; + } + + bindAttribs(specAttribs: ModelAttributeSpecs) { + const gl = this.gl; + let shaderAttrib; + for (let id in specAttribs) { + if ((shaderAttrib = this.attribs[id])) { + const attr = specAttribs[id]; + attr.buffer!.bind(); + gl.enableVertexAttribArray(shaderAttrib.loc); + gl.vertexAttribPointer( + shaderAttrib.loc, + attr.size || 3, + attr.type || gl.FLOAT, + attr.normalized || false, + attr.stride || 0, + attr.offset || 0 + ); + } else { + console.warn(`unknown attrib: ${id}`); + } + } + } + + bindUniforms(specUnis: UniformValues = {}) { + const shaderUnis = this.uniforms; + for (let id in specUnis) { + const u = shaderUnis[id]; + if (u) { + let val = specUnis[id]; + val = isFunction(val) + ? val(shaderUnis, specUnis) + : implementsFunction(val, "deref") + ? (>val).deref() + : val; + // console.log(id, val); + u.setter(val); + } else { + console.warn(`unknown uniform: ${id}`); + } + } + // apply defaults for non-specified uniforms in user spec + for (let id in shaderUnis) { + if ( + shaderUnis.hasOwnProperty(id) && + (!specUnis || !existsAndNotNull(specUnis[id])) + ) { + const u = shaderUnis[id]; + const val = u.defaultFn + ? u.defaultFn(shaderUnis, specUnis) + : u.defaultVal; + // console.log("default", id, val); + u.setter(val); + } + } + } + + prepareState(state = this.state) { + const gl = this.gl; + state.depth !== undefined && this.setState(gl.DEPTH_TEST, state.depth); + if (state.cull !== undefined) { + this.setState(gl.CULL_FACE, state.cull); + state.cullMode && gl.cullFace(state.cullMode); + } + if (state.blend !== undefined) { + this.setState(gl.BLEND, state.blend); + state.blendFn && gl.blendFunc(state.blendFn[0], state.blendFn[1]); + state.blendEq !== undefined && gl.blendEquation(state.blendEq); + } + if (state.stencil !== undefined) { + this.setState(gl.STENCIL_TEST, state.stencil); + state.stencilFn && + gl.stencilFunc( + state.stencilFn[0], + state.stencilFn[1], + state.stencilFn[2] + ); + state.stencilOp && + gl.stencilOp( + state.stencilOp[0], + state.stencilOp[1], + state.stencilOp[2] + ); + state.stencilMask !== undefined && + gl.stencilMask(state.stencilMask); + } + } + + protected setState(id: number, val: GLenum | boolean) { + if (val) { + this.gl.enable(id); + } else { + this.gl.disable(id); + } + } +} + +export const shader = (gl: WebGLRenderingContext, spec: ShaderSpec) => { + const version = isGL2Context(gl) + ? GLSLVersion.GLES_300 + : GLSLVersion.GLES_100; + const srcVS = isFunction(spec.vs) + ? shaderSourceFromAST(spec, "vs", version) + : prepareShaderSource(spec, "vs", version); + const srcFS = isFunction(spec.fs) + ? shaderSourceFromAST(spec, "fs", version) + : prepareShaderSource(spec, "fs", version); + console.log(srcVS); + console.log(srcFS); + initShaderExtensions(gl, spec.ext); + const vs = compileShader(gl, gl.VERTEX_SHADER, srcVS); + const fs = compileShader(gl, gl.FRAGMENT_SHADER, srcFS); + const program = + gl.createProgram() || error("error creating shader program"); + gl.attachShader(program, vs); + gl.attachShader(program, fs); + gl.linkProgram(program); + if (gl.getProgramParameter(program, gl.LINK_STATUS)) { + const attribs = initAttributes(gl, program, spec.attribs); + const uniforms = initUniforms(gl, program, spec.uniforms); + gl.deleteShader(vs); + gl.deleteShader(fs); + return new Shader(gl, program, attribs, uniforms, spec.state); + } + throw new Error(`Error linking shader: ${gl.getProgramInfoLog(program)}`); +}; + +const compileVars = ( + attribs: any, + syntax: Fn3, + prefixes: GLSLDeclPrefixes +) => { + let decls: string[] = []; + for (let id in attribs) { + if (attribs.hasOwnProperty(id)) { + decls.push(syntax(id, attribs[id], prefixes)); + } + } + decls.push(""); + return decls.join("\n"); +}; + +const compileExtensionPragma = ( + id: string, + behavior: GLSLExtensionBehavior, + version: GLSLVersion +) => { + const ext = (GL_EXT_INFO)[id]; + const gl2 = version === GLSLVersion.GLES_300; + return !ext || (!gl2 && ext.gl) || (gl2 && ext.gl2) + ? `#extension ${ext.alias || id} : ${ + isBoolean(behavior) ? (behavior ? "enable" : "disable") : behavior + }\n` + : ""; +}; + +const initShaderExtensions = ( + gl: WebGLRenderingContext, + exts: IObjectOf | undefined +) => { + if (exts) { + for (let id in exts) { + const state = exts[id]; + if (state === true || state === "require") { + getExtensions(gl, [id], state === "require"); + } + } + } +}; + +export const shaderSourceFromAST = ( + spec: ShaderSpec, + type: ShaderType, + version: GLSLVersion +) => { + let prelude = ""; + prelude += spec.pre + ? spec.replacePrelude + ? spec.pre + : spec.pre + "\n" + GLSL_HEADER + : GLSL_HEADER; + if (spec.ext) { + for (let id in spec.ext) { + prelude += compileExtensionPragma(id, spec.ext[id], version); + } + } + const inputs: IObjectOf> = {}; + const outputs: IObjectOf> = {}; + const outputAliases: IObjectOf> = {}; + const unis: IObjectOf> = {}; + if (spec.uniforms) { + for (let id in spec.uniforms) { + const u = spec.uniforms[id]; + unis[id] = isArray(u) + ? u[0].indexOf("[]") > 0 + ? uniform(u[0], id, { num: u[1] }) + : uniform(u[0], id) + : uniform(u, id); + } + } + if (type === "vs") { + for (let id in spec.attribs) { + const a = spec.attribs[id]; + inputs[id] = isArray(a) + ? input(a[0], id, { loc: a[1] }) + : input(a, id); + } + if (spec.varying) { + for (let id in spec.varying) { + const v = spec.varying[id]; + outputs[id] = isArray(v) + ? output(v[0], id, { num: v[1] }) + : output(v, id); + } + } + } else { + if (spec.varying) { + for (let id in spec.varying) { + const v = spec.varying[id]; + inputs[id] = isArray(v) + ? input(v[0], id, { num: v[1] }) + : input(v, id); + } + } + const outs = spec.outputs || DEFAULT_OUTPUT; + if (version >= GLSLVersion.GLES_300) { + for (let id in outs) { + const o = outs[id]; + outputs[id] = isArray(o) + ? output(o[0], id, { loc: o[1] }) + : output(o, id); + } + } else { + for (let id in outs) { + const o = outs[id]; + if (isArray(o) && o[0] === "vec4") { + prelude += `#define ${id} gl_FragData[${o[1]}]\n`; + outputAliases[id] = sym("vec4", id); + } else { + unsupported(`GLSL ${version} doesn't support output vars`); + } + } + } + } + const target = targetGLSL({ + type, + version, + prelude + }); + return ( + target( + program([ + ...vals(unis), + ...vals(inputs), + ...vals(outputs), + ...(spec[type])(target, unis, inputs, { + ...outputs, + ...outputAliases + }) + ]) + ) + (spec.post ? "\n" + spec.post : "") + ); +}; + +export const prepareShaderSource = ( + spec: ShaderSpec, + type: ShaderType, + version: GLSLVersion +) => { + const syntax = SYNTAX[version]; + const prefixes = { ...NO_PREFIXES, ...spec.declPrefixes }; + const isVS = type === "vs"; + let src = ""; + src += `#version ${version}\n`; + src += spec.pre + ? spec.replacePrelude + ? spec.pre + : spec.pre + "\n" + GLSL_HEADER + : GLSL_HEADER; + if (spec.ext) { + for (let id in spec.ext) { + src += compileExtensionPragma(id, spec.ext[id], version); + } + } + if (spec.generateDecls !== false) { + src += isVS + ? compileVars(spec.attribs, syntax.attrib, prefixes) + : compileVars( + spec.outputs || DEFAULT_OUTPUT, + syntax.output, + prefixes + ); + src += compileVars(spec.varying, syntax.varying[type], prefixes); + src += compileVars(spec.uniforms, syntax.uniform, prefixes); + } + src += spec[type]; + spec.post && (src += "\n" + spec.post); + return src; +}; + +export const compileShader = ( + gl: WebGLRenderingContext, + type: GLenum, + src: string +) => { + const shader = gl.createShader(type) || error("error creating shader"); + gl.shaderSource(shader, src); + gl.compileShader(shader); + if (gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { + return shader; + } + return parseAndThrowShaderError(gl, shader, src); +}; + +const parseAndThrowShaderError = ( + gl: WebGLRenderingContext, + shader: WebGLShader, + src: string +) => { + const lines = src.split("\n"); + const log = gl.getShaderInfoLog(shader)!.split("\n"); + const errors = log + .map((line) => { + const matches = ERROR_REGEXP.exec(line); + const ln = matches ? matches[1] : null; + if (ln) { + return `line ${ln}: ${matches![2]}\n${lines[parseInt(ln) - 1]}`; + } + }) + .filter(existsAndNotNull) + .join("\n"); + return error(`Error compiling shader:\n${errors}`); +}; + +const initAttributes = ( + gl: WebGLRenderingContext, + prog: WebGLProgram, + attribs: ShaderAttribSpecs +) => { + const res = >{}; + for (let id in attribs) { + const val = attribs[id]; + const [type, loc] = isArray(val) ? val : [val, null]; + const aid = id; + if (loc != null) { + gl.bindAttribLocation(prog, loc, aid); + res[id] = { type, loc }; + } else { + res[id] = { + type, + loc: gl.getAttribLocation(prog, aid) + }; + } + } + return res; +}; + +const initUniforms = ( + gl: WebGLRenderingContext, + prog: WebGLProgram, + uniforms: ShaderUniformSpecs = {} +) => { + const res = >{}; + for (let id in uniforms) { + const val = uniforms[id]; + let type: GLSL; + let t1, t2, defaultVal, defaultFn; + if (isArray(val)) { + [type, t1, t2] = val; + defaultVal = type.indexOf("[]") < 0 ? t1 : t2; + if (isFunction(defaultVal)) { + defaultFn = defaultVal; + defaultVal = undefined; + } + } else { + type = val; + } + const loc = gl.getUniformLocation(prog, id)!; + loc == null && error(`unknown uniform: ${id}`); + const setter = UNIFORM_SETTERS[type]; + if (setter) { + res[id] = { + loc, + setter: setter(gl, loc, defaultVal), + defaultFn, + defaultVal, + type + }; + } else { + error(`invalid uniform type: ${type}`); + } + } + return res; +}; diff --git a/packages/webgl/src/shaders/lambert.ts b/packages/webgl/src/shaders/lambert.ts new file mode 100644 index 0000000000..8982375ae9 --- /dev/null +++ b/packages/webgl/src/shaders/lambert.ts @@ -0,0 +1,101 @@ +import { + $, + assign, + defMain, + mul, + normalize, + texture, + vec4 +} from "@thi.ng/shader-ast"; +import { + diffuseLighting, + halfLambert, + lambert, + surfaceNormal, + transformMVP +} from "@thi.ng/shader-ast-stdlib"; +import { Material, ShaderOpts, ShaderSpec } from "../api"; +import { defMaterial } from "../material"; +import { autoNormalMatrix2 } from "../matrices"; +import { colorAttrib, positionAttrib } from "../utils"; + +export interface LambertOpts + extends ShaderOpts> { + bidir: boolean; +} + +export const LAMBERT = (opts: Partial = {}): ShaderSpec => ({ + vs: (gl, unis, ins, outs) => [ + defMain(() => [ + opts.uv ? assign(outs.vuv, ins[opts.uv]) : null, + assign(outs.vcolor, colorAttrib(opts, ins, unis.diffuseCol)), + assign(outs.vnormal, surfaceNormal(ins.normal, unis.normalMat)), + assign( + gl.gl_Position, + transformMVP( + positionAttrib(opts, ins), + unis.model, + unis.view, + unis.proj + ) + ) + ]) + ], + fs: (_, unis, ins, outs) => [ + defMain(() => [ + assign( + outs.fragColor, + vec4( + diffuseLighting( + (opts.bidir !== false ? halfLambert : lambert)( + normalize(ins.vnormal), + unis.lightDir + ), + opts.uv + ? mul( + $(texture(unis.tex, ins.vuv), "xyz"), + ins.vcolor + ) + : ins.vcolor, + unis.lightCol, + unis.ambientCol + ), + 1 + ) + ) + ]) + ], + // pre: ALIAS_TEXTURE, + attribs: { + position: "vec3", + normal: "vec3", + ...(opts.uv ? { [opts.uv]: "vec2" } : null), + ...(opts.color && !opts.instanceColor + ? { [opts.color]: "vec3" } + : null), + ...(opts.instancePos ? { [opts.instancePos]: "vec3" } : null), + ...(opts.instanceColor ? { [opts.instanceColor]: "vec3" } : null) + }, + varying: { + vcolor: "vec3", + vnormal: "vec3", + ...(opts.uv ? { vuv: "vec2" } : null) + }, + uniforms: { + model: "mat4", + view: "mat4", + proj: "mat4", + normalMat: ["mat4", autoNormalMatrix2()], + lightDir: ["vec3", [0, 1, 0]], + lightCol: ["vec3", [1, 1, 1]], + ...defMaterial( + { diffuseCol: [1, 1, 1], ...opts.material }, + { specularCol: false } + ), + ...(opts.uv ? { tex: "sampler2D" } : null) + }, + state: { + depth: true, + ...opts.state + } +}); diff --git a/packages/webgl/src/shaders/phong.ts b/packages/webgl/src/shaders/phong.ts new file mode 100644 index 0000000000..0d86d21fa8 --- /dev/null +++ b/packages/webgl/src/shaders/phong.ts @@ -0,0 +1,113 @@ +import { + $, + add, + assign, + defMain, + dot, + FLOAT0, + gt, + max, + mul, + normalize, + pow, + sub, + Sym, + sym, + ternary, + vec4 +} from "@thi.ng/shader-ast"; +import { diffuseLighting, surfaceNormal } from "@thi.ng/shader-ast-stdlib"; +import { Material, ShaderOpts, ShaderSpec } from "../api"; +import { defMaterial } from "../material"; +import { autoNormalMatrix1 } from "../matrices"; +import { colorAttrib, positionAttrib } from "../utils"; + +export type PhongOpts = ShaderOpts< + Pick +>; + +export const PHONG = (opts: Partial = {}): ShaderSpec => ({ + vs: (gl, unis, ins, outs) => [ + defMain(() => { + let worldPos: Sym<"vec4">; + return [ + (worldPos = sym( + mul(unis.model, vec4(positionAttrib(opts, ins), 1)) + )), + assign(outs.vnormal, surfaceNormal(ins.normal, unis.normalMat)), + assign(outs.vlight, sub(unis.lightPos, $(worldPos, "xyz"))), + assign(outs.veye, sub(unis.eyePos, $(worldPos, "xyz"))), + assign(outs.vcolor, colorAttrib(opts, ins, unis.diffuseCol)), + assign(gl.gl_Position, mul(mul(unis.proj, unis.view), worldPos)) + ]; + }) + ], + fs: (_, unis, ins, outs) => [ + defMain(() => { + let normal: Sym<"vec3">; + let light: Sym<"vec3">; + let directional: Sym<"float">; + let specular: Sym<"float">; + return [ + (normal = sym(normalize(ins.vnormal))), + (light = sym(normalize(ins.vlight))), + (directional = sym(max(dot(normal, light), FLOAT0))), + (specular = sym( + ternary( + gt(directional, FLOAT0), + pow( + dot( + normal, + normalize(add(light, normalize(ins.veye))) + ), + unis.shininess + ), + FLOAT0 + ) + )), + assign( + outs.fragColor, + add( + diffuseLighting( + directional, + ins.vcolor, + unis.lightCol, + unis.ambientCol + ), + mul(unis.specularCol, specular) + ) + ) + ]; + }) + ], + attribs: { + position: "vec3", + normal: "vec3", + ...(opts.color && !opts.instanceColor + ? { [opts.color]: "vec3" } + : null), + ...(opts.instancePos ? { [opts.instancePos]: "vec3" } : null), + ...(opts.instanceColor ? { [opts.instanceColor]: "vec3" } : null) + }, + varying: { + vnormal: "vec3", + veye: "vec3", + vlight: "vec3", + vcolor: "vec3" + }, + uniforms: { + model: "mat4", + normalMat: ["mat4", autoNormalMatrix1()], + view: "mat4", + proj: "mat4", + shininess: ["float", 32], + eyePos: "vec3", + lightPos: ["vec3", [0, 0, 2]], + lightCol: ["vec3", [1, 1, 1]], + ...defMaterial(opts.material) + }, + state: { + depth: true, + ...opts.state + } +}); diff --git a/packages/webgl/src/syntax.ts b/packages/webgl/src/syntax.ts new file mode 100644 index 0000000000..b4ed10c53e --- /dev/null +++ b/packages/webgl/src/syntax.ts @@ -0,0 +1,126 @@ +import { isArray } from "@thi.ng/checks"; +import { GLSLVersion } from "@thi.ng/shader-ast-glsl"; +import { GLSL, GLSLDeclPrefixes, GLSLSyntax } from "./api"; + +export const PREFIXES: GLSLDeclPrefixes = { + a: "a_", + v: "v_", + u: "u_", + o: "o_" +}; + +export const NO_PREFIXES: GLSLDeclPrefixes = { + a: "", + v: "", + u: "", + o: "" +}; + +/** + * GLSL data declaration code generators. + */ +export const SYNTAX: Record = { + /** + * WebGL (GLSL ES 1.0) + */ + [GLSLVersion.GLES_100]: { + number: 100, + attrib: (id, type, pre) => + `attribute ${isArray(type) ? type[0] : type} ${pre.a}${id};`, + varying: { + vs: (id, type, pre) => arrayDecl("varying", type, pre.v + id), + fs: (id, type, pre) => arrayDecl("varying", type, pre.v + id) + }, + uniform: (id, u, pre) => arrayDecl("uniform", u, pre.u + id), + output: (id, type, pre) => + isArray(type) ? `#define ${pre.o}${id} gl_FragData[${type[1]}]` : "" + }, + /** + * WebGL 2 (GLSL ES 3) + */ + [GLSLVersion.GLES_300]: { + number: 300, + attrib: (id, type, pre) => + isArray(type) + ? `layout(location=${type[1]}) in ${type[0]} ${pre.a}${id};` + : `in ${type} ${pre.a}${id};`, + varying: { + vs: (id, type, pre) => arrayDecl("out", type, pre.v + id), + fs: (id, type, pre) => arrayDecl("in", type, pre.v + id) + }, + uniform: (id, u, pre) => arrayDecl("uniform", u, pre.u + id), + output: (id, type, pre) => + isArray(type) + ? `layout(location=${type[1]}) out ${type[0]} ${pre.o}${id};` + : `out ${type} ${pre.o}${id};` + } +}; + +const arrayDecl = ( + qualifier: string, + decl: GLSL | [GLSL, number], + id: string +) => { + const type = isArray(decl) ? decl[0] : decl; + return type.indexOf("[]") > 0 + ? `${qualifier} ${type.replace("[]", "")} ${id}[${ + (<[GLSL, number]>decl)[1] + }];` + : `${qualifier} ${type} ${id};`; +}; + +/** + * GLSL preprocessor macro for conditional execution based on `__VERSION__`. + * + * @param ver + * @param ok + * @param fail + */ +export const VERSION_CHECK = (ver: number, ok: string, fail = "") => { + let cmp = ">="; + if (!ok) { + ok = fail; + fail = null; + cmp = "<"; + } + return `#if __VERSION__ ${cmp} ${ver} +${ok}${fail ? `\n#else\n${fail}` : ""} +#endif`; +}; + +export const ALIAS_TEXTURE = VERSION_CHECK( + 300, + "", + "#define texture texture2D" +); + +/** + * GLSL version specific fragment shader output. If `__VERSION__ >= 300` + * assigns `body` to `out`, else to `gl_FragColor`. + * + * @param body + * @param out + */ +export const EXPORT_FRAGCOL = (body = "col", out = "o_fragColor") => + VERSION_CHECK(300, `${out}=${body};`, `gl_FragColor=${body};`); + +/** + * Default GLSL prelude. + */ +export const GLSL_HEADER = `#ifdef GL_FRAGMENT_PRECISION_HIGH +precision highp int; +precision highp float; +#else +precision mediump int; +precision mediump float; +#endif +#ifndef PI +#define PI 3.141592653589793 +#endif +#ifndef TAU +#define TAU 6.283185307179586 +#endif +#ifndef HALF_PI +#define HALF_PI 1.570796326794896 +#endif +`; diff --git a/packages/webgl/src/texture.ts b/packages/webgl/src/texture.ts new file mode 100644 index 0000000000..e49611282a --- /dev/null +++ b/packages/webgl/src/texture.ts @@ -0,0 +1,265 @@ +import { withoutKeysObj } from "@thi.ng/associative"; +import { isArray } from "@thi.ng/checks"; +import { ITexture, TextureOpts } from "./api"; +import { error } from "./error"; +import { isGL2Context } from "./utils"; + +export const bindTextures = (textures: ITexture[]) => { + if (!textures) return; + for (let i = textures.length, tex; --i >= 0; ) { + (tex = textures[i]) && tex.bind(i); + } +}; + +export class Texture implements ITexture { + gl: WebGLRenderingContext; + tex: WebGLTexture; + target: GLenum; + + constructor(gl: WebGLRenderingContext, opts: Partial = {}) { + this.gl = gl; + this.tex = gl.createTexture() || error("error creating WebGL texture"); + this.target = opts!.target || gl.TEXTURE_2D; + this.configure(opts); + } + + configure(opts: Partial = {}) { + const gl = this.gl; + const isGL2 = isGL2Context(gl); + const target = this.target; + const imgTarget = opts.target || target; + const format = opts.format || gl.RGBA; + const internalFormat = opts.internalFormat || format; + const type = opts.type || gl.UNSIGNED_BYTE; + let t1: GLenum, t2: GLenum, t3: GLenum; + + gl.bindTexture(this.target, this.tex); + + opts.flip !== undefined && + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, opts.flip ? 1 : 0); + + opts.premultiply !== undefined && + gl.pixelStorei( + gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, + opts.premultiply ? 1 : 0 + ); + + if (opts.image !== undefined) { + const level = opts.level || 0; + const pos = opts.pos || [0, 0]; + if (opts.width && opts.height) { + opts.sub + ? gl.texSubImage2D( + imgTarget, + level, + pos[0], + pos[1], + opts.width, + opts.height, + format, + type, + opts.image + ) + : gl.texImage2D( + imgTarget, + level, + internalFormat, + opts.width, + opts.height, + 0, + format, + type, + opts.image + ); + } else { + opts.sub + ? gl.texSubImage2D( + imgTarget, + level, + pos[0], + pos[1], + format, + type, + opts.image + ) + : gl.texImage2D( + imgTarget, + level, + internalFormat, + format, + type, + opts.image + ); + } + } + + opts.mipmap && gl.generateMipmap(target); + + if (opts.filter) { + const flt = opts.filter; + if (isArray(flt)) { + t1 = flt[0]; + t2 = flt[1]!; + } else { + t1 = t2 = flt; + } + t1 && gl.texParameteri(target, gl.TEXTURE_MIN_FILTER, t1); + t2 && gl.texParameteri(target, gl.TEXTURE_MAG_FILTER, t2); + } + + if (opts.wrap) { + const wrap = opts.wrap; + if (isArray(wrap)) { + t1 = wrap[0]; + t2 = wrap[1]!; + t3 = wrap[2]!; + } else { + t1 = t2 = t3 = wrap; + } + t1 && gl.texParameteri(target, gl.TEXTURE_WRAP_S, t1); + t2 && gl.texParameteri(target, gl.TEXTURE_WRAP_T, t2); + t3 && + isGL2 && + target === (gl).TEXTURE_3D && + gl.texParameteri( + target, + (gl).TEXTURE_WRAP_R, + t3 + ); + } + + if (opts.lod) { + const [t1, t2] = opts.lod; + t1 && + gl.texParameteri( + target, + (gl).TEXTURE_MIN_LOD, + t1 + ); + t2 && + gl.texParameteri( + target, + (gl).TEXTURE_MAX_LOD, + t2 + ); + } + + if (opts.minMaxLevel) { + const [t1, t2] = opts.minMaxLevel; + gl.texParameteri( + target, + (gl).TEXTURE_BASE_LEVEL, + t1 + ); + gl.texParameteri( + target, + (gl).TEXTURE_MAX_LEVEL, + t2 + ); + } + + return true; + } + + bind(id = 0) { + const gl = this.gl; + gl.activeTexture(gl.TEXTURE0 + id); + gl.bindTexture(this.target, this.tex); + return true; + } + + unbind(id = 0) { + const gl = this.gl; + gl.activeTexture(gl.TEXTURE0 + id); + gl.bindTexture(this.target, null); + return true; + } + + release() { + if (this.tex) { + this.gl.deleteTexture(this.tex); + delete this.tex; + delete this.gl; + return true; + } + return false; + } +} + +export const texture = ( + gl: WebGLRenderingContext, + opts?: Partial +) => new Texture(gl, opts); + +/** + * Creates cube map texture from given 6 `face` texture sources. The + * given options are shared by each each side/face of the cube map. The + * following options are applied to the cube map directly: + * + * - `filter` + * - `mipmap` + * + * The following options are ignored entirely: + * + * - `target` + * - `image` + * + * @param gl + * @param faces in order: +x,-x,+y,-y,+z,-z + * @param opts + */ +export const cubeMap = ( + gl: WebGLRenderingContext, + faces: (ArrayBufferView | TexImageSource)[], + opts: Partial = {} +) => { + const tex = new Texture(gl, { target: gl.TEXTURE_CUBE_MAP }); + const faceOpts = withoutKeysObj(opts, [ + "target", + "image", + "filter", + "mipmap" + ]); + for (let i = 0; i < 6; i++) { + faceOpts.target = gl.TEXTURE_CUBE_MAP_POSITIVE_X + i; + faceOpts.image = faces[i]; + tex.configure(faceOpts); + } + tex.configure({ filter: opts.filter, mipmap: opts.mipmap }); + return tex; +}; + +/** + * Creates & configure a new FLOAT texture. + * + * **Important:** Since each texel will hold 4x 32-bit float values, the + * `data` buffer needs to have a length of at least `4 * width * + * height`. + * + * Under WebGL 1.0, we assume the caller has previously enabled the + * `OES_texture_float` extension. + * + * @param gl GL context + * @param data texture data + * @param width width + * @param height height + */ +export const floatTexture = ( + gl: WebGLRenderingContext, + data: Float32Array | undefined | null, + width: number, + height: number, + internalFormat?: GLenum, + format?: GLenum +) => + new Texture(gl, { + filter: gl.NEAREST, + wrap: gl.CLAMP_TO_EDGE, + internalFormat: + internalFormat || (isGL2Context(gl) ? gl.RGBA32F : gl.RGBA), + format: format || gl.RGBA, + type: gl.FLOAT, + image: data, + width, + height + }); diff --git a/packages/webgl/src/textures/checkerboard.ts b/packages/webgl/src/textures/checkerboard.ts new file mode 100644 index 0000000000..dc2a4547e3 --- /dev/null +++ b/packages/webgl/src/textures/checkerboard.ts @@ -0,0 +1,37 @@ +import { abgr, canvas2d } from "./utils"; + +export interface CheckerboardOpts { + size: number; + col1: number; + col2: number; + corners: boolean; + cornerCols: number[]; +} + +export const checkerboard = (opts: Partial) => { + opts = { + size: 16, + col1: 0xffffffff, + col2: 0xff000000, + cornerCols: [0xffff0000, 0xff00ff00, 0xff0000ff, 0xffffff00], + ...opts + }; + const size = opts.size!; + const col1 = abgr(opts.col1!); + const col2 = abgr(opts.col2!); + const { canvas, ctx, img, pix } = canvas2d(size); + for (let y = 0, i = 0; y < size; y++) { + for (let x = 0; x < size; x++, i++) { + pix[i] = (y & 1) ^ (x & 1) ? col1 : col2; + } + } + if (opts.corners) { + const corners = opts.cornerCols!.map(abgr); + pix[0] = corners[0]; + pix[size - 1] = corners[1]; + pix[pix.length - size] = corners[2]; + pix[pix.length - 1] = corners[3]; + } + ctx.putImageData(img, 0, 0); + return canvas; +}; diff --git a/packages/webgl/src/textures/stripes.ts b/packages/webgl/src/textures/stripes.ts new file mode 100644 index 0000000000..8d8b911d80 --- /dev/null +++ b/packages/webgl/src/textures/stripes.ts @@ -0,0 +1,28 @@ +import { abgr, canvas2d } from "./utils"; + +export interface StripeOpts { + size: number; + col1: number; + col2: number; + horizontal: boolean; +} + +export const stripes = (opts: Partial) => { + opts = { + size: 16, + col1: 0xffffffff, + col2: 0xff000000, + ...opts + }; + const size = opts.size!; + const col1 = abgr(opts.col1!); + const col2 = abgr(opts.col2!); + const { canvas, ctx, img, pix } = opts.horizontal + ? canvas2d(1, size) + : canvas2d(size, 1); + for (let x = size; --x >= 0; ) { + pix[x] = x & 1 ? col1 : col2; + } + ctx.putImageData(img, 0, 0); + return canvas; +}; diff --git a/packages/webgl/src/textures/utils.ts b/packages/webgl/src/textures/utils.ts new file mode 100644 index 0000000000..cbfb1dd7e9 --- /dev/null +++ b/packages/webgl/src/textures/utils.ts @@ -0,0 +1,19 @@ +import { swizzle8 } from "@thi.ng/binary"; +import { error } from "../error"; + +export const canvas2d = (width: number, height = width) => { + const canvas = document.createElement("canvas"); + canvas.width = width; + canvas.height = height; + const ctx = canvas.getContext("2d") || error("can't create texture canvas"); + const img = ctx.getImageData(0, 0, width, height); + const pix = new Uint32Array(img.data.buffer); + return { + canvas, + ctx, + img, + pix + }; +}; + +export const abgr = (argb: number) => swizzle8(argb, 0, 3, 1, 2); diff --git a/packages/webgl/src/uniforms.ts b/packages/webgl/src/uniforms.ts new file mode 100644 index 0000000000..c80f8e1216 --- /dev/null +++ b/packages/webgl/src/uniforms.ts @@ -0,0 +1,125 @@ +import { Fn, Fn3, IObjectOf } from "@thi.ng/api"; +import { equivArrayLike } from "@thi.ng/equiv"; +import { IDENT22, IDENT33, IDENT44 } from "@thi.ng/matrices"; +import { + ReadonlyVec, + ZERO2, + ZERO3, + ZERO4 +} from "@thi.ng/vectors"; +import { GLVec, UniformValue } from "./api"; + +type SetterS = "f" | "i" | "ui"; + +type SetterV = + | "1fv" + | "2fv" + | "3fv" + | "4fv" + | "1iv" + | "2iv" + | "3iv" + | "4iv" + | "1uiv" + | "2uiv" + | "3uiv" + | "4uiv"; + +type SetterM = "2fv" | "3fv" | "4fv"; + +const uniformS = (fn: SetterS) => ( + gl: WebGLRenderingContext, + loc: WebGLUniformLocation, + defaultVal = 0 +) => { + let prev: number; + return (x?: number) => { + x = x === undefined ? defaultVal : x; + if (x !== prev) { + (gl)["uniform1" + fn](loc, x); + prev = x; + } + }; +}; + +const uniformV = (fn: SetterV, sysDefault?: ReadonlyVec) => ( + gl: WebGLRenderingContext, + loc: WebGLUniformLocation, + defaultVal = sysDefault +) => { + let prev: GLVec = []; + return (x?: any) => { + x = x === undefined ? defaultVal : x; + if (!equivArrayLike(prev, x)) { + (gl)["uniform" + fn](loc, x); + prev = x; + } + }; +}; + +const uniformM = (fn: SetterM, sysDefault?: ReadonlyVec) => ( + gl: WebGLRenderingContext, + loc: WebGLUniformLocation, + defaultVal = sysDefault +) => { + let prev: GLVec = []; + return (x?: any) => { + x = x === undefined ? defaultVal : x; + if (!equivArrayLike(prev, x)) { + (gl)["uniformMatrix" + fn](loc, false, x); + prev = x; + } + }; +}; + +export const UNIFORM_SETTERS: IObjectOf< + Fn3< + WebGLRenderingContext, + WebGLUniformLocation, + number | ReadonlyVec | undefined, + Fn + > +> = { + bool: uniformS("i"), + float: uniformS("f"), + int: uniformS("i"), + uint: uniformS("ui"), + bvec2: uniformV("2iv", ZERO2), + bvec3: uniformV("3iv", ZERO3), + bvec4: uniformV("4iv", ZERO4), + ivec2: uniformV("2iv", ZERO2), + ivec3: uniformV("3iv", ZERO3), + ivec4: uniformV("4iv", ZERO4), + vec2: uniformV("2fv", ZERO2), + vec3: uniformV("3fv", ZERO3), + vec4: uniformV("4fv", ZERO4), + mat2: uniformM("2fv", IDENT22), + mat3: uniformM("3fv", IDENT33), + mat4: uniformM("4fv", IDENT44), + sampler2D: uniformS("i"), + sampler2DShadow: uniformS("i"), + sampler3D: uniformS("i"), + samplerCube: uniformS("i"), + samplerCubeShadow: uniformS("i"), + "bool[]": uniformV("1iv"), + "float[]": uniformV("1fv"), + "int[]": uniformV("1iv"), + "uint[]": uniformV("1uiv"), + "bvec2[]": uniformV("2iv"), + "bvec3[]": uniformV("3iv"), + "bvec4[]": uniformV("4iv"), + "ivec2[]": uniformV("2iv"), + "ivec3[]": uniformV("3iv"), + "ivec4[]": uniformV("4iv"), + "vec2[]": uniformV("2fv"), + "vec3[]": uniformV("3fv"), + "vec4[]": uniformV("4fv"), + "mat2[]": uniformM("2fv"), + "mat3[]": uniformM("3fv"), + "mat4[]": uniformM("4fv"), + "sampler2D[]": uniformV("1iv"), + "sampler2DShadow[]": uniformV("1iv"), + "sampler3D[]": uniformV("1iv"), + "samplerCube[]": uniformV("1iv"), + "samplerCubeShadow[]": uniformV("1iv") +}; diff --git a/packages/webgl/src/utils.ts b/packages/webgl/src/utils.ts new file mode 100644 index 0000000000..625522d3f5 --- /dev/null +++ b/packages/webgl/src/utils.ts @@ -0,0 +1,34 @@ +import { IObjectOf } from "@thi.ng/api"; +import { + add, + mul, + Sym, + Term +} from "@thi.ng/shader-ast"; +import { ShaderOpts } from "./api"; + +export const isGL2Context = ( + gl: WebGLRenderingContext +): gl is WebGL2RenderingContext => + typeof WebGL2RenderingContext !== "undefined" && + gl instanceof WebGL2RenderingContext; + +export const positionAttrib = ( + opts: Partial>, + attribs: IObjectOf>, + pos = "position" +) => + opts.instancePos + ? add(attribs[pos], attribs[opts.instancePos]) + : attribs[pos]; + +export const colorAttrib = ( + opts: Partial>, + attribs: IObjectOf>, + fallback: Sym<"vec3"> +): Term<"vec3"> => + opts.instanceColor + ? mul(attribs[opts.instanceColor], fallback) + : opts.color + ? mul(attribs[opts.color], fallback) + : fallback; diff --git a/packages/webgl/test/index.ts b/packages/webgl/test/index.ts new file mode 100644 index 0000000000..b4b0d407d2 --- /dev/null +++ b/packages/webgl/test/index.ts @@ -0,0 +1,6 @@ +// import * as assert from "assert"; +// import * as w from "../src/index"; + +describe("webgl", () => { + it("tests pending"); +}); diff --git a/packages/webgl/test/tsconfig.json b/packages/webgl/test/tsconfig.json new file mode 100644 index 0000000000..f6e63560dd --- /dev/null +++ b/packages/webgl/test/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../../tsconfig.json", + "compilerOptions": { + "outDir": "../build", + "module": "commonjs" + }, + "include": [ + "./**/*.ts", + "../src/**/*.ts" + ] +} diff --git a/packages/webgl/tsconfig.json b/packages/webgl/tsconfig.json new file mode 100644 index 0000000000..893b9979c5 --- /dev/null +++ b/packages/webgl/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": ".", + "module": "es6", + "target": "es6" + }, + "include": [ + "./src/**/*.ts" + ] +} diff --git a/tsconfig.json b/tsconfig.json index 67f0c1e296..d84f30937d 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,9 +6,9 @@ "noUnusedParameters": true, "noUnusedLocals": true, "preserveConstEnums": true, - "moduleResolution": "node" + "moduleResolution": "node", + "strict": true, + "strictNullChecks": true }, - "exclude": [ - "./**/node_modules" - ] -} \ No newline at end of file + "exclude": ["./**/node_modules"] +} diff --git a/yarn.lock b/yarn.lock index 1905554cda..d7a220a0aa 100644 --- a/yarn.lock +++ b/yarn.lock @@ -29,17 +29,6 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/generator@^7.0.0", "@babel/generator@^7.2.2": - version "7.2.2" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.2.2.tgz#18c816c70962640eab42fe8cae5f3947a5c65ccc" - integrity sha512-I4o675J/iS8k+P38dvJ3IBGqObLXyQLTxtrR4u9cSUJOURvafeEWb/pFMOTwtNrmq73mJzyF6ueTbO1BtN0Zeg== - dependencies: - "@babel/types" "^7.2.2" - jsesc "^2.5.1" - lodash "^4.17.10" - source-map "^0.5.0" - trim-right "^1.0.1" - "@babel/generator@^7.0.0 <7.4.0": version "7.3.4" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.3.4.tgz#9aa48c1989257877a9d971296e5b73bfe72e446e" @@ -51,12 +40,12 @@ source-map "^0.5.0" trim-right "^1.0.1" -"@babel/generator@^7.3.4", "@babel/generator@^7.4.0": - version "7.4.0" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.4.0.tgz#c230e79589ae7a729fd4631b9ded4dc220418196" - integrity sha512-/v5I+a1jhGSKLgZDcmAUZ4K/VePi43eRkUs3yePW1HB1iANOD5tqJXwGSG4BZhSksP8J9ejSlwGeTiiOFZOrXQ== +"@babel/generator@^7.3.4", "@babel/generator@^7.4.0", "@babel/generator@^7.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.4.4.tgz#174a215eb843fc392c7edcaabeaa873de6e8f041" + integrity sha512-53UOLK6TVNqKxf7RUh8NE851EHRxOOeVXKbK2bivdb+iziMyk03Sr4eaE9OELCbyZAAafAKPDwF2TPUES5QbxQ== dependencies: - "@babel/types" "^7.4.0" + "@babel/types" "^7.4.4" jsesc "^2.5.1" lodash "^4.17.11" source-map "^0.5.0" @@ -85,22 +74,22 @@ "@babel/types" "^7.3.0" esutils "^2.0.0" -"@babel/helper-call-delegate@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/helper-call-delegate/-/helper-call-delegate-7.1.0.tgz#6a957f105f37755e8645343d3038a22e1449cc4a" - integrity sha512-YEtYZrw3GUK6emQHKthltKNZwszBcHK58Ygcis+gVUrF4/FmTVr5CCqQNSfmvg2y+YDEANyYoaLz/SHsnusCwQ== +"@babel/helper-call-delegate@^7.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/helper-call-delegate/-/helper-call-delegate-7.4.4.tgz#87c1f8ca19ad552a736a7a27b1c1fcf8b1ff1f43" + integrity sha512-l79boDFJ8S1c5hvQvG+rc+wHw6IuH7YldmRKsYtpbawsxURu/paVy57FZMomGK22/JckepaikOkY0MoAmdyOlQ== dependencies: - "@babel/helper-hoist-variables" "^7.0.0" - "@babel/traverse" "^7.1.0" - "@babel/types" "^7.0.0" + "@babel/helper-hoist-variables" "^7.4.4" + "@babel/traverse" "^7.4.4" + "@babel/types" "^7.4.4" -"@babel/helper-define-map@^7.4.0": - version "7.4.0" - resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.4.0.tgz#cbfd8c1b2f12708e262c26f600cd16ed6a3bc6c9" - integrity sha512-wAhQ9HdnLIywERVcSvX40CEJwKdAa1ID4neI9NXQPDOHwwA+57DqwLiPEVy2AIyWzAk0CQ8qx4awO0VUURwLtA== +"@babel/helper-define-map@^7.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.4.4.tgz#6969d1f570b46bdc900d1eba8e5d59c48ba2c12a" + integrity sha512-IX3Ln8gLhZpSuqHJSnTNBWGDE9kdkTEWl21A/K7PQ00tseBwbqCHTvNLHSBd9M0R5rER4h5Rsvj9vw0R5SieBg== dependencies: "@babel/helper-function-name" "^7.1.0" - "@babel/types" "^7.4.0" + "@babel/types" "^7.4.4" lodash "^4.17.11" "@babel/helper-explode-assignable-expression@^7.1.0": @@ -127,19 +116,12 @@ dependencies: "@babel/types" "^7.0.0" -"@babel/helper-hoist-variables@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.0.0.tgz#46adc4c5e758645ae7a45deb92bab0918c23bb88" - integrity sha512-Ggv5sldXUeSKsuzLkddtyhyHe2YantsxWKNi7A+7LeD12ExRDWTRk29JCXpaHPAbMaIPZSil7n+lq78WY2VY7w== - dependencies: - "@babel/types" "^7.0.0" - -"@babel/helper-hoist-variables@^7.4.0": - version "7.4.0" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.4.0.tgz#25b621399ae229869329730a62015bbeb0a6fbd6" - integrity sha512-/NErCuoe/et17IlAQFKWM24qtyYYie7sFIrW/tIQXpck6vAu2hhtYYsKLBWQV+BQZMbcIYPU/QMYuTufrY4aQw== +"@babel/helper-hoist-variables@^7.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.4.4.tgz#0298b5f25c8c09c53102d52ac4a98f773eb2850a" + integrity sha512-VYk2/H/BnYbZDDg39hr3t2kKyifAm1W6zHRfhx8jGjIHpQEBv9dry7oQ2f3+J703TLu69nYdxsovl0XYfcnK4w== dependencies: - "@babel/types" "^7.4.0" + "@babel/types" "^7.4.4" "@babel/helper-member-expression-to-functions@^7.0.0": version "7.0.0" @@ -155,17 +137,17 @@ dependencies: "@babel/types" "^7.0.0" -"@babel/helper-module-transforms@^7.1.0": - version "7.2.2" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.2.2.tgz#ab2f8e8d231409f8370c883d20c335190284b963" - integrity sha512-YRD7I6Wsv+IHuTPkAmAS4HhY0dkPobgLftHp0cRGZSdrRvmZY8rFvae/GVu3bD00qscuvK3WPHB3YdNpBXUqrA== +"@babel/helper-module-transforms@^7.1.0", "@babel/helper-module-transforms@^7.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.4.4.tgz#96115ea42a2f139e619e98ed46df6019b94414b8" + integrity sha512-3Z1yp8TVQf+B4ynN7WoHPKS8EkdTbgAEy0nU0rs/1Kw4pDgmvYH3rz3aI11KgxKCba2cn7N+tqzV1mY2HMN96w== dependencies: "@babel/helper-module-imports" "^7.0.0" "@babel/helper-simple-access" "^7.1.0" - "@babel/helper-split-export-declaration" "^7.0.0" - "@babel/template" "^7.2.2" - "@babel/types" "^7.2.2" - lodash "^4.17.10" + "@babel/helper-split-export-declaration" "^7.4.4" + "@babel/template" "^7.4.4" + "@babel/types" "^7.4.4" + lodash "^4.17.11" "@babel/helper-optimise-call-expression@^7.0.0": version "7.0.0" @@ -179,12 +161,12 @@ resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz#bbb3fbee98661c569034237cc03967ba99b4f250" integrity sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA== -"@babel/helper-regex@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.0.0.tgz#2c1718923b57f9bbe64705ffe5640ac64d9bdb27" - integrity sha512-TR0/N0NDCcUIUEbqV6dCO+LptmmSQFQ7q70lfcEB4URsjD0E1HzicrwUH+ap6BAQ2jhCX9Q4UqZy4wilujWlkg== +"@babel/helper-regex@^7.0.0", "@babel/helper-regex@^7.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.4.4.tgz#a47e02bc91fb259d2e6727c2a30013e3ac13c4a2" + integrity sha512-Y5nuB/kESmR3tKjU8Nkn1wMGEx1tjJX076HBMeL3XLQCu6vA/YRzuTW0bbb+qRnXvQGn+d6Rx953yffl8vEy7Q== dependencies: - lodash "^4.17.10" + lodash "^4.17.11" "@babel/helper-remap-async-to-generator@^7.1.0": version "7.1.0" @@ -197,25 +179,15 @@ "@babel/traverse" "^7.1.0" "@babel/types" "^7.0.0" -"@babel/helper-replace-supers@^7.1.0": - version "7.2.3" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.2.3.tgz#19970020cf22677d62b3a689561dbd9644d8c5e5" - integrity sha512-GyieIznGUfPXPWu0yLS6U55Mz67AZD9cUk0BfirOWlPrXlBcan9Gz+vHGz+cPfuoweZSnPzPIm67VtQM0OWZbA== - dependencies: - "@babel/helper-member-expression-to-functions" "^7.0.0" - "@babel/helper-optimise-call-expression" "^7.0.0" - "@babel/traverse" "^7.2.3" - "@babel/types" "^7.0.0" - -"@babel/helper-replace-supers@^7.4.0": - version "7.4.0" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.4.0.tgz#4f56adb6aedcd449d2da9399c2dcf0545463b64c" - integrity sha512-PVwCVnWWAgnal+kJ+ZSAphzyl58XrFeSKSAJRiqg5QToTsjL+Xu1f9+RJ+d+Q0aPhPfBGaYfkox66k86thxNSg== +"@babel/helper-replace-supers@^7.1.0", "@babel/helper-replace-supers@^7.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.4.4.tgz#aee41783ebe4f2d3ab3ae775e1cc6f1a90cefa27" + integrity sha512-04xGEnd+s01nY1l15EuMS1rfKktNF+1CkKmHoErDppjAAZL+IUBZpzT748x262HF7fibaQPhbvWUl5HeSt1EXg== dependencies: "@babel/helper-member-expression-to-functions" "^7.0.0" "@babel/helper-optimise-call-expression" "^7.0.0" - "@babel/traverse" "^7.4.0" - "@babel/types" "^7.4.0" + "@babel/traverse" "^7.4.4" + "@babel/types" "^7.4.4" "@babel/helper-simple-access@^7.1.0": version "7.1.0" @@ -225,19 +197,12 @@ "@babel/template" "^7.1.0" "@babel/types" "^7.0.0" -"@babel/helper-split-export-declaration@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0.tgz#3aae285c0311c2ab095d997b8c9a94cad547d813" - integrity sha512-MXkOJqva62dfC0w85mEf/LucPPS/1+04nmmRMPEBUB++hiiThQ2zPtX/mEWQ3mtzCEjIJvPY8nuwxXtQeQwUag== - dependencies: - "@babel/types" "^7.0.0" - -"@babel/helper-split-export-declaration@^7.4.0": - version "7.4.0" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.0.tgz#571bfd52701f492920d63b7f735030e9a3e10b55" - integrity sha512-7Cuc6JZiYShaZnybDmfwhY4UYHzI6rlqhWjaIqbsJGsIqPimEYy5uh3akSRLMg65LSdSEnJ8a8/bWQN6u2oMGw== +"@babel/helper-split-export-declaration@^7.0.0", "@babel/helper-split-export-declaration@^7.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz#ff94894a340be78f53f06af038b205c49d993677" + integrity sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q== dependencies: - "@babel/types" "^7.4.0" + "@babel/types" "^7.4.4" "@babel/helper-wrap-function@^7.1.0": version "7.2.0" @@ -250,13 +215,13 @@ "@babel/types" "^7.2.0" "@babel/helpers@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.2.0.tgz#8335f3140f3144270dc63c4732a4f8b0a50b7a21" - integrity sha512-Fr07N+ea0dMcMN8nFpuK6dUIT7/ivt9yKQdEEnjVS83tG2pHwPi03gYmk/tyuwONnZ+sY+GFFPlWGgCtW1hF9A== + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.4.4.tgz#868b0ef59c1dd4e78744562d5ce1b59c89f2f2a5" + integrity sha512-igczbR/0SeuPR8RFfC7tGrbdTbFL3QTvH6D+Z6zNxnTe//GyqmtHmDkzrqDmyZ3eSwPqB/LhyKoU5DXsp+Vp2A== dependencies: - "@babel/template" "^7.1.2" - "@babel/traverse" "^7.1.5" - "@babel/types" "^7.2.0" + "@babel/template" "^7.4.4" + "@babel/traverse" "^7.4.4" + "@babel/types" "^7.4.4" "@babel/highlight@^7.0.0": version "7.0.0" @@ -267,20 +232,15 @@ esutils "^2.0.2" js-tokens "^4.0.0" -"@babel/parser@^7.0.0", "@babel/parser@^7.2.2", "@babel/parser@^7.2.3": - version "7.2.3" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.2.3.tgz#32f5df65744b70888d17872ec106b02434ba1489" - integrity sha512-0LyEcVlfCoFmci8mXx8A5oIkpkOgyo8dRHtxBnK9RRBwxO2+JZPNsqtVEZQ7mJFPxnXF9lfmU24mHOPI0qnlkA== - "@babel/parser@^7.0.0 <7.4.0": version "7.3.4" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.3.4.tgz#a43357e4bbf4b92a437fb9e465c192848287f27c" integrity sha512-tXZCqWtlOOP4wgCp6RjRvLmfuhnqTLy9VHwRochJBCP2nDm27JnnuFEnXFASVyQNHk36jD1tAammsCEEqgscIQ== -"@babel/parser@^7.3.4", "@babel/parser@^7.4.0": - version "7.4.2" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.4.2.tgz#b4521a400cb5a871eab3890787b4bc1326d38d91" - integrity sha512-9fJTDipQFvlfSVdD/JBtkiY0br9BtfvW2R8wo6CX/Ej2eMuV0gWPk1M67Mt3eggQvBqYW1FCEk8BN7WvGm/g5g== +"@babel/parser@^7.2.2", "@babel/parser@^7.3.4", "@babel/parser@^7.4.3", "@babel/parser@^7.4.4", "@babel/parser@^7.4.5": + version "7.4.5" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.4.5.tgz#04af8d5d5a2b044a2a1bffacc1e5e6673544e872" + integrity sha512-9mUqkL1FF5T7f0WDFfAoDdiMVPWsdD1gZYzSnaXsxUCUqzuch/8of9G3VUSNiZmMBoRxT3neyVsqeiL/ZPcjew== "@babel/plugin-proposal-async-generator-functions@^7.2.0": version "7.2.0" @@ -300,9 +260,9 @@ "@babel/plugin-syntax-json-strings" "^7.2.0" "@babel/plugin-proposal-object-rest-spread@^7.3.4": - version "7.4.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.4.0.tgz#e4960575205eadf2a1ab4e0c79f9504d5b82a97f" - integrity sha512-uTNi8pPYyUH2eWHyYWWSYJKwKg34hhgl4/dbejEjL+64OhbHjTX7wEVWMQl82tEmdDsGeu77+s8HHLS627h6OQ== + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.4.4.tgz#1ef173fcf24b3e2df92a678f027673b55e7e3005" + integrity sha512-dMBG6cSPBbHeEBdFXeQ2QLc5gUpg4Vkaz8octD4aoW/ISO+jBOcsuxYL7bsb5WSu8RLP6boxrBIALEHgoHtO9g== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-object-rest-spread" "^7.2.0" @@ -316,13 +276,13 @@ "@babel/plugin-syntax-optional-catch-binding" "^7.2.0" "@babel/plugin-proposal-unicode-property-regex@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.2.0.tgz#abe7281fe46c95ddc143a65e5358647792039520" - integrity sha512-LvRVYb7kikuOtIoUeWTkOxQEV1kYvL5B6U3iWEGCzPNRus1MzJweFqORTj+0jkxozkTSYNJozPOddxmqdqsRpw== + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.4.4.tgz#501ffd9826c0b91da22690720722ac7cb1ca9c78" + integrity sha512-j1NwnOqMG9mFUOH58JTFsA/+ZYzQLUZ/drqWUqxCYLGeu2JFZL8YrNC9hBxKmWtAuOCHPcRpgv7fhap09Fb4kA== dependencies: "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-regex" "^7.0.0" - regexpu-core "^4.2.0" + "@babel/helper-regex" "^7.4.4" + regexpu-core "^4.5.4" "@babel/plugin-syntax-async-generators@^7.2.0": version "7.2.0" @@ -374,9 +334,9 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-async-to-generator@^7.3.4": - version "7.4.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.4.0.tgz#234fe3e458dce95865c0d152d256119b237834b0" - integrity sha512-EeaFdCeUULM+GPFEsf7pFcNSxM7hYjoj5fiYbyuiXobW4JhFnjAv9OWzNwHyHcKoPNpAfeRDuW6VyaXEDUBa7g== + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.4.4.tgz#a3f1d01f2f21cadab20b33a82133116f14fb5894" + integrity sha512-YiqW2Li8TXmzgbXw+STsSqPBPFnGviiaSp6CYOq55X8GQ2SGVLrXB6pNid8HkqkZAzOH6knbai3snhP7v0fNwA== dependencies: "@babel/helper-module-imports" "^7.0.0" "@babel/helper-plugin-utils" "^7.0.0" @@ -390,25 +350,25 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-block-scoping@^7.3.4": - version "7.4.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.4.0.tgz#164df3bb41e3deb954c4ca32ffa9fcaa56d30bcb" - integrity sha512-AWyt3k+fBXQqt2qb9r97tn3iBwFpiv9xdAiG+Gr2HpAZpuayvbL55yWrsV3MyHvXk/4vmSiedhDRl1YI2Iy5nQ== + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.4.4.tgz#c13279fabf6b916661531841a23c4b7dae29646d" + integrity sha512-jkTUyWZcTrwxu5DD4rWz6rDB5Cjdmgz6z7M7RLXOJyCUkFBawssDGcGh8M/0FTSB87avyJI1HsTwUXp9nKA1PA== dependencies: "@babel/helper-plugin-utils" "^7.0.0" lodash "^4.17.11" "@babel/plugin-transform-classes@^7.3.4": - version "7.4.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.4.0.tgz#e3428d3c8a3d01f33b10c529b998ba1707043d4d" - integrity sha512-XGg1Mhbw4LDmrO9rSTNe+uI79tQPdGs0YASlxgweYRLZqo/EQktjaOV4tchL/UZbM0F+/94uOipmdNGoaGOEYg== + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.4.4.tgz#0ce4094cdafd709721076d3b9c38ad31ca715eb6" + integrity sha512-/e44eFLImEGIpL9qPxSRat13I5QNRgBLu2hOQJCF7VLy/otSM/sypV1+XaIw5+502RX/+6YaSAPmldk+nhHDPw== dependencies: "@babel/helper-annotate-as-pure" "^7.0.0" - "@babel/helper-define-map" "^7.4.0" + "@babel/helper-define-map" "^7.4.4" "@babel/helper-function-name" "^7.1.0" "@babel/helper-optimise-call-expression" "^7.0.0" "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-replace-supers" "^7.4.0" - "@babel/helper-split-export-declaration" "^7.4.0" + "@babel/helper-replace-supers" "^7.4.4" + "@babel/helper-split-export-declaration" "^7.4.4" globals "^11.1.0" "@babel/plugin-transform-computed-properties@^7.2.0": @@ -419,20 +379,20 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-destructuring@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.2.0.tgz#e75269b4b7889ec3a332cd0d0c8cff8fed0dc6f3" - integrity sha512-coVO2Ayv7g0qdDbrNiadE4bU7lvCd9H539m2gMknyVjjMdwF/iCOM7R+E8PkntoqLkltO0rk+3axhpp/0v68VQ== + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.4.4.tgz#9d964717829cc9e4b601fc82a26a71a4d8faf20f" + integrity sha512-/aOx+nW0w8eHiEHm+BTERB2oJn5D127iye/SUQl7NjHy0lf+j7h4MKMMSOwdazGq9OxgiNADncE+SRJkCxjZpQ== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-dotall-regex@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.2.0.tgz#f0aabb93d120a8ac61e925ea0ba440812dbe0e49" - integrity sha512-sKxnyHfizweTgKZf7XsXu/CNupKhzijptfTM+bozonIuyVrLWVUvYjE2bhuSBML8VQeMxq4Mm63Q9qvcvUcciQ== + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.4.4.tgz#361a148bc951444312c69446d76ed1ea8e4450c3" + integrity sha512-P05YEhRc2h53lZDjRPk/OektxCVevFzZs2Gfjd545Wde3k+yFDbXORgl2e0xpbq8mLcKJ7Idss4fAg0zORN/zg== dependencies: "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-regex" "^7.0.0" - regexpu-core "^4.1.3" + "@babel/helper-regex" "^7.4.4" + regexpu-core "^4.5.4" "@babel/plugin-transform-duplicate-keys@^7.2.0": version "7.2.0" @@ -458,16 +418,16 @@ "@babel/plugin-syntax-flow" "^7.2.0" "@babel/plugin-transform-for-of@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.2.0.tgz#ab7468befa80f764bb03d3cb5eef8cc998e1cad9" - integrity sha512-Kz7Mt0SsV2tQk6jG5bBv5phVbkd0gd27SgYD4hH1aLMJRchM0dzHaXvrWhVZ+WxAlDoAKZ7Uy3jVTW2mKXQ1WQ== + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.4.4.tgz#0267fc735e24c808ba173866c6c4d1440fc3c556" + integrity sha512-9T/5Dlr14Z9TIEXLXkt8T1DU7F24cbhwhMNUziN3hB1AXoZcdzPcTiKGRn/6iOymDqtTKWnr/BtRKN9JwbKtdQ== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-function-name@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.2.0.tgz#f7930362829ff99a3174c39f0afcc024ef59731a" - integrity sha512-kWgksow9lHdvBC2Z4mxTsvc7YdY7w/V6B2vy9cTIPtLEE9NhwoWivaxdNM/S37elu5bqlLP/qOY906LukO9lkQ== + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.4.4.tgz#e1436116abb0610c2259094848754ac5230922ad" + integrity sha512-iU9pv7U+2jC9ANQkKeNF6DrPy4GBa4NWQtl6dHB4Pb3izX2JOEvDTFarlNsBj/63ZEzNNIAMs3Qw4fNCcSOXJA== dependencies: "@babel/helper-function-name" "^7.1.0" "@babel/helper-plugin-utils" "^7.0.0" @@ -487,7 +447,7 @@ "@babel/helper-module-transforms" "^7.1.0" "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-modules-commonjs@^7.0.0 <7.4.0", "@babel/plugin-transform-modules-commonjs@^7.2.0": +"@babel/plugin-transform-modules-commonjs@^7.0.0 <7.4.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.2.0.tgz#c4f1933f5991d5145e9cfad1dfd848ea1727f404" integrity sha512-V6y0uaUQrQPXUrmj+hgnks8va2L0zcZymeU7TtWEgdRLNkceafKXEduv7QzgQAE4lT+suwooG9dC7LFhdRAbVQ== @@ -496,12 +456,21 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/helper-simple-access" "^7.1.0" +"@babel/plugin-transform-modules-commonjs@^7.2.0": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.4.4.tgz#0bef4713d30f1d78c2e59b3d6db40e60192cac1e" + integrity sha512-4sfBOJt58sEo9a2BQXnZq+Q3ZTSAUXyK3E30o36BOGnJ+tvJ6YSxF0PG6kERvbeISgProodWuI9UVG3/FMY6iw== + dependencies: + "@babel/helper-module-transforms" "^7.4.4" + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/helper-simple-access" "^7.1.0" + "@babel/plugin-transform-modules-systemjs@^7.3.4": - version "7.4.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.4.0.tgz#c2495e55528135797bc816f5d50f851698c586a1" - integrity sha512-gjPdHmqiNhVoBqus5qK60mWPp1CmYWp/tkh11mvb0rrys01HycEGD7NvvSoKXlWEfSM9TcL36CpsK8ElsADptQ== + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.4.4.tgz#dc83c5665b07d6c2a7b224c00ac63659ea36a405" + integrity sha512-MSiModfILQc3/oqnG7NrP1jHaSPryO6tA2kOMmAQApz5dayPxWiHqmq4sWH2xF5LcQK56LlbKByCd8Aah/OIkQ== dependencies: - "@babel/helper-hoist-variables" "^7.4.0" + "@babel/helper-hoist-variables" "^7.4.4" "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-modules-umd@^7.2.0": @@ -513,16 +482,16 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-named-capturing-groups-regex@^7.3.0": - version "7.4.2" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.4.2.tgz#800391136d6cbcc80728dbdba3c1c6e46f86c12e" - integrity sha512-NsAuliSwkL3WO2dzWTOL1oZJHm0TM8ZY8ZSxk2ANyKkt5SQlToGA4pzctmq1BEjoacurdwZ3xp2dCQWJkME0gQ== + version "7.4.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.4.5.tgz#9d269fd28a370258199b4294736813a60bbdd106" + integrity sha512-z7+2IsWafTBbjNsOxU/Iv5CvTJlr5w4+HGu1HovKYTtgJ362f7kBcQglkfmlspKKZ3bgrbSGvLfNx++ZJgCWsg== dependencies: - regexp-tree "^0.1.0" + regexp-tree "^0.1.6" "@babel/plugin-transform-new-target@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.0.0.tgz#ae8fbd89517fa7892d20e6564e641e8770c3aa4a" - integrity sha512-yin069FYjah+LbqfGeTfzIBODex/e++Yfa0rH0fpfam9uTbuEeEOx5GLGr210ggOV77mVRNoeqSYqeuaqSzVSw== + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.4.4.tgz#18d120438b0cc9ee95a47f2c72bc9768fbed60a5" + integrity sha512-r1z3T2DNGQwwe2vPGZMBNjioT2scgWzK9BCnDEh+46z8EEwXBq24uRzd65I7pjtugzPSj921aM15RpESgzsSuA== dependencies: "@babel/helper-plugin-utils" "^7.0.0" @@ -535,11 +504,11 @@ "@babel/helper-replace-supers" "^7.1.0" "@babel/plugin-transform-parameters@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.2.0.tgz#0d5ad15dc805e2ea866df4dd6682bfe76d1408c2" - integrity sha512-kB9+hhUidIgUoBQ0MsxMewhzr8i60nMa2KgeJKQWYrqQpqcBYtnpR+JgkadZVZoaEZ/eKu9mclFaVwhRpLNSzA== + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.4.4.tgz#7556cf03f318bd2719fe4c922d2d808be5571e16" + integrity sha512-oMh5DUO1V63nZcu/ZVLQFqiihBGo4OpxJxR1otF50GMeCLiRx5nUdtokd+u9SuVJrvvuIh9OosRFPP4pIPnwmw== dependencies: - "@babel/helper-call-delegate" "^7.1.0" + "@babel/helper-call-delegate" "^7.4.4" "@babel/helper-get-function-arity" "^7.0.0" "@babel/helper-plugin-utils" "^7.0.0" @@ -553,11 +522,11 @@ "@babel/plugin-syntax-jsx" "^7.2.0" "@babel/plugin-transform-regenerator@^7.3.4": - version "7.4.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.4.0.tgz#0780e27ee458cc3fdbad18294d703e972ae1f6d1" - integrity sha512-SZ+CgL4F0wm4npojPU6swo/cK4FcbLgxLd4cWpHaNXY/NJ2dpahODCqBbAwb2rDmVszVb3SSjnk9/vik3AYdBw== + version "7.4.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.4.5.tgz#629dc82512c55cee01341fb27bdfcb210354680f" + integrity sha512-gBKRh5qAaCWntnd09S8QC7r3auLCqq5DI6O0DlfoyDjslSBVqBibrMdsqO+Uhmx3+BlOmE/Kw1HFxmGbv0N9dA== dependencies: - regenerator-transform "^0.13.4" + regenerator-transform "^0.14.0" "@babel/plugin-transform-shorthand-properties@^7.2.0": version "7.2.0" @@ -582,9 +551,9 @@ "@babel/helper-regex" "^7.0.0" "@babel/plugin-transform-template-literals@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.2.0.tgz#d87ed01b8eaac7a92473f608c97c089de2ba1e5b" - integrity sha512-FkPix00J9A/XWXv4VoKJBMeSkyY9x/TqIh76wzcdfl57RJJcf8CehQ08uwfhCDNtRQYtHQKBTwKZDEyjE13Lwg== + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.4.4.tgz#9d28fea7bbce637fb7612a0750989d8321d4bcb0" + integrity sha512-mQrEC4TWkhLN0z8ygIvEL9ZEToPhG5K7KDW3pzGqOfIGZ28Jb0POUkeWcoz8HnHvhFy6dwAT1j8OzqN8s804+g== dependencies: "@babel/helper-annotate-as-pure" "^7.0.0" "@babel/helper-plugin-utils" "^7.0.0" @@ -597,13 +566,13 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-unicode-regex@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.2.0.tgz#4eb8db16f972f8abb5062c161b8b115546ade08b" - integrity sha512-m48Y0lMhrbXEJnVUaYly29jRXbQ3ksxPrS1Tg8t+MHqzXhtBYAvI51euOBaoAlZLPHsieY9XPVMf80a5x0cPcA== + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.4.4.tgz#ab4634bb4f14d36728bf5978322b35587787970f" + integrity sha512-il+/XdNw01i93+M9J9u4T7/e/Ue/vWfNZE4IRUQjplu2Mqb/AFTDimkw2tdEdSH50wuQXZAbXSql0UphQke+vA== dependencies: "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-regex" "^7.0.0" - regexpu-core "^4.1.3" + "@babel/helper-regex" "^7.4.4" + regexpu-core "^4.5.4" "@babel/preset-env@^7.0.0 <7.4.0": version "7.3.4" @@ -661,7 +630,7 @@ dependencies: regenerator-runtime "^0.12.0" -"@babel/template@^7.0.0", "@babel/template@^7.0.0 <7.4.0", "@babel/template@^7.1.0", "@babel/template@^7.1.2", "@babel/template@^7.2.2": +"@babel/template@^7.0.0 <7.4.0": version "7.2.2" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.2.2.tgz#005b3fdf0ed96e88041330379e0da9a708eb2907" integrity sha512-zRL0IMM02AUDwghf5LMSSDEz7sBCO2YnNmpg3uWTZj/v1rcG2BmQUvaGU8GhU8BvfMh1k2KIAYZ7Ji9KXPUg7g== @@ -670,20 +639,14 @@ "@babel/parser" "^7.2.2" "@babel/types" "^7.2.2" -"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.1.5", "@babel/traverse@^7.2.3": - version "7.2.3" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.2.3.tgz#7ff50cefa9c7c0bd2d81231fdac122f3957748d8" - integrity sha512-Z31oUD/fJvEWVR0lNZtfgvVt512ForCTNKYcJBGbPb1QZfve4WGH8Wsy7+Mev33/45fhP/hwQtvgusNdcCMgSw== +"@babel/template@^7.1.0", "@babel/template@^7.2.2", "@babel/template@^7.4.0", "@babel/template@^7.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.4.4.tgz#f4b88d1225689a08f5bc3a17483545be9e4ed237" + integrity sha512-CiGzLN9KgAvgZsnivND7rkA+AeJ9JB0ciPOD4U59GKbQP2iQl+olF1l76kJOupqidozfZ32ghwBEJDhnk9MEcw== dependencies: "@babel/code-frame" "^7.0.0" - "@babel/generator" "^7.2.2" - "@babel/helper-function-name" "^7.1.0" - "@babel/helper-split-export-declaration" "^7.0.0" - "@babel/parser" "^7.2.3" - "@babel/types" "^7.2.2" - debug "^4.1.0" - globals "^11.1.0" - lodash "^4.17.10" + "@babel/parser" "^7.4.4" + "@babel/types" "^7.4.4" "@babel/traverse@^7.0.0 <7.4.0": version "7.3.4" @@ -700,28 +663,28 @@ globals "^11.1.0" lodash "^4.17.11" -"@babel/traverse@^7.3.4", "@babel/traverse@^7.4.0": - version "7.4.0" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.4.0.tgz#14006967dd1d2b3494cdd650c686db9daf0ddada" - integrity sha512-/DtIHKfyg2bBKnIN+BItaIlEg5pjAnzHOIQe5w+rHAw/rg9g0V7T4rqPX8BJPfW11kt3koyjAnTNwCzb28Y1PA== +"@babel/traverse@^7.1.0", "@babel/traverse@^7.3.4", "@babel/traverse@^7.4.3", "@babel/traverse@^7.4.4": + version "7.4.5" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.4.5.tgz#4e92d1728fd2f1897dafdd321efbff92156c3216" + integrity sha512-Vc+qjynwkjRmIFGxy0KYoPj4FdVDxLej89kMHFsWScq999uX+pwcX4v9mWRjW0KcAYTPAuVQl2LKP1wEVLsp+A== dependencies: "@babel/code-frame" "^7.0.0" - "@babel/generator" "^7.4.0" + "@babel/generator" "^7.4.4" "@babel/helper-function-name" "^7.1.0" - "@babel/helper-split-export-declaration" "^7.4.0" - "@babel/parser" "^7.4.0" - "@babel/types" "^7.4.0" + "@babel/helper-split-export-declaration" "^7.4.4" + "@babel/parser" "^7.4.5" + "@babel/types" "^7.4.4" debug "^4.1.0" globals "^11.1.0" lodash "^4.17.11" -"@babel/types@^7.0.0", "@babel/types@^7.2.0", "@babel/types@^7.2.2": - version "7.2.2" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.2.2.tgz#44e10fc24e33af524488b716cdaee5360ea8ed1e" - integrity sha512-fKCuD6UFUMkR541eDWL+2ih/xFZBXPOg/7EQFeTluMDebfqR4jrpaCjLhkWlQS4hT6nRa2PMEgXKbRB5/H2fpg== +"@babel/types@^7.0.0", "@babel/types@^7.2.0", "@babel/types@^7.2.2", "@babel/types@^7.3.0", "@babel/types@^7.3.4", "@babel/types@^7.4.0", "@babel/types@^7.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.4.4.tgz#8db9e9a629bb7c29370009b4b779ed93fe57d5f0" + integrity sha512-dOllgYdnEFOebhkKCjzSVFqw/PmmB8pH6RGOWkY4GsboQNd47b1fBThBSwlHAq9alF9vc1M3+6oqR47R50L0tQ== dependencies: esutils "^2.0.2" - lodash "^4.17.10" + lodash "^4.17.11" to-fast-properties "^2.0.0" "@babel/types@^7.0.0 <7.4.0": @@ -733,62 +696,124 @@ lodash "^4.17.11" to-fast-properties "^2.0.0" -"@babel/types@^7.3.0", "@babel/types@^7.3.4", "@babel/types@^7.4.0": - version "7.4.0" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.4.0.tgz#670724f77d24cce6cc7d8cf64599d511d164894c" - integrity sha512-aPvkXyU2SPOnztlgo8n9cEiXW755mgyvueUPcpStqdzoSPm0fjO0vQBjLkt3JKJW7ufikfcnMTTPsN1xaTsBPA== +"@evocateur/libnpmaccess@^3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@evocateur/libnpmaccess/-/libnpmaccess-3.1.0.tgz#e546ee4e4bedca54ed9303948ec54c985cec33e4" + integrity sha512-bfrqZ0v+Il5TJBsgF2oyepeJg34K2pBItapzP+UT1QMIGpUh/Zc1pQql4jrafamZTqP3ZvdJxaElat8B5K3ICA== dependencies: - esutils "^2.0.2" - lodash "^4.17.11" - to-fast-properties "^2.0.0" + "@evocateur/npm-registry-fetch" "^3.9.1" + aproba "^2.0.0" + figgy-pudding "^3.5.1" + get-stream "^4.0.0" + npm-package-arg "^6.1.0" -"@iarna/toml@^2.2.0": - version "2.2.1" - resolved "https://registry.yarnpkg.com/@iarna/toml/-/toml-2.2.1.tgz#82d0993d8882bb05e0645fbb4731d9e939e895b3" - integrity sha512-I2EjI9TbEFJNLziNPFfpo64PNanOaK17iL2kTW/jGlGOa4bvHw4VEied83kOEB7NJjXf1KfvmsQ2aEjy3xjiGg== +"@evocateur/libnpmpublish@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@evocateur/libnpmpublish/-/libnpmpublish-1.2.0.tgz#3e0d79fdc0a75f212adabb7c7e341b017effeac2" + integrity sha512-sezhX9FSnPIyrBBvxVocVJVO1uIWPczf6rOmUZSntCWfQMraO8pWTFlDJbroFqPbEqFFHf3eyw8NQ0Eb7OLd1g== + dependencies: + "@evocateur/npm-registry-fetch" "^3.9.1" + aproba "^2.0.0" + figgy-pudding "^3.5.1" + get-stream "^4.0.0" + lodash.clonedeep "^4.5.0" + normalize-package-data "^2.4.0" + npm-package-arg "^6.1.0" + semver "^5.5.1" + ssri "^6.0.1" -"@lerna/add@3.13.3": - version "3.13.3" - resolved "https://registry.yarnpkg.com/@lerna/add/-/add-3.13.3.tgz#f4c1674839780e458f0426d4f7b6d0a77b9a2ae9" - integrity sha512-T3/Lsbo9ZFq+vL3ssaHxA8oKikZAPTJTGFe4CRuQgWCDd/M61+51jeWsngdaHpwzSSRDRjxg8fJTG10y10pnfA== +"@evocateur/npm-registry-fetch@^3.9.1": + version "3.9.1" + resolved "https://registry.yarnpkg.com/@evocateur/npm-registry-fetch/-/npm-registry-fetch-3.9.1.tgz#75b3917320e559f6c91e26af17e62b085ec457a2" + integrity sha512-6v1bHbcAypQ+te/1RGSNL4JkK6mcMtcZrUusqo5iKRtYSAig9UJXlOaCcBR+eLywt2DQMNpEwAj24jwWDX5G/w== dependencies: - "@lerna/bootstrap" "3.13.3" - "@lerna/command" "3.13.3" - "@lerna/filter-options" "3.13.3" + JSONStream "^1.3.4" + bluebird "^3.5.1" + figgy-pudding "^3.4.1" + lru-cache "^4.1.3" + make-fetch-happen "^4.0.1" + npm-package-arg "^6.1.0" + safe-buffer "^5.1.2" + +"@evocateur/pacote@^9.6.0": + version "9.6.0" + resolved "https://registry.yarnpkg.com/@evocateur/pacote/-/pacote-9.6.0.tgz#3f0d08fb81c572289a2dfa981e7f97b6dd83cef2" + integrity sha512-nKx8EPxXhzqNfePbqC6603z7Kkf6GBS2q+SNGtBS/bCgS5Q+p3OVR6MXKOkpvC3WHse98W2WLu8QaV9axtfxyw== + dependencies: + "@evocateur/npm-registry-fetch" "^3.9.1" + bluebird "^3.5.3" + cacache "^11.3.2" + figgy-pudding "^3.5.1" + get-stream "^4.1.0" + glob "^7.1.3" + lru-cache "^5.1.1" + make-fetch-happen "^4.0.1" + minimatch "^3.0.4" + minipass "^2.3.5" + mississippi "^3.0.0" + mkdirp "^0.5.1" + normalize-package-data "^2.4.0" + npm-package-arg "^6.1.0" + npm-packlist "^1.1.12" + npm-pick-manifest "^2.2.3" + osenv "^0.1.5" + promise-inflight "^1.0.1" + promise-retry "^1.1.1" + protoduck "^5.0.1" + rimraf "^2.6.2" + safe-buffer "^5.1.2" + semver "^5.6.0" + ssri "^6.0.1" + tar "^4.4.8" + unique-filename "^1.1.1" + which "^1.3.1" + +"@iarna/toml@^2.2.0": + version "2.2.3" + resolved "https://registry.yarnpkg.com/@iarna/toml/-/toml-2.2.3.tgz#f060bf6eaafae4d56a7dac618980838b0696e2ab" + integrity sha512-FmuxfCuolpLl0AnQ2NHSzoUKWEJDFl63qXjzdoWBVyFCXzMGm1spBzk7LeHNoVCiWCF7mRVms9e6jEV9+MoPbg== + +"@lerna/add@3.15.0": + version "3.15.0" + resolved "https://registry.yarnpkg.com/@lerna/add/-/add-3.15.0.tgz#10be562f43cde59b60f299083d54ac39520ec60a" + integrity sha512-+KrG4GFy/6FISZ+DwWf5Fj5YB4ESa4VTnSn/ujf3VEda6dxngHPN629j+TcPbsdOxUYVah+HuZbC/B8NnkrKpQ== + dependencies: + "@evocateur/pacote" "^9.6.0" + "@lerna/bootstrap" "3.15.0" + "@lerna/command" "3.15.0" + "@lerna/filter-options" "3.14.2" "@lerna/npm-conf" "3.13.0" "@lerna/validation-error" "3.13.0" dedent "^0.7.0" npm-package-arg "^6.1.0" p-map "^1.2.0" - pacote "^9.5.0" semver "^5.5.0" -"@lerna/batch-packages@3.13.0": - version "3.13.0" - resolved "https://registry.yarnpkg.com/@lerna/batch-packages/-/batch-packages-3.13.0.tgz#697fde5be28822af9d9dca2f750250b90a89a000" - integrity sha512-TgLBTZ7ZlqilGnzJ3xh1KdAHcySfHytgNRTdG9YomfriTU6kVfp1HrXxKJYVGs7ClPUNt2CTFEOkw0tMBronjw== +"@lerna/batch-packages@3.14.0": + version "3.14.0" + resolved "https://registry.yarnpkg.com/@lerna/batch-packages/-/batch-packages-3.14.0.tgz#0208663bab3ddbf57956b370aaec4c9ebee6c800" + integrity sha512-RlBkQVNTqk1qvn6PFWiWNiskllUHh6tXbTVm43mZRNd+vhAyvrQC8RWJxH0ECVvnFAt9rSNGRIVbEJ31WnNQLg== dependencies: - "@lerna/package-graph" "3.13.0" - "@lerna/validation-error" "3.13.0" + "@lerna/package-graph" "3.14.0" npmlog "^4.1.2" -"@lerna/bootstrap@3.13.3": - version "3.13.3" - resolved "https://registry.yarnpkg.com/@lerna/bootstrap/-/bootstrap-3.13.3.tgz#a0e5e466de5c100b49d558d39139204fc4db5c95" - integrity sha512-2XzijnLHRZOVQh8pwS7+5GR3cG4uh+EiLrWOishCq2TVzkqgjaS3GGBoef7KMCXfWHoLqAZRr/jEdLqfETLVqg== - dependencies: - "@lerna/batch-packages" "3.13.0" - "@lerna/command" "3.13.3" - "@lerna/filter-options" "3.13.3" - "@lerna/has-npm-version" "3.13.3" - "@lerna/npm-install" "3.13.3" - "@lerna/package-graph" "3.13.0" +"@lerna/bootstrap@3.15.0": + version "3.15.0" + resolved "https://registry.yarnpkg.com/@lerna/bootstrap/-/bootstrap-3.15.0.tgz#f53e0bbbbfb8367e609a06378409bfc673ff2930" + integrity sha512-4AxsPKKbgj2Ju03qDddQTpOHvpqnwd0yaiEU/aCcWv/4tDTe79NqUne2Z3+P2WZY0Zzb8+nUKcskwYBMTeq+Mw== + dependencies: + "@lerna/batch-packages" "3.14.0" + "@lerna/command" "3.15.0" + "@lerna/filter-options" "3.14.2" + "@lerna/has-npm-version" "3.14.2" + "@lerna/npm-install" "3.14.2" + "@lerna/package-graph" "3.14.0" "@lerna/pulse-till-done" "3.13.0" - "@lerna/rimraf-dir" "3.13.3" - "@lerna/run-lifecycle" "3.13.0" + "@lerna/rimraf-dir" "3.14.2" + "@lerna/run-lifecycle" "3.14.0" "@lerna/run-parallel-batches" "3.13.0" - "@lerna/symlink-binary" "3.13.0" - "@lerna/symlink-dependencies" "3.13.0" + "@lerna/symlink-binary" "3.14.2" + "@lerna/symlink-dependencies" "3.14.2" "@lerna/validation-error" "3.13.0" dedent "^0.7.0" get-port "^3.2.0" @@ -802,44 +827,45 @@ read-package-tree "^5.1.6" semver "^5.5.0" -"@lerna/changed@3.13.3": - version "3.13.3" - resolved "https://registry.yarnpkg.com/@lerna/changed/-/changed-3.13.3.tgz#f2a2e982f4317157345f7abb3f6b12cc69394657" - integrity sha512-REMZ/1UvYrizUhN7ktlbfMUa0vhMf1ogAe97WQC4I8r3s973Orfhs3aselo1GwudUwM4tMHBH8A9vnll9or3iA== +"@lerna/changed@3.15.0": + version "3.15.0" + resolved "https://registry.yarnpkg.com/@lerna/changed/-/changed-3.15.0.tgz#20db9d992d697e4288c260aa38b989dcb93f4b40" + integrity sha512-Hns1ssI9T9xOTGVc7PT2jUaqzsSkxV3hV/Y7iFO0uKTk+fduyTwGTHU9A/ybQ/xi/9iaJbvaXyjxKiGoEnzmhg== dependencies: - "@lerna/collect-updates" "3.13.3" - "@lerna/command" "3.13.3" - "@lerna/listable" "3.13.0" + "@lerna/collect-updates" "3.14.2" + "@lerna/command" "3.15.0" + "@lerna/listable" "3.14.0" "@lerna/output" "3.13.0" - "@lerna/version" "3.13.3" + "@lerna/version" "3.15.0" -"@lerna/check-working-tree@3.13.3": - version "3.13.3" - resolved "https://registry.yarnpkg.com/@lerna/check-working-tree/-/check-working-tree-3.13.3.tgz#836a3ffd4413a29aca92ccca4a115e4f97109992" - integrity sha512-LoGZvTkne+V1WpVdCTU0XNzFKsQa2AiAFKksGRT0v8NQj6VAPp0jfVYDayTqwaWt2Ne0OGKOFE79Y5LStOuhaQ== +"@lerna/check-working-tree@3.14.2": + version "3.14.2" + resolved "https://registry.yarnpkg.com/@lerna/check-working-tree/-/check-working-tree-3.14.2.tgz#5ce007722180a69643a8456766ed8a91fc7e9ae1" + integrity sha512-7safqxM/MYoAoxZxulUDtIJIbnBIgo0PB/FHytueG+9VaX7GMnDte2Bt1EKa0dz2sAyQdmQ3Q8ZXpf/6JDjaeg== dependencies: - "@lerna/describe-ref" "3.13.3" + "@lerna/collect-uncommitted" "3.14.2" + "@lerna/describe-ref" "3.14.2" "@lerna/validation-error" "3.13.0" -"@lerna/child-process@3.13.3": - version "3.13.3" - resolved "https://registry.yarnpkg.com/@lerna/child-process/-/child-process-3.13.3.tgz#6c084ee5cca9fc9e04d6bf4fc3f743ed26ff190c" - integrity sha512-3/e2uCLnbU+bydDnDwyadpOmuzazS01EcnOleAnuj9235CU2U97DH6OyoG1EW/fU59x11J+HjIqovh5vBaMQjQ== +"@lerna/child-process@3.14.2": + version "3.14.2" + resolved "https://registry.yarnpkg.com/@lerna/child-process/-/child-process-3.14.2.tgz#950240cba83f7dfe25247cfa6c9cebf30b7d94f6" + integrity sha512-xnq+W5yQb6RkwI0p16ZQnrn6HkloH/MWTw4lGE1nKsBLAUbmSU5oTE93W1nrG0X3IMF/xWc9UYvNdUGMWvZZ4w== dependencies: chalk "^2.3.1" execa "^1.0.0" strong-log-transformer "^2.0.0" -"@lerna/clean@3.13.3": - version "3.13.3" - resolved "https://registry.yarnpkg.com/@lerna/clean/-/clean-3.13.3.tgz#5673a1238e0712d31711e7e4e8cb9641891daaea" - integrity sha512-xmNauF1PpmDaKdtA2yuRc23Tru4q7UMO6yB1a/TTwxYPYYsAWG/CBK65bV26J7x4RlZtEv06ztYGMa9zh34UXA== +"@lerna/clean@3.15.0": + version "3.15.0" + resolved "https://registry.yarnpkg.com/@lerna/clean/-/clean-3.15.0.tgz#a94da50908a80ba443a0a682706aca79ac2ecf27" + integrity sha512-D1BN7BnJk6YjrSR7E7RiCmWiFVWDo3L+OSe6zDq6rNNYexPBtSi2JOCeF/Dibi3jd2luVu0zkVpUtuEEdPiD+A== dependencies: - "@lerna/command" "3.13.3" - "@lerna/filter-options" "3.13.3" + "@lerna/command" "3.15.0" + "@lerna/filter-options" "3.14.2" "@lerna/prompt" "3.13.0" "@lerna/pulse-till-done" "3.13.0" - "@lerna/rimraf-dir" "3.13.3" + "@lerna/rimraf-dir" "3.14.2" p-map "^1.2.0" p-map-series "^1.0.0" p-waterfall "^1.0.0" @@ -854,25 +880,35 @@ npmlog "^4.1.2" yargs "^12.0.1" -"@lerna/collect-updates@3.13.3": - version "3.13.3" - resolved "https://registry.yarnpkg.com/@lerna/collect-updates/-/collect-updates-3.13.3.tgz#616648da59f0aff4a8e60257795cc46ca6921edd" - integrity sha512-sTpALOAxli/ZS+Mjq6fbmjU9YXqFJ2E4FrE1Ijl4wPC5stXEosg2u0Z1uPY+zVKdM+mOIhLxPVdx83rUgRS+Cg== +"@lerna/collect-uncommitted@3.14.2": + version "3.14.2" + resolved "https://registry.yarnpkg.com/@lerna/collect-uncommitted/-/collect-uncommitted-3.14.2.tgz#b5ed00d800bea26bb0d18404432b051eee8d030e" + integrity sha512-4EkQu4jIOdNL2BMzy/N0ydHB8+Z6syu6xiiKXOoFl0WoWU9H1jEJCX4TH7CmVxXL1+jcs8FIS2pfQz4oew99Eg== + dependencies: + "@lerna/child-process" "3.14.2" + chalk "^2.3.1" + figgy-pudding "^3.5.1" + npmlog "^4.1.2" + +"@lerna/collect-updates@3.14.2": + version "3.14.2" + resolved "https://registry.yarnpkg.com/@lerna/collect-updates/-/collect-updates-3.14.2.tgz#396201f6568ec5916bf2c11e7a29b0931fcd3e5b" + integrity sha512-+zSQ2ZovH8Uc0do5dR+sk8VvRJc6Xl+ZnJJGESIl17KSpEw/lVjcOyt6f3BP+WHn+iSOjMWcGvUVA601FIEdZw== dependencies: - "@lerna/child-process" "3.13.3" - "@lerna/describe-ref" "3.13.3" + "@lerna/child-process" "3.14.2" + "@lerna/describe-ref" "3.14.2" minimatch "^3.0.4" npmlog "^4.1.2" slash "^1.0.0" -"@lerna/command@3.13.3": - version "3.13.3" - resolved "https://registry.yarnpkg.com/@lerna/command/-/command-3.13.3.tgz#5b20b3f507224573551039e0460bc36c39f7e9d1" - integrity sha512-WHFIQCubJV0T8gSLRNr6exZUxTswrh+iAtJCb86SE0Sa+auMPklE8af7w2Yck5GJfewmxSjke3yrjNxQrstx7w== +"@lerna/command@3.15.0": + version "3.15.0" + resolved "https://registry.yarnpkg.com/@lerna/command/-/command-3.15.0.tgz#e1dc1319054f1cf0b135aa0c5730f3335641a0ca" + integrity sha512-dZqr4rKFN+veuXakIQ1DcGUpzBgcWKaYFNN4O6/skOdVQaEfGefzo1sZET+q7k/BkypxkhXHXpv5UqqSuL/EHQ== dependencies: - "@lerna/child-process" "3.13.3" - "@lerna/package-graph" "3.13.0" - "@lerna/project" "3.13.1" + "@lerna/child-process" "3.14.2" + "@lerna/package-graph" "3.14.0" + "@lerna/project" "3.15.0" "@lerna/validation-error" "3.13.0" "@lerna/write-log-file" "3.13.0" dedent "^0.7.0" @@ -881,10 +917,10 @@ lodash "^4.17.5" npmlog "^4.1.2" -"@lerna/conventional-commits@3.13.0": - version "3.13.0" - resolved "https://registry.yarnpkg.com/@lerna/conventional-commits/-/conventional-commits-3.13.0.tgz#877aa225ca34cca61c31ea02a5a6296af74e1144" - integrity sha512-BeAgcNXuocmLhPxnmKU2Vy8YkPd/Uo+vu2i/p3JGsUldzrPC8iF3IDxH7fuXpEFN2Nfogu7KHachd4tchtOppA== +"@lerna/conventional-commits@3.14.0": + version "3.14.0" + resolved "https://registry.yarnpkg.com/@lerna/conventional-commits/-/conventional-commits-3.14.0.tgz#24f643550dc29d4f1249cc26d0eb453d7a1c513d" + integrity sha512-hGZ2qQZ9uEGf2eeIiIpEodSs9Qkkf/2uYEtNT7QN1RYISPUh6/lKGBssc5dpbCF64aEuxmemWLdlDf1ogG6++w== dependencies: "@lerna/validation-error" "3.13.0" conventional-changelog-angular "^5.0.3" @@ -897,22 +933,23 @@ pify "^3.0.0" semver "^5.5.0" -"@lerna/create-symlink@3.13.0": - version "3.13.0" - resolved "https://registry.yarnpkg.com/@lerna/create-symlink/-/create-symlink-3.13.0.tgz#e01133082fe040779712c960683cb3a272b67809" - integrity sha512-PTvg3jAAJSAtLFoZDsuTMv1wTOC3XYIdtg54k7uxIHsP8Ztpt+vlilY/Cni0THAqEMHvfiToel76Xdta4TU21Q== +"@lerna/create-symlink@3.14.0": + version "3.14.0" + resolved "https://registry.yarnpkg.com/@lerna/create-symlink/-/create-symlink-3.14.0.tgz#f40ae06e8cebe70c694368ebf9a4af5ab380fbea" + integrity sha512-Kw51HYOOi6UfCKncqkgEU1k/SYueSBXgkNL91FR8HAZH7EPSRTEtp9mnJo568g0+Hog5C+3cOaWySwhHpRG29A== dependencies: cmd-shim "^2.0.2" fs-extra "^7.0.0" npmlog "^4.1.2" -"@lerna/create@3.13.3": - version "3.13.3" - resolved "https://registry.yarnpkg.com/@lerna/create/-/create-3.13.3.tgz#6ded142c54b7f3cea86413c3637b067027b7f55d" - integrity sha512-4M5xT1AyUMwt1gCDph4BfW3e6fZmt0KjTa3FoXkUotf/w/eqTsc2IQ+ULz2+gOFQmtuNbqIZEOK3J4P9ArJJ/A== +"@lerna/create@3.15.0": + version "3.15.0" + resolved "https://registry.yarnpkg.com/@lerna/create/-/create-3.15.0.tgz#27bfadcbdf71d34226aa82432293f5290f7ab1aa" + integrity sha512-doXGt0HTwTQl8GkC2tOrraA/5OWbz35hJqi7Dsl3Fl0bAxiv9XmF3LykHFJ+YTDHfGpdoJ8tKu66f/VKP16G0w== dependencies: - "@lerna/child-process" "3.13.3" - "@lerna/command" "3.13.3" + "@evocateur/pacote" "^9.6.0" + "@lerna/child-process" "3.14.2" + "@lerna/command" "3.15.0" "@lerna/npm-conf" "3.13.0" "@lerna/validation-error" "3.13.0" camelcase "^5.0.0" @@ -922,7 +959,6 @@ init-package-json "^1.10.3" npm-package-arg "^6.1.0" p-reduce "^1.0.0" - pacote "^9.5.0" pify "^3.0.0" semver "^5.5.0" slash "^1.0.0" @@ -930,42 +966,42 @@ validate-npm-package-name "^3.0.0" whatwg-url "^7.0.0" -"@lerna/describe-ref@3.13.3": - version "3.13.3" - resolved "https://registry.yarnpkg.com/@lerna/describe-ref/-/describe-ref-3.13.3.tgz#13318513613f6a407d37fc5dc025ec2cfb705606" - integrity sha512-5KcLTvjdS4gU5evW8ESbZ0BF44NM5HrP3dQNtWnOUSKJRgsES8Gj0lq9AlB2+YglZfjEftFT03uOYOxnKto4Uw== +"@lerna/describe-ref@3.14.2": + version "3.14.2" + resolved "https://registry.yarnpkg.com/@lerna/describe-ref/-/describe-ref-3.14.2.tgz#edc3c973f5ca9728d23358c4f4d3b55a21f65be5" + integrity sha512-qa5pzDRK2oBQXNjyRmRnN7E8a78NMYfQjjlRFB0KNHMsT6mCiL9+8kIS39sSE2NqT8p7xVNo2r2KAS8R/m3CoQ== dependencies: - "@lerna/child-process" "3.13.3" + "@lerna/child-process" "3.14.2" npmlog "^4.1.2" -"@lerna/diff@3.13.3": - version "3.13.3" - resolved "https://registry.yarnpkg.com/@lerna/diff/-/diff-3.13.3.tgz#883cb3a83a956dbfc2c17bc9a156468a5d3fae17" - integrity sha512-/DRS2keYbnKaAC+5AkDyZRGkP/kT7v1GlUS0JGZeiRDPQ1H6PzhX09EgE5X6nj0Ytrm0sUasDeN++CDVvgaI+A== +"@lerna/diff@3.15.0": + version "3.15.0" + resolved "https://registry.yarnpkg.com/@lerna/diff/-/diff-3.15.0.tgz#573d6f58f6809d16752dcfab74c5e286b6678371" + integrity sha512-N1Pr0M554Bt+DlVoD+DXWGh92gcq6G9icn8sH5GSqfwi0XCpPNJ2i1BNEZpUQ6ulLWOMa1YHR4PypPxecRGBjA== dependencies: - "@lerna/child-process" "3.13.3" - "@lerna/command" "3.13.3" + "@lerna/child-process" "3.14.2" + "@lerna/command" "3.15.0" "@lerna/validation-error" "3.13.0" npmlog "^4.1.2" -"@lerna/exec@3.13.3": - version "3.13.3" - resolved "https://registry.yarnpkg.com/@lerna/exec/-/exec-3.13.3.tgz#5d2eda3f6e584f2f15b115e8a4b5bc960ba5de85" - integrity sha512-c0bD4XqM96CTPV8+lvkxzE7mkxiFyv/WNM4H01YvvbFAJzk+S4Y7cBtRkIYFTfkFZW3FLo8pEgtG1ONtIdM+tg== +"@lerna/exec@3.15.0": + version "3.15.0" + resolved "https://registry.yarnpkg.com/@lerna/exec/-/exec-3.15.0.tgz#b31510f47255367eb0d3e4a4f7b6ef8f7e41b985" + integrity sha512-YuXPd64TNG9wbb3lRvyMARQbdlbMZ1bJZ+GCm0enivnIWUyg0qtBDcfPY2dWpIgOif04zx+K/gmOX4lCaGM4UQ== dependencies: - "@lerna/batch-packages" "3.13.0" - "@lerna/child-process" "3.13.3" - "@lerna/command" "3.13.3" - "@lerna/filter-options" "3.13.3" - "@lerna/run-parallel-batches" "3.13.0" + "@lerna/child-process" "3.14.2" + "@lerna/command" "3.15.0" + "@lerna/filter-options" "3.14.2" + "@lerna/run-topologically" "3.14.0" "@lerna/validation-error" "3.13.0" + p-map "^1.2.0" -"@lerna/filter-options@3.13.3": - version "3.13.3" - resolved "https://registry.yarnpkg.com/@lerna/filter-options/-/filter-options-3.13.3.tgz#aa42a4ab78837b8a6c4278ba871d27e92d77c54f" - integrity sha512-DbtQX4eRgrBz1wCFWRP99JBD7ODykYme9ykEK79+RrKph40znhJQRlLg4idogj6IsUEzwo1OHjihCzSfnVo6Cg== +"@lerna/filter-options@3.14.2": + version "3.14.2" + resolved "https://registry.yarnpkg.com/@lerna/filter-options/-/filter-options-3.14.2.tgz#7ba91cb54ff3fd9f4650ad8d7c40bc1075e44c2d" + integrity sha512-Ct8oYvRttbYB9JalngHhirb8o9ZVyLm5a9MpXNevXoHiu6j0vNhI19BQCwNnrL6wZvEHJnzPuUl/jO23tWxemg== dependencies: - "@lerna/collect-updates" "3.13.3" + "@lerna/collect-updates" "3.14.2" "@lerna/filter-packages" "3.13.0" dedent "^0.7.0" @@ -994,37 +1030,46 @@ ssri "^6.0.1" tar "^4.4.8" -"@lerna/github-client@3.13.3": - version "3.13.3" - resolved "https://registry.yarnpkg.com/@lerna/github-client/-/github-client-3.13.3.tgz#bcf9b4ff40bdd104cb40cd257322f052b41bb9ce" - integrity sha512-fcJkjab4kX0zcLLSa/DCUNvU3v8wmy2c1lhdIbL7s7gABmDcV0QZq93LhnEee3VkC9UpnJ6GKG4EkD7eIifBnA== +"@lerna/github-client@3.14.2": + version "3.14.2" + resolved "https://registry.yarnpkg.com/@lerna/github-client/-/github-client-3.14.2.tgz#a743792b51cd9bdfb785186e429568827a6372eb" + integrity sha512-+2Xh7t4qVmXiXE2utPnh5T7YwSltG74JP7c+EiooRY5+3zjh9MpPOcTKxVY3xKclzpsyXMohk2KpTF4tzA5rrg== dependencies: - "@lerna/child-process" "3.13.3" + "@lerna/child-process" "3.14.2" "@octokit/plugin-enterprise-rest" "^2.1.1" "@octokit/rest" "^16.16.0" git-url-parse "^11.1.2" npmlog "^4.1.2" +"@lerna/gitlab-client@3.15.0": + version "3.15.0" + resolved "https://registry.yarnpkg.com/@lerna/gitlab-client/-/gitlab-client-3.15.0.tgz#91f4ec8c697b5ac57f7f25bd50fe659d24aa96a6" + integrity sha512-OsBvRSejHXUBMgwWQqNoioB8sgzL/Pf1pOUhHKtkiMl6aAWjklaaq5HPMvTIsZPfS6DJ9L5OK2GGZuooP/5c8Q== + dependencies: + node-fetch "^2.5.0" + npmlog "^4.1.2" + whatwg-url "^7.0.0" + "@lerna/global-options@3.13.0": version "3.13.0" resolved "https://registry.yarnpkg.com/@lerna/global-options/-/global-options-3.13.0.tgz#217662290db06ad9cf2c49d8e3100ee28eaebae1" integrity sha512-SlZvh1gVRRzYLVluz9fryY1nJpZ0FHDGB66U9tFfvnnxmueckRQxLopn3tXj3NU1kc3QANT2I5BsQkOqZ4TEFQ== -"@lerna/has-npm-version@3.13.3": - version "3.13.3" - resolved "https://registry.yarnpkg.com/@lerna/has-npm-version/-/has-npm-version-3.13.3.tgz#167e3f602a2fb58f84f93cf5df39705ca6432a2d" - integrity sha512-mQzoghRw4dBg0R9FFfHrj0TH0glvXyzdEZmYZ8Isvx5BSuEEwpsryoywuZSdppcvLu8o7NAdU5Tac8cJ/mT52w== +"@lerna/has-npm-version@3.14.2": + version "3.14.2" + resolved "https://registry.yarnpkg.com/@lerna/has-npm-version/-/has-npm-version-3.14.2.tgz#ac17f7c68e92114b8332b95ae6cffec9c0d67a7b" + integrity sha512-cG+z5bB8JPd5f+nT2eLN2LmKg06O11AxlnUxgw2W7cLyc7cnsmMSp/rxt2JBMwW2r4Yn+CLLJIRwJZ2Es8jFSw== dependencies: - "@lerna/child-process" "3.13.3" + "@lerna/child-process" "3.14.2" semver "^5.5.0" -"@lerna/import@3.13.3": - version "3.13.3" - resolved "https://registry.yarnpkg.com/@lerna/import/-/import-3.13.3.tgz#1dc84f2c5644ba874be9552395a3b158688b263c" - integrity sha512-gDjLAFVavG/CMvj9leBfiwd7vrXqtdFXPIz1oXmghBMnje7nCTbodbNWFe4VDDWx7reDaZIN+6PxTSvrPcF//A== +"@lerna/import@3.15.0": + version "3.15.0" + resolved "https://registry.yarnpkg.com/@lerna/import/-/import-3.15.0.tgz#47f2da52059a96bb08a4c09e18d985258fce9ce1" + integrity sha512-4GKQgeTXBTwMbZNkYyPdQIVA41HIISD7D6XRNrDaG0falUfvoPsknijQPCBmGqeh66u1Fcn2+4lkL3OCTj2FMg== dependencies: - "@lerna/child-process" "3.13.3" - "@lerna/command" "3.13.3" + "@lerna/child-process" "3.14.2" + "@lerna/command" "3.15.0" "@lerna/prompt" "3.13.0" "@lerna/pulse-till-done" "3.13.0" "@lerna/validation-error" "3.13.0" @@ -1032,44 +1077,44 @@ fs-extra "^7.0.0" p-map-series "^1.0.0" -"@lerna/init@3.13.3": - version "3.13.3" - resolved "https://registry.yarnpkg.com/@lerna/init/-/init-3.13.3.tgz#ebd522fee9b9d7d3b2dacb0261eaddb4826851ff" - integrity sha512-bK/mp0sF6jT0N+c+xrbMCqN4xRoiZCXQzlYsyACxPK99KH/mpHv7hViZlTYUGlYcymtew6ZC770miv5A9wF9hA== +"@lerna/init@3.15.0": + version "3.15.0" + resolved "https://registry.yarnpkg.com/@lerna/init/-/init-3.15.0.tgz#bda36de44c365972f87cbd287fe85b6fb7bb1070" + integrity sha512-VOqH6kFbFtfUbXxhSqXKY6bjnVp9nLuLRI6x9tVHOANX2LmSlXm17OUGBnNt+eM4uJLuiUsAR8nTlpCiz//lPQ== dependencies: - "@lerna/child-process" "3.13.3" - "@lerna/command" "3.13.3" + "@lerna/child-process" "3.14.2" + "@lerna/command" "3.15.0" fs-extra "^7.0.0" p-map "^1.2.0" write-json-file "^2.3.0" -"@lerna/link@3.13.3": - version "3.13.3" - resolved "https://registry.yarnpkg.com/@lerna/link/-/link-3.13.3.tgz#11124d4a0c8d0b79752fbda3babedfd62dd57847" - integrity sha512-IHhtdhA0KlIdevCsq6WHkI2rF3lHWHziJs2mlrEWAKniVrFczbELON1KJAgdJS1k3kAP/WeWVqmIYZ2hJDxMvg== +"@lerna/link@3.15.0": + version "3.15.0" + resolved "https://registry.yarnpkg.com/@lerna/link/-/link-3.15.0.tgz#718b4116a8eacb3fc73414ae8d97f8fdaf8125da" + integrity sha512-yKHuifADINobvDOLljBGkVGpVwy6J3mg5p9lQXBdOLXBoIKC8o/UKBR9JvZMFvT/Iy6zn6FPy1v5lz9iU1Ib0Q== dependencies: - "@lerna/command" "3.13.3" - "@lerna/package-graph" "3.13.0" - "@lerna/symlink-dependencies" "3.13.0" + "@lerna/command" "3.15.0" + "@lerna/package-graph" "3.14.0" + "@lerna/symlink-dependencies" "3.14.2" p-map "^1.2.0" slash "^1.0.0" -"@lerna/list@3.13.3": - version "3.13.3" - resolved "https://registry.yarnpkg.com/@lerna/list/-/list-3.13.3.tgz#fa93864d43cadeb4cd540a4e78a52886c57dbe74" - integrity sha512-rLRDsBCkydMq2FL6WY1J/elvnXIjxxRtb72lfKHdvDEqVdquT5Qgt9ci42hwjmcocFwWcFJgF6BZozj5pbc13A== +"@lerna/list@3.15.0": + version "3.15.0" + resolved "https://registry.yarnpkg.com/@lerna/list/-/list-3.15.0.tgz#4e401c1ad990bb12bd38298cb61d21136420ff68" + integrity sha512-8SvxnlfAnbEzQDf2NL0IxWyUuqWTykF9cHt5/f5TOzgESClpaOkDtqwh/UlE8nVTzWMnxnQUPQi3UTKyJD3i3g== dependencies: - "@lerna/command" "3.13.3" - "@lerna/filter-options" "3.13.3" - "@lerna/listable" "3.13.0" + "@lerna/command" "3.15.0" + "@lerna/filter-options" "3.14.2" + "@lerna/listable" "3.14.0" "@lerna/output" "3.13.0" -"@lerna/listable@3.13.0": - version "3.13.0" - resolved "https://registry.yarnpkg.com/@lerna/listable/-/listable-3.13.0.tgz#babc18442c590b549cf0966d20d75fea066598d4" - integrity sha512-liYJ/WBUYP4N4MnSVZuLUgfa/jy3BZ02/1Om7xUY09xGVSuNVNEeB8uZUMSC+nHqFHIsMPZ8QK9HnmZb1E/eTA== +"@lerna/listable@3.14.0": + version "3.14.0" + resolved "https://registry.yarnpkg.com/@lerna/listable/-/listable-3.14.0.tgz#08f4c78e0466568e8e8a57d4ad09537f2bb7bbb9" + integrity sha512-ZK44Mo8xf/N97eQZ236SPSq0ek6+gk4HqHIx05foEMZVV1iIDH4a/nblLsJNjGQVsIdMYFPaqNJ0z+ZQfiJazQ== dependencies: - "@lerna/batch-packages" "3.13.0" + "@lerna/query-graph" "3.14.0" chalk "^2.3.1" columnify "^1.5.4" @@ -1091,22 +1136,23 @@ config-chain "^1.1.11" pify "^3.0.0" -"@lerna/npm-dist-tag@3.13.0": - version "3.13.0" - resolved "https://registry.yarnpkg.com/@lerna/npm-dist-tag/-/npm-dist-tag-3.13.0.tgz#49ecbe0e82cbe4ad4a8ea6de112982bf6c4e6cd4" - integrity sha512-mcuhw34JhSRFrbPn0vedbvgBTvveG52bR2lVE3M3tfE8gmR/cKS/EJFO4AUhfRKGCTFn9rjaSEzlFGYV87pemQ== +"@lerna/npm-dist-tag@3.15.0": + version "3.15.0" + resolved "https://registry.yarnpkg.com/@lerna/npm-dist-tag/-/npm-dist-tag-3.15.0.tgz#262dd1e67a4cf82ae78fadfe02622ebce4add078" + integrity sha512-lnbdwc4Ebs7/EI9fTIgbH3dxXnP+SuCcGhG7P5ZjOqo67SY09sRZGcygEzabpvIwXvKpBF8vCd4xxzjnF2u+PA== dependencies: + "@evocateur/npm-registry-fetch" "^3.9.1" + "@lerna/otplease" "3.14.0" figgy-pudding "^3.5.1" npm-package-arg "^6.1.0" - npm-registry-fetch "^3.9.0" npmlog "^4.1.2" -"@lerna/npm-install@3.13.3": - version "3.13.3" - resolved "https://registry.yarnpkg.com/@lerna/npm-install/-/npm-install-3.13.3.tgz#9b09852732e51c16d2e060ff2fd8bfbbb49cf7ba" - integrity sha512-7Jig9MLpwAfcsdQ5UeanAjndChUjiTjTp50zJ+UZz4CbIBIDhoBehvNMTCL2G6pOEC7sGEg6sAqJINAqred6Tg== +"@lerna/npm-install@3.14.2": + version "3.14.2" + resolved "https://registry.yarnpkg.com/@lerna/npm-install/-/npm-install-3.14.2.tgz#fd22ff432f8b7cbe05bedfd36b0506482f1a4732" + integrity sha512-JYJJRtLETrGpcQZa8Rj16vbye399RqnaXmJlZuZ2twjJ2DYVYtwkfsGEOdvdaKw5KVOEpWcAxBA9OMmKQtCLQw== dependencies: - "@lerna/child-process" "3.13.3" + "@lerna/child-process" "3.14.2" "@lerna/get-npm-exec-opts" "3.13.0" fs-extra "^7.0.0" npm-package-arg "^6.1.0" @@ -1114,29 +1160,38 @@ signal-exit "^3.0.2" write-pkg "^3.1.0" -"@lerna/npm-publish@3.13.2": - version "3.13.2" - resolved "https://registry.yarnpkg.com/@lerna/npm-publish/-/npm-publish-3.13.2.tgz#ad713ca6f91a852687d7d0e1bda7f9c66df21768" - integrity sha512-HMucPyEYZfom5tRJL4GsKBRi47yvSS2ynMXYxL3kO0ie+j9J7cb0Ir8NmaAMEd3uJWJVFCPuQarehyfTDZsSxg== +"@lerna/npm-publish@3.15.0": + version "3.15.0" + resolved "https://registry.yarnpkg.com/@lerna/npm-publish/-/npm-publish-3.15.0.tgz#89126d74ec97186475767b852954a5f55b732a71" + integrity sha512-G7rcNcSGjG0La8eHPXDvCvoNXbwNnP6XJ+GPh3CH5xiR/nikfLOa+Bfm4ytdjVWWxnKfCT4qyMTCoV1rROlqQQ== dependencies: - "@lerna/run-lifecycle" "3.13.0" + "@evocateur/libnpmpublish" "^1.2.0" + "@lerna/otplease" "3.14.0" + "@lerna/run-lifecycle" "3.14.0" figgy-pudding "^3.5.1" fs-extra "^7.0.0" - libnpmpublish "^1.1.1" npm-package-arg "^6.1.0" npmlog "^4.1.2" pify "^3.0.0" read-package-json "^2.0.13" -"@lerna/npm-run-script@3.13.3": - version "3.13.3" - resolved "https://registry.yarnpkg.com/@lerna/npm-run-script/-/npm-run-script-3.13.3.tgz#9bb6389ed70cd506905d6b05b6eab336b4266caf" - integrity sha512-qR4o9BFt5hI8Od5/DqLalOJydnKpiQFEeN0h9xZi7MwzuX1Ukwh3X22vqsX4YRbipIelSFtrDzleNVUm5jj0ow== +"@lerna/npm-run-script@3.14.2": + version "3.14.2" + resolved "https://registry.yarnpkg.com/@lerna/npm-run-script/-/npm-run-script-3.14.2.tgz#8c518ea9d241a641273e77aad6f6fddc16779c3f" + integrity sha512-LbVFv+nvAoRTYLMrJlJ8RiakHXrLslL7Jp/m1R18vYrB8LYWA3ey+nz5Tel2OELzmjUiemAKZsD9h6i+Re5egg== dependencies: - "@lerna/child-process" "3.13.3" + "@lerna/child-process" "3.14.2" "@lerna/get-npm-exec-opts" "3.13.0" npmlog "^4.1.2" +"@lerna/otplease@3.14.0": + version "3.14.0" + resolved "https://registry.yarnpkg.com/@lerna/otplease/-/otplease-3.14.0.tgz#b539fd3e7a08452fc0db3b10010ca3cf0e4a73e7" + integrity sha512-rYAWzaYZ81bwnrmTkYWGgcc13bl/6DlG7pjWQWNGAJNLzO5zzj0xmXN5sMFJnNvDpSiS/ZS1sIuPvb4xnwLUkg== + dependencies: + "@lerna/prompt" "3.13.0" + figgy-pudding "^3.5.1" + "@lerna/output@3.13.0": version "3.13.0" resolved "https://registry.yarnpkg.com/@lerna/output/-/output-3.13.0.tgz#3ded7cc908b27a9872228a630d950aedae7a4989" @@ -1144,44 +1199,53 @@ dependencies: npmlog "^4.1.2" -"@lerna/pack-directory@3.13.1": - version "3.13.1" - resolved "https://registry.yarnpkg.com/@lerna/pack-directory/-/pack-directory-3.13.1.tgz#5ad4d0945f86a648f565e24d53c1e01bb3a912d1" - integrity sha512-kXnyqrkQbCIZOf1054N88+8h0ItC7tUN5v9ca/aWpx298gsURpxUx/1TIKqijL5TOnHMyIkj0YJmnH/PyBVLKA== +"@lerna/pack-directory@3.14.2": + version "3.14.2" + resolved "https://registry.yarnpkg.com/@lerna/pack-directory/-/pack-directory-3.14.2.tgz#577b8ebf867c9b636a2e4659a27552ee24d83b9d" + integrity sha512-b3LnJEmIml3sDj94TQT8R+kVyrDlmE7Su0WwcBYZDySXPMSZ38WA2/2Xjy/EWhXlFxp/nUJKyUG78nDrZ/00Uw== dependencies: "@lerna/get-packed" "3.13.0" - "@lerna/package" "3.13.0" - "@lerna/run-lifecycle" "3.13.0" + "@lerna/package" "3.14.2" + "@lerna/run-lifecycle" "3.14.0" figgy-pudding "^3.5.1" npm-packlist "^1.4.1" npmlog "^4.1.2" tar "^4.4.8" temp-write "^3.4.0" -"@lerna/package-graph@3.13.0": - version "3.13.0" - resolved "https://registry.yarnpkg.com/@lerna/package-graph/-/package-graph-3.13.0.tgz#607062f8d2ce22b15f8d4a0623f384736e67f760" - integrity sha512-3mRF1zuqFE1HEFmMMAIggXy+f+9cvHhW/jzaPEVyrPNLKsyfJQtpTNzeI04nfRvbAh+Gd2aNksvaW/w3xGJnnw== +"@lerna/package-graph@3.14.0": + version "3.14.0" + resolved "https://registry.yarnpkg.com/@lerna/package-graph/-/package-graph-3.14.0.tgz#4ccdf446dccedfbbeb4efff3eb720cb6fcb109fc" + integrity sha512-dNpA/64STD5YXhaSlg4gT6Z474WPJVCHoX1ibsVIFu0fVgH609Y69bsdmbvTRdI7r6Dcu4ZfGxdR636RTrH+Eg== dependencies: + "@lerna/prerelease-id-from-version" "3.14.0" "@lerna/validation-error" "3.13.0" npm-package-arg "^6.1.0" + npmlog "^4.1.2" semver "^5.5.0" -"@lerna/package@3.13.0": - version "3.13.0" - resolved "https://registry.yarnpkg.com/@lerna/package/-/package-3.13.0.tgz#4baeebc49a57fc9b31062cc59f5ee38384429fc8" - integrity sha512-kSKO0RJQy093BufCQnkhf1jB4kZnBvL7kK5Ewolhk5gwejN+Jofjd8DGRVUDUJfQ0CkW1o6GbUeZvs8w8VIZDg== +"@lerna/package@3.14.2": + version "3.14.2" + resolved "https://registry.yarnpkg.com/@lerna/package/-/package-3.14.2.tgz#f893cb42e26c869df272dafbe1dd5a3473b0bd4d" + integrity sha512-YR/+CzYdufJYfsUlrfuhTjA35iSZpXK7mVOZmeR9iRWhSaqesm4kq2zfxm9vCpZV2oAQQZOwi4eo5h0rQBtdiw== dependencies: load-json-file "^4.0.0" npm-package-arg "^6.1.0" write-pkg "^3.1.0" -"@lerna/project@3.13.1": - version "3.13.1" - resolved "https://registry.yarnpkg.com/@lerna/project/-/project-3.13.1.tgz#bce890f60187bd950bcf36c04b5260642e295e79" - integrity sha512-/GoCrpsCCTyb9sizk1+pMBrIYchtb+F1uCOn3cjn9yenyG/MfYEnlfrbV5k/UDud0Ei75YBLbmwCbigHkAKazQ== +"@lerna/prerelease-id-from-version@3.14.0": + version "3.14.0" + resolved "https://registry.yarnpkg.com/@lerna/prerelease-id-from-version/-/prerelease-id-from-version-3.14.0.tgz#d5da9c26ac4a0d0ecde09018f06e41ca4dd444c2" + integrity sha512-Ap3Z/dNhqQuSrKmK+JmzYvQYI2vowxHvUVxZJiDVilW8dyNnxkCsYFmkuZytk5sxVz4VeGLNPS2RSsU5eeSS+Q== dependencies: - "@lerna/package" "3.13.0" + semver "^5.5.0" + +"@lerna/project@3.15.0": + version "3.15.0" + resolved "https://registry.yarnpkg.com/@lerna/project/-/project-3.15.0.tgz#733b0993a849dcf5b68fcd0ec11d8f7de38a6999" + integrity sha512-eNGUWiMbQ9kh9kGkomtMnsLypS0rfLqxKgZP2+VnNVtIXjnLv4paeTm+1lkL+naNJUwhnpMk2NSLEeoxT/20QA== + dependencies: + "@lerna/package" "3.14.2" "@lerna/validation-error" "3.13.0" cosmiconfig "^5.1.0" dedent "^0.7.0" @@ -1202,40 +1266,39 @@ inquirer "^6.2.0" npmlog "^4.1.2" -"@lerna/publish@3.13.3": - version "3.13.3" - resolved "https://registry.yarnpkg.com/@lerna/publish/-/publish-3.13.3.tgz#9adde543064e85851f02c0c2dbd40d52d1c519a4" - integrity sha512-Ni3pZKueIfgJJoL0OXfbAuWhGlJrDNwGx3CYWp2dbNqJmKD6uBZmsDtmeARKDp92oUK60W0drXCMydkIFFHMDQ== - dependencies: - "@lerna/batch-packages" "3.13.0" - "@lerna/check-working-tree" "3.13.3" - "@lerna/child-process" "3.13.3" - "@lerna/collect-updates" "3.13.3" - "@lerna/command" "3.13.3" - "@lerna/describe-ref" "3.13.3" +"@lerna/publish@3.15.0": + version "3.15.0" + resolved "https://registry.yarnpkg.com/@lerna/publish/-/publish-3.15.0.tgz#54f93f8f0820d2d419d0b65df1eb55d8277090c9" + integrity sha512-6tRRBJ8olLSXfrUsR4f7vSfx0cT1oPi6/v06yI3afDSsUX6eQ3ooZh7gMY4RWmd+nM/IJHTUzhlKF6WhTvo+9g== + dependencies: + "@evocateur/libnpmaccess" "^3.1.0" + "@evocateur/npm-registry-fetch" "^3.9.1" + "@evocateur/pacote" "^9.6.0" + "@lerna/check-working-tree" "3.14.2" + "@lerna/child-process" "3.14.2" + "@lerna/collect-updates" "3.14.2" + "@lerna/command" "3.15.0" + "@lerna/describe-ref" "3.14.2" "@lerna/log-packed" "3.13.0" "@lerna/npm-conf" "3.13.0" - "@lerna/npm-dist-tag" "3.13.0" - "@lerna/npm-publish" "3.13.2" + "@lerna/npm-dist-tag" "3.15.0" + "@lerna/npm-publish" "3.15.0" "@lerna/output" "3.13.0" - "@lerna/pack-directory" "3.13.1" + "@lerna/pack-directory" "3.14.2" + "@lerna/prerelease-id-from-version" "3.14.0" "@lerna/prompt" "3.13.0" "@lerna/pulse-till-done" "3.13.0" - "@lerna/run-lifecycle" "3.13.0" - "@lerna/run-parallel-batches" "3.13.0" + "@lerna/run-lifecycle" "3.14.0" + "@lerna/run-topologically" "3.14.0" "@lerna/validation-error" "3.13.0" - "@lerna/version" "3.13.3" + "@lerna/version" "3.15.0" figgy-pudding "^3.5.1" fs-extra "^7.0.0" - libnpmaccess "^3.0.1" npm-package-arg "^6.1.0" - npm-registry-fetch "^3.9.0" npmlog "^4.1.2" p-finally "^1.0.0" p-map "^1.2.0" p-pipe "^1.2.0" - p-reduce "^1.0.0" - pacote "^9.5.0" semver "^5.5.0" "@lerna/pulse-till-done@3.13.0": @@ -1245,6 +1308,14 @@ dependencies: npmlog "^4.1.2" +"@lerna/query-graph@3.14.0": + version "3.14.0" + resolved "https://registry.yarnpkg.com/@lerna/query-graph/-/query-graph-3.14.0.tgz#2abb36f445bd924d0f85ac7aec1445e9ef1e2c6c" + integrity sha512-6YTh3vDMW2hUxHdKeRvx4bosc9lZClKaN+DzC1XKTkwDbWrsjmEzLcemKL6QnyyeuryN2f/eto7P9iSe3z3pQQ== + dependencies: + "@lerna/package-graph" "3.14.0" + figgy-pudding "^3.5.1" + "@lerna/resolve-symlink@3.13.0": version "3.13.0" resolved "https://registry.yarnpkg.com/@lerna/resolve-symlink/-/resolve-symlink-3.13.0.tgz#3e6809ef53b63fe914814bfa071cd68012e22fbb" @@ -1254,24 +1325,24 @@ npmlog "^4.1.2" read-cmd-shim "^1.0.1" -"@lerna/rimraf-dir@3.13.3": - version "3.13.3" - resolved "https://registry.yarnpkg.com/@lerna/rimraf-dir/-/rimraf-dir-3.13.3.tgz#3a8e71317fde853893ef0262bc9bba6a180b7227" - integrity sha512-d0T1Hxwu3gpYVv73ytSL+/Oy8JitsmvOYUR5ouRSABsmqS7ZZCh5t6FgVDDGVXeuhbw82+vuny1Og6Q0k4ilqw== +"@lerna/rimraf-dir@3.14.2": + version "3.14.2" + resolved "https://registry.yarnpkg.com/@lerna/rimraf-dir/-/rimraf-dir-3.14.2.tgz#103a49882abd85d42285d05cc76869b89f21ffd2" + integrity sha512-eFNkZsy44Bu9v1Hrj5Zk6omzg8O9h/7W6QYK1TTUHeyrjTEwytaNQlqF0lrTLmEvq55sviV42NC/8P3M2cvq8Q== dependencies: - "@lerna/child-process" "3.13.3" + "@lerna/child-process" "3.14.2" npmlog "^4.1.2" path-exists "^3.0.0" rimraf "^2.6.2" -"@lerna/run-lifecycle@3.13.0": - version "3.13.0" - resolved "https://registry.yarnpkg.com/@lerna/run-lifecycle/-/run-lifecycle-3.13.0.tgz#d8835ee83425edee40f687a55f81b502354d3261" - integrity sha512-oyiaL1biZdjpmjh6X/5C4w07wNFyiwXSSHH5GQB4Ay4BPwgq9oNhCcxRoi0UVZlZ1YwzSW8sTwLgj8emkIo3Yg== +"@lerna/run-lifecycle@3.14.0": + version "3.14.0" + resolved "https://registry.yarnpkg.com/@lerna/run-lifecycle/-/run-lifecycle-3.14.0.tgz#0499eca0e7f393faf4e24e6c8737302a9059c22b" + integrity sha512-GUM3L9MzGRSW0WQ8wbLW1+SYStU1OFjW0GBzShhBnFrO4nGRrU7VchsLpcLu0hk2uCzyhsrDKzifEdOdUyMoEQ== dependencies: "@lerna/npm-conf" "3.13.0" figgy-pudding "^3.5.1" - npm-lifecycle "^2.1.0" + npm-lifecycle "^2.1.1" npmlog "^4.1.2" "@lerna/run-parallel-batches@3.13.0": @@ -1282,39 +1353,47 @@ p-map "^1.2.0" p-map-series "^1.0.0" -"@lerna/run@3.13.3": - version "3.13.3" - resolved "https://registry.yarnpkg.com/@lerna/run/-/run-3.13.3.tgz#0781c82d225ef6e85e28d3e763f7fc090a376a21" - integrity sha512-ygnLIfIYS6YY1JHWOM4CsdZiY8kTYPsDFOLAwASlRnlAXF9HiMT08GFXLmMHIblZJ8yJhsM2+QgraCB0WdxzOQ== +"@lerna/run-topologically@3.14.0": + version "3.14.0" + resolved "https://registry.yarnpkg.com/@lerna/run-topologically/-/run-topologically-3.14.0.tgz#2a560cb657f0ef1565c680b6001b4b01b872dc07" + integrity sha512-y+KBpC1YExFzGynovt9MY4O/bc3RrJaKeuXieiPfKGKxrdtmZe/r33oj/xePTXZq65jnw3SaU3H8S5CrrdkwDg== + dependencies: + "@lerna/query-graph" "3.14.0" + figgy-pudding "^3.5.1" + p-queue "^4.0.0" + +"@lerna/run@3.15.0": + version "3.15.0" + resolved "https://registry.yarnpkg.com/@lerna/run/-/run-3.15.0.tgz#465028b5b561a050bd760924e4a0749de3f43172" + integrity sha512-KQBkzZYoEKmzILKjbjsm1KKVWFBXwAdwzqJWj/lfxxd3V5LRF8STASk8aiw8bSpB0bUL9TU/pbXakRxiNzjDwQ== dependencies: - "@lerna/batch-packages" "3.13.0" - "@lerna/command" "3.13.3" - "@lerna/filter-options" "3.13.3" - "@lerna/npm-run-script" "3.13.3" + "@lerna/command" "3.15.0" + "@lerna/filter-options" "3.14.2" + "@lerna/npm-run-script" "3.14.2" "@lerna/output" "3.13.0" - "@lerna/run-parallel-batches" "3.13.0" + "@lerna/run-topologically" "3.14.0" "@lerna/timer" "3.13.0" "@lerna/validation-error" "3.13.0" p-map "^1.2.0" -"@lerna/symlink-binary@3.13.0": - version "3.13.0" - resolved "https://registry.yarnpkg.com/@lerna/symlink-binary/-/symlink-binary-3.13.0.tgz#36a9415d468afcb8105750296902f6f000a9680d" - integrity sha512-obc4Y6jxywkdaCe+DB0uTxYqP0IQ8mFWvN+k/YMbwH4G2h7M7lCBWgPy8e7xw/50+1II9tT2sxgx+jMus1sTJg== +"@lerna/symlink-binary@3.14.2": + version "3.14.2" + resolved "https://registry.yarnpkg.com/@lerna/symlink-binary/-/symlink-binary-3.14.2.tgz#a832fdc6c4b1e5aaf9e6ac9c7e6c322746965eb0" + integrity sha512-tqMwuWi6z1da0AFFbleWyu3H9fqayiV50rjj4anFTfayel9jSjlA1xPG+56sGIP6zUUNuUSc9kLh7oRRmlauoA== dependencies: - "@lerna/create-symlink" "3.13.0" - "@lerna/package" "3.13.0" + "@lerna/create-symlink" "3.14.0" + "@lerna/package" "3.14.2" fs-extra "^7.0.0" p-map "^1.2.0" -"@lerna/symlink-dependencies@3.13.0": - version "3.13.0" - resolved "https://registry.yarnpkg.com/@lerna/symlink-dependencies/-/symlink-dependencies-3.13.0.tgz#76c23ecabda7824db98a0561364f122b457509cf" - integrity sha512-7CyN5WYEPkbPLbqHBIQg/YiimBzb5cIGQB0E9IkLs3+racq2vmUNQZn38LOaazQacAA83seB+zWSxlI6H+eXSg== +"@lerna/symlink-dependencies@3.14.2": + version "3.14.2" + resolved "https://registry.yarnpkg.com/@lerna/symlink-dependencies/-/symlink-dependencies-3.14.2.tgz#e6b2a9544ff26addc1f4324734595e2f71dfc795" + integrity sha512-Ox7WKXnHZ7IwWlejcCq3n0Hd/yMLv8AwIryhvWxM/RauAge+ML4wg578SsdCyKob8ecgm/R0ytHiU06j81iL1w== dependencies: - "@lerna/create-symlink" "3.13.0" + "@lerna/create-symlink" "3.14.0" "@lerna/resolve-symlink" "3.13.0" - "@lerna/symlink-binary" "3.13.0" + "@lerna/symlink-binary" "3.14.2" fs-extra "^7.0.0" p-finally "^1.0.0" p-map "^1.2.0" @@ -1332,21 +1411,23 @@ dependencies: npmlog "^4.1.2" -"@lerna/version@3.13.3": - version "3.13.3" - resolved "https://registry.yarnpkg.com/@lerna/version/-/version-3.13.3.tgz#3ec1b5aee2fd42353b95452c38cc0b284b93a1f0" - integrity sha512-o/yQGAwDHmyu17wTj4Kat1/uDhjYFMeG+H0Y0HC4zJ4a/T6rEiXx7jJrnucPTmTQTDcUBoH/It5LrPYGOPsExA== - dependencies: - "@lerna/batch-packages" "3.13.0" - "@lerna/check-working-tree" "3.13.3" - "@lerna/child-process" "3.13.3" - "@lerna/collect-updates" "3.13.3" - "@lerna/command" "3.13.3" - "@lerna/conventional-commits" "3.13.0" - "@lerna/github-client" "3.13.3" +"@lerna/version@3.15.0": + version "3.15.0" + resolved "https://registry.yarnpkg.com/@lerna/version/-/version-3.15.0.tgz#3c65d223d94f211312995266abb07ee6606d5f73" + integrity sha512-vReYX1NMXZ9PwzTZm97wAl/k3bmRnRZhnQi3mq/m49xTnDavq7p4sbUdFpvu8cVZNKnYS02pNIVGHrQw+K8ZCw== + dependencies: + "@lerna/check-working-tree" "3.14.2" + "@lerna/child-process" "3.14.2" + "@lerna/collect-updates" "3.14.2" + "@lerna/command" "3.15.0" + "@lerna/conventional-commits" "3.14.0" + "@lerna/github-client" "3.14.2" + "@lerna/gitlab-client" "3.15.0" "@lerna/output" "3.13.0" + "@lerna/prerelease-id-from-version" "3.14.0" "@lerna/prompt" "3.13.0" - "@lerna/run-lifecycle" "3.13.0" + "@lerna/run-lifecycle" "3.14.0" + "@lerna/run-topologically" "3.14.0" "@lerna/validation-error" "3.13.0" chalk "^2.3.1" dedent "^0.7.0" @@ -1381,14 +1462,14 @@ resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b" integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw== -"@octokit/endpoint@^3.2.0": - version "3.2.3" - resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-3.2.3.tgz#bd9aea60cd94ce336656b57a5c9cb7f10be8f4f3" - integrity sha512-yUPCt4vMIOclox13CUxzuKiPJIFo46b/6GhUnUTw5QySczN1L0DtSxgmIZrZV4SAb9EyAqrceoyrWoYVnfF2AA== +"@octokit/endpoint@^5.1.0": + version "5.1.7" + resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-5.1.7.tgz#cfbd473a6adf5fea747520972e1af676406f7c26" + integrity sha512-MfsXHx9z9EPxLYSf7PYuzWvVZTotx+/QTFk7UMp4Fv83k3QrvmovEjP0pl141g+Uq/w9CcDuuXhsiq4X3oxVsA== dependencies: - deepmerge "3.2.0" - is-plain-object "^2.0.4" - universal-user-agent "^2.0.1" + deepmerge "3.2.1" + is-plain-object "^3.0.0" + universal-user-agent "^2.1.0" url-template "^2.0.8" "@octokit/plugin-enterprise-rest@^2.1.1": @@ -1396,28 +1477,38 @@ resolved "https://registry.yarnpkg.com/@octokit/plugin-enterprise-rest/-/plugin-enterprise-rest-2.2.2.tgz#c0e22067a043e19f96ff9c7832e2a3019f9be75c" integrity sha512-CTZr64jZYhGWNTDGlSJ2mvIlFsm9OEO3LqWn9I/gmoHI4jRBp4kpHoFYNemG4oA75zUAcmbuWblb7jjP877YZw== -"@octokit/request@2.4.2": - version "2.4.2" - resolved "https://registry.yarnpkg.com/@octokit/request/-/request-2.4.2.tgz#87c36e820dd1e43b1629f4f35c95b00cd456320b" - integrity sha512-lxVlYYvwGbKSHXfbPk5vxEA8w4zHOH1wobado4a9EfsyD3Cbhuhus1w0Ye9Ro0eMubGO8kNy5d+xNFisM3Tvaw== +"@octokit/request-error@^1.0.1", "@octokit/request-error@^1.0.2": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-1.0.4.tgz#15e1dc22123ba4a9a4391914d80ec1e5303a23be" + integrity sha512-L4JaJDXn8SGT+5G0uX79rZLv0MNJmfGa4vb4vy1NnpjSnWDLJRy6m90udGwvMmavwsStgbv2QNkPzzTCMmL+ig== dependencies: - "@octokit/endpoint" "^3.2.0" - deprecation "^1.0.1" - is-plain-object "^2.0.4" + deprecation "^2.0.0" + once "^1.4.0" + +"@octokit/request@^4.0.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@octokit/request/-/request-4.1.1.tgz#614262214f48417b4d3b14e047d09a9c8e2f7a09" + integrity sha512-LOyL0i3oxRo418EXRSJNk/3Q4I0/NKawTn6H/CQp+wnrG1UFLGu080gSsgnWobhPo5BpUNgSQ5BRk5FOOJhD1Q== + dependencies: + "@octokit/endpoint" "^5.1.0" + "@octokit/request-error" "^1.0.1" + deprecation "^2.0.0" + is-plain-object "^3.0.0" node-fetch "^2.3.0" once "^1.4.0" - universal-user-agent "^2.0.1" + universal-user-agent "^2.1.0" "@octokit/rest@^16.16.0": - version "16.23.1" - resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-16.23.1.tgz#cbc0bbd78f3990580a64be29309eb3f709d3c762" - integrity sha512-Kwjt6Ue6lgRcc6enQ2O6QLkDtK1yTDJgfjrfyGar5R+fsESVomOTl1D9iq9NNSQMPaDctcpUD8C/HudjYAeoWw== + version "16.28.1" + resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-16.28.1.tgz#a10c3d4fe61e994878d66a4c12b9923b18548236" + integrity sha512-9H/5F0f2bSVhk78ypu/A9dkK5GCH/aI8CxRJ0L8JU/XEYNIYozxqD6HVC7shsofrCfR61YORfjTE+GxfZ/wasQ== dependencies: - "@octokit/request" "2.4.2" + "@octokit/request" "^4.0.1" + "@octokit/request-error" "^1.0.2" atob-lite "^2.0.0" before-after-hook "^1.4.0" btoa-lite "^1.0.0" - deprecation "^1.0.1" + deprecation "^2.0.0" lodash.get "^4.4.2" lodash.set "^4.3.2" lodash.uniq "^4.5.0" @@ -1473,14 +1564,14 @@ integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== "@types/events@*": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@types/events/-/events-1.2.0.tgz#81a6731ce4df43619e5c8c945383b3e62a89ea86" - integrity sha512-KEIlhXnIutzKwRbQkGWb/I4HFqBuUykAdHgDED6xqwXJfONCjF5VoE0cXEiurh3XauygxzeDzgtXUqvLkxFzzA== + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7" + integrity sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g== "@types/fs-extra@^5.0.3": - version "5.0.4" - resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-5.0.4.tgz#b971134d162cc0497d221adde3dbb67502225599" - integrity sha512-DsknoBvD8s+RFfSGjmERJ7ZOP1HI0UZRA3FSI+Zakhrc/Gy26YQsLI+m5V5DHxroHRJqCDLKJp7Hixn8zyaF7g== + version "5.1.0" + resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-5.1.0.tgz#2a325ef97901504a3828718c390d34b8426a10a1" + integrity sha512-AInn5+UBFIK9FK5xc9yP5e3TQSPNNgjHByqYcj9g5elVBnDQcQL7PlO1CIRy2gWlbwK7UPYqi7vRvFA44dCmYQ== dependencies: "@types/node" "*" @@ -1494,9 +1585,11 @@ "@types/node" "*" "@types/handlebars@^4.0.38": - version "4.0.40" - resolved "https://registry.yarnpkg.com/@types/handlebars/-/handlebars-4.0.40.tgz#b714e13d296a75bff3f199316d1311933ca79ffd" - integrity sha512-sGWNtsjNrLOdKha2RV1UeF8+UbQnPSG7qbe5wwbni0mw4h2gHXyPFUMOC+xwGirIiiydM/HSqjDO4rk6NFB18w== + version "4.1.0" + resolved "https://registry.yarnpkg.com/@types/handlebars/-/handlebars-4.1.0.tgz#3fcce9bf88f85fe73dc932240ab3fb682c624850" + integrity sha512-gq9YweFKNNB1uFK71eRqsd4niVkXrxHugqWFQkeLRJvGjnxsLr16bYtcsG4tOFwmYi0Bax+wCkbf1reUfdl4kA== + dependencies: + handlebars "*" "@types/highlight.js@^9.12.3": version "9.12.3" @@ -1504,9 +1597,9 @@ integrity sha512-pGF/zvYOACZ/gLGWdQH8zSwteQS1epp68yRcVLJMgUck/MjEn/FBYmPub9pXT8C1e4a8YZfHo1CKyV8q1vKUnQ== "@types/lodash@^4.14.110": - version "4.14.119" - resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.119.tgz#be847e5f4bc3e35e46d041c394ead8b603ad8b39" - integrity sha512-Z3TNyBL8Vd/M9D9Ms2S3LmFq2sSMzahodD6rCS9V2N44HUMINb75jNkSuwAx7eo2ufqTdfOdtGQpNbieUjPQmw== + version "4.14.134" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.134.tgz#9032b440122db3a2a56200e91191996161dde5b9" + integrity sha512-2/O0khFUCFeDlbi7sZ7ZFRCcT812fAeOLm7Ev4KbwASkZ575TDrDcY7YyaoHdTOzKcNbfiwLYZqPmoC4wadrsw== "@types/marked@^0.4.0": version "0.4.2" @@ -1519,34 +1612,24 @@ integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== "@types/mocha@^5.2.6": - version "5.2.6" - resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-5.2.6.tgz#b8622d50557dd155e9f2f634b7d68fd38de5e94b" - integrity sha512-1axi39YdtBI7z957vdqXI4Ac25e7YihYQtJa+Clnxg1zTJEaIRbndt71O3sP4GAMgiAm0pY26/b9BrY4MR/PMw== + version "5.2.7" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-5.2.7.tgz#315d570ccb56c53452ff8638738df60726d5b6ea" + integrity sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ== -"@types/node@*", "@types/node@^10.11.7": - version "10.12.18" - resolved "https://registry.yarnpkg.com/@types/node/-/node-10.12.18.tgz#1d3ca764718915584fcd9f6344621b7672665c67" - integrity sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ== - -"@types/node@^11.13.5", "@types/node@^11.13.7": - version "11.13.7" - resolved "https://registry.yarnpkg.com/@types/node/-/node-11.13.7.tgz#85dbb71c510442d00c0631f99dae957ce44fd104" - integrity sha512-suFHr6hcA9mp8vFrZTgrmqW2ZU3mbWsryQtQlY/QvwTISCw7nw/j+bCQPPohqmskhmqa5wLNuMHTTsc+xf1MQg== +"@types/node@*", "@types/node@^12.0.8": + version "12.0.8" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.0.8.tgz#551466be11b2adc3f3d47156758f610bd9f6b1d8" + integrity sha512-b8bbUOTwzIY3V5vDTY1fIJ+ePKDUBqt2hC2woVGotdQQhG/2Sh62HOKHrT7ab+VerXAcPyAiTEipPu/FsreUtg== "@types/q@^1.5.1": - version "1.5.1" - resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.1.tgz#48fd98c1561fe718b61733daed46ff115b496e18" - integrity sha512-eqz8c/0kwNi/OEHQfvIuJVLTst3in0e7uTKeuY+WL/zfKn0xVujOTp42bS/vUUokhK5P2BppLd9JXMOMHcgbjA== - -"@types/semver@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@types/semver/-/semver-5.5.0.tgz#146c2a29ee7d3bae4bf2fcb274636e264c813c45" - integrity sha512-41qEJgBH/TWgo5NFSvBCJ1qkoi3Q6ONSF2avrHq1LVEZfYpdHmj0y9SuTK+u9ZhG1sYQKBL1AWXKyLWP4RaUoQ== + version "1.5.2" + resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8" + integrity sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw== "@types/shelljs@^0.8.0": - version "0.8.1" - resolved "https://registry.yarnpkg.com/@types/shelljs/-/shelljs-0.8.1.tgz#133e874b5fb816a2e1c8647839c82d76760b1191" - integrity sha512-1lQw+48BuVgp6c1+z8EMipp18IdnV2dLh6KQGwOm+kJy9nPjEkaqRKmwbDNEYf//EKBvKcwOC6V2cDrNxVoQeQ== + version "0.8.5" + resolved "https://registry.yarnpkg.com/@types/shelljs/-/shelljs-0.8.5.tgz#1e507b2f6d1f893269bd3e851ec24419ef9beeea" + integrity sha512-bZgjwIWu9gHCjirKJoOlLzGi5N0QgZ5t7EXEuoqyWCHTuSddURXo3FOBYDyRPNOWzZ6NbkLvZnVkn483Y/tvcQ== dependencies: "@types/glob" "*" "@types/node" "*" @@ -1736,9 +1819,9 @@ acorn-dynamic-import@^4.0.0: integrity sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw== acorn-globals@^4.1.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-4.3.0.tgz#e3b6f8da3c1552a95ae627571f7dd6923bb54103" - integrity sha512-hMtHj3s5RnuhvHPowpBYvJVj3rAar82JiDQHvGs1zO0l10ocX/xEdBShNHTJaboucJUsScghp74pH3s7EnHHQw== + version "4.3.2" + resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-4.3.2.tgz#4e2c2313a597fd589720395f6354b41cd5ec8006" + integrity sha512-BbzvZhVtZP+Bs1J1HcwrQe8ycfO0wStkSGxuul3He3GkHOIZ6eTqOkPuw9IP1X3+IkOo4wiJmwkobzXYz4wewQ== dependencies: acorn "^6.0.1" acorn-walk "^6.0.1" @@ -1758,7 +1841,14 @@ acorn@^6.0.1, acorn@^6.0.5, acorn@^6.1.1: resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.1.1.tgz#7d25ae05bb8ad1f9b699108e1094ecd7884adc1f" integrity sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA== -agent-base@4, agent-base@^4.1.0, agent-base@~4.2.0: +agent-base@4, agent-base@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee" + integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg== + dependencies: + es6-promisify "^5.0.0" + +agent-base@~4.2.1: version "4.2.1" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.1.tgz#d89e5999f797875674c07d87f260fc41e83e8ca9" integrity sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg== @@ -1778,14 +1868,14 @@ ajv-errors@^1.0.0: integrity sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ== ajv-keywords@^3.1.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.2.0.tgz#e86b819c602cf8821ad637413698f1dec021847a" - integrity sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo= + version "3.4.0" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.4.0.tgz#4b831e7b531415a7cc518cd404e73f6193c6349d" + integrity sha512-aUjdRFISbuFOl0EIZc+9e4FfZp0bDZgAdOOf30bJmw8VM9v84SHyVyxDfbWxpGYbdZD/9XoKxfHVNmxPkhwyGw== ajv@^6.1.0, ajv@^6.5.5: - version "6.6.2" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.6.2.tgz#caceccf474bf3fc3ce3b147443711a24063cc30d" - integrity sha512-FBHEW6Jf5TB9MGBgUUA9XHkTbjXYfAUjY43ACMfmdMRHniyoMHjHjzD50OK8LGDWQwp4rWEsIq5kEqq7rvIM1g== + version "6.10.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.0.tgz#90d0d54439da587cd7e843bfb7045f50bd22bdf1" + integrity sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg== dependencies: fast-deep-equal "^2.0.1" fast-json-stable-stringify "^2.0.0" @@ -1802,10 +1892,10 @@ ansi-colors@3.2.3: resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813" integrity sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw== -ansi-escapes@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.1.0.tgz#f73207bb81207d75fd6c83f125af26eea378ca30" - integrity sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw== +ansi-escapes@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" + integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== ansi-regex@^2.0.0: version "2.1.1" @@ -1817,11 +1907,6 @@ ansi-regex@^3.0.0: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= -ansi-regex@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.0.0.tgz#70de791edf021404c3fd615aa89118ae0432e5a9" - integrity sha512-iB5Dda8t/UqpPI/IjsejXu5jOGDrzn41wJyljwPH65VCIbk6+1BzFIMJGFwTNrYXT1CrD+B4l19U7awiQ8rk7w== - ansi-regex@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" @@ -1832,7 +1917,7 @@ ansi-styles@^2.2.1: resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= -ansi-styles@^3.2.1: +ansi-styles@^3.2.0, ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== @@ -1840,9 +1925,9 @@ ansi-styles@^3.2.1: color-convert "^1.9.0" ansi-to-html@^0.6.4: - version "0.6.9" - resolved "https://registry.yarnpkg.com/ansi-to-html/-/ansi-to-html-0.6.9.tgz#f4f2e2361792269cc62da85944f39759fc71b1e2" - integrity sha512-hwNdg2DNgCzsrvaNc+LDqSxJkpxf9oEt4R7KE0IeURXhEOlontEqNpXNiGeFBpSes8TZF+ZZ9sjB85QzjPsI6A== + version "0.6.11" + resolved "https://registry.yarnpkg.com/ansi-to-html/-/ansi-to-html-0.6.11.tgz#5093fc4962186c0e9343dec572a4f71abdc93439" + integrity sha512-88XZtrcwrfkyn6fGstHnkaF1kl7hGtNCYh4vSmItgEV+6JnQHryDBf7udF4f2RhTRQmYvJvPcTtqgaqrxzc9oA== dependencies: entities "^1.1.1" @@ -1975,10 +2060,11 @@ assert-plus@1.0.0, assert-plus@^1.0.0: integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= assert@^1.1.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/assert/-/assert-1.4.1.tgz#99912d591836b5a6f5b345c0f07eefc08fc65d91" - integrity sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE= + version "1.5.0" + resolved "https://registry.yarnpkg.com/assert/-/assert-1.5.0.tgz#55c109aaf6e0aefdb3dc4b71240c70bf574b18eb" + integrity sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA== dependencies: + object-assign "^4.1.1" util "0.10.3" assign-symbols@^1.0.0: @@ -1986,23 +2072,16 @@ assign-symbols@^1.0.0: resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= -async-each@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" - integrity sha1-GdOGodntxufByF04iu28xW0zYC0= +async-each@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" + integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== async-limiter@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" integrity sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg== -async@^2.5.0: - version "2.6.1" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.1.tgz#b245a23ca71930044ec53fa46aa00a3e87c6a610" - integrity sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ== - dependencies: - lodash "^4.17.10" - asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -2104,26 +2183,19 @@ big.js@^5.2.2: integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== binary-extensions@^1.0.0: - version "1.12.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.12.0.tgz#c2d780f53d45bba8317a8902d4ceeaf3a6385b14" - integrity sha512-DYWGk01lDcxeS/K9IHPGWfT8PsJmbXRtRd2Sx72Tnb8pcYZQFF1oSDb8hJtS1vhp212q1Rzi5dUf9+nq0o9UIg== + version "1.13.1" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" + integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== bindings@~1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.2.1.tgz#14ad6113812d2d37d72e67b4cacb4bb726505f11" integrity sha1-FK1hE4EtLTfXLme0ystLtyZQXxE= -block-stream@*: - version "0.0.9" - resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" - integrity sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo= - dependencies: - inherits "~2.0.0" - bluebird@^3.5.1, bluebird@^3.5.3: - version "3.5.3" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.3.tgz#7d01c6f9616c9a51ab0f8c549a79dfe6ec33efa7" - integrity sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw== + version "3.5.5" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.5.tgz#a8d0afd73251effbbd5fe384a77d73003c17a71f" + integrity sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w== bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0: version "4.11.8" @@ -2143,7 +2215,7 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -braces@^2.3.0, braces@^2.3.1: +braces@^2.3.1, braces@^2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== @@ -2159,6 +2231,13 @@ braces@^2.3.0, braces@^2.3.1: split-string "^3.0.2" to-regex "^3.0.1" +braces@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + brfs@^1.2.0: version "1.6.1" resolved "https://registry.yarnpkg.com/brfs/-/brfs-1.6.1.tgz#b78ce2336d818e25eea04a0947cba6d4fb8849c3" @@ -2244,13 +2323,13 @@ browserify-zlib@^0.2.0: pako "~1.0.5" browserslist@^4.0.0, browserslist@^4.1.0, browserslist@^4.3.4: - version "4.3.7" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.3.7.tgz#f1de479a6466ea47a0a26dcc725e7504817e624a" - integrity sha512-pWQv51Ynb0MNk9JGMCZ8VkM785/4MQNXiFYtPqI7EEP0TJO+/d/NqRVn1uiAN0DNbnlUSpL2sh16Kspasv3pUQ== + version "4.6.2" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.6.2.tgz#574c665950915c2ac73a4594b8537a9eba26203f" + integrity sha512-2neU/V0giQy9h3XMPwLhEY3+Ao0uHSwHvU8Q1Ea6AgLVL1sXbX3dzPrJ8NWe5Hi4PoTkCYXOtVR9rfRLI0J/8Q== dependencies: - caniuse-lite "^1.0.30000925" - electron-to-chromium "^1.3.96" - node-releases "^1.1.3" + caniuse-lite "^1.0.30000974" + electron-to-chromium "^1.3.150" + node-releases "^1.1.23" btoa-lite@^1.0.0: version "1.0.0" @@ -2281,7 +2360,7 @@ buffer@^4.3.0: ieee754 "^1.1.4" isarray "^1.0.0" -builtin-modules@^1.0.0, builtin-modules@^1.1.1: +builtin-modules@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" integrity sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8= @@ -2306,7 +2385,7 @@ byte-size@^4.0.3: resolved "https://registry.yarnpkg.com/byte-size/-/byte-size-4.0.4.tgz#29d381709f41aae0d89c631f1c81aec88cd40b23" integrity sha512-82RPeneC6nqCdSwCX2hZUz3JPOvN5at/nTEw/CMf05Smu3Hrpo9Psb7LjN+k+XndNArG1EY8L4+BM3aTM4BCvw== -cacache@^11.0.1, cacache@^11.0.2, cacache@^11.3.2: +cacache@^11.0.1, cacache@^11.3.2: version "11.3.2" resolved "https://registry.yarnpkg.com/cacache/-/cacache-11.3.2.tgz#2d81e308e3d258ca38125b676b98b2ac9ce69bfa" integrity sha512-E0zP4EPGDOaT2chM08Als91eYnf8Z+eH1awwwVsngUmgppfM5jjJ8l3z5vO5p5w/I3LsiXawb1sW0VY65pQABg== @@ -2403,9 +2482,9 @@ camelcase@^4.1.0: integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0= camelcase@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.0.0.tgz#03295527d58bd3cd4aa75363f35b2e8d97be2f42" - integrity sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA== + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== caniuse-api@^3.0.0: version "3.0.0" @@ -2417,10 +2496,10 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000925: - version "1.0.30000927" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000927.tgz#114a9de4ff1e01f5790fe578ecd93421c7524665" - integrity sha512-ogq4NbUWf1uG/j66k0AmiO3GjqJAlQyF8n4w8a954cbCyFKmYGvRtgz6qkq2fWuduTXHibX7GyYL5Pg58Aks2g== +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000974: + version "1.0.30000974" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000974.tgz#b7afe14ee004e97ce6dc73e3f878290a12928ad8" + integrity sha512-xc3rkNS/Zc3CmpMKuczWEdY2sZgx09BkAxfvkxlAEBTqcMHeL8QnPqhKse+5sRTi3nrw2pJwToD2WvKn1Uhvww== caseless@~0.12.0: version "0.12.0" @@ -2453,24 +2532,23 @@ chardet@^0.7.0: integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== chokidar@^2.0.2, chokidar@^2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.0.4.tgz#356ff4e2b0e8e43e322d18a372460bbcf3accd26" - integrity sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ== + version "2.1.6" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.6.tgz#b6cad653a929e244ce8a834244164d241fa954c5" + integrity sha512-V2jUo67OKkc6ySiRpJrjlpJKl9kDuG+Xb8VgsGzb+aEouhgS1D0weyPU4lEzdAcsCAvrih2J2BqyXqHWvVLw5g== dependencies: anymatch "^2.0.0" - async-each "^1.0.0" - braces "^2.3.0" + async-each "^1.0.1" + braces "^2.3.2" glob-parent "^3.1.0" - inherits "^2.0.1" + inherits "^2.0.3" is-binary-path "^1.0.0" is-glob "^4.0.0" - lodash.debounce "^4.0.8" - normalize-path "^2.1.1" + normalize-path "^3.0.0" path-is-absolute "^1.0.0" - readdirp "^2.0.0" - upath "^1.0.5" + readdirp "^2.2.1" + upath "^1.1.1" optionalDependencies: - fsevents "^1.2.2" + fsevents "^1.2.7" chownr@^1.1.1: version "1.1.1" @@ -2478,9 +2556,9 @@ chownr@^1.1.1: integrity sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g== chrome-trace-event@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.0.tgz#45a91bd2c20c9411f0963b5aaeb9a1b95e09cc48" - integrity sha512-xDbVgyfDTT2piup/h8dK/y4QZfJRSa73bw1WZ8b4XM1o7fsFubUVGYcE+1ANtOzJJELGpYoG2961z0Z6OAld9A== + version "1.0.2" + resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz#234090ee97c7d4ad1a2c4beae27505deffc608a4" + integrity sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ== dependencies: tslib "^1.9.0" @@ -2533,6 +2611,15 @@ cliui@^4.0.0: strip-ansi "^4.0.0" wrap-ansi "^2.0.0" +cliui@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" + integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== + dependencies: + string-width "^3.1.0" + strip-ansi "^5.2.0" + wrap-ansi "^5.1.0" + clone@^1.0.2: version "1.0.4" resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" @@ -2556,7 +2643,7 @@ cmd-shim@^2.0.2: graceful-fs "^4.1.2" mkdirp "~0.5.0" -coa@~2.0.1: +coa@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/coa/-/coa-2.0.2.tgz#43f6c21151b4ef2bf57187db0d73de229e3e7ec3" integrity sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA== @@ -2604,18 +2691,13 @@ color-string@^1.5.2: simple-swizzle "^0.2.2" color@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/color/-/color-3.1.0.tgz#d8e9fb096732875774c84bf922815df0308d0ffc" - integrity sha512-CwyopLkuRYO5ei2EpzpIh6LqJMt6Mt+jZhO5VI5f/wJLZriXQE32/SSqzmrh+QB+AZT81Cj8yv+7zwToW8ahZg== + version "3.1.2" + resolved "https://registry.yarnpkg.com/color/-/color-3.1.2.tgz#68148e7f85d41ad7649c5fa8c8106f098d229e10" + integrity sha512-vXTJhHebByxZn3lDvDJYw4lR5+uB3vuoHsuYA5AKuxRVn5wzzIfQKGLBmgdVRHKTJYeK5rvJcHnrd0Li49CFpg== dependencies: color-convert "^1.9.1" color-string "^1.5.2" -colors@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63" - integrity sha1-FopHAXVran9RoSzgyXv6KMCE7WM= - columnify@^1.5.4: version "1.5.4" resolved "https://registry.yarnpkg.com/columnify/-/columnify-1.5.4.tgz#4737ddf1c7b69a8a7c340570782e947eec8e78bb" @@ -2625,9 +2707,9 @@ columnify@^1.5.4: wcwidth "^1.0.0" combined-stream@^1.0.6, combined-stream@~1.0.6: - version "1.0.7" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.7.tgz#2d1d24317afb8abe95d6d2c0b07b57813539d828" - integrity sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w== + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== dependencies: delayed-stream "~1.0.0" @@ -2636,15 +2718,10 @@ command-exists@^1.2.6: resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.8.tgz#715acefdd1223b9c9b37110a149c6392c2852291" integrity sha512-PM54PkseWbiiD/mMsbvW351/u+dafwTJ0ye2qB60G1aGQP9j3xK2gmMDc+R34L3nDtx4qMCitXT75mkbkGJDLw== -commander@^2.11.0, commander@^2.12.1, commander@^2.19.0, commander@^2.9.0: - version "2.19.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a" - integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg== - -commander@~2.17.1: - version "2.17.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" - integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg== +commander@^2.11.0, commander@^2.12.1, commander@^2.19.0, commander@^2.9.0, commander@~2.20.0: + version "2.20.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422" + integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ== commondir@^1.0.1: version "1.0.1" @@ -2660,16 +2737,16 @@ compare-func@^1.3.1: dot-prop "^3.0.0" component-emitter@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" - integrity sha1-E3kY1teCg/ffemt8WmPhQOaUJeY= + version "1.3.0" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" + integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= -concat-stream@^1.5.0, concat-stream@^1.6.0, concat-stream@~1.6.0: +concat-stream@^1.5.0, concat-stream@~1.6.0: version "1.6.2" resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== @@ -2679,6 +2756,16 @@ concat-stream@^1.5.0, concat-stream@^1.6.0, concat-stream@~1.6.0: readable-stream "^2.2.2" typedarray "^0.0.6" +concat-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-2.0.0.tgz#414cf5af790a48c60ab9be4527d56d5e41133cb1" + integrity sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A== + dependencies: + buffer-from "^1.0.0" + inherits "^2.0.3" + readable-stream "^3.0.2" + typedarray "^0.0.6" + config-chain@^1.1.11, config-chain@^1.1.12: version "1.1.12" resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.12.tgz#0fde8d091200eb5e808caf25fe618c02f48e4efa" @@ -2713,12 +2800,12 @@ conventional-changelog-angular@^5.0.3: q "^1.5.1" conventional-changelog-core@^3.1.6: - version "3.1.6" - resolved "https://registry.yarnpkg.com/conventional-changelog-core/-/conventional-changelog-core-3.1.6.tgz#ac1731a461c50d150d29c1ad4f33143293bcd32f" - integrity sha512-5teTAZOtJ4HLR6384h50nPAaKdDr+IaU0rnD2Gg2C3MS7hKsEPH8pZxrDNqam9eOSPQg9tET6uZY79zzgSz+ig== + version "3.2.2" + resolved "https://registry.yarnpkg.com/conventional-changelog-core/-/conventional-changelog-core-3.2.2.tgz#de41e6b4a71011a18bcee58e744f6f8f0e7c29c0" + integrity sha512-cssjAKajxaOX5LNAJLB+UOcoWjAIBvXtDMedv/58G+YEmAXMNfC16mmPl0JDOuVJVfIqM0nqQiZ8UCm8IXbE0g== dependencies: - conventional-changelog-writer "^4.0.3" - conventional-commits-parser "^3.0.1" + conventional-changelog-writer "^4.0.5" + conventional-commits-parser "^3.0.2" dateformat "^3.0.0" get-pkg-repo "^1.0.0" git-raw-commits "2.0.0" @@ -2729,59 +2816,59 @@ conventional-changelog-core@^3.1.6: q "^1.5.1" read-pkg "^3.0.0" read-pkg-up "^3.0.0" - through2 "^2.0.0" + through2 "^3.0.0" -conventional-changelog-preset-loader@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-2.0.2.tgz#81d1a07523913f3d17da3a49f0091f967ad345b0" - integrity sha512-pBY+qnUoJPXAXXqVGwQaVmcye05xi6z231QM98wHWamGAmu/ghkBprQAwmF5bdmyobdVxiLhPY3PrCfSeUNzRQ== +conventional-changelog-preset-loader@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-2.1.1.tgz#65bb600547c56d5627d23135154bcd9a907668c4" + integrity sha512-K4avzGMLm5Xw0Ek/6eE3vdOXkqnpf9ydb68XYmCc16cJ99XMMbc2oaNMuPwAsxVK6CC1yA4/I90EhmWNj0Q6HA== -conventional-changelog-writer@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/conventional-changelog-writer/-/conventional-changelog-writer-4.0.3.tgz#916a2b302d0bb5ef18efd236a034c13fb273cde1" - integrity sha512-bIlpSiQtQZ1+nDVHEEh798Erj2jhN/wEjyw9sfxY9es6h7pREE5BNJjfv0hXGH/FTrAsEpHUq4xzK99eePpwuA== +conventional-changelog-writer@^4.0.5: + version "4.0.6" + resolved "https://registry.yarnpkg.com/conventional-changelog-writer/-/conventional-changelog-writer-4.0.6.tgz#24db578ac8e7c89a409ef9bba12cf3c095990148" + integrity sha512-ou/sbrplJMM6KQpR5rKFYNVQYesFjN7WpNGdudQSWNi6X+RgyFUcSv871YBYkrUYV9EX8ijMohYVzn9RUb+4ag== dependencies: compare-func "^1.3.1" - conventional-commits-filter "^2.0.1" + conventional-commits-filter "^2.0.2" dateformat "^3.0.0" handlebars "^4.1.0" json-stringify-safe "^5.0.1" lodash "^4.2.1" meow "^4.0.0" - semver "^5.5.0" + semver "^6.0.0" split "^1.0.0" - through2 "^2.0.0" + through2 "^3.0.0" -conventional-commits-filter@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/conventional-commits-filter/-/conventional-commits-filter-2.0.1.tgz#55a135de1802f6510b6758e0a6aa9e0b28618db3" - integrity sha512-92OU8pz/977udhBjgPEbg3sbYzIxMDFTlQT97w7KdhR9igNqdJvy8smmedAAgn4tPiqseFloKkrVfbXCVd+E7A== +conventional-commits-filter@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/conventional-commits-filter/-/conventional-commits-filter-2.0.2.tgz#f122f89fbcd5bb81e2af2fcac0254d062d1039c1" + integrity sha512-WpGKsMeXfs21m1zIw4s9H5sys2+9JccTzpN6toXtxhpw2VNF2JUXwIakthKBy+LN4DvJm+TzWhxOMWOs1OFCFQ== dependencies: - is-subset "^0.1.1" + lodash.ismatch "^4.4.0" modify-values "^1.0.0" -conventional-commits-parser@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/conventional-commits-parser/-/conventional-commits-parser-3.0.1.tgz#fe1c49753df3f98edb2285a5e485e11ffa7f2e4c" - integrity sha512-P6U5UOvDeidUJ8ebHVDIoXzI7gMlQ1OF/id6oUvp8cnZvOXMt1n8nYl74Ey9YMn0uVQtxmCtjPQawpsssBWtGg== +conventional-commits-parser@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/conventional-commits-parser/-/conventional-commits-parser-3.0.3.tgz#c3f972fd4e056aa8b9b4f5f3d0e540da18bf396d" + integrity sha512-KaA/2EeUkO4bKjinNfGUyqPTX/6w9JGshuQRik4r/wJz7rUw3+D3fDG6sZSEqJvKILzKXFQuFkpPLclcsAuZcg== dependencies: JSONStream "^1.0.4" - is-text-path "^1.0.0" + is-text-path "^2.0.0" lodash "^4.2.1" meow "^4.0.0" split2 "^2.0.0" - through2 "^2.0.0" + through2 "^3.0.0" trim-off-newlines "^1.0.0" conventional-recommended-bump@^4.0.4: - version "4.0.4" - resolved "https://registry.yarnpkg.com/conventional-recommended-bump/-/conventional-recommended-bump-4.0.4.tgz#05540584641d3da758c8863c09788fcaeb586872" - integrity sha512-9mY5Yoblq+ZMqJpBzgS+RpSq+SUfP2miOR3H/NR9drGf08WCrY9B6HAGJZEm6+ThsVP917VHAahSOjM6k1vhPg== + version "4.1.1" + resolved "https://registry.yarnpkg.com/conventional-recommended-bump/-/conventional-recommended-bump-4.1.1.tgz#37014fadeda267d0607e2fc81124da840a585127" + integrity sha512-JT2vKfSP9kR18RXXf55BRY1O3AHG8FPg5btP3l7LYfcWJsiXI6MCf30DepQ98E8Qhowvgv7a8iev0J1bEDkTFA== dependencies: - concat-stream "^1.6.0" - conventional-changelog-preset-loader "^2.0.2" - conventional-commits-filter "^2.0.1" - conventional-commits-parser "^3.0.1" + concat-stream "^2.0.0" + conventional-changelog-preset-loader "^2.1.1" + conventional-commits-filter "^2.0.2" + conventional-commits-parser "^3.0.2" git-raw-commits "2.0.0" git-semver-tags "^2.0.2" meow "^4.0.0" @@ -2812,33 +2899,23 @@ copy-descriptor@^0.1.0: integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= core-js@^2.4.0: - version "2.6.1" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.1.tgz#87416ae817de957a3f249b3b5ca475d4aaed6042" - integrity sha512-L72mmmEayPJBejKIWe2pYtGis5r0tQ5NaJekdhyXgeMQTpJoBsH0NL4ElY2LfSoV15xeQWKQ+XTTOZdyero5Xg== + version "2.6.9" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.9.tgz#6b4b214620c834152e179323727fc19741b084f2" + integrity sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A== core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= -cosmiconfig@^5.0.0: - version "5.0.7" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.0.7.tgz#39826b292ee0d78eda137dfa3173bd1c21a43b04" - integrity sha512-PcLqxTKiDmNT6pSpy4N6KtuPwb53W+2tzNvwOZw0WH9N6O0vLIBq0x8aj8Oj75ere4YcGi48bDFCL+3fRJdlNA== - dependencies: - import-fresh "^2.0.0" - is-directory "^0.3.1" - js-yaml "^3.9.0" - parse-json "^4.0.0" - -cosmiconfig@^5.1.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.0.tgz#45038e4d28a7fe787203aede9c25bca4a08b12c8" - integrity sha512-nxt+Nfc3JAqf4WIWd0jXLjTJZmsPLrA9DDc4nRw2KFJQJK7DNooqSXrNI7tzLG50CF8axczly5UV929tBmh/7g== +cosmiconfig@^5.0.0, cosmiconfig@^5.1.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" + integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA== dependencies: import-fresh "^2.0.0" is-directory "^0.3.1" - js-yaml "^3.13.0" + js-yaml "^3.13.1" parse-json "^4.0.0" cp-file@^6.2.0: @@ -2944,7 +3021,7 @@ css-modules-loader-core@^1.1.0: postcss-modules-scope "1.1.0" postcss-modules-values "1.3.0" -css-select-base-adapter@~0.1.0: +css-select-base-adapter@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz#3b2ff4972cc362ab88561507a95408a1432135d7" integrity sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w== @@ -2995,9 +3072,9 @@ css-url-regex@^1.1.0: integrity sha1-g4NCMMyfdMRX3lnuvRVD/uuDt+w= css-what@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.2.tgz#c0876d9d0480927d7d4920dcd72af3595649554d" - integrity sha512-wan8dMWQ0GUeF7DGEPVjhHemVW/vy6xUYmFzRY8RYqgA0JtXC9rJmbScBjqSu6dg9q0lwPQy6ZAmJVr3PPTvqQ== + version "2.1.3" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.3.tgz#a6d7604573365fe74686c3f311c56513d88285f2" + integrity sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg== cssesc@^0.1.0: version "0.1.0" @@ -3009,42 +3086,6 @@ cssesc@^2.0.0: resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-2.0.0.tgz#3b13bd1bb1cb36e1bcb5a4dcd27f54c5dcb35703" integrity sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg== -cssnano-preset-default@^4.0.6: - version "4.0.6" - resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-4.0.6.tgz#92379e2a6db4a91c0ea727f5f556eeac693eab6a" - integrity sha512-UPboYbFaJFtDUhJ4fqctThWbbyF4q01/7UhsZbLzp35l+nUxtzh1SifoVlEfyLM3n3Z0htd8B1YlCxy9i+bQvg== - dependencies: - css-declaration-sorter "^4.0.1" - cssnano-util-raw-cache "^4.0.1" - postcss "^7.0.0" - postcss-calc "^7.0.0" - postcss-colormin "^4.0.2" - postcss-convert-values "^4.0.1" - postcss-discard-comments "^4.0.1" - postcss-discard-duplicates "^4.0.2" - postcss-discard-empty "^4.0.1" - postcss-discard-overridden "^4.0.1" - postcss-merge-longhand "^4.0.10" - postcss-merge-rules "^4.0.2" - postcss-minify-font-values "^4.0.2" - postcss-minify-gradients "^4.0.1" - postcss-minify-params "^4.0.1" - postcss-minify-selectors "^4.0.1" - postcss-normalize-charset "^4.0.1" - postcss-normalize-display-values "^4.0.1" - postcss-normalize-positions "^4.0.1" - postcss-normalize-repeat-style "^4.0.1" - postcss-normalize-string "^4.0.1" - postcss-normalize-timing-functions "^4.0.1" - postcss-normalize-unicode "^4.0.1" - postcss-normalize-url "^4.0.1" - postcss-normalize-whitespace "^4.0.1" - postcss-ordered-values "^4.1.1" - postcss-reduce-initial "^4.0.2" - postcss-reduce-transforms "^4.0.1" - postcss-svgo "^4.0.1" - postcss-unique-selectors "^4.0.1" - cssnano-preset-default@^4.0.7: version "4.0.7" resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-4.0.7.tgz#51ec662ccfca0f88b396dcd9679cdb931be17f76" @@ -3103,17 +3144,7 @@ cssnano-util-same-parent@^4.0.0: resolved "https://registry.yarnpkg.com/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz#574082fb2859d2db433855835d9a8456ea18bbf3" integrity sha512-WcKx5OY+KoSIAxBW6UBBRay1U6vkYheCdjyVNDm85zt5K9mHoGOfsOsqIszfAqrQQFIIKgjh2+FDgIj/zsl21Q== -cssnano@^4.0.0: - version "4.1.8" - resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-4.1.8.tgz#8014989679d5fd42491e4499a521dbfb85c95fd1" - integrity sha512-5GIY0VzAHORpbKiL3rMXp4w4M1Ki+XlXgEXyuWXVd3h6hlASb+9Vo76dNP56/elLMVBBsUfusCo1q56uW0UWig== - dependencies: - cosmiconfig "^5.0.0" - cssnano-preset-default "^4.0.6" - is-resolvable "^1.0.0" - postcss "^7.0.0" - -cssnano@^4.1.9: +cssnano@^4.0.0, cssnano@^4.1.9: version "4.1.10" resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-4.1.10.tgz#0ac41f0b13d13d465487e111b778d42da631b8b2" integrity sha512-5wny+F6H4/8RgNlaqab4ktc3e0/blKutmq8yNlBFXA//nSFFAqAngjNVRzUvCgYROULmZZUoosL/KSoZo5aUaQ== @@ -3123,7 +3154,7 @@ cssnano@^4.1.9: is-resolvable "^1.0.0" postcss "^7.0.0" -csso@^3.5.0: +csso@^3.5.1: version "3.5.1" resolved "https://registry.yarnpkg.com/csso/-/csso-3.5.1.tgz#7b9eb8be61628973c1b261e169d2f024008e758b" integrity sha512-vrqULLffYU1Q2tLdJvaCYbONStnfkfimRxXNaGjxMldI0C7JPBC4rB1RyjhfdZ4m1frm8pM9uRPKH3d2knZ8gg== @@ -3188,14 +3219,14 @@ dateformat@^3.0.0: integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q== deasync@^0.1.14: - version "0.1.14" - resolved "https://registry.yarnpkg.com/deasync/-/deasync-0.1.14.tgz#232ea2252b443948cad033d792eb3b24b0a3d828" - integrity sha512-wN8sIuEqIwyQh72AG7oY6YQODCxIp1eXzEZlZznBuwDF8Q03Tdy9QNp1BNZXeadXoklNrw+Ip1fch+KXo/+ASw== + version "0.1.15" + resolved "https://registry.yarnpkg.com/deasync/-/deasync-0.1.15.tgz#788c4bbe6d32521233b28d23936de1bbadd2e112" + integrity sha512-pxMaCYu8cQIbGkA4Y1R0PLSooPIpH1WgFBLeJ+zLxQgHfkZG86ViJSmZmONSjZJ/R3NjwkMcIWZAzpLB2G9/CA== dependencies: bindings "~1.2.1" node-addon-api "^1.6.0" -debug@2.6.9, debug@^2.1.2, debug@^2.2.0, debug@^2.3.3: +debug@2.6.9, debug@^2.2.0, debug@^2.3.3: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== @@ -3209,7 +3240,7 @@ debug@3.1.0: dependencies: ms "2.0.0" -debug@3.2.6, debug@^3.1.0: +debug@3.2.6, debug@^3.1.0, debug@^3.2.6: version "3.2.6" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== @@ -3261,10 +3292,10 @@ deep-is@~0.1.3: resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= -deepmerge@3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-3.2.0.tgz#58ef463a57c08d376547f8869fdc5bcee957f44e" - integrity sha512-6+LuZGU7QCNUnAJyX8cIrlzoEgggTM6B7mm+znKOX4t5ltluT9KLjN6g61ECMS0LTsLW7yDpNoxhix5FZcrIow== +deepmerge@3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-3.2.1.tgz#76a1f47854bcfcd66ee9a948d110540a8e12b261" + integrity sha512-+hbDSzTqEW0fWgnlKksg7XAOtT+ddZS5lHZJ6f6MdixRs9wQy+50fm1uUCVb1IkvjLUYX/SfFO021ZNwriURTw== default-require-extensions@^2.0.0: version "2.0.0" @@ -3324,10 +3355,10 @@ depd@~1.1.2: resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= -deprecation@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/deprecation/-/deprecation-1.0.1.tgz#2df79b79005752180816b7b6e079cbd80490d711" - integrity sha512-ccVHpE72+tcIKaGMql33x5MAjKQIZrk+3x2GbJ7TeraUCZWHoT+KSZpoC+JQFsUBlSTXUrBaGiF0j6zVTepPLg== +deprecation@^2.0.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/deprecation/-/deprecation-2.3.1.tgz#6368cbdb40abf3373b525ac87e4a260c3a700919" + integrity sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ== des.js@^1.0.0: version "1.0.0" @@ -3379,7 +3410,7 @@ diffie-hellman@^5.0.0: miller-rabin "^4.0.0" randombytes "^2.0.0" -dir-glob@^2.0.0: +dir-glob@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-2.0.0.tgz#0b205d2b6aef98238ca286598a8204d29d0a0034" integrity sha512-37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag== @@ -3388,28 +3419,23 @@ dir-glob@^2.0.0: path-type "^3.0.0" dom-serializer@0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82" - integrity sha1-BzxpdUbOB4DOI75KKOKT5AvDDII= + version "0.1.1" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.1.tgz#1ec4059e284babed36eec2941d4a970a189ce7c0" + integrity sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA== dependencies: - domelementtype "~1.1.1" - entities "~1.1.1" + domelementtype "^1.3.0" + entities "^1.1.1" domain-browser@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== -domelementtype@1, domelementtype@^1.3.0: +domelementtype@1, domelementtype@^1.3.0, domelementtype@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== -domelementtype@~1.1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.1.3.tgz#bd28773e2642881aec51544924299c5cd822185b" - integrity sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs= - domexception@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/domexception/-/domexception-1.0.1.tgz#937442644ca6a31261ef36e3ec677fe805582c90" @@ -3469,9 +3495,9 @@ duplexer@^0.1.1: integrity sha1-rOb/gIwc5mtX0ev5eXessCM0z8E= duplexify@^3.4.2, duplexify@^3.6.0: - version "3.6.1" - resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.6.1.tgz#b1a7a29c4abfd639585efaecce80d666b1e34125" - integrity sha512-vM58DwdnKmty+FSPzT14K9JXb90H+j5emaR4KYbr2KTIz00WHGbWOe5ghQTx233ZCLZtrGDALzKwcjEtSt35mA== + version "3.7.1" + resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309" + integrity sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g== dependencies: end-of-stream "^1.0.0" inherits "^2.0.1" @@ -3486,15 +3512,13 @@ ecc-jsbn@~0.1.1: jsbn "~0.1.0" safer-buffer "^2.1.0" -editorconfig@^0.15.2: - version "0.15.2" - resolved "https://registry.yarnpkg.com/editorconfig/-/editorconfig-0.15.2.tgz#047be983abb9ab3c2eefe5199cb2b7c5689f0702" - integrity sha512-GWjSI19PVJAM9IZRGOS+YKI8LN+/sjkSjNyvxL5ucqP9/IqtYNXBaQ/6c/hkPNYQHyOHra2KoXZI/JVpuqwmcQ== +editorconfig@^0.15.3: + version "0.15.3" + resolved "https://registry.yarnpkg.com/editorconfig/-/editorconfig-0.15.3.tgz#bef84c4e75fb8dcb0ce5cee8efd51c15999befc5" + integrity sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g== dependencies: - "@types/node" "^10.11.7" - "@types/semver" "^5.5.0" commander "^2.19.0" - lru-cache "^4.1.3" + lru-cache "^4.1.5" semver "^5.6.0" sigmund "^1.0.1" @@ -3503,10 +3527,10 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= -electron-to-chromium@^1.3.96: - version "1.3.98" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.98.tgz#f200bdac84b1110d7d9904f34f4fc6d5573a8a9c" - integrity sha512-WIZdNuvE3dFr6kkPgv4d/cfswNZD6XbeLBM8baOIQTsnbf4xWrVEaLvp7oNnbnMWWXDqq7Tbv+H5JfciLTJm4Q== +electron-to-chromium@^1.3.150: + version "1.3.163" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.163.tgz#7fc3d637f5d8fa4ca4a052cad0de7675bd98b911" + integrity sha512-uCEoqQeKrjlhUSUudY0XvyNVDhWR5XmnCIV0WXr2Qo9PVzEVXI75LHGtzwro9Qh8NNetRjSitrm8AfQvPGaSqA== elliptic@^6.0.0: version "6.4.1" @@ -3559,7 +3583,7 @@ enhanced-resolve@^4.0.0, enhanced-resolve@^4.1.0: memory-fs "^0.4.0" tapable "^1.0.0" -entities@^1.1.1, entities@~1.1.1: +entities@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== @@ -3610,9 +3634,9 @@ es6-error@^4.0.1: integrity sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg== es6-promise@^4.0.3: - version "4.2.5" - resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.5.tgz#da6d0d5692efb461e082c14817fe2427d8f5d054" - integrity sha512-n6wvpdE43VFtJq+lUDYDBFUwV8TZbuGXLV4D6wKafg13ldznKsyEvatubnmUe31zcvelSzOHF+XbaT+Bl9ObDg== + version "4.2.8" + resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" + integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== es6-promisify@^5.0.0: version "5.0.0" @@ -3631,19 +3655,7 @@ escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1 resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= -escodegen@^1.8.1: - version "1.11.0" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.11.0.tgz#b27a9389481d5bfd5bec76f7bb1eb3f8f4556589" - integrity sha512-IeMV45ReixHS53K/OmfKAIztN/igDHzTJUhZM3k1jMhIZWjk45SMwAtBsEXiJp3vSPmTcu6CXn7mDvFHRN66fw== - dependencies: - esprima "^3.1.3" - estraverse "^4.2.0" - esutils "^2.0.2" - optionator "^0.8.1" - optionalDependencies: - source-map "~0.6.1" - -escodegen@^1.9.1: +escodegen@^1.8.1, escodegen@^1.9.1: version "1.11.1" resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.11.1.tgz#c485ff8d6b4cdb89e27f4a856e91f118401ca510" integrity sha512-JwiqFD9KdGVVpeuRa68yU3zZnBEOcPs0nKW7wZzXky8Z7tffdYUHbe11bPCV5jYlK6DVdKLWLm0f5I/QlL0Kmw== @@ -3668,9 +3680,9 @@ escodegen@~1.9.0: source-map "~0.6.1" eslint-scope@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.0.tgz#50bf3071e9338bcdc43331794a0cb533f0136172" - integrity sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA== + version "4.0.3" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" + integrity sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg== dependencies: esrecurse "^4.1.0" estraverse "^4.1.1" @@ -3697,10 +3709,10 @@ estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" integrity sha1-De4/7TH81GlhjOc0IJn8GvoL2xM= -estree-walker@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.6.0.tgz#5d865327c44a618dde5699f763891ae31f257dae" - integrity sha512-peq1RfVAVzr3PU/jL31RaOjUKLoZJpObQWJJ+LgfcxDUifyLZ1RjPQZTl0pzj2uJ45b7A7XpyppXvxdEqzo4rw== +estree-walker@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.6.1.tgz#53049143f40c6eb918b23671d1fe3219f3a1b362" + integrity sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w== esutils@^2.0.0, esutils@^2.0.2: version "2.0.2" @@ -3712,31 +3724,23 @@ etag@~1.8.1: resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= -events@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" - integrity sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ= +eventemitter3@^3.1.0: + version "3.1.2" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.2.tgz#2d3d48f9c346698fce83a85d7d664e98535df6e7" + integrity sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q== -evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" - integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== - dependencies: - md5.js "^1.3.4" - safe-buffer "^5.1.1" +events@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.0.0.tgz#9a0a0dfaf62893d92b875b8f2698ca4114973e88" + integrity sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA== -execa@^0.10.0: - version "0.10.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-0.10.0.tgz#ff456a8f53f90f8eccc71a96d11bdfc7f082cb50" - integrity sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw== - dependencies: - cross-spawn "^6.0.0" - get-stream "^3.0.0" - is-stream "^1.1.0" - npm-run-path "^2.0.0" - p-finally "^1.0.0" - signal-exit "^3.0.0" - strip-eof "^1.0.0" +evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" + integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== + dependencies: + md5.js "^1.3.4" + safe-buffer "^5.1.1" execa@^1.0.0: version "1.0.0" @@ -3791,7 +3795,7 @@ extend@~3.0.2: resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== -external-editor@^3.0.0: +external-editor@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.0.3.tgz#5866db29a97826dbe4bf3afd24070ead9ea43a27" integrity sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA== @@ -3840,9 +3844,9 @@ fast-deep-equal@^2.0.1: integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= fast-glob@^2.0.2, fast-glob@^2.2.2: - version "2.2.4" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.2.4.tgz#e54f4b66d378040e0e4d6a68ec36bbc5b04363c0" - integrity sha512-FjK2nCGI/McyzgNtTESqaWP3trPvHyRyoyY70hxjc3oKPNmDe8taohLZpoVKoUjW85tbU5txaYUZCNtVzygl1g== + version "2.2.7" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.2.7.tgz#6953857c3afa475fff92ee6015d52da70a4cd39d" + integrity sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw== dependencies: "@mrmlnc/readdir-enhanced" "^2.2.1" "@nodelib/fs.stat" "^1.1.2" @@ -3878,12 +3882,12 @@ figures@^2.0.0: dependencies: escape-string-regexp "^1.0.5" -file-loader@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-3.0.1.tgz#f8e0ba0b599918b51adfe45d66d1e771ad560faa" - integrity sha512-4sNIOXgtH/9WZq4NvlfU3Opn5ynUsqBwSLyM+I7UOwdGigTBYfVVQEwe/msZNX/j4pCJTIM14Fsw66Svo1oVrw== +file-loader@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-4.0.0.tgz#c3570783fefb6e1bc0978a856f4bf5825b966c2a" + integrity sha512-roAbL6IdSGczwfXxhMi6Zq+jD4IfUpL0jWHD7fvmjdOVb7xBfdRUHe4LpBgO23VtVK5AW1OlWZo0p34Jvx3iWg== dependencies: - loader-utils "^1.0.2" + loader-utils "^1.2.2" schema-utils "^1.0.0" filesize@^3.6.0: @@ -3901,16 +3905,14 @@ fill-range@^4.0.0: repeat-string "^1.6.1" to-regex-range "^2.1.0" -find-cache-dir@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.0.0.tgz#4c1faed59f45184530fb9d7fa123a4d04a98472d" - integrity sha512-LDUY6V1Xs5eFskUVYtIwatojt6+9xC9Chnlk/jYOOvn3FAFfSaWddxahDGyNHh0b2dMXa6YW2m0tk8TdVaXHlA== +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== dependencies: - commondir "^1.0.1" - make-dir "^1.0.0" - pkg-dir "^3.0.0" + to-regex-range "^5.0.1" -find-cache-dir@^2.1.0: +find-cache-dir@^2.0.0, find-cache-dir@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ== @@ -3959,12 +3961,12 @@ flat@^4.1.0: is-buffer "~2.0.3" flush-write-stream@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.0.3.tgz#c5d586ef38af6097650b49bc41b55fabb19f35bd" - integrity sha512-calZMC10u0FMUqoiunI2AiGIIUtUIvifNwkHhNupZH4cbNnW1Itkoh/Nf5HFYmDrwWPjrUxpkZT0KhuCq0jmGw== + version "1.1.1" + resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.1.1.tgz#8dd7d873a1babc207d94ead0c2e0e44276ebf2e8" + integrity sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w== dependencies: - inherits "^2.0.1" - readable-stream "^2.0.4" + inherits "^2.0.3" + readable-stream "^2.3.6" for-in@^1.0.2: version "1.0.2" @@ -4028,9 +4030,9 @@ fs-extra@^7.0.0: universalify "^0.1.0" fs-minipass@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.5.tgz#06c277218454ec288df77ada54a03b8702aacb9d" - integrity sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ== + version "1.2.6" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.6.tgz#2c5cc30ded81282bfe8a0d7c7c1853ddeb102c07" + integrity sha512-crhvyXcMejjv3Z5d2Fa9sf5xLYVCF5O1c71QxbVnbLsmYMBEvDAftewesN/HhY03YRoA7zOMxjNGrF5svGaaeQ== dependencies: minipass "^2.2.1" @@ -4049,23 +4051,13 @@ fs.realpath@^1.0.0: resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= -fsevents@^1.2.2: - version "1.2.4" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.4.tgz#f41dcb1af2582af3692da36fc55cbd8e1041c426" - integrity sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg== - dependencies: - nan "^2.9.2" - node-pre-gyp "^0.10.0" - -fstream@^1.0.0, fstream@^1.0.2: - version "1.0.11" - resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171" - integrity sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE= +fsevents@^1.2.7: + version "1.2.9" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.9.tgz#3f5ed66583ccd6f400b5a00db6f7e861363e388f" + integrity sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw== dependencies: - graceful-fs "^4.1.2" - inherits "~2.0.0" - mkdirp ">=0.5 0" - rimraf "2" + nan "^2.12.1" + node-pre-gyp "^0.12.0" function-bind@^1.1.1: version "1.1.1" @@ -4122,11 +4114,6 @@ get-stdin@^4.0.1: resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" integrity sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4= -get-stream@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" - integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ= - get-stream@^4.0.0, get-stream@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" @@ -4208,7 +4195,7 @@ glob-to-regexp@^0.3.0: resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab" integrity sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs= -glob@7.1.3, glob@^7.0.0, glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3: +glob@7.1.3: version "7.1.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== @@ -4220,6 +4207,18 @@ glob@7.1.3, glob@^7.0.0, glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3: once "^1.3.0" path-is-absolute "^1.0.0" +glob@^7.0.0, glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3: + version "7.1.4" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.4.tgz#aa608a2f6c577ad357e1ae5a5c26d9a8d1969255" + integrity sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + global-modules@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea" @@ -4241,17 +4240,17 @@ global-prefix@^1.0.1: which "^1.2.14" globals@^11.1.0: - version "11.9.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.9.0.tgz#bde236808e987f290768a93d065060d78e6ab249" - integrity sha512-5cJVtyXWH8PiJPVLZzzoIizXx944O4OmRro5MWKx5fT4MgcN7OfaMutPeaTdJCCURwbWdhhcCWcKIffPnmTzBg== + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== globby@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/globby/-/globby-8.0.1.tgz#b5ad48b8aa80b35b814fc1281ecc851f1d2b5b50" - integrity sha512-oMrYrJERnKBLXNLVTqhm3vPEdJ/b2ZE28xN4YARiix1NOIOBPEpOUnm844K1iu/BkphCaf2WNFwMszv8Soi1pw== + version "8.0.2" + resolved "https://registry.yarnpkg.com/globby/-/globby-8.0.2.tgz#5697619ccd95c5275dbb2d6faa42087c1a941d8d" + integrity sha512-yTzMmKygLp8RUpG1Ymu2VXPSJQZjNAZPD4ywgYEaG7e4tBJeUQBO8OpXrf1RCNcEs5alsoJYPAMiIHP0cmeC7w== dependencies: array-union "^1.0.1" - dir-glob "^2.0.0" + dir-glob "2.0.0" fast-glob "^2.0.2" glob "^7.1.2" ignore "^3.3.5" @@ -4277,28 +4276,17 @@ growl@1.10.5: integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== gzip-size@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-5.1.0.tgz#2db0396c71f5c902d5cf6b52add5030b93c99bd2" - integrity sha512-wfSnvypBDRW94v5W3ckvvz/zFUNdJ81VgOP6tE4bPpRUcc0wGqU+y0eZjJEvKxwubJFix6P84sE8M51YWLT7rQ== + version "5.1.1" + resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-5.1.1.tgz#cb9bee692f87c0612b232840a873904e4c135274" + integrity sha512-FNHi6mmoHvs1mxZAds4PpdCS6QG8B4C1krxJsMutgxl5t3+GlRTzzI3NEkifXx2pVsOvJdOGSmIgDhQ55FwdPA== dependencies: duplexer "^0.1.1" pify "^4.0.1" -handlebars@^4.0.6: - version "4.0.12" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.12.tgz#2c15c8a96d46da5e266700518ba8cb8d919d5bc5" - integrity sha512-RhmTekP+FZL+XNhwS1Wf+bTTZpdLougwt5pcgA1tuz6Jcx0fpH/7z0qd71RKnZHBCxIRBHfBOnio4gViPemNzA== - dependencies: - async "^2.5.0" - optimist "^0.6.1" - source-map "^0.6.1" - optionalDependencies: - uglify-js "^3.1.4" - -handlebars@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.1.1.tgz#6e4e41c18ebe7719ae4d38e5aca3d32fa3dd23d3" - integrity sha512-3Zhi6C0euYZL5sM0Zcy7lInLXKQ+YLcF/olbN010mzGQ4XVm50JeyBnMqofHh696GrciGruC7kCcApPDJvVgwA== +handlebars@*, handlebars@^4.0.6, handlebars@^4.1.0, handlebars@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.1.2.tgz#b6b37c1ced0306b221e094fc7aca3ec23b131b67" + integrity sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw== dependencies: neo-async "^2.6.0" optimist "^0.6.1" @@ -4418,9 +4406,9 @@ hex-color-regex@^1.1.0: integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ== highlight.js@^9.13.1: - version "9.15.6" - resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.15.6.tgz#72d4d8d779ec066af9a17cb14360c3def0aa57c4" - integrity sha512-zozTAWM1D6sozHo8kqhfYgsac+B+q0PmsjXeyDrYIHHcBN0zTVT66+s2GW1GZv7DbyaROdLXKdabwS/WqPyIdQ== + version "9.15.8" + resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.15.8.tgz#f344fda123f36f1a65490e932cf90569e4999971" + integrity sha512-RrapkKQWwE+wKdF73VsOa2RQdIoO3mxwJ4P8mhbI6KYJUraUHRKM5w5zQQKXNk0xNL4UVRdulV9SBJcmzJNzVA== hmac-drbg@^1.0.0: version "1.0.1" @@ -4432,9 +4420,9 @@ hmac-drbg@^1.0.0: minimalistic-crypto-utils "^1.0.1" homedir-polyfill@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz#4c2bbc8a758998feebf5ed68580f76d46768b4bc" - integrity sha1-TCu8inWJmP7r9e1oWA921GdotLw= + version "1.0.3" + resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz#743298cef4e5af3e194161fbadcc2151d3a058e8" + integrity sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA== dependencies: parse-passwd "^1.0.0" @@ -4485,31 +4473,32 @@ htmlnano@^0.2.2: uncss "^0.16.2" htmlparser2@^3.9.2: - version "3.10.0" - resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.0.tgz#5f5e422dcf6119c0d983ed36260ce9ded0bee464" - integrity sha512-J1nEUGv+MkXS0weHNWVKJJ+UrLfePxRWpN3C9bEi9fLxL2+ggW94DQvgYVXsaT30PGwYRIZKNZXuyMhp3Di4bQ== + version "3.10.1" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f" + integrity sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ== dependencies: - domelementtype "^1.3.0" + domelementtype "^1.3.1" domhandler "^2.3.0" domutils "^1.5.1" entities "^1.1.1" inherits "^2.0.1" - readable-stream "^3.0.6" + readable-stream "^3.1.1" http-cache-semantics@^3.8.1: version "3.8.1" resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2" integrity sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w== -http-errors@~1.6.2: - version "1.6.3" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" - integrity sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0= +http-errors@~1.7.2: + version "1.7.2" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f" + integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg== dependencies: depd "~1.1.2" inherits "2.0.3" - setprototypeof "1.1.0" - statuses ">= 1.4.0 < 2" + setprototypeof "1.1.1" + statuses ">= 1.5.0 < 2" + toidentifier "1.0.0" http-proxy-agent@^2.1.0: version "2.1.0" @@ -4561,9 +4550,9 @@ icss-replace-symbols@1.1.0, icss-replace-symbols@^1.1.0: integrity sha1-Bupvg2ead0njhs/h/oEq5dsiPe0= ieee754@^1.1.4: - version "1.1.12" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.12.tgz#50bf24e5b9c8bb98af4964c941cdb0918da7b60b" - integrity sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA== + version "1.1.13" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84" + integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg== iferr@^0.1.5: version "0.1.5" @@ -4628,11 +4617,6 @@ indexes-of@^1.0.1: resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607" integrity sha1-8w9xbI4r00bHtn0985FVZqfAVgc= -indexof@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d" - integrity sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10= - inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" @@ -4641,7 +4625,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: +inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= @@ -4671,22 +4655,22 @@ init-package-json@^1.10.3: validate-npm-package-name "^3.0.0" inquirer@^6.2.0: - version "6.2.1" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.2.1.tgz#9943fc4882161bdb0b0c9276769c75b32dbfcd52" - integrity sha512-088kl3DRT2dLU5riVMKKr1DlImd6X7smDhpXUCkJDCKvTEJeRiXh0G132HG9u5a+6Ylw9plFRY7RuTnwohYSpg== + version "6.3.1" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.3.1.tgz#7a413b5e7950811013a3db491c61d1f3b776e8e7" + integrity sha512-MmL624rfkFt4TG9y/Jvmt8vdmOo836U7Y0Hxr2aFk3RelZEGX4Igk0KabWrcaaZaTv9uzglOqWh1Vly+FAWAXA== dependencies: - ansi-escapes "^3.0.0" - chalk "^2.0.0" + ansi-escapes "^3.2.0" + chalk "^2.4.2" cli-cursor "^2.1.0" cli-width "^2.0.0" - external-editor "^3.0.0" + external-editor "^3.0.3" figures "^2.0.0" - lodash "^4.17.10" + lodash "^4.17.11" mute-stream "0.0.7" run-async "^2.2.0" - rxjs "^6.1.0" + rxjs "^6.4.0" string-width "^2.1.0" - strip-ansi "^5.0.0" + strip-ansi "^5.1.0" through "^2.3.6" interpret@^1.0.0, interpret@^1.1.0: @@ -4757,13 +4741,6 @@ is-buffer@~2.0.3: resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.3.tgz#4ecf3fcf749cbd1e472689e109ac66261a25e725" integrity sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw== -is-builtin-module@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe" - integrity sha1-VAVy0096wxGfj3bDDLwbHgN6/74= - dependencies: - builtin-modules "^1.0.0" - is-callable@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" @@ -4874,9 +4851,9 @@ is-glob@^3.1.0: is-extglob "^2.1.0" is-glob@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.0.tgz#9521c76845cc2610a85203ddf080a958c2ffabc0" - integrity sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A= + version "4.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" + integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== dependencies: is-extglob "^2.1.1" @@ -4894,6 +4871,11 @@ is-number@^3.0.0: dependencies: kind-of "^3.0.2" +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + is-obj@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" @@ -4911,6 +4893,13 @@ is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: dependencies: isobject "^3.0.1" +is-plain-object@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-3.0.0.tgz#47bfc5da1b5d50d64110806c199359482e75a928" + integrity sha512-tZIpofR+P05k8Aocp7UI/2UTa9lTJSebCXpFFoR9aibpokDj/uXBsJ8luUu0tTVYKkMU6URDUuOfJZ7koewXvg== + dependencies: + isobject "^4.0.0" + is-promise@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" @@ -4940,11 +4929,6 @@ is-stream@^1.0.1, is-stream@^1.1.0: resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= -is-subset@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-subset/-/is-subset-0.1.1.tgz#8a59117d932de1de00f245fcdd39ce43f1e939a6" - integrity sha1-ilkRfZMt4d4A8kX83TnOQ/HpOaY= - is-svg@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-svg/-/is-svg-3.0.0.tgz#9321dbd29c212e5ca99c4fa9794c714bcafa2f75" @@ -4959,12 +4943,12 @@ is-symbol@^1.0.2: dependencies: has-symbols "^1.0.0" -is-text-path@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-text-path/-/is-text-path-1.0.1.tgz#4e1aa0fb51bfbcb3e92688001397202c1775b66e" - integrity sha1-Thqg+1G/vLPpJogAE5cgLBd1tm4= +is-text-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-text-path/-/is-text-path-2.0.0.tgz#b2484e2b720a633feb2e85b67dc193ff72c75636" + integrity sha512-+oDTluR6WEjdXEJMnC2z6A4FRwFoYuvShVVEGsS7ewc0UTi2QtAKMDJuL4BDEVt+5T7MjFo12RP8ghOM75oKJw== dependencies: - text-extensions "^1.0.0" + text-extensions "^2.0.0" is-typedarray@~1.0.0: version "1.0.0" @@ -5006,7 +4990,7 @@ isexe@^2.0.0: resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= -isobject@^2.0.0, isobject@^2.1.0: +isobject@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= @@ -5018,72 +5002,77 @@ isobject@^3.0.0, isobject@^3.0.1: resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= +isobject@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-4.0.0.tgz#3f1c9155e73b192022a80819bacd0343711697b0" + integrity sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA== + isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= -istanbul-lib-coverage@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz#927a354005d99dd43a24607bb8b33fd4e9aca1ad" - integrity sha512-LXTBICkMARVgo579kWDm8SqfB6nvSDKNqIOBEjmJRnL04JvoMHCYGWaMddQnseJYtkEuEvO/sIcOxPLk9gERug== +istanbul-lib-coverage@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz#675f0ab69503fad4b1d849f736baaca803344f49" + integrity sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA== -istanbul-lib-hook@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-2.0.6.tgz#5baa6067860a38290aef038b389068b225b01b7d" - integrity sha512-829DKONApZ7UCiPXcOYWSgkFXa4+vNYoNOt3F+4uDJLKL1OotAoVwvThoEj1i8jmOj7odbYcR3rnaHu+QroaXg== +istanbul-lib-hook@^2.0.7: + version "2.0.7" + resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-2.0.7.tgz#c95695f383d4f8f60df1f04252a9550e15b5b133" + integrity sha512-vrRztU9VRRFDyC+aklfLoeXyNdTfga2EI3udDGn4cZ6fpSXpHLV9X6CHvfoMCPtggg8zvDDmC4b9xfu0z6/llA== dependencies: append-transform "^1.0.0" -istanbul-lib-instrument@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-3.2.0.tgz#c549208da8a793f6622257a2da83e0ea96ae6a93" - integrity sha512-06IM3xShbNW4NgZv5AP4QH0oHqf1/ivFo8eFys0ZjPXHGldHJQWb3riYOKXqmOqfxXBfxu4B+g/iuhOPZH0RJg== +istanbul-lib-instrument@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz#a5f63d91f0bbc0c3e479ef4c5de027335ec6d630" + integrity sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA== dependencies: - "@babel/generator" "^7.0.0" - "@babel/parser" "^7.0.0" - "@babel/template" "^7.0.0" - "@babel/traverse" "^7.0.0" - "@babel/types" "^7.0.0" - istanbul-lib-coverage "^2.0.4" + "@babel/generator" "^7.4.0" + "@babel/parser" "^7.4.3" + "@babel/template" "^7.4.0" + "@babel/traverse" "^7.4.3" + "@babel/types" "^7.4.0" + istanbul-lib-coverage "^2.0.5" semver "^6.0.0" -istanbul-lib-report@^2.0.7: - version "2.0.7" - resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-2.0.7.tgz#370d80d433c4dbc7f58de63618f49599c74bd954" - integrity sha512-wLH6beJBFbRBLiTlMOBxmb85cnVM1Vyl36N48e4e/aTKSM3WbOx7zbVIH1SQ537fhhsPbX0/C5JB4qsmyRXXyA== +istanbul-lib-report@^2.0.8: + version "2.0.8" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz#5a8113cd746d43c4889eba36ab10e7d50c9b4f33" + integrity sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ== dependencies: - istanbul-lib-coverage "^2.0.4" + istanbul-lib-coverage "^2.0.5" make-dir "^2.1.0" - supports-color "^6.0.0" + supports-color "^6.1.0" -istanbul-lib-source-maps@^3.0.5: - version "3.0.5" - resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.5.tgz#1d9ee9d94d2633f15611ee7aae28f9cac6d1aeb9" - integrity sha512-eDhZ7r6r1d1zQPVZehLc3D0K14vRba/eBYkz3rw16DLOrrTzve9RmnkcwrrkWVgO1FL3EK5knujVe5S8QHE9xw== +istanbul-lib-source-maps@^3.0.6: + version "3.0.6" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz#284997c48211752ec486253da97e3879defba8c8" + integrity sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw== dependencies: debug "^4.1.1" - istanbul-lib-coverage "^2.0.4" + istanbul-lib-coverage "^2.0.5" make-dir "^2.1.0" - rimraf "^2.6.2" + rimraf "^2.6.3" source-map "^0.6.1" -istanbul-reports@^2.2.2: - version "2.2.3" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-2.2.3.tgz#14e0d00ecbfa9387757999cf36599b88e9f2176e" - integrity sha512-T6EbPuc8Cb620LWAYyZ4D8SSn06dY9i1+IgUX2lTH8gbwflMc9Obd33zHTyNX653ybjpamAHS9toKS3E6cGhTw== +istanbul-reports@^2.2.4: + version "2.2.6" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-2.2.6.tgz#7b4f2660d82b29303a8fe6091f8ca4bf058da1af" + integrity sha512-SKi4rnMyLBKe0Jy2uUdx28h8oG7ph2PPuQPvIAh31d+Ci+lSiEu4C+h3oBPuJ9+mPKhOyW0M8gY4U5NM1WLeXA== dependencies: - handlebars "^4.1.0" + handlebars "^4.1.2" js-beautify@^1.8.9: - version "1.8.9" - resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.8.9.tgz#08e3c05ead3ecfbd4f512c3895b1cda76c87d523" - integrity sha512-MwPmLywK9RSX0SPsUJjN7i+RQY9w/yC17Lbrq9ViEefpLRgqAR2BgrMN2AbifkUuhDV8tRauLhLda/9+bE0YQA== + version "1.10.0" + resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.10.0.tgz#9753a13c858d96828658cd18ae3ca0e5783ea672" + integrity sha512-OMwf/tPDpE/BLlYKqZOhqWsd3/z2N3KOlyn1wsCRGFwViE8LOQTcDtathQvHvZc+q+zWmcNAbwKSC+iJoMaH2Q== dependencies: config-chain "^1.1.12" - editorconfig "^0.15.2" + editorconfig "^0.15.3" glob "^7.1.3" - mkdirp "~0.5.0" + mkdirp "~0.5.1" nopt "~4.0.1" js-cleanup@^1.0.1: @@ -5096,16 +5085,16 @@ js-cleanup@^1.0.1: skip-regex "^1.0.2" js-levenshtein@^1.1.3: - version "1.1.4" - resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.4.tgz#3a56e3cbf589ca0081eb22cd9ba0b1290a16d26e" - integrity sha512-PxfGzSs0ztShKrUYPIn5r0MtyAhYcCwmndozzpz8YObbPnD1jFxzlBGbRnX2mIu6Z13xN6+PTu05TQFnZFlzow== + version "1.1.6" + resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.6.tgz#c6cee58eb3550372df8deb85fad5ce66ce01d59d" + integrity sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g== "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-yaml@3.13.1: +js-yaml@3.13.1, js-yaml@^3.10.0, js-yaml@^3.13.1: version "3.13.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== @@ -5113,22 +5102,6 @@ js-yaml@3.13.1: argparse "^1.0.7" esprima "^4.0.0" -js-yaml@^3.10.0, js-yaml@^3.12.0, js-yaml@^3.9.0: - version "3.12.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.1.tgz#295c8632a18a23e054cf5c9d3cecafe678167600" - integrity sha512-um46hB9wNOKlwkHgiuyEVAybXBjwFUV0Z/RaHJblRd9DXltue9FTYvzCr9ErQrK9Adz5MU4gHWVaNUfdmrC8qA== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - -js-yaml@^3.13.0: - version "3.13.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.0.tgz#38ee7178ac0eea2c97ff6d96fff4b18c7d8cf98e" - integrity sha512-pZZoSxcCYco+DIKBTimr67J6Hy+EYGZDY/HCWC+iAEA9h1ByhMXAIVUXMcMFpOCxQ/xjXmPI2MkDL5HRm5eFrQ== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" @@ -5269,25 +5242,25 @@ left-pad@^1.3.0: integrity sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA== lerna@^3.13.3: - version "3.13.3" - resolved "https://registry.yarnpkg.com/lerna/-/lerna-3.13.3.tgz#bfd64e99466eaaf35b5d27994973b9f694796181" - integrity sha512-0TkG40F02A4wjKraJBztPtj87BjUezFmaZKAha8eLdtngZkSpAdrSANa5K7jnnA8mywmpQwrKJuBmjdNpm9cBw== - dependencies: - "@lerna/add" "3.13.3" - "@lerna/bootstrap" "3.13.3" - "@lerna/changed" "3.13.3" - "@lerna/clean" "3.13.3" + version "3.15.0" + resolved "https://registry.yarnpkg.com/lerna/-/lerna-3.15.0.tgz#b044dba8138d7a1a8dd48ac1d80e7541bdde0d1f" + integrity sha512-kRIQ3bgzkmew5/WZQ0C9WjH0IUf3ZmTNnBwTHfXgLkVY7td0lbwMQFD7zehflUn0zG4ou54o/gn+IfjF0ti/5A== + dependencies: + "@lerna/add" "3.15.0" + "@lerna/bootstrap" "3.15.0" + "@lerna/changed" "3.15.0" + "@lerna/clean" "3.15.0" "@lerna/cli" "3.13.0" - "@lerna/create" "3.13.3" - "@lerna/diff" "3.13.3" - "@lerna/exec" "3.13.3" - "@lerna/import" "3.13.3" - "@lerna/init" "3.13.3" - "@lerna/link" "3.13.3" - "@lerna/list" "3.13.3" - "@lerna/publish" "3.13.3" - "@lerna/run" "3.13.3" - "@lerna/version" "3.13.3" + "@lerna/create" "3.15.0" + "@lerna/diff" "3.15.0" + "@lerna/exec" "3.15.0" + "@lerna/import" "3.15.0" + "@lerna/init" "3.15.0" + "@lerna/link" "3.15.0" + "@lerna/list" "3.15.0" + "@lerna/publish" "3.15.0" + "@lerna/run" "3.15.0" + "@lerna/version" "3.15.0" import-local "^1.0.0" npmlog "^4.1.2" @@ -5299,31 +5272,6 @@ levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" -libnpmaccess@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/libnpmaccess/-/libnpmaccess-3.0.1.tgz#5b3a9de621f293d425191aa2e779102f84167fa8" - integrity sha512-RlZ7PNarCBt+XbnP7R6PoVgOq9t+kou5rvhaInoNibhPO7eMlRfS0B8yjatgn2yaHIwWNyoJDolC/6Lc5L/IQA== - dependencies: - aproba "^2.0.0" - get-stream "^4.0.0" - npm-package-arg "^6.1.0" - npm-registry-fetch "^3.8.0" - -libnpmpublish@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/libnpmpublish/-/libnpmpublish-1.1.1.tgz#ff0c6bb0b4ad2bda2ad1f5fba6760a4af37125f0" - integrity sha512-nefbvJd/wY38zdt+b9SHL6171vqBrMtZ56Gsgfd0duEKb/pB8rDT4/ObUQLrHz1tOfht1flt2zM+UGaemzAG5g== - dependencies: - aproba "^2.0.0" - figgy-pudding "^3.5.1" - get-stream "^4.0.0" - lodash.clonedeep "^4.5.0" - normalize-package-data "^2.4.0" - npm-package-arg "^6.1.0" - npm-registry-fetch "^3.8.0" - semver "^5.5.1" - ssri "^6.0.1" - load-json-file@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" @@ -5346,11 +5294,11 @@ load-json-file@^4.0.0: strip-bom "^3.0.0" loader-runner@^2.3.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.3.1.tgz#026f12fe7c3115992896ac02ba022ba92971b979" - integrity sha512-By6ZFY7ETWOc9RFaAIb23IjJVcM4dvJC/N57nmdz9RSkMXvAXGI7SyVlAw3v8vjtDRlqThgVDVmTnr9fqMlxkw== + version "2.4.0" + resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357" + integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw== -loader-utils@^1.0.2, loader-utils@^1.1.0: +loader-utils@^1.0.2, loader-utils@^1.1.0, loader-utils@^1.2.2, loader-utils@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.2.3.tgz#1ff5dc6911c9f0a062531a4c04b609406108c2c7" integrity sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA== @@ -5390,11 +5338,6 @@ lodash.clonedeep@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8= -lodash.debounce@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" - integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= - lodash.flattendeep@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz#fb030917f86a3134e5bc9bec0d69e0013ddfedb2" @@ -5405,6 +5348,11 @@ lodash.get@^4.4.2: resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= +lodash.ismatch@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz#756cb5150ca3ba6f11085a78849645f188f85f37" + integrity sha1-dWy1FQyjum8RCFp4hJZF8Yj4Xzc= + lodash.memoize@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" @@ -5467,7 +5415,7 @@ loud-rejection@^1.0.0: currently-unhandled "^0.4.1" signal-exit "^3.0.0" -lru-cache@^4.0.1, lru-cache@^4.1.2, lru-cache@^4.1.3: +lru-cache@^4.0.1, lru-cache@^4.1.2, lru-cache@^4.1.3, lru-cache@^4.1.5: version "4.1.5" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== @@ -5482,10 +5430,10 @@ lru-cache@^5.1.1: dependencies: yallist "^3.0.2" -macos-release@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/macos-release/-/macos-release-2.2.0.tgz#ab58d55dd4714f0a05ad4b0e90f4370fef5cdea8" - integrity sha512-iV2IDxZaX8dIcM7fG6cI46uNmHUxHE4yN+Z8tKHAW1TBPMZDIKHf/3L+YnOuj/FK9il14UaVdHmiQ1tsi90ltA== +macos-release@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/macos-release/-/macos-release-2.3.0.tgz#eb1930b036c0800adebccd5f17bc4c12de8bb71f" + integrity sha512-OHhSbtcviqMPt7yfw5ef5aghS2jzFVKEFyCJndQt2YpSQ9qRVSEv2axSJI1paVThEu+FFGs584h/1YhxjVqajA== magic-string@^0.22.4: version "0.22.5" @@ -5495,11 +5443,11 @@ magic-string@^0.22.4: vlq "^0.2.2" magic-string@^0.25.1: - version "0.25.1" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.1.tgz#b1c248b399cd7485da0fe7385c2fc7011843266e" - integrity sha512-sCuTz6pYom8Rlt4ISPFn6wuFodbKMIHUMv4Qko9P17dpxb7s52KJTmRuZZqHdGmLCK9AOcDare039nRIcfdkEg== + version "0.25.2" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.2.tgz#139c3a729515ec55e96e69e82a11fe890a293ad9" + integrity sha512-iLs9mPjh9IuTtRsqqhNGYcZXGei0Nh/A4xirrsqW7c+QhKVFL2vm7U09ru6cHRD22azaP/wMDgI+HCqbETMTtg== dependencies: - sourcemap-codec "^1.4.1" + sourcemap-codec "^1.4.4" make-dir@^1.0.0: version "1.3.0" @@ -5587,13 +5535,13 @@ mdn-data@~1.1.0: integrity sha512-FSYbp3lyKjyj3E7fMl6rYvUdX0FBXaluGqlFoYESWQlyUTq8R+wp0rkFxoYFqZlHCvsUXGjyJmLQSnXToYhOSA== mem@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/mem/-/mem-4.0.0.tgz#6437690d9471678f6cc83659c00cbafcd6b0cdaf" - integrity sha512-WQxG/5xYc3tMbYLXoXPm81ET2WDULiU5FxbuIoNbJqLOOI8zehXFdZuiUEgfdrU2mVB1pxBZUGlYORSrpuJreA== + version "4.3.0" + resolved "https://registry.yarnpkg.com/mem/-/mem-4.3.0.tgz#461af497bc4ae09608cdb2e60eefb69bff744178" + integrity sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w== dependencies: map-age-cleaner "^0.1.1" - mimic-fn "^1.0.0" - p-is-promise "^1.1.0" + mimic-fn "^2.0.0" + p-is-promise "^2.0.0" memory-fs@^0.4.0, memory-fs@~0.4.1: version "0.4.1" @@ -5672,6 +5620,14 @@ micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4, micromatch@^3.1.8: snapdragon "^0.8.1" to-regex "^3.0.2" +micromatch@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259" + integrity sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q== + dependencies: + braces "^3.0.1" + picomatch "^2.0.5" + miller-rabin@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" @@ -5680,28 +5636,33 @@ miller-rabin@^4.0.0: bn.js "^4.0.0" brorand "^1.0.1" -mime-db@~1.37.0: - version "1.37.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.37.0.tgz#0b6a0ce6fdbe9576e25f1f2d2fde8830dc0ad0d8" - integrity sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg== +mime-db@1.40.0: + version "1.40.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.40.0.tgz#a65057e998db090f732a68f6c276d387d4126c32" + integrity sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA== mime-types@^2.1.12, mime-types@~2.1.19: - version "2.1.21" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.21.tgz#28995aa1ecb770742fe6ae7e58f9181c744b3f96" - integrity sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg== + version "2.1.24" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.24.tgz#b6f8d0b3e951efb77dedeca194cff6d16f676f81" + integrity sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ== dependencies: - mime-db "~1.37.0" + mime-db "1.40.0" -mime@1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" - integrity sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ== +mime@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== mimic-fn@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== +mimic-fn@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" @@ -5742,7 +5703,7 @@ minimist@~0.0.1: resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" integrity sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8= -minipass@^2.2.1, minipass@^2.3.4, minipass@^2.3.5: +minipass@^2.2.1, minipass@^2.3.5: version "2.3.5" resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.5.tgz#cacebe492022497f656b0f0f51e2682a9ed2d848" integrity sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA== @@ -5750,7 +5711,7 @@ minipass@^2.2.1, minipass@^2.3.4, minipass@^2.3.5: safe-buffer "^5.1.2" yallist "^3.0.0" -minizlib@^1.1.1: +minizlib@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.2.1.tgz#dd27ea6136243c7c880684e8672bb3a45fd9b614" integrity sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA== @@ -5781,7 +5742,7 @@ mixin-deep@^1.2.0: for-in "^1.0.2" is-extendable "^1.0.1" -mkdirp@0.5.1, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1: +mkdirp@0.5.1, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= @@ -5839,11 +5800,16 @@ ms@2.0.0: resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= -ms@2.1.1, ms@^2.0.0, ms@^2.1.1: +ms@2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== +ms@^2.0.0, ms@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + multimatch@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-2.1.0.tgz#9c7906a22fb4c02919e2f5f75161b4cdbd4b2a2b" @@ -5864,10 +5830,10 @@ mute-stream@~0.0.4: resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== -nan@^2.9.2: - version "2.12.1" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.12.1.tgz#7b1aa193e9aa86057e3c7bbd0ac448e770925552" - integrity sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw== +nan@^2.12.1: + version "2.14.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" + integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg== nanomatch@^1.2.9: version "1.2.13" @@ -5887,18 +5853,18 @@ nanomatch@^1.2.9: to-regex "^3.0.1" needle@^2.2.1: - version "2.2.4" - resolved "https://registry.yarnpkg.com/needle/-/needle-2.2.4.tgz#51931bff82533b1928b7d1d69e01f1b00ffd2a4e" - integrity sha512-HyoqEb4wr/rsoaIDfTH2aVL9nWtQqba2/HvMv+++m8u0dz808MaagKILxtfeSN7QU7nvbQ79zk3vYOJp9zsNEA== + version "2.4.0" + resolved "https://registry.yarnpkg.com/needle/-/needle-2.4.0.tgz#6833e74975c444642590e15a750288c5f939b57c" + integrity sha512-4Hnwzr3mi5L97hMYeNl8wRW/Onhy4nUKR/lVemJ8gJedxxUyBLm9kkrDColJvoSfwi0jCNhD+xCdOtiGDQiRZg== dependencies: - debug "^2.1.2" + debug "^3.2.6" iconv-lite "^0.4.4" sax "^1.2.4" neo-async@^2.5.0, neo-async@^2.6.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.0.tgz#b9d15e4d71c6762908654b5183ed38b753340835" - integrity sha512-MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA== + version "2.6.1" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c" + integrity sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw== nested-error-stacks@^2.0.0: version "2.1.0" @@ -5911,9 +5877,9 @@ nice-try@^1.0.4: integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== node-addon-api@^1.6.0: - version "1.6.2" - resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-1.6.2.tgz#d8aad9781a5cfc4132cc2fecdbdd982534265217" - integrity sha512-479Bjw9nTE5DdBSZZWprFryHGjUaQC31y1wHo19We/k0BZlrmhqQitWoUL0cD8+scljCbIUL+E58oRDEakdGGA== + version "1.6.3" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-1.6.3.tgz#3998d4593e2dca2ea82114670a4eb003386a9fe1" + integrity sha512-FXWH6mqjWgU8ewuahp4spec8LkroFZK2NicOv6bNwZC3kcwZUI8LeZdG80UzTSLLhK4T7MsgNwlYDVRlDdfTDg== node-environment-flags@1.0.5: version "1.0.5" @@ -5932,22 +5898,21 @@ node-fetch-npm@^2.0.2: json-parse-better-errors "^1.0.0" safe-buffer "^5.1.1" -node-fetch@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.3.0.tgz#1a1d940bbfb916a1d3e0219f037e89e71f8c5fa5" - integrity sha512-MOd8pV3fxENbryESLgVIeaGKrdl+uaYhCSSVkjeOb/31/njTpcis5aWfdqgNlHIrKOLRbMnfPINPOML2CIFeXA== +node-fetch@^2.3.0, node-fetch@^2.5.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd" + integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA== node-forge@^0.7.1: version "0.7.6" resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.7.6.tgz#fdf3b418aee1f94f0ef642cd63486c77ca9724ac" integrity sha512-sol30LUpz1jQFBjOKwbjxijiE3b6pjd74YwfD0fJOKPjF+fONKb2Yg8rYgS6+bK6VDl+/wfr4IYpC7jDzLUIfw== -node-gyp@^3.8.0: - version "3.8.0" - resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-3.8.0.tgz#540304261c330e80d0d5edce253a68cb3964218c" - integrity sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA== +node-gyp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-4.0.0.tgz#972654af4e5dd0cd2a19081b4b46fe0442ba6f45" + integrity sha512-2XiryJ8sICNo6ej8d0idXDEMKfVfFK7kekGCtJAuelGsYHQxhj13KTf95swTCN2dZ/4lTfZ84Fu31jqJEEgjWA== dependencies: - fstream "^1.0.0" glob "^7.0.3" graceful-fs "^4.1.2" mkdirp "^0.5.0" @@ -5957,13 +5922,13 @@ node-gyp@^3.8.0: request "^2.87.0" rimraf "2" semver "~5.3.0" - tar "^2.0.0" + tar "^4.4.8" which "1" node-libs-browser@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.1.0.tgz#5f94263d404f6e44767d726901fff05478d600df" - integrity sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg== + version "2.2.1" + resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425" + integrity sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q== dependencies: assert "^1.1.1" browserify-zlib "^0.2.0" @@ -5972,10 +5937,10 @@ node-libs-browser@^2.0.0: constants-browserify "^1.0.0" crypto-browserify "^3.11.0" domain-browser "^1.1.1" - events "^1.0.0" + events "^3.0.0" https-browserify "^1.0.0" os-browserify "^0.3.0" - path-browserify "0.0.0" + path-browserify "0.0.1" process "^0.11.10" punycode "^1.2.4" querystring-es3 "^0.2.0" @@ -5986,13 +5951,13 @@ node-libs-browser@^2.0.0: timers-browserify "^2.0.4" tty-browserify "0.0.0" url "^0.11.0" - util "^0.10.3" - vm-browserify "0.0.4" + util "^0.11.0" + vm-browserify "^1.0.1" -node-pre-gyp@^0.10.0: - version "0.10.3" - resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.10.3.tgz#3070040716afdc778747b61b6887bf78880b80fc" - integrity sha512-d1xFs+C/IPS8Id0qPTZ4bUT8wWryfR/OzzAFxweG+uLN85oPzyo2Iw6bVlLQ/JOdgNonXLCoRyqDzDWq4iw72A== +node-pre-gyp@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.12.0.tgz#39ba4bb1439da030295f899e3b520b7785766149" + integrity sha512-4KghwV8vH5k+g2ylT+sLTjy5wmUOb9vPhnM8NHvRf9dHmnW/CndrFXy2aRPaPST6dugXSdHXfeaHQm77PIz/1A== dependencies: detect-libc "^1.0.2" mkdirp "^0.5.1" @@ -6005,10 +5970,10 @@ node-pre-gyp@^0.10.0: semver "^5.3.0" tar "^4" -node-releases@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.3.tgz#aad9ce0dcb98129c753f772c0aa01360fb90fbd2" - integrity sha512-6VrvH7z6jqqNFY200kdB6HdzkgM96Oaj9v3dqGfgp6mF+cHmU4wyQKZ2/WPDRVoR0Jz9KqbamaBN0ZhdUaysUQ== +node-releases@^1.1.23: + version "1.1.23" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.23.tgz#de7409f72de044a2fa59c097f436ba89c39997f0" + integrity sha512-uq1iL79YjfYC0WXoHbC/z28q/9pOl8kSHaXdWmAAc8No+bDwqkZbzIJz55g/MUsPgSGm9LZ7QSUbzTcH5tz47w== dependencies: semver "^5.3.0" @@ -6033,12 +5998,12 @@ normalize-html-whitespace@^0.2.0: integrity sha1-EBci9kI1Ucdc24+dEE/4UNrx4Q4= normalize-package-data@^2.0.0, normalize-package-data@^2.3.0, normalize-package-data@^2.3.2, normalize-package-data@^2.3.4, normalize-package-data@^2.3.5, normalize-package-data@^2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f" - integrity sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw== + version "2.5.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" + integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== dependencies: hosted-git-info "^2.1.4" - is-builtin-module "^1.0.0" + resolve "^1.10.0" semver "2 || 3 || 4 || 5" validate-npm-package-license "^3.0.1" @@ -6049,24 +6014,29 @@ normalize-path@^2.1.1: dependencies: remove-trailing-separator "^1.0.1" +normalize-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + normalize-url@^3.0.0, normalize-url@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559" integrity sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg== npm-bundled@^1.0.1: - version "1.0.5" - resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.5.tgz#3c1732b7ba936b3a10325aef616467c0ccbcc979" - integrity sha512-m/e6jgWu8/v5niCUKQi9qQl8QdeEduFA96xHDDzFGqly0OOjI7c+60KM/2sppfnUU9JJagf+zs+yGhqSOFj71g== + version "1.0.6" + resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.6.tgz#e7ba9aadcef962bb61248f91721cd932b3fe6bdd" + integrity sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g== -npm-lifecycle@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/npm-lifecycle/-/npm-lifecycle-2.1.0.tgz#1eda2eedb82db929e3a0c50341ab0aad140ed569" - integrity sha512-QbBfLlGBKsktwBZLj6AviHC6Q9Y3R/AY4a2PYSIRhSKSS0/CxRyD/PfxEX6tPeOCXQgMSNdwGeECacstgptc+g== +npm-lifecycle@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/npm-lifecycle/-/npm-lifecycle-2.1.1.tgz#0027c09646f0fd346c5c93377bdaba59c6748fdf" + integrity sha512-+Vg6I60Z75V/09pdcH5iUo/99Q/vop35PaI99elvxk56azSVVsdsSsS/sXqKDNwbRRNN1qSxkcO45ZOu0yOWew== dependencies: byline "^5.0.0" - graceful-fs "^4.1.11" - node-gyp "^3.8.0" + graceful-fs "^4.1.15" + node-gyp "^4.0.0" resolve-from "^4.0.0" slide "^1.1.6" uid-number "0.0.6" @@ -6083,15 +6053,7 @@ npm-lifecycle@^2.1.0: semver "^5.5.0" validate-npm-package-name "^3.0.0" -npm-packlist@^1.1.12, npm-packlist@^1.1.6: - version "1.2.0" - resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.2.0.tgz#55a60e793e272f00862c7089274439a4cc31fc7f" - integrity sha512-7Mni4Z8Xkx0/oegoqlcao/JpPCPEMtUvsmB0q7mgvlMinykJLSRTYuFqoQLYgGY8biuxIeiHO+QNJKbCfljewQ== - dependencies: - ignore-walk "^3.0.1" - npm-bundled "^1.0.1" - -npm-packlist@^1.4.1: +npm-packlist@^1.1.12, npm-packlist@^1.1.6, npm-packlist@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.1.tgz#19064cdf988da80ea3cee45533879d90192bbfbc" integrity sha512-+TcdO7HJJ8peiiYhvPxsEDhF3PJFGUGRcFsGve3vxvxdcpO2Z4Z7rkosRM0kWj6LfbK/P0gu3dzk5RU1ffvFcw== @@ -6108,30 +6070,6 @@ npm-pick-manifest@^2.2.3: npm-package-arg "^6.0.0" semver "^5.4.1" -npm-registry-fetch@^3.8.0: - version "3.8.0" - resolved "https://registry.yarnpkg.com/npm-registry-fetch/-/npm-registry-fetch-3.8.0.tgz#aa7d9a7c92aff94f48dba0984bdef4bd131c88cc" - integrity sha512-hrw8UMD+Nob3Kl3h8Z/YjmKamb1gf7D1ZZch2otrIXM3uFLB5vjEY6DhMlq80z/zZet6eETLbOXcuQudCB3Zpw== - dependencies: - JSONStream "^1.3.4" - bluebird "^3.5.1" - figgy-pudding "^3.4.1" - lru-cache "^4.1.3" - make-fetch-happen "^4.0.1" - npm-package-arg "^6.1.0" - -npm-registry-fetch@^3.9.0: - version "3.9.0" - resolved "https://registry.yarnpkg.com/npm-registry-fetch/-/npm-registry-fetch-3.9.0.tgz#44d841780e2833f06accb34488f8c7450d1a6856" - integrity sha512-srwmt8YhNajAoSAaDWndmZgx89lJwIZ1GWxOuckH4Coek4uHv5S+o/l9FLQe/awA+JwTnj4FJHldxhlXdZEBmw== - dependencies: - JSONStream "^1.3.4" - bluebird "^3.5.1" - figgy-pudding "^3.4.1" - lru-cache "^4.1.3" - make-fetch-happen "^4.0.1" - npm-package-arg "^6.1.0" - npm-run-path@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" @@ -6162,14 +6100,14 @@ number-is-nan@^1.0.0: integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= nwsapi@^2.0.7: - version "2.1.1" - resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.1.1.tgz#08d6d75e69fd791bdea31507ffafe8c843b67e9c" - integrity sha512-T5GaA1J/d34AC8mkrFD2O0DR17kwJ702ZOtJOsS8RpbsQZVOC2/xYFb1i/cw+xdM54JIlMuojjDOYct8GIWtwg== + version "2.1.4" + resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.1.4.tgz#e006a878db23636f8e8a67d33ca0e4edf61a842f" + integrity sha512-iGfd9Y6SFdTNldEy2L0GUhcarIutFmk+MPWIn9dmj8NMIup03G08uUF2KGbbmv/Ux4RT0VZJoP/sVbWA6d/VIw== nyc@^14.0.0: - version "14.0.0" - resolved "https://registry.yarnpkg.com/nyc/-/nyc-14.0.0.tgz#f9fc4b4d73afc976f76e72352e70f742bbfab829" - integrity sha512-R1zC6UZak6pzn5BZQorkSH5GdOGafrwyeja+eimS5Tu+KJ/hCgBc8qA1QWSzxQmT2FDl2lbpqPw7tBDbSvhAHg== + version "14.1.1" + resolved "https://registry.yarnpkg.com/nyc/-/nyc-14.1.1.tgz#151d64a6a9f9f5908a1b73233931e4a0a3075eeb" + integrity sha512-OI0vm6ZGUnoGZv/tLdZ2esSVzDwUC88SNs+6JoSOMVxA+gKMB8Tk7jBwgemLx4O40lhhvZCVw1C+OYLOBOPXWw== dependencies: archy "^1.0.0" caching-transform "^3.0.2" @@ -6179,19 +6117,20 @@ nyc@^14.0.0: find-up "^3.0.0" foreground-child "^1.5.6" glob "^7.1.3" - istanbul-lib-coverage "^2.0.4" - istanbul-lib-hook "^2.0.6" - istanbul-lib-instrument "^3.2.0" - istanbul-lib-report "^2.0.7" - istanbul-lib-source-maps "^3.0.5" - istanbul-reports "^2.2.2" + istanbul-lib-coverage "^2.0.5" + istanbul-lib-hook "^2.0.7" + istanbul-lib-instrument "^3.3.0" + istanbul-lib-report "^2.0.8" + istanbul-lib-source-maps "^3.0.6" + istanbul-reports "^2.2.4" + js-yaml "^3.13.1" make-dir "^2.1.0" merge-source-map "^1.1.0" resolve-from "^4.0.0" rimraf "^2.6.3" signal-exit "^3.0.2" spawn-wrap "^1.4.2" - test-exclude "^5.2.2" + test-exclude "^5.2.3" uuid "^3.3.2" yargs "^13.2.2" yargs-parser "^13.0.0" @@ -6220,15 +6159,10 @@ object-inspect@~1.4.0: resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.4.1.tgz#37ffb10e71adaf3748d05f713b4c9452f402cbc4" integrity sha512-wqdhLpfCUbEsoEwl3FXwGyv8ief1k/1aUdIPCqVnupM6e8l63BEJdiF/0swtn04/8p05tG/T0FrpTlfwvljOdw== -object-keys@^1.0.11: - version "1.1.0" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.0.tgz#11bd22348dd2e096a045ab06f6c85bcc340fa032" - integrity sha512-6OO5X1+2tYkNyNEx6TsCxEqFfRWaqx6EtMiSbGrw8Ob8v9Ne+Hl8rBAgLBZn5wjEz3s/s6U1WXFUFOcxxAwUpg== - -object-keys@^1.0.12, object-keys@^1.0.6: - version "1.0.12" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.12.tgz#09c53855377575310cca62f55bb334abff7b3ed2" - integrity sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag== +object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.0.6: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== object-visit@^1.0.0: version "1.0.1" @@ -6262,7 +6196,7 @@ object.pick@^1.3.0: dependencies: isobject "^3.0.1" -object.values@^1.0.4: +object.values@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.0.tgz#bf6810ef5da3e5325790eaaa2be213ea84624da9" integrity sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg== @@ -6299,9 +6233,9 @@ onetime@^2.0.0: mimic-fn "^1.0.0" opn@^5.1.0: - version "5.4.0" - resolved "https://registry.yarnpkg.com/opn/-/opn-5.4.0.tgz#cb545e7aab78562beb11aa3bfabc7042e1761035" - integrity sha512-YF9MNdVy/0qvJvDtunAOzFw9iasOQHpVthTCvGzxt61Il64AYSGdK+rYwld7NAfk9qJ7dt+hymBNSc9LNYS+Sw== + version "5.5.0" + resolved "https://registry.yarnpkg.com/opn/-/opn-5.5.0.tgz#fc7164fab56d235904c51c3b27da6758ca3b9bfc" + integrity sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA== dependencies: is-wsl "^1.1.0" @@ -6357,11 +6291,11 @@ os-locale@^3.0.0, os-locale@^3.1.0: mem "^4.0.0" os-name@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/os-name/-/os-name-3.0.0.tgz#e1434dbfddb8e74b44c98b56797d951b7648a5d9" - integrity sha512-7c74tib2FsdFbQ3W+qj8Tyd1R3Z6tuVRNNxXjJcZ4NgjIEQU9N/prVMqcW29XZPXGACqaXN3jq58/6hoaoXH6g== + version "3.1.0" + resolved "https://registry.yarnpkg.com/os-name/-/os-name-3.1.0.tgz#dec19d966296e1cd62d701a5a66ee1ddeae70801" + integrity sha512-h8L+8aNjNcMpo/mAIBPn5PXCM16iyPGjHNWo6U1YO8sJTMHtEtyczI6QJnLoplswm6goopQkqc7OAnjhWcugVg== dependencies: - macos-release "^2.0.0" + macos-release "^2.2.0" windows-release "^3.1.0" os-tmpdir@^1.0.0, os-tmpdir@~1.0.2: @@ -6387,10 +6321,10 @@ p-finally@^1.0.0: resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= -p-is-promise@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-1.1.0.tgz#9c9456989e9f6588017b0434d56097675c3da05e" - integrity sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4= +p-is-promise@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-2.1.0.tgz#918cebaea248a62cf7ffab8e3bca8c5f882fc42e" + integrity sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg== p-limit@^1.1.0: version "1.3.0" @@ -6400,9 +6334,9 @@ p-limit@^1.1.0: p-try "^1.0.0" p-limit@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.1.0.tgz#1d5a0d20fb12707c758a655f6bbc4386b5930d68" - integrity sha512-NhURkNcrVB+8hNfLuysU8enY5xn2KXphsHBaC2YmRNTZRc7RWusw6apSpdEj3jo4CMb6W9nrF6tTnsJsJeyu6g== + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.0.tgz#417c9941e6027a9abcba5092dd2904e255b5fbc2" + integrity sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ== dependencies: p-try "^2.0.0" @@ -6437,6 +6371,13 @@ p-pipe@^1.2.0: resolved "https://registry.yarnpkg.com/p-pipe/-/p-pipe-1.2.0.tgz#4b1a11399a11520a67790ee5a0c1d5881d6befe9" integrity sha1-SxoROZoRUgpneQ7loMHViB1r7+k= +p-queue@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/p-queue/-/p-queue-4.0.0.tgz#ed0eee8798927ed6f2c2f5f5b77fdb2061a5d346" + integrity sha512-3cRXXn3/O0o3+eVmUroJPSj/esxoEFIm0ZOno/T+NzG/VZgPOqQ8WKmlNqubSEpZmCIngEy34unkHGg83ZIBmg== + dependencies: + eventemitter3 "^3.1.0" + p-reduce@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-reduce/-/p-reduce-1.0.0.tgz#18c2b0dd936a4690a529f8231f58a0fdb6a47dfa" @@ -6448,9 +6389,9 @@ p-try@^1.0.0: integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= p-try@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.0.0.tgz#85080bb87c64688fa47996fe8f7dfbe8211760b1" - integrity sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ== + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== p-waterfall@^1.0.0: version "1.0.0" @@ -6469,48 +6410,15 @@ package-hash@^3.0.0: lodash.flattendeep "^4.4.0" release-zalgo "^1.0.0" -pacote@^9.5.0: - version "9.5.0" - resolved "https://registry.yarnpkg.com/pacote/-/pacote-9.5.0.tgz#85f3013a3f6dd51c108b0ccabd3de8102ddfaeda" - integrity sha512-aUplXozRbzhaJO48FaaeClmN+2Mwt741MC6M3bevIGZwdCaP7frXzbUOfOWa91FPHoLITzG0hYaKY363lxO3bg== - dependencies: - bluebird "^3.5.3" - cacache "^11.3.2" - figgy-pudding "^3.5.1" - get-stream "^4.1.0" - glob "^7.1.3" - lru-cache "^5.1.1" - make-fetch-happen "^4.0.1" - minimatch "^3.0.4" - minipass "^2.3.5" - mississippi "^3.0.0" - mkdirp "^0.5.1" - normalize-package-data "^2.4.0" - npm-package-arg "^6.1.0" - npm-packlist "^1.1.12" - npm-pick-manifest "^2.2.3" - npm-registry-fetch "^3.8.0" - osenv "^0.1.5" - promise-inflight "^1.0.1" - promise-retry "^1.1.1" - protoduck "^5.0.1" - rimraf "^2.6.2" - safe-buffer "^5.1.2" - semver "^5.6.0" - ssri "^6.0.1" - tar "^4.4.8" - unique-filename "^1.1.1" - which "^1.3.1" - pako@^0.2.5: version "0.2.9" resolved "https://registry.yarnpkg.com/pako/-/pako-0.2.9.tgz#f3f7522f4ef782348da8161bad9ecfd51bf83a75" integrity sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU= pako@~1.0.5: - version "1.0.7" - resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.7.tgz#2473439021b57f1516c82f58be7275ad8ef1bb27" - integrity sha512-3HNK5tW4x8o5mO8RuHZp3Ydw9icZXx0RANAOMzlMzx7LVXhMJ4mo3MOBpzyd7r/+RUu8BmndP47LXT+vzjtWcQ== + version "1.0.10" + resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.10.tgz#4328badb5086a426aa90f541977d4955da5c9732" + integrity sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw== parallel-transform@^1.1.0: version "1.1.0" @@ -6585,15 +6493,16 @@ parcel-bundler@^1.12.3: ws "^5.1.1" parse-asn1@^5.0.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.1.tgz#f6bf293818332bd0dab54efb16087724745e6ca8" - integrity sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw== + version "5.1.4" + resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.4.tgz#37f6628f823fbdeb2273b4d540434a22f3ef1fcc" + integrity sha512-Qs5duJcuvNExRfFZ99HDD3z4mAi3r9Wl/FOjEOijlxwCZs7E7mW2vjTpgQ4J8LpTF8x5v+1Vn5UQFejmWT11aw== dependencies: asn1.js "^4.0.0" browserify-aes "^1.0.0" create-hash "^1.1.0" evp_bytestokey "^1.0.0" pbkdf2 "^3.0.3" + safe-buffer "^5.1.1" parse-github-repo-url@^1.3.0: version "1.4.1" @@ -6643,20 +6552,20 @@ parse5@4.0.0: resolved "https://registry.yarnpkg.com/parse5/-/parse5-4.0.0.tgz#6d78656e3da8d78b4ec0b906f7c08ef1dfe3f608" integrity sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA== -parseurl@~1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3" - integrity sha1-/CidTtiZMRlGDBViUyYs3I3mW/M= +parseurl@~1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== pascalcase@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= -path-browserify@0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.0.tgz#a0b870729aae214005b7d5032ec2cbbb0fb4451a" - integrity sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo= +path-browserify@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a" + integrity sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ== path-dirname@^1.0.0: version "1.0.2" @@ -6718,9 +6627,9 @@ pbkdf2@^3.0.3: sha.js "^2.4.8" pegjs@^0.11.0-dev.325: - version "0.11.0-dev.325" - resolved "https://registry.yarnpkg.com/pegjs/-/pegjs-0.11.0-dev.325.tgz#5af06561c8b3f10ef57dcfcba89075a677af393a" - integrity sha512-7YGSJyY9YHMS16zY14sVO6zF+SRGgIGVVtK4/SerLuOOyeWz/MFlE6RB5jJRBjODM5//OsfPrPBIpQDPEMh+/A== + version "0.11.0-master.f69239d" + resolved "https://registry.yarnpkg.com/pegjs/-/pegjs-0.11.0-master.f69239d.tgz#4f6e445231cc369f9860a0999a685a79cec520ab" + integrity sha512-8PXSaXnLh9hw0R/SfOL1b8JSgiPv1KSl8B1h+sP0uwngmx3Vk+QdB2cuBAT1lXPbP5necVZ2Dl2t4DfR3KKbZg== perf-regexes@^1.0.1: version "1.0.1" @@ -6737,6 +6646,11 @@ physical-cpu-count@^2.0.0: resolved "https://registry.yarnpkg.com/physical-cpu-count/-/physical-cpu-count-2.0.0.tgz#18de2f97e4bf7a9551ad7511942b5496f7aba660" integrity sha1-GN4vl+S/epVRrXURlCtUlverpmA= +picomatch@^2.0.5: + version "2.0.7" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.0.7.tgz#514169d8c7cd0bdbeecc8a2609e34a7163de69f6" + integrity sha512-oLHIdio3tZ0qH76NybpeneBhYVj0QFTfXEFTc/B3zKQspYfYYkWYgFsmzo+4kvId/bQRcNkVeguI3y+CD22BtA== + pify@^2.0.0, pify@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" @@ -6793,7 +6707,7 @@ posix-character-classes@^0.1.0: resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= -postcss-calc@^7.0.0, postcss-calc@^7.0.1: +postcss-calc@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-7.0.1.tgz#36d77bab023b0ecbb9789d84dcb23c4941145436" integrity sha512-oXqx0m6tb4N3JGdmeMSc/i91KppbYsFZKdH0xMOqK8V1rJlzrKlTdokz8ozUXLVejydRN6u2IddxpcijRj2FqQ== @@ -6803,17 +6717,6 @@ postcss-calc@^7.0.0, postcss-calc@^7.0.1: postcss-selector-parser "^5.0.0-rc.4" postcss-value-parser "^3.3.1" -postcss-colormin@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-4.0.2.tgz#93cd1fa11280008696887db1a528048b18e7ed99" - integrity sha512-1QJc2coIehnVFsz0otges8kQLsryi4lo19WD+U5xCWvXd0uw/Z+KKYnbiNDCnO9GP+PvErPHCG0jNvWTngk9Rw== - dependencies: - browserslist "^4.0.0" - color "^3.0.0" - has "^1.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - postcss-colormin@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-4.0.3.tgz#ae060bce93ed794ac71264f08132d550956bd381" @@ -6828,17 +6731,10 @@ postcss-colormin@^4.0.3: postcss-convert-values@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-4.0.1.tgz#ca3813ed4da0f812f9d43703584e449ebe189a7f" - integrity sha512-Kisdo1y77KUC0Jmn0OXU/COOJbzM8cImvw1ZFsBgBgMgb1iL23Zs/LXRe3r+EZqM3vGYKdQ2YJVQ5VkJI+zEJQ== - dependencies: - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - -postcss-discard-comments@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-4.0.1.tgz#30697735b0c476852a7a11050eb84387a67ef55d" - integrity sha512-Ay+rZu1Sz6g8IdzRjUgG2NafSNpp2MSMOQUb+9kkzzzP+kh07fP0yNbhtFejURnyVXSX3FYy2nVNW1QTnNjgBQ== + integrity sha512-Kisdo1y77KUC0Jmn0OXU/COOJbzM8cImvw1ZFsBgBgMgb1iL23Zs/LXRe3r+EZqM3vGYKdQ2YJVQ5VkJI+zEJQ== dependencies: postcss "^7.0.0" + postcss-value-parser "^3.0.0" postcss-discard-comments@^4.0.2: version "4.0.2" @@ -6868,16 +6764,6 @@ postcss-discard-overridden@^4.0.1: dependencies: postcss "^7.0.0" -postcss-merge-longhand@^4.0.10: - version "4.0.10" - resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-4.0.10.tgz#c4d63ab57bdc054ab4067ab075d488c8c2978380" - integrity sha512-hME10s6CSjm9nlVIcO1ukR7Jr5RisTaaC1y83jWCivpuBtPohA3pZE7cGTIVSYjXvLnXozHTiVOkG4dnnl756g== - dependencies: - css-color-names "0.0.4" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - stylehacks "^4.0.0" - postcss-merge-longhand@^4.0.11: version "4.0.11" resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-4.0.11.tgz#62f49a13e4a0ee04e7b98f42bb16062ca2549e24" @@ -6888,18 +6774,6 @@ postcss-merge-longhand@^4.0.11: postcss-value-parser "^3.0.0" stylehacks "^4.0.0" -postcss-merge-rules@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-4.0.2.tgz#2be44401bf19856f27f32b8b12c0df5af1b88e74" - integrity sha512-UiuXwCCJtQy9tAIxsnurfF0mrNHKc4NnNx6NxqmzNNjXpQwLSukUxELHTRF0Rg1pAmcoKLih8PwvZbiordchag== - dependencies: - browserslist "^4.0.0" - caniuse-api "^3.0.0" - cssnano-util-same-parent "^4.0.0" - postcss "^7.0.0" - postcss-selector-parser "^3.0.0" - vendors "^1.0.0" - postcss-merge-rules@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-4.0.3.tgz#362bea4ff5a1f98e4075a713c6cb25aefef9a650" @@ -6920,16 +6794,6 @@ postcss-minify-font-values@^4.0.2: postcss "^7.0.0" postcss-value-parser "^3.0.0" -postcss-minify-gradients@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-4.0.1.tgz#6da95c6e92a809f956bb76bf0c04494953e1a7dd" - integrity sha512-pySEW3E6Ly5mHm18rekbWiAjVi/Wj8KKt2vwSfVFAWdW6wOIekgqxKxLU7vJfb107o3FDNPkaYFCxGAJBFyogA== - dependencies: - cssnano-util-get-arguments "^4.0.0" - is-color-stop "^1.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - postcss-minify-gradients@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-4.0.2.tgz#93b29c2ff5099c535eecda56c4aa6e665a663471" @@ -6940,18 +6804,6 @@ postcss-minify-gradients@^4.0.2: postcss "^7.0.0" postcss-value-parser "^3.0.0" -postcss-minify-params@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-4.0.1.tgz#5b2e2d0264dd645ef5d68f8fec0d4c38c1cf93d2" - integrity sha512-h4W0FEMEzBLxpxIVelRtMheskOKKp52ND6rJv+nBS33G1twu2tCyurYj/YtgU76+UDCvWeNs0hs8HFAWE2OUFg== - dependencies: - alphanum-sort "^1.0.0" - browserslist "^4.0.0" - cssnano-util-get-arguments "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - uniqs "^2.0.0" - postcss-minify-params@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-4.0.2.tgz#6b9cef030c11e35261f95f618c90036d680db874" @@ -6964,16 +6816,6 @@ postcss-minify-params@^4.0.2: postcss-value-parser "^3.0.0" uniqs "^2.0.0" -postcss-minify-selectors@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-4.0.1.tgz#a891c197977cc37abf60b3ea06b84248b1c1e9cd" - integrity sha512-8+plQkomve3G+CodLCgbhAKrb5lekAnLYuL1d7Nz+/7RANpBEVdgBkPNwljfSKvZ9xkkZTZITd04KP+zeJTJqg== - dependencies: - alphanum-sort "^1.0.0" - has "^1.0.0" - postcss "^7.0.0" - postcss-selector-parser "^3.0.0" - postcss-minify-selectors@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-4.0.2.tgz#e2e5eb40bfee500d0cd9243500f5f8ea4262fbd8" @@ -7022,15 +6864,6 @@ postcss-normalize-charset@^4.0.1: dependencies: postcss "^7.0.0" -postcss-normalize-display-values@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.1.tgz#d9a83d47c716e8a980f22f632c8b0458cfb48a4c" - integrity sha512-R5mC4vaDdvsrku96yXP7zak+O3Mm9Y8IslUobk7IMP+u/g+lXvcN4jngmHY5zeJnrQvE13dfAg5ViU05ZFDwdg== - dependencies: - cssnano-util-get-match "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - postcss-normalize-display-values@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.2.tgz#0dbe04a4ce9063d4667ed2be476bb830c825935a" @@ -7040,16 +6873,6 @@ postcss-normalize-display-values@^4.0.2: postcss "^7.0.0" postcss-value-parser "^3.0.0" -postcss-normalize-positions@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-4.0.1.tgz#ee2d4b67818c961964c6be09d179894b94fd6ba1" - integrity sha512-GNoOaLRBM0gvH+ZRb2vKCIujzz4aclli64MBwDuYGU2EY53LwiP7MxOZGE46UGtotrSnmarPPZ69l2S/uxdaWA== - dependencies: - cssnano-util-get-arguments "^4.0.0" - has "^1.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - postcss-normalize-positions@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-4.0.2.tgz#05f757f84f260437378368a91f8932d4b102917f" @@ -7060,16 +6883,6 @@ postcss-normalize-positions@^4.0.2: postcss "^7.0.0" postcss-value-parser "^3.0.0" -postcss-normalize-repeat-style@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.1.tgz#5293f234b94d7669a9f805495d35b82a581c50e5" - integrity sha512-fFHPGIjBUyUiswY2rd9rsFcC0t3oRta4wxE1h3lpwfQZwFeFjXFSiDtdJ7APCmHQOnUZnqYBADNRPKPwFAONgA== - dependencies: - cssnano-util-get-arguments "^4.0.0" - cssnano-util-get-match "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - postcss-normalize-repeat-style@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.2.tgz#c4ebbc289f3991a028d44751cbdd11918b17910c" @@ -7080,15 +6893,6 @@ postcss-normalize-repeat-style@^4.0.2: postcss "^7.0.0" postcss-value-parser "^3.0.0" -postcss-normalize-string@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-4.0.1.tgz#23c5030c2cc24175f66c914fa5199e2e3c10fef3" - integrity sha512-IJoexFTkAvAq5UZVxWXAGE0yLoNN/012v7TQh5nDo6imZJl2Fwgbhy3J2qnIoaDBrtUP0H7JrXlX1jjn2YcvCQ== - dependencies: - has "^1.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - postcss-normalize-string@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-4.0.2.tgz#cd44c40ab07a0c7a36dc5e99aace1eca4ec2690c" @@ -7098,15 +6902,6 @@ postcss-normalize-string@^4.0.2: postcss "^7.0.0" postcss-value-parser "^3.0.0" -postcss-normalize-timing-functions@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.1.tgz#8be83e0b9cb3ff2d1abddee032a49108f05f95d7" - integrity sha512-1nOtk7ze36+63ONWD8RCaRDYsnzorrj+Q6fxkQV+mlY5+471Qx9kspqv0O/qQNMeApg8KNrRf496zHwJ3tBZ7w== - dependencies: - cssnano-util-get-match "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - postcss-normalize-timing-functions@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.2.tgz#8e009ca2a3949cdaf8ad23e6b6ab99cb5e7d28d9" @@ -7135,14 +6930,6 @@ postcss-normalize-url@^4.0.1: postcss "^7.0.0" postcss-value-parser "^3.0.0" -postcss-normalize-whitespace@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-4.0.1.tgz#d14cb639b61238418ac8bc8d3b7bdd65fc86575e" - integrity sha512-U8MBODMB2L+nStzOk6VvWWjZgi5kQNShCyjRhMT3s+W9Jw93yIjOnrEkKYD3Ul7ChWbEcjDWmXq0qOL9MIAnAw== - dependencies: - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - postcss-normalize-whitespace@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-4.0.2.tgz#bf1d4070fe4fcea87d1348e825d8cc0c5faa7d82" @@ -7151,15 +6938,6 @@ postcss-normalize-whitespace@^4.0.2: postcss "^7.0.0" postcss-value-parser "^3.0.0" -postcss-ordered-values@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-4.1.1.tgz#2e3b432ef3e489b18333aeca1f1295eb89be9fc2" - integrity sha512-PeJiLgJWPzkVF8JuKSBcylaU+hDJ/TX3zqAMIjlghgn1JBi6QwQaDZoDIlqWRcCAI8SxKrt3FCPSRmOgKRB97Q== - dependencies: - cssnano-util-get-arguments "^4.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - postcss-ordered-values@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-4.1.2.tgz#0cf75c820ec7d5c4d280189559e0b571ebac0eee" @@ -7169,16 +6947,6 @@ postcss-ordered-values@^4.1.2: postcss "^7.0.0" postcss-value-parser "^3.0.0" -postcss-reduce-initial@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-4.0.2.tgz#bac8e325d67510ee01fa460676dc8ea9e3b40f15" - integrity sha512-epUiC39NonKUKG+P3eAOKKZtm5OtAtQJL7Ye0CBN1f+UQTHzqotudp+hki7zxXm7tT0ZAKDMBj1uihpPjP25ug== - dependencies: - browserslist "^4.0.0" - caniuse-api "^3.0.0" - has "^1.0.0" - postcss "^7.0.0" - postcss-reduce-initial@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-4.0.3.tgz#7fd42ebea5e9c814609639e2c2e84ae270ba48df" @@ -7189,16 +6957,6 @@ postcss-reduce-initial@^4.0.3: has "^1.0.0" postcss "^7.0.0" -postcss-reduce-transforms@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.1.tgz#8600d5553bdd3ad640f43bff81eb52f8760d4561" - integrity sha512-sZVr3QlGs0pjh6JAIe6DzWvBaqYw05V1t3d9Tp+VnFRT5j+rsqoWsysh/iSD7YNsULjq9IAylCznIwVd5oU/zA== - dependencies: - cssnano-util-get-match "^4.0.0" - has "^1.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - postcss-reduce-transforms@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.2.tgz#17efa405eacc6e07be3414a5ca2d1074681d4e29" @@ -7227,16 +6985,6 @@ postcss-selector-parser@^5.0.0-rc.4: indexes-of "^1.0.1" uniq "^1.0.1" -postcss-svgo@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-4.0.1.tgz#5628cdb38f015de6b588ce6d0bf0724b492b581d" - integrity sha512-YD5uIk5NDRySy0hcI+ZJHwqemv2WiqqzDgtvgMzO8EGSkK5aONyX8HMVFRFJSdO8wUWTuisUFn/d7yRRbBr5Qw== - dependencies: - is-svg "^3.0.0" - postcss "^7.0.0" - postcss-value-parser "^3.0.0" - svgo "^1.0.0" - postcss-svgo@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-4.0.2.tgz#17b997bc711b333bab143aaed3b8d3d6e3d38258" @@ -7279,34 +7027,16 @@ postcss@^6.0.1, postcss@^6.0.14: source-map "^0.6.1" supports-color "^5.4.0" -postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.5: - version "7.0.7" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.7.tgz#2754d073f77acb4ef08f1235c36c5721a7201614" - integrity sha512-HThWSJEPkupqew2fnuQMEI2YcTj/8gMV3n80cMdJsKxfIh5tHf7nM5JigNX6LxVMqo6zkgQNAI88hyFvBk41Pg== - dependencies: - chalk "^2.4.1" - source-map "^0.6.1" - supports-color "^5.5.0" - -postcss@^7.0.11: - version "7.0.14" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.14.tgz#4527ed6b1ca0d82c53ce5ec1a2041c2346bbd6e5" - integrity sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg== +postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.11, postcss@^7.0.5: + version "7.0.17" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.17.tgz#4da1bdff5322d4a0acaab4d87f3e782436bad31f" + integrity sha512-546ZowA+KZ3OasvQZHsbuEpysvwTZNGJv9EfyCQdsIDltPSWHAeTQ5fQy/Npi2ZDtLI3zs7Ps/p6wThErhm9fQ== dependencies: chalk "^2.4.2" source-map "^0.6.1" supports-color "^6.1.0" -posthtml-parser@^0.3.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/posthtml-parser/-/posthtml-parser-0.3.3.tgz#3fe986fca9f00c0f109d731ba590b192f26e776d" - integrity sha512-H/Z/yXGwl49A7hYQLV1iQ3h87NE0aZ/PMZhFwhw3lKeCAN+Ti4idrHvVvh4/GX10I7u77aQw+QB4vV5/Lzvv5A== - dependencies: - htmlparser2 "^3.9.2" - isobject "^2.1.0" - object-assign "^4.1.1" - -posthtml-parser@^0.4.0: +posthtml-parser@^0.4.0, posthtml-parser@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/posthtml-parser/-/posthtml-parser-0.4.1.tgz#95b78fef766fbbe0a6f861b6e95582bc3d1ff933" integrity sha512-h7vXIQ21Ikz2w5wPClPakNP6mJeJCK6BT0GpqnQrNNABdR7/TchNlFyryL1Bz6Ww53YWCKkr6tdZuHlxY1AVdQ== @@ -7314,25 +7044,29 @@ posthtml-parser@^0.4.0: htmlparser2 "^3.9.2" object-assign "^4.1.1" -posthtml-render@^1.1.0, posthtml-render@^1.1.3, posthtml-render@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/posthtml-render/-/posthtml-render-1.1.4.tgz#95dac09892f4f183fad5ac823f08f42c0256551e" - integrity sha512-jL6eFIzoN3xUEvbo33OAkSDE2VIKU4JQ1wENOows1DpfnrdapR/K3Q1/fB43Mq7wQlcSgRm23nFrvoioufM7eA== +posthtml-render@^1.1.3, posthtml-render@^1.1.4, posthtml-render@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/posthtml-render/-/posthtml-render-1.1.5.tgz#387934e85438a3de77085fbc7d264efb00bd0e0f" + integrity sha512-yvt54j0zCBHQVEFAuR+yHld8CZrCa/E1Z/OcFNCV1IEWTLVxT8O7nYnM4IIw1CD4r8kaRd3lc42+0lgCKgm87w== posthtml@^0.11.2, posthtml@^0.11.3: - version "0.11.3" - resolved "https://registry.yarnpkg.com/posthtml/-/posthtml-0.11.3.tgz#17ea2921b0555b7455f33c977bd16d8b8cb74f27" - integrity sha512-quMHnDckt2DQ9lRi6bYLnuyBDnVzK+McHa8+ar4kTdYbWEo/92hREOu3h70ZirudOOp/my2b3r0m5YtxY52yrA== + version "0.11.4" + resolved "https://registry.yarnpkg.com/posthtml/-/posthtml-0.11.4.tgz#26784d005d57d7aea93ab06dda899d59bdf186c7" + integrity sha512-ezlzBkoPoRgh0jkmT1dsM8eT+lr2azyZ546kbda8oHnVnzvyaB3Ywo6UxUz8wPSOkFAAflCxZJhvvpQH1F6qcA== dependencies: - object-assign "^4.1.1" - posthtml-parser "^0.3.3" - posthtml-render "^1.1.0" + posthtml-parser "^0.4.1" + posthtml-render "^1.1.5" prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= +prettier@^1.17.0: + version "1.18.2" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.18.2.tgz#6823e7c5900017b4bd3acf46fe9ac4b4d7bda9ea" + integrity sha512-OeHeMc0JhFE9idD4ZdtNibzY0+TPHSpSSb9h8FqtP+YnoZZ1sl8Vc9b1sasjfymH3SonAF4QcA2+mzHPhMvIiw== + private@^0.1.6: version "0.1.8" resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" @@ -7401,9 +7135,9 @@ pseudomap@^1.0.2: integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= psl@^1.1.24, psl@^1.1.28: - version "1.1.31" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.31.tgz#e9aa86d0101b5b105cbe93ac6b784cd547276184" - integrity sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw== + version "1.1.32" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.32.tgz#3f132717cf2f9c169724b2b6caf373cf694198db" + integrity sha512-MHACAkHpihU/REGGPLj4sEfc/XKW2bheigvHO1dUqjaKigMp1C8+WLQYRGgeKFMsw5PMfegZcaN8IDXK/cD0+g== public-encrypt@^4.0.0: version "4.0.3" @@ -7492,9 +7226,9 @@ quote-stream@^1.0.1, quote-stream@~1.0.2: through2 "^2.0.0" randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: - version "2.0.6" - resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.0.6.tgz#d302c522948588848a8d300c932b44c24231da80" - integrity sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A== + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== dependencies: safe-buffer "^5.1.0" @@ -7506,10 +7240,10 @@ randomfill@^1.0.3: randombytes "^2.0.5" safe-buffer "^5.1.0" -range-parser@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" - integrity sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4= +range-parser@~1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" + integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== rc@^1.2.7: version "1.2.8" @@ -7541,9 +7275,9 @@ read-cmd-shim@^1.0.1: graceful-fs "^4.1.2" read-package-tree@^5.1.6: - version "5.2.1" - resolved "https://registry.yarnpkg.com/read-package-tree/-/read-package-tree-5.2.1.tgz#6218b187d6fac82289ce4387bbbaf8eef536ad63" - integrity sha512-2CNoRoh95LxY47LvqrehIAfUVda2JbuFE/HaGYs42bNrGG+ojbw1h3zOcPcQ+1GQ3+rkzNndZn85u1XyZ3UsIA== + version "5.2.2" + resolved "https://registry.yarnpkg.com/read-package-tree/-/read-package-tree-5.2.2.tgz#4b6a0ef2d943c1ea36a578214c9a7f6b7424f7a8" + integrity sha512-rW3XWUUkhdKmN2JKB4FL563YAgtINifso5KShykufR03nJ5loGFlkUMe1g/yxmqX073SoYYTsgXu7XdDinKZuA== dependencies: debuglog "^1.0.1" dezalgo "^1.0.0" @@ -7600,7 +7334,7 @@ read@1, read@~1.0.1: dependencies: mute-stream "~0.0.4" -"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.3, readable-stream@~2.3.6: +"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.3, readable-stream@~2.3.6: version "2.3.6" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== @@ -7613,10 +7347,10 @@ read@1, read@~1.0.1: string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@^3.0.6: - version "3.1.1" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.1.1.tgz#ed6bbc6c5ba58b090039ff18ce670515795aeb06" - integrity sha512-DkN66hPyqDhnIQ6Jcsvx9bFjhw214O4poMBcIMgPVpQvNy9a0e0Uhg5SqySyDKAmUlwt8LonTBz1ezOnM8pUdA== +"readable-stream@2 || 3", readable-stream@^3.0.2, readable-stream@^3.1.1: + version "3.4.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.4.0.tgz#a51c26754658e0a3c21dbf59163bd45ba6f447fc" + integrity sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ== dependencies: inherits "^2.0.3" string_decoder "^1.1.1" @@ -7632,7 +7366,7 @@ readdir-scoped-modules@^1.0.0: graceful-fs "^4.1.2" once "^1.3.0" -readdirp@^2.0.0: +readdirp@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== @@ -7664,10 +7398,10 @@ redent@^2.0.0: indent-string "^3.0.0" strip-indent "^2.0.0" -regenerate-unicode-properties@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-7.0.0.tgz#107405afcc4a190ec5ed450ecaa00ed0cafa7a4c" - integrity sha512-s5NGghCE4itSlUS+0WUj88G6cfMVMmH8boTPNvABf8od+2dhT9WDlWu8n01raQAJZMOK8Ch6jSexaRO7swd6aw== +regenerate-unicode-properties@^8.0.2: + version "8.1.0" + resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz#ef51e0f0ea4ad424b77bf7cb41f3e015c70a3f0e" + integrity sha512-LGZzkgtLY79GeXLm8Dp0BVLdQlWICzBnJz/ipWUgo59qBaZ+BHtq51P2q1uVZlppMuUAT37SDk39qUbjTWB7bA== dependencies: regenerate "^1.4.0" @@ -7686,10 +7420,10 @@ regenerator-runtime@^0.12.0: resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz#fa1a71544764c036f8c49b13a08b2594c9f8a0de" integrity sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg== -regenerator-transform@^0.13.4: - version "0.13.4" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.13.4.tgz#18f6763cf1382c69c36df76c6ce122cc694284fb" - integrity sha512-T0QMBjK3J0MtxjPmdIMXm72Wvj2Abb0Bd4HADdfijwMdoIsyQZ6fWC7kDFhk2YinBBEMZDL7Y7wh0J1sGx3S4A== +regenerator-transform@^0.14.0: + version "0.14.0" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.0.tgz#2ca9aaf7a2c239dd32e4761218425b8c7a86ecaf" + integrity sha512-rtOelq4Cawlbmq9xuMR5gdFmv7ku/sFoB7sRiywx7aq53bc52b4j6zvH7Te1Vt/X2YveDKnCGUbioieU7FEL3w== dependencies: private "^0.1.6" @@ -7701,10 +7435,10 @@ regex-not@^1.0.0, regex-not@^1.0.2: extend-shallow "^3.0.2" safe-regex "^1.1.0" -regexp-tree@^0.1.0: - version "0.1.5" - resolved "https://registry.yarnpkg.com/regexp-tree/-/regexp-tree-0.1.5.tgz#7cd71fca17198d04b4176efd79713f2998009397" - integrity sha512-nUmxvfJyAODw+0B13hj8CFVAxhe7fDEAgJgaotBu3nnR+IgGgZq59YedJP5VYTlkEfqjuK6TuRpnymKdatLZfQ== +regexp-tree@^0.1.6: + version "0.1.10" + resolved "https://registry.yarnpkg.com/regexp-tree/-/regexp-tree-0.1.10.tgz#d837816a039c7af8a8d64d7a7c3cf6a1d93450bc" + integrity sha512-K1qVSbcedffwuIslMwpe6vGlj+ZXRnGkvjAtFHfDZZZuEdA/h0dxljAPu9vhUo6Rrx2U2AwJ+nSQ6hK+lrP5MQ== regexpu-core@^1.0.0: version "1.0.0" @@ -7715,17 +7449,17 @@ regexpu-core@^1.0.0: regjsgen "^0.2.0" regjsparser "^0.1.4" -regexpu-core@^4.1.3, regexpu-core@^4.2.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.4.0.tgz#8d43e0d1266883969720345e70c275ee0aec0d32" - integrity sha512-eDDWElbwwI3K0Lo6CqbQbA6FwgtCz4kYTarrri1okfkRLZAqstU+B3voZBCjg8Fl6iq0gXrJG6MvRgLthfvgOA== +regexpu-core@^4.5.4: + version "4.5.4" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.5.4.tgz#080d9d02289aa87fe1667a4f5136bc98a6aebaae" + integrity sha512-BtizvGtFQKGPUcTy56o3nk1bGRp4SZOTYrDtGNlqCQufptV5IkkLN6Emw+yunAJjzf+C9FQFtvq7IoA3+oMYHQ== dependencies: regenerate "^1.4.0" - regenerate-unicode-properties "^7.0.0" + regenerate-unicode-properties "^8.0.2" regjsgen "^0.5.0" regjsparser "^0.6.0" unicode-match-property-ecmascript "^1.0.4" - unicode-match-property-value-ecmascript "^1.0.2" + unicode-match-property-value-ecmascript "^1.1.0" regjsgen@^0.2.0: version "0.2.0" @@ -7867,10 +7601,10 @@ resolve-url@^0.2.1: resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= -resolve@^1.1.5, resolve@^1.1.6, resolve@^1.3.2, resolve@^1.4.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.9.0.tgz#a14c6fdfa8f92a7df1d996cb7105fa744658ea06" - integrity sha512-TZNye00tI67lwYvzxCxHGjwTNlUV70io54/Ed4j6PscB8xVfuBJpRenI/o6dVk0cY0PYTY27AgCoGGxRnYuItQ== +resolve@^1.1.5, resolve@^1.1.6, resolve@^1.10.0, resolve@^1.3.2, resolve@^1.4.0: + version "1.11.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.11.0.tgz#4014870ba296176b86343d50b60f3b50609ce232" + integrity sha512-WL2pBDjqT6pGUNSUzMw00o4T7If+z4H2x3Gz893WoUQ5KW8Vr9txp00ykiP16VBaZF5+j/OcXJHZ9+PCvdiDKw== dependencies: path-parse "^1.0.6" @@ -7926,20 +7660,19 @@ rollup-plugin-cleanup@^3.1.1: rollup-pluginutils "^2.3.3" rollup-pluginutils@^2.3.3: - version "2.5.0" - resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-2.5.0.tgz#23be0f05ac3972ea7b08fc7870cb91fde5b23a09" - integrity sha512-9Muh1H+XB5f5ONmKMayUoTYR1EZwHbwJJ9oZLrKT5yuTf/RLIQ5mYIGsrERquVucJmjmaAW0Y7+6Qo1Ep+5w3Q== + version "2.8.1" + resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-2.8.1.tgz#8fa6dd0697344938ef26c2c09d2488ce9e33ce97" + integrity sha512-J5oAoysWar6GuZo0s+3bZ6sVZAC0pfqKz68De7ZgDi5z63jOVZn1uJL/+z1jeKHNbGII8kAyHF5q8LnxSX5lQg== dependencies: - estree-walker "^0.6.0" - micromatch "^3.1.10" + estree-walker "^0.6.1" rollup@^1.10.1: - version "1.10.1" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-1.10.1.tgz#aeb763bbe98f707dc6496708db88372fa66687e7" - integrity sha512-pW353tmBE7QP622ITkGxtqF0d5gSRCVPD9xqM+fcPjudeZfoXMFW2sCzsTe2TU/zU1xamIjiS9xuFCPVT9fESw== + version "1.15.6" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-1.15.6.tgz#caf0ed28d2d78e3a59c1398e5a3695fb600a0ef0" + integrity sha512-s3Vn3QJQ5YVFfIG4nXoG9VdL1I37IZsft+4ZyeBhxE0df1kCFz9e+4bEAbR4mKH3pvBO9e9xjdxWPhhIp0r9ow== dependencies: "@types/estree" "0.0.39" - "@types/node" "^11.13.5" + "@types/node" "^12.0.8" acorn "^6.1.1" run-async@^2.2.0: @@ -7956,10 +7689,10 @@ run-queue@^1.0.0, run-queue@^1.0.3: dependencies: aproba "^1.1.1" -rxjs@^6.1.0: - version "6.3.3" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.3.3.tgz#3c6a7fa420e844a81390fb1158a9ec614f4bad55" - integrity sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw== +rxjs@^6.4.0: + version "6.5.2" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.2.tgz#2e35ce815cd46d84d02a209fb4e5921e051dbec7" + integrity sha512-HUb7j3kvb7p7eCUHE3FqjoDsC1xfZQ4AHFWfTKSpZ+sAhhz5X1WX0ZuUqWbzB2QhSLp3DoLUG+hMdEDKqWo2Zg== dependencies: tslib "^1.9.0" @@ -7981,9 +7714,9 @@ safe-regex@^1.1.0: integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== safer-eval@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/safer-eval/-/safer-eval-1.3.0.tgz#dc4fc5fe0221434c117cfc41b899fe2b33c8c20e" - integrity sha512-4qkBS8VzJatFR7F0eZfKoJyjqo43jY1jBvRhB5WXM0eJNjx9fiSmph5NApJefqKqpASKWPfaIJCJMMeWePSzfw== + version "1.3.3" + resolved "https://registry.yarnpkg.com/safer-eval/-/safer-eval-1.3.3.tgz#0309e9fcc0609e66c1b599fd0d4772132b260ca8" + integrity sha512-j/qb0rtnwTp5V1D7nR0Ns/14HU8OiHPaoZNJhM+Lfmv1nbXZCXG9LHaVW157agEocdSVAeeRNddK/yuWfalzGQ== dependencies: clones "^1.2.0" @@ -8001,30 +7734,25 @@ schema-utils@^1.0.0: ajv-errors "^1.0.0" ajv-keywords "^3.1.0" -"semver@2 || 3 || 4 || 5", "semver@2.x || 3.x || 4 || 5", semver@^5.0.1, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0: - version "5.6.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004" - integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg== - -semver@^5.7.0: +"semver@2 || 3 || 4 || 5", "semver@2.x || 3.x || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0, semver@^5.7.0: version "5.7.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b" integrity sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA== semver@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.0.0.tgz#05e359ee571e5ad7ed641a6eec1e547ba52dea65" - integrity sha512-0UewU+9rFapKFnlbirLi3byoOuhrSsli/z/ihNnvM24vgF+8sNBiI1LZPBSH9wJKUwaUbw+s3hToDLCXkrghrQ== + version "6.1.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.1.1.tgz#53f53da9b30b2103cd4f15eab3a18ecbcb210c9b" + integrity sha512-rWYq2e5iYW+fFe/oPPtYJxYgjBm8sC4rmoGdUOgBB7VnwKt6HrL793l2voH1UlsyYZpJ4g0wfjnTEO1s1NP2eQ== semver@~5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" integrity sha1-myzl094C0XxgEq0yaqa00M9U+U8= -send@0.16.2: - version "0.16.2" - resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1" - integrity sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw== +send@0.17.1: + version "0.17.1" + resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" + integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg== dependencies: debug "2.6.9" depd "~1.1.2" @@ -8033,17 +7761,17 @@ send@0.16.2: escape-html "~1.0.3" etag "~1.8.1" fresh "0.5.2" - http-errors "~1.6.2" - mime "1.4.1" - ms "2.0.0" + http-errors "~1.7.2" + mime "1.6.0" + ms "2.1.1" on-finished "~2.3.0" - range-parser "~1.2.0" - statuses "~1.4.0" + range-parser "~1.2.1" + statuses "~1.5.0" -serialize-javascript@^1.4.0: - version "1.6.1" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.6.1.tgz#4d1f697ec49429a847ca6f442a2a755126c4d879" - integrity sha512-A5MOagrPFga4YaKQSWHryl7AXvbQkEqpw4NNYMTNYUNV51bA8ABHgYFpqKx+YFFrw59xMV1qGH1R4AgoNIVgCw== +serialize-javascript@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.7.0.tgz#d6e0dfb2a3832a8c94468e6eb1db97e55a192a65" + integrity sha512-ke8UG8ulpFOxO8f8gRYabHQe/ZntKlcig2Mp+8+URDP1D8vJZ0KUt7LYo07q25Z/+JVSgpr/cui9PIp5H6/+nA== serialize-to-js@^1.1.1: version "1.2.2" @@ -8054,14 +7782,14 @@ serialize-to-js@^1.1.1: safer-eval "^1.3.0" serve-static@^1.12.4: - version "1.13.2" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.13.2.tgz#095e8472fd5b46237db50ce486a43f4b86c6cec1" - integrity sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw== + version "1.14.1" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9" + integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg== dependencies: encodeurl "~1.0.2" escape-html "~1.0.3" - parseurl "~1.3.2" - send "0.16.2" + parseurl "~1.3.3" + send "0.17.1" set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" @@ -8093,10 +7821,10 @@ setimmediate@^1.0.4: resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= -setprototypeof@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" - integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== +setprototypeof@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" + integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== sha.js@^2.4.0, sha.js@^2.4.8: version "2.4.11" @@ -8164,10 +7892,10 @@ slide@^1.1.6: resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" integrity sha1-VusCfWW00tzmyy4tMsTUr8nh1wc= -smart-buffer@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.0.1.tgz#07ea1ca8d4db24eb4cac86537d7d18995221ace3" - integrity sha512-RFqinRVJVcCAL9Uh1oVqE6FZkqsyLiVOYEZ20TqIOjuX7iFVJ+zsbs4RIghnw/pTs7mZvt8ZHhvm1ZUrR4fykg== +smart-buffer@4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.0.2.tgz#5207858c3815cc69110703c6b94e46c15634395d" + integrity sha512-JDhEpTKzXusOqXZ0BUIdH+CjFdO/CR3tLlf5CN34IypI+xMmXW1uB16OOY8z3cICbJlDAVJzNbwBhNO0wt9OAw== snapdragon-node@^2.0.1: version "2.1.1" @@ -8200,20 +7928,20 @@ snapdragon@^0.8.1: use "^3.1.0" socks-proxy-agent@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-4.0.1.tgz#5936bf8b707a993079c6f37db2091821bffa6473" - integrity sha512-Kezx6/VBguXOsEe5oU3lXYyKMi4+gva72TwJ7pQY5JfqUx2nMk7NXA6z/mpNqIlfQjWYVfeuNvQjexiTaTn6Nw== + version "4.0.2" + resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-4.0.2.tgz#3c8991f3145b2799e70e11bd5fbc8b1963116386" + integrity sha512-NT6syHhI9LmuEMSK6Kd2V7gNv5KFZoLE7V5udWmn0de+3Mkj3UMA/AJPLyeNUVmElCurSHtUdM3ETpR3z770Wg== dependencies: - agent-base "~4.2.0" - socks "~2.2.0" + agent-base "~4.2.1" + socks "~2.3.2" -socks@~2.2.0: - version "2.2.2" - resolved "https://registry.yarnpkg.com/socks/-/socks-2.2.2.tgz#f061219fc2d4d332afb4af93e865c84d3fa26e2b" - integrity sha512-g6wjBnnMOZpE0ym6e0uHSddz9p3a+WsBaaYQaBaSCJYvrC4IXykQR9MNGjLQf38e9iIIhp3b1/Zk8YZI3KGJ0Q== +socks@~2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/socks/-/socks-2.3.2.tgz#ade388e9e6d87fdb11649c15746c578922a5883e" + integrity sha512-pCpjxQgOByDHLlNqlnh/mNSAxIUkyBBuwwhTcV+enZGbDaClPvHdvm6uvOwZfFJkam7cGhBNbb4JxiP8UZkRvQ== dependencies: ip "^1.1.5" - smart-buffer "^4.0.1" + smart-buffer "4.0.2" sort-keys@^2.0.0: version "2.0.0" @@ -8239,17 +7967,9 @@ source-map-resolve@^0.5.0: urix "^0.1.0" source-map-support@~0.5.10: - version "0.5.11" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.11.tgz#efac2ce0800355d026326a0ca23e162aeac9a4e2" - integrity sha512-//sajEx/fGL3iw6fltKMdPvy8kL3kJ2O3iuYlRoT3k9Kb4BjOoZ+BZzaNHeuaruSt+Kf3Zk9tnfAQg9/AJqUVQ== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map-support@~0.5.6: - version "0.5.9" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.9.tgz#41bc953b2534267ea2d605bccfa7bfa3111ced5f" - integrity sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA== + version "0.5.12" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.12.tgz#b4f3b10d51857a5af0138d3ce8003b201613d599" + integrity sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ== dependencies: buffer-from "^1.0.0" source-map "^0.6.0" @@ -8269,7 +7989,7 @@ source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= -sourcemap-codec@^1.4.1: +sourcemap-codec@^1.4.4: version "1.4.4" resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.4.tgz#c63ea927c029dd6bd9a2b7fa03b3fec02ad56e9f" integrity sha512-CYAPYdBu34781kLHkaW3m6b/uUSyMOC2R61gcYMWooeuaGtjof86ZA/8T+qVPPt7np1085CR9hmMGrySwEc8Xg== @@ -8308,9 +8028,9 @@ spdx-expression-parse@^3.0.0: spdx-license-ids "^3.0.0" spdx-license-ids@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.3.tgz#81c0ce8f21474756148bbb5f3bfc0f36bf15d76e" - integrity sha512-uBIcIl3Ih6Phe3XHK1NqboJLdGfwr1UN3k6wSD1dZpmPsIkb8AGNbZYJ1fOBk834+Gxy8rpfDxrS6XLEMZMY2g== + version "3.0.4" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.4.tgz#75ecd1a88de8c184ef015eafb51b5b48bfd11bb1" + integrity sha512-7j8LYJLeY/Yb6ACbQ7F76qy5jHkp0U6jgBfJsk97bwWlVUnUWsAgpyaCvo17h0/RQGnQ036tVDomiwoI4pDkQA== split-string@^3.0.1, split-string@^3.0.2: version "3.1.0" @@ -8339,9 +8059,9 @@ sprintf-js@~1.0.2: integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= sshpk@^1.7.0: - version "1.16.0" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.0.tgz#1d4963a2fbffe58050aa9084ca20be81741c07de" - integrity sha512-Zhev35/y7hRMcID/upReIvRse+I9SVhyVre/KTJSJQWMz3C3+G+HpO7m1wK/yckEtujKZ7dS4hkVxAnmHaIGVQ== + version "1.16.1" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" + integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== dependencies: asn1 "~0.2.3" assert-plus "^1.0.0" @@ -8360,15 +8080,15 @@ ssri@^6.0.0, ssri@^6.0.1: dependencies: figgy-pudding "^3.5.1" -stable@~0.1.6: +stable@^0.1.8: version "0.1.8" resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== static-eval@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/static-eval/-/static-eval-2.0.0.tgz#0e821f8926847def7b4b50cda5d55c04a9b13864" - integrity sha512-6flshd3F1Gwm+Ksxq463LtFd1liC77N/PX1FVVc3OzL3hAmo2fwHFbuArkcfi7s9rTNsLEhcRmXGFZhlgy40uw== + version "2.0.2" + resolved "https://registry.yarnpkg.com/static-eval/-/static-eval-2.0.2.tgz#2d1759306b1befa688938454c546b7871f806a42" + integrity sha512-N/D219Hcr2bPjLxPiV+TQE++Tsmrady7TqAJugLy7Xk1EumfDWS/f5dtBbkRCGE7wKKXuYockQoj8Rm2/pVKyg== dependencies: escodegen "^1.8.1" @@ -8400,25 +8120,20 @@ static-module@^2.2.0: static-eval "^2.0.0" through2 "~2.0.3" -"statuses@>= 1.4.0 < 2": +"statuses@>= 1.5.0 < 2", statuses@~1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= -statuses@~1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087" - integrity sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew== - stealthy-require@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks= stream-browserify@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.1.tgz#66266ee5f9bdb9940a4e4514cafb43bb71e5c9db" - integrity sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds= + version "2.0.2" + resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b" + integrity sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg== dependencies: inherits "~2.0.1" readable-stream "^2.0.2" @@ -8464,7 +8179,7 @@ string-width@^1.0.1: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" -string-width@^3.0.0: +string-width@^3.0.0, string-width@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== @@ -8501,14 +8216,7 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" -strip-ansi@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.0.0.tgz#f78f68b5d0866c20b2c9b8c61b5298508dc8756f" - integrity sha512-Uu7gQyZI7J7gn5qLn1Np3G9vcYGTVqB+lFTytnDJv83dd8T22aGH451P3jueT2/QemInJDfxHB5Tde5OzgG1Ow== - dependencies: - ansi-regex "^4.0.0" - -strip-ansi@^5.1.0: +strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== @@ -8559,9 +8267,9 @@ strong-log-transformer@^2.0.0: through "^2.3.4" stylehacks@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-4.0.1.tgz#3186595d047ab0df813d213e51c8b94e0b9010f2" - integrity sha512-TK5zEPeD9NyC1uPIdjikzsgWxdQQN/ry1X3d1iOz1UkYDCmcr928gWD1KHgyC27F50UnE0xCTrBOO1l6KR8M4w== + version "4.0.3" + resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-4.0.3.tgz#6718fcaf4d1e07d8a1318690881e8d96726a71d5" + integrity sha512-7GlLk9JwlElY4Y6a/rmbH2MhVlTyVmiJd1PfTCqFaIBEGMYNsrO/v3SeGTdhBThLg4Z+NbOk/qFMwCa+J+3p/g== dependencies: browserslist "^4.0.0" postcss "^7.0.0" @@ -8593,7 +8301,7 @@ supports-color@^5.3.0, supports-color@^5.4.0, supports-color@^5.5.0: dependencies: has-flag "^3.0.0" -supports-color@^6.0.0, supports-color@^6.1.0: +supports-color@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ== @@ -8601,56 +8309,47 @@ supports-color@^6.0.0, supports-color@^6.1.0: has-flag "^3.0.0" svgo@^1.0.0, svgo@^1.0.5: - version "1.1.1" - resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.1.1.tgz#12384b03335bcecd85cfa5f4e3375fed671cb985" - integrity sha512-GBkJbnTuFpM4jFbiERHDWhZc/S/kpHToqmZag3aEBjPYK44JAN2QBjvrGIxLOoCyMZjuFQIfTO2eJd8uwLY/9g== + version "1.2.2" + resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.2.2.tgz#0253d34eccf2aed4ad4f283e11ee75198f9d7316" + integrity sha512-rAfulcwp2D9jjdGu+0CuqlrAUin6bBWrpoqXWwKDZZZJfXcUXQSxLJOFJCQCSA0x0pP2U0TxSlJu2ROq5Bq6qA== dependencies: - coa "~2.0.1" - colors "~1.1.2" + chalk "^2.4.1" + coa "^2.0.2" css-select "^2.0.0" - css-select-base-adapter "~0.1.0" + css-select-base-adapter "^0.1.1" css-tree "1.0.0-alpha.28" css-url-regex "^1.1.0" - csso "^3.5.0" - js-yaml "^3.12.0" + csso "^3.5.1" + js-yaml "^3.13.1" mkdirp "~0.5.1" - object.values "^1.0.4" + object.values "^1.1.0" sax "~1.2.4" - stable "~0.1.6" + stable "^0.1.8" unquote "~1.1.1" util.promisify "~1.0.0" symbol-tree@^3.2.2: - version "3.2.2" - resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.2.tgz#ae27db38f660a7ae2e1c3b7d1bc290819b8519e6" - integrity sha1-rifbOPZgp64uHDt9G8KQgZuFGeY= + version "3.2.4" + resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" + integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== tapable@^1.0.0, tapable@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.1.tgz#4d297923c5a72a42360de2ab52dadfaaec00018e" - integrity sha512-9I2ydhj8Z9veORCw5PRm4u9uebCn0mcCa6scWoNcbZ6dAtoo2618u9UUzxgmsCOreJpqDDuv61LvwofW7hLcBA== - -tar@^2.0.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" - integrity sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE= - dependencies: - block-stream "*" - fstream "^1.0.2" - inherits "2" + version "1.1.3" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" + integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== tar@^4, tar@^4.4.8: - version "4.4.8" - resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.8.tgz#b19eec3fde2a96e64666df9fdb40c5ca1bc3747d" - integrity sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ== + version "4.4.10" + resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.10.tgz#946b2810b9a5e0b26140cf78bea6b0b0d689eba1" + integrity sha512-g2SVs5QIxvo6OLp0GudTqEf05maawKUxXru104iaayWA09551tFCTI8f1Asb4lPfkBr91k07iL4c11XO3/b0tA== dependencies: chownr "^1.1.1" fs-minipass "^1.2.5" - minipass "^2.3.4" - minizlib "^1.1.1" + minipass "^2.3.5" + minizlib "^1.2.1" mkdirp "^0.5.0" safe-buffer "^5.1.2" - yallist "^3.0.2" + yallist "^3.0.3" temp-dir@^1.0.0: version "1.0.0" @@ -8670,20 +8369,22 @@ temp-write@^3.4.0: uuid "^3.0.1" terser-webpack-plugin@^1.1.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.2.1.tgz#7545da9ae5f4f9ae6a0ac961eb46f5e7c845cc26" - integrity sha512-GGSt+gbT0oKcMDmPx4SRSfJPE1XaN3kQRWG4ghxKQw9cn5G9x6aCKSsgYdvyM0na9NJ4Drv0RG6jbBByZ5CMjw== + version "1.3.0" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.3.0.tgz#69aa22426299f4b5b3775cbed8cb2c5d419aa1d4" + integrity sha512-W2YWmxPjjkUcOWa4pBEv4OP4er1aeQJlSo2UhtCFQCuRXEHjOFscO8VyWHj9JLlA0RzQb8Y2/Ta78XZvT54uGg== dependencies: - cacache "^11.0.2" + cacache "^11.3.2" find-cache-dir "^2.0.0" + is-wsl "^1.1.0" + loader-utils "^1.2.3" schema-utils "^1.0.0" - serialize-javascript "^1.4.0" + serialize-javascript "^1.7.0" source-map "^0.6.1" - terser "^3.8.1" - webpack-sources "^1.1.0" - worker-farm "^1.5.2" + terser "^4.0.0" + webpack-sources "^1.3.0" + worker-farm "^1.7.0" -terser@^3.16.1, terser@^3.17.0: +terser@^3.16.1, terser@^3.7.3: version "3.17.0" resolved "https://registry.yarnpkg.com/terser/-/terser-3.17.0.tgz#f88ffbeda0deb5637f9d24b0da66f4e15ab10cb2" integrity sha512-/FQzzPJmCpjAH9Xvk2paiWrFq+5M6aVOf+2KRbwhByISDX/EujxsK+BAvrhb6H+2rtrLCHK9N01wO014vrIwVQ== @@ -8692,29 +8393,29 @@ terser@^3.16.1, terser@^3.17.0: source-map "~0.6.1" source-map-support "~0.5.10" -terser@^3.7.3, terser@^3.8.1: - version "3.14.1" - resolved "https://registry.yarnpkg.com/terser/-/terser-3.14.1.tgz#cc4764014af570bc79c79742358bd46926018a32" - integrity sha512-NSo3E99QDbYSMeJaEk9YW2lTg3qS9V0aKGlb+PlOrei1X02r1wSBHCNX/O+yeTRFSWPKPIGj6MqvvdqV4rnVGw== +terser@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-4.0.0.tgz#ef356f6f359a963e2cc675517f21c1c382877374" + integrity sha512-dOapGTU0hETFl1tCo4t56FN+2jffoKyER9qBGoUFyZ6y7WLoKT0bF+lAYi6B6YsILcGF3q1C2FBh8QcKSCgkgA== dependencies: - commander "~2.17.1" + commander "^2.19.0" source-map "~0.6.1" - source-map-support "~0.5.6" + source-map-support "~0.5.10" -test-exclude@^5.2.2: - version "5.2.2" - resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-5.2.2.tgz#7322f8ab037b0b93ad2aab35fe9068baf997a4c4" - integrity sha512-N2pvaLpT8guUpb5Fe1GJlmvmzH3x+DAKmmyEQmFP792QcLYoGE1syxztSvPD1V8yPe6VrcCt6YGQVjSRjCASsA== +test-exclude@^5.2.3: + version "5.2.3" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-5.2.3.tgz#c3d3e1e311eb7ee405e092dac10aefd09091eac0" + integrity sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g== dependencies: glob "^7.1.3" minimatch "^3.0.4" read-pkg-up "^4.0.0" require-main-filename "^2.0.0" -text-extensions@^1.0.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/text-extensions/-/text-extensions-1.9.0.tgz#1853e45fee39c945ce6f6c36b2d659b5aabc2a26" - integrity sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ== +text-extensions@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/text-extensions/-/text-extensions-2.0.0.tgz#43eabd1b495482fae4a2bf65e5f56c29f69220f6" + integrity sha512-F91ZqLgvi1E0PdvmxMgp+gcf6q8fMH7mhdwWfzXnl1k+GbpQDmi8l7DzLC5JTASKbwpY3TfxajAUzAXcv2NmsQ== through2@^2.0.0, through2@^2.0.2, through2@~2.0.3: version "2.0.5" @@ -8724,6 +8425,13 @@ through2@^2.0.0, through2@^2.0.2, through2@~2.0.3: readable-stream "~2.3.6" xtend "~4.0.1" +through2@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/through2/-/through2-3.0.1.tgz#39276e713c3302edf9e388dd9c812dd3b825bd5a" + integrity sha512-M96dvTalPT3YbYLaKaCuwu+j06D/8Jfib0o/PxbVt6Amhv3dUAtW6rTV1jPgJSBG83I/e04Y6xkVdVhSRhi0ww== + dependencies: + readable-stream "2 || 3" + through@2, "through@>=2.2.7 <3", through@^2.3.4, through@^2.3.6: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" @@ -8783,6 +8491,13 @@ to-regex-range@^2.1.0: is-number "^3.0.0" repeat-string "^1.6.1" +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + to-regex@^3.0.1, to-regex@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" @@ -8793,6 +8508,11 @@ to-regex@^3.0.1, to-regex@^3.0.2: regex-not "^1.0.2" safe-regex "^1.1.0" +toidentifier@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" + integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== + tough-cookie@^2.3.3, tough-cookie@^2.3.4: version "2.5.0" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" @@ -8836,26 +8556,26 @@ trim-right@^1.0.1: resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM= -ts-loader@^5.4.3: - version "5.4.3" - resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-5.4.3.tgz#837f7f397799a665fc1774303c9fd0930d1c5947" - integrity sha512-pHwZFkZioL7Yi2su0bhW2/djxZ+0iGat1cxlAif4Eg9j5znVYuWGtW0YYY/5w8W+IzLcAlD5KwJDrs5unUKIRA== +ts-loader@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-6.0.2.tgz#cbd46a1495668ed9d59813f5c66f4bb49ff0c14c" + integrity sha512-kkF3sGf3oBUehlvXI9fkbItbFTnNgGkYAz91vtWnsKAU4m+LAmQjuby7uTZNo3As+/zHLuyB052SkQDY6vLXtg== dependencies: chalk "^2.3.0" enhanced-resolve "^4.0.0" loader-utils "^1.0.2" - micromatch "^3.1.4" - semver "^5.0.1" + micromatch "^4.0.0" + semver "^6.0.0" tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0: - version "1.9.3" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" - integrity sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ== + version "1.10.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" + integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== tslint@^5.16.0: - version "5.16.0" - resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.16.0.tgz#ae61f9c5a98d295b9a4f4553b1b1e831c1984d67" - integrity sha512-UxG2yNxJ5pgGwmMzPMYh/CCnCnh0HfPgtlVRDs1ykZklufFBL1ZoTlWFRz2NQjcoEiDoRp+JyT0lhBbbH/obyA== + version "5.17.0" + resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.17.0.tgz#f9f0ce2011d8e90debaa6e9b4975f24cd16852b8" + integrity sha512-pflx87WfVoYepTet3xLfDOLDm9Jqi61UXIKePOuca0qoAZyrGWonDG9VTbji58Fy+8gciUn8Bt7y69+KEVjc/w== dependencies: "@babel/code-frame" "^7.0.0" builtin-modules "^1.1.1" @@ -8863,7 +8583,7 @@ tslint@^5.16.0: commander "^2.12.1" diff "^3.2.0" glob "^7.1.1" - js-yaml "^3.13.0" + js-yaml "^3.13.1" minimatch "^3.0.4" mkdirp "^0.5.1" resolve "^1.3.2" @@ -8936,21 +8656,21 @@ typedoc@^0.14.2: typescript "3.2.x" typescript@3.2.x: - version "3.2.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.2.2.tgz#fe8101c46aa123f8353523ebdcf5730c2ae493e5" - integrity sha512-VCj5UiSyHBjwfYacmDuc/NOk4QQixbE+Wn7MFJuS0nRuPQbof132Pw4u53dm264O8LPc2MVsc7RJNml5szurkg== + version "3.2.4" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.2.4.tgz#c585cb952912263d915b462726ce244ba510ef3d" + integrity sha512-0RNDbSdEokBeEAkgNbxJ+BLwSManFy9TeXz8uW+48j/xhEXv1ePME60olyzw2XzUqUBNAYFeJadIqAgNqIACwg== -typescript@^3.4.5: - version "3.4.5" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.4.5.tgz#2d2618d10bb566572b8d7aad5180d84257d70a99" - integrity sha512-YycBxUb49UUhdNMU5aJ7z5Ej2XGmaIBL0x34vZ82fn3hGvD+bgrMrVDpatgz2f7YxUMJxMkbWxJZeAvDxVe7Vw== +typescript@^3.5.2: + version "3.5.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.5.2.tgz#a09e1dc69bc9551cadf17dba10ee42cf55e5d56c" + integrity sha512-7KxJovlYhTX5RaRbUdkAXN1KUZ8PwWlTzQdHV6xNqvuFOs7+WBo10TQUqT19Q/Jz2hk5v9TQDIhyLhhJY4p5AA== uglify-js@^3.1.4: - version "3.4.9" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.9.tgz#af02f180c1207d76432e473ed24a28f4a782bae3" - integrity sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q== + version "3.6.0" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.6.0.tgz#704681345c53a8b2079fb6cec294b05ead242ff5" + integrity sha512-W+jrUHJr3DXKhrsS7NUVxn3zqMOFn0hL/Ei6v0anCIMoKC93TjcflTagwIHLW7SfMFfiQuktQyFVCFHGUE0+yg== dependencies: - commander "~2.17.1" + commander "~2.20.0" source-map "~0.6.1" uid-number@0.0.6: @@ -8991,15 +8711,15 @@ unicode-match-property-ecmascript@^1.0.4: unicode-canonical-property-names-ecmascript "^1.0.4" unicode-property-aliases-ecmascript "^1.0.4" -unicode-match-property-value-ecmascript@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.0.2.tgz#9f1dc76926d6ccf452310564fd834ace059663d4" - integrity sha512-Rx7yODZC1L/T8XKo/2kNzVAQaRE88AaMvI1EF/Xnj3GW2wzN6fop9DDWuFAKUVFH7vozkz26DzP0qyWLKLIVPQ== +unicode-match-property-value-ecmascript@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.1.0.tgz#5b4b426e08d13a80365e0d657ac7a6c1ec46a277" + integrity sha512-hDTHvaBk3RmFzvSl0UVrUmC3PuW9wKVnpoUDYH0JDkSIovzw+J5viQmeYHxVSBptubnr7PbH2e0fnpDRQnQl5g== unicode-property-aliases-ecmascript@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.4.tgz#5a533f31b4317ea76f17d807fa0d116546111dd0" - integrity sha512-2WSLa6OdYd2ng8oqiGIWnJqyFArvhn+5vgx5GTxMbUYjCYKUcuKS62YLFF0R/BDGlB1yzXjQOLtPAfHsgirEpg== + version "1.0.5" + resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.5.tgz#a9cc6cc7ce63a0a3023fc99e341b94431d405a57" + integrity sha512-L5RAqCfXqAwR3RriF8pM0lU0w4Ryf/GgzONwi6KnL1taJQa7x1TCxdJnILX59WIGOwR57IVxn7Nej0fz1Ny6fw== unicode-trie@^0.3.1: version "0.3.1" @@ -9037,16 +8757,16 @@ unique-filename@^1.1.1: unique-slug "^2.0.0" unique-slug@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.1.tgz#5e9edc6d1ce8fb264db18a507ef9bd8544451ca6" - integrity sha512-n9cU6+gITaVu7VGj1Z8feKMmfAjEAQGhwD9fE3zvpRRa0wEIx8ODYkVGfSc94M2OX00tUFV8wH3zYbm1I8mxFg== + version "2.0.2" + resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.2.tgz#baabce91083fc64e945b0f3ad613e264f7cd4e6c" + integrity sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w== dependencies: imurmurhash "^0.1.4" -universal-user-agent@^2.0.0, universal-user-agent@^2.0.1: - version "2.0.3" - resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-2.0.3.tgz#9f6f09f9cc33de867bb720d84c08069b14937c6c" - integrity sha512-eRHEHhChCBHrZsA4WEhdgiOKgdvgrMIHwnwnqD0r5C6AO8kwKcG7qSku3iXdhvHL3YvsS9ZkSGN8h/hIpoFC8g== +universal-user-agent@^2.0.0, universal-user-agent@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-2.1.0.tgz#5abfbcc036a1ba490cb941f8fd68c46d3669e8e4" + integrity sha512-8itiX7G05Tu3mGDTdNY2fB4KJ8MgZLS54RdG6PkkfwMAavrXu1mV/lls/GABx9O3Rw4PnTtasxrvbMQoBYY92Q== dependencies: os-name "^3.0.0" @@ -9068,10 +8788,10 @@ unset-value@^1.0.0: has-value "^0.3.1" isobject "^3.0.0" -upath@^1.0.5: - version "1.1.0" - resolved "https://registry.yarnpkg.com/upath/-/upath-1.1.0.tgz#35256597e46a581db4793d0ce47fa9aebfc9fabd" - integrity sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw== +upath@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/upath/-/upath-1.1.2.tgz#3db658600edaeeccbe6db5e684d67ee8c2acd068" + integrity sha512-kXpym8nmDmlCBr7nKdIx8P2jNBa+pBpIUFRnKJ4dr8htyYGJFokkr2ZvERRtUN+9SY+JqXouNgUPtv6JQva/2Q== uri-js@^4.2.2: version "4.2.2" @@ -9123,10 +8843,10 @@ util@0.10.3: dependencies: inherits "2.0.1" -util@^0.10.3: - version "0.10.4" - resolved "https://registry.yarnpkg.com/util/-/util-0.10.4.tgz#3aa0125bfe668a4672de58857d3ace27ecb76901" - integrity sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A== +util@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/util/-/util-0.11.1.tgz#3236733720ec64bb27f6e26f421aaa2e1b588d61" + integrity sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ== dependencies: inherits "2.0.3" @@ -9136,9 +8856,9 @@ uuid@^3.0.1, uuid@^3.3.2: integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== v8-compile-cache@^2.0.0, v8-compile-cache@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.0.2.tgz#a428b28bb26790734c4fc8bc9fa106fccebf6a6c" - integrity sha512-1wFuMUIM16MDJRCrpbpuEPTUGmM5QMUg0cr3KFwra2XgOgFcPGDQHDh3CszSCD2Zewc/dh/pamNEW8CbfDebUw== + version "2.0.3" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.0.3.tgz#00f7494d2ae2b688cfe2899df6ed2c54bef91dbe" + integrity sha512-CNmdbwQMBjwr9Gsmohvm0pbL954tJrNzf6gWL3K+QMQf00PF7ERGrEiLgjuU3mKreLC2MeGhUsNV9ybTbLgd3w== validate-npm-package-license@^3.0.1, validate-npm-package-license@^3.0.3: version "3.0.4" @@ -9156,9 +8876,9 @@ validate-npm-package-name@^3.0.0: builtins "^1.0.3" vendors@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.2.tgz#7fcb5eef9f5623b156bcea89ec37d63676f21801" - integrity sha512-w/hry/368nO21AN9QljsaIhb9ZiZtZARoVH5f3CsFbawdLdayCgKRPup7CggujvySMxx0I91NOyxdVENohprLQ== + version "1.0.3" + resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.3.tgz#a6467781abd366217c050f8202e7e50cc9eef8c0" + integrity sha512-fOi47nsJP5Wqefa43kyWSg80qF+Q3XA6MUkgi7Hp1HQaKDQW4cQrK2D0P7mmbFtsV1N89am55Yru/nyEwRubcw== verror@1.10.0: version "1.10.0" @@ -9174,12 +8894,10 @@ vlq@^0.2.2: resolved "https://registry.yarnpkg.com/vlq/-/vlq-0.2.3.tgz#8f3e4328cf63b1540c0d67e1b2778386f8975b26" integrity sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow== -vm-browserify@0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-0.0.4.tgz#5d7ea45bbef9e4a6ff65f95438e0a87c357d5a73" - integrity sha1-XX6kW7755Kb/ZflUOOCofDV9WnM= - dependencies: - indexof "0.0.1" +vm-browserify@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.0.tgz#bd76d6a23323e2ca8ffa12028dc04559c75f9019" + integrity sha512-iq+S7vZJE60yejDYM0ek6zg308+UZsdtPExWP9VZoCFCz1zkJoXFnAX7aZfd/ZwrkidzdUZL0C/ryW+JwAiIGw== w3c-hr-time@^1.0.1: version "1.0.1" @@ -9210,9 +8928,9 @@ webidl-conversions@^4.0.2: integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg== webpack-cli@^3.3.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.3.1.tgz#98b0499c7138ba9ece8898bd99c4f007db59909d" - integrity sha512-c2inFU7SM0IttEgF7fK6AaUsbBnORRzminvbyRKS+NlbQHVZdCtzKBlavRL5359bFsywXGRAItA5di/IruC8mg== + version "3.3.4" + resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.3.4.tgz#de27e281c48a897b8c219cb093e261d5f6afe44a" + integrity sha512-ubJGQEKMtBSpT+LiL5hXvn2GIOWiRWItR1DGUqJRhwRBeGhpRXjvF5f0erqdRJLErkfqS5/Ldkkedh4AL5Q1ZQ== dependencies: chalk "^2.4.1" cross-spawn "^6.0.5" @@ -9222,11 +8940,12 @@ webpack-cli@^3.3.1: import-local "^2.0.0" interpret "^1.1.0" loader-utils "^1.1.0" + prettier "^1.17.0" supports-color "^5.5.0" v8-compile-cache "^2.0.2" yargs "^12.0.5" -webpack-sources@^1.1.0, webpack-sources@^1.3.0: +webpack-sources@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.3.0.tgz#2a28dcb9f1f45fe960d8f1493252b5ee6530fa85" integrity sha512-OiVgSrbGu7NEnEvQJJgdSFPl2qWKkWq5lHMhgiToIiN9w34EBnjYzSYs+VbL5KoYiLNtFFa7BZIKxRED3I32pA== @@ -9235,9 +8954,9 @@ webpack-sources@^1.1.0, webpack-sources@^1.3.0: source-map "~0.6.1" webpack@^4.30.0: - version "4.30.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.30.0.tgz#aca76ef75630a22c49fcc235b39b4c57591d33a9" - integrity sha512-4hgvO2YbAFUhyTdlR4FNyt2+YaYBYHavyzjCMbZzgglo02rlKi/pcsEzwCuCpsn1ryzIl1cq/u8ArIKu8JBYMg== + version "4.34.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.34.0.tgz#a4c30129482f7b4ece4c0842002dedf2b56fab58" + integrity sha512-ry2IQy1wJjOefLe1uJLzn5tG/DdIKzQqNlIAd2L84kcaADqNvQDTBlo8UcCNyDaT5FiaB+16jhAkb63YeG3H8Q== dependencies: "@webassemblyjs/ast" "1.8.5" "@webassemblyjs/helper-module-context" "1.8.5" @@ -9314,11 +9033,11 @@ wide-align@1.1.3, wide-align@^1.1.0: string-width "^1.0.2 || 2" windows-release@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/windows-release/-/windows-release-3.1.0.tgz#8d4a7e266cbf5a233f6c717dac19ce00af36e12e" - integrity sha512-hBb7m7acFgQPQc222uEQTmdcGLeBmQLNLFIh0rDk3CwFOBrfjefLzEfEfmpMq8Af/n/GnFf3eYf203FY1PmudA== + version "3.2.0" + resolved "https://registry.yarnpkg.com/windows-release/-/windows-release-3.2.0.tgz#8122dad5afc303d833422380680a79cdfa91785f" + integrity sha512-QTlz2hKLrdqukrsapKsINzqMgOUpQW268eJ0OaOpJN32h272waxR9fkB9VoWRtK7uKHG5EHJcTXQBD8XZVJkFA== dependencies: - execa "^0.10.0" + execa "^1.0.0" wordwrap@~0.0.2: version "0.0.3" @@ -9330,10 +9049,10 @@ wordwrap@~1.0.0: resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= -worker-farm@^1.5.2: - version "1.6.0" - resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.6.0.tgz#aecc405976fab5a95526180846f0dba288f3a4a0" - integrity sha512-6w+3tHbM87WnSWnENBUvA2pxJPLhQUg5LKwUQHq3r+XPhIM+Gh2R5ycbwPCyuGbNg+lPgdcnQUhuC02kJCvffQ== +worker-farm@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.7.0.tgz#26a94c5391bbca926152002f69b84a4bf772e5a8" + integrity sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw== dependencies: errno "~0.1.7" @@ -9345,24 +9064,24 @@ wrap-ansi@^2.0.0: string-width "^1.0.1" strip-ansi "^3.0.1" +wrap-ansi@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" + integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== + dependencies: + ansi-styles "^3.2.0" + string-width "^3.0.0" + strip-ansi "^5.0.0" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= -write-file-atomic@^2.0.0, write-file-atomic@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.3.0.tgz#1ff61575c2e2a4e8e510d6fa4e243cce183999ab" - integrity sha512-xuPeK4OdjWqtfi59ylvVL0Yn35SF3zgcAcv7rBPFHVaEapaDr4GdGgm3j7ckTwH9wHL7fGmgfAnb0+THrHb8tA== - dependencies: - graceful-fs "^4.1.11" - imurmurhash "^0.1.4" - signal-exit "^3.0.2" - -write-file-atomic@^2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.2.tgz#a7181706dfba17855d221140a9c06e15fcdd87b9" - integrity sha512-s0b6vB3xIVRLWywa6X9TOMA7k9zio0TMOsl9ZnDkliA/cfJlpHXAscj0gbHVJiTdIuAYpIyqS5GW91fqm6gG5g== +write-file-atomic@^2.0.0, write-file-atomic@^2.3.0, write-file-atomic@^2.4.2: + version "2.4.3" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.3.tgz#1fd2e9ae1df3e75b8d8c367443c692d4ca81f481" + integrity sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ== dependencies: graceful-fs "^4.1.11" imurmurhash "^0.1.4" @@ -9415,12 +9134,12 @@ yallist@^2.1.2: resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= -yallist@^3.0.0, yallist@^3.0.2: +yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.3.tgz#b4b049e314be545e3ce802236d6cd22cd91c3de9" integrity sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A== -yargs-parser@13.0.0, yargs-parser@^13.0.0: +yargs-parser@13.0.0: version "13.0.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.0.0.tgz#3fc44f3e76a8bdb1cc3602e860108602e5ccde8b" integrity sha512-w2LXjoL8oRdRQN+hOyppuXs+V/fVAYtpcrRxZuF7Kt/Oc+Jr2uAcVntaUTNT6w5ihoWfFDpNY8CPx1QskxZ/pw== @@ -9436,6 +9155,14 @@ yargs-parser@^11.1.1: camelcase "^5.0.0" decamelize "^1.2.0" +yargs-parser@^13.0.0, yargs-parser@^13.1.0: + version "13.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0" + integrity sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + yargs-unparser@1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-1.5.0.tgz#f2bb2a7e83cbc87bb95c8e572828a06c9add6e0d" @@ -9445,7 +9172,7 @@ yargs-unparser@1.5.0: lodash "^4.17.11" yargs "^12.0.5" -yargs@13.2.2, yargs@^13.2.2: +yargs@13.2.2: version "13.2.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.2.2.tgz#0c101f580ae95cea7f39d927e7770e3fdc97f993" integrity sha512-WyEoxgyTD3w5XRpAQNYUB9ycVH/PQrToaTXdYXRdOXvEy1l19br+VJsc0vcO8PTGg5ro/l/GY7F/JMEBmI0BxA== @@ -9479,3 +9206,20 @@ yargs@^12.0.1, yargs@^12.0.5: which-module "^2.0.0" y18n "^3.2.1 || ^4.0.0" yargs-parser "^11.1.1" + +yargs@^13.2.2: + version "13.2.4" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.2.4.tgz#0b562b794016eb9651b98bd37acf364aa5d6dc83" + integrity sha512-HG/DWAJa1PAnHT9JAhNa8AbAv3FPaiLzioSjCcmuXXhP8MlpHO5vwls4g4j6n30Z74GVQj8Xa62dWVx1QCGklg== + dependencies: + cliui "^5.0.0" + find-up "^3.0.0" + get-caller-file "^2.0.1" + os-locale "^3.1.0" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^3.0.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^13.1.0"