diff --git a/.gitignore b/.gitignore index 4641eed96e..9b08949279 100644 --- a/.gitignore +++ b/.gitignore @@ -1,23 +1,28 @@ -node_modules +.cache +.DS_Store +.meta .nyc_output -coverage +*.bak* +*.d.ts +*.gz +*.js +*.log +*.map +*.tgz +*.zip +/.gtm/ build +bundle.* +coverage dev doc docs -export examples/dataflow-scenegraph examples/hdc examples/hdom-class examples/hdom-clj examples/ts-parse -.DS_Store +export +lib +node_modules tachyons.min.css -bundle.* -*.log -*.tgz -*.js -*.d.ts -*.bak* -*.zip -/.gtm/ diff --git a/.travis.yml b/.travis.yml index 60be2f977b..cb8d32e4f1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: node_js node_js: - - "9" + - "10" branches: only: diff --git a/README.md b/README.md index 0f88dbcd57..a41e91fac3 100644 --- a/README.md +++ b/README.md @@ -19,8 +19,8 @@ All / most packages: - have detailed, individual README files w/ small usage examples - are versioned independently -- distributed in ES6 syntax (as CommonJS modules) with doc comments - (incl. example code snippets), bundled TypeScript typings & changelogs +- distributed in ES6 syntax and multiple format (ESM, CommonJS, UMD) + with TypeScript typings & changelogs - highly modular with largely only a few closely related functions or single function / class per file to help w/ tree shaking - provide re-exports of all their publics for full library imports @@ -31,8 +31,8 @@ All / most packages: - auto-generated online documentation at [docs.thi.ng](http://docs.thi.ng) - licensed under Apache Software License 2.0 -There's a steadily growing number (~40) of standalone examples -(different difficulties, many combining functionality from several +There's a steadily growing number (40+) of standalone examples +(different complexities, many combining functionality from several packages) in the [examples](./examples) directory. ## Projects @@ -61,6 +61,7 @@ packages) in the [examples](./examples) directory. | Project | Version | Changelog | Description | |-------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------|----------------------------------| | [`@thi.ng/csp`](./packages/csp) | [![version](https://img.shields.io/npm/v/@thi.ng/csp.svg)](https://www.npmjs.com/package/@thi.ng/csp) | [changelog](./packages/csp/CHANGELOG.md) | Channel based async ops | +| [`@thi.ng/fsm`](./packages/fsm) | [![version](https://img.shields.io/npm/v/@thi.ng/fsm.svg)](https://www.npmjs.com/package/@thi.ng/fsm) | [changelog](./packages/fsm/CHANGELOG.md) | FSM / parser primitives | | [`@thi.ng/iterators`](./packages/iterators) | [![version](https://img.shields.io/npm/v/@thi.ng/iterators.svg)](https://www.npmjs.com/package/@thi.ng/iterators) | [changelog](./packages/iterators/CHANGELOG.md) | ES6 generators / iterators | | [`@thi.ng/sax`](./packages/sax) | [![version](https://img.shields.io/npm/v/@thi.ng/sax.svg)](https://www.npmjs.com/package/@thi.ng/sax) | [changelog](./packages/sax/CHANGELOG.md) | SAX-like XML parser / transducer | | [`@thi.ng/transducers`](./packages/transducers) | [![version](https://img.shields.io/npm/v/@thi.ng/transducers.svg)](https://www.npmjs.com/package/@thi.ng/transducers) | [changelog](./packages/transducers/CHANGELOG.md) | Composable data transformations | @@ -112,26 +113,29 @@ packages) in the [examples](./examples) directory. ### Geometry & visualization -| Project | Version | Changelog | Description | -|-----------------------------------------------|---------------------------------------------------------------------------------------------------------------------|-------------------------------------------------|------------------------------------------| -| [`@thi.ng/dot`](./packages/dot) | [![version](https://img.shields.io/npm/v/@thi.ng/dot.svg)](https://www.npmjs.com/package/@thi.ng/dot) | [changelog](./packages/dot/CHANGELOG.md) | Graphviz DOM & export | -| [`@thi.ng/geom`](./packages/geom) | [![version](https://img.shields.io/npm/v/@thi.ng/geom.svg)](https://www.npmjs.com/package/@thi.ng/geom) | [changelog](./packages/geom/CHANGELOG.md) | 2D geometry types & operations | -| [`@thi.ng/geom-accel`](./packages/geom-accel) | [![version](https://img.shields.io/npm/v/@thi.ng/geom-accel.svg)](https://www.npmjs.com/package/@thi.ng/geom-accel) | [changelog](./packages/geom-accel/CHANGELOG.md) | Spatial indexing data structures | -| [`@thi.ng/iges`](./packages/iges) | [![version](https://img.shields.io/npm/v/@thi.ng/iges.svg)](https://www.npmjs.com/package/@thi.ng/iges) | [changelog](./packages/iges/CHANGELOG.md) | IGES format geometry serialization | -| [`@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) | Memory-mapped vector & matrix operations | +| Project | Version | Changelog | Description | +|-----------------------------------------------|---------------------------------------------------------------------------------------------------------------------|-------------------------------------------------|-------------------------------------| +| [`@thi.ng/color`](./packages/color) | [![version](https://img.shields.io/npm/v/@thi.ng/color.svg)](https://www.npmjs.com/package/@thi.ng/color) | [changelog](./packages/color/CHANGELOG.md) | Color | +| [`@thi.ng/dot`](./packages/dot) | [![version](https://img.shields.io/npm/v/@thi.ng/dot.svg)](https://www.npmjs.com/package/@thi.ng/dot) | [changelog](./packages/dot/CHANGELOG.md) | Graphviz DOM & export | +| [`@thi.ng/geom`](./packages/geom) | [![version](https://img.shields.io/npm/v/@thi.ng/geom.svg)](https://www.npmjs.com/package/@thi.ng/geom) | [changelog](./packages/geom/CHANGELOG.md) | 2D geometry types & operations | +| [`@thi.ng/geom-accel`](./packages/geom-accel) | [![version](https://img.shields.io/npm/v/@thi.ng/geom-accel.svg)](https://www.npmjs.com/package/@thi.ng/geom-accel) | [changelog](./packages/geom-accel/CHANGELOG.md) | Spatial indexing data structures | +| [`@thi.ng/iges`](./packages/iges) | [![version](https://img.shields.io/npm/v/@thi.ng/iges.svg)](https://www.npmjs.com/package/@thi.ng/iges) | [changelog](./packages/iges/CHANGELOG.md) | IGES format geometry serialization | +| [`@thi.ng/matrices`](./packages/matrices) | [![version](https://img.shields.io/npm/v/@thi.ng/matrices.svg)](https://www.npmjs.com/package/@thi.ng/matrices) | [changelog](./packages/matrices/CHANGELOG.md) | Matrix operations | +| [`@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 | ### Low-level, binary, memory management -| Project | Version | Changelog | Description | -|-------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------|--------------------------------------------------|-------------------------------------------| -| [`@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 | +| Project | Version | Changelog | Description | +|---------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------|-------------------------------------------| +| [`@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 | ### DSLs @@ -140,18 +144,13 @@ 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 | -### Experimental packages (WIP / unreleased) - -- [@thi.ng/geom2](https://github.com/thi-ng/umbrella/tree/feature/vec-refactor/packages/geom2) -- [@thi.ng/matrices](https://github.com/thi-ng/umbrella/tree/feature/vec-refactor/packages/matrices) -- [@thi.ng/vector-pools](https://github.com/thi-ng/umbrella/tree/feature/vec-refactor/packages/vector-pools) -- [@thi.ng/vectors3](https://github.com/thi-ng/umbrella/tree/feature/vec-refactor/packages/vectors3) - ## Building ```bash git clone https://github.com/thi-ng/umbrella.git cd umbrella + +yarn install yarn build ``` @@ -179,7 +178,7 @@ yarn build ### Testing -(TODO most but not all packages have tests) +(most, but not all packages have tests) ```bash yarn test diff --git a/assets/porter-duff.png b/assets/porter-duff.png new file mode 100644 index 0000000000..fe93829379 Binary files /dev/null and b/assets/porter-duff.png differ diff --git a/examples/README.md b/examples/README.md index 2472d69dad..4b6a41c28e 100644 --- a/examples/README.md +++ b/examples/README.md @@ -32,6 +32,7 @@ If you want to [contribute](../CONTRIBUTING.md) an example, please get in touch | 24 | [json-components](./json-components) | JSON->component transformation, live editor | hdom, transducers | intermediate | | 25 | [login-form](./login-form) | Basic SPA without router | atom, hdom | intermediate | | 26 | [mandelbrot](./mandelbrot) | Worker-based mandelbrot fractal renderer | rstream, rstream-gestures, transducers-hdom | advanced | +| 26 | [markdown](./markdown) | Markdown parser & editor w/ live preview | fsm, rstream, transducers-hdom | advanced | | 27 | [pointfree-svg](./pointfree-svg) | Generate SVG using pointfree DSL | hiccup, hiccup-svg, pointfree-lang | intermediate | | 28 | [router-basics](./router-basics) | Complete mini SPA | atom, hdom, interceptors, router | advanced | | 29 | [rstream-dataflow](./rstream-dataflow) | Dataflow graph | atom, hdom, rstream, rstream-gestures, rstream-graph, transducers | intermediate | diff --git a/examples/async-effect/README.md b/examples/async-effect/README.md index 2793114889..00bc303112 100644 --- a/examples/async-effect/README.md +++ b/examples/async-effect/README.md @@ -2,9 +2,6 @@ [Live demo](https://demo.thi.ng/umbrella/async-effect/) -```bash -git clone https://github.com/thi-ng/umbrella.git -cd umbrella/examples/async-effect -yarn install -yarn start -``` +Please refer to the [example build +instructions](https://github.com/thi-ng/umbrella/wiki/Example-build-instructions) +on the wiki. diff --git a/examples/async-effect/package.json b/examples/async-effect/package.json index 49117455ee..76c3a31231 100644 --- a/examples/async-effect/package.json +++ b/examples/async-effect/package.json @@ -7,17 +7,16 @@ "scripts": { "clean": "rm -rf .cache build out", "prep": "yarn clean && mkdir -p out && cp foo.json out", - "build": "yarn prep && parcel build index.html -d out --no-source-maps --no-cache --detailed-report --public-url ./", + "build": "yarn prep && parcel build index.html -d out --no-source-maps --no-cache --experimental-scope-hoisting --detailed-report --public-url ./", "start": "yarn prep && parcel index.html -p 8080 --open -d out" }, "devDependencies": { - "parcel-bundler": "^1.10.3", - "terser": "^3.11.0", + "parcel-bundler": "^1.11.0", + "terser": "^3.14.1", "typescript": "^3.2.2" }, "dependencies": { "@thi.ng/api": "latest", - "@thi.ng/atom": "latest", "@thi.ng/hdom": "latest", "@thi.ng/interceptors": "latest" }, diff --git a/examples/async-effect/src/index.ts b/examples/async-effect/src/index.ts index f60a8c5da1..fdc827cef3 100644 --- a/examples/async-effect/src/index.ts +++ b/examples/async-effect/src/index.ts @@ -1,13 +1,13 @@ -import { IObjectOf } from "@thi.ng/api/api"; -import { start } from "@thi.ng/hdom/start"; +import { IObjectOf } from "@thi.ng/api"; +import { start } from "@thi.ng/hdom"; import { EffectDef, + EventBus, EventDef, FX_DISPATCH_ASYNC, - FX_DISPATCH_NOW -} from "@thi.ng/interceptors/api"; -import { EventBus } from "@thi.ng/interceptors/event-bus"; -import { valueSetter } from "@thi.ng/interceptors/interceptors"; + FX_DISPATCH_NOW, + valueSetter +} from "@thi.ng/interceptors"; // best practice tip: // define event & effect names as consts or enums and diff --git a/examples/async-effect/tsconfig.json b/examples/async-effect/tsconfig.json index b7d63aedf0..50a1cade93 100644 --- a/examples/async-effect/tsconfig.json +++ b/examples/async-effect/tsconfig.json @@ -2,6 +2,7 @@ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": ".", + "module": "es6", "target": "es6", "sourceMap": true }, diff --git a/examples/canvas-dial/README.md b/examples/canvas-dial/README.md index d74977360d..f0277ca369 100644 --- a/examples/canvas-dial/README.md +++ b/examples/canvas-dial/README.md @@ -5,12 +5,9 @@ Customizable canvas-based radial dial component with mouse & touch support. -```bash -git clone https://github.com/thi-ng/umbrella.git -cd umbrella/examples/canvas-dial -yarn install -yarn start -``` +Please refer to the [example build +instructions](https://github.com/thi-ng/umbrella/wiki/Example-build-instructions) +on the wiki. ## Authors diff --git a/examples/canvas-dial/package.json b/examples/canvas-dial/package.json index 32eddd14d2..6fe997818c 100644 --- a/examples/canvas-dial/package.json +++ b/examples/canvas-dial/package.json @@ -6,12 +6,12 @@ "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 --detailed-report --public-url ./", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --experimental-scope-hoisting --detailed-report --public-url ./", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { - "parcel-bundler": "^1.10.3", - "terser": "^3.11.0", + "parcel-bundler": "^1.11.0", + "terser": "^3.14.1", "typescript": "^3.2.2" }, "dependencies": { @@ -19,10 +19,12 @@ "@thi.ng/checks": "latest", "@thi.ng/hdom": "latest", "@thi.ng/hdom-components": "latest", + "@thi.ng/math": "latest", "@thi.ng/rstream": "latest", "@thi.ng/rstream-gestures": "latest", "@thi.ng/strings": "latest", - "@thi.ng/transducers": "latest" + "@thi.ng/transducers": "latest", + "@thi.ng/transducers-hdom": "latest" }, "browserslist": [ "last 3 Chrome versions" diff --git a/examples/canvas-dial/src/dial.ts b/examples/canvas-dial/src/dial.ts index 36fa94ad35..094943689c 100644 --- a/examples/canvas-dial/src/dial.ts +++ b/examples/canvas-dial/src/dial.ts @@ -1,11 +1,11 @@ -import { Fn } from "@thi.ng/api/api"; -import { isString } from "@thi.ng/checks/is-string"; -import { canvas2D } from "@thi.ng/hdom-components/canvas"; +import { Fn } from "@thi.ng/api"; +import { isString } from "@thi.ng/checks"; +import { canvas2D } from "@thi.ng/hdom-components"; +import { fitClamped } from "@thi.ng/math"; +import { Subscription } from "@thi.ng/rstream"; import { GestureEvent, gestureStream, GestureType } from "@thi.ng/rstream-gestures"; -import { Subscription } from "@thi.ng/rstream/subscription"; -import { peek } from "@thi.ng/transducers/func/peek"; -import { fitClamped } from "@thi.ng/math/fit"; -import { heading2, sub2 } from "@thi.ng/vectors/vec2"; +import { peek } from "@thi.ng/transducers"; +import { heading2, sub2 } from "@thi.ng/vectors"; /** * Dial component options. diff --git a/examples/canvas-dial/src/index.ts b/examples/canvas-dial/src/index.ts index b3fe03cc38..55f9059438 100644 --- a/examples/canvas-dial/src/index.ts +++ b/examples/canvas-dial/src/index.ts @@ -1,10 +1,7 @@ -import { stream } from "@thi.ng/rstream/stream"; -import { sync } from "@thi.ng/rstream/stream-sync"; -import { percent } from "@thi.ng/strings/percent"; +import { stream, sync } from "@thi.ng/rstream"; +import { percent } from "@thi.ng/strings"; +import { comp, map } from "@thi.ng/transducers"; import { updateDOM } from "@thi.ng/transducers-hdom"; -import { comp } from "@thi.ng/transducers/func/comp"; -import { map } from "@thi.ng/transducers/xform/map"; - import { dial } from "./dial"; // hdom context & app state object diff --git a/examples/canvas-dial/tsconfig.json b/examples/canvas-dial/tsconfig.json index b7d63aedf0..50a1cade93 100644 --- a/examples/canvas-dial/tsconfig.json +++ b/examples/canvas-dial/tsconfig.json @@ -2,6 +2,7 @@ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": ".", + "module": "es6", "target": "es6", "sourceMap": true }, diff --git a/examples/cellular-automata/README.md b/examples/cellular-automata/README.md index 8d0a4384d8..89bcf409eb 100644 --- a/examples/cellular-automata/README.md +++ b/examples/cellular-automata/README.md @@ -2,12 +2,9 @@ [Live demo](https://demo.thi.ng/umbrella/cellular-automata/) -```bash -git clone https://github.com/thi-ng/umbrella.git -cd umbrella/examples/cellular-automata -yarn install -yarn start -``` +Please refer to the [example build +instructions](https://github.com/thi-ng/umbrella/wiki/Example-build-instructions) +on the wiki. ## Example configurations diff --git a/examples/cellular-automata/package.json b/examples/cellular-automata/package.json index 0f13799a9b..2949a9e5ca 100644 --- a/examples/cellular-automata/package.json +++ b/examples/cellular-automata/package.json @@ -6,16 +6,15 @@ "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 --detailed-report --public-url ./", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --experimental-scope-hoisting --detailed-report --public-url ./", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { - "parcel-bundler": "^1.10.3", - "terser": "^3.11.0", + "parcel-bundler": "^1.11.0", + "terser": "^3.14.1", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/api": "latest", "@thi.ng/hdom": "latest", "@thi.ng/hdom-components": "latest", "@thi.ng/transducers": "latest" diff --git a/examples/cellular-automata/src/index.ts b/examples/cellular-automata/src/index.ts index 996f69a46b..6fa7cc29d1 100644 --- a/examples/cellular-automata/src/index.ts +++ b/examples/cellular-automata/src/index.ts @@ -1,18 +1,21 @@ import { start } from "@thi.ng/hdom"; -import { dropdown, DropDownOption } from "@thi.ng/hdom-components/dropdown"; -import { comp } from "@thi.ng/transducers/func/comp"; -import { lookup2d } from "@thi.ng/transducers/func/lookup"; -import { range2d } from "@thi.ng/transducers/iter/range2d"; -import { repeatedly } from "@thi.ng/transducers/iter/repeatedly"; -import { push } from "@thi.ng/transducers/rfn/push"; -import { str } from "@thi.ng/transducers/rfn/str"; -import { step } from "@thi.ng/transducers/step"; -import { transduce } from "@thi.ng/transducers/transduce"; -import { bits } from "@thi.ng/transducers/xform/bits"; -import { buildKernel2d, convolve2d } from "@thi.ng/transducers/xform/convolve"; -import { map } from "@thi.ng/transducers/xform/map"; -import { multiplex } from "@thi.ng/transducers/xform/multiplex"; -import { partition } from "@thi.ng/transducers/xform/partition"; +import { dropdown, DropDownOption } from "@thi.ng/hdom-components"; +import { + bits, + buildKernel2d, + comp, + convolve2d, + lookup2d, + map, + multiplex, + partition, + push, + range2d, + repeatedly, + step, + str, + transduce +} from "@thi.ng/transducers"; const W = 128; const H = 48; @@ -36,80 +39,97 @@ let rules: number[]; // 3x3 convolution kernel (Moore neighborhood) const kernel = buildKernel2d([1, 1, 1, 1, 0, 1, 1, 1, 1], 3, 3); -const setHash = () => (location.hash = rules.join("")); +const setHash = + () => (location.hash = rules.join("")); // build transducer to parse rules from string (e.g. location hash or preset) // (an older version used a preset format w/ "-" to separate rule groups) -const parseRules = step( - comp( - map((x: string) => parseInt(x.replace("-", ""), 2)), - bits(18) - ) -); +const parseRules = + step( + comp( + map((x: string) => parseInt(x.replace("-", ""), 2)), + bits(18) + ) + ); -const applyRules = (raw) => { - if (raw.length >= 18) { - rules = parseRules(raw); - randomizeGrid(); - setHash(); - } -}; +const applyRules = + (raw) => { + if (raw.length >= 18) { + rules = parseRules(raw); + randomizeGrid(); + setHash(); + } + }; // create random bit sequence w/ ones appearing in given probability -const randomSeq = (num, prob = 0.5) => [...repeatedly(() => Math.random() < prob ? 1 : 0, num)]; -const randomizeGrid = (prob = 0.5) => (grid = randomSeq(W * H, prob)); -const randomizeRules = () => { - rules = randomSeq(18); - randomizeGrid(); - setHash(); -}; +const randomSeq = + (num, prob = 0.5) => [...repeatedly(() => Math.random() < prob ? 1 : 0, num)]; + +const randomizeGrid = + (prob = 0.5) => (grid = randomSeq(W * H, prob)); + +const randomizeRules = + () => { + rules = randomSeq(18); + randomizeGrid(); + setHash(); + }; // apply convolution & CA rules (in basically 2 lines of code, i.e. the transducer part!!) // this produces the next generation of the CA // we're using `multiplex` to run 2 transducers in parallel and // produce a tuple of `[neighbor-count, orig-cell-value]` // this tuple is then used to lookup the next cell state using the current rule set -export const convolve = (src: number[], rules: number[], width: number, height: number, rstride = 9, wrap = true) => - transduce( - comp( - multiplex(convolve2d({ src, width, height, kernel, wrap }), map(lookup2d(src, width))), - map(lookup2d(rules, rstride)) - ), - push(), - range2d(width, height) - ); +export const convolve = + (src: number[], rules: number[], width: number, height: number, rstride = 9, wrap = true) => + transduce( + comp( + multiplex( + convolve2d({ src, width, height, kernel, wrap }), + map(lookup2d(src, width)) + ), + map(lookup2d(rules, rstride)) + ), + push(), + range2d(width, height) + ); // format grid values as string -const format = (src: number[], width: number, fill = "\u2588", empty = " ") => - transduce( - comp( - map((x: number) => x ? fill : empty), - partition(width), - map((x) => x.join("")) - ), - str("\n"), - src - ); +const format = + (src: number[], width: number, fill = "\u2588", empty = " ") => + transduce( + comp( + map((x: number) => x ? fill : empty), + partition(width), + map((x) => x.join("")) + ), + str("\n"), + src + ); // event handler for rule edits -const setRule = (i: number, j: number, s: number, rstride = 9) => { - rules[i * rstride + j] = s ? 1 : 0; - setHash(); -}; +const setRule = + (i: number, j: number, s: number, rstride = 9) => { + rules[i * rstride + j] = s ? 1 : 0; + setHash(); + }; // single checkbox component -const checkbox = (x, onchange) => ["input", { type: "checkbox", checked: !!x, onchange }]; +const checkbox = + (x, onchange) => ["input", { type: "checkbox", checked: !!x, onchange }]; // component for single CA rule group (alive / dead FSM) -const ruleBoxes = (prefix, i, rstride = 9) => - ["div", - ["label", prefix], - ...rules - .slice(i * rstride, (i + 1) * rstride) - .map((rule, j) => checkbox(rule, (e) => setRule(i, j, e.target.checked))), - ]; - -const isPreset = (id) => presets.findIndex((x) => x[0] === id) !== -1; +const ruleBoxes = + (prefix, i, rstride = 9) => + ["div", + ["label", prefix], + ...rules + .slice(i * rstride, (i + 1) * rstride) + .map((rule, j) => checkbox(rule, (e) => setRule(i, j, e.target.checked))), + ]; + +const isPreset = + (id) => 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]); diff --git a/examples/cellular-automata/tsconfig.json b/examples/cellular-automata/tsconfig.json index b7d63aedf0..50a1cade93 100644 --- a/examples/cellular-automata/tsconfig.json +++ b/examples/cellular-automata/tsconfig.json @@ -2,6 +2,7 @@ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": ".", + "module": "es6", "target": "es6", "sourceMap": true }, diff --git a/examples/commit-table-ssr/package.json b/examples/commit-table-ssr/package.json index 4290c33267..07fae2ab2e 100644 --- a/examples/commit-table-ssr/package.json +++ b/examples/commit-table-ssr/package.json @@ -8,12 +8,12 @@ "clean": "rm -rf .cache build out", "prep": "yarn clean && mkdir -p out && cp commits.json out", "build-static": "tsc && node build/server/static.js", - "build": "yarn prep && parcel build index.html -d out --no-source-maps --no-cache --detailed-report --public-url ./", + "build": "yarn prep && parcel build index.html -d out --no-source-maps --no-cache --experimental-scope-hoisting --detailed-report --public-url ./", "start": "tsc && node build/server/index.js" }, "devDependencies": { - "parcel-bundler": "^1.10.3", - "terser": "^3.11.0", + "parcel-bundler": "^1.11.0", + "terser": "^3.14.1", "typescript": "^3.2.2" }, "dependencies": { diff --git a/examples/commit-table-ssr/src/client/index.ts b/examples/commit-table-ssr/src/client/index.ts index 0a9bb6abca..ad1b380993 100644 --- a/examples/commit-table-ssr/src/client/index.ts +++ b/examples/commit-table-ssr/src/client/index.ts @@ -1,16 +1,19 @@ import { resolve as resolveMap } from "@thi.ng/resolve-map"; -import { fromInterval } from "@thi.ng/rstream/from/interval"; -import { stream } from "@thi.ng/rstream/stream"; -import { sync } from "@thi.ng/rstream/stream-sync"; -import { resolve as resolvePromise } from "@thi.ng/rstream/subs/resolve"; +import { + fromInterval, + resolve as resolvePromise, + stream, + sync +} from "@thi.ng/rstream"; +import { + add, + conj, + map, + pluck, + throttleTime, + transduce +} from "@thi.ng/transducers"; import { updateDOM } from "@thi.ng/transducers-hdom"; -import { add } from "@thi.ng/transducers/rfn/add"; -import { conj } from "@thi.ng/transducers/rfn/conj"; -import { transduce } from "@thi.ng/transducers/transduce"; -import { map } from "@thi.ng/transducers/xform/map"; -import { pluck } from "@thi.ng/transducers/xform/pluck"; -import { throttleTime } from "@thi.ng/transducers/xform/throttle-time"; - import { AppContext, Commit } from "../common/api"; import { header } from "../common/components/header"; import { link } from "../common/components/link"; diff --git a/examples/commit-table-ssr/src/common/components/repo-table.ts b/examples/commit-table-ssr/src/common/components/repo-table.ts index 13a672c284..a2d6559f26 100644 --- a/examples/commit-table-ssr/src/common/components/repo-table.ts +++ b/examples/commit-table-ssr/src/common/components/repo-table.ts @@ -1,10 +1,11 @@ -import { comp } from "@thi.ng/transducers/func/comp"; -import { repeat } from "@thi.ng/transducers/iter/repeat"; -import { iterator } from "@thi.ng/transducers/iterator"; -import { map } from "@thi.ng/transducers/xform/map"; -import { mapIndexed } from "@thi.ng/transducers/xform/map-indexed"; -import { partitionBy } from "@thi.ng/transducers/xform/partition-by"; - +import { + comp, + iterator, + map, + mapIndexed, + partitionBy, + repeat +} from "@thi.ng/transducers"; import { AppContext, Commit } from "../api"; import { commitLink } from "./commit-link"; import { table } from "./table"; diff --git a/examples/commit-table-ssr/src/common/components/table.ts b/examples/commit-table-ssr/src/common/components/table.ts index 4a32cb6258..3c781ce283 100644 --- a/examples/commit-table-ssr/src/common/components/table.ts +++ b/examples/commit-table-ssr/src/common/components/table.ts @@ -1,7 +1,5 @@ -import { map } from "@thi.ng/transducers/xform/map"; - +import { map, mapcat } from "@thi.ng/transducers"; import { AppContext } from "../api"; -import { mapcat } from "@thi.ng/transducers/xform/mapcat"; const thead = (ctx: AppContext, head: Iterable) => ["thead", diff --git a/examples/commit-table-ssr/src/server/git.ts b/examples/commit-table-ssr/src/server/git.ts index 8120bcca59..de5cd3ff02 100644 --- a/examples/commit-table-ssr/src/server/git.ts +++ b/examples/commit-table-ssr/src/server/git.ts @@ -11,7 +11,6 @@ import { } from "@thi.ng/transducers"; import { execSync } from "child_process"; import { resolve } from "path"; - import { Commit } from "../common/api"; /** diff --git a/examples/commit-table-ssr/src/server/html.ts b/examples/commit-table-ssr/src/server/html.ts index 07781d8d94..d98822d964 100644 --- a/examples/commit-table-ssr/src/server/html.ts +++ b/examples/commit-table-ssr/src/server/html.ts @@ -1,7 +1,6 @@ -import { mergeDeepObj } from "@thi.ng/associative/merge-deep"; +import { mergeDeepObj } from "@thi.ng/associative"; import { serialize } from "@thi.ng/hiccup"; -import { map } from "@thi.ng/transducers/xform/map"; - +import { map } from "@thi.ng/transducers"; import { AppContext, HTMLDoc } from "../common/api"; import { DEFAULT_DOC } from "../common/config"; diff --git a/examples/commit-table-ssr/src/server/index.ts b/examples/commit-table-ssr/src/server/index.ts index 0292329c79..99c1e6b754 100644 --- a/examples/commit-table-ssr/src/server/index.ts +++ b/examples/commit-table-ssr/src/server/index.ts @@ -1,8 +1,7 @@ import { TLRUCache } from "@thi.ng/cache"; import * as express from "express"; -import * as Bundler from "parcel-bundler"; import * as fs from "fs"; - +import * as Bundler from "parcel-bundler"; import { Commit } from "../common/api"; import { ctx } from "../common/config"; import { buildRepoTableHTML } from "./build-table"; diff --git a/examples/commit-table-ssr/src/server/static.ts b/examples/commit-table-ssr/src/server/static.ts index 4170ca5191..8691b1793a 100644 --- a/examples/commit-table-ssr/src/server/static.ts +++ b/examples/commit-table-ssr/src/server/static.ts @@ -1,5 +1,4 @@ import { writeFileSync } from "fs"; - import { ctx } from "../common/config"; import { buildRepoTableHTML } from "./build-table"; import { repoCommits } from "./git"; diff --git a/examples/commit-table-ssr/tsconfig.json b/examples/commit-table-ssr/tsconfig.json index 2210c34a04..5ecdbdef82 100644 --- a/examples/commit-table-ssr/tsconfig.json +++ b/examples/commit-table-ssr/tsconfig.json @@ -1,7 +1,8 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "build", + "outDir": "./build", + "module": "commonjs", "target": "es6", "sourceMap": true }, diff --git a/examples/crypto-chart/README.md b/examples/crypto-chart/README.md index 99d2d52d05..5a4dc6df14 100644 --- a/examples/crypto-chart/README.md +++ b/examples/crypto-chart/README.md @@ -24,12 +24,9 @@ The diagram below shows a schematic of the dataflow graph used: ## Building -```bash -git clone https://github.com/thi-ng/umbrella.git -cd umbrella/examples/crypto-chart -yarn install -yarn start -``` +Please refer to the [example build +instructions](https://github.com/thi-ng/umbrella/wiki/Example-build-instructions) +on the wiki. ## Authors diff --git a/examples/crypto-chart/package.json b/examples/crypto-chart/package.json index ab1c7c6525..0cacc2d8cc 100644 --- a/examples/crypto-chart/package.json +++ b/examples/crypto-chart/package.json @@ -6,23 +6,22 @@ "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 --detailed-report --public-url ./", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --experimental-scope-hoisting --detailed-report --public-url ./", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { - "parcel-bundler": "^1.10.3", - "terser": "^3.11.0", + "parcel-bundler": "^1.11.0", + "terser": "^3.14.1", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/api": "latest", - "@thi.ng/hdom": "latest", "@thi.ng/hdom-components": "latest", "@thi.ng/hiccup-svg": "latest", "@thi.ng/resolve-map": "latest", "@thi.ng/rstream": "latest", "@thi.ng/strings": "latest", "@thi.ng/transducers": "latest", + "@thi.ng/transducers-hdom": "latest", "@thi.ng/transducers-stats": "latest" }, "browserslist": [ diff --git a/examples/crypto-chart/src/index.ts b/examples/crypto-chart/src/index.ts index 9566131cb8..49d2ff9408 100644 --- a/examples/crypto-chart/src/index.ts +++ b/examples/crypto-chart/src/index.ts @@ -1,36 +1,44 @@ -import { dropdown, DropDownOption } from "@thi.ng/hdom-components/dropdown"; -import { group } from "@thi.ng/hiccup-svg/group"; -import { line } from "@thi.ng/hiccup-svg/line"; -import { polygon } from "@thi.ng/hiccup-svg/polygon"; -import { polyline } from "@thi.ng/hiccup-svg/polyline"; -import { rect } from "@thi.ng/hiccup-svg/rect"; -import { svg } from "@thi.ng/hiccup-svg/svg"; -import { text } from "@thi.ng/hiccup-svg/text"; +import { dropdown, DropDownOption } from "@thi.ng/hdom-components"; +import { + group, + line, + polygon, + polyline, + rect, + svg, + text +} from "@thi.ng/hiccup-svg"; import { resolve } from "@thi.ng/resolve-map"; -import { fromEvent } from "@thi.ng/rstream/from/event"; -import { fromInterval } from "@thi.ng/rstream/from/interval"; -import { stream } from "@thi.ng/rstream/stream"; -import { sync } from "@thi.ng/rstream/stream-sync"; -import { resolve as resolvePromise } from "@thi.ng/rstream/subs/resolve"; -import { trace } from "@thi.ng/rstream/subs/trace"; -import { padLeft } from "@thi.ng/strings/pad-left"; +import { + fromEvent, + fromInterval, + resolve as resolvePromise, + stream, + sync, + trace +} from "@thi.ng/rstream"; +import { padLeft } from "@thi.ng/strings"; +import { + comp, + filter, + map, + mapcat, + mapIndexed, + max, + min, + pairs, + pluck, + push, + range, + transduce +} from "@thi.ng/transducers"; import { updateDOM } from "@thi.ng/transducers-hdom"; -import { ema } from "@thi.ng/transducers-stats/ema"; -import { hma } from "@thi.ng/transducers-stats/hma"; -import { sma } from "@thi.ng/transducers-stats/sma"; -import { wma } from "@thi.ng/transducers-stats/wma"; -import { comp } from "@thi.ng/transducers/func/comp"; -import { pairs } from "@thi.ng/transducers/iter/pairs"; -import { range } from "@thi.ng/transducers/iter/range"; -import { max } from "@thi.ng/transducers/rfn/max"; -import { min } from "@thi.ng/transducers/rfn/min"; -import { push } from "@thi.ng/transducers/rfn/push"; -import { transduce } from "@thi.ng/transducers/transduce"; -import { filter } from "@thi.ng/transducers/xform/filter"; -import { map } from "@thi.ng/transducers/xform/map"; -import { mapIndexed } from "@thi.ng/transducers/xform/map-indexed"; -import { mapcat } from "@thi.ng/transducers/xform/mapcat"; -import { pluck } from "@thi.ng/transducers/xform/pluck"; +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 diff --git a/examples/crypto-chart/tsconfig.json b/examples/crypto-chart/tsconfig.json index b7d63aedf0..50a1cade93 100644 --- a/examples/crypto-chart/tsconfig.json +++ b/examples/crypto-chart/tsconfig.json @@ -2,6 +2,7 @@ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": ".", + "module": "es6", "target": "es6", "sourceMap": true }, diff --git a/examples/dashboard/README.md b/examples/dashboard/README.md index 652fa64438..c9c6ab7576 100644 --- a/examples/dashboard/README.md +++ b/examples/dashboard/README.md @@ -2,9 +2,6 @@ [Live demo here](https://demo.thi.ng/umbrella/dashboard/) -```bash -git clone https://github.com/thi-ng/umbrella.git -cd umbrella/examples/dashboard -yarn install -yarn start -``` +Please refer to the [example build +instructions](https://github.com/thi-ng/umbrella/wiki/Example-build-instructions) +on the wiki. diff --git a/examples/dashboard/package.json b/examples/dashboard/package.json index 8dd96ed989..30bb565e92 100644 --- a/examples/dashboard/package.json +++ b/examples/dashboard/package.json @@ -6,12 +6,12 @@ "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 --detailed-report --public-url ./", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --experimental-scope-hoisting --detailed-report --public-url ./", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { - "parcel-bundler": "^1.10.3", - "terser": "^3.11.0", + "parcel-bundler": "^1.11.0", + "terser": "^3.14.1", "typescript": "^3.2.2" }, "dependencies": { diff --git a/examples/dashboard/tsconfig.json b/examples/dashboard/tsconfig.json index b7d63aedf0..50a1cade93 100644 --- a/examples/dashboard/tsconfig.json +++ b/examples/dashboard/tsconfig.json @@ -2,6 +2,7 @@ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": ".", + "module": "es6", "target": "es6", "sourceMap": true }, diff --git a/examples/devcards/README.md b/examples/devcards/README.md index 1ac1638f32..e8852251d3 100644 --- a/examples/devcards/README.md +++ b/examples/devcards/README.md @@ -2,9 +2,6 @@ [Live demo](https://demo.thi.ng/umbrella/devcards/) -```bash -git clone https://github.com/thi-ng/umbrella.git -cd umbrella/examples/devcards -yarn install -yarn start -``` +Please refer to the [example build +instructions](https://github.com/thi-ng/umbrella/wiki/Example-build-instructions) +on the wiki. diff --git a/examples/devcards/package.json b/examples/devcards/package.json index 1b56495ea9..515ed8e2c5 100644 --- a/examples/devcards/package.json +++ b/examples/devcards/package.json @@ -6,12 +6,12 @@ "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 --detailed-report --public-url ./", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --experimental-scope-hoisting --detailed-report --public-url ./", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { - "parcel-bundler": "^1.10.3", - "terser": "^3.11.0", + "parcel-bundler": "^1.11.0", + "terser": "^3.14.1", "typescript": "^3.2.2" }, "dependencies": { diff --git a/examples/devcards/src/index.ts b/examples/devcards/src/index.ts index 0db3e0b898..c49e03c7ed 100644 --- a/examples/devcards/src/index.ts +++ b/examples/devcards/src/index.ts @@ -1,6 +1,5 @@ -import { IAtom } from "@thi.ng/atom/api"; -import { Atom } from "@thi.ng/atom/atom"; -import { Cursor } from "@thi.ng/atom/cursor"; +import { IAtom } from "@thi.ng/atom"; +import { Atom, Cursor } from "@thi.ng/atom"; import { start } from "@thi.ng/hdom"; type CardFn = (state: IAtom) => any; diff --git a/examples/devcards/tsconfig.json b/examples/devcards/tsconfig.json index b7d63aedf0..50a1cade93 100644 --- a/examples/devcards/tsconfig.json +++ b/examples/devcards/tsconfig.json @@ -2,6 +2,7 @@ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": ".", + "module": "es6", "target": "es6", "sourceMap": true }, diff --git a/examples/geom-knn/README.md b/examples/geom-knn/README.md index 941f574ecb..395bb29744 100644 --- a/examples/geom-knn/README.md +++ b/examples/geom-knn/README.md @@ -10,12 +10,13 @@ up to 200 neighboring points. Those points are highlighted in blue. For each of those a secondary KNN search is performed selecting up to 8 neighbors. These matches are visualized as lines. -```bash -git clone https://github.com/thi-ng/umbrella.git -cd umbrella/examples/geom-knn -yarn install -yarn start -``` +Please refer to the [example build +instructions](https://github.com/thi-ng/umbrella/wiki/Example-build-instructions) +on the wiki. + +**IMPORTANT:** Please also see the [troubleshooting +note](https://github.com/thi-ng/umbrella/wiki/Example-build-instructions#troubleshooting) +and temporary workaround for this example. ## Authors diff --git a/examples/geom-knn/package.json b/examples/geom-knn/package.json index 6beffe1a45..ac4ce070a9 100644 --- a/examples/geom-knn/package.json +++ b/examples/geom-knn/package.json @@ -6,12 +6,12 @@ "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": "yarn clean && parcel build index.html -d out --public-url ./ --no-source-maps --no-cache --experimental-scope-hoisting --detailed-report", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { - "parcel-bundler": "^1.10.3", - "terser": "^3.11.0", + "parcel-bundler": "^1.11.0", + "terser": "^3.14.1", "typescript": "^3.2.2" }, "dependencies": { diff --git a/examples/geom-knn/src/index.ts b/examples/geom-knn/src/index.ts index 44d45482ad..06282c8fce 100644 --- a/examples/geom-knn/src/index.ts +++ b/examples/geom-knn/src/index.ts @@ -1,13 +1,11 @@ import { timedResult } from "@thi.ng/bench"; -import { KdTree } from "@thi.ng/geom-accel/kdtree"; +import { KdTree } from "@thi.ng/geom-accel"; import { canvas } from "@thi.ng/hdom-canvas"; +import { sync, trigger } from "@thi.ng/rstream"; import { gestureStream } from "@thi.ng/rstream-gestures"; -import { sync } from "@thi.ng/rstream/stream-sync"; -import { trigger } from "@thi.ng/rstream/trigger"; +import { map, mapcat } from "@thi.ng/transducers"; import { updateDOM } from "@thi.ng/transducers-hdom"; -import { map } from "@thi.ng/transducers/xform/map"; -import { mapcat } from "@thi.ng/transducers/xform/mapcat"; -import { asVec2, Vec2 } from "@thi.ng/vectors/vec2"; +import { Vec } from "@thi.ng/vectors"; const app = (main) => { // augment hdom-canvas component w/ `init` lifecycle method: this is @@ -24,7 +22,7 @@ const app = (main) => { // initialize 1st point & store in tree for fast KNN searches const width = window.innerWidth; const height = window.innerHeight; - let tree = new KdTree(2); + let tree = new KdTree(2); // return root component function, triggered by each new mouse / touch event return ({ mpos }) => { @@ -36,24 +34,25 @@ const app = (main) => { // `trigger()` stream defined further below. that means // initially, there will be no valid `mpos` and so we insert a // default point instead - mpos = mpos ? asVec2(mpos) : new Vec2([width / 2, height / 2, 5]); + mpos = mpos || [width / 2, height / 2]; // record new pos in tree - tree.addKey(mpos); + tree.add(mpos, 1.5 + Math.random() * 5); // even though we only create 2d vectors, we store a 3rd value // in the backing array, which will be later used as radius when // the point has been selected as part of a KNN query and is // visualized as circle. - mpos.buf.push(1.5 + Math.random() * 5); + // mpos.push(1.5 + Math.random() * 5); + // select max. 200 neighbors for given mouse position, // measure execution time... let [selected, t1] = timedResult(() => - tree.selectKeys(mpos, 200, width / 4) + tree.select(mpos, 200, width / 4) ); // for each selected neighbor, perform another KNN search and // create line segments to each of these secondary matches // use `mapcat` to yield a flat array of lines let [neighbors, t2] = timedResult(() => - [...mapcat((p) => tree.selectKeys(p, 8, width / 4).map((q) => ["line", {}, p, q]), selected)] + [...mapcat((p) => tree.selectKeys(p[0], 8, width / 4).map((q) => ["line", {}, p[0], q]), selected)] ); return ["div.overflow-hidden.sans-serif.f7", // tree stats @@ -69,7 +68,7 @@ const app = (main) => { ["points", { fill: "black" }, tree.keys()], // selected points as circles (using 3rd array item as radius) ["g", { fill: "rgba(0,192,255,0.5)" }, - ...selected.map((p) => ["circle", {}, p, p.buf[2]])], + ...selected.map((p) => ["circle", {}, p[0], p[1]])], // secondary neighbor connections ["g", { stroke: "rgba(0,0,0,0.25)" }, ...neighbors]]]; diff --git a/examples/geom-knn/tsconfig.json b/examples/geom-knn/tsconfig.json index bbf112cc18..50a1cade93 100644 --- a/examples/geom-knn/tsconfig.json +++ b/examples/geom-knn/tsconfig.json @@ -2,10 +2,11 @@ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": ".", + "module": "es6", "target": "es6", "sourceMap": true }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/examples/geom-tessel/README.md b/examples/geom-tessel/README.md index f33a8c6287..ec07408b62 100644 --- a/examples/geom-tessel/README.md +++ b/examples/geom-tessel/README.md @@ -11,12 +11,13 @@ Note the lack of explicit hiccup shape defs in this example. All @thi.ng/geom types support auto-conversion via the [`IToHiccup` interface](https://github.com/thi-ng/umbrella/blob/master/packages/api/src/api.ts#L415). -```bash -git clone https://github.com/thi-ng/umbrella.git -cd umbrella/examples/geom-tessel -yarn install -yarn start -``` +Please refer to the [example build +instructions](https://github.com/thi-ng/umbrella/wiki/Example-build-instructions) +on the wiki. + +**IMPORTANT:** Please also see the [troubleshooting +note](https://github.com/thi-ng/umbrella/wiki/Example-build-instructions#troubleshooting) +and temporary workaround for this example. ## Authors diff --git a/examples/geom-tessel/package.json b/examples/geom-tessel/package.json index 3f6496ff04..b6a007b4cd 100644 --- a/examples/geom-tessel/package.json +++ b/examples/geom-tessel/package.json @@ -6,18 +6,21 @@ "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": "yarn clean && parcel build index.html -d out --public-url ./ --no-source-maps --no-cache --experimental-scope-hoisting --detailed-report", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { - "parcel-bundler": "^1.10.3", - "terser": "^3.11.0", + "parcel-bundler": "^1.11.0", + "terser": "^3.14.1", "typescript": "^3.2.2" }, "dependencies": { "@thi.ng/compose": "latest", "@thi.ng/geom": "latest", - "@thi.ng/hdom-canvas": "latest" + "@thi.ng/hdom": "latest", + "@thi.ng/hdom-canvas": "latest", + "@thi.ng/math": "latest", + "@thi.ng/vectors": "latest" }, "browserslist": [ "last 3 Chrome versions" diff --git a/examples/geom-tessel/src/index.ts b/examples/geom-tessel/src/index.ts index 3e11ac592c..5f929e179a 100644 --- a/examples/geom-tessel/src/index.ts +++ b/examples/geom-tessel/src/index.ts @@ -1,16 +1,36 @@ import { partial } from "@thi.ng/compose/partial"; -import { IArcLength, ICentroid, Tessellator } from "@thi.ng/geom/api"; -import { circle2 } from "@thi.ng/geom/circle2"; -import { polygon2, Polygon2 } from "@thi.ng/geom/polygon2"; -import { edgeSplit, quadFan, triFan } from "@thi.ng/geom/tessellate"; +import { + arcLength, + asPolygon, + centroid, + circle, + IShape, + Polygon, + polygon, + tesselEdgeSplit, + tessellate, + Tessellator, + tesselQuadFan, + tesselTriFan +} from "@thi.ng/geom"; import { canvas } from "@thi.ng/hdom-canvas"; -import { start } from "@thi.ng/hdom/start"; -import { deg } from "@thi.ng/math/angle"; -import { TAU } from "@thi.ng/math/api"; -import { fit01 } from "@thi.ng/math/fit"; -import { Vec2 } from "@thi.ng/vectors/vec2"; +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: Polygon2) => string; +type Tint = (p: Polygon) => string; + +const MIN_RES = 3; +const MAX_RES = 30; +// const MAX_RES = MIN_RES; + +// const SUBDIVS = [tesselQuadFan]; +// const SUBDIVS = [tesselTriFan]; +// const SUBDIVS = [tesselEdgeSplit]; +const SUBDIVS = [tesselQuadFan, tesselTriFan, tesselEdgeSplit, tesselQuadFan]; +// const SUBDIVS = [...take(4, cycle([tesselQuadFan]))]; const W = 600; const W2 = W / 2; @@ -19,11 +39,11 @@ const W2 = W / 2; * Creates a color by mapping the centroid of given shape from cartesian * space to HSL. */ -const centroidToHSL = (p: ICentroid) => { - const c = p.centroid().toPolar(); - const h = deg(c.y); - const s = fit01(c.x / W2, 0, 100); - const l = fit01(c.x / W2, 100, 50); +const centroidToHSL = (p: IShape) => { + 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); return `hsl(${h},${s}%,${l}%)`; }; @@ -31,56 +51,72 @@ const centroidToHSL = (p: ICentroid) => { * Creates an HSL color from the arc length / circumference of the given * shape. */ -const arclengthToHSL = (max: number, p: IArcLength) => - `hsl(${fit01(p.arcLength() / max, 0, 360)},100%,50%)`; +const arclengthToHSL = (max: number, p: IShape) => + `hsl(${fit01(arcLength(p) / max, 0, 360)},100%,50%)`; /** * Converts given point array into a polygon and computes fill color * with provided `tint` function. */ -const tintedPoly = (tint: Tint, points: Vec2[]) => { - const p = polygon2(points); - p.attribs = { fill: tint(p) }; +const tintedPoly = (tint: Tint, points: Vec[]) => { + const p = polygon(points); + p.attribs = { + fill: tint(p), + // stroke: tint(p), + }; return p; }; /** * Creates a regular polygon, then recursively subdivides it and tints */ -const tessellation = (t: number, tessel: Tessellator[], tint: Tint) => { - return circle2(W2) - .toPolygon(Math.floor(12 + 9 * Math.sin(t))) - .tessellate(tessel) - .map(partial(tintedPoly, tint)); +const tessellation = (t: number, tessel: Tessellator[], tint: Tint) => { + return tessellate( + asPolygon( + circle([0, 0], W2), + Math.floor(fit11(Math.sin(t), MIN_RES, MAX_RES)) + ), + tessel + ).map(partial(tintedPoly, tint)); }; -const cancel = start(() => { - const t = Date.now() * 0.005; - // create tessellation - // resulting array contains Polygon2 values - // Polygon2 implements the .toHiccup() method for - // auto-conversion during hdom tree normalization - const cells = tessellation( - t, - [quadFan, triFan, edgeSplit, quadFan], - partial(arclengthToHSL, 250) - ); - return ["div.ma2.sans-serif", - ["div", `Cells: ${cells.length}`], - [canvas, - { width: 600, height: 600 }, - ["g", - { - translate: [300, 300], - rotate: (t / 10) % TAU, - stroke: "#000", - weight: 0.25 - }, - ...cells]]]; -}); +const main = sync({ + src: { + time: fromInterval(16), + } +}).transform( + // root component function + map(({ time }) => { + time *= 0.1; + // create tessellation + // resulting array contains Polygon2 values + // Polygon2 implements the .toHiccup() method for + // auto-conversion during hdom tree normalization + const cells = tessellation( + time, + SUBDIVS, + partial(arclengthToHSL, 250) + ); + return ["div.ma2.sans-serif", + ["div", `Cells: ${cells.length}`], + [canvas, + { width: 600, height: 600 }, + // ["polygon", { stroke: "black" }, vertices(asPolygon(circle([300, 300], 300), 3))], + ["g", + { + translate: [300, 300], + // rotate: (time / 10) % TAU, + stroke: "#000", + weight: 0.25 + }, + ...cells] + ]]; + }), + updateDOM() +); // HMR handling if (process.env.NODE_ENV !== "production") { const hot = (module).hot; - hot && hot.dispose(cancel); + hot && hot.dispose(() => main.done()); } diff --git a/examples/geom-tessel/tsconfig.json b/examples/geom-tessel/tsconfig.json index bbf112cc18..440ebac19c 100644 --- a/examples/geom-tessel/tsconfig.json +++ b/examples/geom-tessel/tsconfig.json @@ -2,10 +2,13 @@ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": ".", + "module": "es6", "target": "es6", - "sourceMap": true + "sourceMap": true, + "noUnusedLocals": false, + "noUnusedParameters": false, }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/examples/gesture-analysis/README.md b/examples/gesture-analysis/README.md index 850d99da18..1105260ee7 100644 --- a/examples/gesture-analysis/README.md +++ b/examples/gesture-analysis/README.md @@ -10,12 +10,13 @@ constructs and **Note: Currently only really works on desktop until I figured out a way to better attach touch events...** -```bash -git clone https://github.com/thi-ng/umbrella.git -cd umbrella/examples/gesture-analysis -yarn install -yarn start -``` +Please refer to the [example build +instructions](https://github.com/thi-ng/umbrella/wiki/Example-build-instructions) +on the wiki. + +**IMPORTANT:** Please also see the [troubleshooting +note](https://github.com/thi-ng/umbrella/wiki/Example-build-instructions#troubleshooting) +and temporary workaround for this example. ## Authors diff --git a/examples/gesture-analysis/package.json b/examples/gesture-analysis/package.json index 3ed3783c76..8c0a4f1ff9 100644 --- a/examples/gesture-analysis/package.json +++ b/examples/gesture-analysis/package.json @@ -6,12 +6,12 @@ "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 --detailed-report --public-url ./", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --experimental-scope-hoisting --detailed-report --public-url ./", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { - "parcel-bundler": "^1.10.3", - "terser": "^3.11.0", + "parcel-bundler": "^1.11.0", + "terser": "^3.14.1", "typescript": "^3.2.2" }, "dependencies": { diff --git a/examples/gesture-analysis/src/config.ts b/examples/gesture-analysis/src/config.ts index b03ccf284d..6739761ec3 100644 --- a/examples/gesture-analysis/src/config.ts +++ b/examples/gesture-analysis/src/config.ts @@ -1,5 +1,4 @@ -import { transformVectors1 } from "@thi.ng/vectors/common"; -import { mul2, Vec2 } from "@thi.ng/vectors/vec2"; +import { Vec2 } from "@thi.ng/vectors"; // initial call to action gesture // (recorded handwriting) @@ -64,7 +63,4 @@ const raw = [ ]; // downscale & transform into memory mapped Vec2 array -export const CTA = Vec2.mapBuffer( - transformVectors1(mul2, raw, [0.75, 0.75], raw.length / 2, 2), - raw.length / 2 -); +export const CTA = Vec2.mapBuffer(raw, raw.length / 2); diff --git a/examples/gesture-analysis/src/index.ts b/examples/gesture-analysis/src/index.ts index 124f311b04..a050fb83dc 100644 --- a/examples/gesture-analysis/src/index.ts +++ b/examples/gesture-analysis/src/index.ts @@ -1,23 +1,30 @@ -import { circle } from "@thi.ng/hiccup-svg/circle"; -import { group } from "@thi.ng/hiccup-svg/group"; -import { polyline } from "@thi.ng/hiccup-svg/polyline"; -import { svg } from "@thi.ng/hiccup-svg/svg"; +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"; -import { fromIterable } from "@thi.ng/rstream/from/iterable"; -import { merge } from "@thi.ng/rstream/stream-merge"; -import { sync } from "@thi.ng/rstream/stream-sync"; +import { + comp, + filter, + identity, + map, + multiplexObj, + partition, + peek, + push, + transduce +} from "@thi.ng/transducers"; import { updateDOM } from "@thi.ng/transducers-hdom"; -import { comp } from "@thi.ng/transducers/func/comp"; -import { identity } from "@thi.ng/transducers/func/identity"; -import { peek } from "@thi.ng/transducers/func/peek"; -import { push } from "@thi.ng/transducers/rfn/push"; -import { transduce } from "@thi.ng/transducers/transduce"; -import { filter } from "@thi.ng/transducers/xform/filter"; -import { map } from "@thi.ng/transducers/xform/map"; -import { multiplexObj } from "@thi.ng/transducers/xform/multiplex-obj"; -import { partition } from "@thi.ng/transducers/xform/partition"; -import { Vec2 } from "@thi.ng/vectors/vec2"; - +import { + angleBetween2, + mixN2, + sub2, + Vec +} from "@thi.ng/vectors"; import { CTA } from "./config"; /** @@ -27,23 +34,24 @@ import { CTA } from "./config"; * @param raw * @param processed */ -const app = ({ raw, processed }) => - ["div", - svg( - { - width: window.innerWidth, - height: window.innerHeight, - stroke: "none", - fill: "none", - }, - path(raw || [], processed.path, processed.corners || []) - ), - ["div.fixed.top-0.left-0.ma3", - ["div", `raw: ${(raw && raw.length) || 0}`], - ["div", `resampled: ${(processed && processed.path.length) || 0}`], - ["div", `corners: ${(processed && processed.corners.length) || 0}`], - ] - ]; +const app = + ({ raw, processed }) => + ["div", + svg( + { + width: window.innerWidth, + height: window.innerHeight, + stroke: "none", + fill: "none", + }, + path(raw || [], processed.path, processed.corners || []) + ), + ["div.fixed.top-0.left-0.ma3", + ["div", `raw: ${(raw && raw.length) || 0}`], + ["div", `resampled: ${(processed && processed.path.length) || 0}`], + ["div", `corners: ${(processed && processed.corners.length) || 0}`], + ] + ]; /** * Gesture visualization component. Creates an SVG group of shape @@ -53,16 +61,17 @@ const app = ({ raw, processed }) => * @param sampled resampled path * @param corners array of corner points */ -const path = (raw: Vec2[], sampled: Vec2[], corners: Vec2[]) => - group({}, - polyline(raw, { stroke: "#444" }), - map((p) => circle(p, 2, { fill: "#444" }), raw), - polyline(sampled, { stroke: "#fff" }), - map((p) => circle(p, 2, { fill: "#fff" }), sampled), - map((p) => circle(p, 6, { fill: "#cf0" }), corners), - circle(sampled[0], 6, { fill: "#f0c" }), - circle(peek(sampled), 6, { fill: "#0cf" }), - ); +const path = + (raw: Vec[], sampled: Vec[], corners: Vec[]) => + group({ __diff: false }, + polyline(raw, { stroke: "#444" }), + map((p) => circle(p, 2, { fill: "#444" }), raw), + polyline(sampled, { stroke: "#fff" }), + map((p) => circle(p, 2, { fill: "#fff" }), sampled), + map((p) => circle(p, 6, { fill: "#cf0" }), corners), + circle(sampled[0], 6, { fill: "#f0c" }), + circle(peek(sampled), 6, { fill: "#0cf" }), + ); /** * Re-samples given polyline at given uniform distance. Returns array of @@ -71,21 +80,9 @@ const path = (raw: Vec2[], sampled: Vec2[], corners: Vec2[]) => * @param step sample distance * @param pts */ -const sampleUniform = (step: number, pts: Vec2[]) => { - if (!pts.length) return []; - let prev = pts[0]; - const res: Vec2[] = [prev]; - for (let i = 1, n = pts.length; i < n; prev = peek(res), i++) { - const p = pts[i]; - let d = p.dist(prev); - while (d >= step) { - res.push(prev = prev.copy().mixN(p, step / d)); - d -= step; - } - } - res.push(peek(pts)); - return res; -}; +const sampleUniform = + (step: number, pts: Vec[]) => + vertices(resample(gPolyline(pts), { dist: step })); /** * Applies low-pass filter to given polyline. I.e. Each point in the @@ -94,13 +91,14 @@ const sampleUniform = (step: number, pts: Vec2[]) => { * * @param path */ -const smoothPath = (smooth: number, path: Vec2[]) => { - const res: Vec2[] = [path[0]]; - for (let i = 1, n = path.length; i < n; i++) { - res.push(path[i].copy().mixN(res[i - 1], smooth)); - } - return res; -}; +const smoothPath = + (smooth: number, path: Vec[]) => { + const res: Vec[] = [path[0]]; + for (let i = 1, n = path.length; i < n; i++) { + res.push(mixN2([], path[i], res[i - 1], smooth)); + } + return res; + }; /** * Corner detector HOF. Returns new function which takes 3 successive @@ -108,34 +106,31 @@ const smoothPath = (smooth: number, path: Vec2[]) => { * * @param thresh normalized angle threshold */ -const isCorner = (thresh: number) => { - thresh = Math.PI * (1 - thresh); - return ([a, b, c]: Vec2[]) => - b.copy().sub(a).angleBetween(b.copy().sub(c), true) < thresh; -}; +const isCorner = + (thresh: number) => + ([a, b, c]: Vec[]) => + angleBetween2(sub2([], b, a), sub2([], b, c), true) < thresh; /** * Gesture event processor. Collects gesture event positions into an * array of Vec2. */ -const collectPath = () => { - let pts: Vec2[] = []; - return (g: GestureEvent) => { - const pos = new Vec2(g[1].pos); - switch (g[0]) { - case GestureType.START: - pts = [pos]; - break; - case GestureType.DRAG: - pts.push(pos); - break; - // uncomment to destroy path on mouseup / touchend - // case GestureType.END: - // pts = []; +const collectPath = + () => { + let pts: Vec[] = []; + return (g: GestureEvent) => { + const pos = g[1].pos; + switch (g[0]) { + case GestureType.START: + pts = [pos]; + break; + case GestureType.DRAG: + pts.push(pos); + break; + } + return pts; } - return pts; - } -}; + }; // gesture input stream(s) const gesture = merge({ @@ -166,15 +161,15 @@ sync({ raw: gesture, processed: gesture.transform( comp( - map((pts: Vec2[]) => smoothPath(3 / 4, pts)), - map((pts: Vec2[]) => sampleUniform(20, pts)), + map((pts: Vec[]) => smoothPath(3 / 4, pts)), + map((pts: Vec[]) => sampleUniform(20, pts)), multiplexObj({ path: map(identity), corners: map( (pts) => transduce( comp( partition(3, 1), - filter(isCorner(1 / 4)), + filter(isCorner(Math.PI * 2 / 3)), map((x) => x[1]) ), push(), @@ -191,3 +186,6 @@ sync({ // update UI diff updateDOM() ); + +window["v"] = require("@thi.ng/vectors"); +window["m"] = require("@thi.ng/math"); \ No newline at end of file diff --git a/examples/gesture-analysis/tsconfig.json b/examples/gesture-analysis/tsconfig.json index b7d63aedf0..50a1cade93 100644 --- a/examples/gesture-analysis/tsconfig.json +++ b/examples/gesture-analysis/tsconfig.json @@ -2,6 +2,7 @@ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": ".", + "module": "es6", "target": "es6", "sourceMap": true }, diff --git a/examples/hdom-basics/README.md b/examples/hdom-basics/README.md index d3137177d5..a4e78c004a 100644 --- a/examples/hdom-basics/README.md +++ b/examples/hdom-basics/README.md @@ -2,9 +2,14 @@ [Live demo](https://demo.thi.ng/umbrella/hdom-basics/) -```bash -git clone https://github.com/thi-ng/umbrella.git -cd umbrella/examples/hdom-basics -yarn install -yarn start -``` +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/hdom-basics/package.json b/examples/hdom-basics/package.json index 0f8e338544..5802e501d6 100644 --- a/examples/hdom-basics/package.json +++ b/examples/hdom-basics/package.json @@ -6,12 +6,12 @@ "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 --detailed-report --public-url ./", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --experimental-scope-hoisting --detailed-report --public-url ./", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { - "parcel-bundler": "^1.10.3", - "terser": "^3.11.0", + "parcel-bundler": "^1.11.0", + "terser": "^3.14.1", "typescript": "^3.2.2" }, "dependencies": { diff --git a/examples/hdom-basics/src/index.ts b/examples/hdom-basics/src/index.ts index d75a570397..5ff0052bd8 100644 --- a/examples/hdom-basics/src/index.ts +++ b/examples/hdom-basics/src/index.ts @@ -1,4 +1,4 @@ -import * as hdom from "@thi.ng/hdom"; +import { start } from "@thi.ng/hdom"; // stateless component w/ params // the first arg is an auto-injected context object @@ -18,7 +18,7 @@ const app = () => { }; // start update loop (browser only, see diagram below) -hdom.start(app()); +start(app()); // alternatively apply DOM tree only once // (stateful components won't update though) diff --git a/examples/hdom-basics/tsconfig.json b/examples/hdom-basics/tsconfig.json index b7d63aedf0..50a1cade93 100644 --- a/examples/hdom-basics/tsconfig.json +++ b/examples/hdom-basics/tsconfig.json @@ -2,6 +2,7 @@ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": ".", + "module": "es6", "target": "es6", "sourceMap": true }, diff --git a/examples/hdom-benchmark/README.md b/examples/hdom-benchmark/README.md index 14b269d669..7c259cfa1e 100644 --- a/examples/hdom-benchmark/README.md +++ b/examples/hdom-benchmark/README.md @@ -2,9 +2,14 @@ [Live demo](https://demo.thi.ng/umbrella/hdom-benchmark/) -```bash -git clone https://github.com/thi-ng/umbrella.git -cd umbrella/examples/hdom-benchmark -yarn install -yarn start -``` \ No newline at end of file +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/hdom-benchmark/package.json b/examples/hdom-benchmark/package.json index 69b6e84237..5f64b8531a 100644 --- a/examples/hdom-benchmark/package.json +++ b/examples/hdom-benchmark/package.json @@ -6,16 +6,15 @@ "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 --detailed-report --public-url ./", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --experimental-scope-hoisting --detailed-report --public-url ./", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { - "parcel-bundler": "^1.10.3", - "terser": "^3.11.0", + "parcel-bundler": "^1.11.0", + "terser": "^3.14.1", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/api": "latest", "@thi.ng/hdom": "latest", "@thi.ng/hdom-components": "latest", "@thi.ng/rstream": "latest", diff --git a/examples/hdom-benchmark/src/index.ts b/examples/hdom-benchmark/src/index.ts index e8bcc63db4..97ffd9290e 100644 --- a/examples/hdom-benchmark/src/index.ts +++ b/examples/hdom-benchmark/src/index.ts @@ -1,15 +1,16 @@ import { start } from "@thi.ng/hdom"; -import { dropdown } from "@thi.ng/hdom-components/dropdown"; -import { fromRAF } from "@thi.ng/rstream/from/raf"; -import { Stream } from "@thi.ng/rstream/stream"; -import { radix } from "@thi.ng/strings/radix"; -import { comp } from "@thi.ng/transducers/func/comp"; -import { range } from "@thi.ng/transducers/iter/range"; -import { benchmark } from "@thi.ng/transducers/xform/benchmark"; -import { map } from "@thi.ng/transducers/xform/map"; -import { mapIndexed } from "@thi.ng/transducers/xform/map-indexed"; -import { movingAverage } from "@thi.ng/transducers/xform/moving-average"; -import { partition } from "@thi.ng/transducers/xform/partition"; +import { dropdown } from "@thi.ng/hdom-components"; +import { fromRAF, Stream } from "@thi.ng/rstream"; +import { radix } from "@thi.ng/strings"; +import { + benchmark, + comp, + map, + mapIndexed, + movingAverage, + partition, + range +} from "@thi.ng/transducers"; // pre-defined hex formatters const hex4 = radix(16, 4); diff --git a/examples/hdom-benchmark/tsconfig.json b/examples/hdom-benchmark/tsconfig.json index b7d63aedf0..50a1cade93 100644 --- a/examples/hdom-benchmark/tsconfig.json +++ b/examples/hdom-benchmark/tsconfig.json @@ -2,6 +2,7 @@ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": ".", + "module": "es6", "target": "es6", "sourceMap": true }, diff --git a/examples/hdom-benchmark2/README.md b/examples/hdom-benchmark2/README.md index f08f0c4cff..ff2d2933f1 100644 --- a/examples/hdom-benchmark2/README.md +++ b/examples/hdom-benchmark2/README.md @@ -2,12 +2,9 @@ [Live demo](http://demo.thi.ng/umbrella/hdom-benchmark2/) -```bash -git clone https://github.com/thi-ng/umbrella.git -cd umbrella/examples/hdom-benchmark2 -yarn install -yarn start -``` +Please refer to the [example build +instructions](https://github.com/thi-ng/umbrella/wiki/Example-build-instructions) +on the wiki. ## Authors diff --git a/examples/hdom-benchmark2/package.json b/examples/hdom-benchmark2/package.json index a026e49776..4eee0ca969 100644 --- a/examples/hdom-benchmark2/package.json +++ b/examples/hdom-benchmark2/package.json @@ -6,12 +6,12 @@ "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": "yarn clean && parcel build index.html -d out --public-url ./ --no-source-maps --no-cache --experimental-scope-hoisting --detailed-report", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { - "parcel-bundler": "^1.10.3", - "terser": "^3.11.0", + "parcel-bundler": "^1.11.0", + "terser": "^3.14.1", "typescript": "^3.2.2" }, "dependencies": { diff --git a/examples/hdom-benchmark2/src/index.ts b/examples/hdom-benchmark2/src/index.ts index 3b9328f071..29d2d37e6e 100644 --- a/examples/hdom-benchmark2/src/index.ts +++ b/examples/hdom-benchmark2/src/index.ts @@ -1,17 +1,17 @@ -import { splat4_24 } from "@thi.ng/binary/splat"; -import { dropdown } from "@thi.ng/hdom-components/dropdown"; -import { fpsCounter } from "@thi.ng/hdom-components/fps-counter"; -import { start } from "@thi.ng/hdom/start"; -import { css } from "@thi.ng/hiccup-css/css"; -import { injectStyleSheet } from "@thi.ng/hiccup-css/inject"; -import { U24 } from "@thi.ng/strings/radix"; -import { comp } from "@thi.ng/transducers/func/comp"; -import { range } from "@thi.ng/transducers/iter/range"; -import { push } from "@thi.ng/transducers/rfn/push"; -import { transduce } from "@thi.ng/transducers/transduce"; -import { map } from "@thi.ng/transducers/xform/map"; -import { mapIndexed } from "@thi.ng/transducers/xform/map-indexed"; -import { partition } from "@thi.ng/transducers/xform/partition"; +import { splat4_24 } from "@thi.ng/binary"; +import { 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"; +import { + comp, + map, + mapIndexed, + partition, + push, + range, + transduce +} from "@thi.ng/transducers"; const SIZE = "0.5rem"; diff --git a/examples/hdom-benchmark2/tsconfig.json b/examples/hdom-benchmark2/tsconfig.json index bbf112cc18..50a1cade93 100644 --- a/examples/hdom-benchmark2/tsconfig.json +++ b/examples/hdom-benchmark2/tsconfig.json @@ -2,10 +2,11 @@ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": ".", + "module": "es6", "target": "es6", "sourceMap": true }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/examples/hdom-canvas-clock/README.md b/examples/hdom-canvas-clock/README.md index c5b92f327a..4f1b55135f 100644 --- a/examples/hdom-canvas-clock/README.md +++ b/examples/hdom-canvas-clock/README.md @@ -2,7 +2,7 @@ [Live demo](http://demo.thi.ng/umbrella/hdom-canvas-clock/) -Declarative canvas drawing using the upcoming +Declarative canvas drawing using the [@thi.ng/hdom-canvas](https://github.com/thi-ng/umbrella/tree/master/packages/hdom-canvas) package. @@ -13,18 +13,9 @@ Related examples: ## Building -Note: Currently, some of the packages used by this demo are only -available as pre-releases (e.g. `"@thi.ng/hdom": "^5.0.0-alpha"`). - -The example project also assumes that [Parcel](https://parceljs.org) is -installed globally. - -```bash -git clone https://github.com/thi-ng/umbrella.git -cd umbrella/examples/hdom-canvas-clock -yarn install -yarn start -``` +Please refer to the [example build +instructions](https://github.com/thi-ng/umbrella/wiki/Example-build-instructions) +on the wiki. ## Authors diff --git a/examples/hdom-canvas-clock/package.json b/examples/hdom-canvas-clock/package.json index e3d7f1d855..88d52d89e5 100644 --- a/examples/hdom-canvas-clock/package.json +++ b/examples/hdom-canvas-clock/package.json @@ -6,18 +6,20 @@ "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 --detailed-report --public-url ./", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --experimental-scope-hoisting --detailed-report --public-url ./", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { - "parcel-bundler": "^1.10.3", - "terser": "^3.11.0", + "parcel-bundler": "^1.11.0", + "terser": "^3.14.1", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/api": "latest", "@thi.ng/hdom": "latest", - "@thi.ng/hdom-canvas": "latest" + "@thi.ng/hdom-canvas": "latest", + "@thi.ng/math": "latest", + "@thi.ng/transducers": "latest", + "@thi.ng/vectors": "latest" }, "browserslist": [ "last 3 Chrome versions" diff --git a/examples/hdom-canvas-clock/src/index.ts b/examples/hdom-canvas-clock/src/index.ts index 872c01b220..ff4126a2a6 100644 --- a/examples/hdom-canvas-clock/src/index.ts +++ b/examples/hdom-canvas-clock/src/index.ts @@ -1,9 +1,8 @@ import { start } from "@thi.ng/hdom"; import { canvas } from "@thi.ng/hdom-canvas"; -import { range } from "@thi.ng/transducers/iter/range"; -import { mapcat } from "@thi.ng/transducers/xform/mapcat"; -import { HALF_PI, TAU } from "@thi.ng/math/api"; -import { toCartesian2 } from "@thi.ng/vectors/vec2"; +import { HALF_PI, TAU } from "@thi.ng/math"; +import { mapcat, range } from "@thi.ng/transducers"; +import { toCartesian2 } from "@thi.ng/vectors"; const WEEKDAYS = ["SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"]; diff --git a/examples/hdom-canvas-clock/tsconfig.json b/examples/hdom-canvas-clock/tsconfig.json index b7d63aedf0..50a1cade93 100644 --- a/examples/hdom-canvas-clock/tsconfig.json +++ b/examples/hdom-canvas-clock/tsconfig.json @@ -2,6 +2,7 @@ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": ".", + "module": "es6", "target": "es6", "sourceMap": true }, diff --git a/examples/hdom-canvas-draw/README.md b/examples/hdom-canvas-draw/README.md index 5ca912c7a2..da13473855 100644 --- a/examples/hdom-canvas-draw/README.md +++ b/examples/hdom-canvas-draw/README.md @@ -2,12 +2,9 @@ [Live demo](http://demo.thi.ng/umbrella/hdom-canvas-draw/) -```bash -git clone https://github.com/thi-ng/umbrella.git -cd umbrella/examples/hdom-canvas-draw -yarn install -yarn start -``` +Please refer to the [example build +instructions](https://github.com/thi-ng/umbrella/wiki/Example-build-instructions) +on the wiki. ## Authors diff --git a/examples/hdom-canvas-draw/package.json b/examples/hdom-canvas-draw/package.json index 72cae997cf..1eba6d4fc4 100644 --- a/examples/hdom-canvas-draw/package.json +++ b/examples/hdom-canvas-draw/package.json @@ -6,12 +6,12 @@ "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 --detailed-report --public-url ./", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --experimental-scope-hoisting --detailed-report --public-url ./", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { - "parcel-bundler": "^1.10.3", - "terser": "^3.11.0", + "parcel-bundler": "^1.11.0", + "terser": "^3.14.1", "typescript": "^3.2.2" }, "dependencies": { diff --git a/examples/hdom-canvas-draw/src/index.ts b/examples/hdom-canvas-draw/src/index.ts index 4ee1cbf5d6..a026fc9f53 100644 --- a/examples/hdom-canvas-draw/src/index.ts +++ b/examples/hdom-canvas-draw/src/index.ts @@ -1,17 +1,18 @@ 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 { sync } from "@thi.ng/rstream/stream-sync"; -import { trigger } from "@thi.ng/rstream/trigger"; +import { + filter, + map, + mapcat, + normRange, + partition, + repeat, + tuples +} from "@thi.ng/transducers"; import { updateDOM } from "@thi.ng/transducers-hdom"; -import { normRange } from "@thi.ng/transducers/iter/norm-range"; -import { repeat } from "@thi.ng/transducers/iter/repeat"; -import { tuples } from "@thi.ng/transducers/iter/tuples"; -import { filter } from "@thi.ng/transducers/xform/filter"; -import { map } from "@thi.ng/transducers/xform/map"; -import { mapcat } from "@thi.ng/transducers/xform/mapcat"; -import { partition } from "@thi.ng/transducers/xform/partition"; -import { HALF_PI, PI } from "@thi.ng/math/api"; -import { dist2 } from "@thi.ng/vectors/vec2"; +import { dist2 } from "@thi.ng/vectors"; // canvas size const W = 480; diff --git a/examples/hdom-canvas-draw/tsconfig.json b/examples/hdom-canvas-draw/tsconfig.json index bbf112cc18..50a1cade93 100644 --- a/examples/hdom-canvas-draw/tsconfig.json +++ b/examples/hdom-canvas-draw/tsconfig.json @@ -2,10 +2,11 @@ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": ".", + "module": "es6", "target": "es6", "sourceMap": true }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/examples/hdom-canvas-shapes/README.md b/examples/hdom-canvas-shapes/README.md index 9ff45425fd..7b0b4bcf4a 100644 --- a/examples/hdom-canvas-shapes/README.md +++ b/examples/hdom-canvas-shapes/README.md @@ -34,18 +34,13 @@ Dataflow diagram: ## Building -Note: Currently, some of the packages used by this demo are only -available as pre-releases (e.g. `"@thi.ng/hdom": "^5.0.0-alpha"`). - -The example project also assumes that [Parcel](https://parceljs.org) is -installed globally. - -```bash -git clone https://github.com/thi-ng/umbrella.git -cd umbrella/examples/hdom-canvas-shapes -yarn install -yarn start -``` +Please refer to the [example build +instructions](https://github.com/thi-ng/umbrella/wiki/Example-build-instructions) +on the wiki. + +**IMPORTANT:** Please also see the [troubleshooting +note](https://github.com/thi-ng/umbrella/wiki/Example-build-instructions#troubleshooting) +and temporary workaround for this example. ## Authors diff --git a/examples/hdom-canvas-shapes/package.json b/examples/hdom-canvas-shapes/package.json index 6e1cf9dac8..46695975ce 100644 --- a/examples/hdom-canvas-shapes/package.json +++ b/examples/hdom-canvas-shapes/package.json @@ -6,12 +6,12 @@ "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 --detailed-report --public-url ./", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --experimental-scope-hoisting --detailed-report --public-url ./", "start": "parcel index.html -p 8080 --open --no-cache" }, "devDependencies": { - "parcel-bundler": "^1.10.3", - "terser": "^3.11.0", + "parcel-bundler": "^1.11.0", + "terser": "^3.14.1", "typescript": "^3.2.2" }, "dependencies": { @@ -21,7 +21,8 @@ "@thi.ng/hiccup-svg": "latest", "@thi.ng/rstream": "latest", "@thi.ng/transducers": "latest", - "@thi.ng/transducers-hdom": "latest" + "@thi.ng/transducers-hdom": "latest", + "@thi.ng/vectors": "latest" }, "browserslist": [ "last 3 Chrome versions" diff --git a/examples/hdom-canvas-shapes/src/index.ts b/examples/hdom-canvas-shapes/src/index.ts index cacd1843cf..128afc6cf7 100644 --- a/examples/hdom-canvas-shapes/src/index.ts +++ b/examples/hdom-canvas-shapes/src/index.ts @@ -1,23 +1,18 @@ import { canvas, normalizeTree } from "@thi.ng/hdom-canvas"; -// import { canvas2D, adaptDPI } from "@thi.ng/hdom-components/canvas"; -import { dropdown } from "@thi.ng/hdom-components/dropdown"; -import { stream } from "@thi.ng/rstream/stream"; -import { fromRAF } from "@thi.ng/rstream/from/raf"; -import { sync } from "@thi.ng/rstream/stream-sync"; +import { dropdown } from "@thi.ng/hdom-components"; +import { COMMENT, serialize } from "@thi.ng/hiccup"; +import { convertTree, svg } from "@thi.ng/hiccup-svg"; +import { fromRAF, stream, sync } from "@thi.ng/rstream"; +import { map, range, repeatedly } from "@thi.ng/transducers"; import { updateDOM } from "@thi.ng/transducers-hdom"; -import { range } from "@thi.ng/transducers/iter/range"; -import { repeatedly } from "@thi.ng/transducers/iter/repeatedly"; -import { map } from "@thi.ng/transducers/xform/map"; -import { Mat23 } from "@thi.ng/vectors/mat23"; +import { Mat23 } from "@thi.ng/vectors"; // for testing SVG conversion -import { COMMENT, serialize } from "@thi.ng/hiccup"; -import { convertTree } from "@thi.ng/hiccup-svg/convert"; -import { svg } from "@thi.ng/hiccup-svg/svg"; - -import logo from "../assets/logo-64.png"; // ignore error, resolved by parcel import { download } from "./download"; +// ignore error, resolved by parcel +import logo from "../assets/logo-64.png"; + // canvas size const W = 300; const W2 = W / 2; diff --git a/examples/hdom-canvas-shapes/tsconfig.json b/examples/hdom-canvas-shapes/tsconfig.json index c1eeed2aa3..50a1cade93 100644 --- a/examples/hdom-canvas-shapes/tsconfig.json +++ b/examples/hdom-canvas-shapes/tsconfig.json @@ -2,9 +2,11 @@ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": ".", - "target": "es6" + "module": "es6", + "target": "es6", + "sourceMap": true }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/examples/hdom-dropdown-fuzzy/README.md b/examples/hdom-dropdown-fuzzy/README.md index fa2f87153f..687b27556e 100644 --- a/examples/hdom-dropdown-fuzzy/README.md +++ b/examples/hdom-dropdown-fuzzy/README.md @@ -5,12 +5,9 @@ **This example is a work-in-progress trying out different ideas. Do not (yet) take as reference for your own projects.** -```bash -git clone https://github.com/thi-ng/umbrella.git -cd umbrella/examples/hdom-dropdown-fuzzy -yarn install -yarn start -``` +Please refer to the [example build +instructions](https://github.com/thi-ng/umbrella/wiki/Example-build-instructions) +on the wiki. ## Authors diff --git a/examples/hdom-dropdown-fuzzy/package.json b/examples/hdom-dropdown-fuzzy/package.json index 8add8bc01b..a6b31a00c8 100644 --- a/examples/hdom-dropdown-fuzzy/package.json +++ b/examples/hdom-dropdown-fuzzy/package.json @@ -6,16 +6,17 @@ "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 --detailed-report --public-url ./", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --experimental-scope-hoisting --detailed-report --public-url ./", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { - "parcel-bundler": "^1.10.3", - "terser": "^3.11.0", + "parcel-bundler": "^1.11.0", + "terser": "^3.14.1", "typescript": "^3.2.2" }, "dependencies": { "@thi.ng/api": "latest", + "@thi.ng/atom": "latest", "@thi.ng/hdom": "latest", "@thi.ng/hdom-components": "latest", "@thi.ng/interceptors": "latest", diff --git a/examples/hdom-dropdown-fuzzy/src/dropdown.ts b/examples/hdom-dropdown-fuzzy/src/dropdown.ts index 44640e3708..bcb46d6522 100644 --- a/examples/hdom-dropdown-fuzzy/src/dropdown.ts +++ b/examples/hdom-dropdown-fuzzy/src/dropdown.ts @@ -1,9 +1,8 @@ -import { IObjectOf } from "@thi.ng/api/api"; -import { ReadonlyAtom } from "@thi.ng/atom/api"; +import { IObjectOf } from "@thi.ng/api"; +import { ReadonlyAtom } from "@thi.ng/atom"; import { isString } from "@thi.ng/checks"; -import { appLink } from "@thi.ng/hdom-components/link"; -import { EV_SET_VALUE, EV_TOGGLE_VALUE } from "@thi.ng/interceptors/api"; -import { EventBus } from "@thi.ng/interceptors/event-bus"; +import { appLink } from "@thi.ng/hdom-components"; +import { EventBus, EV_SET_VALUE, EV_TOGGLE_VALUE } from "@thi.ng/interceptors"; import { getIn, Path } from "@thi.ng/paths"; export interface BaseContext { diff --git a/examples/hdom-dropdown-fuzzy/src/fuzzy.ts b/examples/hdom-dropdown-fuzzy/src/fuzzy.ts index 4c551d0693..b01659f57a 100644 --- a/examples/hdom-dropdown-fuzzy/src/fuzzy.ts +++ b/examples/hdom-dropdown-fuzzy/src/fuzzy.ts @@ -1,11 +1,12 @@ -import { IView } from "@thi.ng/atom/api"; -import { EV_SET_VALUE } from "@thi.ng/interceptors/api"; -import { comp } from "@thi.ng/transducers/func/comp"; -import { iterator } from "@thi.ng/transducers/iterator"; -import { filterFuzzy } from "@thi.ng/transducers/xform/filter-fuzzy"; -import { map } from "@thi.ng/transducers/xform/map"; - -import { dropdownListeners, DropdownState, DropdownItem } from "./dropdown"; +import { IView } from "@thi.ng/atom"; +import { EV_SET_VALUE } from "@thi.ng/interceptors"; +import { + comp, + filterFuzzy, + iterator, + map +} from "@thi.ng/transducers"; +import { DropdownItem, dropdownListeners, DropdownState } from "./dropdown"; export interface FuzzyArgs { state: IView; diff --git a/examples/hdom-dropdown-fuzzy/src/index.ts b/examples/hdom-dropdown-fuzzy/src/index.ts index 890bac3535..269c4ac088 100644 --- a/examples/hdom-dropdown-fuzzy/src/index.ts +++ b/examples/hdom-dropdown-fuzzy/src/index.ts @@ -1,8 +1,7 @@ -import { Atom } from "@thi.ng/atom/atom"; -import { start } from "@thi.ng/hdom/start"; -import { EventBus } from "@thi.ng/interceptors/event-bus"; -import { trace } from "@thi.ng/interceptors/interceptors"; - +import { Atom } from "@thi.ng/atom"; +import { start } from "@thi.ng/hdom"; +import { EventBus } from "@thi.ng/interceptors"; +import { trace } from "@thi.ng/interceptors"; import { state, theme } from "./config"; import { dropdown } from "./dropdown"; import { fuzzyDropdown } from "./fuzzy"; diff --git a/examples/hdom-dropdown-fuzzy/src/input.ts b/examples/hdom-dropdown-fuzzy/src/input.ts index 847ca34f1f..8d42a33dc5 100644 --- a/examples/hdom-dropdown-fuzzy/src/input.ts +++ b/examples/hdom-dropdown-fuzzy/src/input.ts @@ -1,5 +1,5 @@ -import { Path } from "@thi.ng/api/api"; -import { IView } from "@thi.ng/atom/api"; +import { Path } from "@thi.ng/api"; +import { IView } from "@thi.ng/atom"; import { getIn } from "@thi.ng/paths"; export interface InputArgs { diff --git a/examples/hdom-dropdown-fuzzy/tsconfig.json b/examples/hdom-dropdown-fuzzy/tsconfig.json index b7d63aedf0..50a1cade93 100644 --- a/examples/hdom-dropdown-fuzzy/tsconfig.json +++ b/examples/hdom-dropdown-fuzzy/tsconfig.json @@ -2,6 +2,7 @@ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": ".", + "module": "es6", "target": "es6", "sourceMap": true }, diff --git a/examples/hdom-dropdown/README.md b/examples/hdom-dropdown/README.md index c9c006e3ab..0192fba45c 100644 --- a/examples/hdom-dropdown/README.md +++ b/examples/hdom-dropdown/README.md @@ -2,12 +2,9 @@ [Live demo](https://demo.thi.ng/umbrella/hdom-dropdown/) -```bash -git clone https://github.com/thi-ng/umbrella.git -cd umbrella/examples/hdom-dropdown -yarn install -yarn start -``` +Please refer to the [example build +instructions](https://github.com/thi-ng/umbrella/wiki/Example-build-instructions) +on the wiki. ## Authors diff --git a/examples/hdom-dropdown/package.json b/examples/hdom-dropdown/package.json index bad9cdbfce..3619b30329 100644 --- a/examples/hdom-dropdown/package.json +++ b/examples/hdom-dropdown/package.json @@ -6,16 +6,17 @@ "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 --detailed-report --public-url ./", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --experimental-scope-hoisting --detailed-report --public-url ./", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { - "parcel-bundler": "^1.10.3", - "terser": "^3.11.0", + "parcel-bundler": "^1.11.0", + "terser": "^3.14.1", "typescript": "^3.2.2" }, "dependencies": { "@thi.ng/api": "latest", + "@thi.ng/atom": "latest", "@thi.ng/hdom": "latest", "@thi.ng/hdom-components": "latest", "@thi.ng/interceptors": "latest", diff --git a/examples/hdom-dropdown/src/dropdown.ts b/examples/hdom-dropdown/src/dropdown.ts index 2f02d09c89..a41e1afe72 100644 --- a/examples/hdom-dropdown/src/dropdown.ts +++ b/examples/hdom-dropdown/src/dropdown.ts @@ -1,8 +1,7 @@ -import { IObjectOf } from "@thi.ng/api/api"; -import { ReadonlyAtom } from "@thi.ng/atom/api"; -import { appLink } from "@thi.ng/hdom-components/link"; -import { EV_SET_VALUE, EV_TOGGLE_VALUE } from "@thi.ng/interceptors/api"; -import { EventBus } from "@thi.ng/interceptors/event-bus"; +import { IObjectOf } from "@thi.ng/api"; +import { ReadonlyAtom } from "@thi.ng/atom"; +import { appLink } from "@thi.ng/hdom-components"; +import { EV_SET_VALUE, EV_TOGGLE_VALUE, EventBus } from "@thi.ng/interceptors"; import { getIn, Path } from "@thi.ng/paths"; export interface BaseContext { diff --git a/examples/hdom-dropdown/src/index.ts b/examples/hdom-dropdown/src/index.ts index a33829c656..7cd45947b1 100644 --- a/examples/hdom-dropdown/src/index.ts +++ b/examples/hdom-dropdown/src/index.ts @@ -1,8 +1,6 @@ -import { Atom } from "@thi.ng/atom/atom"; -import { start } from "@thi.ng/hdom/start"; -import { EventBus } from "@thi.ng/interceptors/event-bus"; -import { trace } from "@thi.ng/interceptors/interceptors"; - +import { Atom } from "@thi.ng/atom"; +import { start } from "@thi.ng/hdom"; +import { EventBus, trace } from "@thi.ng/interceptors"; import { state, theme } from "./config"; import { dropdown, dropdownListeners } from "./dropdown"; diff --git a/examples/hdom-dropdown/tsconfig.json b/examples/hdom-dropdown/tsconfig.json index b7d63aedf0..50a1cade93 100644 --- a/examples/hdom-dropdown/tsconfig.json +++ b/examples/hdom-dropdown/tsconfig.json @@ -2,6 +2,7 @@ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": ".", + "module": "es6", "target": "es6", "sourceMap": true }, diff --git a/examples/hdom-dyn-context/README.md b/examples/hdom-dyn-context/README.md index 5109ea6edf..1535023283 100644 --- a/examples/hdom-dyn-context/README.md +++ b/examples/hdom-dyn-context/README.md @@ -5,12 +5,9 @@ Minimal example demonstrating use of dynamic hdom user context values, here used for app-wide theme switching. -```bash -git clone https://github.com/thi-ng/umbrella.git -cd umbrella/examples/hdom-dyn-context -yarn install -yarn start -``` +Please refer to the [example build +instructions](https://github.com/thi-ng/umbrella/wiki/Example-build-instructions) +on the wiki. ## Authors diff --git a/examples/hdom-dyn-context/package.json b/examples/hdom-dyn-context/package.json index 4d26dd4252..dbbba7e2b9 100644 --- a/examples/hdom-dyn-context/package.json +++ b/examples/hdom-dyn-context/package.json @@ -6,12 +6,12 @@ "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": "yarn clean && parcel build index.html -d out --public-url ./ --no-source-maps --no-cache --experimental-scope-hoisting --detailed-report", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { - "parcel-bundler": "^1.10.3", - "terser": "^3.11.0", + "parcel-bundler": "^1.11.0", + "terser": "^3.14.1", "typescript": "^3.2.2" }, "dependencies": { diff --git a/examples/hdom-dyn-context/src/index.ts b/examples/hdom-dyn-context/src/index.ts index abb460cb2e..9c4868ac90 100644 --- a/examples/hdom-dyn-context/src/index.ts +++ b/examples/hdom-dyn-context/src/index.ts @@ -1,5 +1,5 @@ -import { Atom } from "@thi.ng/atom/atom"; -import { start } from "@thi.ng/hdom/start"; +import { Atom } from "@thi.ng/atom"; +import { start } from "@thi.ng/hdom"; // theme definitions const THEMES = [ diff --git a/examples/hdom-dyn-context/tsconfig.json b/examples/hdom-dyn-context/tsconfig.json index bbf112cc18..50a1cade93 100644 --- a/examples/hdom-dyn-context/tsconfig.json +++ b/examples/hdom-dyn-context/tsconfig.json @@ -2,10 +2,11 @@ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": ".", + "module": "es6", "target": "es6", "sourceMap": true }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/examples/hdom-inner-html/.gitignore b/examples/hdom-inner-html/.gitignore new file mode 100644 index 0000000000..0c5abcab62 --- /dev/null +++ b/examples/hdom-inner-html/.gitignore @@ -0,0 +1,5 @@ +.cache +out +node_modules +yarn.lock +*.js diff --git a/examples/hdom-inner-html/README.md b/examples/hdom-inner-html/README.md new file mode 100644 index 0000000000..a1373d097c --- /dev/null +++ b/examples/hdom-inner-html/README.md @@ -0,0 +1,13 @@ +# hdom-inner-html + +[Live demo](http://demo.thi.ng/umbrella/hdom-inner-html/) + +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/hdom-inner-html/index.html b/examples/hdom-inner-html/index.html new file mode 100644 index 0000000000..9551c2e5d6 --- /dev/null +++ b/examples/hdom-inner-html/index.html @@ -0,0 +1,16 @@ + + + + + + + hdom-inner-html + + + + +
+ + + diff --git a/examples/hdom-inner-html/package.json b/examples/hdom-inner-html/package.json new file mode 100644 index 0000000000..dc0296cb0c --- /dev/null +++ b/examples/hdom-inner-html/package.json @@ -0,0 +1,27 @@ +{ + "name": "hdom-inner-html", + "version": "0.0.1", + "repository": "https://github.com/thi-ng/umbrella", + "author": "Karsten Schmidt ", + "license": "Apache-2.0", + "scripts": { + "clean": "rimraf .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.11.0", + "rimraf": "^2.6.3", + "terser": "^3.14.1", + "typescript": "^3.2.2" + }, + "dependencies": { + "@thi.ng/hdom": "latest" + }, + "browserslist": [ + "last 3 Chrome versions" + ], + "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 new file mode 100644 index 0000000000..8da0aba198 --- /dev/null +++ b/examples/hdom-inner-html/src/index.ts @@ -0,0 +1,50 @@ +import { start } from "@thi.ng/hdom"; + +/** + * HOF component for rendering HTML strings by setting `innerHTML`. The + * 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; + } + return ["div"]; + }, + release() { + this.el.innerHTML = ""; + delete this.prev; + delete this.el; + } + }); + +/** + * Root component. + */ +const app = () => { + // instantiate HTML wrapper + const wrapper = innerHtmlWrapper(); + return () => + [wrapper, + new Date().getSeconds() & 1 ? + `
Time now:
` : + `
${new Date().toLocaleTimeString()}
` + ]; +}; + +// kick off +const cancel = start(app()); + +// HMR handling +if (process.env.NODE_ENV !== "production") { + const hot = (module).hot; + hot && hot.dispose(cancel); +} diff --git a/examples/hdom-inner-html/tsconfig.json b/examples/hdom-inner-html/tsconfig.json new file mode 100644 index 0000000000..bbf112cc18 --- /dev/null +++ b/examples/hdom-inner-html/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": ".", + "target": "es6", + "sourceMap": true + }, + "include": [ + "./src/**/*.ts" + ] +} diff --git a/examples/hdom-skip/README.md b/examples/hdom-skip/README.md index 6dbd95f5f0..b1efe64eb6 100644 --- a/examples/hdom-skip/README.md +++ b/examples/hdom-skip/README.md @@ -5,12 +5,9 @@ Minimal example demonstrating use of the hdom `__skip` control attribute to selectively skip diffing & updating DOM tree branches. -```bash -git clone https://github.com/thi-ng/umbrella.git -cd umbrella/examples/hdom-skip -yarn install -yarn start -``` +Please refer to the [example build +instructions](https://github.com/thi-ng/umbrella/wiki/Example-build-instructions) +on the wiki. ## Authors diff --git a/examples/hdom-skip/package.json b/examples/hdom-skip/package.json index decb5f7656..62e9bd8197 100644 --- a/examples/hdom-skip/package.json +++ b/examples/hdom-skip/package.json @@ -6,19 +6,16 @@ "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": "yarn clean && parcel build index.html -d out --public-url ./ --no-source-maps --no-cache --experimental-scope-hoisting --detailed-report", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { - "parcel-bundler": "^1.10.3", - "terser": "^3.11.0", + "parcel-bundler": "^1.11.0", + "terser": "^3.14.1", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/api": "latest", - "@thi.ng/atom": "latest", - "@thi.ng/rstream": "latest", - "@thi.ng/transducers-hdom": "latest" + "@thi.ng/hdom": "latest" }, "browserslist": [ "last 3 Chrome versions" diff --git a/examples/hdom-skip/tsconfig.json b/examples/hdom-skip/tsconfig.json index bbf112cc18..50a1cade93 100644 --- a/examples/hdom-skip/tsconfig.json +++ b/examples/hdom-skip/tsconfig.json @@ -2,10 +2,11 @@ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": ".", + "module": "es6", "target": "es6", "sourceMap": true }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/examples/hdom-theme-adr-0003/README.md b/examples/hdom-theme-adr-0003/README.md index 7d42d4a39c..c8e5434959 100644 --- a/examples/hdom-theme-adr-0003/README.md +++ b/examples/hdom-theme-adr-0003/README.md @@ -5,12 +5,9 @@ WIP demo of themed component proposal discussed in [ADR-0003](https://github.com/thi-ng/umbrella/blob/master/packages/hdom-components/adr/0003-component-configuration-via-context.md). -```bash -git clone https://github.com/thi-ng/umbrella.git -cd umbrella/examples/hdom-theme-adr-0003 -yarn install -yarn start -``` +Please refer to the [example build +instructions](https://github.com/thi-ng/umbrella/wiki/Example-build-instructions) +on the wiki. ## Authors diff --git a/examples/hdom-theme-adr-0003/package.json b/examples/hdom-theme-adr-0003/package.json index bf358a6e87..d10a5151fc 100644 --- a/examples/hdom-theme-adr-0003/package.json +++ b/examples/hdom-theme-adr-0003/package.json @@ -6,17 +6,18 @@ "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 --detailed-report --public-url ./", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --experimental-scope-hoisting --detailed-report --public-url ./", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { - "parcel-bundler": "^1.10.3", - "terser": "^3.11.0", + "parcel-bundler": "^1.11.0", + "terser": "^3.14.1", "typescript": "^3.2.2" }, "dependencies": { "@thi.ng/api": "latest", - "@thi.ng/hdom": "latest" + "@thi.ng/hdom": "latest", + "@thi.ng/paths": "latest" }, "browserslist": [ "last 3 Chrome versions" diff --git a/examples/hdom-theme-adr-0003/src/index.ts b/examples/hdom-theme-adr-0003/src/index.ts index 9e0b6e2735..1b992a881e 100644 --- a/examples/hdom-theme-adr-0003/src/index.ts +++ b/examples/hdom-theme-adr-0003/src/index.ts @@ -1,5 +1,5 @@ -import { IObjectOf } from "@thi.ng/api/api"; -import { start } from "@thi.ng/hdom/start"; +import { IObjectOf } from "@thi.ng/api"; +import { start } from "@thi.ng/hdom"; import { getIn, Path } from "@thi.ng/paths"; interface ButtonBehavior { diff --git a/examples/hdom-theme-adr-0003/tsconfig.json b/examples/hdom-theme-adr-0003/tsconfig.json index b7d63aedf0..50a1cade93 100644 --- a/examples/hdom-theme-adr-0003/tsconfig.json +++ b/examples/hdom-theme-adr-0003/tsconfig.json @@ -2,6 +2,7 @@ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": ".", + "module": "es6", "target": "es6", "sourceMap": true }, diff --git a/examples/hmr-basics/README.md b/examples/hmr-basics/README.md index d1a10951a1..9c60480d57 100644 --- a/examples/hmr-basics/README.md +++ b/examples/hmr-basics/README.md @@ -6,12 +6,9 @@ Minimal example demonstrating the combined usage of @thi.ng/memoize's [`defonce`](https://github.com/thi-ng/umbrella/tree/master/packages/memoize/src/defonce.ts) and parcel's [Hot Module Replacement API](https://parceljs.org/hmr.html). -```bash -git clone https://github.com/thi-ng/umbrella.git -cd umbrella/examples/hmr-basics -yarn install -yarn start -``` +Please refer to the [example build +instructions](https://github.com/thi-ng/umbrella/wiki/Example-build-instructions) +on the wiki. ## Authors diff --git a/examples/hmr-basics/package.json b/examples/hmr-basics/package.json index af7b321481..9d4eb6fc54 100644 --- a/examples/hmr-basics/package.json +++ b/examples/hmr-basics/package.json @@ -6,12 +6,12 @@ "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 --detailed-report --public-url ./", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --experimental-scope-hoisting --detailed-report --public-url ./", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { - "parcel-bundler": "^1.10.3", - "terser": "^3.11.0", + "parcel-bundler": "^1.11.0", + "terser": "^3.14.1", "typescript": "^3.2.2" }, "dependencies": { diff --git a/examples/hmr-basics/src/index.ts b/examples/hmr-basics/src/index.ts index a1181a8bb7..c2646ad1cc 100644 --- a/examples/hmr-basics/src/index.ts +++ b/examples/hmr-basics/src/index.ts @@ -1,8 +1,6 @@ -import { fromAtom } from "@thi.ng/rstream/from/atom"; -import { fromInterval } from "@thi.ng/rstream/from/interval"; -import { sync } from "@thi.ng/rstream/stream-sync"; +import { fromAtom, fromInterval, sync } from "@thi.ng/rstream"; +import { map } from "@thi.ng/transducers"; import { updateDOM } from "@thi.ng/transducers-hdom"; -import { map } from "@thi.ng/transducers/xform/map"; import { app } from "./app"; import { state } from "./state"; diff --git a/examples/hmr-basics/src/state.ts b/examples/hmr-basics/src/state.ts index be31ba6a61..451bc4a279 100644 --- a/examples/hmr-basics/src/state.ts +++ b/examples/hmr-basics/src/state.ts @@ -1,12 +1,13 @@ -import { Atom } from "@thi.ng/atom/atom"; -import { defonce } from "@thi.ng/memoize/defonce"; +import { Atom } from "@thi.ng/atom"; +import { defonce } from "@thi.ng/memoize"; // `defonce` is used here to protect the app stat atom from // re-initializing during hot module replacement. // in other words, the atom is *only* initialized once when the // application first loads / reloads -export const state = defonce("umbrella.example.hmr", () => - new Atom({ - launched: new Date(), - seed: (Math.random() * 100) | 0, - })); +export const state = + defonce("umbrella.example.hmr", () => + new Atom({ + launched: new Date(), + seed: (Math.random() * 100) | 0, + })); diff --git a/examples/hmr-basics/tsconfig.json b/examples/hmr-basics/tsconfig.json index 98e83903d2..50a1cade93 100644 --- a/examples/hmr-basics/tsconfig.json +++ b/examples/hmr-basics/tsconfig.json @@ -2,10 +2,9 @@ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": ".", + "module": "es6", "target": "es6", - "sourceMap": true, - "noUnusedLocals": false, - "noUnusedParameters": false + "sourceMap": true }, "include": [ "./src/**/*.ts" diff --git a/examples/hydrate-basics/README.md b/examples/hydrate-basics/README.md index 4fcad46175..cc4589d4fe 100644 --- a/examples/hydrate-basics/README.md +++ b/examples/hydrate-basics/README.md @@ -5,12 +5,9 @@ This example demonstrates how to hydrate a pre-created HTML DOM (e.g. server-side rendering) client-side. -```bash -git clone https://github.com/thi-ng/umbrella.git -cd umbrella/examples/hydrate-basics -yarn install -yarn start -``` +Please refer to the [example build +instructions](https://github.com/thi-ng/umbrella/wiki/Example-build-instructions) +on the wiki. ## Authors diff --git a/examples/hydrate-basics/package.json b/examples/hydrate-basics/package.json index 3eeff85f23..dc21ad11bc 100644 --- a/examples/hydrate-basics/package.json +++ b/examples/hydrate-basics/package.json @@ -6,16 +6,16 @@ "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 --detailed-report --public-url ./", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --experimental-scope-hoisting --detailed-report --public-url ./", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { - "parcel-bundler": "^1.10.3", - "terser": "^3.11.0", + "parcel-bundler": "^1.11.0", + "terser": "^3.14.1", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/api": "latest", + "@thi.ng/atom": "latest", "@thi.ng/hdom": "latest", "@thi.ng/hdom-components": "latest", "@thi.ng/hiccup": "latest" diff --git a/examples/hydrate-basics/src/index.ts b/examples/hydrate-basics/src/index.ts index 0faa1b3e45..025491b200 100644 --- a/examples/hydrate-basics/src/index.ts +++ b/examples/hydrate-basics/src/index.ts @@ -1,8 +1,7 @@ import { Atom } from "@thi.ng/atom"; -import { serialize } from "@thi.ng/hiccup/serialize"; -import { start } from "@thi.ng/hdom/start"; -import { canvas2D } from "@thi.ng/hdom-components/canvas"; -import { dropdown } from "@thi.ng/hdom-components/dropdown"; +import { start } from "@thi.ng/hdom"; +import { canvas2D, dropdown } from "@thi.ng/hdom-components"; +import { serialize } from "@thi.ng/hiccup"; // basic state container const state = new Atom({ diff --git a/examples/hydrate-basics/tsconfig.json b/examples/hydrate-basics/tsconfig.json index b7d63aedf0..50a1cade93 100644 --- a/examples/hydrate-basics/tsconfig.json +++ b/examples/hydrate-basics/tsconfig.json @@ -2,6 +2,7 @@ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": ".", + "module": "es6", "target": "es6", "sourceMap": true }, diff --git a/examples/interceptor-basics/README.md b/examples/interceptor-basics/README.md index 17744b1f5c..49c61fe778 100644 --- a/examples/interceptor-basics/README.md +++ b/examples/interceptor-basics/README.md @@ -2,12 +2,9 @@ [Live demo](http://demo.thi.ng/umbrella/interceptor-basics/) -```bash -git clone https://github.com/thi-ng/umbrella.git -cd umbrella/examples/interceptor-basics -yarn install -yarn start -``` +Please refer to the [example build +instructions](https://github.com/thi-ng/umbrella/wiki/Example-build-instructions) +on the wiki. ## Authors diff --git a/examples/interceptor-basics/package.json b/examples/interceptor-basics/package.json index 06cb1d3b78..b209dae0b3 100644 --- a/examples/interceptor-basics/package.json +++ b/examples/interceptor-basics/package.json @@ -6,19 +6,19 @@ "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 --detailed-report --public-url ./", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --experimental-scope-hoisting --detailed-report --public-url ./", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { - "parcel-bundler": "^1.10.3", - "terser": "^3.11.0", + "parcel-bundler": "^1.11.0", + "terser": "^3.14.1", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/api": "latest", "@thi.ng/atom": "latest", - "@thi.ng/rstream": "latest", - "@thi.ng/transducers-hdom": "latest" + "@thi.ng/hdom": "latest", + "@thi.ng/interceptors": "latest", + "@thi.ng/transducers": "latest" }, "browserslist": [ "last 3 Chrome versions" diff --git a/examples/interceptor-basics/src/index.ts b/examples/interceptor-basics/src/index.ts index 428a3b2c46..1c29156961 100644 --- a/examples/interceptor-basics/src/index.ts +++ b/examples/interceptor-basics/src/index.ts @@ -1,7 +1,12 @@ import { Atom } from "@thi.ng/atom"; import { start } from "@thi.ng/hdom"; +import { + dispatchNow, + EventBus, + FX_STATE, + valueUpdater +} from "@thi.ng/interceptors"; import { choices } from "@thi.ng/transducers"; -import * as icep from "@thi.ng/interceptors"; // infinite iterator of random color choices const colors = choices(["cyan", "yellow", "magenta", "chartreuse"]); @@ -11,15 +16,15 @@ const db = new Atom({}); // event bus w/ handlers // see @thi.ng/interceptors for more details -const bus = new icep.EventBus(db, { +const bus = new EventBus(db, { "init": () => ({ - [icep.FX_STATE]: { clicks: 0, color: "grey" } + [FX_STATE]: { clicks: 0, color: "grey" } }), "inc-counter": [ - icep.valueUpdater("clicks", (x: number) => x + 1), - icep.dispatchNow(["randomize-color"]) + valueUpdater("clicks", (x: number) => x + 1), + dispatchNow(["randomize-color"]) ], - "randomize-color": icep.valueUpdater( + "randomize-color": valueUpdater( "color", () => colors.next().value ) }); diff --git a/examples/interceptor-basics/tsconfig.json b/examples/interceptor-basics/tsconfig.json index bbf112cc18..50a1cade93 100644 --- a/examples/interceptor-basics/tsconfig.json +++ b/examples/interceptor-basics/tsconfig.json @@ -2,10 +2,11 @@ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": ".", + "module": "es6", "target": "es6", "sourceMap": true }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/examples/interceptor-basics2/README.md b/examples/interceptor-basics2/README.md index 5ebb07a76f..a09cad11c0 100644 --- a/examples/interceptor-basics2/README.md +++ b/examples/interceptor-basics2/README.md @@ -2,9 +2,14 @@ [Live demo](https://demo.thi.ng/umbrella/interceptor-basics2/) -```bash -git clone https://github.com/thi-ng/umbrella.git -cd umbrella/examples/interceptor-basics2 -yarn install -yarn start -``` +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/interceptor-basics2/package.json b/examples/interceptor-basics2/package.json index 784456752c..da6e654725 100644 --- a/examples/interceptor-basics2/package.json +++ b/examples/interceptor-basics2/package.json @@ -6,18 +6,19 @@ "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 --detailed-report --public-url ./", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --experimental-scope-hoisting --detailed-report --public-url ./", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { - "parcel-bundler": "^1.10.3", - "terser": "^3.11.0", + "parcel-bundler": "^1.11.0", + "terser": "^3.14.1", "typescript": "^3.2.2" }, "dependencies": { "@thi.ng/api": "latest", - "@thi.ng/atom": "latest", - "@thi.ng/hdom": "latest" + "@thi.ng/hdom": "latest", + "@thi.ng/intereptors": "latest", + "@thi.ng/paths": "latest" }, "browserslist": [ "last 3 Chrome versions" diff --git a/examples/interceptor-basics2/src/index.ts b/examples/interceptor-basics2/src/index.ts index 7027aeb40c..2c15f686a1 100644 --- a/examples/interceptor-basics2/src/index.ts +++ b/examples/interceptor-basics2/src/index.ts @@ -1,9 +1,17 @@ -import { IObjectOf } from "@thi.ng/api/api"; -import { start } from "@thi.ng/hdom/start"; -import { EffectDef, EventDef, IDispatch } from "@thi.ng/interceptors/api"; -import { EV_SET_VALUE, EV_UPDATE_VALUE, FX_DISPATCH_NOW } from "@thi.ng/interceptors/api"; -import { EventBus } from "@thi.ng/interceptors/event-bus"; -import { ensureStateGreaterThan, ensureStateLessThan, trace } from "@thi.ng/interceptors/interceptors"; +import { IObjectOf } from "@thi.ng/api"; +import { start } from "@thi.ng/hdom"; +import { + EffectDef, + ensureStateGreaterThan, + ensureStateLessThan, + EV_SET_VALUE, + EV_UPDATE_VALUE, + EventBus, + EventDef, + FX_DISPATCH_NOW, + IDispatch, + trace +} from "@thi.ng/interceptors"; import { Path } from "@thi.ng/paths"; /////////////////////////////////////////////////////////////////////// diff --git a/examples/interceptor-basics2/tsconfig.json b/examples/interceptor-basics2/tsconfig.json index b7d63aedf0..50a1cade93 100644 --- a/examples/interceptor-basics2/tsconfig.json +++ b/examples/interceptor-basics2/tsconfig.json @@ -2,6 +2,7 @@ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": ".", + "module": "es6", "target": "es6", "sourceMap": true }, diff --git a/examples/json-components/README.md b/examples/json-components/README.md index ed374c29c4..b33c2e93ea 100644 --- a/examples/json-components/README.md +++ b/examples/json-components/README.md @@ -2,9 +2,14 @@ [Live demo](https://demo.thi.ng/umbrella/json-components/) -```bash -git clone https://github.com/thi-ng/umbrella.git -cd umbrella/examples/json-components -yarn install -yarn start -``` +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/json-components/package.json b/examples/json-components/package.json index a961527c47..a8a4a3fd3d 100644 --- a/examples/json-components/package.json +++ b/examples/json-components/package.json @@ -6,12 +6,12 @@ "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 --detailed-report --public-url ./", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --experimental-scope-hoisting --detailed-report --public-url ./", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { - "parcel-bundler": "^1.10.3", - "terser": "^3.11.0", + "parcel-bundler": "^1.11.0", + "terser": "^3.14.1", "typescript": "^3.2.2" }, "dependencies": { diff --git a/examples/json-components/src/index.ts b/examples/json-components/src/index.ts index 728ae931aa..77452331ca 100644 --- a/examples/json-components/src/index.ts +++ b/examples/json-components/src/index.ts @@ -1,6 +1,5 @@ import { start } from "@thi.ng/hdom"; -import { TransformSubSpec } from "@thi.ng/transducers/api"; -import { deepTransform } from "@thi.ng/transducers/func/deep-transform"; +import { deepTransform, TransformSubSpec } from "@thi.ng/transducers"; // some dummy JSON records let db = [ diff --git a/examples/json-components/tsconfig.json b/examples/json-components/tsconfig.json index b7d63aedf0..50a1cade93 100644 --- a/examples/json-components/tsconfig.json +++ b/examples/json-components/tsconfig.json @@ -2,6 +2,7 @@ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": ".", + "module": "es6", "target": "es6", "sourceMap": true }, diff --git a/examples/login-form/README.md b/examples/login-form/README.md index 2ccd05549f..dce5b12170 100644 --- a/examples/login-form/README.md +++ b/examples/login-form/README.md @@ -2,9 +2,14 @@ [Live demo](https://demo.thi.ng/umbrella/login-form/) -```bash -git clone https://github.com/thi-ng/umbrella.git -cd umbrella/examples/login-form -yarn install -yarn start -``` +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/login-form/package.json b/examples/login-form/package.json index 9a2f396e19..639a3432ce 100644 --- a/examples/login-form/package.json +++ b/examples/login-form/package.json @@ -6,17 +6,18 @@ "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 --detailed-report --public-url ./", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --experimental-scope-hoisting --detailed-report --public-url ./", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { - "parcel-bundler": "^1.10.3", - "terser": "^3.11.0", + "parcel-bundler": "^1.11.0", + "terser": "^3.14.1", "typescript": "^3.2.2" }, "dependencies": { "@thi.ng/atom": "latest", - "@thi.ng/hdom": "latest" + "@thi.ng/hdom": "latest", + "@thi.ng/paths": "latest" }, "browserslist": [ "last 3 Chrome versions" diff --git a/examples/login-form/src/index.ts b/examples/login-form/src/index.ts index 089be68615..3a4f540a9b 100644 --- a/examples/login-form/src/index.ts +++ b/examples/login-form/src/index.ts @@ -1,5 +1,5 @@ -import { Atom } from "@thi.ng/atom/atom"; -import { start } from "@thi.ng/hdom/start"; +import { Atom } from "@thi.ng/atom"; +import { start } from "@thi.ng/hdom"; import { setIn } from "@thi.ng/paths"; // central immutable app state diff --git a/examples/login-form/tsconfig.json b/examples/login-form/tsconfig.json index b7d63aedf0..50a1cade93 100644 --- a/examples/login-form/tsconfig.json +++ b/examples/login-form/tsconfig.json @@ -2,6 +2,7 @@ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": ".", + "module": "es6", "target": "es6", "sourceMap": true }, diff --git a/examples/mandelbrot/README.md b/examples/mandelbrot/README.md index 5d03c89f3b..ab087eb66a 100644 --- a/examples/mandelbrot/README.md +++ b/examples/mandelbrot/README.md @@ -2,12 +2,9 @@ [Live demo](http://demo.thi.ng/umbrella/mandelbrot/) -```bash -git clone https://github.com/thi-ng/umbrella.git -cd umbrella/examples/mandelbrot -yarn install -yarn start -``` +Please refer to the [example build +instructions](https://github.com/thi-ng/umbrella/wiki/Example-build-instructions) +on the wiki. ## Authors diff --git a/examples/mandelbrot/package.json b/examples/mandelbrot/package.json index 35fe5eadf6..bea1fc5a6f 100644 --- a/examples/mandelbrot/package.json +++ b/examples/mandelbrot/package.json @@ -6,19 +6,25 @@ "license": "Apache-2.0", "scripts": { "clean": "rm -rf .cache build out", - "build": "yarn clean && yarn build:worker && parcel build index.html -d out --public-url ./ --no-source-maps --no-cache --detailed-report", - "build:worker": "parcel build src/worker.ts -d out --no-source-maps --no-cache --detailed-report", + "build": "yarn clean && yarn build:worker && parcel build index.html -d out --public-url ./ --no-source-maps --no-cache --experimental-scope-hoisting --detailed-report", + "build:worker": "parcel build src/worker.ts -d out --no-source-maps --no-cache --experimental-scope-hoisting --detailed-report --experimental-scope-hoisting", "start": "yarn build:worker && parcel index.html -d out -p 8080 --open" }, "devDependencies": { - "parcel-bundler": "^1.10.3", - "terser": "^3.11.0", + "parcel-bundler": "^1.11.0", + "terser": "^3.14.1", "typescript": "^3.2.2" }, "dependencies": { "@thi.ng/api": "latest", - "@thi.ng/atom": "latest", + "@thi.ng/compose": "latest", + "@thi.ng/equiv": "latest", + "@thi.ng/hdom-components": "latest", + "@thi.ng/math": "latest", "@thi.ng/rstream": "latest", + "@thi.ng/rstream-gestures": "latest", + "@thi.ng/strings": "latest", + "@thi.ng/transducers": "latest", "@thi.ng/transducers-hdom": "latest" }, "browserslist": [ diff --git a/examples/mandelbrot/src/gradient.ts b/examples/mandelbrot/src/gradient.ts index 752fd1d0b4..48cc6ef7a0 100644 --- a/examples/mandelbrot/src/gradient.ts +++ b/examples/mandelbrot/src/gradient.ts @@ -6,17 +6,20 @@ import { tuples } from "@thi.ng/transducers/iter/tuples"; import { push } from "@thi.ng/transducers/rfn/push"; import { transduce } from "@thi.ng/transducers/transduce"; import { map } from "@thi.ng/transducers/xform/map"; +import { partial } from "@thi.ng/compose/partial"; +// see http://dev.thi.ng/gradients/ // see http://dev.thi.ng/gradients/ -const cosColor = (dc: number[], amp: number[], fmod: number[], phase: number[], t: number) => - transduce( - map( - ([a, b, c, d]) => clamp01(a + b * Math.cos(TAU * (c * t + d))) - ), - push(), - tuples(dc, amp, fmod, phase) - ); +const cosColor = + (dc: number[], amp: number[], fmod: number[], phase: number[], t: number) => + transduce( + map( + ([a, b, c, d]) => clamp01(a + b * Math.cos(TAU * (c * t + d))) + ), + push(), + tuples(dc, amp, fmod, phase) + ); export const cosineGradient = (n: number, spec: number[][]) => { const [dc, amp, fmod, phase] = spec; @@ -29,3 +32,11 @@ export const cosineGradient = (n: number, spec: number[][]) => { normRange(n - 1) ); }; + +export const GRADIENTS = [ + [[0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [-1.0, -1.0, -1.0], [0.00, 0.10, 0.20]], + [[0.500, 0.500, 0.500], [0.500, 0.500, 0.500], [0.500, 0.618, 0.500], [-1.000, 0.828, -0.152]], + [[0.402, 0.654, 0.247], [0.835, 0.668, 0.420], [1.226, 1.553, 1.445], [2.684, 6.256, 4.065]], + [[0.500, 0.500, 0.500], [0.500, 0.500, 0.500], [0.500, 0.500, 0.500], [0.500, 0.500, 0.500]], + [[0.5, 0.5, 0.5], [1.000, 1.000, 1.000], [10.000, 10.000, 10.000], [0.000, 0.000, 0.000]], +].map(partial(cosineGradient, 256)); diff --git a/examples/mandelbrot/src/index.ts b/examples/mandelbrot/src/index.ts index de54786dbd..5577e14895 100644 --- a/examples/mandelbrot/src/index.ts +++ b/examples/mandelbrot/src/index.ts @@ -1,14 +1,11 @@ import { equiv } from "@thi.ng/equiv"; -import { canvas2D } from "@thi.ng/hdom-components/canvas"; -import { fit } from "@thi.ng/math/fit"; -import { mix } from "@thi.ng/math/mix"; +import { canvas2D } from "@thi.ng/hdom-components"; +import { fit, mix } from "@thi.ng/math"; +import { stream, sync, tunnel } from "@thi.ng/rstream"; import { gestureStream, GestureType } from "@thi.ng/rstream-gestures"; -import { stream } from "@thi.ng/rstream/stream"; -import { sync } from "@thi.ng/rstream/stream-sync"; -import { tunnel } from "@thi.ng/rstream/subs/tunnel"; +import { padLeft } from "@thi.ng/strings"; +import { map } from "@thi.ng/transducers"; import { updateDOM } from "@thi.ng/transducers-hdom"; -import { map } from "@thi.ng/transducers/xform/map"; -import { padLeft } from "@thi.ng/strings/pad-left"; import { download } from "./download"; // if enabled, auto-zoom out & export frames diff --git a/examples/mandelbrot/src/worker.ts b/examples/mandelbrot/src/worker.ts index 45e889820f..19480517f9 100644 --- a/examples/mandelbrot/src/worker.ts +++ b/examples/mandelbrot/src/worker.ts @@ -1,16 +1,5 @@ -import { partial } from "@thi.ng/compose/partial"; import { fit01 } from "@thi.ng/math/fit"; -import { cosineGradient } from "./gradient"; - -// see http://dev.thi.ng/gradients/ - -const gradients = [ - [[0.5, 0.5, 0.5], [0.5, 0.5, 0.5], [-1.0, -1.0, -1.0], [0.00, 0.10, 0.20]], - [[0.500, 0.500, 0.500], [0.500, 0.500, 0.500], [0.500, 0.618, 0.500], [-1.000, 0.828, -0.152]], - [[0.402, 0.654, 0.247], [0.835, 0.668, 0.420], [1.226, 1.553, 1.445], [2.684, 6.256, 4.065]], - [[0.500, 0.500, 0.500], [0.500, 0.500, 0.500], [0.500, 0.500, 0.500], [0.500, 0.500, 0.500]], - [[0.5, 0.5, 0.5], [1.000, 1.000, 1.000], [10.000, 10.000, 10.000], [0.000, 0.000, 0.000]], -].map(partial(cosineGradient, 256)); +import { GRADIENTS } from "./gradient"; // host message listener & responder const $self: any = self; @@ -36,7 +25,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 grad = gradients[gradient]; + const grad = GRADIENTS[gradient]; const pix = new Uint32Array(w * h); for (let y = 0, i = 0; y < h; y++) { for (let x = 0; x < w; x++) { diff --git a/examples/mandelbrot/tsconfig.json b/examples/mandelbrot/tsconfig.json index bbf112cc18..50a1cade93 100644 --- a/examples/mandelbrot/tsconfig.json +++ b/examples/mandelbrot/tsconfig.json @@ -2,10 +2,11 @@ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": ".", + "module": "es6", "target": "es6", "sourceMap": true }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/examples/markdown/.gitignore b/examples/markdown/.gitignore new file mode 100644 index 0000000000..0c5abcab62 --- /dev/null +++ b/examples/markdown/.gitignore @@ -0,0 +1,5 @@ +.cache +out +node_modules +yarn.lock +*.js diff --git a/examples/markdown/README.md b/examples/markdown/README.md new file mode 100644 index 0000000000..840d3f9e28 --- /dev/null +++ b/examples/markdown/README.md @@ -0,0 +1,163 @@ +# Minimal Markdown parser + +This project is part of the +[@thi.ng/umbrella](https://github.com/thi-ng/umbrella/) monorepo. + +## About + +This example is a test environment for the new & minimal +[Markdown](https://en.wikipedia.org/wiki/Markdown) parser & converter to +[hiccup](https://github.com/thi-ng/umbrella/tree/master/packages/hiccup) +format from the +[@thi.ng/hiccup-markdown](https://github.com/thi-ng/umbrella/tree/master/packages/hiccup-markdown) +package. + +The rest of this file is an excerpt of the relevant parts of that +package's `README.md`... + +### Features + +The parser itself is not aimed at supporting **all** of Markdown's +quirky syntax features, but will restrict itself to a sane subset of +features and already sports: + +| Feature | Comments | +|-------------|-----------------------------------------------------------------------------------------------------| +| Heading | ATX only (`#` line prefix), levels 1-6, then downgrade to paragraph | +| Paragraph | no support for `\` line breaks | +| Blockquote | Respects newlines | +| Format | **bold**, _emphasis_, `code`, ~~strikethrough~~ in paragraphs, headings, lists, blockquotes, tables | +| Link | no support for inline formats in label | +| Image | no image links | +| List | only unordered (`- ` line prefix), no nesting, supports line breaks | +| Table | no support for column alignment | +| Code block | GFM only (triple backtick prefix), w/ optional language hint | +| Horiz. Rule | only dash supported (e.g. `---`), min 3 chars required | + +Note: Currently, the last heading, paragraph, blockquote, list or table requires an additional newline. + +### Limitations + +These MD features (and probably many more) are **not** supported: + +- inline HTML +- nested inline formats (e.g. **bold** inside _italic_) +- inline formats within link labels +- image links +- footnotes +- link references +- nested / ordered / numbered / todo lists + +Some of these are considered, though currently not high priority... + +> "Weeks of coding can **save hours** of planning." +> -- Anonymous + +### Other features + +- **Functional:** parser entirely built using + [transducers](https://github.com/thi-ng/umbrella/tree/master/packages/transducers) + & function composition. Use the parser in a transducer pipeline to + easily apply post-processing of the emitted results +- **Declarative:** parsing rules defined declaratively with only minimal + state/context handling needed +- **No regex:** consumes input character-wise and produces an iterator + of hiccup-style tree nodes, ready to be used with + [@thi.ng/hdom](https://github.com/thi-ng/umbrella/tree/master/packages/hdom), + [@thi.ng/hiccup](https://github.com/thi-ng/umbrella/tree/master/packages/hiccup) + or + [@thi.ng/hiccup-markdown](https://github.com/thi-ng/umbrella/tree/master/packages/hiccup-markdown) + (for back conversion to MD) +- **Customizable:** supports custom tag factory functions to override + default behavior / representation of each parsed result element +- **Fast (enough):** parses this markdown file (5.8KB) in ~5ms on MBP2016 / Chrome 71 +- **Small:** minified + gzipped ~2.6KB + +See [example source +code](https://github.com/thi-ng/umbrella/tree/master/examples/markdown/src/) +for reference... + +## Parsing & serializing to HTML + +```ts +import { iterator } from "@thi.ng/transducers"; +import { serialize } from "@thi.ng/hiccup"; + +import { parse } from "@thi.ng/hiccup-markdown"; + +const src = ` +# Hello world + +[This](http://example.com) is a _test_. + +`; + +// convert to hiccup tree +[...iterator(parse(), src)] +// [ [ 'h1', ' Hello world ' ], +// [ 'p', +// [ 'a', { href: 'http://example.com' }, 'This' ], +// ' is a ', +// [ 'em', 'test' ], +// '. ' ] ] + +// or serialize to HTML +serialize(iterator(parse(), src)); + +//

Hello world

+// This is a test.

+``` + +## Customizing tags + +The following interface defines factory functions for all supported +elements. User implementations / overrides can be given to the +`parseMD()` transducer to customize output. + +```ts +interface TagFactories { + blockquote(...children: any[]): any[]; + code(body: string): any[]; + codeblock(lang: string, body: string): any[]; + em(body: string): any[]; + heading(level, children: any[]): any[]; + hr(): any[]; + img(src: string, alt: string): any[]; + li(children: any[]): any[]; + link(href: string, body: string): any[]; + list(type: string, items: any[]): any[]; + paragraph(children: any[]): any[]; + strike(body: string): any[]; + strong(body: string): any[]; + table(rows: any[]): any[]; + td(i: number, children: any[]): any[]; + tr(i: number, cells: any[]): any[]; +} +``` + +Example with custom link elements: + +```ts +const tags = { + link: (href, body) => ["a.link.blue", { href }, body] +}; + +serialize(iterator(parse(tags), src)); + +//

Hello world

+//

This is a test.

+``` + +## Building locally + +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/markdown/index.html b/examples/markdown/index.html new file mode 100644 index 0000000000..3beebc571f --- /dev/null +++ b/examples/markdown/index.html @@ -0,0 +1,41 @@ + + + + + + + + markdown + + + + + +
+ + + + \ No newline at end of file diff --git a/examples/markdown/package.json b/examples/markdown/package.json new file mode 100644 index 0000000000..9fe5de8778 --- /dev/null +++ b/examples/markdown/package.json @@ -0,0 +1,31 @@ +{ + "name": "markdown", + "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 --experimental-scope-hoisting --detailed-report", + "build-parser": "yarn clean && parcel build src/parser.ts -d out --global md --public-url ./ --no-source-maps --no-cache --experimental-scope-hoisting --detailed-report --experimental-scope-hoisting", + "start": "parcel index.html -p 8080 --open" + }, + "devDependencies": { + "parcel-bundler": "^1.11.0", + "terser": "^3.14.1", + "typescript": "^3.2.2" + }, + "dependencies": { + "@thi.ng/api": "latest", + "@thi.ng/bench": "latest", + "@thi.ng/hiccup-markdown": "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/markdown/src/index.ts b/examples/markdown/src/index.ts new file mode 100644 index 0000000000..7c84089307 --- /dev/null +++ b/examples/markdown/src/index.ts @@ -0,0 +1,64 @@ +import { timedResult } from "@thi.ng/bench"; +import { TagFactories, parse } 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"; + +// ignore error, resolved by parcel +import readme from "../README.md"; +// const readme = "README.af35c500.md" + +// custom tag factories (passed to parser) +// uses Tachyons CSS classes for styling +const CUSTOM_TAGS: Partial = { + blockquote: (xs) => ["blockquote.pl3.bl.bw2.i.f4.gray", ...xs], + code: (body) => ["code.bg-light-gray.ph1", body], + codeblock: (lang, body) => ["pre.bg-washed-yellow.pa3.f7.overflow-x-scroll", { lang: lang || "code" }, ["code", body]], + link: (href, body) => ["a.link.dark-blue.hover-white.hover-bg-dark-blue.b", { href }, body], + strike: (body) => ["del.bg-washed-red", body], + table: (xs) => ["table.w-100.collapse.ba.b--black-10", ["tbody", ...xs]], + tr: (_, xs) => ["tr.striped--near-white", ...xs], + td: (i, xs) => [i < 1 ? "th.pa2.ttu.tl" : "td.pa2", ...xs], +}; + +// UI root component +const app = + (input: Stream) => + ({ src, parsed: [hiccup, time] }) => + ["div.flex.vh-100.sans-serif.flex-column.flex-row-l", + ["div.w-100.h-50.w-50-l.h-100-l", + ["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) + } + ]], + ["div.w-100.h-50.w-50-l.vh-100-l.overflow-y-scroll.pa3.lh-copy", + ["div.pa2.bg-yellow.purple.f7", `Parsed ${src.length} chars in ${time}ms`], + ...hiccup] + ]; + +// markdown input stream +const src = stream(); + +// stream transformer & UI update +src.transform( + map((src) => ({ src, parsed: timedResult(() => [...iterator(parse(CUSTOM_TAGS), src)]) })), + map(app(src)), + updateDOM() +); + +// seed temp input +src.next(`# Loading readme...`); + +// load markdown & seed input +fetch(readme) + .then((res) => res.text()) + .then((txt) => src.next(txt)) + .catch((e) => src.next(`# Error loading file: ${e}`)); + +// HMR handling +if (process.env.NODE_ENV !== "production") { + const hot = (module).hot; + hot && hot.dispose(() => src.done()); +} diff --git a/examples/markdown/tsconfig.json b/examples/markdown/tsconfig.json new file mode 100644 index 0000000000..50a1cade93 --- /dev/null +++ b/examples/markdown/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": ".", + "module": "es6", + "target": "es6", + "sourceMap": true + }, + "include": [ + "./src/**/*.ts" + ] +} \ No newline at end of file diff --git a/examples/package-stats/.gitignore b/examples/package-stats/.gitignore new file mode 100644 index 0000000000..5559447e1d --- /dev/null +++ b/examples/package-stats/.gitignore @@ -0,0 +1,6 @@ +.cache +out +node_modules +yarn.lock +*.js +*.svg diff --git a/examples/package-stats/README.md b/examples/package-stats/README.md new file mode 100644 index 0000000000..283cba90ab --- /dev/null +++ b/examples/package-stats/README.md @@ -0,0 +1,26 @@ +# package-stats + +This non-browser example generates several SVG charts of various package +stats in this mono-repo. The charts will be saved in this example's +directory. + +```bash +git clone https://github.com/thi-ng/umbrella.git + +# first need to build the entire mono-repo +# to produce necessary meta data +yarn install +yarn build + +# then run example +cd umbrella/examples/module-stats +yarn build +``` + +## Authors + +- Karsten Schmidt + +## License + +© 2018 Karsten Schmidt // Apache Software License 2.0 diff --git a/examples/package-stats/package.json b/examples/package-stats/package.json new file mode 100644 index 0000000000..0ab15e5c0d --- /dev/null +++ b/examples/package-stats/package.json @@ -0,0 +1,32 @@ +{ + "name": "package-stats", + "version": "0.0.1", + "repository": "https://github.com/thi-ng/umbrella", + "author": "Karsten Schmidt ", + "license": "Apache-2.0", + "scripts": { + "clean": "rm -rf *.js *.svg lib", + "build": "yarn clean && tsc && node lib/index.js" + }, + "devDependencies": { + "parcel-bundler": "^1.10.3", + "terser": "^3.11.0", + "typescript": "^3.2.2" + }, + "dependencies": { + "@thi.ng/checks": "latest", + "@thi.ng/dgraph": "latest", + "@thi.ng/hiccup": "latest", + "@thi.ng/hiccup-svg": "latest", + "@thi.ng/math": "latest", + "@thi.ng/path": "latest", + "@thi.ng/strings": "latest", + "@thi.ng/transducers": "latest" + }, + "browserslist": [ + "last 3 Chrome versions" + ], + "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 new file mode 100644 index 0000000000..5ae4a3fe42 --- /dev/null +++ b/examples/package-stats/src/dep-chart.ts @@ -0,0 +1,91 @@ +import { exists } from "@thi.ng/checks"; +import { DGraph } from "@thi.ng/dgraph"; +import { serialize } from "@thi.ng/hiccup"; +import { group, text } from "@thi.ng/hiccup-svg"; +import { + comp, + filter, + map, + mapcat, + mapIndexed, + max, + pluck, + push, + reducer, + repeat, + transduce, + tuples +} from "@thi.ng/transducers"; +import * as fs from "fs"; +import { + barChart, + labeledTickY, + labeledTickX, +} from "./viz"; + +const BASE_DIR = "../../packages/"; + +const packages = transduce( + comp( + map((f) => BASE_DIR + f), + filter((f) => fs.statSync(f).isDirectory()), + map((f) => { try { return fs.readFileSync(f + "/package.json"); } catch (_) { } }), + filter(exists), + map((p) => JSON.parse(p.toString())), + map((p) => ({ + id: p.name, + v: p.version, + deps: p.dependencies ? Object.keys(p.dependencies) : [] + })) + ), + push(), + fs.readdirSync(BASE_DIR) +); + +const graph = transduce( + mapcat((p: any) => tuples(repeat(p.id), p.deps)), + reducer(() => new DGraph(), (g, [p, d]) => g.addDependency(p, d)), + packages +); + +const packageDeps = packages + .map((p) => [p.id, graph.transitiveDependents(p.id).size]) + .sort((a, b) => b[1] - a[1]); + +const maxDeps = transduce(pluck(1), max(), packageDeps); + +fs.writeFileSync( + `package-deps.svg`, + serialize( + [barChart, + { + attribs: { + width: 1024, + height: 260, + "font-size": "10px", + "font-family": "Iosevka-Term-Light, Menlo, sans-serif" + }, + x: { + axis: [80, 1010, 170], + domain: [0, packageDeps.length, 1], + range: [80, 1020], + ticks: [...map((x) => x[0].substr(8), packageDeps)], + label: labeledTickX + }, + y: { + axis: [170, 10, 65], + domain: [0, maxDeps, 10], + range: [160, 20], + label: labeledTickY(1010) + }, + axis: "#666", + fill: "#0cc" + }, + mapIndexed((i, m) => [i, m[1]], packageDeps), + group({ "font-size": "20px", "text-anchor": "middle" }, + text([552, 28], "@thi.ng/umbrella internal re-use"), + text([552, 56], "(transitive dependents)"), + ) + ] + ) +); diff --git a/examples/package-stats/src/index.ts b/examples/package-stats/src/index.ts new file mode 100644 index 0000000000..3efde481ca --- /dev/null +++ b/examples/package-stats/src/index.ts @@ -0,0 +1,2 @@ +import "./dep-chart"; +import "./size-chart"; diff --git a/examples/package-stats/src/size-chart.ts b/examples/package-stats/src/size-chart.ts new file mode 100644 index 0000000000..89c115248f --- /dev/null +++ b/examples/package-stats/src/size-chart.ts @@ -0,0 +1,83 @@ +import { serialize } from "@thi.ng/hiccup"; +import { group, text } from "@thi.ng/hiccup-svg"; +import { getter } from "@thi.ng/paths"; +import { bytes } from "@thi.ng/strings"; +import { + comp, + filter, + map, + mapcat, + mapIndexed, + max, + push, + transduce +} from "@thi.ng/transducers"; +import * as fs from "fs"; +import { barChart, labeledTickX, labeledTickY } from "./viz"; + +const BASE_DIR = "../../packages/"; + +const meta = transduce( + comp( + map((m: string) => [m, BASE_DIR + m + "/.meta/size.json"]), + filter(([_, path]) => fs.existsSync(path)), + map(([m, path]) => [m, JSON.parse(fs.readFileSync(path).toString())]) + ), + push(), + fs.readdirSync(BASE_DIR) +); + +console.log(meta.length); + +const fileSizeChart = + (stats, modType, type) => { + + const get = getter([1, modType, type]); + stats = [...stats].sort((a, b) => get(b) - get(a)); + + const maxSize = transduce( + mapcat(([_, m]) => [m.esm[type], m.cjs[type], m.umd[type]]), + max(), + stats + ); + + fs.writeFileSync( + `package-sizes-${modType}.svg`, + serialize( + [barChart, + { + attribs: { + width: 1024, + height: 260, + "font-size": "10px", + "font-family": "Iosevka-Term-Light, Menlo, sans-serif" + }, + x: { + axis: [80, 1010, 170], + domain: [0, stats.length, 1], + range: [80, 1020], + ticks: [...map((x) => x[0], stats)], + label: labeledTickX + }, + y: { + axis: [170, 10, 65], + domain: [0, maxSize, 5 * 1024], + range: [160, 20], + label: labeledTickY(1010, bytes) + }, + axis: "#666", + fill: "#0cc" + }, + mapIndexed((i, m) => [i, get(m)], stats), + group({ "font-size": "20px", "text-anchor": "middle" }, + text([552, 28], `@thi.ng/umbrella package sizes (${modType.toUpperCase()})`), + text([552, 56], `(minified + gzipped)`), + ) + ] + ) + ); + }; + +fileSizeChart(meta, "esm", "gzip"); +fileSizeChart(meta, "cjs", "gzip"); +fileSizeChart(meta, "umd", "gzip"); diff --git a/examples/package-stats/src/viz.ts b/examples/package-stats/src/viz.ts new file mode 100644 index 0000000000..986d24fc86 --- /dev/null +++ b/examples/package-stats/src/viz.ts @@ -0,0 +1,107 @@ +import { group, line, svg, text, rect } from "@thi.ng/hiccup-svg"; +import { fit, fit01 } from "@thi.ng/math"; +import { map, mapcat, range, normRange, mapIndexed } from "@thi.ng/transducers"; + +// iterator of range mapped tuples: `[mapped, orig]` +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) + ); + +const mappedTicks = + (start: number, end: number, ticks: any[]) => + mapIndexed( + (i, x) => [fit01(i / ticks.length, start, end), x], + 0, + ticks + ); + +// reusuable axis tick & label combo +export const tick = + (x1: number, y1: number, x2: number, y2: number, tx: number, ty: number, label: any) => [ + line([x1, y1], [x2, y2]), + text([tx, ty], label, { stroke: "none" }) + ]; + +// mapping fn for x-axis ticks +const tickX = + (y: number) => + ([x, n]: [number, any]) => + tick(x, y, x, y + 10, x, y + 20, n); + +// mapping fn for y-axis ticks +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[]) => [ + line([x, y], [x, y + 5]), + text([x, y + 15], n, { + stroke: "none", + "text-anchor": "end", + transform: `rotate(-45 ${x} ${y + 15})` + }) + ]; + +export const labeledTickY = + (width, fmt = (x) => String(x)) => + (x) => + ([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 }) => + ["g", { "text-anchor": "middle" }, + line([a[0], a[2]], [a[1], a[2]]), + mapcat( + (label || tickX)(a[2]), + ticks ? + mappedTicks(r[0], r[1], ticks) : + mappedRange(d[0], d[1], d[2], r[0], r[1]) + )]; + +// y-axis with ticks as SVG group +const axisY = + ({ axis: a, domain: d, range: r, label, ticks }) => + ["g", { "text-anchor": "end" }, + line([a[2], a[0]], [a[2], a[1]]), + mapcat( + (label || tickY)(a[2]), + ticks ? + mappedTicks(r[0], r[1], ticks) : + mappedRange(d[0], d[1], d[2], r[0], r[1]) + )]; + +// mapping fn to create a single bar from `[domainPos, value]` +const bar = + ({ domain: xd, range: xr }, { domain: yd, range: yr }) => + ([xx, yy]) => { + 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) => + svg( + opts.attribs, + group({ stroke: opts.axis, fill: opts.axis }, + axisX(opts.x), + axisY(opts.y)), + group({ fill: opts.fill }, + map(bar(opts.x, opts.y), values)), + ...xs + ); diff --git a/examples/package-stats/tsconfig.json b/examples/package-stats/tsconfig.json new file mode 100644 index 0000000000..933ec03d70 --- /dev/null +++ b/examples/package-stats/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "lib", + "module": "commonjs", + "target": "es6", + "noUnusedLocals": false, + "noUnusedParameters": false, + }, + "include": [ + "./src/**/*.ts" + ] +} \ No newline at end of file diff --git a/examples/pointfree-svg/README.md b/examples/pointfree-svg/README.md index f2835888b0..34d974a6c2 100644 --- a/examples/pointfree-svg/README.md +++ b/examples/pointfree-svg/README.md @@ -1,6 +1,7 @@ # pointfree-svg -This is a non-interactive demo combining the following packages to generate the SVG graphic below: +This is a non-browser demo combining the following packages to generate +the SVG graphic below: - [@thi.ng/hiccup](https://github.com/thi-ng/umbrella/tree/master/packages/hiccup) - [@thi.ng/hiccup-svg](https://github.com/thi-ng/umbrella/tree/master/packages/hiccup-svg) @@ -21,5 +22,14 @@ The generated SVG file will be written in this example's directory... ```bash git clone https://github.com/thi-ng/umbrella.git cd umbrella/examples/pointfree-svg +yarn install yarn build ``` + +## Authors + +- Karsten Schmidt + +## License + +© 2018 Karsten Schmidt // Apache Software License 2.0 diff --git a/examples/pointfree-svg/output.svg b/examples/pointfree-svg/output.svg index 5789d06190..cd29cbc172 100644 --- a/examples/pointfree-svg/output.svg +++ b/examples/pointfree-svg/output.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/examples/pointfree-svg/tsconfig.json b/examples/pointfree-svg/tsconfig.json index 9afed7f9d2..79a8c793a7 100644 --- a/examples/pointfree-svg/tsconfig.json +++ b/examples/pointfree-svg/tsconfig.json @@ -2,9 +2,9 @@ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": ".", + "module": "commonjs", "target": "es6", - "sourceMap": true, - "noUnusedLocals": false, + "sourceMap": true }, "include": [ "./src/**/*.ts" diff --git a/examples/router-basics/README.md b/examples/router-basics/README.md index c9f2c4119b..f2e6ed58a2 100644 --- a/examples/router-basics/README.md +++ b/examples/router-basics/README.md @@ -2,14 +2,9 @@ [Live demo](https://demo.thi.ng/umbrella/router-basics/) -```bash -git clone https://github.com/thi-ng/umbrella.git -cd umbrella/examples/router-basics -yarn install -yarn start -``` - -Installs all dependencies, runs `parcel serve` and opens the app in your browser. +Please refer to the [example build +instructions](https://github.com/thi-ng/umbrella/wiki/Example-build-instructions) +on the wiki. ## About @@ -28,14 +23,6 @@ Features covered: - Dynamic JSON content loading / transformation - Component styling with [Tachyons CSS](http://tachyons.io/) -### Production build - -```bash -yarn build -``` - -Builds a minified version of the app and places it in `/out` directory. - ## Authors - Karsten Schmidt diff --git a/examples/router-basics/package.json b/examples/router-basics/package.json index 7c5bc56019..5e69aefe18 100644 --- a/examples/router-basics/package.json +++ b/examples/router-basics/package.json @@ -8,18 +8,20 @@ "scripts": { "clean": "rm -rf .cache build out", "prep": "yarn clean && mkdir -p out && cp -R assets out", - "build": "yarn prep && parcel build index.html -d out --no-source-maps --no-cache --detailed-report --public-url ./", + "build": "yarn prep && parcel build index.html -d out --no-source-maps --no-cache --experimental-scope-hoisting --detailed-report --public-url ./", "start": "yarn prep && parcel index.html -p 8080 --open -d out" }, "dependencies": { + "@thi.ng/api": "latest", "@thi.ng/atom": "latest", + "@thi.ng/checks": "latest", "@thi.ng/interceptors": "latest", "@thi.ng/hdom": "latest", "@thi.ng/router": "latest" }, "devDependencies": { - "parcel-bundler": "^1.10.3", - "terser": "^3.11.0", + "parcel-bundler": "^1.11.0", + "terser": "^3.14.1", "typescript": "^3.2.2" }, "browserslist": [ diff --git a/examples/router-basics/src/api.ts b/examples/router-basics/src/api.ts index 296ce1831c..11e823b6ff 100644 --- a/examples/router-basics/src/api.ts +++ b/examples/router-basics/src/api.ts @@ -1,8 +1,7 @@ -import { IObjectOf } from "@thi.ng/api/api"; -import { IView, ViewTransform } from "@thi.ng/atom/api"; -import { EffectDef, EventDef } from "@thi.ng/interceptors/api"; -import { EventBus } from "@thi.ng/interceptors/event-bus"; -import { HTMLRouterConfig, RouteMatch } from "@thi.ng/router/api"; +import { IObjectOf } from "@thi.ng/api"; +import { IView, ViewTransform } from "@thi.ng/atom"; +import { EffectDef, EventBus, EventDef } from "@thi.ng/interceptors"; +import { HTMLRouterConfig, RouteMatch } from "@thi.ng/router"; // general types defined for the base app diff --git a/examples/router-basics/src/app.ts b/examples/router-basics/src/app.ts index c046f68e70..584c2c22a2 100644 --- a/examples/router-basics/src/app.ts +++ b/examples/router-basics/src/app.ts @@ -1,12 +1,9 @@ -import { IObjectOf } from "@thi.ng/api/api"; -import { Atom } from "@thi.ng/atom/atom"; -import { isArray } from "@thi.ng/checks/is-array"; +import { IObjectOf } from "@thi.ng/api"; +import { Atom } from "@thi.ng/atom"; +import { isArray } from "@thi.ng/checks"; import { start } from "@thi.ng/hdom"; -import { EventBus } from "@thi.ng/interceptors/event-bus"; -import { trace, valueSetter } from "@thi.ng/interceptors/interceptors"; -import { EVENT_ROUTE_CHANGED } from "@thi.ng/router/api"; -import { HTMLRouter } from "@thi.ng/router/history"; - +import { EventBus, trace, valueSetter } from "@thi.ng/interceptors"; +import { EVENT_ROUTE_CHANGED, HTMLRouter } from "@thi.ng/router"; import { AppConfig, AppContext, @@ -18,6 +15,7 @@ import { nav } from "./components/nav"; import * as fx from "./effects"; import * as ev from "./events"; + /** * Generic base app skeleton. You can use this as basis for your own * apps. diff --git a/examples/router-basics/src/components/event-link.ts b/examples/router-basics/src/components/event-link.ts index 810aac41a0..3104c74161 100644 --- a/examples/router-basics/src/components/event-link.ts +++ b/examples/router-basics/src/components/event-link.ts @@ -1,4 +1,4 @@ -import { Event } from "@thi.ng/interceptors/api"; +import { Event } from "@thi.ng/interceptors"; import { AppContext } from "../api"; diff --git a/examples/router-basics/src/components/home.ts b/examples/router-basics/src/components/home.ts index d04ff6a853..5ce2d56d24 100644 --- a/examples/router-basics/src/components/home.ts +++ b/examples/router-basics/src/components/home.ts @@ -27,6 +27,6 @@ export function home(ctx: AppContext) { ]], ["p", "Please see the related blog post and the commented source code for more details."], - ["p", "(total app file size: 11.8KB)"] + ["p", "(total app file size: 11.2KB)"] ]; } diff --git a/examples/router-basics/src/config.ts b/examples/router-basics/src/config.ts index 0b15eb161d..616ebd2449 100644 --- a/examples/router-basics/src/config.ts +++ b/examples/router-basics/src/config.ts @@ -3,10 +3,9 @@ import { Event, FX_DELAY, FX_DISPATCH_ASYNC, - FX_DISPATCH_NOW -} from "@thi.ng/interceptors/api"; -import { valueUpdater } from "@thi.ng/interceptors/interceptors"; - + FX_DISPATCH_NOW, + valueUpdater +} from "@thi.ng/interceptors"; import { AppConfig, StatusType } from "./api"; import { allUsers } from "./components/all-users"; import { contact } from "./components/contact"; diff --git a/examples/router-basics/src/routes.ts b/examples/router-basics/src/routes.ts index 01a68be3fb..4bf0ec9a44 100644 --- a/examples/router-basics/src/routes.ts +++ b/examples/router-basics/src/routes.ts @@ -1,4 +1,4 @@ -import { Route } from "@thi.ng/router/api"; +import { Route } from "@thi.ng/router"; // route definitions: // routes are 1st class objects and used directly throughout the app diff --git a/examples/router-basics/tsconfig.json b/examples/router-basics/tsconfig.json index b7d63aedf0..50a1cade93 100644 --- a/examples/router-basics/tsconfig.json +++ b/examples/router-basics/tsconfig.json @@ -2,6 +2,7 @@ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": ".", + "module": "es6", "target": "es6", "sourceMap": true }, diff --git a/examples/rstream-dataflow/README.md b/examples/rstream-dataflow/README.md index 0d5e0b1024..4b28b9a965 100644 --- a/examples/rstream-dataflow/README.md +++ b/examples/rstream-dataflow/README.md @@ -2,15 +2,9 @@ [Live demo](https://demo.thi.ng/umbrella/rstream-dataflow/) -```bash -git clone https://github.com/thi-ng/umbrella.git -cd umbrella/examples/rstream-dataflow -yarn install -yarn start -``` - -Installs all dependencies, runs `parcel serve` and opens the app in your -browser. +Please refer to the [example build +instructions](https://github.com/thi-ng/umbrella/wiki/Example-build-instructions) +on the wiki. ## About @@ -32,3 +26,11 @@ package. - [@thi.ng/transducers](https://github.com/thi-ng/umbrella/tree/master/packages/transducers) - data transformations (here used for stream transforms) Please see detailed comments in the source code for further explanations. + +## Authors + +- Karsten Schmidt + +## License + +© 2018 Karsten Schmidt // Apache Software License 2.0 diff --git a/examples/rstream-dataflow/package.json b/examples/rstream-dataflow/package.json index ae22cad7b0..98ca3abb35 100644 --- a/examples/rstream-dataflow/package.json +++ b/examples/rstream-dataflow/package.json @@ -6,17 +6,17 @@ "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 --detailed-report --public-url ./", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --experimental-scope-hoisting --detailed-report --public-url ./", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { - "parcel-bundler": "^1.10.3", - "terser": "^3.11.0", + "parcel-bundler": "^1.11.0", + "terser": "^3.14.1", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/api": "latest", "@thi.ng/atom": "latest", + "@thi.ng/equiv": "latest", "@thi.ng/hdom": "latest", "@thi.ng/paths": "latest", "@thi.ng/rstream": "latest", diff --git a/examples/rstream-dataflow/src/circle.ts b/examples/rstream-dataflow/src/circle.ts index 324ba14133..50e78e5497 100644 --- a/examples/rstream-dataflow/src/circle.ts +++ b/examples/rstream-dataflow/src/circle.ts @@ -1,15 +1,15 @@ const px = (x: number) => x.toFixed(3) + "px"; // @thi.ng/hdom UI component function -export function circle(col: string, x: number, y: number, w: number, h = w) { - return ["div", { - class: "absolute z-1 white f7 tc br-100 " + col, - style: { - left: px(x - w / 2), - top: px(y - h / 2), - width: px(w), - height: px(h), - "line-height": px(h), - } - }, `${x};${y}`]; -} +export const circle = + (col: string, x: number, y: number, w: number, h = w) => + ["div", { + class: "absolute z-1 white f7 tc br-100 " + col, + style: { + left: px(x - w / 2), + top: px(y - h / 2), + width: px(w), + height: px(h), + "line-height": px(h), + } + }, `${x};${y}`]; diff --git a/examples/rstream-dataflow/src/index.ts b/examples/rstream-dataflow/src/index.ts index d402f326d4..64ef333e62 100644 --- a/examples/rstream-dataflow/src/index.ts +++ b/examples/rstream-dataflow/src/index.ts @@ -1,18 +1,23 @@ -import { Atom } from "@thi.ng/atom/atom"; +import { Atom } from "@thi.ng/atom"; import { equiv } from "@thi.ng/equiv"; import { start } from "@thi.ng/hdom"; 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 { initGraph, node, node1 } from "@thi.ng/rstream-graph/graph"; -import { extract } from "@thi.ng/rstream-graph/nodes/extract"; -import { mul } from "@thi.ng/rstream-graph/nodes/math"; -import { fromRAF } from "@thi.ng/rstream/from/raf"; -import { comp } from "@thi.ng/transducers/func/comp"; -import { choices } from "@thi.ng/transducers/iter/choices"; -import { dedupe } from "@thi.ng/transducers/xform/dedupe"; -import { map } from "@thi.ng/transducers/xform/map"; - +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) diff --git a/examples/rstream-dataflow/tsconfig.json b/examples/rstream-dataflow/tsconfig.json index fa5ea1aab2..50a1cade93 100644 --- a/examples/rstream-dataflow/tsconfig.json +++ b/examples/rstream-dataflow/tsconfig.json @@ -2,14 +2,11 @@ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": ".", + "module": "es6", "target": "es6", - "sourceMap": true, - "noUnusedLocals": false, + "sourceMap": true }, "include": [ "./src/**/*.ts" - ], - "exclude": [ - "**/node_modules" ] } \ No newline at end of file diff --git a/examples/rstream-grid/README.md b/examples/rstream-grid/README.md index d26e34f992..5ecc6f2e6a 100644 --- a/examples/rstream-grid/README.md +++ b/examples/rstream-grid/README.md @@ -23,27 +23,14 @@ template. ### Development -```bash -git clone https://github.com/thi-ng/umbrella/ -cd umbrella/examples/rstream-grid -yarn install -yarn start -``` - -Installs all dependencies, runs `parcel serve` and opens the app in your -browser. - -### Production - -```bash -yarn build -``` - -Builds a minified version of the app and places it in the `/out` -directory. +Please refer to the [example build +instructions](https://github.com/thi-ng/umbrella/wiki/Example-build-instructions) +on the wiki. ## Authors - Karsten Schmidt -© 2018 \ No newline at end of file +## License + +© 2018 Karsten Schmidt // Apache Software License 2.0 diff --git a/examples/rstream-grid/package.json b/examples/rstream-grid/package.json index 07b9693170..760a3b0f87 100644 --- a/examples/rstream-grid/package.json +++ b/examples/rstream-grid/package.json @@ -7,21 +7,26 @@ "license": "MIT", "scripts": { "clean": "rm -rf .cache build out", - "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --detailed-report --public-url ./", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --experimental-scope-hoisting --detailed-report --public-url ./", "start": "parcel index.html -p 8080 --open" }, "dependencies": { + "@thi.ng/api": "latest", "@thi.ng/atom": "latest", + "@thi.ng/checks": "latest", "@thi.ng/hdom": "latest", + "@thi.ng/hiccup": "latest", "@thi.ng/hiccup-svg": "latest", "@thi.ng/interceptors": "latest", + "@thi.ng/paths": "latest", + "@thi.ng/rstream": "latest", "@thi.ng/rstream-graph": "latest", "@thi.ng/transducers": "latest" }, "devDependencies": { "@types/node": "^9.6.2", - "parcel-bundler": "^1.10.3", - "terser": "^3.11.0", + "parcel-bundler": "^1.11.0", + "terser": "^3.14.1", "typescript": "^3.2.2" }, "browserslist": [ diff --git a/examples/rstream-grid/src/api.ts b/examples/rstream-grid/src/api.ts index 6f788867c0..a6ebf7199e 100644 --- a/examples/rstream-grid/src/api.ts +++ b/examples/rstream-grid/src/api.ts @@ -1,7 +1,6 @@ -import { IObjectOf } from "@thi.ng/api/api"; -import { IView, ViewTransform } from "@thi.ng/atom/api"; -import { EffectDef, EventDef } from "@thi.ng/interceptors/api"; -import { EventBus } from "@thi.ng/interceptors/event-bus"; +import { IObjectOf } from "@thi.ng/api"; +import { IView, ViewTransform } from "@thi.ng/atom"; +import { EffectDef, EventBus, EventDef } from "@thi.ng/interceptors"; /** * Function signature for main app components. diff --git a/examples/rstream-grid/src/app.ts b/examples/rstream-grid/src/app.ts index 8a8d10b1fe..54332df1b6 100644 --- a/examples/rstream-grid/src/app.ts +++ b/examples/rstream-grid/src/app.ts @@ -1,11 +1,8 @@ -import { IObjectOf } from "@thi.ng/api/api"; -import { Atom } from "@thi.ng/atom/atom"; -import { Cursor } from "@thi.ng/atom/cursor"; -import { History } from "@thi.ng/atom/history"; -import { isArray } from "@thi.ng/checks/is-array"; -import { start } from "@thi.ng/hdom/start"; -import { EventBus } from "@thi.ng/interceptors/event-bus"; - +import { IObjectOf } from "@thi.ng/api"; +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, diff --git a/examples/rstream-grid/src/components/event-link.ts b/examples/rstream-grid/src/components/event-link.ts index ddc4c8bb7a..b0eb0a936c 100644 --- a/examples/rstream-grid/src/components/event-link.ts +++ b/examples/rstream-grid/src/components/event-link.ts @@ -1,4 +1,4 @@ -import { Event } from "@thi.ng/interceptors/api"; +import { Event } from "@thi.ng/interceptors"; import { AppContext } from "../api"; diff --git a/examples/rstream-grid/src/config.ts b/examples/rstream-grid/src/config.ts index 5b08bd848b..a812d509fd 100644 --- a/examples/rstream-grid/src/config.ts +++ b/examples/rstream-grid/src/config.ts @@ -1,9 +1,8 @@ -import { serialize } from "@thi.ng/hiccup/serialize"; -import { snapshot, valueSetter } from "@thi.ng/interceptors/interceptors"; +import { serialize } from "@thi.ng/hiccup"; +import { snapshot, valueSetter } from "@thi.ng/interceptors"; import { getIn } from "@thi.ng/paths"; -import { fromIterable } from "@thi.ng/rstream/from/iterable"; -import { range } from "@thi.ng/transducers/iter/range"; - +import { fromIterable } from "@thi.ng/rstream"; +import { range } from "@thi.ng/transducers"; import { AppConfig } from "./api"; import { main } from "./components/main"; import { download } from "./download"; diff --git a/examples/rstream-grid/src/dataflow.ts b/examples/rstream-grid/src/dataflow.ts index e17ea7ab81..42809b4425 100644 --- a/examples/rstream-grid/src/dataflow.ts +++ b/examples/rstream-grid/src/dataflow.ts @@ -1,11 +1,7 @@ -import { svg } from "@thi.ng/hiccup-svg/svg"; -import { group } from "@thi.ng/hiccup-svg/group"; -import { rect } from "@thi.ng/hiccup-svg/rect"; -import { EventBus } from "@thi.ng/interceptors/event-bus"; -import { initGraph, node } from "@thi.ng/rstream-graph/graph"; -import { range2d } from "@thi.ng/transducers/iter/range2d"; -import { map } from "@thi.ng/transducers/xform/map"; - +import { group, rect, svg } from "@thi.ng/hiccup-svg"; +import { EventBus } from "@thi.ng/interceptors"; +import { initGraph, node } from "@thi.ng/rstream-graph"; +import { map, range2d } from "@thi.ng/transducers"; import * as ev from "./events"; import * as paths from "./paths"; diff --git a/examples/rstream-grid/src/events.ts b/examples/rstream-grid/src/events.ts index 6ba34a9487..2402d9388b 100644 --- a/examples/rstream-grid/src/events.ts +++ b/examples/rstream-grid/src/events.ts @@ -1,4 +1,4 @@ -import { EV_REDO, EV_UNDO } from "@thi.ng/interceptors/api"; +import { EV_REDO, EV_UNDO } from "@thi.ng/interceptors"; // best practice tip: define event & effect names as consts or enums // and avoid hardcoded strings for more safety and easier refactoring diff --git a/examples/rstream-grid/tsconfig.json b/examples/rstream-grid/tsconfig.json index 614bda1f84..50a1cade93 100644 --- a/examples/rstream-grid/tsconfig.json +++ b/examples/rstream-grid/tsconfig.json @@ -2,10 +2,9 @@ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": ".", + "module": "es6", "target": "es6", - "sourceMap": true, - "noUnusedParameters": true, - "noUnusedLocals": true + "sourceMap": true }, "include": [ "./src/**/*.ts" diff --git a/examples/rstream-hdom/README.md b/examples/rstream-hdom/README.md index 23e391d662..5191cbcffd 100644 --- a/examples/rstream-hdom/README.md +++ b/examples/rstream-hdom/README.md @@ -8,12 +8,9 @@ constructs can be used for state handling and reactively trigger [@thi.ng/hdom](https://github.com/thi-ng/umbrella/tree/master/packages/hdom) updates only when any of the UI related streams have value changes. -```bash -git clone https://github.com/thi-ng/umbrella.git -cd umbrella/examples/rstream-hdom -yarn install -yarn start -``` +Please refer to the [example build +instructions](https://github.com/thi-ng/umbrella/wiki/Example-build-instructions) +on the wiki. ## Authors diff --git a/examples/rstream-hdom/package.json b/examples/rstream-hdom/package.json index 2decae4fec..c78c6361aa 100644 --- a/examples/rstream-hdom/package.json +++ b/examples/rstream-hdom/package.json @@ -6,19 +6,18 @@ "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 --detailed-report --public-url ./", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --experimental-scope-hoisting --detailed-report --public-url ./", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { - "parcel-bundler": "^1.10.3", - "terser": "^3.11.0", + "parcel-bundler": "^1.11.0", + "terser": "^3.14.1", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/api": "latest", - "@thi.ng/hdom": "latest", "@thi.ng/rstream": "latest", - "@thi.ng/transducers": "latest" + "@thi.ng/transducers": "latest", + "@thi.ng/transducers-hdom": "latest" }, "browserslist": [ "last 3 Chrome versions" diff --git a/examples/rstream-hdom/src/index.ts b/examples/rstream-hdom/src/index.ts index ca7f079685..56b79ba5a3 100644 --- a/examples/rstream-hdom/src/index.ts +++ b/examples/rstream-hdom/src/index.ts @@ -1,14 +1,19 @@ -import { ISubscribable } from "@thi.ng/rstream/api"; -import { fromRAF } from "@thi.ng/rstream/from/raf"; -import { sync } from "@thi.ng/rstream/stream-sync"; -import { sidechainPartition } from "@thi.ng/rstream/subs/sidechain-partition"; -import { Subscription, subscription } from "@thi.ng/rstream/subscription"; +import { + fromRAF, + ISubscribable, + sidechainPartition, + Subscription, + subscription, + sync +} from "@thi.ng/rstream"; +import { + map, + peek, + reducer, + scan, + vals +} from "@thi.ng/transducers"; import { updateDOM } from "@thi.ng/transducers-hdom"; -import { peek } from "@thi.ng/transducers/func/peek"; -import { vals } from "@thi.ng/transducers/iter/vals"; -import { reducer } from "@thi.ng/transducers/reduce"; -import { map } from "@thi.ng/transducers/xform/map"; -import { scan } from "@thi.ng/transducers/xform/scan"; // example user context object // here only used to provide style / theme config using diff --git a/examples/rstream-hdom/tsconfig.json b/examples/rstream-hdom/tsconfig.json index b7d63aedf0..50a1cade93 100644 --- a/examples/rstream-hdom/tsconfig.json +++ b/examples/rstream-hdom/tsconfig.json @@ -2,6 +2,7 @@ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": ".", + "module": "es6", "target": "es6", "sourceMap": true }, diff --git a/examples/svg-barchart/README.md b/examples/svg-barchart/README.md index 6068c24e7b..2c0026dddf 100644 --- a/examples/svg-barchart/README.md +++ b/examples/svg-barchart/README.md @@ -6,12 +6,9 @@ SVG bar chart component & one-off rendering. ![screenshot](https://raw.githubusercontent.com/thi-ng/umbrella/master/assets/screenshots/svg-barchart.png) -```bash -git clone https://github.com/thi-ng/umbrella.git -cd umbrella/examples/svg-barchart -yarn install -yarn start -``` +Please refer to the [example build +instructions](https://github.com/thi-ng/umbrella/wiki/Example-build-instructions) +on the wiki. ## Authors diff --git a/examples/svg-barchart/package.json b/examples/svg-barchart/package.json index 75290b28f1..961f66b2d1 100644 --- a/examples/svg-barchart/package.json +++ b/examples/svg-barchart/package.json @@ -6,19 +6,17 @@ "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": "yarn clean && parcel build index.html -d out --public-url ./ --no-source-maps --no-cache --experimental-scope-hoisting --detailed-report", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { - "parcel-bundler": "^1.10.3", - "terser": "^3.11.0", + "parcel-bundler": "^1.11.0", + "terser": "^3.14.1", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/api": "latest", - "@thi.ng/atom": "latest", - "@thi.ng/rstream": "latest", - "@thi.ng/transducers-hdom": "latest" + "@thi.ng/hdom": "latest", + "@thi.ng/transducers": "latest" }, "browserslist": [ "last 3 Chrome versions" diff --git a/examples/svg-barchart/src/index.ts b/examples/svg-barchart/src/index.ts index cdaa640e43..ffc7d76775 100644 --- a/examples/svg-barchart/src/index.ts +++ b/examples/svg-barchart/src/index.ts @@ -1,7 +1,5 @@ import { clearDOM, renderOnce } from "@thi.ng/hdom"; -import { range } from "@thi.ng/transducers/iter/range"; -import { map } from "@thi.ng/transducers/xform/map"; -import { mapcat } from "@thi.ng/transducers/xform/mapcat"; +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; diff --git a/examples/svg-barchart/tsconfig.json b/examples/svg-barchart/tsconfig.json index bbf112cc18..50a1cade93 100644 --- a/examples/svg-barchart/tsconfig.json +++ b/examples/svg-barchart/tsconfig.json @@ -2,10 +2,11 @@ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": ".", + "module": "es6", "target": "es6", "sourceMap": true }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/examples/svg-particles/README.md b/examples/svg-particles/README.md index 096e45720e..2d7fe896c8 100644 --- a/examples/svg-particles/README.md +++ b/examples/svg-particles/README.md @@ -2,9 +2,14 @@ [Live demo](https://demo.thi.ng/umbrella/svg-particles/) -```bash -git clone https://github.com/thi-ng/umbrella.git -cd umbrella/examples/svg-particles -yarn install -yarn start -``` +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/svg-particles/package.json b/examples/svg-particles/package.json index 1bedef4aed..a61e7116ae 100644 --- a/examples/svg-particles/package.json +++ b/examples/svg-particles/package.json @@ -6,12 +6,12 @@ "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 --detailed-report --public-url ./", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --experimental-scope-hoisting --detailed-report --public-url ./", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { - "parcel-bundler": "^1.10.3", - "terser": "^3.11.0", + "parcel-bundler": "^1.11.0", + "terser": "^3.14.1", "typescript": "^3.2.2" }, "dependencies": { diff --git a/examples/svg-particles/src/index.ts b/examples/svg-particles/src/index.ts index 0e6cf49940..441a7cb056 100644 --- a/examples/svg-particles/src/index.ts +++ b/examples/svg-particles/src/index.ts @@ -1,6 +1,6 @@ import { start } from "@thi.ng/hdom"; -import { radix } from "@thi.ng/strings/radix"; -import { repeatedly } from "@thi.ng/transducers/iter/repeatedly"; +import { radix } from "@thi.ng/strings"; +import { repeatedly } from "@thi.ng/transducers"; const width = window.innerWidth; const height = window.innerHeight; @@ -37,7 +37,7 @@ const app = () => { for (let i = particles.length - 1; i > 0; i--) { updateParticle(particles[i][1], velocities[i]); } - return ["svg", { width, height }, particles]; + return ["svg", { width, height, __diff: false }, particles]; }; -start(app); \ No newline at end of file +start(app); diff --git a/examples/svg-particles/tsconfig.json b/examples/svg-particles/tsconfig.json index b7d63aedf0..50a1cade93 100644 --- a/examples/svg-particles/tsconfig.json +++ b/examples/svg-particles/tsconfig.json @@ -2,6 +2,7 @@ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": ".", + "module": "es6", "target": "es6", "sourceMap": true }, diff --git a/examples/svg-waveform/README.md b/examples/svg-waveform/README.md index bb6fd12eb5..5d9cb17a14 100644 --- a/examples/svg-waveform/README.md +++ b/examples/svg-waveform/README.md @@ -14,27 +14,14 @@ template. ### Development -```bash -git clone https://github.com/thi-ng/umbrella/ -cd umbrella/examples/svg-waveform -yarn install -yarn start -``` - -Installs all dependencies, runs `parcel serve` and opens the app in your -browser. - -### Production - -```bash -yarn build -``` - -Builds a minified version of the app and places it in the `/out` -directory. +Please refer to the [example build +instructions](https://github.com/thi-ng/umbrella/wiki/Example-build-instructions) +on the wiki. ## Authors - Karsten Schmidt -© 2018 \ No newline at end of file +## License + +© 2018 Karsten Schmidt // Apache Software License 2.0 diff --git a/examples/svg-waveform/package.json b/examples/svg-waveform/package.json index b1492a28e3..f8add8cb71 100644 --- a/examples/svg-waveform/package.json +++ b/examples/svg-waveform/package.json @@ -7,11 +7,13 @@ "license": "MIT", "scripts": { "clean": "rm -rf .cache build out", - "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --detailed-report --public-url ./", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --experimental-scope-hoisting --detailed-report --public-url ./", "start": "parcel index.html -p 8080 --open" }, "dependencies": { + "@thi.ng/api": "latest", "@thi.ng/atom": "latest", + "@thi.ng/checks": "latest", "@thi.ng/hdom": "latest", "@thi.ng/hiccup-svg": "latest", "@thi.ng/interceptors": "latest", @@ -19,8 +21,8 @@ }, "devDependencies": { "@types/node": "^9.6.2", - "parcel-bundler": "^1.10.3", - "terser": "^3.11.0", + "parcel-bundler": "^1.11.0", + "terser": "^3.14.1", "typescript": "^3.2.2" }, "browserslist": [ diff --git a/examples/svg-waveform/src/api.ts b/examples/svg-waveform/src/api.ts index bdafc7ba5a..05f240e789 100644 --- a/examples/svg-waveform/src/api.ts +++ b/examples/svg-waveform/src/api.ts @@ -1,7 +1,6 @@ -import { IObjectOf } from "@thi.ng/api/api"; -import { ViewTransform, IView } from "@thi.ng/atom/api"; -import { EventDef, EffectDef } from "@thi.ng/interceptors/api"; -import { EventBus } from "@thi.ng/interceptors/event-bus"; +import { IObjectOf } from "@thi.ng/api"; +import { IView, ViewTransform } from "@thi.ng/atom"; +import { EffectDef, EventBus, EventDef } from "@thi.ng/interceptors"; /** * Function signature for main app components. diff --git a/examples/svg-waveform/src/app.ts b/examples/svg-waveform/src/app.ts index 2e5bbf4c2a..1e1ad456a6 100644 --- a/examples/svg-waveform/src/app.ts +++ b/examples/svg-waveform/src/app.ts @@ -1,11 +1,14 @@ -import { IObjectOf } from "@thi.ng/api/api"; -import { Atom } from "@thi.ng/atom/atom"; -import { History } from "@thi.ng/atom/history"; -import { isArray } from "@thi.ng/checks/is-array"; +import { IObjectOf } from "@thi.ng/api"; +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/event-bus"; - -import { AppConfig, AppContext, AppViews, ViewSpec } from "./api"; +import { EventBus } from "@thi.ng/interceptors"; +import { + AppConfig, + AppContext, + AppViews, + ViewSpec +} from "./api"; import * as ev from "./events"; /** diff --git a/examples/svg-waveform/src/components/event-link.ts b/examples/svg-waveform/src/components/event-link.ts index fce1ca8aa7..721bf6dd5d 100644 --- a/examples/svg-waveform/src/components/event-link.ts +++ b/examples/svg-waveform/src/components/event-link.ts @@ -1,4 +1,4 @@ -import { Event } from "@thi.ng/interceptors/api"; +import { Event } from "@thi.ng/interceptors"; import { AppContext } from "../api"; diff --git a/examples/svg-waveform/src/components/waveform.ts b/examples/svg-waveform/src/components/waveform.ts index 7940b64fe2..b196817f00 100644 --- a/examples/svg-waveform/src/components/waveform.ts +++ b/examples/svg-waveform/src/components/waveform.ts @@ -1,11 +1,15 @@ -import { svg } from "@thi.ng/hiccup-svg/svg"; -import { defs } from "@thi.ng/hiccup-svg/defs"; -import { linearGradient } from "@thi.ng/hiccup-svg/gradients"; -import { polyline } from "@thi.ng/hiccup-svg/polyline"; -import { map } from "@thi.ng/transducers/xform/map"; -import { range } from "@thi.ng/transducers/iter/range"; -import { reduce, reducer } from "@thi.ng/transducers/reduce"; - +import { + defs, + linearGradient, + polyline, + svg +} from "@thi.ng/hiccup-svg"; +import { + map, + range, + reduce, + reducer +} from "@thi.ng/transducers"; import { AppContext } from "../api"; const TAU = Math.PI * 2; diff --git a/examples/svg-waveform/src/config.ts b/examples/svg-waveform/src/config.ts index 3ddd2aa651..63454bf03e 100644 --- a/examples/svg-waveform/src/config.ts +++ b/examples/svg-waveform/src/config.ts @@ -1,4 +1,4 @@ -import { ensureParamRange, snapshot, valueSetter } from "@thi.ng/interceptors/interceptors" +import { ensureParamRange, snapshot, valueSetter } from "@thi.ng/interceptors" import { AppConfig } from "./api"; // import * as ev from "./events"; // import * as fx from "./effects"; diff --git a/examples/svg-waveform/src/events.ts b/examples/svg-waveform/src/events.ts index 4f9837bb18..e57f04400e 100644 --- a/examples/svg-waveform/src/events.ts +++ b/examples/svg-waveform/src/events.ts @@ -1,4 +1,4 @@ -import { EV_UNDO, EV_REDO } from "@thi.ng/interceptors/api"; +import { EV_UNDO, EV_REDO } from "@thi.ng/interceptors"; // best practice tip: define event & effect names as consts or enums // and avoid hardcoded strings for more safety and easier refactoring diff --git a/examples/svg-waveform/tsconfig.json b/examples/svg-waveform/tsconfig.json index 614bda1f84..50a1cade93 100644 --- a/examples/svg-waveform/tsconfig.json +++ b/examples/svg-waveform/tsconfig.json @@ -2,10 +2,9 @@ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": ".", + "module": "es6", "target": "es6", - "sourceMap": true, - "noUnusedParameters": true, - "noUnusedLocals": true + "sourceMap": true }, "include": [ "./src/**/*.ts" diff --git a/examples/talk-slides/README.md b/examples/talk-slides/README.md index ec44933758..0eefe8e574 100644 --- a/examples/talk-slides/README.md +++ b/examples/talk-slides/README.md @@ -30,12 +30,9 @@ As usual, all theming is done via [Tachyons CSS](http://tachyons.io), also see this useful site for quick reference: [Tachyons TL;DR](https://tachyons-tldr.now.sh/). -```bash -git clone https://github.com/thi-ng/umbrella.git -cd umbrella/examples/talk-slides -yarn install -yarn start -``` +Please refer to the [example build +instructions](https://github.com/thi-ng/umbrella/wiki/Example-build-instructions) +on the wiki. ## Authors diff --git a/examples/talk-slides/package.json b/examples/talk-slides/package.json index 86af6005ba..eea34b055b 100644 --- a/examples/talk-slides/package.json +++ b/examples/talk-slides/package.json @@ -6,18 +6,19 @@ "license": "Apache-2.0", "scripts": { "clean": "rm -rf .cache build out", - "build": "parcel build index.html -d out --public-url ./ --no-source-maps --no-cache --detailed-report", + "build": "parcel build index.html -d out --public-url ./ --no-source-maps --no-cache --experimental-scope-hoisting --detailed-report", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { - "parcel-bundler": "^1.10.3", - "terser": "^3.11.0", + "parcel-bundler": "^1.11.0", + "terser": "^3.14.1", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/api": "latest", + "@thi.ng/hdom": "latest", "@thi.ng/math": "latest", "@thi.ng/rstream": "latest", + "@thi.ng/strings": "latest", "@thi.ng/transducers": "latest", "@thi.ng/transducers-hdom": "latest" }, diff --git a/examples/talk-slides/src/index.ts b/examples/talk-slides/src/index.ts index ea1660cd0b..e87fb41fd3 100644 --- a/examples/talk-slides/src/index.ts +++ b/examples/talk-slides/src/index.ts @@ -1,16 +1,20 @@ -import { renderOnce } from "@thi.ng/hdom/render-once"; -import { clamp } from "@thi.ng/math/interval"; -import { fromEvent } from "@thi.ng/rstream/from/event"; -import { fromInterval } from "@thi.ng/rstream/from/interval"; -import { stream } from "@thi.ng/rstream/stream"; -import { sync } from "@thi.ng/rstream/stream-sync"; -import { padLeft } from "@thi.ng/strings/pad-left"; +import { renderOnce } from "@thi.ng/hdom"; +import { clamp } from "@thi.ng/math"; +import { + fromEvent, + fromInterval, + stream, + sync +} from "@thi.ng/rstream"; +import { padLeft } from "@thi.ng/strings"; +import { + dedupe, + map, + reducer, + scan, + sideEffect +} from "@thi.ng/transducers"; import { updateDOM } from "@thi.ng/transducers-hdom"; -import { reducer } from "@thi.ng/transducers/reduce"; -import { dedupe } from "@thi.ng/transducers/xform/dedupe"; -import { map } from "@thi.ng/transducers/xform/map"; -import { scan } from "@thi.ng/transducers/xform/scan"; -import { sideEffect } from "@thi.ng/transducers/xform/side-effect"; import { app, printApp } from "./components"; import { ctx } from "./config"; import { SLIDES } from "./slides"; diff --git a/examples/talk-slides/tsconfig.json b/examples/talk-slides/tsconfig.json index bbf112cc18..50a1cade93 100644 --- a/examples/talk-slides/tsconfig.json +++ b/examples/talk-slides/tsconfig.json @@ -2,10 +2,11 @@ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": ".", + "module": "es6", "target": "es6", "sourceMap": true }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/examples/todo-list/README.md b/examples/todo-list/README.md index df37f41c20..a2260e0264 100644 --- a/examples/todo-list/README.md +++ b/examples/todo-list/README.md @@ -2,9 +2,14 @@ [Live demo here](https://demo.thi.ng/umbrella/todo-list/) -```bash -git clone https://github.com/thi-ng/umbrella.git -cd umbrella/examples/todo-list -yarn install -yarn start -``` +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/todo-list/package.json b/examples/todo-list/package.json index 079ff4cbec..f9982ad6d3 100644 --- a/examples/todo-list/package.json +++ b/examples/todo-list/package.json @@ -6,15 +6,16 @@ "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 --detailed-report --public-url ./", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --experimental-scope-hoisting --detailed-report --public-url ./", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { - "parcel-bundler": "^1.10.3", - "terser": "^3.11.0", + "parcel-bundler": "^1.11.0", + "terser": "^3.14.1", "typescript": "^3.2.2" }, "dependencies": { + "@thi.ng/api": "latest", "@thi.ng/atom": "latest", "@thi.ng/hdom": "latest", "@thi.ng/paths": "latest", diff --git a/examples/todo-list/src/index.ts b/examples/todo-list/src/index.ts index f539dd9e96..48ba33b4aa 100644 --- a/examples/todo-list/src/index.ts +++ b/examples/todo-list/src/index.ts @@ -1,9 +1,8 @@ -import { IObjectOf } from "@thi.ng/api/api"; +import { IObjectOf } from "@thi.ng/api"; import { Atom, Cursor, History } from "@thi.ng/atom"; -import { start } from "@thi.ng/hdom/start"; +import { start } from "@thi.ng/hdom"; import { setIn, updateIn } from "@thi.ng/paths"; -import { pairs } from "@thi.ng/transducers/iter/pairs"; -import { map } from "@thi.ng/transducers/xform/map"; +import { map, pairs } from "@thi.ng/transducers"; interface Task { done: boolean; diff --git a/examples/todo-list/tsconfig.json b/examples/todo-list/tsconfig.json index b7d63aedf0..50a1cade93 100644 --- a/examples/todo-list/tsconfig.json +++ b/examples/todo-list/tsconfig.json @@ -2,6 +2,7 @@ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": ".", + "module": "es6", "target": "es6", "sourceMap": true }, diff --git a/examples/transducers-hdom/README.md b/examples/transducers-hdom/README.md index 5e95e328d6..8a04234d13 100644 --- a/examples/transducers-hdom/README.md +++ b/examples/transducers-hdom/README.md @@ -2,12 +2,9 @@ [Live demo](https://demo.thi.ng/umbrella/transducers-hdom/) -```bash -git clone https://github.com/thi-ng/umbrella.git -cd umbrella/examples/transducers-hdom -yarn install -yarn start -``` +Please refer to the [example build +instructions](https://github.com/thi-ng/umbrella/wiki/Example-build-instructions) +on the wiki. ## Authors diff --git a/examples/transducers-hdom/package.json b/examples/transducers-hdom/package.json index aabe19927d..922591d1db 100644 --- a/examples/transducers-hdom/package.json +++ b/examples/transducers-hdom/package.json @@ -6,16 +6,17 @@ "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 --detailed-report --public-url ./", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --experimental-scope-hoisting --detailed-report --public-url ./", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { - "parcel-bundler": "^1.10.3", - "terser": "^3.11.0", + "parcel-bundler": "^1.11.0", + "terser": "^3.14.1", "typescript": "^3.2.2" }, "dependencies": { "@thi.ng/rstream": "latest", + "@thi.ng/transducers": "latest", "@thi.ng/transducers-hdom": "latest" }, "browserslist": [ diff --git a/examples/transducers-hdom/src/index.ts b/examples/transducers-hdom/src/index.ts index 8ae55763e1..52e47c407a 100644 --- a/examples/transducers-hdom/src/index.ts +++ b/examples/transducers-hdom/src/index.ts @@ -1,10 +1,6 @@ -import { fromInterval } from "@thi.ng/rstream/from/interval"; -import { stream } from "@thi.ng/rstream/stream"; -import { sync } from "@thi.ng/rstream/stream-sync"; +import { fromInterval, stream, sync } from "@thi.ng/rstream"; +import { count, map, scan } from "@thi.ng/transducers"; import { updateDOM } from "@thi.ng/transducers-hdom"; -import { count } from "@thi.ng/transducers/rfn/count"; -import { map } from "@thi.ng/transducers/xform/map"; -import { scan } from "@thi.ng/transducers/xform/scan"; // root component function // (using Tachyons CSS classes for styling) diff --git a/examples/transducers-hdom/tsconfig.json b/examples/transducers-hdom/tsconfig.json index b7d63aedf0..50a1cade93 100644 --- a/examples/transducers-hdom/tsconfig.json +++ b/examples/transducers-hdom/tsconfig.json @@ -2,6 +2,7 @@ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": ".", + "module": "es6", "target": "es6", "sourceMap": true }, diff --git a/examples/triple-query/README.md b/examples/triple-query/README.md index 3aaddfe213..c10f1deb11 100644 --- a/examples/triple-query/README.md +++ b/examples/triple-query/README.md @@ -2,12 +2,9 @@ [Live demo](https://demo.thi.ng/umbrella/triple-query/) -```bash -git clone https://github.com/thi-ng/umbrella.git -cd umbrella/examples/triple-query -yarn install -yarn start -``` +Please refer to the [example build +instructions](https://github.com/thi-ng/umbrella/wiki/Example-build-instructions) +on the wiki. ## Authors diff --git a/examples/triple-query/package.json b/examples/triple-query/package.json index 016b34009e..8913b5c0b8 100644 --- a/examples/triple-query/package.json +++ b/examples/triple-query/package.json @@ -6,17 +6,22 @@ "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 --detailed-report --public-url ./", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --experimental-scope-hoisting --detailed-report --public-url ./", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { - "parcel-bundler": "^1.10.3", - "terser": "^3.11.0", + "parcel-bundler": "^1.11.0", + "terser": "^3.14.1", "typescript": "^3.2.2" }, "dependencies": { "@thi.ng/api": "latest", + "@thi.ng/atom": "latest", + "@thi.ng/checks": "latest", + "@thi.ng/compare": "latest", "@thi.ng/hdom": "latest", + "@thi.ng/hdom-components": "latest", + "@thi.ng/paths": "latest", "@thi.ng/rstream-query": "latest", "@thi.ng/transducers": "latest" }, diff --git a/examples/triple-query/src/api.ts b/examples/triple-query/src/api.ts index dea7859178..680da2d331 100644 --- a/examples/triple-query/src/api.ts +++ b/examples/triple-query/src/api.ts @@ -1,9 +1,12 @@ -import { IObjectOf } from "@thi.ng/api/api"; -import { IView, ViewTransform } from "@thi.ng/atom/api"; -import { EffectDef, EventDef, InterceptorContext } from "@thi.ng/interceptors/api"; -import { EventBus } from "@thi.ng/interceptors/event-bus"; -import { QuerySpec } from "@thi.ng/rstream-query/api"; -import { TripleStore } from "@thi.ng/rstream-query/store"; +import { IObjectOf } from "@thi.ng/api"; +import { IView, ViewTransform } from "@thi.ng/atom"; +import { + EffectDef, + EventBus, + EventDef, + InterceptorContext +} from "@thi.ng/interceptors"; +import { QuerySpec, TripleStore } from "@thi.ng/rstream-query"; /** * Function signature for main app components. diff --git a/examples/triple-query/src/app.ts b/examples/triple-query/src/app.ts index 06a9aba1e5..0da6769183 100644 --- a/examples/triple-query/src/app.ts +++ b/examples/triple-query/src/app.ts @@ -1,11 +1,9 @@ -import { IObjectOf } from "@thi.ng/api/api"; -import { Atom } from "@thi.ng/atom/atom"; -import { isArray } from "@thi.ng/checks/is-array"; -import { start } from "@thi.ng/hdom/start"; -import { EV_SET_VALUE } from "@thi.ng/interceptors/api"; -import { EventBus } from "@thi.ng/interceptors/event-bus"; -import { TripleStore } from "@thi.ng/rstream-query/store"; - +import { IObjectOf } from "@thi.ng/api"; +import { Atom } from "@thi.ng/atom"; +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, @@ -14,6 +12,7 @@ import { } from "./api"; import * as ev from "./events"; + /** * Generic base app skeleton. You can use this as basis for your own * apps. diff --git a/examples/triple-query/src/components/event-link.ts b/examples/triple-query/src/components/event-link.ts index fce1ca8aa7..721bf6dd5d 100644 --- a/examples/triple-query/src/components/event-link.ts +++ b/examples/triple-query/src/components/event-link.ts @@ -1,4 +1,4 @@ -import { Event } from "@thi.ng/interceptors/api"; +import { Event } from "@thi.ng/interceptors"; import { AppContext } from "../api"; diff --git a/examples/triple-query/src/components/query-results.ts b/examples/triple-query/src/components/query-results.ts index c9dcfffc32..917e8b5c44 100644 --- a/examples/triple-query/src/components/query-results.ts +++ b/examples/triple-query/src/components/query-results.ts @@ -1,7 +1,4 @@ -import { repeat } from "@thi.ng/transducers/iter/repeat"; -import { map } from "@thi.ng/transducers/xform/map"; -import { mapIndexed } from "@thi.ng/transducers/xform/map-indexed"; - +import { map, mapIndexed, repeat } from "@thi.ng/transducers"; import { AppContext } from "../api"; import { section } from "./section"; import { table } from "./table"; diff --git a/examples/triple-query/src/components/section.ts b/examples/triple-query/src/components/section.ts index da0e102d10..9f73b69c37 100644 --- a/examples/triple-query/src/components/section.ts +++ b/examples/triple-query/src/components/section.ts @@ -1,4 +1,4 @@ -import { title } from "@thi.ng/hdom-components/title"; +import { title } from "@thi.ng/hdom-components"; const h1 = title({ subAttribs: { class: "moon-gray" } }); diff --git a/examples/triple-query/src/components/table.ts b/examples/triple-query/src/components/table.ts index d76fcd6b4b..0159f3c109 100644 --- a/examples/triple-query/src/components/table.ts +++ b/examples/triple-query/src/components/table.ts @@ -1,4 +1,4 @@ -import { map } from "@thi.ng/transducers/xform/map"; +import { map } from "@thi.ng/transducers"; import { AppContext } from "../api"; diff --git a/examples/triple-query/src/components/triple-table.ts b/examples/triple-query/src/components/triple-table.ts index c3f1ab3ad0..d830e09133 100644 --- a/examples/triple-query/src/components/triple-table.ts +++ b/examples/triple-query/src/components/triple-table.ts @@ -1,4 +1,4 @@ -import { pager } from "@thi.ng/hdom-components/pager"; +import { pager } from "@thi.ng/hdom-components"; import { AppContext } from "../api"; import { SET_PAGE, SET_SORT } from "../events"; diff --git a/examples/triple-query/src/handlers.ts b/examples/triple-query/src/handlers.ts index 769f3b5633..3c983e8dec 100644 --- a/examples/triple-query/src/handlers.ts +++ b/examples/triple-query/src/handlers.ts @@ -1,17 +1,23 @@ -import { IObjectOf } from "@thi.ng/api/api"; +import { IObjectOf } from "@thi.ng/api"; import { compare } from "@thi.ng/compare"; -import { FX_DISPATCH_NOW, FX_STATE } from "@thi.ng/interceptors/api"; -import { EffectDef, EventDef } from "@thi.ng/interceptors/api"; -import { dispatchNow, valueSetter } from "@thi.ng/interceptors/interceptors"; +import { + dispatchNow, + EffectDef, + EventDef, + FX_DISPATCH_NOW, + FX_STATE, + valueSetter +} from "@thi.ng/interceptors"; import { getIn, setIn } from "@thi.ng/paths"; -import { Triple } from "@thi.ng/rstream-query/api"; -import { comp } from "@thi.ng/transducers/func/comp"; -import { repeat } from "@thi.ng/transducers/iter/repeat"; -import { iterator } from "@thi.ng/transducers/iterator"; -import { mapIndexed } from "@thi.ng/transducers/xform/map-indexed"; -import { padLast } from "@thi.ng/transducers/xform/pad-last"; -import { page } from "@thi.ng/transducers/xform/page"; - +import { Triple } from "@thi.ng/rstream-query"; +import { + comp, + iterator, + mapIndexed, + padLast, + page, + repeat +} from "@thi.ng/transducers"; import { AppInterceptorContext } from "./api"; import * as fx from "./effects"; import * as ev from "./events"; diff --git a/examples/triple-query/src/index.ts b/examples/triple-query/src/index.ts index 3031006634..408b3861c3 100644 --- a/examples/triple-query/src/index.ts +++ b/examples/triple-query/src/index.ts @@ -8,5 +8,3 @@ if (process.env.NODE_ENV == "development") { } else { new App(CONFIG).start(); } - -window["equiv"] = require("@thi.ng/equiv").equiv; \ No newline at end of file diff --git a/examples/triple-query/tsconfig.json b/examples/triple-query/tsconfig.json index 13b7ae5211..50a1cade93 100644 --- a/examples/triple-query/tsconfig.json +++ b/examples/triple-query/tsconfig.json @@ -2,9 +2,9 @@ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": ".", + "module": "es6", "target": "es6", - "sourceMap": true, - "noUnusedLocals": false + "sourceMap": true }, "include": [ "./src/**/*.ts" diff --git a/examples/webgl/README.md b/examples/webgl/README.md index baf68109e0..30c1423225 100644 --- a/examples/webgl/README.md +++ b/examples/webgl/README.md @@ -2,9 +2,14 @@ [Live demo](https://demo.thi.ng/umbrella/webgl/) -```bash -git clone https://github.com/thi-ng/umbrella.git -cd umbrella/examples/webgl -yarn install -yarn start -``` +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/package.json b/examples/webgl/package.json index 66b19bdd5e..b77b59b4ad 100644 --- a/examples/webgl/package.json +++ b/examples/webgl/package.json @@ -6,12 +6,12 @@ "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 --detailed-report --public-url ./", + "build": "yarn clean && parcel build index.html -d out --no-source-maps --no-cache --experimental-scope-hoisting --detailed-report --public-url ./", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { - "parcel-bundler": "^1.10.3", - "terser": "^3.11.0", + "parcel-bundler": "^1.11.0", + "terser": "^3.14.1", "typescript": "^3.2.2" }, "dependencies": { diff --git a/examples/webgl/src/index.ts b/examples/webgl/src/index.ts index 3899b07843..602d5043fc 100644 --- a/examples/webgl/src/index.ts +++ b/examples/webgl/src/index.ts @@ -1,6 +1,6 @@ import { start } from "@thi.ng/hdom"; -import { canvasWebGL } from "@thi.ng/hdom-components/canvas"; -import { repeatedly } from "@thi.ng/transducers/iter/repeatedly"; +import { canvasWebGL } from "@thi.ng/hdom-components"; +import { repeatedly } from "@thi.ng/transducers"; // canvas init hook const initGL = (_: HTMLCanvasElement, __: WebGLRenderingContext) => { diff --git a/examples/webgl/tsconfig.json b/examples/webgl/tsconfig.json index 98e83903d2..21c832b5d7 100644 --- a/examples/webgl/tsconfig.json +++ b/examples/webgl/tsconfig.json @@ -2,6 +2,7 @@ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": ".", + "module": "es6", "target": "es6", "sourceMap": true, "noUnusedLocals": false, diff --git a/examples/xml-converter/README.md b/examples/xml-converter/README.md index c3c9333baa..d60ae94e3e 100644 --- a/examples/xml-converter/README.md +++ b/examples/xml-converter/README.md @@ -18,12 +18,14 @@ dataflow topology used by the browser app: ![dataflow](https://raw.githubusercontent.com/thi-ng/umbrella/master/assets/xml-converter.png) ## Browser version -```bash -git clone https://github.com/thi-ng/umbrella.git -cd umbrella/examples/xml-converter -yarn install -yarn start -``` + +Please refer to the [example build +instructions](https://github.com/thi-ng/umbrella/wiki/Example-build-instructions) +on the wiki. + +**IMPORTANT:** Please also see the [troubleshooting +note](https://github.com/thi-ng/umbrella/wiki/Example-build-instructions#troubleshooting) +and temporary workaround for this example. ## CLI version @@ -33,6 +35,8 @@ written to stdout). ```bash # in this example's project root... +yarn install + yarn build-cli bin/hiccup --help diff --git a/examples/xml-converter/package.json b/examples/xml-converter/package.json index a41d418575..62410ee370 100644 --- a/examples/xml-converter/package.json +++ b/examples/xml-converter/package.json @@ -6,19 +6,22 @@ "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": "yarn clean && parcel build index.html -d out --public-url ./ --no-source-maps --no-cache --experimental-scope-hoisting --detailed-report", "build-cli": "tsc -p tsconfig-cli.json", "start": "parcel index.html -p 8080 --open" }, "devDependencies": { - "parcel-bundler": "^1.10.3", - "terser": "^3.11.0", + "parcel-bundler": "^1.11.0", + "terser": "^3.14.1", "typescript": "^3.2.2" }, "dependencies": { + "@thi.ng/checks": "latest", + "@thi.ng/defmulti": "latest", "@thi.ng/rstream": "latest", "@thi.ng/sax": "latest", "@thi.ng/strings": "latest", + "@thi.ng/transducers": "latest", "@thi.ng/transducers-hdom": "latest", "commander": "^2.18.0" }, diff --git a/examples/xml-converter/src/convert.ts b/examples/xml-converter/src/convert.ts index 08bf73e1ff..347adc560f 100644 --- a/examples/xml-converter/src/convert.ts +++ b/examples/xml-converter/src/convert.ts @@ -1,18 +1,20 @@ -import { isString } from "@thi.ng/checks/is-string"; +import { isString } from "@thi.ng/checks"; import { parse, ParseElement, ParseEvent, Type } from "@thi.ng/sax"; -import { comp } from "@thi.ng/transducers/func/comp"; -import { pairs } from "@thi.ng/transducers/iter/pairs"; -import { assocObj } from "@thi.ng/transducers/rfn/assoc-obj"; -import { last } from "@thi.ng/transducers/rfn/last"; -import { push } from "@thi.ng/transducers/rfn/push"; -import { transduce } from "@thi.ng/transducers/transduce"; -import { filter } from "@thi.ng/transducers/xform/filter"; -import { map } from "@thi.ng/transducers/xform/map"; +import { + assocObj, + comp, + filter, + last, + map, + pairs, + push, + transduce +} from "@thi.ng/transducers"; import { DEFAULT_FORMAT, format, FormatOpts } from "./format"; export interface ConversionOpts { diff --git a/examples/xml-converter/src/format.ts b/examples/xml-converter/src/format.ts index db99cc652c..13986f74e7 100644 --- a/examples/xml-converter/src/format.ts +++ b/examples/xml-converter/src/format.ts @@ -1,10 +1,12 @@ -import { isArray } from "@thi.ng/checks/is-array"; -import { isBoolean } from "@thi.ng/checks/is-boolean"; -import { isNumber } from "@thi.ng/checks/is-number"; -import { isPlainObject } from "@thi.ng/checks/is-plain-object"; +import { + isArray, + isBoolean, + isNumber, + isPlainObject +} from "@thi.ng/checks"; import { DEFAULT, defmulti } from "@thi.ng/defmulti"; -import { repeat } from "@thi.ng/strings/repeat"; -import { peek } from "@thi.ng/transducers/func/peek"; +import { repeat } from "@thi.ng/strings"; +import { peek } from "@thi.ng/transducers"; export interface FormatOpts { indent: number; @@ -57,13 +59,19 @@ const formatVal = (opts: FormatOpts, x: any, indent = true) => x : isPlainObject(x) ? format(indent ? indentState(opts) : opts, "", x) : - opts.quote + x + opts.quote; + opts.quote + escape(opts, x) + opts.quote; // attrib key-value pair formatter w/ indentation const formatPair = (opts: FormatOpts, x: any, k: string) => spaces(opts.indent) + formatAttrib(opts, k) + ":" + opts.ws + formatVal(opts, x[k], k !== "style"); +const escape = + (opts: FormatOpts, x: any) => + opts.quote === "\"" ? + String(x).replace(/"/g, "\\\"") : + String(x).replace(/'/g, "\\\'"); + // multiple-dispatch function to format the transformed tree (hiccup // structure) into a more compact & legible format than produced by // standard: `JSON.stringify(tree, null, 4)` diff --git a/examples/xml-converter/src/index.ts b/examples/xml-converter/src/index.ts index 402b9c11ef..cac40e5857 100644 --- a/examples/xml-converter/src/index.ts +++ b/examples/xml-converter/src/index.ts @@ -1,8 +1,6 @@ -import { stream } from "@thi.ng/rstream/stream"; -import { sync } from "@thi.ng/rstream/stream-sync"; +import { stream, sync } from "@thi.ng/rstream"; +import { map } from "@thi.ng/transducers"; import { updateDOM } from "@thi.ng/transducers-hdom"; -import { map } from "@thi.ng/transducers/xform/map"; - import { convertXML } from "./convert"; import { COMPACT_FORMAT, DEFAULT_FORMAT } from "./format"; import { app, UI } from "./ui"; diff --git a/examples/xml-converter/src/ui.ts b/examples/xml-converter/src/ui.ts index 738453d71d..1425e1aa41 100644 --- a/examples/xml-converter/src/ui.ts +++ b/examples/xml-converter/src/ui.ts @@ -1,4 +1,4 @@ -import { mapIndexed } from "@thi.ng/transducers/xform/map-indexed"; +import { mapIndexed } from "@thi.ng/transducers"; import { handleTab } from "./utils"; // converted from: diff --git a/examples/xml-converter/src/utils.ts b/examples/xml-converter/src/utils.ts index ecb05108a1..0cfd9a1838 100644 --- a/examples/xml-converter/src/utils.ts +++ b/examples/xml-converter/src/utils.ts @@ -1,26 +1,29 @@ -import { splice } from "@thi.ng/strings/splice"; -import { map } from "@thi.ng/transducers/xform/map"; +import { splice } from "@thi.ng/strings"; +import { map } from "@thi.ng/transducers"; -export const asSet = (x: string) => - new Set(map((x) => x.trim(), x.split(","))); +export const asSet = + (x: string) => + new Set(map((x) => x.trim(), x.split(","))); // helper transducer to convert a CSV string into an ES6 Set 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) => { - // override tab to insert spaces at edit pos - if (e.key === "Tab") { - e.preventDefault(); - stream.next( - splice((e.target).value, " ", - (e.target).selectionStart - ) - ); - } - }; +export const handleTab = + (stream) => + (e: KeyboardEvent) => { + // override tab to insert spaces at edit pos + if (e.key === "Tab") { + e.preventDefault(); + stream.next( + splice((e.target).value, " ", + (e.target).selectionStart + ) + ); + } + }; -export const varName = (name: string) => - name.replace(/\-+/g, "_"); +export const varName = + (name: string) => + name.replace(/\-+/g, "_"); diff --git a/examples/xml-converter/tsconfig.json b/examples/xml-converter/tsconfig.json index bbf112cc18..50a1cade93 100644 --- a/examples/xml-converter/tsconfig.json +++ b/examples/xml-converter/tsconfig.json @@ -2,10 +2,11 @@ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": ".", + "module": "es6", "target": "es6", "sourceMap": true }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/lerna.json b/lerna.json index 1d7b66a51d..fb17f8b5e5 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "lerna": "3.3.0", + "lerna": "3.8.5", "packages": [ "packages/*" ], diff --git a/package.json b/package.json index 2f033a9c96..1dc905d799 100644 --- a/package.json +++ b/package.json @@ -5,22 +5,32 @@ ], "devDependencies": { "benchmark": "^2.1.4", - "lerna": "^3.6.0", + "gzip-size": "^5.0.0", + "lerna": "^3.8.5", "mocha": "^5.2.0", "nyc": "^13.1.0", - "parcel-bundler": "^1.10.3", - "terser": "^3.11.0", - "tslint": "^5.11.0", - "typescript": "^3.2.2" + "parcel-bundler": "^1.11.0", + "rimraf": "^2.6.3", + "rollup": "^1.1.0", + "rollup-plugin-cleanup": "^3.1.0", + "terser": "^3.14.1", + "tslint": "^5.12.0", + "typescript": "^3.2.2", + "webpack": "^4.28.1", + "webpack-cli": "^3.2.1", + "ts-loader": "^5.3.3", + "file-loader": "^3.0.1" }, "scripts": { "bootstrap": "lerna bootstrap", "build": "yarn install && lerna -v && lerna bootstrap && lerna run build --sort", + "build:es6only": "lerna run clean && lerna run build:es6", "cover": "lerna run cover", "depgraph": "scripts/depgraph && git add assets/deps.png && git commit -m 'docs: update dep graph' && git push", "doc": "lerna run doc", "examples": "scripts/build-examples", "pub": "lerna publish --registry https://registry.npmjs.org/ && yarn doc && scripts/upload-docs", - "test": "yarn build && lerna run test" + "test": "yarn build && yarn test:only", + "test:only": "lerna run test" } -} +} \ No newline at end of file diff --git a/packages/api/.npmignore b/packages/api/.npmignore index 478163840f..67d0c55714 100644 --- a/packages/api/.npmignore +++ b/packages/api/.npmignore @@ -1,9 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc src* test -.nyc_output -*.tgz -*.html +tsconfig.json diff --git a/packages/api/CHANGELOG.md b/packages/api/CHANGELOG.md index 1444cf4943..2178f99fa2 100644 --- a/packages/api/CHANGELOG.md +++ b/packages/api/CHANGELOG.md @@ -3,6 +3,35 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [5.0.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/api@4.2.4...@thi.ng/api@5.0.0) (2019-01-21) + + +### Bug Fixes + +* **api:** update assert(), re-export mixin() ([9f91cfa](https://github.com/thi-ng/umbrella/commit/9f91cfa)) + + +### Build System + +* **api:** update package build scripts / outputs ([f913d7b](https://github.com/thi-ng/umbrella/commit/f913d7b)) + + +### Features + +* **api:** add assert() ([d381ace](https://github.com/thi-ng/umbrella/commit/d381ace)) + + +### BREAKING CHANGES + +* **api:** rename mixins to avoid name clashes, update decorators + +- append `Mixin` suffix to all mixins (i.e. `INotify` => `INotifyMixin`) +- update re-exports of mixins & decorators (no more nested child namespace) + + + + + ## [4.2.4](https://github.com/thi-ng/umbrella/compare/@thi.ng/api@4.2.3...@thi.ng/api@4.2.4) (2018-12-15) **Note:** Version bump only for package @thi.ng/api diff --git a/packages/api/package.json b/packages/api/package.json index aa2c8f97a0..e2710f0403 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/api", - "version": "4.2.4", + "version": "5.0.0", "description": "Common, generic types & interfaces for thi.ng projects", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,23 +14,25 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc decorators mixins", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module api errors", + "test": "rimraf build && tsc -p test/tsconfig.json && nyc mocha build/test/*.js", + "clean": "rimraf *.js *.d.ts .nyc_output build coverage doc lib decorators mixins", "cover": "yarn test && nyc report --reporter=lcov", "doc": "node_modules/.bin/typedoc --mode modules --out doc src", - "pub": "yarn build && yarn publish --access public", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/errors": "^0.1.12" + "@thi.ng/errors": "^1.0.0" }, "keywords": [ "compare", @@ -42,5 +46,13 @@ ], "publishConfig": { "access": "public" - } + }, + "browserslist": [ + "since 2018-07" + ], + "browser": { + "process": false, + "setTimeout": false + }, + "sideEffects": false } diff --git a/packages/api/src/api.ts b/packages/api/src/api.ts index c698bff645..cbb01063a4 100644 --- a/packages/api/src/api.ts +++ b/packages/api/src/api.ts @@ -19,7 +19,17 @@ export type Comparator = (a: T, b: T) => number; /** * A single arg function from A => B. */ -export type Fn = (x: A) => B; +export type Fn = (a: A) => B; + +/** + * A 2-arg function from A,B => C. + */ +export type Fn2 = (a: A, b: B) => C; + +/** + * A 3-arg function from A,B,C => D. + */ +export type Fn3 = (a: A, b: B, c: C) => D; /** * A vararg arg function to type T. diff --git a/packages/api/src/assert.ts b/packages/api/src/assert.ts new file mode 100644 index 0000000000..43143364f2 --- /dev/null +++ b/packages/api/src/assert.ts @@ -0,0 +1,17 @@ +/** + * Takes a `test` result or predicate function without args and throws + * error with given `msg` if test failed (i.e. is falsy). The function + * is only enabled if `NODE_ENV != "production"` or if + * `UMBRELLA_ASSERTS = 1`. + */ +export const assert = ( + typeof process === "undefined" || + process.env.NODE_ENV !== "production" || + process.env.UMBRELLA_ASSERTS === "1" +) ? + (test: boolean | (() => boolean), msg = "assertion failed") => { + if ((typeof test === "function" && !test()) || !test) { + throw new Error(msg); + } + } : + () => { }; diff --git a/packages/api/src/decorators/configurable.ts b/packages/api/src/decorators/configurable.ts index d8e9510539..afe5f3b6e9 100644 --- a/packages/api/src/decorators/configurable.ts +++ b/packages/api/src/decorators/configurable.ts @@ -4,8 +4,8 @@ * * @param state */ -export function configurable(state: boolean): MethodDecorator { - return function (_: any, __: string | symbol, descriptor: PropertyDescriptor) { - descriptor.configurable = state; - }; -} +export const configurable = + (state: boolean): MethodDecorator => + function (_: any, __: string | symbol, descriptor: PropertyDescriptor) { + descriptor.configurable = state; + }; diff --git a/packages/api/src/decorators/deprecated.ts b/packages/api/src/decorators/deprecated.ts index e3a918bb37..e8dcc40d03 100644 --- a/packages/api/src/decorators/deprecated.ts +++ b/packages/api/src/decorators/deprecated.ts @@ -8,8 +8,8 @@ import { illegalArgs } from "@thi.ng/errors"; * * @param msg deprecation message */ -export function deprecated(msg?: string, log = console.log): MethodDecorator { - return function (target: any, prop: string | symbol, descriptor: PropertyDescriptor) { +export const deprecated = (msg?: string, log = console.log): MethodDecorator => + function (target: any, prop: string | symbol, descriptor: PropertyDescriptor) { const signature = `${target.constructor.name}#${prop.toString()}`; const fn = descriptor.value; if (typeof fn !== "function") { @@ -21,4 +21,3 @@ export function deprecated(msg?: string, log = console.log): MethodDecorator { }; return descriptor; }; -} diff --git a/packages/api/src/decorators/index.ts b/packages/api/src/decorators/index.ts deleted file mode 100644 index 2788d027e7..0000000000 --- a/packages/api/src/decorators/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from "./configurable"; -export * from "./deprecated"; -export * from "./nomixin"; -export * from "./sealed"; diff --git a/packages/api/src/decorators/nomixin.ts b/packages/api/src/decorators/nomixin.ts index 8df3a24b35..1e180c5ab4 100644 --- a/packages/api/src/decorators/nomixin.ts +++ b/packages/api/src/decorators/nomixin.ts @@ -5,6 +5,7 @@ * partial implementations of mixed-in behaviors in target class and * avoid them being overidden by mixed-in behaviour. */ -export function nomixin(_: any, __: string, descriptor: PropertyDescriptor) { - descriptor.configurable = false; -} +export const nomixin = + (_: any, __: string, descriptor: PropertyDescriptor) => { + descriptor.configurable = false; + }; diff --git a/packages/api/src/decorators/sealed.ts b/packages/api/src/decorators/sealed.ts index 39fc0b1085..240602bcfe 100644 --- a/packages/api/src/decorators/sealed.ts +++ b/packages/api/src/decorators/sealed.ts @@ -3,7 +3,8 @@ * * @param constructor */ -export function sealed(constructor: Function) { - Object.seal(constructor); - Object.seal(constructor.prototype); -} +export const sealed = + (constructor: Function) => { + Object.seal(constructor); + Object.seal(constructor.prototype); + }; diff --git a/packages/api/src/index.ts b/packages/api/src/index.ts index 4da35daf6f..a88afb5ccf 100644 --- a/packages/api/src/index.ts +++ b/packages/api/src/index.ts @@ -1,8 +1,14 @@ -import * as decorators from "./decorators"; -import * as mixins from "./mixins"; -export { - decorators, - mixins, -} - export * from "./api"; + +export * from "./assert"; +export * from "./mixin"; + +export * from "./decorators/configurable"; +export * from "./decorators/deprecated"; +export * from "./decorators/nomixin"; +export * from "./decorators/sealed"; + +export * from "./mixins/ienable"; +export * from "./mixins/inotify"; +export * from "./mixins/iterable"; +export * from "./mixins/iwatch"; diff --git a/packages/api/src/mixin.ts b/packages/api/src/mixin.ts index c060776535..55e75cfae4 100644 --- a/packages/api/src/mixin.ts +++ b/packages/api/src/mixin.ts @@ -10,35 +10,36 @@ * @param sharedBehaviour * @returns decorator function */ -export function mixin(behaviour: any, sharedBehaviour = {}) { - const instanceKeys = Reflect.ownKeys(behaviour); - const sharedKeys = Reflect.ownKeys(sharedBehaviour); - const typeTag = Symbol("isa"); +export const mixin = + (behaviour: any, sharedBehaviour = {}) => { + const instanceKeys = Reflect.ownKeys(behaviour); + const sharedKeys = Reflect.ownKeys(sharedBehaviour); + const typeTag = Symbol("isa"); - function _mixin(clazz) { - for (let key of instanceKeys) { - const existing = Object.getOwnPropertyDescriptor(clazz.prototype, key); - if (!existing || existing.configurable) { - Object.defineProperty(clazz.prototype, key, { - value: behaviour[key], - writable: true, - }); - } else { - console.log(`not patching: ${clazz.name}.${key.toString()}`); + function _mixin(clazz) { + for (let key of instanceKeys) { + const existing = Object.getOwnPropertyDescriptor(clazz.prototype, key); + if (!existing || existing.configurable) { + Object.defineProperty(clazz.prototype, key, { + value: behaviour[key], + writable: true, + }); + } else { + console.log(`not patching: ${clazz.name}.${key.toString()}`); + } } + Object.defineProperty(clazz.prototype, typeTag, { value: true }); + return clazz; } - Object.defineProperty(clazz.prototype, typeTag, { value: true }); - return clazz; - } - for (let key of sharedKeys) { - Object.defineProperty(_mixin, key, { - value: sharedBehaviour[key], - enumerable: sharedBehaviour.propertyIsEnumerable(key), - }); - } + for (let key of sharedKeys) { + Object.defineProperty(_mixin, key, { + value: sharedBehaviour[key], + enumerable: sharedBehaviour.propertyIsEnumerable(key), + }); + } - Object.defineProperty(_mixin, Symbol.hasInstance, { value: (x) => !!x[typeTag] }); + Object.defineProperty(_mixin, Symbol.hasInstance, { value: (x) => !!x[typeTag] }); - return _mixin; -} + return _mixin; + } diff --git a/packages/api/src/mixins/ienable.ts b/packages/api/src/mixins/ienable.ts index 838b45a1f7..a4e1f01504 100644 --- a/packages/api/src/mixins/ienable.ts +++ b/packages/api/src/mixins/ienable.ts @@ -1,4 +1,9 @@ -import * as api from "../api"; +import { + Event, + EVENT_DISABLE, + EVENT_ENABLE, + IEnable +} from "../api"; import { mixin } from "../mixin"; /** @@ -7,7 +12,7 @@ import { mixin } from "../mixin"; * interface, `enable()` and `disable()` will automatically emit the * respective events. */ -export const IEnable = mixin(>{ +export const IEnableMixin = mixin(>{ _enabled: true, @@ -18,14 +23,14 @@ export const IEnable = mixin(>{ enable() { this._enabled = true; if (this.notify) { - this.notify({ id: api.EVENT_ENABLE, target: this }); + this.notify({ id: EVENT_ENABLE, target: this }); } }, disable() { this._enabled = false; if (this.notify) { - this.notify({ id: api.EVENT_DISABLE, target: this }); + this.notify({ id: EVENT_DISABLE, target: this }); } }, diff --git a/packages/api/src/mixins/index.ts b/packages/api/src/mixins/index.ts deleted file mode 100644 index edd9378eb5..0000000000 --- a/packages/api/src/mixins/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from "./ienable"; -export * from "./inotify"; -export * from "./iterable"; -export * from "./iwatch"; diff --git a/packages/api/src/mixins/inotify.ts b/packages/api/src/mixins/inotify.ts index 114ce2bd19..1515b3b68d 100644 --- a/packages/api/src/mixins/inotify.ts +++ b/packages/api/src/mixins/inotify.ts @@ -1,27 +1,31 @@ -import * as api from "../api"; +import { + Event, + EVENT_ALL, + INotify, + Listener +} from "../api"; import { mixin } from "../mixin"; -export function inotify_dispatch(listeners: any[][], e: api.Event) { - if (!listeners) return; - const n = listeners.length; - let i = 0, l; - for (i = 0; i < n; i++) { - l = listeners[i]; - l[0].call(l[1], e); - if (e.canceled) { - return; +export const inotify_dispatch = + (listeners: any[][], e: Event) => { + if (!listeners) return; + for (let i = 0, n = listeners.length, l; i < n; i++) { + l = listeners[i]; + l[0].call(l[1], e); + if (e.canceled) { + return; + } } - } -} + }; /** * Mixin class decorator, injects INotify default implementation, incl. * a lazily instantiated `_listeners` property object, storing * registered listeners. */ -export const INotify = mixin({ +export const INotifyMixin = mixin({ - addListener(id: PropertyKey, fn: api.Listener, scope?: any) { + addListener(id: PropertyKey, fn: Listener, scope?: any) { let l = (this._listeners = this._listeners || {})[id]; if (!l) { l = this._listeners[id] = []; @@ -33,7 +37,7 @@ export const INotify = mixin({ return false; }, - removeListener(id: PropertyKey, fn: api.Listener, scope?: any) { + removeListener(id: PropertyKey, fn: Listener, scope?: any) { if (!this._listeners) return false; const l: any[][] = this._listeners[id]; if (l) { @@ -46,14 +50,14 @@ export const INotify = mixin({ return false; }, - notify(e: api.Event) { + notify(e: Event) { if (!this._listeners) return; e.target === undefined && (e.target = this); inotify_dispatch(this._listeners[e.id], e); - inotify_dispatch(this._listeners[api.EVENT_ALL], e); + inotify_dispatch(this._listeners[EVENT_ALL], e); }, - __listener(listeners: any[][], f: api.Listener, scope: any) { + __listener(listeners: any[][], f: Listener, scope: any) { let i = listeners.length; while (--i >= 0) { const l = listeners[i]; diff --git a/packages/api/src/mixins/iterable.ts b/packages/api/src/mixins/iterable.ts index 1677bce57b..e457619e7d 100644 --- a/packages/api/src/mixins/iterable.ts +++ b/packages/api/src/mixins/iterable.ts @@ -1,7 +1,7 @@ import { mixin } from "../mixin"; -export function iterable(prop: PropertyKey) { - return mixin({ - *[Symbol.iterator]() { yield* (this[prop]); }, - }); -} +export const iterable = + (prop: PropertyKey) => + mixin({ + *[Symbol.iterator]() { yield* (this[prop]); }, + }); diff --git a/packages/api/src/mixins/iwatch.ts b/packages/api/src/mixins/iwatch.ts index 84df30cc41..54d0af5e11 100644 --- a/packages/api/src/mixins/iwatch.ts +++ b/packages/api/src/mixins/iwatch.ts @@ -1,32 +1,33 @@ -import * as api from "../api"; +import { IWatch } from "../api"; import { mixin } from "../mixin"; -export const IWatch = mixin(>{ +export const IWatchMixin = + mixin(>{ - addWatch(id: string, fn: (id: string, oldState: any, newState: any) => void) { - this._watches = this._watches || {}; - if (this._watches[id]) { - return false; - } - this._watches[id] = fn; - return true; - }, - - removeWatch(id: string) { - if (!this._watches) return; - if (this._watches[id]) { - delete this._watches[id]; + addWatch(id: string, fn: (id: string, oldState: any, newState: any) => void) { + this._watches = this._watches || {}; + if (this._watches[id]) { + return false; + } + this._watches[id] = fn; return true; - } - return false; - }, + }, + + removeWatch(id: string) { + if (!this._watches) return; + if (this._watches[id]) { + delete this._watches[id]; + return true; + } + return false; + }, - notifyWatches(oldState: any, newState: any) { - if (!this._watches) return; - const w = this._watches; - for (let id in w) { - w[id](id, oldState, newState); + notifyWatches(oldState: any, newState: any) { + if (!this._watches) return; + const w = this._watches; + for (let id in w) { + w[id](id, oldState, newState); + } } - } -}); + }); diff --git a/packages/api/test/index.ts b/packages/api/test/index.ts new file mode 100644 index 0000000000..6a03f273cd --- /dev/null +++ b/packages/api/test/index.ts @@ -0,0 +1 @@ +export * from "./mixins"; diff --git a/packages/api/test/mixins.ts b/packages/api/test/mixins.ts index 1c4ee4ece0..70e4798de2 100644 --- a/packages/api/test/mixins.ts +++ b/packages/api/test/mixins.ts @@ -1,13 +1,13 @@ import * as assert from "assert"; import { Event, INotify, EVENT_ALL } from "../src/api"; -import * as mixins from "../src/mixins"; +import { INotifyMixin } from "../src/mixins/inotify"; describe("mixins", () => { it("INotify", () => { - @mixins.INotify + @INotifyMixin class Foo implements INotify { addListener(_: string, __: (e: Event) => void, ___?: any): boolean { throw new Error(); diff --git a/packages/api/test/tsconfig.json b/packages/api/test/tsconfig.json index 13d45669e5..2c9c12a650 100644 --- a/packages/api/test/tsconfig.json +++ b/packages/api/test/tsconfig.json @@ -1,7 +1,8 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", diff --git a/packages/api/tsconfig.json b/packages/api/tsconfig.json index f6c291a0a0..bcf03f18b4 100644 --- a/packages/api/tsconfig.json +++ b/packages/api/tsconfig.json @@ -1,7 +1,9 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" diff --git a/packages/associative/.npmignore b/packages/associative/.npmignore index d703bda97a..67d0c55714 100644 --- a/packages/associative/.npmignore +++ b/packages/associative/.npmignore @@ -1,10 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/associative/CHANGELOG.md b/packages/associative/CHANGELOG.md index 5025bb1ccb..d0ce9e38d4 100644 --- a/packages/associative/CHANGELOG.md +++ b/packages/associative/CHANGELOG.md @@ -3,6 +3,28 @@ 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/associative@0.6.23...@thi.ng/associative@1.0.0) (2019-01-21) + + +### Build System + +* update package build scripts & outputs, imports in ~50 packages ([b54b703](https://github.com/thi-ng/umbrella/commit/b54b703)) + + +### BREAKING CHANGES + +* enabled multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols. + + + + + ## [0.6.23](https://github.com/thi-ng/umbrella/compare/@thi.ng/associative@0.6.22...@thi.ng/associative@0.6.23) (2019-01-02) **Note:** Version bump only for package @thi.ng/associative diff --git a/packages/associative/package.json b/packages/associative/package.json index 4239bf72aa..e3583eac37 100644 --- a/packages/associative/package.json +++ b/packages/associative/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/associative", - "version": "0.6.23", + "version": "1.0.0", "description": "Alternative Set & Map data type implementations with customizable equality semantics & supporting operations", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,29 +14,31 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn run clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module associative api checks compare dcons equiv errors transducers", + "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 run build && yarn publish --access public", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/api": "^4.2.4", - "@thi.ng/checks": "^1.5.14", - "@thi.ng/compare": "^0.1.12", - "@thi.ng/dcons": "^1.1.23", - "@thi.ng/equiv": "^0.1.15", - "@thi.ng/errors": "^0.1.12", - "@thi.ng/transducers": "^2.3.2" + "@thi.ng/api": "^5.0.0", + "@thi.ng/checks": "^2.0.0", + "@thi.ng/compare": "^1.0.0", + "@thi.ng/dcons": "^2.0.0", + "@thi.ng/equiv": "^1.0.0", + "@thi.ng/errors": "^1.0.0", + "@thi.ng/transducers": "^3.0.0" }, "keywords": [ "data structures", @@ -53,5 +57,6 @@ ], "publishConfig": { "access": "public" - } + }, + "sideEffects": false } diff --git a/packages/associative/src/api.ts b/packages/associative/src/api.ts index bcb6d9c5cf..3b92d71fcf 100644 --- a/packages/associative/src/api.ts +++ b/packages/associative/src/api.ts @@ -4,7 +4,7 @@ import { IEmpty, IEquiv, Predicate2 -} from "@thi.ng/api/api"; +} from "@thi.ng/api"; export interface IEquivSet extends Set, diff --git a/packages/associative/src/array-set.ts b/packages/associative/src/array-set.ts index f6da3eeddf..3e4098fd53 100644 --- a/packages/associative/src/array-set.ts +++ b/packages/associative/src/array-set.ts @@ -1,4 +1,4 @@ -import { Pair, Predicate2, SEMAPHORE } from "@thi.ng/api/api"; +import { Pair, Predicate2, SEMAPHORE } from "@thi.ng/api"; import { equiv } from "@thi.ng/equiv"; import { EquivSetOpts, IEquivSet } from "./api"; diff --git a/packages/associative/src/common-keys.ts b/packages/associative/src/common-keys.ts index 513736f4d1..ce5b8962dc 100644 --- a/packages/associative/src/common-keys.ts +++ b/packages/associative/src/common-keys.ts @@ -1,4 +1,4 @@ -import { IObjectOf } from "@thi.ng/api/api"; +import { IObjectOf } from "@thi.ng/api"; /** * Like `commonKeysObj()`, but for ES6 Maps. @@ -6,15 +6,16 @@ import { IObjectOf } from "@thi.ng/api/api"; * @param a * @param b */ -export function commonKeysMap(a: Map, b: Map) { - const res: K[] = []; - for (let k of a.keys()) { - if (b.has(k)) { - res.push(k); +export const commonKeysMap = + (a: Map, b: Map) => { + const res: K[] = []; + for (let k of a.keys()) { + if (b.has(k)) { + res.push(k); + } } - } - return res; -} + return res; + }; /** * Returns array of keys present in both args, i.e. the set intersection @@ -28,12 +29,13 @@ export function commonKeysMap(a: Map, b: Map) { * @param a * @param b */ -export function commonKeysObj(a: IObjectOf, b: IObjectOf) { - const res: string[] = []; - for (let k in a) { - if (b.hasOwnProperty(k)) { - res.push(k); +export const commonKeysObj = + (a: IObjectOf, b: IObjectOf) => { + const res: string[] = []; + for (let k in a) { + if (b.hasOwnProperty(k)) { + res.push(k); + } } - } - return res; -} + return res; + }; diff --git a/packages/associative/src/difference.ts b/packages/associative/src/difference.ts index b3af70cb30..af90913daa 100644 --- a/packages/associative/src/difference.ts +++ b/packages/associative/src/difference.ts @@ -1,12 +1,13 @@ import { copy, empty } from "./utils"; -export function difference(a: Set, b: Set): Set { - if (a === b) { - return empty(a, Set); - } - const res = copy(a, Set); - for (let i of b) { - res.delete(i); - } - return res; -} +export const difference = + (a: Set, b: Set): Set => { + if (a === b) { + return empty(a, Set); + } + const res = copy(a, Set); + for (let i of b) { + res.delete(i); + } + return res; + }; diff --git a/packages/associative/src/equiv-map.ts b/packages/associative/src/equiv-map.ts index e66f961a9b..883f7ac8c8 100644 --- a/packages/associative/src/equiv-map.ts +++ b/packages/associative/src/equiv-map.ts @@ -5,9 +5,8 @@ import { IObjectOf, Pair, SEMAPHORE -} from "@thi.ng/api/api"; +} from "@thi.ng/api"; import { equiv } from "@thi.ng/equiv"; - import { EquivMapOpts, IEquivSet } from "./api"; import { ArraySet } from "./array-set"; diff --git a/packages/associative/src/indexed.ts b/packages/associative/src/indexed.ts index f54b920e45..7b91ba8885 100644 --- a/packages/associative/src/indexed.ts +++ b/packages/associative/src/indexed.ts @@ -20,14 +20,15 @@ import { empty } from "./utils"; * @param records objects to index * @param ks keys used for indexing */ -export function indexed(records: Iterable, ks: PropertyKey[]) { - const res = new EquivMap>(); - let x, ik, rv; - for (x of records) { - ik = selectKeysObj(x, ks); - rv = res.get(ik); - !rv && res.set(ik, rv = empty(records, Set)); - rv.add(x); - } - return res; -} +export const indexed = + (records: Iterable, ks: PropertyKey[]) => { + const res = new EquivMap>(); + let x, ik, rv; + for (x of records) { + ik = selectKeysObj(x, ks); + rv = res.get(ik); + !rv && res.set(ik, rv = empty(records, Set)); + rv.add(x); + } + return res; + }; diff --git a/packages/associative/src/intersection.ts b/packages/associative/src/intersection.ts index 31ec753705..d3b2daafa3 100644 --- a/packages/associative/src/intersection.ts +++ b/packages/associative/src/intersection.ts @@ -1,17 +1,18 @@ import { empty } from "./utils"; -export function intersection(a: Set, b: Set): Set { - if (a === b) { - return a; - } - if (b.size < a.size) { - return intersection(b, a); - } - const res = empty(a, Set); - for (let i of b) { - if (a.has(i)) { - res.add(i); +export const intersection = + (a: Set, b: Set): Set => { + if (a === b) { + return a; } - } - return res; -} + if (b.size < a.size) { + return intersection(b, a); + } + const res = empty(a, Set); + for (let i of b) { + if (a.has(i)) { + res.add(i); + } + } + return res; + }; diff --git a/packages/associative/src/invert.ts b/packages/associative/src/invert.ts index 35ca6ca375..88eac4c0dd 100644 --- a/packages/associative/src/invert.ts +++ b/packages/associative/src/invert.ts @@ -1,5 +1,4 @@ -import { IObjectOf } from "@thi.ng/api/api"; - +import { IObjectOf } from "@thi.ng/api"; import { empty } from "./utils"; /** @@ -13,13 +12,14 @@ import { empty } from "./utils"; * * @param src */ -export function invertMap(src: Map) { - const dest: Map = empty(src, Map); - for (let p of src) { - dest.set(p[1], p[0]); - } - return dest; -} +export const invertMap = + (src: Map) => { + const dest: Map = empty(src, Map); + for (let p of src) { + dest.set(p[1], p[0]); + } + return dest; + }; /** * Returns a new object in which the original values are used as keys @@ -32,10 +32,11 @@ export function invertMap(src: Map) { * * @param src */ -export function invertObj(src: IObjectOf) { - const dest: IObjectOf = {}; - for (let k in src) { - dest[src[k]] = k; - } - return dest; -} +export const invertObj = + (src: IObjectOf) => { + const dest: IObjectOf = {}; + for (let k in src) { + dest[src[k]] = k; + } + return dest; + }; diff --git a/packages/associative/src/join.ts b/packages/associative/src/join.ts index 4f81f7ef0b..040c825fb1 100644 --- a/packages/associative/src/join.ts +++ b/packages/associative/src/join.ts @@ -1,5 +1,4 @@ -import { IObjectOf } from "@thi.ng/api/api"; - +import { IObjectOf } from "@thi.ng/api"; import { commonKeysObj } from "./common-keys"; import { indexed } from "./indexed"; import { invertObj } from "./invert"; @@ -34,7 +33,11 @@ import { empty, first, objValues } from "./utils"; * @param xrel * @param yrel */ -export function join(xrel: Set>, yrel: Set>): Set> { +export const join = ( + xrel: Set>, + yrel: Set> +): Set> => { + if (xrel.size && yrel.size) { const ks = commonKeysObj(first(xrel) || {}, first(yrel) || {}); let a: Set, b: Set; @@ -58,7 +61,7 @@ export function join(xrel: Set>, yrel: Set>): Set< return res; } return empty(xrel, Set); -} +}; /** * Similar to `join()`, computes the join between two sets of relations, @@ -88,7 +91,12 @@ export function join(xrel: Set>, yrel: Set>): Set< * @param yrel * @param kmap keys to compute join for */ -export function joinWith(xrel: Set, yrel: Set, kmap: IObjectOf): Set { +export const joinWith = ( + xrel: Set, + yrel: Set, + kmap: IObjectOf +): Set => { + if (xrel.size && yrel.size) { let r: Set, s: Set; let k: IObjectOf; @@ -115,4 +123,4 @@ export function joinWith(xrel: Set, yrel: Set, kmap: IObjectOf { diff --git a/packages/associative/src/merge-apply.ts b/packages/associative/src/merge-apply.ts index 5d52106b13..4f9c77c8be 100644 --- a/packages/associative/src/merge-apply.ts +++ b/packages/associative/src/merge-apply.ts @@ -1,6 +1,5 @@ -import { IObjectOf } from "@thi.ng/api/api"; -import { isFunction } from "@thi.ng/checks/is-function"; - +import { IObjectOf } from "@thi.ng/api"; +import { isFunction } from "@thi.ng/checks"; import { copy } from "./utils"; /** @@ -9,15 +8,16 @@ import { copy } from "./utils"; * @param src * @param xs */ -export function mergeApplyMap(src: Map, xs: Map V)>) { - const res: any = copy(src, Map); - for (let p of xs) { - let [k, v] = p; - isFunction(v) && (v = v(res[k])); - res.set(k, v); - } - return res; -} +export const mergeApplyMap = + (src: Map, xs: Map V)>) => { + const res: any = copy(src, Map); + for (let p of xs) { + let [k, v] = p; + isFunction(v) && (v = v(res[k])); + res.set(k, v); + } + return res; + }; /** * Similar to `mergeObj()`, but only supports 2 args and any function @@ -33,12 +33,13 @@ export function mergeApplyMap(src: Map, xs: Map V) * @param src * @param xs */ -export function mergeApplyObj(src: IObjectOf, xs: IObjectOf V)>) { - const res: any = { ...src }; - for (let k in xs) { - let v = xs[k]; - isFunction(v) && (v = v(res[k])); - res[k] = v; - } - return res; -} +export const mergeApplyObj = + (src: IObjectOf, xs: IObjectOf V)>) => { + const res: any = { ...src }; + for (let k in xs) { + let v = xs[k]; + isFunction(v) && (v = v(res[k])); + res[k] = v; + } + return res; + }; diff --git a/packages/associative/src/merge-deep.ts b/packages/associative/src/merge-deep.ts index b05eef217d..577a8f0e8e 100644 --- a/packages/associative/src/merge-deep.ts +++ b/packages/associative/src/merge-deep.ts @@ -1,10 +1,14 @@ -import { IObjectOf } from "@thi.ng/api/api"; -import { isPlainObject } from "@thi.ng/checks/is-plain-object"; - +import { IObjectOf } from "@thi.ng/api"; +import { isPlainObject } from "@thi.ng/checks"; import { mergeObjWith } from "./merge-with"; -export function mergeDeepObj(dest: IObjectOf, ...xs: IObjectOf[]) { - return mergeObjWith( - (a, b) => isPlainObject(a) && isPlainObject(b) ? mergeDeepObj(a, b) : b, - dest, ...xs); -} +export const mergeDeepObj = + (dest: IObjectOf, ...xs: IObjectOf[]) => + mergeObjWith( + (a, b) => + isPlainObject(a) && isPlainObject(b) ? + mergeDeepObj(a, b) : + b, + dest, + ...xs + ); diff --git a/packages/associative/src/merge-with.ts b/packages/associative/src/merge-with.ts index 364cc28240..2f3adb9fd3 100644 --- a/packages/associative/src/merge-with.ts +++ b/packages/associative/src/merge-with.ts @@ -1,8 +1,12 @@ -import { IObjectOf } from "@thi.ng/api/api"; - +import { IObjectOf } from "@thi.ng/api"; import { copy } from "./utils"; -export function mergeMapWith(f: (a: V, b: V) => V, dest: Map, ...xs: Map[]) { +export const mergeMapWith = ( + f: (a: V, b: V) => V, + dest: Map, + ...xs: Map[] +) => { + const res: Map = copy(dest, Map); for (let x of xs) { for (let [k, v] of x) { @@ -14,9 +18,14 @@ export function mergeMapWith(f: (a: V, b: V) => V, dest: Map, ...xs: } } return res; -} +}; + +export const mergeObjWith = ( + f: (a: T, b: T) => T, + dest: IObjectOf, + ...xs: IObjectOf[] +) => { -export function mergeObjWith(f: (a: T, b: T) => T, dest: IObjectOf, ...xs: IObjectOf[]) { const res: IObjectOf = { ...dest }; for (let x of xs) { for (let k in x) { @@ -29,4 +38,4 @@ export function mergeObjWith(f: (a: T, b: T) => T, dest: IObjectOf, ...xs: } } return res; -} +}; diff --git a/packages/associative/src/merge.ts b/packages/associative/src/merge.ts index 2da2a81a37..3ddea8e7d3 100644 --- a/packages/associative/src/merge.ts +++ b/packages/associative/src/merge.ts @@ -1,4 +1,4 @@ -import { IObjectOf } from "@thi.ng/api/api"; +import { IObjectOf } from "@thi.ng/api"; /** * Merges all given maps in left-to-right order into `dest`. @@ -7,14 +7,15 @@ import { IObjectOf } from "@thi.ng/api/api"; * @param dest * @param xs */ -export function mergeMap(dest: Map, ...xs: Map[]) { - for (let x of xs) { - for (let pair of x) { - dest.set(pair[0], pair[1]); +export const mergeMap = + (dest: Map, ...xs: Map[]) => { + for (let x of xs) { + for (let pair of x) { + dest.set(pair[0], pair[1]); + } } - } - return dest; -} + return dest; + }; /** * Merges all given objects in left-to-right order into `dest`. @@ -23,6 +24,6 @@ export function mergeMap(dest: Map, ...xs: Map[]) { * @param dest * @param xs */ -export function mergeObj(dest: IObjectOf, ...xs: IObjectOf[]): IObjectOf { - return Object.assign(dest, ...xs); -} +export const mergeObj = + (dest: IObjectOf, ...xs: IObjectOf[]): IObjectOf => + Object.assign(dest, ...xs); diff --git a/packages/associative/src/rename-keys.ts b/packages/associative/src/rename-keys.ts index 860186ce1a..5dbf167e55 100644 --- a/packages/associative/src/rename-keys.ts +++ b/packages/associative/src/rename-keys.ts @@ -1,5 +1,4 @@ -import { IObjectOf } from "@thi.ng/api/api"; - +import { IObjectOf } from "@thi.ng/api"; import { empty } from "./utils"; /** @@ -9,13 +8,14 @@ import { empty } from "./utils"; * @param src * @param km */ -export function renameKeysMap(src: Map, km: Map) { - const dest: Map = empty(src, Map); - for (let [k, v] of src) { - dest.set(km.has(k) ? km.get(k) : k, v); - } - return dest; -} +export const renameKeysMap = + (src: Map, km: Map) => { + const dest: Map = empty(src, Map); + for (let [k, v] of src) { + dest.set(km.has(k) ? km.get(k) : k, v); + } + return dest; + }; /** * Renames keys in `src` using mapping provided by key map `km`. Does @@ -30,10 +30,11 @@ export function renameKeysMap(src: Map, km: Map) { * @param src * @param km */ -export function renameKeysObj(src: IObjectOf, km: IObjectOf) { - const dest = {}; - for (let k in src) { - dest[km.hasOwnProperty(k) ? km[k] : k] = src[k]; - } - return dest; -} +export const renameKeysObj = + (src: IObjectOf, km: IObjectOf) => { + const dest = {}; + for (let k in src) { + dest[km.hasOwnProperty(k) ? km[k] : k] = src[k]; + } + return dest; + }; diff --git a/packages/associative/src/select-keys.ts b/packages/associative/src/select-keys.ts index 28c60f18ac..9494862568 100644 --- a/packages/associative/src/select-keys.ts +++ b/packages/associative/src/select-keys.ts @@ -1,5 +1,4 @@ -import { IObjectOf } from "@thi.ng/api/api"; - +import { IObjectOf } from "@thi.ng/api"; import { empty } from "./utils"; /** @@ -9,15 +8,16 @@ import { empty } from "./utils"; * @param src * @param ks selected keys */ -export function selectKeysMap(src: Map, ks: Iterable): any { - const dest = empty(src, Map); - for (let k of ks) { - if (src.has(k)) { - dest.set(k, src.get(k)); +export const selectKeysMap = + (src: Map, ks: Iterable): any => { + const dest = empty(src, Map); + for (let k of ks) { + if (src.has(k)) { + dest.set(k, src.get(k)); + } } - } - return dest; -} + return dest; + }; /** * Returns a new object only containing given keys (and only if they @@ -26,12 +26,13 @@ export function selectKeysMap(src: Map, ks: Iterable): any { * @param src * @param ks */ -export function selectKeysObj(src: IObjectOf, ks: Iterable): any { - const dest: IObjectOf = {}; - for (let k of ks) { - if (src.hasOwnProperty(k)) { - dest[k] = src[k]; +export const selectKeysObj = + (src: IObjectOf, ks: Iterable): any => { + const dest: IObjectOf = {}; + for (let k of ks) { + if (src.hasOwnProperty(k)) { + dest[k] = src[k]; + } } - } - return dest; -} + return dest; + }; diff --git a/packages/associative/src/sorted-map.ts b/packages/associative/src/sorted-map.ts index 49b7763a8c..465d43e8d6 100644 --- a/packages/associative/src/sorted-map.ts +++ b/packages/associative/src/sorted-map.ts @@ -8,15 +8,17 @@ import { Pair, Predicate2, SEMAPHORE -} from "@thi.ng/api/api"; -import { isArray } from "@thi.ng/checks/is-array"; +} from "@thi.ng/api"; +import { isArray } from "@thi.ng/checks"; import { compare } from "@thi.ng/compare"; import { equiv } from "@thi.ng/equiv"; -import { illegalArgs } from "@thi.ng/errors/illegal-arguments"; -import { IReducible, ReductionFn } from "@thi.ng/transducers/api"; -import { isReduced } from "@thi.ng/transducers/reduced"; -import { map } from "@thi.ng/transducers/xform/map"; - +import { illegalArgs } from "@thi.ng/errors"; +import { + IReducible, + isReduced, + map, + ReductionFn +} from "@thi.ng/transducers"; import { SortedMapOpts } from "./api"; // stores private properties for all instances diff --git a/packages/associative/src/sorted-set.ts b/packages/associative/src/sorted-set.ts index 10f2ba080b..657426c76e 100644 --- a/packages/associative/src/sorted-set.ts +++ b/packages/associative/src/sorted-set.ts @@ -1,10 +1,8 @@ -import { ICompare, Pair, } from "@thi.ng/api/api"; import { compare } from "@thi.ng/compare"; -import { IReducible, ReductionFn } from "@thi.ng/transducers/api"; -import { map } from "@thi.ng/transducers/xform/map"; - +import { IReducible, map, ReductionFn } from "@thi.ng/transducers"; import { IEquivSet, SortedSetOpts } from "./api"; import { SortedMap } from "./sorted-map"; +import { ICompare, Pair, } from "@thi.ng/api"; const __private = new WeakMap, SortedMap>(); diff --git a/packages/associative/src/union.ts b/packages/associative/src/union.ts index ce185e89eb..f223644601 100644 --- a/packages/associative/src/union.ts +++ b/packages/associative/src/union.ts @@ -1,15 +1,16 @@ import { copy } from "./utils"; -export function union(a: Set, b: Set): Set { - if (a === b) { - return a; - } - if (b.size > a.size) { - return union(b, a); - } - const res = copy(a, Set); - for (let i of b) { - res.add(i); - } - return res; -} \ No newline at end of file +export const union = + (a: Set, b: Set): Set => { + if (a === b) { + return a; + } + if (b.size > a.size) { + return union(b, a); + } + const res = copy(a, Set); + for (let i of b) { + res.add(i); + } + return res; + }; diff --git a/packages/associative/src/utils.ts b/packages/associative/src/utils.ts index 7082e43c53..51da602328 100644 --- a/packages/associative/src/utils.ts +++ b/packages/associative/src/utils.ts @@ -1,4 +1,4 @@ -import { implementsFunction } from "@thi.ng/checks/implements-function"; +import { implementsFunction } from "@thi.ng/checks"; export const empty = (x, ctor) => implementsFunction(x, "empty") ? x.empty() : new (x[Symbol.species] || ctor)(); diff --git a/packages/associative/test/tsconfig.json b/packages/associative/test/tsconfig.json index bcf29ace54..2c9c12a650 100644 --- a/packages/associative/test/tsconfig.json +++ b/packages/associative/test/tsconfig.json @@ -1,10 +1,11 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", "../src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/associative/tsconfig.json b/packages/associative/tsconfig.json index bd6481a5a6..bcf03f18b4 100644 --- a/packages/associative/tsconfig.json +++ b/packages/associative/tsconfig.json @@ -1,9 +1,11 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/atom/.npmignore b/packages/atom/.npmignore index d703bda97a..67d0c55714 100644 --- a/packages/atom/.npmignore +++ b/packages/atom/.npmignore @@ -1,10 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/atom/CHANGELOG.md b/packages/atom/CHANGELOG.md index 1f538c4f99..39b501ce7e 100644 --- a/packages/atom/CHANGELOG.md +++ b/packages/atom/CHANGELOG.md @@ -3,6 +3,28 @@ 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/atom@1.5.8...@thi.ng/atom@2.0.0) (2019-01-21) + + +### Build System + +* update package build scripts & outputs, imports in ~50 packages ([b54b703](https://github.com/thi-ng/umbrella/commit/b54b703)) + + +### BREAKING CHANGES + +* enabled multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols. + + + + + ## [1.5.8](https://github.com/thi-ng/umbrella/compare/@thi.ng/atom@1.5.7...@thi.ng/atom@1.5.8) (2018-12-15) **Note:** Version bump only for package @thi.ng/atom diff --git a/packages/atom/package.json b/packages/atom/package.json index 8a45e08b01..51444b2515 100644 --- a/packages/atom/package.json +++ b/packages/atom/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/atom", - "version": "1.5.8", - "description": "Mutable wrapper for immutable values", - "main": "./index.js", + "version": "2.0.0", + "description": "Mutable wrappers for nested immutable values w/ optional undo/redo history", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,38 +14,50 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module atom api checks equiv errors paths", + "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": "typedoc --mode modules --out doc src", - "pub": "yarn build && yarn publish --access public", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/api": "^4.2.4", - "@thi.ng/checks": "^1.5.14", - "@thi.ng/equiv": "^0.1.15", - "@thi.ng/errors": "^0.1.12", - "@thi.ng/paths": "^1.6.6" + "@thi.ng/api": "^5.0.0", + "@thi.ng/checks": "^2.0.0", + "@thi.ng/equiv": "^1.0.0", + "@thi.ng/errors": "^1.0.0", + "@thi.ng/paths": "^2.0.0" }, "keywords": [ + "derived views", "cursor", - "datastructure", + "data structure", "ES6", "history", "immutable", + "redo", "typescript", "undo" ], "publishConfig": { "access": "public" - } + }, + "browserslist": [ + "since 2018-07" + ], + "browser": { + "process": false, + "setTimeout": false + }, + "sideEffects": false } diff --git a/packages/atom/src/api.ts b/packages/atom/src/api.ts index 2f64fc85a1..68ed2ca515 100644 --- a/packages/atom/src/api.ts +++ b/packages/atom/src/api.ts @@ -1,4 +1,11 @@ -import * as api from "@thi.ng/api/api"; +import { + IDeref, + IID, + INotify, + IRelease, + IWatch, + Predicate +} from "@thi.ng/api"; import { Path } from "@thi.ng/paths"; export type SwapFn = (curr: T, ...args: any[]) => T; @@ -6,9 +13,9 @@ export type SwapFn = (curr: T, ...args: any[]) => T; export type ViewTransform = (x: any) => T; export interface ReadonlyAtom extends - api.IDeref, - api.IRelease, - api.IWatch, + IDeref, + IRelease, + IWatch, IViewable { } @@ -29,9 +36,9 @@ export interface ISwap { } export interface IView extends - api.IDeref, - api.IID, - api.IRelease { + IDeref, + IID, + IRelease { readonly path: PropertyKey[]; readonly value: T; @@ -47,13 +54,13 @@ export interface IViewable { export interface CursorOpts { parent: IAtom; path: Path | [(s: any) => T, (s: any, v: T) => any]; - validate?: api.Predicate; + validate?: Predicate; id?: string; } export interface IHistory extends IAtom, - api.INotify { + INotify { canUndo(): boolean; canRedo(): boolean; diff --git a/packages/atom/src/atom.ts b/packages/atom/src/atom.ts index 888d2226cc..3aaebf8749 100644 --- a/packages/atom/src/atom.ts +++ b/packages/atom/src/atom.ts @@ -1,8 +1,11 @@ -import { IEquiv, Predicate, Watch } from "@thi.ng/api/api"; -import { IWatch } from "@thi.ng/api/mixins/iwatch"; -import { illegalState } from "@thi.ng/errors/illegal-state"; +import { + IEquiv, + IWatchMixin, + Predicate, + Watch +} from "@thi.ng/api"; +import { illegalState } from "@thi.ng/errors"; import { Path, setIn, updateIn } from "@thi.ng/paths"; - import { IAtom, IView, @@ -11,11 +14,12 @@ import { } from "./api"; import { View } from "./view"; + /** * Mutable wrapper for an (usually) immutable value. Support for * watches. */ -@IWatch +@IWatchMixin export class Atom implements IAtom, IEquiv { @@ -72,19 +76,19 @@ export class Atom implements // mixin stub /* istanbul ignore next */ - addWatch(id: string, fn: Watch) { + addWatch(_: string, __: Watch) { return false; } // mixin stub /* istanbul ignore next */ - removeWatch(id: string) { + removeWatch(_: string) { return false; } // mixin stub /* istanbul ignore next */ - notifyWatches(oldState: T, newState: T) { } + notifyWatches(_: T, __: T) { } addView(path: Path, tx?: ViewTransform, lazy = true): IView { return new View(this, path, tx, lazy); diff --git a/packages/atom/src/cursor.ts b/packages/atom/src/cursor.ts index 04e74535d7..23f249272d 100644 --- a/packages/atom/src/cursor.ts +++ b/packages/atom/src/cursor.ts @@ -1,10 +1,7 @@ -import { IID, IRelease, Watch } from "@thi.ng/api/api"; -import { isArray } from "@thi.ng/checks/is-array"; -import { isFunction } from "@thi.ng/checks/is-function"; -import { illegalArgs } from "@thi.ng/errors/illegal-arguments"; -import { illegalArity } from "@thi.ng/errors/illegal-arity"; +import { IID, IRelease, Watch } from "@thi.ng/api"; +import { isArray, isFunction } from "@thi.ng/checks"; +import { illegalArgs, illegalArity } from "@thi.ng/errors"; import { getter, Path, setter } from "@thi.ng/paths"; - import { CursorOpts, IAtom, @@ -13,9 +10,9 @@ import { ViewTransform } from "./api"; import { Atom } from "./atom"; +import { nextID } from "./idgen"; import { View } from "./view"; - /** * A cursor provides read/write access to a path location within a * nested parent state (Atom or another Cursor). Cursors behave like @@ -46,8 +43,6 @@ export class Cursor implements IID, IRelease { - static NEXT_ID = 0; - readonly id: string; parent: IAtom; @@ -89,7 +84,7 @@ export class Cursor implements illegalArity(args.length); } this.parent = parent; - this.id = id || `cursor-${Cursor.NEXT_ID++}`; + this.id = id || `cursor-${nextID()}`; this.selfUpdate = false; if (!lookup || !update) { illegalArgs(); diff --git a/packages/atom/src/history.ts b/packages/atom/src/history.ts index fe473c38ce..3b806945b3 100644 --- a/packages/atom/src/history.ts +++ b/packages/atom/src/history.ts @@ -1,5 +1,9 @@ -import { Event, Predicate2, Watch } from "@thi.ng/api/api"; -import * as mixin from "@thi.ng/api/mixins/inotify"; +import { + Event, + INotifyMixin, + Predicate2, + Watch +} from "@thi.ng/api"; import { equiv } from "@thi.ng/equiv"; import { getIn, @@ -7,7 +11,6 @@ import { setIn, updateIn } from "@thi.ng/paths"; - import { IAtom, IHistory, @@ -17,6 +20,7 @@ import { } from "./api"; import { View } from "./view"; + /** * Undo/redo history stack wrapper for atoms and cursors. Implements * `IAtom` interface and so can be used directly in place and delegates @@ -26,7 +30,7 @@ import { View } from "./view"; * `INotify` interface to support event listeners for `undo()`, `redo()` * and `record()`. */ -@mixin.INotify +@INotifyMixin export class History implements IHistory { @@ -255,14 +259,14 @@ export class History implements return true; } - addListener(id: string, fn: (e: Event) => void, scope?: any): boolean { + addListener(_: string, __: (e: Event) => void, ___?: any): boolean { return false; } - removeListener(id: string, fn: (e: Event) => void, scope?: any): boolean { + removeListener(_: string, __: (e: Event) => void, ___?: any): boolean { return false; } - notify(event: Event): void { + notify(_: Event): void { } } diff --git a/packages/atom/src/idgen.ts b/packages/atom/src/idgen.ts new file mode 100644 index 0000000000..6a23983489 --- /dev/null +++ b/packages/atom/src/idgen.ts @@ -0,0 +1,3 @@ +let NEXT_ID = 0; + +export const nextID = () => NEXT_ID++; diff --git a/packages/atom/src/view.ts b/packages/atom/src/view.ts index d0ae30f58c..4462d32899 100644 --- a/packages/atom/src/view.ts +++ b/packages/atom/src/view.ts @@ -1,7 +1,7 @@ import { equiv as _equiv } from "@thi.ng/equiv"; import { getter, Path, toPath } from "@thi.ng/paths"; - import { IView, ReadonlyAtom, ViewTransform } from "./api"; +import { nextID } from "./idgen"; /** * This class implements readonly access to a deeply nested value with @@ -47,8 +47,6 @@ import { IView, ReadonlyAtom, ViewTransform } from "./api"; export class View implements IView { - protected static NEXT_ID = 0; - readonly id: string; readonly parent: ReadonlyAtom; @@ -62,7 +60,7 @@ export class View implements constructor(parent: ReadonlyAtom, path: Path, tx?: ViewTransform, lazy = true, equiv = _equiv) { this.parent = parent; - this.id = `view-${View.NEXT_ID++}`; + this.id = `view-${nextID()}`; this.tx = tx || ((x: any) => x); this.path = toPath(path); this.isDirty = true; diff --git a/packages/atom/test/atom.ts b/packages/atom/test/atom.ts index 937b2710f7..c81ff901bb 100644 --- a/packages/atom/test/atom.ts +++ b/packages/atom/test/atom.ts @@ -1,6 +1,6 @@ +import { isNumber } from "@thi.ng/checks"; import * as assert from "assert"; import { Atom } from "../src/index"; -import { isNumber } from "@thi.ng/checks/is-number"; describe("atom", function () { @@ -15,8 +15,8 @@ describe("atom", function () { }); it("can be equiv'd", () => { - assert(a.equiv(a)); - assert(!a.equiv(new Atom(23))); + assert.ok(a.equiv(a)); + assert.ok(!a.equiv(new Atom(23))); }); it("can be reset", () => { @@ -30,10 +30,10 @@ describe("atom", function () { }); it("can add & remove watch", () => { - assert(a.addWatch("foo", () => { }), "can't add watch"); - assert((a)._watches && (a)._watches.foo, "watch missing"); - assert(a.removeWatch("foo"), "can't remove watch"); - assert(!a.removeWatch("foo"), "should fail to remove invalid watch id"); + assert.ok(a.addWatch("foo", () => { }), "can't add watch"); + assert.ok((a)._watches && (a)._watches.foo, "watch missing"); + assert.ok(a.removeWatch("foo"), "can't remove watch"); + assert.ok(!a.removeWatch("foo"), "should fail to remove invalid watch id"); }); it("can be watched", () => { @@ -51,7 +51,7 @@ describe("atom", function () { assert.equal(a.reset(2), 2); assert.equal(a.reset("3"), 2); assert.equal(a.reset(null), 2); - assert.equal(a.swap((x) => "3"), 2); - assert.equal(a.swap((x) => null), 2); + assert.equal(a.swap(() => "3"), 2); + assert.equal(a.swap(() => null), 2); }); }); diff --git a/packages/atom/test/cursor.ts b/packages/atom/test/cursor.ts index 6b59f4e76d..bd168fbada 100644 --- a/packages/atom/test/cursor.ts +++ b/packages/atom/test/cursor.ts @@ -1,8 +1,7 @@ -import * as assert from "assert"; +import { isNumber } from "@thi.ng/checks"; import { getIn } from "@thi.ng/paths"; - +import * as assert from "assert"; import { Atom, Cursor } from "../src/index"; -import { isNumber } from "@thi.ng/checks/is-number"; describe("cursor", function () { @@ -126,17 +125,17 @@ describe("cursor", function () { c = new Cursor(a, "a"); let id = c.id; assert.notEqual((a)._watches[id], null); - assert(c.release()); + assert.ok(c.release()); assert.strictEqual(c.parent, undefined); assert.strictEqual((a)._watches[id], undefined); }); it("can add & remove watch", () => { c = new Cursor(a, "a.b.c"); - assert(c.addWatch("foo", () => { }), "can't add watch"); - assert((c).local._watches && (c).local._watches.foo, "watch missing"); - assert(c.removeWatch("foo"), "can't remove watch"); - assert(!c.removeWatch("foo"), "should fail to remove invalid watch id"); + 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"); }); it("can be watched", () => { diff --git a/packages/atom/test/history.ts b/packages/atom/test/history.ts index 6b0445693e..20a7e49732 100644 --- a/packages/atom/test/history.ts +++ b/packages/atom/test/history.ts @@ -1,5 +1,4 @@ import * as assert from "assert"; - import { Atom } from "../src/atom"; import { Cursor } from "../src/cursor"; import { History } from "../src/history"; diff --git a/packages/atom/test/index.ts b/packages/atom/test/index.ts new file mode 100644 index 0000000000..ff27842a95 --- /dev/null +++ b/packages/atom/test/index.ts @@ -0,0 +1,4 @@ +export * from "./atom"; +export * from "./cursor"; +export * from "./history"; +export * from "./view"; diff --git a/packages/atom/test/tsconfig.json b/packages/atom/test/tsconfig.json index e077d51a4c..2c9c12a650 100644 --- a/packages/atom/test/tsconfig.json +++ b/packages/atom/test/tsconfig.json @@ -2,7 +2,7 @@ "extends": "../../../tsconfig.json", "compilerOptions": { "outDir": "../build", - "noUnusedParameters": false + "module": "commonjs", }, "include": [ "./**/*.ts", diff --git a/packages/atom/test/view.ts b/packages/atom/test/view.ts index 7c29de165c..c755ec7017 100644 --- a/packages/atom/test/view.ts +++ b/packages/atom/test/view.ts @@ -1,7 +1,5 @@ -import * as assert from "assert"; - import { setIn, updateIn } from "@thi.ng/paths"; - +import * as assert from "assert"; import { IView } from "../src/api"; import { Atom } from "../src/atom"; import { Cursor } from "../src/cursor"; @@ -18,20 +16,20 @@ describe("view", () => { it("can be created from atom", () => { s = a.addView("e"); - assert(s instanceof View); + assert.ok(s instanceof View); assert.equal(s.deref(), 4); s = a.addView("e", (x) => x * 10); - assert(s instanceof View); + assert.ok(s instanceof View); assert.equal(s.deref(), 40); }); it("can be created from cursor", () => { let c = new Cursor(a, "b"); s = c.addView("d"); - assert(s instanceof View); + assert.ok(s instanceof View); assert.equal(s.deref(), 3); s = c.addView("c", (x: number) => x * 10); - assert(s instanceof View); + assert.ok(s instanceof View); assert.equal(s.deref(), 20); }); @@ -55,33 +53,33 @@ describe("view", () => { it("reflects updates", () => { s = new View(a, "b.c", (x) => x * 10); - assert(s.changed(), "not dirty"); + assert.ok(s.changed(), "not dirty"); assert.equal(s.deref(), 20); - assert(!s.changed(), "changed"); + assert.ok(!s.changed(), "changed"); a.swap((state) => updateIn(state, "b.c", (x) => x + 1)); - assert(s.changed(), "not dirty #2"); + assert.ok(s.changed(), "not dirty #2"); assert.equal(s.deref(), 30); - assert(!s.changed(), "changed #2"); + assert.ok(!s.changed(), "changed #2"); }); it("reflects updates (initially undefined)", () => { s = new View(a, "f"); - assert(s.changed(), "not dirty"); + assert.ok(s.changed(), "not dirty"); assert.equal(s.deref(), undefined); - assert(!s.changed(), "changed"); + assert.ok(!s.changed(), "changed"); a.swap((state) => setIn(state, "f", 100)); - assert(s.changed(), "not dirty #2"); + assert.ok(s.changed(), "not dirty #2"); assert.equal(s.deref(), 100); }); it("can be released", () => { s = new View(a, "b.c") assert.equal(s.deref(), 2); - assert(!s.changed(), "changed"); - assert(s.release()); - assert(s.changed(), "not dirty"); + assert.ok(!s.changed(), "changed"); + assert.ok(s.release()); + assert.ok(s.changed(), "not dirty"); assert.equal(s.deref(), undefined); - assert(!s.changed(), "changed #2"); + assert.ok(!s.changed(), "changed #2"); assert.equal(s.deref(), undefined); }); diff --git a/packages/atom/tsconfig.json b/packages/atom/tsconfig.json index 7e59425303..bcf03f18b4 100644 --- a/packages/atom/tsconfig.json +++ b/packages/atom/tsconfig.json @@ -2,7 +2,8 @@ "extends": "../../tsconfig.json", "compilerOptions": { "outDir": ".", - "noUnusedParameters": false + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" diff --git a/packages/bench/.npmignore b/packages/bench/.npmignore index d703bda97a..67d0c55714 100644 --- a/packages/bench/.npmignore +++ b/packages/bench/.npmignore @@ -1,10 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/bench/CHANGELOG.md b/packages/bench/CHANGELOG.md index d2954fe76d..f71a907dde 100644 --- a/packages/bench/CHANGELOG.md +++ b/packages/bench/CHANGELOG.md @@ -3,6 +3,28 @@ 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/bench@0.3.1...@thi.ng/bench@1.0.0) (2019-01-21) + + +### Build System + +* update package build scripts & outputs, imports in ~50 packages ([b54b703](https://github.com/thi-ng/umbrella/commit/b54b703)) + + +### BREAKING CHANGES + +* enabled multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols. + + + + + ## [0.3.1](https://github.com/thi-ng/umbrella/compare/@thi.ng/bench@0.3.0...@thi.ng/bench@0.3.1) (2018-12-15) **Note:** Version bump only for package @thi.ng/bench diff --git a/packages/bench/package.json b/packages/bench/package.json index a5d1656f79..67bdd0fbf8 100644 --- a/packages/bench/package.json +++ b/packages/bench/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/bench", - "version": "0.3.1", + "version": "1.0.0", "description": "Basic benchmarking helpers", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,28 +14,41 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn run clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module bench", + "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 run build && yarn publish --access public", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "keywords": [ "benchmark", "ES6", + "execution", + "function", + "measure", "timing", "typescript" ], "publishConfig": { "access": "public" - } + }, + "browserslist": [ + "since 2018-07" + ], + "browser": { + "process": false, + "setTimeout": false + }, + "sideEffects": false } diff --git a/packages/bench/test/tsconfig.json b/packages/bench/test/tsconfig.json index bcf29ace54..2c9c12a650 100644 --- a/packages/bench/test/tsconfig.json +++ b/packages/bench/test/tsconfig.json @@ -1,10 +1,11 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", "../src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/bench/tsconfig.json b/packages/bench/tsconfig.json index bd6481a5a6..bcf03f18b4 100644 --- a/packages/bench/tsconfig.json +++ b/packages/bench/tsconfig.json @@ -1,9 +1,11 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/binary/.npmignore b/packages/binary/.npmignore index d703bda97a..67d0c55714 100644 --- a/packages/binary/.npmignore +++ b/packages/binary/.npmignore @@ -1,10 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/binary/CHANGELOG.md b/packages/binary/CHANGELOG.md index 004f0956bd..69bac0ea7c 100644 --- a/packages/binary/CHANGELOG.md +++ b/packages/binary/CHANGELOG.md @@ -3,6 +3,28 @@ 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/binary@0.1.2...@thi.ng/binary@1.0.0) (2019-01-21) + + +### Build System + +* update package build scripts & outputs, imports in ~50 packages ([b54b703](https://github.com/thi-ng/umbrella/commit/b54b703)) + + +### BREAKING CHANGES + +* enabled multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols. + + + + + ## [0.1.2](https://github.com/thi-ng/umbrella/compare/@thi.ng/binary@0.1.1...@thi.ng/binary@0.1.2) (2018-12-15) **Note:** Version bump only for package @thi.ng/binary diff --git a/packages/binary/package.json b/packages/binary/package.json index 36f80224af..66e07c70d2 100644 --- a/packages/binary/package.json +++ b/packages/binary/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/binary", - "version": "0.1.2", + "version": "1.0.0", "description": "Assorted binary / bitwise operations, conversions, utilities.", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,19 +14,21 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn run clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module binary", + "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 run build && yarn publish --access public", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "keywords": [ @@ -42,5 +46,6 @@ ], "publishConfig": { "access": "public" - } + }, + "sideEffects": false } diff --git a/packages/binary/test/tsconfig.json b/packages/binary/test/tsconfig.json index bcf29ace54..2c9c12a650 100644 --- a/packages/binary/test/tsconfig.json +++ b/packages/binary/test/tsconfig.json @@ -1,10 +1,11 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", "../src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/binary/tsconfig.json b/packages/binary/tsconfig.json index bd6481a5a6..bcf03f18b4 100644 --- a/packages/binary/tsconfig.json +++ b/packages/binary/tsconfig.json @@ -1,9 +1,11 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/bitstream/.npmignore b/packages/bitstream/.npmignore index d703bda97a..67d0c55714 100644 --- a/packages/bitstream/.npmignore +++ b/packages/bitstream/.npmignore @@ -1,10 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/bitstream/CHANGELOG.md b/packages/bitstream/CHANGELOG.md index 0faacd0794..e7ba152bc0 100644 --- a/packages/bitstream/CHANGELOG.md +++ b/packages/bitstream/CHANGELOG.md @@ -3,6 +3,28 @@ 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/bitstream@0.4.21...@thi.ng/bitstream@1.0.0) (2019-01-21) + + +### Build System + +* update package build scripts & outputs, imports in ~50 packages ([b54b703](https://github.com/thi-ng/umbrella/commit/b54b703)) + + +### BREAKING CHANGES + +* enabled multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols. + + + + + ## [0.4.21](https://github.com/thi-ng/umbrella/compare/@thi.ng/bitstream@0.4.20...@thi.ng/bitstream@0.4.21) (2018-12-15) **Note:** Version bump only for package @thi.ng/bitstream diff --git a/packages/bitstream/README.md b/packages/bitstream/README.md index cbe4f7ed85..e9bed5d37a 100644 --- a/packages/bitstream/README.md +++ b/packages/bitstream/README.md @@ -25,7 +25,7 @@ yarn add @thi.ng/bitstream ## API ```ts -import * as bits from "@thi.ng/bitstream"; +import { BitInputStream, BitOutputStream } from "@thi.ng/bitstream"; ``` ### BitOutputStream @@ -47,7 +47,7 @@ but JS can only represent integers (w/o loss of precision) up to technically the max. supported word width is 64 bits. ```ts -out = new bits.BitOutputStream(); +out = new BitOutputStream(); // write 3-bit number (only the lowest 3 bits are used, here 0x05) out.write(0xf5, 3); // write 7-bit number @@ -109,7 +109,7 @@ out.reader().seek(10).readWords(4, 16).map(x=>x.toString(16)); src = new Uint8Array([0xf1,0xe2,0xd3,0xc4,0xb5,0xa6,0x97,0x88]); // create stream from bit 36 -input = new bits.BitInputStream(src, 36); +input = new BitInputStream(src, 36); input.read(12).toString(16); // 5a6 input.read(4) diff --git a/packages/bitstream/package.json b/packages/bitstream/package.json index 79c73888fe..42522c8ead 100644 --- a/packages/bitstream/package.json +++ b/packages/bitstream/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/bitstream", - "version": "0.4.21", + "version": "1.0.0", "description": "ES6 iterator based read/write bit streams & support for variable word widths", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,22 +14,24 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module bitstream errors", + "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", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "dependencies": { - "@thi.ng/errors": "^0.1.12" + "@thi.ng/errors": "^1.0.0" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "keywords": [ @@ -41,5 +45,6 @@ ], "publishConfig": { "access": "public" - } + }, + "sideEffects": false } diff --git a/packages/bitstream/test/index.ts b/packages/bitstream/test/index.ts index 34f9102512..da632c1d66 100644 --- a/packages/bitstream/test/index.ts +++ b/packages/bitstream/test/index.ts @@ -1,5 +1,5 @@ -import * as bits from "../src/index"; 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]); diff --git a/packages/bitstream/test/tsconfig.json b/packages/bitstream/test/tsconfig.json index 13d45669e5..2c9c12a650 100644 --- a/packages/bitstream/test/tsconfig.json +++ b/packages/bitstream/test/tsconfig.json @@ -1,7 +1,8 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", diff --git a/packages/bitstream/tsconfig.json b/packages/bitstream/tsconfig.json index f6c291a0a0..bcf03f18b4 100644 --- a/packages/bitstream/tsconfig.json +++ b/packages/bitstream/tsconfig.json @@ -1,7 +1,9 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" diff --git a/packages/cache/.npmignore b/packages/cache/.npmignore index d703bda97a..67d0c55714 100644 --- a/packages/cache/.npmignore +++ b/packages/cache/.npmignore @@ -1,10 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/cache/CHANGELOG.md b/packages/cache/CHANGELOG.md index f91c90b5fc..17076ddc29 100644 --- a/packages/cache/CHANGELOG.md +++ b/packages/cache/CHANGELOG.md @@ -3,6 +3,33 @@ 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/cache@0.2.40...@thi.ng/cache@1.0.0) (2019-01-21) + + +### Bug Fixes + +* **cache:** TLRU: expected behavior on getSet() ([c3762e9](https://github.com/thi-ng/umbrella/commit/c3762e9)) + + +### Build System + +* update package build scripts & outputs, imports in ~50 packages ([b54b703](https://github.com/thi-ng/umbrella/commit/b54b703)) + + +### BREAKING CHANGES + +* enabled multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols. + + + + + ## [0.2.40](https://github.com/thi-ng/umbrella/compare/@thi.ng/cache@0.2.39...@thi.ng/cache@0.2.40) (2019-01-02) **Note:** Version bump only for package @thi.ng/cache diff --git a/packages/cache/package.json b/packages/cache/package.json index 6ce4a1db97..42f2c2bee5 100644 --- a/packages/cache/package.json +++ b/packages/cache/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/cache", - "version": "0.2.40", + "version": "1.0.0", "description": "In-memory cache implementations with ES6 Map-like API and different eviction strategies", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,25 +14,27 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn run clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module cache api dcons transducers", + "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 run build && yarn publish --access public", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/api": "^4.2.4", - "@thi.ng/dcons": "^1.1.23", - "@thi.ng/transducers": "^2.3.2" + "@thi.ng/api": "^5.0.0", + "@thi.ng/dcons": "^2.0.0", + "@thi.ng/transducers": "^3.0.0" }, "keywords": [ "cache", @@ -45,5 +49,6 @@ ], "publishConfig": { "access": "public" - } + }, + "sideEffects": false } diff --git a/packages/cache/src/api.ts b/packages/cache/src/api.ts index 442a225f3f..537a8b95c9 100644 --- a/packages/cache/src/api.ts +++ b/packages/cache/src/api.ts @@ -3,7 +3,7 @@ import { IEmpty, ILength, IRelease -} from "@thi.ng/api/api"; +} from "@thi.ng/api"; export interface ICache extends Iterable]>>, diff --git a/packages/cache/src/lru.ts b/packages/cache/src/lru.ts index 8c9d18026a..82fa66cd75 100644 --- a/packages/cache/src/lru.ts +++ b/packages/cache/src/lru.ts @@ -1,9 +1,9 @@ import { ConsCell, DCons } from "@thi.ng/dcons"; -import { map } from "@thi.ng/transducers/xform/map"; - +import { map } from "@thi.ng/transducers"; import { CacheEntry, CacheOpts, ICache } from "./api"; -export class LRUCache implements ICache { +export class LRUCache implements + ICache { protected map: Map>>; protected items: DCons>; diff --git a/packages/cache/src/mru.ts b/packages/cache/src/mru.ts index ae8e3632b0..8131202fd6 100644 --- a/packages/cache/src/mru.ts +++ b/packages/cache/src/mru.ts @@ -1,5 +1,4 @@ import { ConsCell } from "@thi.ng/dcons"; - import { CacheEntry, CacheOpts } from "./api"; import { LRUCache } from "./lru"; diff --git a/packages/cache/src/tlru.ts b/packages/cache/src/tlru.ts index 4d0e2f71b9..e5562106b8 100644 --- a/packages/cache/src/tlru.ts +++ b/packages/cache/src/tlru.ts @@ -1,5 +1,4 @@ import { ConsCell, DCons } from "@thi.ng/dcons"; - import { CacheEntry, CacheOpts } from "./api"; import { LRUCache } from "./lru"; @@ -78,6 +77,14 @@ export class TLRUCache extends LRUCache { return value; } + getSet(key: K, retrieve: () => Promise, ttl = this.opts.ttl): Promise { + const e = this.get(key); + if (e) { + return Promise.resolve(e); + } + return retrieve().then((v) => this.set(key, v, ttl)); + } + prune() { const now = Date.now(); let cell = this.items.head; diff --git a/packages/cache/test/tlru.ts b/packages/cache/test/tlru.ts index f3734f8f49..708439da18 100644 --- a/packages/cache/test/tlru.ts +++ b/packages/cache/test/tlru.ts @@ -50,4 +50,18 @@ describe("TLRU", () => { }, 20); }); + it("getSet ttl", (done) => { + setTimeout(() => { + c.getSet("a", () => Promise.resolve(10)).then(v => { + assert.equal(v, 10); + assert(!c.has("b")); + assert(!c.has("c")); + assert.deepEqual([...evicts], [["a", 1], ["b", 2], ["c", 3]]); + assert.deepEqual([...c.keys()], ["a"]); + assert.deepEqual([...c.values()], [10]); + done(); + }).catch(done) + }, 20) + }); + }); diff --git a/packages/cache/test/tsconfig.json b/packages/cache/test/tsconfig.json index bcf29ace54..2c9c12a650 100644 --- a/packages/cache/test/tsconfig.json +++ b/packages/cache/test/tsconfig.json @@ -1,10 +1,11 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", "../src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/cache/tsconfig.json b/packages/cache/tsconfig.json index bd6481a5a6..bcf03f18b4 100644 --- a/packages/cache/tsconfig.json +++ b/packages/cache/tsconfig.json @@ -1,9 +1,11 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/checks/.npmignore b/packages/checks/.npmignore index d703bda97a..67d0c55714 100644 --- a/packages/checks/.npmignore +++ b/packages/checks/.npmignore @@ -1,10 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/checks/CHANGELOG.md b/packages/checks/CHANGELOG.md index c837a26f87..708cc1d107 100644 --- a/packages/checks/CHANGELOG.md +++ b/packages/checks/CHANGELOG.md @@ -3,6 +3,28 @@ 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/checks@1.5.14...@thi.ng/checks@2.0.0) (2019-01-21) + + +### Build System + +* update package build scripts & outputs, imports in ~50 packages ([b54b703](https://github.com/thi-ng/umbrella/commit/b54b703)) + + +### BREAKING CHANGES + +* enabled multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols. + + + + + ## [1.5.14](https://github.com/thi-ng/umbrella/compare/@thi.ng/checks@1.5.13...@thi.ng/checks@1.5.14) (2018-12-15) **Note:** Version bump only for package @thi.ng/checks diff --git a/packages/checks/README.md b/packages/checks/README.md index 14ec1889da..32b333be31 100644 --- a/packages/checks/README.md +++ b/packages/checks/README.md @@ -29,7 +29,7 @@ None import * as checks from "@thi.ng/checks"; // individual import -import { isFunction } from "@thi.ng/checks/is-function"; +import { isFunction } from "@thi.ng/checks"; ``` ## Authors diff --git a/packages/checks/package.json b/packages/checks/package.json index a9d6dd6968..c6cc85562d 100644 --- a/packages/checks/package.json +++ b/packages/checks/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/checks", - "version": "1.5.14", + "version": "2.0.0", "description": "Single-function sub-modules for type, feature & value checks", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,19 +14,21 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module checks", + "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", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "keywords": [ @@ -39,5 +43,13 @@ ], "publishConfig": { "access": "public" - } + }, + "browserslist": [ + "since 2018-07" + ], + "browser": { + "process": false, + "setTimeout": false + }, + "sideEffects": false } diff --git a/packages/checks/src/exists-not-null.ts b/packages/checks/src/exists-not-null.ts index dfc00f83f9..b11de3a1e6 100644 --- a/packages/checks/src/exists-not-null.ts +++ b/packages/checks/src/exists-not-null.ts @@ -1,3 +1,2 @@ -export function existsAndNotNull(x: any) { - return x != null; -} +export const existsAndNotNull = + (x: any) => x != null; diff --git a/packages/checks/src/exists.ts b/packages/checks/src/exists.ts index a0c963d50c..7c548aaada 100644 --- a/packages/checks/src/exists.ts +++ b/packages/checks/src/exists.ts @@ -1,3 +1,2 @@ -export function exists(x: any) { - return x !== undefined; -} +export const exists = + (x: any) => x !== undefined; diff --git a/packages/checks/src/has-crypto.ts b/packages/checks/src/has-crypto.ts index 96609bc53d..11e01ce282 100644 --- a/packages/checks/src/has-crypto.ts +++ b/packages/checks/src/has-crypto.ts @@ -1,3 +1,2 @@ -export function hasCrypto() { - return typeof window !== "undefined" && window["crypto"] !== undefined; -} +export const hasCrypto = + () => typeof window !== "undefined" && window["crypto"] !== undefined; diff --git a/packages/checks/src/has-max-length.ts b/packages/checks/src/has-max-length.ts index 5cd5e31072..3421673854 100644 --- a/packages/checks/src/has-max-length.ts +++ b/packages/checks/src/has-max-length.ts @@ -1,3 +1,3 @@ -export function hasMaxLength(len: number, x: ArrayLike) { - return x != null && x.length <= len; -} +export const hasMaxLength = + (len: number, x: ArrayLike) => + x != null && x.length <= len; diff --git a/packages/checks/src/has-min-length.ts b/packages/checks/src/has-min-length.ts index 905a553295..ae970513bc 100644 --- a/packages/checks/src/has-min-length.ts +++ b/packages/checks/src/has-min-length.ts @@ -1,3 +1,3 @@ -export function hasMinLength(len: number, x: ArrayLike) { - return x != null && x.length >= len; -} +export const hasMinLength = + (len: number, x: ArrayLike) => + x != null && x.length >= len; diff --git a/packages/checks/src/has-performance.ts b/packages/checks/src/has-performance.ts index 7d8b8042c5..75216308be 100644 --- a/packages/checks/src/has-performance.ts +++ b/packages/checks/src/has-performance.ts @@ -1,5 +1,4 @@ import { isFunction } from "./is-function"; -export function hasPerformance() { - return typeof performance !== 'undefined' && isFunction(performance.now); -} +export const hasPerformance = + () => typeof performance !== 'undefined' && isFunction(performance.now); diff --git a/packages/checks/src/has-wasm.ts b/packages/checks/src/has-wasm.ts index 4e2837f890..63d6d157d7 100644 --- a/packages/checks/src/has-wasm.ts +++ b/packages/checks/src/has-wasm.ts @@ -1,4 +1,4 @@ -export function hasWASM() { - return (typeof window !== "undefined" && typeof window["WebAssembly"] !== "undefined") || +export const hasWASM = + () => + (typeof window !== "undefined" && typeof window["WebAssembly"] !== "undefined") || (typeof global !== "undefined" && typeof global["WebAssembly"] !== "undefined"); -} diff --git a/packages/checks/src/has-webgl.ts b/packages/checks/src/has-webgl.ts index 043f42bb0f..f98ed9a797 100644 --- a/packages/checks/src/has-webgl.ts +++ b/packages/checks/src/has-webgl.ts @@ -1,8 +1,9 @@ -export function hasWebGL() { - try { - document.createElement("canvas").getContext("webgl"); - return true; - } catch (e) { - return false; - } -} +export const hasWebGL = + () => { + try { + document.createElement("canvas").getContext("webgl"); + return true; + } catch (e) { + return false; + } + }; diff --git a/packages/checks/src/has-websocket.ts b/packages/checks/src/has-websocket.ts index 1949f25ed3..83399832c5 100644 --- a/packages/checks/src/has-websocket.ts +++ b/packages/checks/src/has-websocket.ts @@ -1,3 +1,2 @@ -export function hasWebSocket() { - return typeof WebSocket !== "undefined"; -} +export const hasWebSocket = + () => typeof WebSocket !== "undefined"; diff --git a/packages/checks/src/implements-function.ts b/packages/checks/src/implements-function.ts index ab0e0e6368..ffc6bac186 100644 --- a/packages/checks/src/implements-function.ts +++ b/packages/checks/src/implements-function.ts @@ -1,3 +1,3 @@ -export function implementsFunction(x: any, fn: string | symbol) { - return x != null && typeof x[fn] === "function"; -} +export const implementsFunction = + (x: any, fn: string | symbol) => + x != null && typeof x[fn] === "function"; diff --git a/packages/checks/src/is-arraylike.ts b/packages/checks/src/is-arraylike.ts index 7824d8f9dc..137f6b5abb 100644 --- a/packages/checks/src/is-arraylike.ts +++ b/packages/checks/src/is-arraylike.ts @@ -1,3 +1,3 @@ -export function isArrayLike(x: any): x is ArrayLike { - return (x != null && typeof x !== "function" && x.length !== undefined); -} +export const isArrayLike = + (x: any): x is ArrayLike => + (x != null && typeof x !== "function" && x.length !== undefined); diff --git a/packages/checks/src/is-blob.ts b/packages/checks/src/is-blob.ts index b8902c8a0a..dfc81a6475 100644 --- a/packages/checks/src/is-blob.ts +++ b/packages/checks/src/is-blob.ts @@ -1,3 +1,2 @@ -export function isBlob(x: any): x is Blob { - return x instanceof Blob; -} +export const isBlob = + (x: any): x is Blob => x instanceof Blob; diff --git a/packages/checks/src/is-boolean.ts b/packages/checks/src/is-boolean.ts index a3657e6a63..501a6368af 100644 --- a/packages/checks/src/is-boolean.ts +++ b/packages/checks/src/is-boolean.ts @@ -1,3 +1,2 @@ -export function isBoolean(x: any): x is boolean { - return typeof x === "boolean"; -} +export const isBoolean = + (x: any): x is boolean => typeof x === "boolean"; diff --git a/packages/checks/src/is-chrome.ts b/packages/checks/src/is-chrome.ts index 9734e4c0f1..391d54deb8 100644 --- a/packages/checks/src/is-chrome.ts +++ b/packages/checks/src/is-chrome.ts @@ -1,3 +1,2 @@ -export function isChrome() { - return typeof window !== "undefined" && !!window["chrome"]; -} +export const isChrome = + () => typeof window !== "undefined" && !!window["chrome"]; diff --git a/packages/checks/src/is-date.ts b/packages/checks/src/is-date.ts index 36e8a3bfee..a1ac5e524f 100644 --- a/packages/checks/src/is-date.ts +++ b/packages/checks/src/is-date.ts @@ -1,3 +1,2 @@ -export function isDate(x: any): x is Date { - return x instanceof Date; -} +export const isDate = + (x: any): x is Date => x instanceof Date; diff --git a/packages/checks/src/is-even.ts b/packages/checks/src/is-even.ts index 464503c36e..444de8bfcf 100644 --- a/packages/checks/src/is-even.ts +++ b/packages/checks/src/is-even.ts @@ -1,3 +1,2 @@ -export function isEven(x: number) { - return (x % 2) === 0; -} +export const isEven = + (x: number) => (x % 2) === 0; diff --git a/packages/checks/src/is-false.ts b/packages/checks/src/is-false.ts index 8dadd935c6..d022dc6a08 100644 --- a/packages/checks/src/is-false.ts +++ b/packages/checks/src/is-false.ts @@ -1,3 +1,2 @@ -export function isFalse(x: any): x is false { - return x === false; -} +export const isFalse = + (x: any): x is false => x === false; diff --git a/packages/checks/src/is-file.ts b/packages/checks/src/is-file.ts index 450a1771a4..0829b72054 100644 --- a/packages/checks/src/is-file.ts +++ b/packages/checks/src/is-file.ts @@ -1,3 +1,2 @@ -export function isFile(x: any): x is File { - return x instanceof File; -} +export const isFile = + (x: any): x is File => x instanceof File; diff --git a/packages/checks/src/is-firefox.ts b/packages/checks/src/is-firefox.ts index a903aded26..ac3be232de 100644 --- a/packages/checks/src/is-firefox.ts +++ b/packages/checks/src/is-firefox.ts @@ -1,3 +1,2 @@ -export function isFirefox() { - return typeof window !== "undefined" && !!window["InstallTrigger"]; -} +export const isFirefox = + () => typeof window !== "undefined" && !!window["InstallTrigger"]; diff --git a/packages/checks/src/is-function.ts b/packages/checks/src/is-function.ts index d474efcb26..b4f74a0716 100644 --- a/packages/checks/src/is-function.ts +++ b/packages/checks/src/is-function.ts @@ -1,3 +1,2 @@ -export function isFunction(x: any): x is Function { - return typeof x === "function"; -} +export const isFunction = + (x: any): x is Function => typeof x === "function"; diff --git a/packages/checks/src/is-ie.ts b/packages/checks/src/is-ie.ts index 0fc94de9d1..635d0dd6aa 100644 --- a/packages/checks/src/is-ie.ts +++ b/packages/checks/src/is-ie.ts @@ -1,5 +1,5 @@ -export function isIE() { - return typeof document !== "undefined" && +export const isIE = + () => + typeof document !== "undefined" && (typeof document["documentMode"] !== "undefined" || navigator.userAgent.indexOf("MSIE") > 0); -} diff --git a/packages/checks/src/is-in-range.ts b/packages/checks/src/is-in-range.ts index 80b89b5930..d1e5eca52f 100644 --- a/packages/checks/src/is-in-range.ts +++ b/packages/checks/src/is-in-range.ts @@ -1,3 +1,3 @@ -export function isInRange(min: number, max: number, x: number) { - return x >= min && x <= max; -} \ No newline at end of file +export const isInRange = + (min: number, max: number, x: number) => + x >= min && x <= max; diff --git a/packages/checks/src/is-int32.ts b/packages/checks/src/is-int32.ts index 60f520c9e3..9855cae552 100644 --- a/packages/checks/src/is-int32.ts +++ b/packages/checks/src/is-int32.ts @@ -1,3 +1,3 @@ -export function isInt32(x: any): x is number { - return typeof x === "number" && (x | 0) === x; -} +export const isInt32 = + (x: any): x is number => + typeof x === "number" && (x | 0) === x; diff --git a/packages/checks/src/is-iterable.ts b/packages/checks/src/is-iterable.ts index f15ab3f953..7bcda95b93 100644 --- a/packages/checks/src/is-iterable.ts +++ b/packages/checks/src/is-iterable.ts @@ -1,3 +1,3 @@ -export function isIterable(x: any): x is Iterable { - return x != null && typeof x[Symbol.iterator] === "function"; -} +export const isIterable = + (x: any): x is Iterable => + x != null && typeof x[Symbol.iterator] === "function"; diff --git a/packages/checks/src/is-map.ts b/packages/checks/src/is-map.ts index d895c5decc..eaa247dc65 100644 --- a/packages/checks/src/is-map.ts +++ b/packages/checks/src/is-map.ts @@ -1,3 +1,2 @@ -export function isMap(x: any): x is Map { - return x instanceof Map; -} +export const isMap = + (x: any): x is Map => x instanceof Map; diff --git a/packages/checks/src/is-mobile.ts b/packages/checks/src/is-mobile.ts index 96a7aef994..63eea28859 100644 --- a/packages/checks/src/is-mobile.ts +++ b/packages/checks/src/is-mobile.ts @@ -1,5 +1,5 @@ -export function isMobile() { - return typeof navigator !== "undefined" && +export const isMobile = + () => + typeof navigator !== "undefined" && /mobile|tablet|ip(ad|hone|od)|android|silk/i.test(navigator.userAgent) && !/crios/i.test(navigator.userAgent); -} diff --git a/packages/checks/src/is-nan.ts b/packages/checks/src/is-nan.ts index bf8ee8bb89..9a70106397 100644 --- a/packages/checks/src/is-nan.ts +++ b/packages/checks/src/is-nan.ts @@ -1,3 +1,2 @@ -export function isNaN(x: any) { - return x !== x; -} +export const isNaN = + (x: any) => x !== x; diff --git a/packages/checks/src/is-negative.ts b/packages/checks/src/is-negative.ts index d577df9f01..b31142b248 100644 --- a/packages/checks/src/is-negative.ts +++ b/packages/checks/src/is-negative.ts @@ -1,3 +1,3 @@ -export function isNegative(x: any): x is number { - return typeof x === "number" && x < 0; -} +export const isNegative = + (x: any): x is number => + typeof x === "number" && x < 0; diff --git a/packages/checks/src/is-node.ts b/packages/checks/src/is-node.ts index d99a8b015c..239f69c3fc 100644 --- a/packages/checks/src/is-node.ts +++ b/packages/checks/src/is-node.ts @@ -1,12 +1,13 @@ declare var process: any; -export function isNode() { - if (typeof process === "object") { - if (typeof process.versions === "object") { - if (typeof process.versions.node !== "undefined") { - return true; +export const isNode = + () => { + if (typeof process === "object") { + if (typeof process.versions === "object") { + if (typeof process.versions.node !== "undefined") { + return true; + } } } - } - return false; -} + return false; + }; diff --git a/packages/checks/src/is-not-string-iterable.ts b/packages/checks/src/is-not-string-iterable.ts index cef0d8f2df..d5c7886a5d 100644 --- a/packages/checks/src/is-not-string-iterable.ts +++ b/packages/checks/src/is-not-string-iterable.ts @@ -1,5 +1,5 @@ -export function isNotStringAndIterable(x: any): x is Iterable { - return x != null && +export const isNotStringAndIterable = + (x: any): x is Iterable => + x != null && typeof x !== "string" && typeof x[Symbol.iterator] === "function"; -} diff --git a/packages/checks/src/is-null.ts b/packages/checks/src/is-null.ts index 9e8acdc7bb..f09baa8188 100644 --- a/packages/checks/src/is-null.ts +++ b/packages/checks/src/is-null.ts @@ -1,3 +1,2 @@ -export function isNull(x: any): x is null { - return x === null; -} +export const isNull = + (x: any): x is null => x === null; diff --git a/packages/checks/src/is-number.ts b/packages/checks/src/is-number.ts index 9a56ac8cb2..9554093c76 100644 --- a/packages/checks/src/is-number.ts +++ b/packages/checks/src/is-number.ts @@ -1,3 +1,2 @@ -export function isNumber(x: any): x is number { - return typeof x === "number"; -} +export const isNumber = + (x: any): x is number => typeof x === "number"; diff --git a/packages/checks/src/is-object.ts b/packages/checks/src/is-object.ts index dca362c824..27d361aa2a 100644 --- a/packages/checks/src/is-object.ts +++ b/packages/checks/src/is-object.ts @@ -1,3 +1,3 @@ -export function isObject(x: any): x is Object { - return x !== null && typeof x === "object"; -} +export const isObject = + (x: any): x is Object => + x !== null && typeof x === "object"; diff --git a/packages/checks/src/is-odd.ts b/packages/checks/src/is-odd.ts index 46eb851ada..e394871b63 100644 --- a/packages/checks/src/is-odd.ts +++ b/packages/checks/src/is-odd.ts @@ -1,3 +1,2 @@ -export function isOdd(x: number) { - return (x % 2) !== 0; -} +export const isOdd = + (x: number) => (x % 2) !== 0; diff --git a/packages/checks/src/is-plain-object.ts b/packages/checks/src/is-plain-object.ts index ce694b554c..c37f935e46 100644 --- a/packages/checks/src/is-plain-object.ts +++ b/packages/checks/src/is-plain-object.ts @@ -6,8 +6,9 @@ const OBJP = Object.getPrototypeOf({}); * * @param x */ -export function isPlainObject(x: any): x is object { - let proto; - return Object.prototype.toString.call(x) === "[object Object]" && - (proto = Object.getPrototypeOf(x), proto === null || proto === OBJP); -} +export const isPlainObject = + (x: any): x is object => { + let proto; + return Object.prototype.toString.call(x) === "[object Object]" && + (proto = Object.getPrototypeOf(x), proto === null || proto === OBJP); + }; diff --git a/packages/checks/src/is-positive.ts b/packages/checks/src/is-positive.ts index d993b81cdc..85ed4d9502 100644 --- a/packages/checks/src/is-positive.ts +++ b/packages/checks/src/is-positive.ts @@ -1,3 +1,2 @@ -export function isPosititve(x: any): x is number { - return typeof x === "number" && x > 0; -} +export const isPosititve = + (x: any): x is number => typeof x === "number" && x > 0; diff --git a/packages/checks/src/is-promise.ts b/packages/checks/src/is-promise.ts index d950e5f9e7..8be66e5903 100644 --- a/packages/checks/src/is-promise.ts +++ b/packages/checks/src/is-promise.ts @@ -1,3 +1,2 @@ -export function isPromise(x: any): x is Promise { - return x instanceof Promise; -} +export const isPromise = + (x: any): x is Promise => x instanceof Promise; diff --git a/packages/checks/src/is-promiselike.ts b/packages/checks/src/is-promiselike.ts index a02355a677..3a2b4a66e4 100644 --- a/packages/checks/src/is-promiselike.ts +++ b/packages/checks/src/is-promiselike.ts @@ -1,6 +1,6 @@ import { implementsFunction } from "./implements-function"; -export function isPromiseLike(x: any): x is Promise { - return x instanceof Promise || +export const isPromiseLike = + (x: any): x is Promise => + x instanceof Promise || (implementsFunction(x, "then") && implementsFunction(x, "catch")); -} diff --git a/packages/checks/src/is-regexp.ts b/packages/checks/src/is-regexp.ts index 9c265f7875..715be99056 100644 --- a/packages/checks/src/is-regexp.ts +++ b/packages/checks/src/is-regexp.ts @@ -1,3 +1,2 @@ -export function isRegExp(x: any): x is RegExp { - return x instanceof RegExp; -} +export const isRegExp = + (x: any): x is RegExp => x instanceof RegExp; diff --git a/packages/checks/src/is-safari.ts b/packages/checks/src/is-safari.ts index 19d3011218..5976f70158 100644 --- a/packages/checks/src/is-safari.ts +++ b/packages/checks/src/is-safari.ts @@ -1,5 +1,7 @@ import { isChrome } from "./is-chrome"; -export function isSafari() { - return typeof navigator !== "undefined" && /Safari/.test(navigator.userAgent) && !isChrome(); -} +export const isSafari = + () => + typeof navigator !== "undefined" && + /Safari/.test(navigator.userAgent) && + !isChrome(); diff --git a/packages/checks/src/is-set.ts b/packages/checks/src/is-set.ts index a7e5d3e65b..468813acb9 100644 --- a/packages/checks/src/is-set.ts +++ b/packages/checks/src/is-set.ts @@ -1,3 +1,2 @@ -export function isSet(x: any): x is Set { - return x instanceof Set; -} +export const isSet = + (x: any): x is Set => x instanceof Set; diff --git a/packages/checks/src/is-string.ts b/packages/checks/src/is-string.ts index 4f4937b2df..1bddcaebc7 100644 --- a/packages/checks/src/is-string.ts +++ b/packages/checks/src/is-string.ts @@ -1,3 +1,2 @@ -export function isString(x: any): x is string { - return typeof x === "string"; -} +export const isString = + (x: any): x is string => typeof x === "string"; diff --git a/packages/checks/src/is-symbol.ts b/packages/checks/src/is-symbol.ts index fe417d1823..92fe97c84d 100644 --- a/packages/checks/src/is-symbol.ts +++ b/packages/checks/src/is-symbol.ts @@ -1,3 +1,2 @@ -export function isSymbol(x: any): x is Symbol { - return typeof x === "symbol"; -} +export const isSymbol = + (x: any): x is Symbol => typeof x === "symbol"; diff --git a/packages/checks/src/is-transferable.ts b/packages/checks/src/is-transferable.ts index af2f3cab43..d5e12fb210 100644 --- a/packages/checks/src/is-transferable.ts +++ b/packages/checks/src/is-transferable.ts @@ -1,7 +1,7 @@ declare var SharedArrayBuffer: any; -export function isTransferable(x: any) { - return x instanceof ArrayBuffer || +export const isTransferable = + (x: any) => + x instanceof ArrayBuffer || (typeof SharedArrayBuffer !== "undefined" && x instanceof SharedArrayBuffer) || (typeof MessagePort !== "undefined" && x instanceof MessagePort); -} diff --git a/packages/checks/src/is-true.ts b/packages/checks/src/is-true.ts index d51b37136b..f88d7fda45 100644 --- a/packages/checks/src/is-true.ts +++ b/packages/checks/src/is-true.ts @@ -1,3 +1,2 @@ -export function isTrue(x: any): x is boolean { - return x === true; -} +export const isTrue = + (x: any): x is boolean => x === true; diff --git a/packages/checks/src/is-typedarray.ts b/packages/checks/src/is-typedarray.ts index 1fd85470bc..1eeaa6b26e 100644 --- a/packages/checks/src/is-typedarray.ts +++ b/packages/checks/src/is-typedarray.ts @@ -1,11 +1,11 @@ -export function isTypedArray(x: any): x is ArrayLike { - return x && (x.constructor === Float32Array || - x.constructor === Uint32Array || - x.constructor === Uint8Array || - x.constructor === Uint8ClampedArray || - x.constructor === Int8Array || - x.constructor === Uint16Array || - x.constructor === Int16Array || - x.constructor === Int32Array || - x.constructor === Float64Array); -} +export const isTypedArray = + (x: any): x is ArrayLike => + x && (x.constructor === Float32Array || + x.constructor === Uint32Array || + x.constructor === Uint8Array || + x.constructor === Uint8ClampedArray || + x.constructor === Int8Array || + x.constructor === Uint16Array || + x.constructor === Int16Array || + x.constructor === Int32Array || + x.constructor === Float64Array); diff --git a/packages/checks/src/is-uint32.ts b/packages/checks/src/is-uint32.ts index 66dc4c1d1e..7a6bdb1b41 100644 --- a/packages/checks/src/is-uint32.ts +++ b/packages/checks/src/is-uint32.ts @@ -1,3 +1,3 @@ -export function isUint32(x: any): x is number { - return typeof x === "number" && (x >>> 0) === x; -} +export const isUint32 = + (x: any): x is number => + typeof x === "number" && (x >>> 0) === x; diff --git a/packages/checks/src/is-undefined.ts b/packages/checks/src/is-undefined.ts index acc51707eb..ee36222a69 100644 --- a/packages/checks/src/is-undefined.ts +++ b/packages/checks/src/is-undefined.ts @@ -1,3 +1,2 @@ -export function isUndefined(x: any): x is undefined { - return x === undefined; -} +export const isUndefined = + (x: any): x is undefined => x === undefined; diff --git a/packages/checks/src/is-uuid.ts b/packages/checks/src/is-uuid.ts index 53c250a6c4..fe7b2c60b4 100644 --- a/packages/checks/src/is-uuid.ts +++ b/packages/checks/src/is-uuid.ts @@ -1,3 +1,4 @@ -export function isUUID(x: string) { - return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(x); -} +const RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i; + +export const isUUID = + (x: string) => RE.test(x); diff --git a/packages/checks/src/is-uuid4.ts b/packages/checks/src/is-uuid4.ts index bcf27d480d..6045145718 100644 --- a/packages/checks/src/is-uuid4.ts +++ b/packages/checks/src/is-uuid4.ts @@ -1,3 +1,4 @@ -export function isUUIDv4(x: string) { - return /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(x); -} +const RE = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i; + +export const isUUIDv4 = + (x: string) => RE.test(x); diff --git a/packages/checks/src/is-zero.ts b/packages/checks/src/is-zero.ts index 79ceb96f8c..6a67a7ba98 100644 --- a/packages/checks/src/is-zero.ts +++ b/packages/checks/src/is-zero.ts @@ -1,3 +1,2 @@ -export function isZero(x: any): x is 0 { - return x === 0; -} +export const isZero = + (x: any): x is 0 => x === 0; diff --git a/packages/checks/test/index.ts b/packages/checks/test/index.ts index a735b68aa5..c70a02cc61 100644 --- a/packages/checks/test/index.ts +++ b/packages/checks/test/index.ts @@ -15,132 +15,132 @@ import { isTypedArray } from "../src/is-typedarray"; describe("checks", function () { it("existsAndNotNull", () => { - assert(existsAndNotNull([]), "empty array"); - assert(existsAndNotNull(new Uint8Array(1)), "typedarray"); - assert(existsAndNotNull({}), "obj"); - assert(existsAndNotNull("[]"), "string"); - assert(existsAndNotNull(0), "zero"); - assert(!existsAndNotNull({}["foobar"]), "prop"); - assert(!existsAndNotNull(null), "null"); - assert(!existsAndNotNull(undefined), "null"); + assert.ok(existsAndNotNull([]), "empty array"); + assert.ok(existsAndNotNull(new Uint8Array(1)), "typedarray"); + assert.ok(existsAndNotNull({}), "obj"); + assert.ok(existsAndNotNull("[]"), "string"); + assert.ok(existsAndNotNull(0), "zero"); + assert.ok(!existsAndNotNull({}["foobar"]), "prop"); + assert.ok(!existsAndNotNull(null), "null"); + assert.ok(!existsAndNotNull(undefined), "null"); }); it("isArray", () => { - assert(isArray([]), "empty array"); - assert(!isArray(new Uint8Array(1)), "typedarray"); - assert(!isArray({}), "obj"); - assert(!isArray("[]"), "string"); - assert(!isArray(0), "zero"); - assert(!isArray(null), "null"); - assert(!isArray(undefined), "null"); + assert.ok(isArray([]), "empty array"); + assert.ok(!isArray(new Uint8Array(1)), "typedarray"); + assert.ok(!isArray({}), "obj"); + assert.ok(!isArray("[]"), "string"); + assert.ok(!isArray(0), "zero"); + assert.ok(!isArray(null), "null"); + assert.ok(!isArray(undefined), "null"); }); it("isTypedArray", () => { - assert(isTypedArray(new Uint8Array(1)), "u8"); - assert(isTypedArray(new Uint8ClampedArray(1)), "u8c"); - assert(isTypedArray(new Uint16Array(1)), "u16"); - assert(isTypedArray(new Uint32Array(1)), "u32"); - assert(isTypedArray(new Int8Array(1)), "i8"); - assert(isTypedArray(new Int16Array(1)), "i16"); - assert(isTypedArray(new Int32Array(1)), "i32"); - assert(isTypedArray(new Float32Array(1)), "f32"); - assert(isTypedArray(new Float64Array(1)), "f64"); - assert(!isTypedArray([]), "empty array"); - assert(!isTypedArray({}), "obj"); - assert(!isTypedArray("[]"), "string"); - assert(!isTypedArray(0), "zero"); - assert(!isTypedArray(null), "null"); - assert(!isTypedArray(undefined), "null"); + assert.ok(isTypedArray(new Uint8Array(1)), "u8"); + assert.ok(isTypedArray(new Uint8ClampedArray(1)), "u8c"); + assert.ok(isTypedArray(new Uint16Array(1)), "u16"); + assert.ok(isTypedArray(new Uint32Array(1)), "u32"); + assert.ok(isTypedArray(new Int8Array(1)), "i8"); + assert.ok(isTypedArray(new Int16Array(1)), "i16"); + assert.ok(isTypedArray(new Int32Array(1)), "i32"); + assert.ok(isTypedArray(new Float32Array(1)), "f32"); + assert.ok(isTypedArray(new Float64Array(1)), "f64"); + assert.ok(!isTypedArray([]), "empty array"); + assert.ok(!isTypedArray({}), "obj"); + assert.ok(!isTypedArray("[]"), "string"); + assert.ok(!isTypedArray(0), "zero"); + assert.ok(!isTypedArray(null), "null"); + assert.ok(!isTypedArray(undefined), "null"); }); it("isArrayLike", () => { - assert(isArrayLike([]), "empty array"); - assert(isArrayLike(new Uint8Array(1)), "typedarray"); - assert(isArrayLike({ length: 1 }), "obj.length"); - assert(isArrayLike("[]"), "string"); - assert(!isArrayLike({}), "empty obj"); - assert(!isArrayLike(0), "zero"); - assert(!isArrayLike(null), "null"); - assert(!isArrayLike(undefined), "null"); - assert(!isArrayLike((x, y) => x + y), "null"); + assert.ok(isArrayLike([]), "empty array"); + assert.ok(isArrayLike(new Uint8Array(1)), "typedarray"); + assert.ok(isArrayLike({ length: 1 }), "obj.length"); + assert.ok(isArrayLike("[]"), "string"); + assert.ok(!isArrayLike({}), "empty obj"); + assert.ok(!isArrayLike(0), "zero"); + assert.ok(!isArrayLike(null), "null"); + assert.ok(!isArrayLike(undefined), "null"); + assert.ok(!isArrayLike((x, y) => x + y), "null"); }); it("isObject", () => { function Foo() { }; - assert(isObject([]), "empty array"); - assert(isObject(new Uint8Array(1)), "typedarray"); - assert(isObject({}), "obj"); - assert(isObject(new Foo()), "class"); - assert(!isObject(Foo), "fn"); - assert(!isObject("[]"), "string"); - assert(!isObject(0), "zero"); - assert(!isObject(null), "null"); - assert(!isObject(undefined), "null"); + assert.ok(isObject([]), "empty array"); + assert.ok(isObject(new Uint8Array(1)), "typedarray"); + assert.ok(isObject({}), "obj"); + assert.ok(isObject(new Foo()), "class"); + assert.ok(!isObject(Foo), "fn"); + assert.ok(!isObject("[]"), "string"); + assert.ok(!isObject(0), "zero"); + assert.ok(!isObject(null), "null"); + assert.ok(!isObject(undefined), "null"); }); it("isPlainObject", () => { function Foo() { }; - assert(isPlainObject({}), "obj"); - assert(isPlainObject(new Object()), "obj ctor"); - assert(!isPlainObject(Foo), "fn"); - assert(!isPlainObject(new Foo()), "class"); - assert(!isPlainObject([]), "empty array"); - assert(!isPlainObject(new Uint8Array(1)), "typedarray"); - assert(!isPlainObject("[]"), "string"); - assert(!isPlainObject(0), "zero"); - assert(!isPlainObject(null), "null"); - assert(!isPlainObject(undefined), "null"); + assert.ok(isPlainObject({}), "obj"); + assert.ok(isPlainObject(new Object()), "obj ctor"); + assert.ok(!isPlainObject(Foo), "fn"); + assert.ok(!isPlainObject(new Foo()), "class"); + assert.ok(!isPlainObject([]), "empty array"); + assert.ok(!isPlainObject(new Uint8Array(1)), "typedarray"); + assert.ok(!isPlainObject("[]"), "string"); + assert.ok(!isPlainObject(0), "zero"); + assert.ok(!isPlainObject(null), "null"); + assert.ok(!isPlainObject(undefined), "null"); }); it("isString", () => { - assert(isString(""), "empty string"); - assert(isString("a"), "empty string"); - assert(!isString({}), "obj"); - assert(!isString([]), "array"); - assert(!isString(new Uint8Array(1)), "typedarray"); - assert(!isString(0), "zero"); - assert(!isString(null), "null"); - assert(!isString(undefined), "null"); + assert.ok(isString(""), "empty string"); + assert.ok(isString("a"), "empty string"); + assert.ok(!isString({}), "obj"); + assert.ok(!isString([]), "array"); + assert.ok(!isString(new Uint8Array(1)), "typedarray"); + assert.ok(!isString(0), "zero"); + assert.ok(!isString(null), "null"); + assert.ok(!isString(undefined), "null"); }); it("isFunction", () => { - assert(isFunction((_) => null), "fn"); - assert(isFunction(Uint8Array), "ctor"); - assert(isFunction("a".toString), "toString"); - assert(!isFunction("a"), "empty string"); - assert(!isFunction({}), "obj"); - assert(!isFunction([]), "array"); - assert(!isFunction(new Uint8Array(1)), "typedarray"); - assert(!isFunction(0), "zero"); - assert(!isFunction(null), "null"); - assert(!isFunction(undefined), "undefined"); + assert.ok(isFunction((_) => null), "fn"); + assert.ok(isFunction(Uint8Array), "ctor"); + assert.ok(isFunction("a".toString), "toString"); + assert.ok(!isFunction("a"), "empty string"); + assert.ok(!isFunction({}), "obj"); + assert.ok(!isFunction([]), "array"); + assert.ok(!isFunction(new Uint8Array(1)), "typedarray"); + assert.ok(!isFunction(0), "zero"); + assert.ok(!isFunction(null), "null"); + assert.ok(!isFunction(undefined), "undefined"); }); it("implementsFunction", () => { - assert(implementsFunction({ a: () => true }, "a"), "obj"); - assert(implementsFunction([], Symbol.iterator), "arr iterator"); - assert(implementsFunction("", Symbol.iterator), "string iterator"); - assert(!implementsFunction(0, Symbol.iterator), "zero"); - assert(!implementsFunction(null, Symbol.iterator), "null"); - assert(!implementsFunction(undefined, Symbol.iterator), "undefined"); + assert.ok(implementsFunction({ a: () => true }, "a"), "obj"); + assert.ok(implementsFunction([], Symbol.iterator), "arr iterator"); + assert.ok(implementsFunction("", Symbol.iterator), "string iterator"); + assert.ok(!implementsFunction(0, Symbol.iterator), "zero"); + assert.ok(!implementsFunction(null, Symbol.iterator), "null"); + assert.ok(!implementsFunction(undefined, Symbol.iterator), "undefined"); }); it("isSymbol", () => { - assert(isSymbol(Symbol.iterator), "iterator"); - assert(!isSymbol("iterator"), "string"); - assert(!isFunction(0), "zero"); - assert(!isFunction(null), "null"); - assert(!isFunction(undefined), "undefined"); + assert.ok(isSymbol(Symbol.iterator), "iterator"); + assert.ok(!isSymbol("iterator"), "string"); + assert.ok(!isFunction(0), "zero"); + assert.ok(!isFunction(null), "null"); + assert.ok(!isFunction(undefined), "undefined"); }); it("isTransferable", () => { - assert(isTransferable(new ArrayBuffer(4)), "arraybuffer"); - assert(!isTransferable(new Uint8Array(4)), "typedarray"); - assert(!isTransferable([]), "array"); - assert(!isTransferable("a"), "string"); - assert(!isTransferable(0), "zero"); - assert(!isTransferable(null), "null"); - assert(!isTransferable(undefined), "undefined"); + assert.ok(isTransferable(new ArrayBuffer(4)), "arraybuffer"); + assert.ok(!isTransferable(new Uint8Array(4)), "typedarray"); + assert.ok(!isTransferable([]), "array"); + assert.ok(!isTransferable("a"), "string"); + assert.ok(!isTransferable(0), "zero"); + assert.ok(!isTransferable(null), "null"); + assert.ok(!isTransferable(undefined), "undefined"); }); }); diff --git a/packages/checks/test/tsconfig.json b/packages/checks/test/tsconfig.json index 13d45669e5..2c9c12a650 100644 --- a/packages/checks/test/tsconfig.json +++ b/packages/checks/test/tsconfig.json @@ -1,7 +1,8 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", diff --git a/packages/checks/tsconfig.json b/packages/checks/tsconfig.json index f6c291a0a0..bcf03f18b4 100644 --- a/packages/checks/tsconfig.json +++ b/packages/checks/tsconfig.json @@ -1,7 +1,9 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" diff --git a/packages/color/.npmignore b/packages/color/.npmignore new file mode 100644 index 0000000000..67d0c55714 --- /dev/null +++ b/packages/color/.npmignore @@ -0,0 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz +build +coverage +dev +doc +src* +test +tsconfig.json diff --git a/packages/color/CHANGELOG.md b/packages/color/CHANGELOG.md new file mode 100644 index 0000000000..124aabcebf --- /dev/null +++ b/packages/color/CHANGELOG.md @@ -0,0 +1,32 @@ +# 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-01-21) + + +### Bug Fixes + +* **color:** add/update conversions ([a5c53c3](https://github.com/thi-ng/umbrella/commit/a5c53c3)) +* **color:** HCYA field names ([1c28c22](https://github.com/thi-ng/umbrella/commit/1c28c22)) + + +### Features + +* **color:** add alpha()/setAlpha(), add docs, re-exports, update readme ([b849bd1](https://github.com/thi-ng/umbrella/commit/b849bd1)) +* **color:** add convert() fallback, minor other updates ([aa30344](https://github.com/thi-ng/umbrella/commit/aa30344)) +* **color:** add HSI converters, add clampH(), minor refactors ([404ac54](https://github.com/thi-ng/umbrella/commit/404ac54)) +* **color:** add Hue enum, closestHue*() fns, namedHueRgba() ([e7bb46b](https://github.com/thi-ng/umbrella/commit/e7bb46b)) +* **color:** add luminance defmulti ([445b8c1](https://github.com/thi-ng/umbrella/commit/445b8c1)) +* **color:** add more color spaces, refactor, rename, simplify ([e930d73](https://github.com/thi-ng/umbrella/commit/e930d73)) +* **color:** add multiCosineGradient() ([dbbb26c](https://github.com/thi-ng/umbrella/commit/dbbb26c)) +* **color:** add new package ([0b51ef1](https://github.com/thi-ng/umbrella/commit/0b51ef1)) +* **color:** add Porter-Duff ops, pre/post-multiply, update types ([a5d2f98](https://github.com/thi-ng/umbrella/commit/a5d2f98)) +* **color:** add RGBA/HSLA wrapper types, update convert ([610699a](https://github.com/thi-ng/umbrella/commit/610699a)) +* **color:** add/update class wrappers ([5788646](https://github.com/thi-ng/umbrella/commit/5788646)) + + +### Performance Improvements + +* **color:** refactor porterDiff as HOF, update all PD ops, add docs ([714381d](https://github.com/thi-ng/umbrella/commit/714381d)) diff --git a/packages/color/LICENSE b/packages/color/LICENSE new file mode 100644 index 0000000000..8dada3edaf --- /dev/null +++ b/packages/color/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/color/README.md b/packages/color/README.md new file mode 100644 index 0000000000..21c12fa897 --- /dev/null +++ b/packages/color/README.md @@ -0,0 +1,237 @@ +# @thi.ng/color + +[![npm (scoped)](https://img.shields.io/npm/v/@thi.ng/color.svg)](https://www.npmjs.com/package/@thi.ng/color) +![npm downloads](https://img.shields.io/npm/dm/@thi.ng/color.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) + - [Color spaces / modes](#color-spaces--modes) + - [RGBA transformations](#rgba-transformations) + - [RGBA Porter-Duff compositing](#rgba-porter-duff-compositing) + - [Cosine gradients](#cosine-gradients) + - [Multi-stop gradients](#multi-stop-gradients) +- [Status](#status) +- [Installation](#installation) +- [Dependencies](#dependencies) +- [Usage examples](#usage-examples) +- [Authors](#authors) +- [License](#license) + + + +## About + +Raw, array-based, color operations, conversions and optional type +wrappers. The functions provided by this package are largely using the +same calling convention as those in the +[@thi.ng/vectors](https://github.com/thi-ng/umbrella/tree/master/packages/vectors) +package. + +### Color spaces / modes + +Fast color space conversions (any direction) between: + +- CSS (string, hex3/hex4/hex6/hex8, rgba(), hsla(), named colors) +- HCYA (float4) +- HSIA (float4) +- HSLA (float4) +- HSVA (float4) +- Int32 (uint32, `0xaarrggbb`) +- RGBA (float4) +- XYZA (float4, aka CIE 1931) +- YCbCr (float4) + +Apart from `CSS` and `Int32` colors, all others can be stored as plain +arrays, typed array or custom array-like types of (mostly) normalized +values (`[0,1]` interval). Where applicable, the hue too is stored in +that range, NOT in degrees. + +Apart from conversions, most other operations provided by this package +are currently only supporting RGBA colors. These can also be converted +to / from sRGB (i.e. linear vs gamma corrected). Additionally, RGBA +colors can be pre-multiplied (and post-multiplied) with their alpha +channel (see [Porter-Duff](#rgba-porter-duff-compositing) section +below). + +#### Class wrappers + +The package provides lightweight class wrappers for each color mode / +space. These wrappers act similarly to the `Vec2/3/4` wrappers in +[@thi.ng/vectors](https://github.com/thi-ng/umbrella/tree/master/packages/vectors), +support striding (for mapped memory views), named channel accessor +aliases (in addition to array indexing) and are fully compatible with +all functions (and act as syntax sugar for generic conversion +functions). Wrapper factory functions are provided for convenience. + +### RGBA transformations + +RGBA [color matrix +transformations](https://github.com/thi-ng/umbrella/tree/master/packages/color/src/matrix.ts), +including parametric preset transforms: + +- brightness +- contrast +- exposure +- saturation (luminance aware) +- hue rotation +- color temperature (warm / cold) +- sepia (w/ fade amount) +- tint (green / purple) +- grayscale (luminance aware) +- subtraction/inversion (also available as non-matrix op) +- luminance to alpha + +Transformation matrices can be combined using matrix multiplication / +concatenation (`concat()`) for more efficient application. + +### RGBA Porter-Duff compositing + +The package provides all 12 basic +[Porter-Duff](https://github.com/thi-ng/umbrella/tree/master/packages/color/src/porter-duff.ts) +compositing / blending operators, both for colors with pre-multiplied +alpha and without. + +![porter-duff compositing modes](https://raw.githubusercontent.com/thi-ng/umbrella/master/assets/porter-duff.png) + +([Image source](http://www.svgopen.org/2005/papers/abstractsvgopen/#PorterDuffMap)) + +### Cosine gradients + +- [Original article](http://www.iquilezles.org/www/articles/palettes/palettes.htm) +- [Gradient generator](http://dev.thi.ng/gradients/) + +The following presets are bundled (in [`cosine-gradients.ts`](https://github.com/thi-ng/umbrella/tree/master/packages/color/src/cosine-gradients.ts)): + +| | | +|----------------------------------------------------------------|------------------------------------------------------------------| +| ![](http://media.thi.ng/color/presets/rainbow1.svg) | ![](http://media.thi.ng/color/presets/rainbow2.svg) | +| rainbow1 | rainbow2 | +| ![](http://media.thi.ng/color/presets/rainbow3.svg) | ![](http://media.thi.ng/color/presets/rainbow4.svg) | +| rainbow3 | rainbow4 | +| ![](http://media.thi.ng/color/presets/yellow-magenta-cyan.svg) | ![](http://media.thi.ng/color/presets/orange-blue.svg) | +| yellow-magenta-cyan preset | orange-blue | +| ![](http://media.thi.ng/color/presets/green-magenta.svg) | ![](http://media.thi.ng/color/presets/green-red.svg) | +| green-magenta | green-red | +| ![](http://media.thi.ng/color/presets/green-cyan.svg) | ![](http://media.thi.ng/color/presets/blue-cyan.svg) | +| green-cyan | blue-cyan | +| ![](http://media.thi.ng/color/presets/yellow-red.svg) | ![](http://media.thi.ng/color/presets/red-blue.svg) | +| yellow-red | red-blue | +| ![](http://media.thi.ng/color/presets/yellow-green-blue.svg) | ![](http://media.thi.ng/color/presets/blue-white-red.svg) | +| yellow-green-blue | blue-white-red | +| ![](http://media.thi.ng/color/presets/cyan-magenta.svg) | ![](http://media.thi.ng/color/presets/yellow-purple-magenta.svg) | +| cyan-magenta | yellow-purple-magenta | +| ![](http://media.thi.ng/color/presets/green-blue-orange.svg) | ![](http://media.thi.ng/color/presets/orange-magenta-blue.svg) | +| green-blue-orange | orange-magenta-blue | +| ![](http://media.thi.ng/color/presets/blue-magenta-orange.svg) | ![](http://media.thi.ng/color/presets/magenta-green.svg) | +| blue-magenta-orange | magenta-green | + +### Multi-stop gradients + +The `multiCosineGradient()` function returns an iterator of raw RGBA +colors based on given gradient stops. This iterator computes a cosine +gradient between each color stop and yields a sequence of RGBA values. + +```ts +col.multiCosineGradient( + // num colors to produce + 10, + // gradient stops (normalized positions, only RGBA colors supported) + [0.1, col.RED], [0.5, col.GREEN], [0.9, col.BLUE] +) +// convert to CSS +.map(col.rgbaCss) + +// [ +// "#ff0000", +// "#ff0000", +// "#da2500", +// "#807f00", +// "#25da00", +// "#00ff00", +// "#00da25", +// "#00807f", +// "#0025da", +// "#0000ff", +// "#0000ff", +// ] +``` + +## Status + +ALPHA - work in progress + +- [@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/vectors](https://github.com/thi-ng/umbrella/tree/master/packages/vectors) - optimized 2d/3d/4d and arbitrary length vector ops +- [@thi.ng/vector-pools](https://github.com/thi-ng/umbrella/tree/master/packages/vector-pools) - operations on memory mapped data + +## Installation + +```bash +yarn add @thi.ng/color +``` + +## Dependencies + +- [@thi.ng/api](https://github.com/thi-ng/umbrella/tree/master/packages/api) +- [@thi.ng/compose](https://github.com/thi-ng/umbrella/tree/master/packages/compose) +- [@thi.ng/defmulti](https://github.com/thi-ng/umbrella/tree/master/packages/defmulti) +- [@thi.ng/errors](https://github.com/thi-ng/umbrella/tree/master/packages/errors) +- [@thi.ng/strings](https://github.com/thi-ng/umbrella/tree/master/packages/strings) +- [@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) + +## Usage examples + +```ts +import * as col from "@thi.ng/color"; + +// route #1: asXXX() converters: string -> CSS -> ARGB (int) -> RGBA +const a = col.asRGBA(col.css("#3cf")); +// [0.2, 0.8, 1, 1] + +// route #2: parseCSS(): string -> HSLA -> RGBA +const b = col.parseCss("hsla(30,100%,50%,0.75)", col.ColorMode.RGBA); +// [ 1, 0.5, 0, 0.75 ] + +// route #3: convert() multi-method: CSS -> RGBA -> HSVA +// (see convert.ts) +const c = col.convert("rgb(0,255,255)", col.ColorMode.HSVA, col.ColorMode.CSS); +// [ 0.4999999722222268, 0.9999990000010001, 1, 1 ] + +// route #4: direct conversion RGBA -> HSLA -> CSS +// first arg is output color (same calling convention as @thi.ng/vectors) +// (use `null` to mutate the input color) +col.hslaCss(col.rgbaHsla([], [1, 0.5, 0.5, 1])) +// "hsl(0.00,100.00%,75.00%)" + +col.luminance(col.css("white")) +col.luminance(0xffffff, col.ColorMode.INT32) +// 1 + +// apply color matrix (RGBA only) +col.transform([], col.saturation(1.25), a) +// [ 0.07835000000000002, 0.82835, 1, 1 ] + +// combine matrix transformations +filter = col.concatMatrices( + col.saturation(0.5), // 50% saturation + col.brightness(0.1), // +10% brightness +); + +col.transform([], filter, col.RED); +// [ 0.7065, 0.2065, 0.2065, 1 ] +``` + +## Authors + +- Karsten Schmidt + +## License + +© 2018 Karsten Schmidt // Apache Software License 2.0 diff --git a/packages/color/package.json b/packages/color/package.json new file mode 100644 index 0000000000..4178733dd0 --- /dev/null +++ b/packages/color/package.json @@ -0,0 +1,78 @@ +{ + "name": "@thi.ng/color", + "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/color", + "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 color api compose defmulti errors math strings transducers vectors", + "test": "rimraf build && tsc -p test/tsconfig.json && nyc mocha build/test/*.js", + "clean": "rimraf *.js *.d.ts .nyc_output build coverage doc lib internal", + "cover": "yarn test && nyc report --reporter=lcov", + "doc": "typedoc --mode modules --out doc src", + "pub": "yarn build && yarn publish --access public" + }, + "devDependencies": { + "@types/mocha": "^5.2.5", + "@types/node": "^10.12.15", + "mocha": "^5.2.0", + "nyc": "^13.1.0", + "typedoc": "^0.14.0", + "typescript": "^3.2.2" + }, + "dependencies": { + "@thi.ng/api": "^5.0.0", + "@thi.ng/compose": "^1.0.0", + "@thi.ng/defmulti": "^1.0.0", + "@thi.ng/errors": "^1.0.0", + "@thi.ng/math": "^1.0.0", + "@thi.ng/strings": "^1.0.0", + "@thi.ng/transducers": "^3.0.0", + "@thi.ng/vectors": "^2.0.0" + }, + "keywords": [ + "alpha", + "blending", + "CSS", + "CIE1931", + "color", + "conversion", + "cosine", + "ES6", + "filter", + "gradient", + "HCY", + "HSL", + "HSV", + "HSI", + "matrix", + "porter-duff", + "RGB", + "sRGB", + "XYZ", + "YCbCr", + "typescript" + ], + "publishConfig": { + "access": "public" + }, + "browserslist": [ + "since 2018-07" + ], + "browser": { + "process": false, + "setTimeout": false + }, + "sideEffects": false +} diff --git a/packages/color/src/alpha.ts b/packages/color/src/alpha.ts new file mode 100644 index 0000000000..516b62130c --- /dev/null +++ b/packages/color/src/alpha.ts @@ -0,0 +1,16 @@ +import { setC4 } from "@thi.ng/vectors"; +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 + ); diff --git a/packages/color/src/api.ts b/packages/color/src/api.ts new file mode 100644 index 0000000000..82f2b9814e --- /dev/null +++ b/packages/color/src/api.ts @@ -0,0 +1,90 @@ +import { float, percent } from "@thi.ng/strings"; +import { ReadonlyVec, Vec } from "@thi.ng/vectors"; + +export type Color = Vec; +export type ReadonlyColor = ReadonlyVec; + +export type ColorMatrix = [ + 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 const enum ColorMode { + RGBA, + HCYA, + HSVA, + HSLA, + HSIA, + INT32, + CSS, + XYZA, + YCBCRA +} + +/** + * Reverse lookup for `ColorMode` enums + */ +export const __ColorMode = (exports).ColorMode; + +export interface IColor { + readonly mode: ColorMode; +} + +// RGBA constants + +export const BLACK = Object.freeze([0, 0, 0, 1]); +export const WHITE = Object.freeze([1, 1, 1, 1]); + +export const RED = Object.freeze([1, 0, 0, 1]); +export const GREEN = Object.freeze([0, 1, 0, 1]); +export const BLUE = Object.freeze([0, 0, 1, 1]); + +export const CYAN = Object.freeze([0, 1, 1, 1]); +export const MAGENTA = Object.freeze([1, 0, 1, 1]); +export const YELLOW = Object.freeze([1, 1, 0, 1]); + +export const RGB_LUMINANCE = [0.299, 0.587, 0.114]; + +// Hue names + +export enum Hue { + RED, + ORANGE, + YELLOW, + CHARTREUSE, + GREEN, + SPRING_GREEN, + CYAN, + AZURE, + BLUE, + VIOLET, + MAGENTA, + ROSE +} + +// internal helpers + +export const SRGB_ALPHA = 0.055; + +export const RGB_XYZ = [ + 0.4124564, 0.3575761, 0.1804375, + 0.2126729, 0.7151522, 0.0721750, + 0.0193339, 0.1191920, 0.9503041 +]; + +export const XYZ_RGB = [ + 3.2404542, -1.5371385, -0.4985314, + -0.9692660, 1.8760108, 0.0415560, + 0.0556434, -0.2040259, 1.0572252 +]; + +export const FF = float(2); +export const PC = percent(2); +export const INV8BIT = 1 / 0xff; diff --git a/packages/color/src/clamp.ts b/packages/color/src/clamp.ts new file mode 100644 index 0000000000..0265c72f0a --- /dev/null +++ b/packages/color/src/clamp.ts @@ -0,0 +1,42 @@ +import { clamp01 } from "@thi.ng/math"; +import { setC4 } from "@thi.ng/vectors"; +import { Color, ReadonlyColor } from "./api"; +import { ensureAlpha } from "./internal/ensure-alpha"; +import { ensureHue } from "./internal/ensure-hue"; + +/** + * Clamps all color channels to [0,1] interval and calls `ensureAlpha()` + * to ensure alpha channel is defined (if missing sets it to `alpha` + * (default: 1)). + * + * @param out + * @param src + * @param alpha + */ +export const clamp = + (out: Color, src: ReadonlyColor, alpha = 1) => + setC4( + out || src, + clamp01(src[0]), + clamp01(src[1]), + clamp01(src[2]), + ensureAlpha(src[3], alpha) + ); + +/** + * Similar to `clamp`, but calls `ensureHue()` to fold (instead of + * clamping) the hue into [0,1] interval. + * + * @param out + * @param src + * @param alpha + */ +export const clampH = + (out: Color, src: ReadonlyColor, alpha = 1) => + setC4( + out || src, + ensureHue(src[0]), + clamp01(src[1]), + clamp01(src[2]), + ensureAlpha(src[3], alpha) + ); diff --git a/packages/color/src/closest-hue.ts b/packages/color/src/closest-hue.ts new file mode 100644 index 0000000000..6d8aeea5c3 --- /dev/null +++ b/packages/color/src/closest-hue.ts @@ -0,0 +1,20 @@ +import { Hue } from "./api"; +import { ensureHue } from "./internal/ensure-hue"; + +/** + * Returns the `Hue` constant of the closest of 12 defined hues. + * + * @param h hue + */ +export const closestHue = + (h: number): Hue => + Math.round(ensureHue(h) * 12) % 12; + +/** + * Returns the `Hue` constant of the closest primary or secondary hue. + * + * @param h + */ +export const closestPrimaryHue = + (h: number): Hue => + (Math.round(ensureHue(h) * 12) % 12) & 0xe; diff --git a/packages/color/src/convert.ts b/packages/color/src/convert.ts new file mode 100644 index 0000000000..8b130f16bd --- /dev/null +++ b/packages/color/src/convert.ts @@ -0,0 +1,284 @@ +import { + DEFAULT, + defmulti, + Implementation3, + MultiFn2O +} from "@thi.ng/defmulti"; +import { illegalArgs } from "@thi.ng/errors"; +import { + __ColorMode, + Color, + ColorConversion, + ColorMode, + IColor, + ReadonlyColor +} from "./api"; +import { hcyaRgba } from "./hcya-rgba"; +import { hsiaRgba } from "./hsia-rgba"; +import { hslaCss } from "./hsla-css"; +import { hslaHsva } from "./hsla-hsva"; +import { hslaRgba } from "./hsla-rgba"; +import { hsvaCss } from "./hsva-css"; +import { hsvaHsla } from "./hsva-hsla"; +import { hsvaRgba } from "./hsva-rgba"; +import { int32Css } from "./int-css"; +import { int32Rgba } from "./int-rgba"; +import { parseCss } from "./parse-css"; +import { rgbaCss } from "./rgba-css"; +import { rgbaHcya } from "./rgba-hcya"; +import { rgbaHsia } from "./rgba-hsia"; +import { rgbaHsla } from "./rgba-hsla"; +import { rgbaHsva } from "./rgba-hsva"; +import { rgbaInt } from "./rgba-int"; +import { rgbaXyza } from "./rgba-xyza"; +import { rgbaYcbcra } from "./rgba-ycbcra"; +import { xyzaRgba } from "./xyza-rgba"; +import { ycbcraRgba } from "./ycbcra-rgba"; + +export const convert: MultiFn2O = + 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 ${__ColorMode[msrc]} -> ${__ColorMode[mdest]}`) +); + +export function asCSS(col: IColor): string; +export function asCSS(col: string | number | ReadonlyColor, mode: ColorMode): string; +export function asCSS(col: any, mode?: ColorMode) { + return convert(col, ColorMode.CSS, mode); +} + +export function asRGBA(col: IColor): Color; +export function asRGBA(col: string | number | ReadonlyColor, mode: ColorMode): Color; +export function asRGBA(col: any, mode?: ColorMode) { + return convert(col, ColorMode.RGBA, mode); +} + +export function asHCYA(col: IColor): Color; +export function asHCYA(col: string | number | ReadonlyColor, mode: ColorMode): Color; +export function asHCYA(col: any, mode?: ColorMode) { + return convert(col, ColorMode.HCYA, mode); +} + +export function asHSIA(col: IColor): Color; +export function asHSIA(col: string | number | ReadonlyColor, mode: ColorMode): Color; +export function asHSIA(col: any, mode?: ColorMode) { + return convert(col, ColorMode.HSIA, mode); +} + +export function asHSLA(col: IColor): Color; +export function asHSLA(col: string | number | ReadonlyColor, mode: ColorMode): Color; +export function asHSLA(col: any, mode?: ColorMode) { + return convert(col, ColorMode.HSLA, mode); +} + +export function asHSVA(col: IColor): Color; +export function asHSVA(col: string | number | ReadonlyColor, mode: ColorMode): Color; +export function asHSVA(col: any, mode?: ColorMode) { + return convert(col, ColorMode.HSVA, mode); +} + +export function asXYZA(col: IColor): Color; +export function asXYZA(col: string | number | ReadonlyColor, mode: ColorMode): Color; +export function asXYZA(col: any, mode?: ColorMode) { + return convert(col, ColorMode.XYZA, mode); +} + +export function asYCbCrA(col: IColor): Color; +export function asYCbCrA(col: string | number | ReadonlyColor, mode: ColorMode): Color; +export function asYCbCrA(col: any, mode?: ColorMode) { + return convert(col, ColorMode.YCBCRA, mode); +} + +const defConversion = ( + dest: ColorMode, + src: ColorMode, + impl: Implementation3 +) => + convert.add(`${dest}-${src}`, impl); + +const defConversions = ( + src: ColorMode, + toRGBA: ColorConversion, + ...dest: ColorMode[] +) => { + defConversion(ColorMode.RGBA, src, (x: any) => toRGBA([], x)); + dest.forEach( + (id) => defConversion( + id, src, + (x: any) => convert(toRGBA([], x), id, ColorMode.RGBA) + ) + ); +}; + +// CSS + +defConversion(ColorMode.RGBA, ColorMode.CSS, (x: string) => parseCss(x)); + +[ + ColorMode.HCYA, + ColorMode.HSIA, + ColorMode.HSLA, + ColorMode.HSVA, + ColorMode.INT32, + ColorMode.XYZA, + ColorMode.YCBCRA +].forEach( + (id) => defConversion( + id, ColorMode.CSS, + (x: string) => convert(parseCss(x), id, ColorMode.RGBA) + ) +); + +// Int + +defConversions( + ColorMode.INT32, + int32Rgba, + ColorMode.HCYA, + ColorMode.HSIA, + ColorMode.HSLA, + ColorMode.HSVA, + ColorMode.XYZA, + ColorMode.YCBCRA +); + +defConversion( + ColorMode.CSS, ColorMode.INT32, + (x: number) => int32Css(x) +); + +// HCYA + +defConversions( + ColorMode.HCYA, + hcyaRgba, + ColorMode.CSS, + ColorMode.INT32, + ColorMode.HSLA, + ColorMode.HSVA, + ColorMode.XYZA, + ColorMode.YCBCRA +); + +// HSIA + +defConversions( + ColorMode.HSIA, + hsiaRgba, + ColorMode.CSS, + ColorMode.INT32, + ColorMode.HCYA, + ColorMode.HSLA, + ColorMode.HSVA, + ColorMode.XYZA, + ColorMode.YCBCRA +); + +// HSLA + +defConversions( + ColorMode.HSLA, + hslaRgba, + ColorMode.HCYA, + ColorMode.HSIA, + ColorMode.INT32, + ColorMode.XYZA, + ColorMode.YCBCRA +); + +defConversion( + ColorMode.CSS, ColorMode.HSLA, + (x: ReadonlyColor) => hslaCss(x) +); + +defConversion( + ColorMode.HSVA, ColorMode.HSLA, + (x: ReadonlyColor) => hslaHsva([], x) +); + +// HSVA + +defConversions( + ColorMode.HSVA, + hsvaRgba, + ColorMode.HCYA, + ColorMode.HSIA, + ColorMode.INT32, + ColorMode.XYZA, + ColorMode.YCBCRA +); + +defConversion( + ColorMode.CSS, ColorMode.HSVA, + (x: ReadonlyColor) => hsvaCss(x) +); + +defConversion( + ColorMode.HSLA, ColorMode.HSVA, + (x: ReadonlyColor) => hsvaHsla([], x) +); + +// RGBA + +[ + [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) + ) +); + +defConversion( + ColorMode.CSS, ColorMode.RGBA, + (x: ReadonlyColor) => rgbaCss(x) +); + +defConversion( + ColorMode.INT32, ColorMode.RGBA, + (x: ReadonlyColor) => rgbaInt(x) +); + +// XYZA + +defConversions( + ColorMode.XYZA, + xyzaRgba, + ColorMode.CSS, + ColorMode.HCYA, + ColorMode.HSIA, + ColorMode.HSLA, + ColorMode.HSVA, + ColorMode.INT32, + ColorMode.YCBCRA +); + +// YCbCr + +defConversions( + ColorMode.YCBCRA, + ycbcraRgba, + ColorMode.CSS, + ColorMode.HCYA, + ColorMode.HSIA, + ColorMode.HSLA, + ColorMode.HSVA, + ColorMode.INT32, + ColorMode.XYZA +); diff --git a/packages/color/src/cosine-gradients.ts b/packages/color/src/cosine-gradients.ts new file mode 100644 index 0000000000..10a1b5dcc9 --- /dev/null +++ b/packages/color/src/cosine-gradients.ts @@ -0,0 +1,107 @@ +import { IObjectOf } from "@thi.ng/api"; +import { partial } from "@thi.ng/compose"; +import { clamp01, TAU } from "@thi.ng/math"; +import { + interpolate, + map, + normRange, + push, + transduce, + tuples +} from "@thi.ng/transducers"; +import { Color, CosGradientSpec, ReadonlyColor } from "./api"; +import { clamp } from "./clamp"; + +// see http://dev.thi.ng/gradients/ - unlike the clojure version, these +// presets are for RGBA (though the alpha channel is configured to +// always be 1.0) + +export const GRADIENTS: IObjectOf = { + "blue-cyan": [[0, 0.5, 0.5, 1], [0, 0.5, 0.5, 0], [0, 0.5, 0.3333, 0], [0, 0.5, 0.6666, 0]], + "blue-magenta-orange": [[0.938, 0.328, 0.718, 1], [0.659, 0.438, 0.328, 0], [0.388, 0.388, 0.296, 0], [2.538, 2.478, 0.168, 0]], + "blue-white-red": [[0.660, 0.56, 0.680, 1], [0.718, 0.438, 0.720, 0], [0.520, 0.8, 0.520, 0], [-0.430, -0.397, -0.083, 0]], + "cyan-magenta": [[0.610, 0.498, 0.650, 1], [0.388, 0.498, 0.350, 0], [0.530, 0.498, 0.620, 0], [3.438, 3.012, 4.025, 0]], + "green-blue-orange": [[0.892, 0.725, 0, 1], [0.878, 0.278, 0.725, 0], [0.332, 0.518, 0.545, 0], [2.440, 5.043, 0.732, 0]], + "green-cyan": [[0, 0.5, 0.5, 1], [0, 0.5, 0.5, 0], [0, 0.3333, 0.5, 0], [0, 0.6666, 0.5, 0]], + "green-magenta": [[0.6666, 0.5, 0.5, 1], [0.5, 0.6666, 0.5, 0], [0.6666, 0.666, 0.5, 0], [0.2, 0, 0.5, 0]], + "green-red": [[0.5, 0.5, 0, 1], [0.5, 0.5, 0, 0], [0.5, 0.5, 0, 0], [0.5, 0, 0, 0]], + "magenta-green": [[0.590, 0.811, 0.120, 1], [0.410, 0.392, 0.590, 0], [0.940, 0.548, 0.278, 0], [-4.242, -6.611, -4.045, 0]], + "orange-blue": [[0.5, 0.5, 0.5, 1], [0.5, 0.5, 0.5, 0], [0.8, 0.8, 0.5, 0], [0, 0.2, 0.5, 0]], + "orange-magenta-blue": [[0.821, 0.328, 0.242, 1], [0.659, 0.481, 0.896, 0], [0.612, 0.340, 0.296, 0], [2.820, 3.026, -0.273, 0]], + "rainbow1": [[0.5, 0.5, 0.5, 1], [0.5, 0.5, 0.5, 0], [1.0, 1.0, 1.0, 0], [0, 0.3333, 0.6666, 0]], + "rainbow2": [[0.5, 0.5, 0.5, 1], [0.666, 0.666, 0.666, 0], [1.0, 1.0, 1.0, 0], [0, 0.3333, 0.6666, 0]], + "rainbow3": [[0.5, 0.5, 0.5, 1], [0.75, 0.75, 0.75, 0], [1.0, 1.0, 1.0, 0], [0, 0.3333, 0.6666, 0]], + "rainbow4": [[0.5, 0.5, 0.5, 1], [1, 1, 1, 0], [1.0, 1.0, 1.0, 0], [0, 0.3333, 0.6666, 0]], + "red-blue": [[0.5, 0, 0.5, 1], [0.5, 0, 0.5, 0], [0.5, 0, 0.5, 0], [0, 0, 0.5, 0]], + "yellow-green-blue": [[0.650, 0.5, 0.310, 1], [-0.650, 0.5, 0.6, 0], [0.333, 0.278, 0.278, 0], [0.660, 0, 0.667, 0]], + "yellow-magenta-cyan": [[1, 0.5, 0.5, 1], [0.5, 0.5, 0.5, 0], [0.75, 1.0, 0.6666, 0], [0.8, 1.0, 0.3333, 0]], + "yellow-purple-magenta": [[0.731, 1.098, 0.192, 1], [0.358, 1.090, 0.657, 0], [1.077, 0.360, 0.328, 0], [0.965, 2.265, 0.837, 0]], + "yellow-red": [[0.5, 0.5, 0, 1], [0.5, 0.5, 0, 0], [0.1, 0.5, 0, 0], [0, 0, 0, 0]], +}; + +export const cosineColor = + (spec: CosGradientSpec, t: number): Color => + transduce( + map( + ([a, b, c, d]) => clamp01(a + b * Math.cos(TAU * (c * t + d))) + ), + push(), + tuples(...spec) + ); + +export const cosineGradient = + (n: number, spec: CosGradientSpec) => + transduce( + map(partial(cosineColor, spec)), + push(), + normRange(n - 1) + ); + +/** + * Returns coefficients to produce a cosine gradient between the two + * given RGBA colors. + * + * @param from + * @param to + */ +export const cosineCoeffs = + (from: ReadonlyColor, to: ReadonlyColor) => { + from = clamp([], from); + to = clamp([], to); + const amp = [...map(([a, b]) => 0.5 * (a - b), tuples(from, to))]; + return [ + [...map(([s, a]) => s - a, tuples(from, amp))], + amp, + [-0.5, -0.5, -0.5, -0.5], + [0, 0, 0, 0] + ]; + }; + +/** + * Multi-color cosine gradient generator using RGBA color stops. Returns + * an array of `n+1` color samples. + * + * ``` + * multiCosineGradient( + * // num colors to produce + * 10, + * // gradient stops (normalized positions) + * [0.1, [1, 0, 0, 1]], [0.5, [0, 1, 0, 1]], [0.9, [0, 0, 1, 1]] + * ) + * ``` + * + * @see thi.ng/transducers/iter/interpolate + * + * @param n + * @param stops + */ +export const multiCosineGradient = + (n: number, ...stops: [number, ReadonlyColor][]): Color[] => + [...interpolate( + n, + 0, + 1, + cosineCoeffs, + cosineColor, + ...stops + )]; diff --git a/packages/color/src/css.ts b/packages/color/src/css.ts new file mode 100644 index 0000000000..4ba25b11a4 --- /dev/null +++ b/packages/color/src/css.ts @@ -0,0 +1,30 @@ +import { ICopy, IDeref } from "@thi.ng/api"; +import { ColorMode, IColor } from "./api"; + +export const css = + (col: string) => + new CSS(col); + +export class CSS implements + IColor, + ICopy, + IDeref { + + value: string; + + constructor(col: string) { + this.value = col; + } + + get mode() { + return ColorMode.CSS; + } + + copy() { + return new CSS(this.value); + } + + deref() { + return this.value; + } +} diff --git a/packages/color/src/hcya-rgba.ts b/packages/color/src/hcya-rgba.ts new file mode 100644 index 0000000000..5e596e13d1 --- /dev/null +++ b/packages/color/src/hcya-rgba.ts @@ -0,0 +1,25 @@ +import { clamp01 } from "@thi.ng/math"; +import { dot3, setC3 } from "@thi.ng/vectors"; +import { Color, ReadonlyColor, RGB_LUMINANCE } from "./api"; +import { hueRgba } from "./hue-rgba"; +import { ensureAlpha } from "./internal/ensure-alpha"; + +export const hcyaRgba = + (out: Color, src: ReadonlyColor) => { + const h = src[0]; + let c = src[1]; + const y = src[2]; + const rgb = hueRgba(out || src, h, ensureAlpha(src[3])); + const lum = dot3(rgb, RGB_LUMINANCE); + if (y < lum) { + c *= y / lum; + } else if (lum < 1) { + c *= (1 - y) / (1 - lum); + } + return setC3( + rgb, + clamp01((rgb[0] - lum) * c + y), + clamp01((rgb[1] - lum) * c + y), + clamp01((rgb[2] - lum) * c + y), + ); + }; diff --git a/packages/color/src/hcya.ts b/packages/color/src/hcya.ts new file mode 100644 index 0000000000..dcd0055553 --- /dev/null +++ b/packages/color/src/hcya.ts @@ -0,0 +1,37 @@ +import { IVector, declareIndices } from "@thi.ng/vectors"; +import { Color, ColorMode } from "./api"; +import { AColor } from "./internal/acolor"; +import { ensureArgs } from "./internal/ensure-args"; + +export function hcya(col: Color): HCYA +export function hcya(h?: number, c?: number, y?: number, a?: number): HCYA; +export function hcya(...args: any[]) { + return new HCYA(ensureArgs(args)); +} + +export class HCYA extends AColor implements + IVector { + + h: number; + c: number; + y: number; + a: number; + + get mode() { + return ColorMode.HCYA; + } + + copy() { + return new HCYA(this.deref()); + } + + copyView() { + return new HCYA(this.buf, this.offset, this.stride); + } + + empty() { + return new HCYA(); + } +} + +declareIndices(HCYA.prototype, ["h", "c", "y", "a"]); diff --git a/packages/color/src/hsia-rgba.ts b/packages/color/src/hsia-rgba.ts new file mode 100644 index 0000000000..1288846e31 --- /dev/null +++ b/packages/color/src/hsia-rgba.ts @@ -0,0 +1,37 @@ +import { setC3 } from "@thi.ng/vectors"; +import { Color, ReadonlyColor } from "./api"; +import { clampH } from "./clamp"; + +// https://en.wikipedia.org/wiki/HSL_and_HSV#From_HSI + +export const hsiaRgba = + (out: Color, src: ReadonlyColor) => { + out = clampH(out || src, src); + const s = out[1]; + const i = out[2]; + if (s < 1e-6) { + return setC3(out, i, i, i); + } + const h = (out[0] * 6) % 6; + const m = i * (1 - s); + const z = 1 - Math.abs(h % 2 - 1); + let c = 3 * i * s / (1 + z); + const x = c * z + m; + c += m; + switch (h | 0) { + case 0: + return setC3(out, c, x, m); + case 1: + return setC3(out, x, c, m); + case 2: + return setC3(out, m, c, x); + case 3: + return setC3(out, m, x, c); + case 4: + return setC3(out, x, m, c); + case 5: + return setC3(out, c, m, x); + default: + return setC3(out, m, m, m); + } + }; diff --git a/packages/color/src/hsia.ts b/packages/color/src/hsia.ts new file mode 100644 index 0000000000..8e6dbeedbc --- /dev/null +++ b/packages/color/src/hsia.ts @@ -0,0 +1,37 @@ +import { declareIndices, IVector } from "@thi.ng/vectors"; +import { Color, ColorMode } from "./api"; +import { AColor } from "./internal/acolor"; +import { ensureArgs } from "./internal/ensure-args"; + +export function hsia(col: Color): HSIA +export function hsia(h?: number, s?: number, i?: number, a?: number): HSIA; +export function hsia(...args: any[]) { + return new HSIA(ensureArgs(args)); +} + +export class HSIA extends AColor implements + IVector { + + h: number; + s: number; + i: number; + a: number; + + get mode() { + return ColorMode.HSIA; + } + + copy() { + return new HSIA(this.deref()); + } + + copyView() { + return new HSIA(this.buf, this.offset, this.stride); + } + + empty() { + return new HSIA(); + } +} + +declareIndices(HSIA.prototype, ["h", "s", "i", "a"]); diff --git a/packages/color/src/hsla-css.ts b/packages/color/src/hsla-css.ts new file mode 100644 index 0000000000..5182d41401 --- /dev/null +++ b/packages/color/src/hsla-css.ts @@ -0,0 +1,15 @@ +import { clamp01 } from "@thi.ng/math"; +import { FF, PC, ReadonlyColor } from "./api"; +import { ensureAlpha } from "./internal/ensure-alpha"; +import { ensureHue } from "./internal/ensure-hue"; + +export const hslaCss = + (src: ReadonlyColor) => { + const h = FF(ensureHue(src[0]) * 360); + const s = PC(clamp01(src[1])); + const l = PC(clamp01(src[2])); + const a = ensureAlpha(src[3]); + return (a < 1) ? + `hsla(${h},${s},${l},${FF(a)})` : + `hsl(${h},${s},${l})` + }; diff --git a/packages/color/src/hsla-hsva.ts b/packages/color/src/hsla-hsva.ts new file mode 100644 index 0000000000..f5ef5856e9 --- /dev/null +++ b/packages/color/src/hsla-hsva.ts @@ -0,0 +1,14 @@ +import { Color, ReadonlyColor } from "./api"; +import { clampH } from "./clamp"; + +export const hslaHsva = + (out: Color, src: ReadonlyColor) => { + out = clampH(out || src, src); + const s = out[1]; + const l = out[2]; + const l2 = 2 * l; + const v = (l2 + s * (1 - Math.abs(l2 - 1))) * 0.5; + out[1] = 2 * (v - l) / v; + out[2] = v; + return out; + }; diff --git a/packages/color/src/hsla-rgba.ts b/packages/color/src/hsla-rgba.ts new file mode 100644 index 0000000000..9704ce0525 --- /dev/null +++ b/packages/color/src/hsla-rgba.ts @@ -0,0 +1,19 @@ +import { clamp01 } from "@thi.ng/math"; +import { setC3 } from "@thi.ng/vectors"; +import { Color, ReadonlyColor } from "./api"; +import { hueRgba } from "./hue-rgba"; +import { ensureAlpha } from "./internal/ensure-alpha"; + +export const hslaRgba = + (out: Color, src: ReadonlyColor) => { + const s = clamp01(src[1]); + const l = clamp01(src[2]); + out = hueRgba(out || src, src[0], ensureAlpha(src[3])); + const c = (1 - Math.abs(2 * l - 1)) * s; + return setC3( + out, + (out[0] - 0.5) * c + l, + (out[1] - 0.5) * c + l, + (out[2] - 0.5) * c + l + ); + }; diff --git a/packages/color/src/hsla.ts b/packages/color/src/hsla.ts new file mode 100644 index 0000000000..85da646801 --- /dev/null +++ b/packages/color/src/hsla.ts @@ -0,0 +1,37 @@ +import { declareIndices, IVector } from "@thi.ng/vectors"; +import { Color, ColorMode } from "./api"; +import { AColor } from "./internal/acolor"; +import { ensureArgs } from "./internal/ensure-args"; + +export function hsla(col: Color): HSLA +export function hsla(h?: number, s?: number, l?: number, a?: number): HSLA; +export function hsla(...args: any[]) { + return new HSLA(ensureArgs(args)); +} + +export class HSLA extends AColor implements + IVector { + + h: number; + s: number; + l: number; + a: number; + + get mode() { + return ColorMode.HSLA; + } + + copy() { + return new HSLA(this.deref()); + } + + copyView() { + return new HSLA(this.buf, this.offset, this.stride); + } + + empty() { + return new HSLA(); + } +} + +declareIndices(HSLA.prototype, ["h", "s", "l", "a"]); diff --git a/packages/color/src/hsva-css.ts b/packages/color/src/hsva-css.ts new file mode 100644 index 0000000000..a338551a3c --- /dev/null +++ b/packages/color/src/hsva-css.ts @@ -0,0 +1,7 @@ +import { ReadonlyColor } from "./api"; +import { hsvaHsla } from "./hsva-hsla"; +import { hslaCss } from "./hsla-css"; + +export const hsvaCss = + (src: ReadonlyColor) => + hslaCss(hsvaHsla([], src)); diff --git a/packages/color/src/hsva-hsla.ts b/packages/color/src/hsva-hsla.ts new file mode 100644 index 0000000000..f37d4374a1 --- /dev/null +++ b/packages/color/src/hsva-hsla.ts @@ -0,0 +1,15 @@ +import { ReadonlyColor, Color } from "./api"; +import { clampH } from "./clamp"; + +export const hsvaHsla = + (out: Color, src: ReadonlyColor) => { + out = clampH(out || src, src); + const s = out[1]; + const v = out[2]; + const l = (2 - s) * v / 2; + out[2] = l; + out[1] = l && l < 1 ? + s * v / (l < 0.5 ? l * 2 : 2 - l * 2) : + s; + return out; + }; \ No newline at end of file diff --git a/packages/color/src/hsva-rgba.ts b/packages/color/src/hsva-rgba.ts new file mode 100644 index 0000000000..835c07731f --- /dev/null +++ b/packages/color/src/hsva-rgba.ts @@ -0,0 +1,18 @@ +import { setC3 } from "@thi.ng/vectors"; +import { Color, ReadonlyColor } from "./api"; +import { clampH } from "./clamp"; +import { hueRgba } from "./hue-rgba"; + +export const hsvaRgba = + (out: Color, src: ReadonlyColor) => { + out = clampH(out || src, src); + const s = out[1]; + const v = out[2]; + hueRgba(out, src[0], out[3]); + return setC3( + out, + ((out[0] - 1) * s + 1) * v, + ((out[1] - 1) * s + 1) * v, + ((out[2] - 1) * s + 1) * v, + ); + }; diff --git a/packages/color/src/hsva.ts b/packages/color/src/hsva.ts new file mode 100644 index 0000000000..6aee7309cd --- /dev/null +++ b/packages/color/src/hsva.ts @@ -0,0 +1,37 @@ +import { IVector, declareIndices } from "@thi.ng/vectors"; +import { Color, ColorMode } from "./api"; +import { AColor } from "./internal/acolor"; +import { ensureArgs } from "./internal/ensure-args"; + +export function hsva(col: Color): HSVA +export function hsva(h?: number, s?: number, v?: number, a?: number): HSVA; +export function hsva(...args: any[]) { + return new HSVA(ensureArgs(args)); +} + +export class HSVA extends AColor implements + IVector { + + h: number; + s: number; + v: number; + a: number; + + get mode() { + return ColorMode.HSVA; + } + + copy() { + return new HSVA(this.deref()); + } + + copyView() { + return new HSVA(this.buf, this.offset, this.stride); + } + + empty() { + return new HSVA(); + } +} + +declareIndices(HSVA.prototype, ["h", "s", "v", "a"]); diff --git a/packages/color/src/hue-rgba.ts b/packages/color/src/hue-rgba.ts new file mode 100644 index 0000000000..80feb44264 --- /dev/null +++ b/packages/color/src/hue-rgba.ts @@ -0,0 +1,27 @@ +import { clamp01 } from "@thi.ng/math"; +import { setC4 } from "@thi.ng/vectors"; +import { Color, Hue } from "./api"; +import { ensureHue } from "./internal/ensure-hue"; + +/** + * Converts a normalized hue to RGBA with given optional `alpha` + * value (default: 1). + * + * @param out + * @param hue + */ +export const hueRgba = + (out: Color, hue: number, alpha = 1): Color => { + hue = ensureHue(hue) * 6; + return setC4( + out, + clamp01(Math.abs(hue - 3) - 1), + clamp01(2 - Math.abs(hue - 2)), + clamp01(2 - Math.abs(hue - 4)), + alpha + ); + }; + +export const namedHueRgba = + (out: Color, hue: Hue, alpha = 1) => + hueRgba(out, hue / 12, alpha); diff --git a/packages/color/src/index.ts b/packages/color/src/index.ts new file mode 100644 index 0000000000..413f74e6bb --- /dev/null +++ b/packages/color/src/index.ts @@ -0,0 +1,51 @@ +export * from "./api"; +export * from "./names"; + +export * from "./hcya-rgba"; +export * from "./hsia-rgba"; +export * from "./hsla-css"; +export * from "./hsla-hsva"; +export * from "./hsla-rgba"; +export * from "./hsva-css"; +export * from "./hsva-hsla"; +export * from "./hsva-rgba"; +export * from "./hue-rgba"; +export * from "./int-css"; +export * from "./int-rgba"; +export * from "./kelvin-rgba"; +export * from "./rgba-css"; +export * from "./rgba-hcva"; +export * from "./rgba-hcya"; +export * from "./rgba-hsia"; +export * from "./rgba-hsla"; +export * from "./rgba-hsva"; +export * from "./rgba-int"; +export * from "./rgba-xyza"; +export * from "./rgba-ycbcra"; +export * from "./srgba"; +export * from "./xyza-rgba"; +export * from "./ycbcra-rgba"; + +export * from "./convert"; +export * from "./parse-css"; + +export * from "./int"; +export * from "./css"; +export * from "./hcya"; +export * from "./hsia"; +export * from "./hsla"; +export * from "./hsva"; +export * from "./rgba"; +export * from "./xyza"; +export * from "./ycbcr"; + +export * from "./alpha"; +export * from "./clamp"; +export * from "./closest-hue"; +export * from "./cosine-gradients"; +export * from "./invert"; +export * from "./luminance"; +export * from "./mix"; +export * from "./porter-duff"; +export * from "./premultiply"; +export * from "./transform"; diff --git a/packages/color/src/int-css.ts b/packages/color/src/int-css.ts new file mode 100644 index 0000000000..d859808c3a --- /dev/null +++ b/packages/color/src/int-css.ts @@ -0,0 +1,18 @@ +import { IDeref } from "@thi.ng/api"; +import { U24 } from "@thi.ng/strings"; +import { FF, INV8BIT } from "./api"; + +export const int32Css = + (src: number | IDeref) => { + src = typeof src === "number" ? src : src.deref(); + const a = src >>> 24; + return (a < 255) ? + `rgba(${(src >> 16) & 0xff},${(src >> 8) & 0xff},${src & 0xff},${FF(a * INV8BIT)})` : + `#${U24(src & 0xffffff)}`; + }; + +export const int24Css = + (src: number | IDeref) => { + src = typeof src === "number" ? src : src.deref(); + return int32Css(src | 0xff000000); + }; diff --git a/packages/color/src/int-rgba.ts b/packages/color/src/int-rgba.ts new file mode 100644 index 0000000000..a391cf5b7f --- /dev/null +++ b/packages/color/src/int-rgba.ts @@ -0,0 +1,21 @@ +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) => { + src = typeof src === "number" ? src : src.deref(); + return setC4( + out || [], + (src >>> 16 & 0xff) * INV8BIT, + (src >>> 8 & 0xff) * INV8BIT, + (src & 0xff) * INV8BIT, + (src >>> 24 & 0xff) * INV8BIT + ); + }; + +export const int24Rgba = + (out: Color, src: number | IDeref) => { + src = typeof src === "number" ? src : src.deref(); + return int32Rgba(out, src | 0xff000000); + }; diff --git a/packages/color/src/int.ts b/packages/color/src/int.ts new file mode 100644 index 0000000000..6637befe8a --- /dev/null +++ b/packages/color/src/int.ts @@ -0,0 +1,45 @@ +import { ICopy, IDeref } from "@thi.ng/api"; +import { ColorMode, IColor } from "./api"; + +/** + * Returns new `Int32` wrapping given ARGB int. + * + * @param rgba + */ +export const int32 = + (rgba: number) => + new Int32(rgba); + +/** + * Returns new `Int32` wrapping given 24bit RGB color and setting alpha + * channel set to 100% opaque. + * + * @param rgb + */ +export const int24 = + (rgb: number) => + new Int32((rgb & 0xffffff) | 0xff000000); + +export class Int32 implements + IColor, + ICopy, + IDeref { + + value: number; + + constructor(col: number) { + this.value = col >>> 0; + } + + get mode() { + return ColorMode.INT32; + } + + copy() { + return new Int32(this.value); + } + + deref() { + return this.value; + } +} diff --git a/packages/color/src/internal/acolor.ts b/packages/color/src/internal/acolor.ts new file mode 100644 index 0000000000..52b129c660 --- /dev/null +++ b/packages/color/src/internal/acolor.ts @@ -0,0 +1,38 @@ +import { IDeref } from "@thi.ng/api"; +import { EPS } from "@thi.ng/math"; +import { eqDelta4, values } from "@thi.ng/vectors"; +import { Color, IColor } from "../api"; + +export abstract class AColor implements + IColor, + IDeref { + + buf: Color; + offset: number; + stride: number; + [id: number]: number; + + constructor(buf?: Color, offset = 0, stride = 1) { + this.buf = buf || [0, 0, 0, 0]; + this.offset = offset; + this.stride = stride; + } + + [Symbol.iterator]() { + return values(this.buf, 4, this.offset, this.stride); + } + + abstract get mode(); + + get length() { + return 4; + } + + deref(): Color { + return [this[0], this[1], this[2], this[3]]; + } + + eqDelta(o: T, eps = EPS): boolean { + return eqDelta4(this, o, eps); + } +} \ No newline at end of file diff --git a/packages/color/src/internal/ensure-alpha.ts b/packages/color/src/internal/ensure-alpha.ts new file mode 100644 index 0000000000..0dfed24831 --- /dev/null +++ b/packages/color/src/internal/ensure-alpha.ts @@ -0,0 +1,7 @@ +import { clamp01 } from "@thi.ng/math"; + +export const ensureAlpha = + (x: number, def = 1) => + x != undefined ? + clamp01(x) : + def; diff --git a/packages/color/src/internal/ensure-args.ts b/packages/color/src/internal/ensure-args.ts new file mode 100644 index 0000000000..6eac8e2149 --- /dev/null +++ b/packages/color/src/internal/ensure-args.ts @@ -0,0 +1,16 @@ +export const ensureArgs = + (args: any[]) => { + if (typeof args[0] === "number") { + switch (args.length) { + case 1: + return (args.push(0, 0, 1), args); + case 2: + return (args.push(0, 1), args); + case 3: + return (args.push(1), args); + default: + return args; + } + } + return args[0]; + }; diff --git a/packages/color/src/internal/ensure-hue.ts b/packages/color/src/internal/ensure-hue.ts new file mode 100644 index 0000000000..5e39ae2192 --- /dev/null +++ b/packages/color/src/internal/ensure-hue.ts @@ -0,0 +1,2 @@ +export const ensureHue = + (x: number) => (x = x % 1, x < 0 ? x + 1 : x); diff --git a/packages/color/src/internal/matrix-ops.ts b/packages/color/src/internal/matrix-ops.ts new file mode 100644 index 0000000000..656cde8584 --- /dev/null +++ b/packages/color/src/internal/matrix-ops.ts @@ -0,0 +1,64 @@ +import { clamp01 } from "@thi.ng/math"; +import { dotS3, dotS4 } from "@thi.ng/vectors"; +import { setC4 } from "@thi.ng/vectors"; +import { Color, ColorMatrix, ReadonlyColor } from "../api"; +import { ensureAlpha } from "./ensure-alpha"; + +export const mulV33 = + (out: Color, mat: number[], src: ReadonlyColor, clampOut = true) => { + const x = dotS3(mat, src, 0, 0, 3); + const y = dotS3(mat, src, 1, 0, 3); + const z = dotS3(mat, src, 2, 0, 3); + const a = ensureAlpha(src[3]); + return clampOut ? + setC4( + out || src, + clamp01(x), + clamp01(y), + clamp01(z), + a + ) : + setC4(out || src, x, y, z, a); + }; + +export const mulV45 = + (out: Color, mat: ColorMatrix, src: ReadonlyColor, clampOut = true) => { + out = setC4(out || src, src[0], src[1], src[2], ensureAlpha(src[3])); + const x = dotS4(out, mat, 0, 0) + mat[4]; + const y = dotS4(out, mat, 0, 5) + mat[9]; + const z = dotS4(out, mat, 0, 10) + mat[14]; + const w = dotS4(out, mat, 0, 15) + mat[19]; + return clampOut ? + setC4( + out, + clamp01(x), + clamp01(y), + clamp01(z), + clamp01(w) + ) : + setC4(out, x, y, z, w); + }; + +export const mulM45 = + (a: ColorMatrix, b: ColorMatrix): ColorMatrix => [ + dotS4(b, a, 0, 0, 1, 5), + dotS4(b, a, 0, 1, 1, 5), + dotS4(b, a, 0, 2, 1, 5), + dotS4(b, a, 0, 3, 1, 5), + dotS4(b, a, 0, 4, 1, 5) + b[4], + dotS4(b, a, 5, 0, 1, 5), + dotS4(b, a, 5, 1, 1, 5), + dotS4(b, a, 5, 2, 1, 5), + dotS4(b, a, 5, 3, 1, 5), + dotS4(b, a, 5, 4, 1, 5) + b[9], + dotS4(b, a, 10, 0, 1, 5), + dotS4(b, a, 10, 1, 1, 5), + dotS4(b, a, 10, 2, 1, 5), + dotS4(b, a, 10, 3, 1, 5), + dotS4(b, a, 10, 4, 1, 5) + b[14], + dotS4(b, a, 15, 0, 1, 5), + dotS4(b, a, 15, 1, 1, 5), + dotS4(b, a, 15, 2, 1, 5), + dotS4(b, a, 15, 3, 1, 5), + dotS4(b, a, 15, 4, 1, 5) + b[19], + ]; diff --git a/packages/color/src/invert.ts b/packages/color/src/invert.ts new file mode 100644 index 0000000000..f8ed7657a5 --- /dev/null +++ b/packages/color/src/invert.ts @@ -0,0 +1,23 @@ +import { ONE3, sub3 } from "@thi.ng/vectors"; +import { Color, ReadonlyColor } from "./api"; +import { clamp } from "./clamp"; + +/** + * Inverts the RGB channels of an RGBA color. + * + * @param out + * @param src + */ +export const invertRGB = + (out: Color, src: ReadonlyColor) => ( + out = clamp(out || src, src), + sub3(out, ONE3, out) + ); + +/** + * Inverts the lowest 24 bits of an ARGB int. + * + * @param src + */ +export const invertInt = + (src: number) => src ^ 0xffffff; diff --git a/packages/color/src/kelvin-rgba.ts b/packages/color/src/kelvin-rgba.ts new file mode 100644 index 0000000000..673db7b980 --- /dev/null +++ b/packages/color/src/kelvin-rgba.ts @@ -0,0 +1,44 @@ +import { clamp01 } from "@thi.ng/math"; + +const G1 = -0.6088425710866344; +const G2 = -0.001748900018414868; +const G3 = 0.4097731842899564; +const G4 = 1.2762722061615583; +const G5 = 0.0003115080994769546; +const G6 = 0.11013841706194392; +const R1 = 1.3803015908551253; +const R2 = 0.0004478684462124118; +const R3 = -0.15785750232675008; +const B1 = -0.9990954974165059; +const B2 = 0.0032447435545127036; +const B3 = 0.453646839257496; + +/** + * Based on: + * https://github.com/neilbartlett/color-temperature/blob/master/index.js + * http://www.zombieprototypes.com/?p=210 + * + * Uses adjusted coefficients to produce normalized RGB values. + * + * @param kelvin color temperature + * @param alpha target alpha channel + */ +export const kelvinRgba = + (kelvin: number, alpha = 1) => { + kelvin *= 0.01; + let t: number; + return kelvin < 66 ? + [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 + ] : + [ + 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-rgb.ts b/packages/color/src/luminance-rgb.ts new file mode 100644 index 0000000000..c244868138 --- /dev/null +++ b/packages/color/src/luminance-rgb.ts @@ -0,0 +1,13 @@ +import { dot3 } from "@thi.ng/vectors"; +import { INV8BIT, ReadonlyColor, RGB_LUMINANCE } from "./api"; + +export const luminanceRGB = + (rgb: ReadonlyColor, weights = RGB_LUMINANCE) => + dot3(rgb, weights); + +export const luminanceInt = + (rgb: number) => ( + ((rgb >>> 16) & 0xff) * 76 + + ((rgb >>> 8) & 0xff) * 150 + + (rgb & 0xff) * 29 + ) * INV8BIT * INV8BIT; diff --git a/packages/color/src/luminance.ts b/packages/color/src/luminance.ts new file mode 100644 index 0000000000..d676eddf22 --- /dev/null +++ b/packages/color/src/luminance.ts @@ -0,0 +1,35 @@ +import { DEFAULT, defmulti, MultiFn1O } from "@thi.ng/defmulti"; +import { illegalArgs } from "@thi.ng/errors"; +import { ColorMode, IColor, ReadonlyColor } from "./api"; +import { convert } from "./convert"; +import { luminanceInt, luminanceRGB } from "./luminance-rgb"; + +/** + * Multi-method to compute relative luminance from any supported input + * color format. Unless color already is an RGBA or ARGB int (plain or + * wrapped), it will first be converted to RGBA. + */ +export const luminance: MultiFn1O = + 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.INT32, + (x: any) => luminanceInt(typeof x === "number" ? x : x.deref()) +); + +luminance.add( + DEFAULT, + (x: any, mode) => luminanceRGB(convert(x, ColorMode.RGBA, mode)) +); diff --git a/packages/color/src/mix.ts b/packages/color/src/mix.ts new file mode 100644 index 0000000000..4e5d205f55 --- /dev/null +++ b/packages/color/src/mix.ts @@ -0,0 +1,16 @@ +import { mix as _mix } from "@thi.ng/math"; +import { mixN4, setC4 } from "@thi.ng/vectors"; +import { Color, ReadonlyColor } from "./api"; + +export const mix: (out: Color, a: ReadonlyColor, b: ReadonlyColor, t: number) => Color = + mixN4; + +export const mixAlpha = + (out: Color, a: ReadonlyColor, b: ReadonlyColor) => + setC4( + out || a, + _mix(a[0], b[0], a[3]), + _mix(a[0], b[0], a[3]), + _mix(a[0], b[0], a[3]), + a[3] + ); diff --git a/packages/color/src/names.ts b/packages/color/src/names.ts new file mode 100644 index 0000000000..f51bd4bc0f --- /dev/null +++ b/packages/color/src/names.ts @@ -0,0 +1,149 @@ +export const CSS_NAMES = { + aliceblue: "f0f8ff", + antiquewhite: "faebd7", + aqua: "0ff", + aquamarine: "7fffd4", + azure: "f0ffff", + beige: "f5f5dc", + bisque: "ffe4c4", + black: "000", + blanchedalmond: "ffebcd", + blue: "00f", + blueviolet: "8a2be2", + brown: "a52a2a", + burlywood: "deb887", + cadetblue: "5f9ea0", + chartreuse: "7fff00", + chocolate: "d2691e", + coral: "ff7f50", + cornflowerblue: "6495ed", + cornsilk: "fff8dc", + crimson: "dc143c", + cyan: "0ff", + darkblue: "00008b", + darkcyan: "008b8b", + darkgoldenrod: "b8860b", + darkgray: "a9a9a9", + darkgreen: "006400", + darkgrey: "a9a9a9", + darkkhaki: "bdb76b", + darkmagenta: "8b008b", + darkolivegreen: "556b2f", + darkorange: "ff8c00", + darkorchid: "9932cc", + darkred: "8b0000", + darksalmon: "e9967a", + darkseagreen: "8fbc8f", + darkslateblue: "483d8b", + darkslategray: "2f4f4f", + darkslategrey: "2f4f4f", + darkturquoise: "00ced1", + darkviolet: "9400d3", + deeppink: "ff1493", + deepskyblue: "00bfff", + dimgray: "696969", + dimgrey: "696969", + dodgerblue: "1e90ff", + firebrick: "b22222", + floralwhite: "fffaf0", + forestgreen: "228b22", + fuchsia: "f0f", + gainsboro: "dcdcdc", + ghostwhite: "f8f8ff", + gold: "ffd700", + goldenrod: "daa520", + gray: "808080", + grey: "808080", + green: "008000", + greenyellow: "adff2f", + honeydew: "f0fff0", + hotpink: "ff69b4", + indianred: "cd5c5c", + indigo: "4b0082", + ivory: "fffff0", + khaki: "f0e68c", + lavender: "e6e6fa", + lavenderblush: "fff0f5", + lawngreen: "7cfc00", + lemonchiffon: "fffacd", + lightblue: "add8e6", + lightcoral: "f08080", + lightcyan: "e0ffff", + lightgoldenrodyellow: "fafad2", + lightgray: "d3d3d3", + lightgreen: "90ee90", + lightgrey: "d3d3d3", + lightpink: "ffb6c1", + lightsalmon: "ffa07a", + lightseagreen: "20b2aa", + lightskyblue: "87cefa", + lightslategray: "789", + lightslategrey: "789", + lightsteelblue: "b0c4de", + lightyellow: "ffffe0", + lime: "0f0", + limegreen: "32cd32", + linen: "faf0e6", + magenta: "f0f", + maroon: "800000", + mediumaquamarine: "66cdaa", + mediumblue: "0000cd", + mediumorchid: "ba55d3", + mediumpurple: "9370db", + mediumseagreen: "3cb371", + mediumslateblue: "7b68ee", + mediumspringgreen: "00fa9a", + mediumturquoise: "48d1cc", + mediumvioletred: "c71585", + midnightblue: "191970", + mintcream: "f5fffa", + mistyrose: "ffe4e1", + moccasin: "ffe4b5", + navajowhite: "ffdead", + navy: "000080", + oldlace: "fdf5e6", + olive: "808000", + olivedrab: "6b8e23", + orange: "ffa500", + orangered: "ff4500", + orchid: "da70d6", + palegoldenrod: "eee8aa", + palegreen: "98fb98", + paleturquoise: "afeeee", + palevioletred: "db7093", + papayawhip: "ffefd5", + peachpuff: "ffdab9", + peru: "cd853f", + pink: "ffc0cb", + plum: "dda0dd", + powderblue: "b0e0e6", + purple: "800080", + red: "f00", + rosybrown: "bc8f8f", + royalblue: "4169e1", + saddlebrown: "8b4513", + salmon: "fa8072", + sandybrown: "f4a460", + seagreen: "2e8b57", + seashell: "fff5ee", + sienna: "a0522d", + silver: "c0c0c0", + skyblue: "87ceeb", + slateblue: "6a5acd", + slategray: "708090", + slategrey: "708090", + snow: "fffafa", + springgreen: "00ff7f", + steelblue: "4682b4", + tan: "d2b48c", + teal: "008080", + thistle: "d8bfd8", + tomato: "ff6347", + turquoise: "40e0d0", + violet: "ee82ee", + wheat: "f5deb3", + white: "fff", + whitesmoke: "f5f5f5", + yellow: "ff0", + yellowgreen: "9acd32", +}; diff --git a/packages/color/src/parse-css.ts b/packages/color/src/parse-css.ts new file mode 100644 index 0000000000..1e39594182 --- /dev/null +++ b/packages/color/src/parse-css.ts @@ -0,0 +1,74 @@ +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 { hslaRgba } from "./hsla-rgba"; +import { int32Rgba } from "./int-rgba"; +import { CSS_NAMES } from "./names"; + +const RE_HEX = /^#?([0-9a-f]{3,8})$/i; +const RE_CSS = /^(rgb|hsl)a?\(\s*([0-9.]+?),\s*([0-9.]+%?),\s*([0-9.]+%?),?\s*([0-9.]+)?\s*\)$/; + +export const parseCss = + (col: string | IDeref) => { + col = typeof col === "string" ? col : col.deref(); + if (col.charAt(0) === "#") { + return int32Rgba([], parseHex(col)); + } else { + const match = RE_CSS.exec(col); + if (match) { + if (match[1] === "rgb" || match[1] === "rgba") { + return [ + parseChannel(match[2]), + parseChannel(match[3]), + parseChannel(match[4]), + maybeParseFloat(match[5], 1) + ]; + } else { + return hslaRgba(null, [ + maybeParseFloat(match[2]) / 360, + parseChannel(match[3]), + parseChannel(match[4]), + maybeParseFloat(match[5], 1) + ]); + } + } else { + const c = CSS_NAMES[col]; + !c && illegalArgs(`invalid color: "${col}"`); + return int32Rgba([], parseHex(c)); + } + } + }; + +export const parseHex = + (src: string): number => { + const match = RE_HEX.exec(src); + if (match) { + const hex = match[1]; + switch (hex.length) { + case 3: { + const [r, g, b] = hex; + return (maybeParseInt(`${r}${r}${g}${g}${b}${b}`, 0, 16) | 0xff000000) >>> 0; + } + case 4: { + const [a, r, g, b] = hex; + return (maybeParseInt(`${a}${a}${r}${r}${g}${g}${b}${b}`, 0, 16)) >>> 0; + } + case 6: + return (maybeParseInt(hex, 0, 16) | 0xff000000) >>> 0; + case 8: + return maybeParseInt(hex, 0, 16) >>> 0; + default: + } + } + illegalArgs(`invalid hex color: "${src}"`); + }; + +const parseChannel = + (c: string) => + clamp01( + c.indexOf("%") > 0 ? + maybeParseFloat(c) * 0.01 : + maybeParseFloat(c) * INV8BIT + ); diff --git a/packages/color/src/porter-duff.ts b/packages/color/src/porter-duff.ts new file mode 100644 index 0000000000..97bba35630 --- /dev/null +++ b/packages/color/src/porter-duff.ts @@ -0,0 +1,174 @@ +import { setC4, setN4 } from "@thi.ng/vectors"; +import { Color, ReadonlyColor } from "./api"; +import { postmultiply, premultiply } from "./premultiply"; + +// http://ssp.impulsetrain.com/porterduff.html +// https://en.wikipedia.org/wiki/Alpha_compositing#Alpha_blending + +/** + * General Porter-Duff HOF operator for **pre-multiplied** RGBA. Use + * `porderDiffP` for applying pre & post multiplication of input and + * output colors. The returned function takes 3 arguments: + * + * - `out` color (if `null` or `undefined` writes to `dest`) + * - `src` color (background) + * - `dest` color (foreground) + * + * Reference: + * https://drafts.fxtf.org/compositing-1/#advancedcompositing + * http://www.svgopen.org/2005/papers/abstractsvgopen/#PorterDuffMap + * + * @param f blend function + * @param x factor of "both" region + * @param y factor of "src" region + * @param z factor of "dest" region + */ +export const porterDuff = ( + f: (s: number, d: number) => number, + x: 0 | 1, + y: 0 | 1, + z: 0 | 1 +) => { + const dot = y ? + z ? + (s: number, d: number, sda: number, sy: number, sz: number) => + f(s, d) * sda + s * sy + d * sz : + (s: number, d: number, sda: number, sy: number) => + f(s, d) * sda + s * sy : + z ? + (s: number, d: number, sda: 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) => { + const sa = src[3]; + const da = dest[3]; + const sda = sa * da; + const sy = y * sa * (1 - da); + const sz = z * da * (1 - sa); + return setC4( + out || dest, + dot(src[0], dest[0], sda, sy, sz), + dot(src[1], dest[1], sda, sy, sz), + dot(src[2], dest[2], sda, sy, sz), + x * sda + sy + sz + ); + }; +}; + +/** + * Like `porterDuff`, but pre-multiplies alpha for both input colors and + * then post-multiplies alpha to output. + * + * @param out + * @param src + * @param dest + * @param mode + */ +export const porterDuffP = ( + out: Color, + src: ReadonlyColor, + dest: ReadonlyColor, + mode: (out: Color, src: ReadonlyColor, dest: ReadonlyColor) => Color +) => + postmultiply(null, mode(null, premultiply([], src), premultiply(out, dest))); + +/** + * Porter-Duff operator. None of the terms are used. Always results in + * [0, 0, 0, 0]. + * + * @see porterDuff + * + * @param out + * @param src + * @param dest + */ +export const composeClear = + (out: Color, _: ReadonlyColor, dest: ReadonlyColor) => + setN4(out || dest, 0); + +/** + * Porter-Duff operator. Always results in `src` color, `dest` ignored. + * + * @see porterDuff + */ +export const composeSrc = porterDuff((s) => s, 1, 1, 0); + +/** + * Porter-Duff operator. Always results in `dest` color, `src` ignored. + * + * @see porterDuff + */ +export const composeDest = porterDuff((_, d) => d, 1, 0, 1); + +/** + * Porter-Duff operator. The source color is placed over the destination + * color. + * + * @see porterDuff + */ +export const composeSrcOver = porterDuff((s) => s, 1, 1, 1); + +/** + * Porter-Duff operator. The destination color is placed over the source + * color. + * + * @see porterDuff + */ +export const composeDestOver = porterDuff((_, d) => d, 1, 1, 1); + +/** + * Porter-Duff operator. The source that overlaps the destination, + * replaces the destination. + * + * @see porterDuff + */ +export const composeSrcIn = porterDuff((s) => s, 1, 0, 0); + +/** + * Porter-Duff operator. The destination that overlaps the source, + * replaces the source. + * + * @see porterDuff + */ +export const composeDestIn = porterDuff((_, d) => d, 1, 0, 0); + +/** + * Porter-Duff operator. The source that does not overlap the + * destination replaces the destination. + * + * @see porterDuff + */ +export const composeSrcOut = porterDuff((s) => s, 0, 1, 0); + +/** + * Porter-Duff operator. The destination that does not overlap the + * source replaces the source. + * + * @see porterDuff + */ +export const composeDestOut = porterDuff((_, d) => d, 0, 0, 1); + +/** + * Porter-Duff operator. The source that overlaps the destination is + * composited with the destination. + * + * @see porterDuff + */ +export const composeSrcAtop = porterDuff((s) => s, 1, 0, 1); + +/** + * Porter-Duff operator. The destination that overlaps the source is + * composited with the source and replaces the destination. + * + * @see porterDuff + */ +export const composeDestAtop = porterDuff((_, d) => d, 1, 1, 0); + +/** + * Porter-Duff operator. The non-overlapping regions of source and + * destination are combined. + * + * @see porterDuff + */ +export const composeXor = porterDuff(() => 0, 0, 1, 1); diff --git a/packages/color/src/premultiply.ts b/packages/color/src/premultiply.ts new file mode 100644 index 0000000000..cac68983b3 --- /dev/null +++ b/packages/color/src/premultiply.ts @@ -0,0 +1,44 @@ +import { set, setC4 } from "@thi.ng/vectors"; +import { Color, ReadonlyColor } from "./api"; + +/** + * RGBA only. Multiplies RGB channels w/ alpha channel. Assumes alpha is + * in [0 .. 1] interval. Does NOT clamp result. + * + * @param out + * @param src + */ +export const premultiply = + (out: Color, src: ReadonlyColor) => { + const a = src[3]; + return setC4( + out || src, + src[0] * a, + src[1] * a, + src[2] * a, + a + ); + }; + +/** + * RGBA only. Reverse operation of `premultiply`. Divides RGB channels + * by alpha, unless alpha is zero. Does NOT clamp result. + * + * @param out + * @param src + */ +export const postmultiply = + (out: Color, src: ReadonlyColor) => { + 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; + }; diff --git a/packages/color/src/rgba-css.ts b/packages/color/src/rgba-css.ts new file mode 100644 index 0000000000..9423234004 --- /dev/null +++ b/packages/color/src/rgba-css.ts @@ -0,0 +1,15 @@ +import { clamp01 } from "@thi.ng/math"; +import { U24 } from "@thi.ng/strings"; +import { FF, ReadonlyColor } from "./api"; +import { ensureAlpha } from "./internal/ensure-alpha"; + +export const rgbaCss = + (src: ReadonlyColor) => { + const r = (clamp01(src[0]) * 0xff + 0.5) | 0; + const g = (clamp01(src[1]) * 0xff + 0.5) | 0; + const b = (clamp01(src[2]) * 0xff + 0.5) | 0; + const a = ensureAlpha(src[3]); + return (a < 1) ? + `rgba(${r},${g},${b},${FF(a)})` : + `#${U24(r << 16 | g << 8 | b)}` + }; diff --git a/packages/color/src/rgba-hcva.ts b/packages/color/src/rgba-hcva.ts new file mode 100644 index 0000000000..ff3f514463 --- /dev/null +++ b/packages/color/src/rgba-hcva.ts @@ -0,0 +1,29 @@ +import { EPS, clamp01 } from "@thi.ng/math"; +import { setC3 } from "@thi.ng/vectors"; +import { Color, ReadonlyColor } from "./api"; +import { clamp } from "./clamp"; + +/** + * Based on: + * https://github.com/tobspr/GLSL-Color-Spaces/blob/master/ColorSpaces.inc.glsl#L159 + * + * @param out + * @param src + */ +export const rgbaHcva = + (out: Color, src: ReadonlyColor) => { + out = clamp(out || src, src); + const p = out[1] < out[2] ? + [out[2], out[1], -1, 2 / 3] : + [out[1], out[2], 0, -1 / 3]; + const q = out[0] < p[0] ? + [p[0], p[1], p[3], out[0]] : + [out[0], p[1], p[2], p[0]]; + const c = q[0] - Math.min(q[1], q[3]); + return setC3( + out, + clamp01(Math.abs((q[3] - q[1]) / (6 * c + EPS) + q[2])), + clamp01(c), + clamp01(q[0]) + ); + }; diff --git a/packages/color/src/rgba-hcya.ts b/packages/color/src/rgba-hcya.ts new file mode 100644 index 0000000000..aa4e2175eb --- /dev/null +++ b/packages/color/src/rgba-hcya.ts @@ -0,0 +1,24 @@ +import { EPS } from "@thi.ng/math"; +import { Color, ReadonlyColor } from "./api"; +import { hueRgba } from "./hue-rgba"; +import { luminanceRGB } from "./luminance-rgb"; +import { rgbaHcva } from "./rgba-hcva"; + +/** + * Ported from: + * https://github.com/tobspr/GLSL-Color-Spaces/blob/master/ColorSpaces.inc.glsl#L226 + * + * @param out + * @param src + */ +export const rgbaHcya = + (out: Color, src: ReadonlyColor) => { + const y = luminanceRGB(src); + out = rgbaHcva(out, src); + const z = luminanceRGB(hueRgba([], out[0])); + out[1] *= y < z ? + z / (y + EPS) : + (1 - z) / (1 + EPS - y); + out[2] = y; + return out; + }; diff --git a/packages/color/src/rgba-hsia.ts b/packages/color/src/rgba-hsia.ts new file mode 100644 index 0000000000..3ee3267207 --- /dev/null +++ b/packages/color/src/rgba-hsia.ts @@ -0,0 +1,33 @@ +import { + atan2Abs, + SQRT3, + TAU, + THIRD +} from "@thi.ng/math"; +import { setC3 } from "@thi.ng/vectors"; +import { Color, ReadonlyColor } 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) => { + out = clamp(out || src, src); + const r = out[0]; + const g = out[1]; + const b = out[2]; + const i = THIRD * (r + g + b); + return i < 1e-6 || (r === g && r === b) ? + setC3(out, 0, 0, i) : + setC3( + out, + atan2Abs( + SQRT32 * (g - b), + 0.5 * (2 * r - g - b) + ) / TAU, + 1 - Math.min(r, g, b) / i, + i + ); + }; diff --git a/packages/color/src/rgba-hsla.ts b/packages/color/src/rgba-hsla.ts new file mode 100644 index 0000000000..7e14ec95c0 --- /dev/null +++ b/packages/color/src/rgba-hsla.ts @@ -0,0 +1,11 @@ +import { EPS } from "@thi.ng/math"; +import { Color, ReadonlyColor } from "./api"; +import { rgbaHcva } from "./rgba-hcva"; + +export const rgbaHsla = + (out: Color, src: ReadonlyColor) => { + out = rgbaHcva(out, src); + out[2] -= out[1] * 0.5; + out[1] /= 1 + EPS - Math.abs(out[2] * 2 - 1); + return out; + }; diff --git a/packages/color/src/rgba-hsva.ts b/packages/color/src/rgba-hsva.ts new file mode 100644 index 0000000000..bda9a16f54 --- /dev/null +++ b/packages/color/src/rgba-hsva.ts @@ -0,0 +1,10 @@ +import { EPS } from "@thi.ng/math"; +import { Color, ReadonlyColor } from "./api"; +import { rgbaHcva } from "./rgba-hcva"; + +export const rgbaHsva = + (out: Color, src: ReadonlyColor) => { + out = rgbaHcva(out, src); + out[1] /= out[2] + EPS; + return out; + }; diff --git a/packages/color/src/rgba-int.ts b/packages/color/src/rgba-int.ts new file mode 100644 index 0000000000..431bbb5cef --- /dev/null +++ b/packages/color/src/rgba-int.ts @@ -0,0 +1,12 @@ +import { clamp01 } from "@thi.ng/math"; +import { ReadonlyColor } from "./api"; +import { ensureAlpha } from "./internal/ensure-alpha"; + +export const rgbaInt = + (src: ReadonlyColor) => + ( + ((ensureAlpha(src[3]) * 0xff) << 24) | + ((clamp01(src[0]) * 0xff) << 16) | + ((clamp01(src[1]) * 0xff) << 8) | + (clamp01(src[2]) * 0xff) + ) >>> 0; diff --git a/packages/color/src/rgba-xyza.ts b/packages/color/src/rgba-xyza.ts new file mode 100644 index 0000000000..4c3103bd3a --- /dev/null +++ b/packages/color/src/rgba-xyza.ts @@ -0,0 +1,17 @@ +import { Color, ReadonlyColor, RGB_XYZ } from "./api"; +import { clamp } from "./clamp"; +import { mulV33 } from "./internal/matrix-ops"; +import { ensureAlpha } from "./internal/ensure-alpha"; + +/** + * https://en.wikipedia.org/wiki/CIE_1931_color_space + * + * @param out + * @param src + */ +export const rgbaXyza = + (out: Color, src: ReadonlyColor) => { + 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 new file mode 100644 index 0000000000..b72787416c --- /dev/null +++ b/packages/color/src/rgba-ycbcra.ts @@ -0,0 +1,16 @@ +import { setC3 } from "@thi.ng/vectors"; +import { Color, ReadonlyColor } from "./api"; +import { clamp } from "./clamp"; +import { luminanceRGB } from "./luminance-rgb"; + +export const rgbaYcbcra = + (out: Color, src: ReadonlyColor) => { + 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 new file mode 100644 index 0000000000..345bb268e7 --- /dev/null +++ b/packages/color/src/rgba.ts @@ -0,0 +1,37 @@ +import { declareIndices, IVector } from "@thi.ng/vectors"; +import { Color, ColorMode } from "./api"; +import { AColor } from "./internal/acolor"; +import { ensureArgs } from "./internal/ensure-args"; + +export function rgba(col: Color): RGBA +export function rgba(r?: number, g?: number, b?: number, a?: number): RGBA; +export function rgba(...args: any[]) { + return new RGBA(ensureArgs(args)); +} + +export class RGBA extends AColor implements + IVector { + + r: number; + g: number; + b: number; + a: number; + + get mode() { + return ColorMode.RGBA; + } + + copy() { + return new RGBA(this.deref()); + } + + copyView() { + return new RGBA(this.buf, this.offset, this.stride); + } + + empty() { + return new RGBA(); + } +} + +declareIndices(RGBA.prototype, ["r", "g", "b", "a"]); diff --git a/packages/color/src/srgba.ts b/packages/color/src/srgba.ts new file mode 100644 index 0000000000..0bfc3258b1 --- /dev/null +++ b/packages/color/src/srgba.ts @@ -0,0 +1,61 @@ +import { setC4 } from "@thi.ng/vectors"; +import { Color, ReadonlyColor, SRGB_ALPHA } from "./api"; +import { ensureAlpha } from "./internal/ensure-alpha"; + +/** + * Maps a single linear RGB channel value to sRGB. + * + * https://en.wikipedia.org/wiki/SRGB + * + * @param x + */ +export const linearSrgb = + (x: number) => + x <= 0.0031308 ? + 12.92 * x : + (1.0 + SRGB_ALPHA) * Math.pow(x, 1.0 / 2.4) - SRGB_ALPHA; + +/** + * Maps a single linear sRGB channel value to linear RGB. + * + * https://en.wikipedia.org/wiki/SRGB + * + * @param x + */ +export const srgbLinear = + (x: number) => + x <= 0.04045 ? + x / 12.92 : + Math.pow((x + SRGB_ALPHA) / (1 + SRGB_ALPHA), 2.4); + +/** + * Converts linear RGB to sRGB. + * + * @param out + * @param src + */ +export const rgbaSrgba = + (out: Color, src: ReadonlyColor) => + setC4( + out || src, + linearSrgb(src[0]), + linearSrgb(src[1]), + linearSrgb(src[2]), + ensureAlpha(src[3]) + ); + +/** + * Converts sRGB to linear RGB. + * + * @param out + * @param src + */ +export const srgbaRgba = + (out: Color, src: ReadonlyColor) => + setC4( + out || src, + srgbLinear(src[0]), + srgbLinear(src[1]), + srgbLinear(src[2]), + ensureAlpha(src[3]) + ); diff --git a/packages/color/src/transform.ts b/packages/color/src/transform.ts new file mode 100644 index 0000000000..e18ecb3fb3 --- /dev/null +++ b/packages/color/src/transform.ts @@ -0,0 +1,197 @@ +import { mix } from "@thi.ng/math"; +import { ColorMatrix, RGB_LUMINANCE, ReadonlyColor, WHITE } from "./api"; +import { mulV45, mulM45 } from "./internal/matrix-ops"; + +// https://drafts.fxtf.org/filter-effects/#feColorMatrixElement + +const S0 = 0.072; +const S1 = 0.213; +const S2 = 0.285; +const S3 = 0.715; +const S4 = 0.787; +const S5 = 0.928; +const S6 = 0.140; +const S7 = 0.143; +const S8 = 0.283; + +/** + * Transforms `src` RGBA color with given matrix and stores result in + * `out` (writes back to `src` if `out` is `null` or `undefined`). + * Unless `clampOut` is false, the result color will be clamped to `[0,1]` + * interval. + * + * @param out + * @param mat + * @param src + * @param clampOut + */ +export const transform = mulV45; + +/** + * Concatenates given color matrices by pairwise multiplying them in + * left-right order. Returns combined result matrix to be used with + * `transform()`. + * + * Note: Using `concat()` is the recommended way when applying multiple + * color transformations in sequence. Since the transforms are combined + * into a single matrix, it is faster than multiple, individual + * `transform()` calls and will also produce more correct results, since + * result color clamping is only applied once at the end (by default, + * unless disabled). + * + * @see transform + * @param mat + * @param xs + */ +export const concat = + (mat: ColorMatrix, ...xs: ColorMatrix[]) => + xs.reduce(mulM45, mat); + +export const IDENTITY: ColorMatrix = + [ + 1, 0, 0, 0, 0, + 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, + 0, 0, 0, 1, 0 + ]; + +/** + * Returns a transformation matrix which subtracts user color from given + * `src` color. With the default color white, this results in the + * inverted color. Does NOT modify alpha channel. + * + * @param src + */ +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 + ]; + +/** + * Returns a transformation matrix which adds the given constant offset + * `x` to RGB channels. Does NOT modify alpha channel. + * + * If `x < 0` results in darker color. + * If `x > 0` results in brighter color. + * + * @param x + */ +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 + ]; + +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 + ]; + +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 + ]; + +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 + ]; + +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, + ]; + }; + +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 + ]; + +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 + ]; + +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 + ]; + +/** + * Returns transformation matrix which computes luminance of user color + * (optionally with custom coefficients). Does NOT modify alpha channel. + * + * @param x + * @param coeffs + */ +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 + ]; + +/** + * Returns transformation matrix which computes luminance of user color + * (optionally with custom coefficients), uses result as alpha channel + * and clears RGB channels (all set to zero). + * + * @param coeffs + */ +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 + ]; diff --git a/packages/color/src/xyza-rgba.ts b/packages/color/src/xyza-rgba.ts new file mode 100644 index 0000000000..1c4eb31855 --- /dev/null +++ b/packages/color/src/xyza-rgba.ts @@ -0,0 +1,12 @@ +import { Color, ReadonlyColor, XYZ_RGB } from "./api"; +import { mulV33 } from "./internal/matrix-ops"; + +/** + * https://en.wikipedia.org/wiki/CIE_1931_color_space + * + * @param out + * @param src + */ +export const xyzaRgba = + (out: Color, src: ReadonlyColor) => + mulV33(out || src, XYZ_RGB, src); diff --git a/packages/color/src/xyza.ts b/packages/color/src/xyza.ts new file mode 100644 index 0000000000..b8edca35fd --- /dev/null +++ b/packages/color/src/xyza.ts @@ -0,0 +1,37 @@ +import { declareIndices, IVector } from "@thi.ng/vectors"; +import { Color, ColorMode } from "./api"; +import { AColor } from "./internal/acolor"; +import { ensureArgs } from "./internal/ensure-args"; + +export function xyza(col: Color): XYZA +export function xyza(x?: number, y?: number, z?: number, a?: number): XYZA; +export function xyza(...args: any[]) { + return new XYZA(ensureArgs(args)); +} + +export class XYZA extends AColor implements + IVector { + + x: number; + y: number; + z: number; + a: number; + + get mode() { + return ColorMode.XYZA; + } + + copy() { + return new XYZA(this.deref()); + } + + copyView() { + return new XYZA(this.buf, this.offset, this.stride); + } + + empty() { + return new XYZA(); + } +} + +declareIndices(XYZA.prototype, ["x", "y", "z", "a"]); diff --git a/packages/color/src/ycbcr.ts b/packages/color/src/ycbcr.ts new file mode 100644 index 0000000000..206f886c89 --- /dev/null +++ b/packages/color/src/ycbcr.ts @@ -0,0 +1,37 @@ +import { declareIndices, IVector } from "@thi.ng/vectors"; +import { Color, ColorMode } from "./api"; +import { AColor } from "./internal/acolor"; +import { ensureArgs } from "./internal/ensure-args"; + +export function ycbcra(col: Color): YCbCrA +export function ycbcra(y: number, b: number, r: number, a?: number): YCbCrA; +export function ycbcra(...args: any[]) { + return new YCbCrA(ensureArgs(args)); +} + +export class YCbCrA extends AColor implements + IVector { + + y: number; + b: number; + r: number; + a: number; + + get mode() { + return ColorMode.YCBCRA; + } + + copy() { + return new YCbCrA(this.deref()); + } + + copyView() { + return new YCbCrA(this.buf, this.offset, this.stride); + } + + empty() { + return new YCbCrA(); + } +} + +declareIndices(YCbCrA.prototype, ["y", "b", "r", "a"]); diff --git a/packages/color/src/ycbcra-rgba.ts b/packages/color/src/ycbcra-rgba.ts new file mode 100644 index 0000000000..62269d26a2 --- /dev/null +++ b/packages/color/src/ycbcra-rgba.ts @@ -0,0 +1,18 @@ +import { clamp01 } from "@thi.ng/math"; +import { setC4 } from "@thi.ng/vectors"; +import { Color, ReadonlyColor } from "./api"; +import { ensureAlpha } from "./internal/ensure-alpha"; + +export const ycbcraRgba = + (out: Color, src: ReadonlyColor) => { + const y = src[0]; + const b = src[1]; + const r = src[2]; + return setC4( + out, + clamp01(y + 1.403 * r), + clamp01(y - 0.344 * b - 0.714 * r), + clamp01(y + 1.770 * b), + ensureAlpha(src[3]) + ); + }; diff --git a/packages/color/test/index.ts b/packages/color/test/index.ts new file mode 100644 index 0000000000..b24042baaf --- /dev/null +++ b/packages/color/test/index.ts @@ -0,0 +1,6 @@ +// import * as assert from "assert"; +// import * as c from "../src/index"; + +describe("color", () => { + it("tests pending"); +}); diff --git a/packages/color/test/tsconfig.json b/packages/color/test/tsconfig.json new file mode 100644 index 0000000000..2c9c12a650 --- /dev/null +++ b/packages/color/test/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../../tsconfig.json", + "compilerOptions": { + "outDir": "../build", + "module": "commonjs", + }, + "include": [ + "./**/*.ts", + "../src/**/*.ts" + ] +} \ No newline at end of file diff --git a/packages/color/tsconfig.json b/packages/color/tsconfig.json new file mode 100644 index 0000000000..bcf03f18b4 --- /dev/null +++ b/packages/color/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": ".", + "module": "es6", + "target": "es6" + }, + "include": [ + "./src/**/*.ts" + ] +} \ No newline at end of file diff --git a/packages/compare/.npmignore b/packages/compare/.npmignore index d703bda97a..67d0c55714 100644 --- a/packages/compare/.npmignore +++ b/packages/compare/.npmignore @@ -1,10 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/compare/CHANGELOG.md b/packages/compare/CHANGELOG.md index 7ffe761e26..11965f328f 100644 --- a/packages/compare/CHANGELOG.md +++ b/packages/compare/CHANGELOG.md @@ -3,6 +3,28 @@ 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/compare@0.1.12...@thi.ng/compare@1.0.0) (2019-01-21) + + +### Build System + +* update package build scripts & outputs, imports in ~50 packages ([b54b703](https://github.com/thi-ng/umbrella/commit/b54b703)) + + +### BREAKING CHANGES + +* enabled multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols. + + + + + ## [0.1.12](https://github.com/thi-ng/umbrella/compare/@thi.ng/compare@0.1.11...@thi.ng/compare@0.1.12) (2018-12-15) **Note:** Version bump only for package @thi.ng/compare diff --git a/packages/compare/package.json b/packages/compare/package.json index 07068a6585..150f858bea 100644 --- a/packages/compare/package.json +++ b/packages/compare/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/compare", - "version": "0.1.12", + "version": "1.0.0", "description": "Comparator with optional delegation for types implementing @thi.ng/api/ICompare interface", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,19 +14,21 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn run clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module compare", + "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 run build && yarn publish --access public", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "keywords": [ @@ -34,5 +38,6 @@ ], "publishConfig": { "access": "public" - } + }, + "sideEffects": false } diff --git a/packages/compare/src/index.ts b/packages/compare/src/index.ts index 3cb0aa864d..32aeca5556 100644 --- a/packages/compare/src/index.ts +++ b/packages/compare/src/index.ts @@ -1,18 +1,19 @@ -export function compare(a: any, b: any): number { - if (a === b) { - return 0; - } - if (a == null) { - return b == null ? 0 : -1; - } - if (b == null) { - return a == null ? 0 : 1; - } - if (typeof a.compare === "function") { - return a.compare(b); - } - if (typeof b.compare === "function") { - return -b.compare(a); - } - return a < b ? -1 : a > b ? 1 : 0; -} +export const compare = + (a: any, b: any): number => { + if (a === b) { + return 0; + } + if (a == null) { + return b == null ? 0 : -1; + } + if (b == null) { + return a == null ? 0 : 1; + } + if (typeof a.compare === "function") { + return a.compare(b); + } + if (typeof b.compare === "function") { + return -b.compare(a); + } + return a < b ? -1 : a > b ? 1 : 0; + }; diff --git a/packages/compare/test/tsconfig.json b/packages/compare/test/tsconfig.json index bcf29ace54..2c9c12a650 100644 --- a/packages/compare/test/tsconfig.json +++ b/packages/compare/test/tsconfig.json @@ -1,10 +1,11 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", "../src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/compare/tsconfig.json b/packages/compare/tsconfig.json index bd6481a5a6..bcf03f18b4 100644 --- a/packages/compare/tsconfig.json +++ b/packages/compare/tsconfig.json @@ -1,9 +1,11 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/compose/.npmignore b/packages/compose/.npmignore index d703bda97a..67d0c55714 100644 --- a/packages/compose/.npmignore +++ b/packages/compose/.npmignore @@ -1,10 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/compose/CHANGELOG.md b/packages/compose/CHANGELOG.md index 4a20608f4a..cace3b7b1d 100644 --- a/packages/compose/CHANGELOG.md +++ b/packages/compose/CHANGELOG.md @@ -3,6 +3,28 @@ 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/compose@0.3.0...@thi.ng/compose@1.0.0) (2019-01-21) + + +### Build System + +* update package build scripts & outputs, imports in ~50 packages ([b54b703](https://github.com/thi-ng/umbrella/commit/b54b703)) + + +### BREAKING CHANGES + +* enabled multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols. + + + + + # [0.3.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/compose@0.2.2...@thi.ng/compose@0.3.0) (2018-12-27) diff --git a/packages/compose/package.json b/packages/compose/package.json index d69c5224a6..29e5d1bd99 100644 --- a/packages/compose/package.json +++ b/packages/compose/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/compose", - "version": "0.3.0", - "description": "Functional composition helpers", - "main": "./index.js", + "version": "1.0.0", + "description": "Arity-optimized functional composition helpers", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,24 +14,26 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn run clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module compose api errors", + "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 run build && yarn publish --access public", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/api": "^4.2.4", - "@thi.ng/errors": "^0.1.12" + "@thi.ng/api": "^5.0.0", + "@thi.ng/errors": "^1.0.0" }, "keywords": [ "composition", @@ -39,5 +43,6 @@ ], "publishConfig": { "access": "public" - } + }, + "sideEffects": false } diff --git a/packages/compose/src/comp.ts b/packages/compose/src/comp.ts index bbd0a4f12a..26903fbfd3 100644 --- a/packages/compose/src/comp.ts +++ b/packages/compose/src/comp.ts @@ -1,5 +1,5 @@ -import { Fn, FnAny } from "@thi.ng/api/api"; -import { illegalArity } from "@thi.ng/errors/illegal-arity"; +import { Fn, FnAny } from "@thi.ng/api"; +import { illegalArity } from "@thi.ng/errors"; /** * Returns the right-to-left composition of given functions. I.e. when diff --git a/packages/compose/src/juxt.ts b/packages/compose/src/juxt.ts index 9c0113be54..4064f77b1c 100644 --- a/packages/compose/src/juxt.ts +++ b/packages/compose/src/juxt.ts @@ -1,4 +1,4 @@ -import { Fn } from "@thi.ng/api/api"; +import { Fn } from "@thi.ng/api"; export function juxt(a: Fn): Fn; export function juxt(a: Fn, b: Fn): Fn; diff --git a/packages/compose/src/partial.ts b/packages/compose/src/partial.ts index d8ba1c883d..b8bd0e82bd 100644 --- a/packages/compose/src/partial.ts +++ b/packages/compose/src/partial.ts @@ -1,4 +1,4 @@ -import { illegalArgs } from "@thi.ng/errors/illegal-arguments"; +import { illegalArgs } from "@thi.ng/errors"; export function partial(fn: (a: A, ...args: any[]) => T, a: A): (...args: any[]) => T; export function partial(fn: (a: A, b: B, ...args: any[]) => T, a: A, b: B): (...args: any[]) => T; diff --git a/packages/compose/src/thread-first.ts b/packages/compose/src/thread-first.ts index fbb77209e7..a4fad7a5c8 100644 --- a/packages/compose/src/thread-first.ts +++ b/packages/compose/src/thread-first.ts @@ -1,4 +1,4 @@ -import { FnAny } from "@thi.ng/api/api"; +import { FnAny } from "@thi.ng/api"; /** * Takes an `init` value and a number of functions and/or function @@ -26,13 +26,13 @@ import { FnAny } from "@thi.ng/api/api"; * @param init * @param fns */ -export function threadFirst(init: any, ...fns: (FnAny | [FnAny, ...any[]])[]) { - return fns.reduce( - (acc, expr) => - typeof expr === "function" ? - expr(acc) : - expr[0](acc, ...expr.slice(1)) - , - init - ); -} +export const threadFirst = + (init: any, ...fns: (FnAny | [FnAny, ...any[]])[]) => + fns.reduce( + (acc, expr) => + typeof expr === "function" ? + expr(acc) : + expr[0](acc, ...expr.slice(1)) + , + init + ); diff --git a/packages/compose/src/thread-last.ts b/packages/compose/src/thread-last.ts index 3502d21b69..24a511445a 100644 --- a/packages/compose/src/thread-last.ts +++ b/packages/compose/src/thread-last.ts @@ -1,4 +1,4 @@ -import { FnAny } from "@thi.ng/api/api"; +import { FnAny } from "@thi.ng/api"; /** * Takes an `init` value and a number of functions and/or function @@ -26,13 +26,13 @@ import { FnAny } from "@thi.ng/api/api"; * @param init * @param fns */ -export function threadLast(init: any, ...fns: (FnAny | [FnAny, ...any[]])[]) { - return fns.reduce( - (acc, expr) => - typeof expr === "function" ? - expr(acc) : - expr[0](...expr.slice(1), acc) - , - init - ); -} +export const threadLast = + (init: any, ...fns: (FnAny | [FnAny, ...any[]])[]) => + fns.reduce( + (acc, expr) => + typeof expr === "function" ? + expr(acc) : + expr[0](...expr.slice(1), acc) + , + init + ); diff --git a/packages/compose/test/tsconfig.json b/packages/compose/test/tsconfig.json index bcf29ace54..2c9c12a650 100644 --- a/packages/compose/test/tsconfig.json +++ b/packages/compose/test/tsconfig.json @@ -1,10 +1,11 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", "../src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/compose/tsconfig.json b/packages/compose/tsconfig.json index bd6481a5a6..bcf03f18b4 100644 --- a/packages/compose/tsconfig.json +++ b/packages/compose/tsconfig.json @@ -1,9 +1,11 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/csp/.npmignore b/packages/csp/.npmignore index d703bda97a..67d0c55714 100644 --- a/packages/csp/.npmignore +++ b/packages/csp/.npmignore @@ -1,10 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/csp/CHANGELOG.md b/packages/csp/CHANGELOG.md index bd988ac80e..f0b4a64cc0 100644 --- a/packages/csp/CHANGELOG.md +++ b/packages/csp/CHANGELOG.md @@ -3,6 +3,33 @@ 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/csp@0.3.79...@thi.ng/csp@1.0.0) (2019-01-21) + + +### Bug Fixes + +* **csp:** disable __State reverse enum lookup ([3b8576f](https://github.com/thi-ng/umbrella/commit/3b8576f)) + + +### Build System + +* update package build scripts & outputs, imports in ~50 packages ([b54b703](https://github.com/thi-ng/umbrella/commit/b54b703)) + + +### BREAKING CHANGES + +* enabled multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols. + + + + + ## [0.3.79](https://github.com/thi-ng/umbrella/compare/@thi.ng/csp@0.3.78...@thi.ng/csp@0.3.79) (2019-01-02) **Note:** Version bump only for package @thi.ng/csp diff --git a/packages/csp/package.json b/packages/csp/package.json index ab83c33fad..2c60fe129a 100644 --- a/packages/csp/package.json +++ b/packages/csp/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/csp", - "version": "0.3.79", + "version": "1.0.0", "description": "ES6 promise based CSP implementation", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,12 +14,14 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc utils", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module csp api checks dcons errors transducers", + "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", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/index.js", "testasync": "tsc -p test && node build/test/async.js", "testfile": "tsc -p test && node build/test/file.js", "testgraph": "tsc -p test && node build/test/graph.js", @@ -28,15 +32,15 @@ "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/api": "^4.2.4", - "@thi.ng/checks": "^1.5.14", - "@thi.ng/dcons": "^1.1.23", - "@thi.ng/errors": "^0.1.12", - "@thi.ng/transducers": "^2.3.2" + "@thi.ng/api": "^5.0.0", + "@thi.ng/checks": "^2.0.0", + "@thi.ng/dcons": "^2.0.0", + "@thi.ng/errors": "^1.0.0", + "@thi.ng/transducers": "^3.0.0" }, "keywords": [ "async", @@ -53,5 +57,6 @@ ], "publishConfig": { "access": "public" - } + }, + "sideEffects": false } diff --git a/packages/csp/src/api.ts b/packages/csp/src/api.ts index 12326397bc..b38084f7b6 100644 --- a/packages/csp/src/api.ts +++ b/packages/csp/src/api.ts @@ -1,5 +1,4 @@ -import { IID, ILength, IRelease } from "@thi.ng/api/api"; - +import { IID, ILength, IRelease } from "@thi.ng/api"; import { Channel } from "./channel"; export const enum State { @@ -11,7 +10,7 @@ export const enum State { /** * Reverse lookup for `State` enums */ -export const __State = (exports).State; +// export const __State = (exports).State; export interface ChannelItem { value: () => Promise; diff --git a/packages/csp/src/buffer.ts b/packages/csp/src/buffer.ts index 98cc936b26..0162e55234 100644 --- a/packages/csp/src/buffer.ts +++ b/packages/csp/src/buffer.ts @@ -1,8 +1,8 @@ import { DCons } from "@thi.ng/dcons"; - import { ChannelItem, IBuffer } from "./api"; -export class FixedBuffer implements IBuffer { +export class FixedBuffer implements + IBuffer { buf: DCons>; limit: number; diff --git a/packages/csp/src/channel.ts b/packages/csp/src/channel.ts index 9b8e48bea4..1b82f0f929 100644 --- a/packages/csp/src/channel.ts +++ b/packages/csp/src/channel.ts @@ -1,13 +1,16 @@ -import { Predicate } from "@thi.ng/api/api"; -import { illegalArity } from "@thi.ng/errors/illegal-arity"; -import { isFunction } from "@thi.ng/checks/is-function"; +import { Predicate } from "@thi.ng/api"; +import { isFunction } from "@thi.ng/checks"; import { DCons } from "@thi.ng/dcons"; -import { Reducer, Transducer } from "@thi.ng/transducers/api"; -import { cycle } from "@thi.ng/transducers/iter/cycle"; -import { range } from "@thi.ng/transducers/iter/range"; -import { isReduced, unreduced } from "@thi.ng/transducers/reduced"; -import { delayed } from "@thi.ng/transducers/xform/delayed"; - +import { illegalArity } from "@thi.ng/errors"; +import { + cycle, + delayed, + isReduced, + range, + Reducer, + Transducer, + unreduced +} from "@thi.ng/transducers"; import { ChannelItem, ErrorHandler, @@ -561,10 +564,9 @@ export class Channel implements } } -function defaultErrorHandler(e: Error, chan: Channel, val?: any) { - console.log(chan.id, "error occurred", e.message, (val !== undefined ? val : "")); -} +const defaultErrorHandler = + (e: Error, chan: Channel, val?: any) => + console.log(chan.id, "error occurred", e.message, (val !== undefined ? val : "")); -function maybeBuffer(x) { - return x instanceof FixedBuffer || typeof x === "number"; -} +const maybeBuffer = (x) => + x instanceof FixedBuffer || typeof x === "number"; diff --git a/packages/csp/src/mult.ts b/packages/csp/src/mult.ts index a5d09addb7..3907574af6 100644 --- a/packages/csp/src/mult.ts +++ b/packages/csp/src/mult.ts @@ -1,7 +1,6 @@ -import { illegalArity } from "@thi.ng/errors/illegal-arity"; import { DCons } from "@thi.ng/dcons"; -import { Transducer } from "@thi.ng/transducers/api"; - +import { illegalArity } from "@thi.ng/errors"; +import { Transducer } from "@thi.ng/transducers"; import { IWriteableChannel } from "./api"; import { Channel } from "./channel"; diff --git a/packages/csp/src/pubsub.ts b/packages/csp/src/pubsub.ts index 56820e6163..a0f33c9815 100644 --- a/packages/csp/src/pubsub.ts +++ b/packages/csp/src/pubsub.ts @@ -1,7 +1,6 @@ -import { IObjectOf } from "@thi.ng/api/api"; -import { illegalArity } from "@thi.ng/errors/illegal-arity"; -import { Transducer } from "@thi.ng/transducers/api"; - +import { IObjectOf } from "@thi.ng/api"; +import { illegalArity } from "@thi.ng/errors"; +import { Transducer } from "@thi.ng/transducers"; import { IWriteableChannel, TopicFn } from "./api"; import { Channel } from "./channel"; import { Mult } from "./mult"; diff --git a/packages/csp/src/utils/shuffle.ts b/packages/csp/src/utils/shuffle.ts index 5c23da9c24..14ff0f63fd 100644 --- a/packages/csp/src/utils/shuffle.ts +++ b/packages/csp/src/utils/shuffle.ts @@ -1,13 +1,14 @@ -export function shuffle(items: T[]) { - let n = items.length; - if (n > 1) { - while (n > 0) { - const i = (Math.random() * n) | 0; - n--; - const t = items[i]; - items[i] = items[n]; - items[n] = t; +export const shuffle = + (items: T[]) => { + let n = items.length; + if (n > 1) { + while (n > 0) { + const i = (Math.random() * n) | 0; + n--; + const t = items[i]; + items[i] = items[n]; + items[n] = t; + } } - } - return items; -} + return items; + }; diff --git a/packages/csp/test/node.ts b/packages/csp/test/node.ts index 4af2ecdeba..af20a74836 100644 --- a/packages/csp/test/node.ts +++ b/packages/csp/test/node.ts @@ -1,11 +1,10 @@ -import { IEnable, IID, IObjectOf } from "@thi.ng/api/api"; -import { implementsFunction } from "@thi.ng/checks/implements-function"; -// import { DCons } from "@thi.ng/dcons"; +import { IEnable, IID, IObjectOf } from "@thi.ng/api"; +import { implementsFunction } from "@thi.ng/checks"; import * as tx from "@thi.ng/transducers"; - import { IBuffer, IWriteableChannel } from "../src/api"; 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 NodeOutput = NodeOutputSpec | IWriteableChannel; diff --git a/packages/csp/test/tsconfig.json b/packages/csp/test/tsconfig.json index 13d45669e5..2c9c12a650 100644 --- a/packages/csp/test/tsconfig.json +++ b/packages/csp/test/tsconfig.json @@ -1,7 +1,8 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", diff --git a/packages/csp/tsconfig.json b/packages/csp/tsconfig.json index f6c291a0a0..bcf03f18b4 100644 --- a/packages/csp/tsconfig.json +++ b/packages/csp/tsconfig.json @@ -1,7 +1,9 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" diff --git a/packages/dcons/.npmignore b/packages/dcons/.npmignore index d703bda97a..67d0c55714 100644 --- a/packages/dcons/.npmignore +++ b/packages/dcons/.npmignore @@ -1,10 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/dcons/CHANGELOG.md b/packages/dcons/CHANGELOG.md index f2779c8b8a..292515d22c 100644 --- a/packages/dcons/CHANGELOG.md +++ b/packages/dcons/CHANGELOG.md @@ -3,6 +3,28 @@ 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/dcons@1.1.23...@thi.ng/dcons@2.0.0) (2019-01-21) + + +### Build System + +* update package build scripts & outputs, imports in ~50 packages ([b54b703](https://github.com/thi-ng/umbrella/commit/b54b703)) + + +### BREAKING CHANGES + +* enabled multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols. + + + + + ## [1.1.23](https://github.com/thi-ng/umbrella/compare/@thi.ng/dcons@1.1.22...@thi.ng/dcons@1.1.23) (2019-01-02) **Note:** Version bump only for package @thi.ng/dcons diff --git a/packages/dcons/package.json b/packages/dcons/package.json index 08bde1a5eb..b82571e97d 100644 --- a/packages/dcons/package.json +++ b/packages/dcons/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/dcons", - "version": "1.1.23", + "version": "2.0.0", "description": "Comprehensive doubly linked list structure w/ iterator support", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,28 +14,30 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module dcons api checks compare equiv errors transducers", + "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", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/api": "^4.2.4", - "@thi.ng/checks": "^1.5.14", - "@thi.ng/compare": "^0.1.12", - "@thi.ng/equiv": "^0.1.15", - "@thi.ng/errors": "^0.1.12", - "@thi.ng/transducers": "^2.3.2" + "@thi.ng/api": "^5.0.0", + "@thi.ng/checks": "^2.0.0", + "@thi.ng/compare": "^1.0.0", + "@thi.ng/equiv": "^1.0.0", + "@thi.ng/errors": "^1.0.0", + "@thi.ng/transducers": "^3.0.0" }, "keywords": [ "datastructure", @@ -48,5 +52,6 @@ ], "publishConfig": { "access": "public" - } + }, + "sideEffects": false } diff --git a/packages/dcons/src/index.ts b/packages/dcons/src/index.ts index 97686dbd57..a861aae749 100644 --- a/packages/dcons/src/index.ts +++ b/packages/dcons/src/index.ts @@ -8,14 +8,12 @@ import { IRelease, IStack, Predicate -} from "@thi.ng/api/api"; -import { isArrayLike } from "@thi.ng/checks/is-arraylike"; +} from "@thi.ng/api"; +import { isArrayLike } from "@thi.ng/checks"; import { compare } from "@thi.ng/compare"; import { equiv } from "@thi.ng/equiv"; -import { illegalArgs } from "@thi.ng/errors/illegal-arguments"; -import { illegalState } from "@thi.ng/errors/illegal-state"; -import { IReducible, ReductionFn } from "@thi.ng/transducers/api"; -import { isReduced } from "@thi.ng/transducers/reduced"; +import { illegalArgs, illegalState } from "@thi.ng/errors"; +import { IReducible, isReduced, ReductionFn } from "@thi.ng/transducers"; export interface ConsCell { value: T; diff --git a/packages/dcons/test/tsconfig.json b/packages/dcons/test/tsconfig.json index 13d45669e5..2c9c12a650 100644 --- a/packages/dcons/test/tsconfig.json +++ b/packages/dcons/test/tsconfig.json @@ -1,7 +1,8 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", diff --git a/packages/dcons/tsconfig.json b/packages/dcons/tsconfig.json index f6c291a0a0..bcf03f18b4 100644 --- a/packages/dcons/tsconfig.json +++ b/packages/dcons/tsconfig.json @@ -1,7 +1,9 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" diff --git a/packages/defmulti/.npmignore b/packages/defmulti/.npmignore index d703bda97a..67d0c55714 100644 --- a/packages/defmulti/.npmignore +++ b/packages/defmulti/.npmignore @@ -1,10 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/defmulti/CHANGELOG.md b/packages/defmulti/CHANGELOG.md index 58f149726d..9e6b30d57b 100644 --- a/packages/defmulti/CHANGELOG.md +++ b/packages/defmulti/CHANGELOG.md @@ -3,6 +3,35 @@ 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/defmulti@0.7.0...@thi.ng/defmulti@1.0.0) (2019-01-21) + + +### Build System + +* update package build scripts & outputs, imports in ~50 packages ([b54b703](https://github.com/thi-ng/umbrella/commit/b54b703)) + + +### Features + +* **defmulti:** add callable() & implementations(), update readme ([fde2db2](https://github.com/thi-ng/umbrella/commit/fde2db2)) +* **defmulti:** add relations() ([4066c80](https://github.com/thi-ng/umbrella/commit/4066c80)) +* **defmulti:** add versions w/ 1 optional typed arg, add .impls() ([125c784](https://github.com/thi-ng/umbrella/commit/125c784)) + + +### BREAKING CHANGES + +* enabled multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols. + + + + + # [0.7.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/defmulti@0.6.0...@thi.ng/defmulti@0.7.0) (2019-01-02) diff --git a/packages/defmulti/README.md b/packages/defmulti/README.md index 0e6e55e5c0..e1ec641b64 100644 --- a/packages/defmulti/README.md +++ b/packages/defmulti/README.md @@ -28,7 +28,7 @@ yarn add @thi.ng/defmulti ## API -### defmulti +### defmulti() `defmulti` returns a new multi-dispatch function using the provided dispatcher function. The dispatcher acts as a mapping function, can take @@ -43,9 +43,19 @@ return type) and the generics will also apply to all implementations. If more than 8 args are required, `defmulti` will fall back to an untyped varargs solution. -Implementations for different dispatch values can be added and removed -dynamically by calling `.add(id, fn)` or `.remove(id)` on the returned -function. +The function returned by `defmulti` can be called like any other +function, but also exposes the following operations: + +- `.add(id, fn)` - adds new implementation for given dispatch value +- `.remove(id)` - removes implementation for dispatch value +- `.callable(...args)` - takes same args as if calling the + multi-function, but only checks if an implementation exists for the + given args. Returns boolean. +- `.isa(child, parent)` - establish dispatch value relationship hierarchy +- `.impls()` - returns set of all dispatch values which have an implementation +- `.rels()` - return all dispatch value relationships +- `.parents(id)` - direct parents of dispatch value `id` +- `.ancestors(id)` - transitive parents of dispatch value `id` #### Dispatch value hierarchies @@ -83,9 +93,15 @@ foo.ancestors(1); // Set { } foo.add("odd", (x) => `${x} is odd`); foo.add("number", (x) => `${x} is a number`); +// dispatch values w/ implementations +foo.impls(); +// Set { "odd", "even", "number", "23", "42" } + foo(23); // "23 is odd" foo(42); // "42 is a number" foo(1); // error (missing impl & no default) + +foo.callable(1) // false ``` Same example, but with relationships provided as argument to `defmulti`: @@ -105,7 +121,63 @@ foo.rels(); // even: Set { "number" } } ``` -### defmultiN +### implementations() + +Syntax-sugar intended for sets of multi-methods sharing same dispatch +values / logic. Takes a dispatch value, an object of "is-a" +relationships and a number of multi-methods, each with an implementation +for the given dispatch value. + +The relations object has dispatch values (parents) as keys and arrays of +multi-methods as their values. For each multi-method associates the +given `type` with the related parent dispatch value to delegate to its +implementation (see `.isa()` above). + +The remaining implementations are associated with their related +multi-method and the given `type` dispatch value. + +```ts +foo = defmulti((x) => x.id); +bar = defmulti((x) => x.id); +bax = defmulti((x) => x.id); +baz = defmulti((x) => x.id); + +// define impls for dispatch value `a` +implementations( + "a", + + // delegate bax & baz impls to dispatch val `b` + { + b: [bax, baz] + }, + + // concrete multi-fn impls + foo, + (x) => `foo: ${x.val}`, + bar, + (x) => `bar: ${x.val.toUpperCase()}` +); + +// some parent impls for bax & baz +bax.add("b", (x) => `bax: ${x.id}`); +baz.add("c", (x) => `baz: ${x.id}`); + +// delegate to use "c" impl for "b" +baz.isa("b", "c"); + +foo({ id: "a", val: "alice" }); // "foo: alice" +bar({ id: "a", val: "alice" }); // "bar: ALICE" +bax({ id: "a", val: "alice" }); // "bax: a" +baz({ id: "a", val: "alice" }); // "baz: a" + +baz.impls(); // Set { "c", "a", "b" } +``` + +Also see the WIP package +[@thi.ng/geom](https://github.com/thi-ng/umbrella/tree/master/packages/geom) +for a concreate realworld usage example. + +### defmultiN() Returns a multi-dispatch function which delegates to one of the provided implementations, based on the arity (number of args) when the function diff --git a/packages/defmulti/package.json b/packages/defmulti/package.json index 67882086ac..9f12d45b34 100644 --- a/packages/defmulti/package.json +++ b/packages/defmulti/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/defmulti", - "version": "0.7.0", + "version": "1.0.0", "description": "Dynamically extensible multiple dispatch via user supplied dispatch function.", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,24 +14,26 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn run clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module defmulti api errors", + "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 run build && yarn publish --access public", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/api": "^4.2.4", - "@thi.ng/errors": "^0.1.12" + "@thi.ng/api": "^5.0.0", + "@thi.ng/errors": "^1.0.0" }, "keywords": [ "ES6", @@ -37,5 +41,6 @@ ], "publishConfig": { "access": "public" - } + }, + "sideEffects": false } diff --git a/packages/defmulti/src/index.ts b/packages/defmulti/src/index.ts index 202714b8f7..d0302e34f0 100644 --- a/packages/defmulti/src/index.ts +++ b/packages/defmulti/src/index.ts @@ -1,28 +1,43 @@ -import { IObjectOf } from "@thi.ng/api/api"; -import { unsupported } from "@thi.ng/errors/unsupported"; -import { illegalArity } from "@thi.ng/errors/illegal-arity"; +import { IObjectOf } from "@thi.ng/api"; +import { illegalArgs, unsupported, illegalArity } from "@thi.ng/errors"; export const DEFAULT: unique symbol = Symbol(); export type DispatchFn = (...args) => PropertyKey; -export type DispatchFn1 = (a: A, ...xs: any[]) => PropertyKey; -export type DispatchFn2 = (a: A, b: B, ...xs: any[]) => PropertyKey; -export type DispatchFn3 = (a: A, b: B, c: C, ...xs: any[]) => PropertyKey; -export type DispatchFn4 = (a: A, b: B, c: C, d: D, ...xs: any[]) => PropertyKey; -export type DispatchFn5 = (a: A, b: B, c: C, d: D, e: E, ...xs: any[]) => PropertyKey; -export type DispatchFn6 = (a: A, b: B, c: C, d: D, e: E, f: F, ...xs: any[]) => PropertyKey; -export type DispatchFn7 = (a: A, b: B, c: C, d: D, e: E, f: F, g: G, ...xs: any[]) => PropertyKey; -export type DispatchFn8 = (a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, ...xs: any[]) => PropertyKey; +export type DispatchFn1 = (a: A) => PropertyKey; +export type DispatchFn1O = (a: A, b?: B) => PropertyKey; +export type DispatchFn2 = (a: A, b: B) => PropertyKey; +export type DispatchFn2O = (a: A, b: B, c?: C) => PropertyKey; +export type DispatchFn3 = (a: A, b: B, c: C) => PropertyKey; +export type DispatchFn3O = (a: A, b: B, c: C, d?: D) => PropertyKey; +export type DispatchFn4 = (a: A, b: B, c: C, d: D) => PropertyKey; +export type DispatchFn4O = (a: A, b: B, c: C, d: D, e?: E) => PropertyKey; +export type DispatchFn5 = (a: A, b: B, c: C, d: D, e: E) => PropertyKey; +export type DispatchFn5O = (a: A, b: B, c: C, d: D, e: E, f?: F) => PropertyKey; +export type DispatchFn6 = (a: A, b: B, c: C, d: D, e: E, f: F) => PropertyKey; +export type DispatchFn6O = (a: A, b: B, c: C, d: D, e: E, f: F, g?: G) => PropertyKey; +export type DispatchFn7 = (a: A, b: B, c: C, d: D, e: E, f: F, g: G) => PropertyKey; +export type DispatchFn7O = (a: A, b: B, c: C, d: D, e: E, f: F, g: G, h?: H) => PropertyKey; +export type DispatchFn8 = (a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H) => PropertyKey; +export type DispatchFn8O = (a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i?: I) => PropertyKey; export type Implementation = (...args: any[]) => T; -export type Implementation1 = (a: A, ...xs: any[]) => T; -export type Implementation2 = (a: A, b: B, ...xs: any[]) => T; -export type Implementation3 = (a: A, b: B, c: C, ...xs: any[]) => T; -export type Implementation4 = (a: A, b: B, c: C, d: D, ...xs: any[]) => T; -export type Implementation5 = (a: A, b: B, c: C, d: D, e: E, ...xs: any[]) => T; -export type Implementation6 = (a: A, b: B, c: C, d: D, e: E, f: F, ...xs: any[]) => T; -export type Implementation7 = (a: A, b: B, c: C, d: D, e: E, f: F, g: G, ...xs: any[]) => T; -export type Implementation8 = (a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, ...xs: any[]) => T; +export type Implementation1 = (a: A) => T; +export type Implementation1O = (a: A, b?: B) => T; +export type Implementation2 = (a: A, b: B) => T; +export type Implementation2O = (a: A, b: B, c?: C) => T; +export type Implementation3 = (a: A, b: B, c: C) => T; +export type Implementation3O = (a: A, b: B, c: C, d?: D) => T; +export type Implementation4 = (a: A, b: B, c: C, d: D) => T; +export type Implementation4O = (a: A, b: B, c: C, d: D, e?: E) => T; +export type Implementation5 = (a: A, b: B, c: C, d: D, e: E) => T; +export type Implementation5O = (a: A, b: B, c: C, d: D, e: E, f?: F) => T; +export type Implementation6 = (a: A, b: B, c: C, d: D, e: E, f: F) => T; +export type Implementation6O = (a: A, b: B, c: C, d: D, e: E, f: F, g?: G) => T; +export type Implementation7 = (a: A, b: B, c: C, d: D, e: E, f: F, g: G) => T; +export type Implementation7O = (a: A, b: B, c: C, d: D, e: E, f: F, g: G, h?: H) => T; +export type Implementation8 = (a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H) => T; +export type Implementation8O = (a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i?: I) => T; export interface MultiFnBase { /** @@ -50,6 +65,17 @@ export interface MultiFnBase { * @param id */ remove(id: PropertyKey): boolean; + /** + * Returns true, if the function is callable (has a valid + * implementation) for given arguments. + * + * @param args + */ + callable(...args: any[]): boolean; + /** + * Returns a set of all registered dispatch values. + */ + impls(): Set; /** * Updates dispatch hierarchy by declaring dispatch value `id` to * delegate to `parent`'s implementation. I.e. in terms of dispatch @@ -88,34 +114,66 @@ export interface MultiFn1 extends Implementation1, MultiFnBase> { } +export interface MultiFn1O extends + Implementation1O, + MultiFnBase> { } + export interface MultiFn2 extends Implementation2, MultiFnBase> { } +export interface MultiFn2O extends + Implementation2O, + MultiFnBase> { } + export interface MultiFn3 extends Implementation3, MultiFnBase> { } +export interface MultiFn3O extends + Implementation3O, + MultiFnBase> { } + export interface MultiFn4 extends Implementation4, MultiFnBase> { } +export interface MultiFn4O extends + Implementation4O, + MultiFnBase> { } + export interface MultiFn5 extends Implementation5, MultiFnBase> { } +export interface MultiFn5O extends + Implementation5O, + MultiFnBase> { } + export interface MultiFn6 extends Implementation6, MultiFnBase> { } +export interface MultiFn6O extends + Implementation6O, + MultiFnBase> { } + export interface MultiFn7 extends Implementation7, MultiFnBase> { } +export interface MultiFn7O extends + Implementation7O, + MultiFnBase> { } + export interface MultiFn8 extends Implementation8, MultiFnBase> { } +export interface MultiFn8O extends + Implementation8O, + MultiFnBase> { } + export type AncestorDefs = IObjectOf>; /** @@ -140,13 +198,21 @@ export type AncestorDefs = IObjectOf>; export function defmulti(f: DispatchFn, rels?: AncestorDefs): MultiFn; export function defmulti(f: DispatchFn1, rels?: AncestorDefs): MultiFn1; export function defmulti(f: DispatchFn2, rels?: AncestorDefs): MultiFn2; +export function defmulti(f: DispatchFn1O, rels?: AncestorDefs): MultiFn1O; export function defmulti(f: DispatchFn3, rels?: AncestorDefs): MultiFn3; +export function defmulti(f: DispatchFn2O, rels?: AncestorDefs): MultiFn2O; export function defmulti(f: DispatchFn4, rels?: AncestorDefs): MultiFn4; +export function defmulti(f: DispatchFn3O, rels?: AncestorDefs): MultiFn3O; export function defmulti(f: DispatchFn5, rels?: AncestorDefs): MultiFn5; +export function defmulti(f: DispatchFn4O, rels?: AncestorDefs): MultiFn4O; export function defmulti(f: DispatchFn6, rels?: AncestorDefs): MultiFn6; +export function defmulti(f: DispatchFn5O, rels?: AncestorDefs): MultiFn5O; export function defmulti(f: DispatchFn7, rels?: AncestorDefs): MultiFn7; +export function defmulti(f: DispatchFn6O, rels?: AncestorDefs): MultiFn6O; export function defmulti(f: DispatchFn8, rels?: AncestorDefs): MultiFn8; -export function defmulti(f: any, ancestors?: AncestorDefs): MultiFn { +export function defmulti(f: DispatchFn7O, rels?: AncestorDefs): MultiFn7O; +export function defmulti(f: DispatchFn8O, rels?: AncestorDefs): MultiFn8O; +export function defmulti(f: any, ancestors?: AncestorDefs) { const impls: IObjectOf> = {}; const rels: IObjectOf> = ancestors ? makeRels(ancestors) : {}; const fn: any = (...args) => { @@ -171,18 +237,34 @@ export function defmulti(f: any, ancestors?: AncestorDefs): MultiFn { delete impls[id]; return true; }; + fn.callable = (...args: any[]) => { + const id = f(...args); + return !!(impls[id] || findImpl(impls, rels, id) || impls[DEFAULT]); + }; fn.isa = (id: PropertyKey, parent: PropertyKey) => { let val = rels[id]; !val && (rels[id] = val = new Set()); val.add(parent); }; + fn.impls = () => { + const res = new Set(Object.keys(impls)); + for (let id in rels) { + findImpl(impls, rels, id) && res.add(id); + } + impls[DEFAULT] && res.add(DEFAULT); + return res; + }; fn.rels = () => rels; fn.parents = (id: PropertyKey) => rels[id]; fn.ancestors = (id: PropertyKey) => new Set(findAncestors([], rels, id)); return fn; }; -const findImpl = (impls: IObjectOf>, rels: IObjectOf>, id: PropertyKey) => { +const findImpl = ( + impls: IObjectOf>, + rels: IObjectOf>, + id: PropertyKey +) => { const parents = rels[id]; if (!parents) return; for (let p of parents) { @@ -191,7 +273,11 @@ const findImpl = (impls: IObjectOf>, rels: IObjectOf>, id: PropertyKey) => { +const findAncestors = ( + acc: PropertyKey[], + rels: IObjectOf>, + id: PropertyKey +) => { const parents = rels[id]; if (parents) { for (let p of parents) { @@ -202,14 +288,15 @@ const findAncestors = (acc: PropertyKey[], rels: IObjectOf>, id return acc; }; -const makeRels = (spec: AncestorDefs) => { - const rels: IObjectOf> = {}; - for (let k in spec) { - const val = spec[k]; - rels[k] = val instanceof Set ? val : new Set(val); - } - return rels; -}; +const makeRels = + (spec: AncestorDefs) => { + const rels: IObjectOf> = {}; + for (let k in spec) { + const val = spec[k]; + rels[k] = val instanceof Set ? val : new Set(val); + } + return rels; + }; /** * Returns a multi-dispatch function which delegates to one of the @@ -247,14 +334,86 @@ const makeRels = (spec: AncestorDefs) => { * @param impls * @param fallback */ -export function defmultiN( +export const defmultiN = ( impls: { [id: number]: Implementation }, fallback?: Implementation -) { +) => { const fn = defmulti((...args: any[]) => args.length); fn.add(DEFAULT, fallback || ((...args) => illegalArity(args.length))); for (let id in impls) { fn.add(id, impls[id]); } return fn; -} +}; + +/** + * Syntax-sugar intended for sets of multi-methods sharing same dispatch + * values / logic. Takes a dispatch value, an object of "is-a" + * relationships and a number of multi-methods, each with an + * implementation for the given dispatch value. + * + * The relations object has dispatch values (parents) as keys and arrays + * of multi-methods as their values. For each multi-method associates + * the given `type` with the related parent dispatch value to delegate + * to its implementation. + * + * The remaining implementations are associated with their related + * multi-method and the given `type` dispatch value. + * + * ``` + * foo = defmulti((x) => x.id); + * bar = defmulti((x) => x.id); + * bax = defmulti((x) => x.id); + * baz = defmulti((x) => x.id); + * + * // define impls for dispatch value `a` + * implementations( + * "a", + * + * // delegate bax & baz impls to dispatch val `b` + * { + * b: [bax, baz] + * }, + * + * // concrete multi-fn impls + * foo, + * (x) => `foo: ${x.val}`, + * + * bar, + * (x) => `bar: ${x.val.toUpperCase()}` + * ); + * + * // add parent impls + * bax.add("b", (x) => `bax: ${x.id}`); + * baz.add("c", (x) => `baz: ${x.id}`); + * // use "c" impl for "b" + * baz.isa("b", "c"); + * + * foo({ id: "a", val: "alice" }); // "foo: alice" + * bar({ id: "a", val: "alice" }); // "bar: ALICE" + * bax({ id: "a", val: "alice" }); // "bax: a" + * baz({ id: "a", val: "alice" }); // "baz: a" + * + * baz.impls(); // Set { "c", "a", "b" } + * ``` + * + * @param type + * @param impls + */ +export const implementations = ( + type: PropertyKey, + rels: IObjectOf[]>, + ...impls: (MultiFn | Implementation)[] +) => { + (impls.length & 1) && illegalArgs("expected an even number of implementation items"); + if (rels) { + for (let parent in rels) { + for (let fn of rels[parent]) { + fn.isa(type, parent); + } + } + } + for (let i = 0; i < impls.length; i += 2) { + (>impls[i]).add(type, impls[i + 1]); + } +}; diff --git a/packages/defmulti/test/index.ts b/packages/defmulti/test/index.ts index 41e17b28ef..9656a9e5df 100644 --- a/packages/defmulti/test/index.ts +++ b/packages/defmulti/test/index.ts @@ -1,5 +1,5 @@ import * as assert from "assert"; -import { DEFAULT, defmulti, defmultiN } from "../src/index"; +import { DEFAULT, defmulti, defmultiN, implementations } from "../src/index"; describe("defmulti", () => { it("flatten", () => { @@ -81,9 +81,13 @@ describe("defmulti", () => { }, "foo rels"); assert.equal(foo(23), "odd"); assert.equal(foo(42), "number"); + assert(foo.callable(23)); + assert(foo.callable(42)); + assert(!foo.callable(66)); assert.throws(() => foo(66), "no default"); foo.add(DEFAULT, (x) => -x); assert.equal(foo(66), -66); + assert.deepEqual(foo.impls(), new Set([DEFAULT, "odd", "even", "number", "23", "42"])); const bar = defmulti((x) => x, { 23: ["odd"], @@ -98,4 +102,19 @@ describe("defmulti", () => { "even": new Set(["number"]), }, "bar rels"); }); + + it("implementations", () => { + const foo = defmulti((x) => x.id); + const bar = defmulti((x) => x.id); + + implementations( + "a", + {}, + foo, (x) => `foo: ${x.val}`, + bar, (x) => `bar: ${x.val.toUpperCase()}` + ) + + assert.equal(foo({ id: "a", val: "alice" }), "foo: alice"); + assert.equal(bar({ id: "a", val: "alice" }), "bar: ALICE"); + }); }); diff --git a/packages/defmulti/test/tsconfig.json b/packages/defmulti/test/tsconfig.json index bcf29ace54..2c9c12a650 100644 --- a/packages/defmulti/test/tsconfig.json +++ b/packages/defmulti/test/tsconfig.json @@ -1,10 +1,11 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", "../src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/defmulti/tsconfig.json b/packages/defmulti/tsconfig.json index bd6481a5a6..bcf03f18b4 100644 --- a/packages/defmulti/tsconfig.json +++ b/packages/defmulti/tsconfig.json @@ -1,9 +1,11 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/dgraph/.npmignore b/packages/dgraph/.npmignore index d703bda97a..67d0c55714 100644 --- a/packages/dgraph/.npmignore +++ b/packages/dgraph/.npmignore @@ -1,10 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/dgraph/CHANGELOG.md b/packages/dgraph/CHANGELOG.md index edff25c8d2..39bfa51e92 100644 --- a/packages/dgraph/CHANGELOG.md +++ b/packages/dgraph/CHANGELOG.md @@ -3,6 +3,28 @@ 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/dgraph@0.2.35...@thi.ng/dgraph@1.0.0) (2019-01-21) + + +### Build System + +* update package build scripts & outputs, imports in ~50 packages ([b54b703](https://github.com/thi-ng/umbrella/commit/b54b703)) + + +### BREAKING CHANGES + +* enabled multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols. + + + + + ## [0.2.35](https://github.com/thi-ng/umbrella/compare/@thi.ng/dgraph@0.2.34...@thi.ng/dgraph@0.2.35) (2019-01-02) **Note:** Version bump only for package @thi.ng/dgraph diff --git a/packages/dgraph/package.json b/packages/dgraph/package.json index 134a9a97fb..376cd79d26 100644 --- a/packages/dgraph/package.json +++ b/packages/dgraph/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/dgraph", - "version": "0.2.35", + "version": "1.0.0", "description": "Type-agnostic directed acyclic graph (DAG) & graph operations", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,27 +14,29 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn run clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module dgraph api associative equiv errors transducers", + "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 run build && yarn publish --access public", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/api": "^4.2.4", - "@thi.ng/associative": "^0.6.23", - "@thi.ng/equiv": "^0.1.15", - "@thi.ng/errors": "^0.1.12", - "@thi.ng/transducers": "^2.3.2" + "@thi.ng/api": "^5.0.0", + "@thi.ng/associative": "^1.0.0", + "@thi.ng/equiv": "^1.0.0", + "@thi.ng/errors": "^1.0.0", + "@thi.ng/transducers": "^3.0.0" }, "keywords": [ "data structure", @@ -44,5 +48,6 @@ ], "publishConfig": { "access": "public" - } + }, + "sideEffects": false } diff --git a/packages/dgraph/src/index.ts b/packages/dgraph/src/index.ts index 369b8725e2..3db28c2f7c 100644 --- a/packages/dgraph/src/index.ts +++ b/packages/dgraph/src/index.ts @@ -1,11 +1,8 @@ -import { ICopy } from "@thi.ng/api/api"; -import { EquivMap } from "@thi.ng/associative/equiv-map"; -import { LLSet } from "@thi.ng/associative/ll-set"; -import { union } from "@thi.ng/associative/union"; +import { ICopy } from "@thi.ng/api"; +import { EquivMap, LLSet, union } from "@thi.ng/associative"; import { equiv } from "@thi.ng/equiv"; -import { illegalArgs } from "@thi.ng/errors/illegal-arguments"; -import { reduce, reducer } from "@thi.ng/transducers/reduce"; -import { filter } from "@thi.ng/transducers/xform/filter"; +import { illegalArgs } from "@thi.ng/errors"; +import { filter, reduce, reducer } from "@thi.ng/transducers"; export class DGraph implements Iterable, diff --git a/packages/dgraph/test/tsconfig.json b/packages/dgraph/test/tsconfig.json index bcf29ace54..2c9c12a650 100644 --- a/packages/dgraph/test/tsconfig.json +++ b/packages/dgraph/test/tsconfig.json @@ -1,10 +1,11 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", "../src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/dgraph/tsconfig.json b/packages/dgraph/tsconfig.json index bd6481a5a6..bcf03f18b4 100644 --- a/packages/dgraph/tsconfig.json +++ b/packages/dgraph/tsconfig.json @@ -1,9 +1,11 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/diff/.npmignore b/packages/diff/.npmignore index d703bda97a..67d0c55714 100644 --- a/packages/diff/.npmignore +++ b/packages/diff/.npmignore @@ -1,10 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/diff/CHANGELOG.md b/packages/diff/CHANGELOG.md index 6792f21ef6..44a346679b 100644 --- a/packages/diff/CHANGELOG.md +++ b/packages/diff/CHANGELOG.md @@ -3,6 +3,28 @@ 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/diff@2.0.2...@thi.ng/diff@3.0.0) (2019-01-21) + + +### Build System + +* update package build scripts & outputs, imports in ~50 packages ([b54b703](https://github.com/thi-ng/umbrella/commit/b54b703)) + + +### BREAKING CHANGES + +* enabled multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols. + + + + + ## [2.0.2](https://github.com/thi-ng/umbrella/compare/@thi.ng/diff@2.0.1...@thi.ng/diff@2.0.2) (2018-12-15) **Note:** Version bump only for package @thi.ng/diff diff --git a/packages/diff/package.json b/packages/diff/package.json index b4628ad9cd..cd50811b88 100644 --- a/packages/diff/package.json +++ b/packages/diff/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/diff", - "version": "2.0.2", + "version": "3.0.0", "description": "Array & object Diff", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,32 +14,38 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn run clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module diff api equiv", + "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 run build && yarn publish --access public", - "test": "rm -rf build && tsc -p test && mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/api": "^4.2.4", - "@thi.ng/equiv": "^0.1.15" + "@thi.ng/api": "^5.0.0", + "@thi.ng/equiv": "^1.0.0" }, "keywords": [ + "additions", "array", "diff", - "edit", + "edits", "ES6", "nested", + "removals", "typescript" ], "publishConfig": { "access": "public" - } + }, + "sideEffects": false } diff --git a/packages/diff/src/api.ts b/packages/diff/src/api.ts index b23f67e1ee..c5100c21d1 100644 --- a/packages/diff/src/api.ts +++ b/packages/diff/src/api.ts @@ -1,4 +1,4 @@ -import { IObjectOf } from "@thi.ng/api/api"; +import { IObjectOf } from "@thi.ng/api"; export type DiffKeyMap = IObjectOf; diff --git a/packages/diff/src/object.ts b/packages/diff/src/object.ts index a1f7c04319..26bc6990f3 100644 --- a/packages/diff/src/object.ts +++ b/packages/diff/src/object.ts @@ -1,4 +1,4 @@ -import { IObjectOf, Predicate2 } from "@thi.ng/api/api"; +import { IObjectOf, Predicate2 } from "@thi.ng/api"; import { equiv } from "@thi.ng/equiv"; import { DiffMode, ObjectDiff } from "./api"; diff --git a/packages/diff/test/tsconfig.json b/packages/diff/test/tsconfig.json index bcf29ace54..2c9c12a650 100644 --- a/packages/diff/test/tsconfig.json +++ b/packages/diff/test/tsconfig.json @@ -1,10 +1,11 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", "../src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/diff/tsconfig.json b/packages/diff/tsconfig.json index bd6481a5a6..bcf03f18b4 100644 --- a/packages/diff/tsconfig.json +++ b/packages/diff/tsconfig.json @@ -1,9 +1,11 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/dlogic/.npmignore b/packages/dlogic/.npmignore index d703bda97a..67d0c55714 100644 --- a/packages/dlogic/.npmignore +++ b/packages/dlogic/.npmignore @@ -1,10 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/dlogic/CHANGELOG.md b/packages/dlogic/CHANGELOG.md index 3310957fe2..3bdaf3c143 100644 --- a/packages/dlogic/CHANGELOG.md +++ b/packages/dlogic/CHANGELOG.md @@ -3,6 +3,28 @@ 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/dlogic@0.1.2...@thi.ng/dlogic@1.0.0) (2019-01-21) + + +### Build System + +* update package build scripts & outputs, imports in ~50 packages ([b54b703](https://github.com/thi-ng/umbrella/commit/b54b703)) + + +### BREAKING CHANGES + +* enabled multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols. + + + + + ## [0.1.2](https://github.com/thi-ng/umbrella/compare/@thi.ng/dlogic@0.1.1...@thi.ng/dlogic@0.1.2) (2018-12-15) **Note:** Version bump only for package @thi.ng/dlogic diff --git a/packages/dlogic/package.json b/packages/dlogic/package.json index b6fc9279bd..56e827cf98 100644 --- a/packages/dlogic/package.json +++ b/packages/dlogic/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/dlogic", - "version": "0.1.2", + "version": "1.0.0", "description": "Assorted digital logic ops / constructs.", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,19 +14,21 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn run clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module dlogic", + "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 run build && yarn publish --access public", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "keywords": [ @@ -39,5 +43,6 @@ ], "publishConfig": { "access": "public" - } + }, + "sideEffects": false } diff --git a/packages/dlogic/test/tsconfig.json b/packages/dlogic/test/tsconfig.json index bcf29ace54..2c9c12a650 100644 --- a/packages/dlogic/test/tsconfig.json +++ b/packages/dlogic/test/tsconfig.json @@ -1,10 +1,11 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", "../src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/dlogic/tsconfig.json b/packages/dlogic/tsconfig.json index bd6481a5a6..bcf03f18b4 100644 --- a/packages/dlogic/tsconfig.json +++ b/packages/dlogic/tsconfig.json @@ -1,9 +1,11 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/dot/.npmignore b/packages/dot/.npmignore index d703bda97a..67d0c55714 100644 --- a/packages/dot/.npmignore +++ b/packages/dot/.npmignore @@ -1,10 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/dot/CHANGELOG.md b/packages/dot/CHANGELOG.md index 9ed32e593f..29da389568 100644 --- a/packages/dot/CHANGELOG.md +++ b/packages/dot/CHANGELOG.md @@ -3,6 +3,28 @@ 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/dot@0.1.18...@thi.ng/dot@1.0.0) (2019-01-21) + + +### Build System + +* update package build scripts & outputs, imports in ~50 packages ([b54b703](https://github.com/thi-ng/umbrella/commit/b54b703)) + + +### BREAKING CHANGES + +* enabled multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols. + + + + + ## [0.1.18](https://github.com/thi-ng/umbrella/compare/@thi.ng/dot@0.1.17...@thi.ng/dot@0.1.18) (2018-12-15) **Note:** Version bump only for package @thi.ng/dot diff --git a/packages/dot/README.md b/packages/dot/README.md index 6da2d1195a..23fdb3f747 100644 --- a/packages/dot/README.md +++ b/packages/dot/README.md @@ -40,7 +40,7 @@ The source code of this example is also available in [/test/example.ts](https://github.com/thi-ng/umbrella/tree/master/packages/dot/test/example.ts). ```ts -import * as dot from "@thi.ng/dot"; +import { serializeGraph } from "@thi.ng/dot"; // node type style presets const terminal = { @@ -57,7 +57,7 @@ const operator = { outs: { "out": "out" } }; -dot.serializeGraph({ +serializeGraph({ directed: true, // default // graph attributes attribs: { diff --git a/packages/dot/package.json b/packages/dot/package.json index 5068c62524..a3f4f66c9a 100644 --- a/packages/dot/package.json +++ b/packages/dot/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/dot", - "version": "0.1.18", + "version": "1.0.0", "description": "Graphviz DOM abstraction as vanilla JS objects & serialization to DOT format", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,24 +14,26 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn run clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module dot api checks", + "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 run build && yarn publish --access public", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/api": "^4.2.4", - "@thi.ng/checks": "^1.5.14" + "@thi.ng/api": "^5.0.0", + "@thi.ng/checks": "^2.0.0" }, "keywords": [ "ES6", @@ -37,5 +41,6 @@ ], "publishConfig": { "access": "public" - } + }, + "sideEffects": false } diff --git a/packages/dot/src/api.ts b/packages/dot/src/api.ts index 3efffb6b0f..5cd087298d 100644 --- a/packages/dot/src/api.ts +++ b/packages/dot/src/api.ts @@ -1,4 +1,4 @@ -import { IObjectOf } from "@thi.ng/api/api"; +import { IObjectOf } from "@thi.ng/api"; export type NodeShape = "box" | diff --git a/packages/dot/src/serialize.ts b/packages/dot/src/serialize.ts index 48495c7804..93589dc65a 100644 --- a/packages/dot/src/serialize.ts +++ b/packages/dot/src/serialize.ts @@ -1,6 +1,5 @@ -import { IObjectOf } from "@thi.ng/api/api"; -import { isArray } from "@thi.ng/checks/is-array"; - +import { IObjectOf } from "@thi.ng/api"; +import { isArray } from "@thi.ng/checks"; import { Edge, Graph, diff --git a/packages/dot/test/tsconfig.json b/packages/dot/test/tsconfig.json index bcf29ace54..2c9c12a650 100644 --- a/packages/dot/test/tsconfig.json +++ b/packages/dot/test/tsconfig.json @@ -1,10 +1,11 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", "../src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/dot/tsconfig.json b/packages/dot/tsconfig.json index bd6481a5a6..bcf03f18b4 100644 --- a/packages/dot/tsconfig.json +++ b/packages/dot/tsconfig.json @@ -1,9 +1,11 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/dsp/.npmignore b/packages/dsp/.npmignore index d703bda97a..67d0c55714 100644 --- a/packages/dsp/.npmignore +++ b/packages/dsp/.npmignore @@ -1,10 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/dsp/CHANGELOG.md b/packages/dsp/CHANGELOG.md index 399f140bd2..9bbeccc5a1 100644 --- a/packages/dsp/CHANGELOG.md +++ b/packages/dsp/CHANGELOG.md @@ -3,6 +3,28 @@ 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/dsp@0.1.3...@thi.ng/dsp@1.0.0) (2019-01-21) + + +### Build System + +* update package build scripts & outputs, imports in ~50 packages ([b54b703](https://github.com/thi-ng/umbrella/commit/b54b703)) + + +### BREAKING CHANGES + +* enabled multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols. + + + + + ## [0.1.3](https://github.com/thi-ng/umbrella/compare/@thi.ng/dsp@0.1.2...@thi.ng/dsp@0.1.3) (2018-12-15) **Note:** Version bump only for package @thi.ng/dsp diff --git a/packages/dsp/README.md b/packages/dsp/README.md index efb553fcda..020e7bc419 100644 --- a/packages/dsp/README.md +++ b/packages/dsp/README.md @@ -47,7 +47,7 @@ yarn add @thi.ng/dsp import * as dsp from "@thi.ng/dsp"; import { take } from "@thi.ng/transducers"; -[...take(20, new dsp.Oscillator(dsp.mix(dsp.sin,dsp.rect), 1/20)] +[...take(20, new dsp.Oscillator(dsp.mix(dsp.sin, dsp.rect), 1/20)] // [ 0.5, // 0.6545084971874737, // 0.7938926261462366, diff --git a/packages/dsp/package.json b/packages/dsp/package.json index 1c53004bf7..fbb1cf77b2 100644 --- a/packages/dsp/package.json +++ b/packages/dsp/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/dsp", - "version": "0.1.3", + "version": "1.0.0", "description": "Assorted DSP utils, oscillators etc.", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,23 +14,25 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn run clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module dsp math", + "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 run build && yarn publish --access public", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/math": "^0.2.2" + "@thi.ng/math": "^1.0.0" }, "keywords": [ "additive", @@ -44,5 +48,6 @@ ], "publishConfig": { "access": "public" - } + }, + "sideEffects": false } diff --git a/packages/dsp/src/api.ts b/packages/dsp/src/api.ts index 99bd50b70f..c364d97acd 100644 --- a/packages/dsp/src/api.ts +++ b/packages/dsp/src/api.ts @@ -1 +1,2 @@ -export type StatelessOscillator = (phase: number, freq: number, amp?: number, dc?: number, opts?: any) => number; +export type StatelessOscillator = + (phase: number, freq: number, amp?: number, dc?: number, opts?: any) => number; diff --git a/packages/dsp/src/osc.ts b/packages/dsp/src/osc.ts index ce932921eb..f0fef27574 100644 --- a/packages/dsp/src/osc.ts +++ b/packages/dsp/src/osc.ts @@ -1,7 +1,10 @@ -import { HALF_PI, TAU } from "@thi.ng/math/api"; -import { mix as _mix } from "@thi.ng/math/mix"; -import { wrap01 } from "@thi.ng/math/interval"; -import { fract } from "@thi.ng/math/prec"; +import { + fract, + HALF_PI, + mix as _mix, + TAU, + wrap01 +} from "@thi.ng/math"; import { StatelessOscillator } from "./api"; export class Oscillator implements diff --git a/packages/dsp/test/tsconfig.json b/packages/dsp/test/tsconfig.json index bcf29ace54..2c9c12a650 100644 --- a/packages/dsp/test/tsconfig.json +++ b/packages/dsp/test/tsconfig.json @@ -1,10 +1,11 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", "../src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/dsp/tsconfig.json b/packages/dsp/tsconfig.json index bd6481a5a6..bcf03f18b4 100644 --- a/packages/dsp/tsconfig.json +++ b/packages/dsp/tsconfig.json @@ -1,9 +1,11 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/equiv/.npmignore b/packages/equiv/.npmignore index d703bda97a..67d0c55714 100644 --- a/packages/equiv/.npmignore +++ b/packages/equiv/.npmignore @@ -1,10 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/equiv/CHANGELOG.md b/packages/equiv/CHANGELOG.md index 8187f2ab41..b378f3fdad 100644 --- a/packages/equiv/CHANGELOG.md +++ b/packages/equiv/CHANGELOG.md @@ -3,6 +3,28 @@ 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/equiv@0.1.15...@thi.ng/equiv@1.0.0) (2019-01-21) + + +### Build System + +* update package build scripts & outputs, imports in ~50 packages ([b54b703](https://github.com/thi-ng/umbrella/commit/b54b703)) + + +### BREAKING CHANGES + +* enabled multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols. + + + + + ## [0.1.15](https://github.com/thi-ng/umbrella/compare/@thi.ng/equiv@0.1.14...@thi.ng/equiv@0.1.15) (2018-12-15) **Note:** Version bump only for package @thi.ng/equiv diff --git a/packages/equiv/package.json b/packages/equiv/package.json index 75288a604a..0f0fc26c4c 100644 --- a/packages/equiv/package.json +++ b/packages/equiv/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/equiv", - "version": "0.1.15", + "version": "1.0.0", "description": "Extensible deep equivalence checking for any data types", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,12 +14,14 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn run clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module equiv", + "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 run build && yarn publish --access public", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", @@ -25,16 +29,28 @@ "benchmark": "^2.1.4", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "keywords": [ "deep", + "equal", "equality", + "extensible", + "interface", "ES6", - "typescript" + "typescript", + "value" ], "publishConfig": { "access": "public" - } + }, + "browserslist": [ + "since 2018-07" + ], + "browser": { + "process": false, + "setTimeout": false + }, + "sideEffects": false } diff --git a/packages/equiv/test/index.ts b/packages/equiv/test/index.ts index acaae4c6f3..4ed9489fd4 100644 --- a/packages/equiv/test/index.ts +++ b/packages/equiv/test/index.ts @@ -5,63 +5,63 @@ import { equiv } from "../src/"; describe("equiv", () => { it("null", () => { - assert(equiv(null, null)); - assert(equiv(null, undefined)); - assert(equiv(undefined, null)); + assert.ok(equiv(null, null)); + assert.ok(equiv(null, undefined)); + assert.ok(equiv(undefined, null)); }); it("boolean", () => { - assert(!equiv(null, false)); - assert(!equiv(false, null)); - assert(!equiv(undefined, false)); - assert(!equiv(false, undefined)); + assert.ok(!equiv(null, false)); + assert.ok(!equiv(false, null)); + assert.ok(!equiv(undefined, false)); + assert.ok(!equiv(false, undefined)); }); it("number", () => { - assert(!equiv(null, 0)); - assert(!equiv(0, null)); - assert(!equiv(0, undefined)); - assert(!equiv(undefined, 0)); - - assert(equiv(0, 0)); - assert(equiv(0, 0.0)); - assert(!equiv(0, 1)); - assert(!equiv(1, 0)); - assert(!equiv(0, "0")); - assert(!equiv("0", 0)); - assert(!equiv(0, [0])); - assert(!equiv([0], 0)); + assert.ok(!equiv(null, 0)); + assert.ok(!equiv(0, null)); + assert.ok(!equiv(0, undefined)); + assert.ok(!equiv(undefined, 0)); + + assert.ok(equiv(0, 0)); + assert.ok(equiv(0, 0.0)); + assert.ok(!equiv(0, 1)); + assert.ok(!equiv(1, 0)); + assert.ok(!equiv(0, "0")); + assert.ok(!equiv("0", 0)); + assert.ok(!equiv(0, [0])); + assert.ok(!equiv([0], 0)); }); it("string", () => { - assert(!equiv(null, "")); - assert(!equiv("", null)); - assert(equiv("a", "a")); - assert(!equiv("a", "ab")); + assert.ok(!equiv(null, "")); + assert.ok(!equiv("", null)); + assert.ok(equiv("a", "a")); + assert.ok(!equiv("a", "ab")); }); it("array", () => { - assert(equiv([], [])); - assert(equiv([], [])); - assert(equiv([], { length: 0 })); - assert(equiv({ length: 0 }, [])); - assert(equiv(["a"], ["a"])); - assert(!equiv(["a"], ["b"])); + assert.ok(equiv([], [])); + assert.ok(equiv([], [])); + assert.ok(equiv([], { length: 0 })); + assert.ok(equiv({ length: 0 }, [])); + assert.ok(equiv(["a"], ["a"])); + assert.ok(!equiv(["a"], ["b"])); }); it("object", () => { - assert(!equiv(undefined, {})); - assert(!equiv({}, undefined)); - assert(!equiv(null, {})); - assert(!equiv({}, null)); - - assert(equiv({}, {})); - assert(!equiv({}, [])); - assert(!equiv([], {})); - assert(equiv({ a: 0 }, { a: 0 })); - assert(equiv({ a: 0, b: { c: 1 } }, { a: 0, b: { c: 1 } })); - assert(!equiv({ a: 0, b: { c: 1 } }, { a: 0, b: { c: 2 } })); - assert(!equiv({ a: 0, b: { c: 1 } }, { a: 0, b: {} })); + assert.ok(!equiv(undefined, {})); + assert.ok(!equiv({}, undefined)); + assert.ok(!equiv(null, {})); + assert.ok(!equiv({}, null)); + + assert.ok(equiv({}, {})); + assert.ok(!equiv({}, [])); + assert.ok(!equiv([], {})); + assert.ok(equiv({ a: 0 }, { a: 0 })); + assert.ok(equiv({ a: 0, b: { c: 1 } }, { a: 0, b: { c: 1 } })); + assert.ok(!equiv({ a: 0, b: { c: 1 } }, { a: 0, b: { c: 2 } })); + assert.ok(!equiv({ a: 0, b: { c: 1 } }, { a: 0, b: {} })); }); it("equiv impl", () => { @@ -76,43 +76,43 @@ describe("equiv", () => { } } - assert(!equiv(new A(1), null)); - assert(!equiv(new A(1), undefined)); - assert(!equiv(null, new A(1))); - assert(!equiv(undefined, new A(1))); - assert(equiv(new A(1), new A(1))); - assert(equiv(new A(1), 1)); - assert(equiv(1, new A(1))); - assert(equiv(1, { equiv(x) { return x === 1; } })); - assert(equiv({ equiv(x) { return x === 1; } }, 1)); - assert(!equiv(new A(1), new A(2))); - assert(!equiv(new A(1), 2)); + assert.ok(!equiv(new A(1), null)); + assert.ok(!equiv(new A(1), undefined)); + assert.ok(!equiv(null, new A(1))); + assert.ok(!equiv(undefined, new A(1))); + 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(new A(1), new A(2))); + assert.ok(!equiv(new A(1), 2)); }); it("set", () => { const a = new Set([1, 2, 3]); - assert(equiv(a, a)); - assert(equiv(a, new Set([3, 2, 1]))); - assert(equiv(new Set([{ a: 1 }, new Set([{ b: 2 }, [3]])]), new Set([new Set([[3], { b: 2 }]), { a: 1 }]))); - assert(!equiv(a, new Set([3, 2, 0]))); - assert(!equiv(a, [3, 2, 0])); - assert(!equiv(a, new Map([[3, 3], [2, 2], [1, 1]]))); - assert(!equiv(a, null)); - assert(!equiv(null, a)); + 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(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]]))); + assert.ok(!equiv(a, null)); + assert.ok(!equiv(null, a)); }); it("date", () => { const a = new Date(123456); - assert(equiv(a, a)); - assert(equiv(a, new Date(123456))); - assert(!equiv(a, new Date(123))); + assert.ok(equiv(a, a)); + assert.ok(equiv(a, new Date(123456))); + assert.ok(!equiv(a, new Date(123))); }); it("regexp", () => { const a = /(\w+)/g; - assert(equiv(a, a)); - assert(equiv(a, /(\w+)/g)); - assert(!equiv(a, /(\w+)/)); - assert(!equiv(a, /(\w*)/g)); + assert.ok(equiv(a, a)); + assert.ok(equiv(a, /(\w+)/g)); + assert.ok(!equiv(a, /(\w+)/)); + assert.ok(!equiv(a, /(\w*)/g)); }); }); diff --git a/packages/equiv/test/tsconfig.json b/packages/equiv/test/tsconfig.json index bcf29ace54..2c9c12a650 100644 --- a/packages/equiv/test/tsconfig.json +++ b/packages/equiv/test/tsconfig.json @@ -1,10 +1,11 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", "../src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/equiv/tsconfig.json b/packages/equiv/tsconfig.json index bd6481a5a6..bcf03f18b4 100644 --- a/packages/equiv/tsconfig.json +++ b/packages/equiv/tsconfig.json @@ -1,9 +1,11 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/errors/.npmignore b/packages/errors/.npmignore index d703bda97a..67d0c55714 100644 --- a/packages/errors/.npmignore +++ b/packages/errors/.npmignore @@ -1,10 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/errors/CHANGELOG.md b/packages/errors/CHANGELOG.md index bc2a63cf79..bf519236a3 100644 --- a/packages/errors/CHANGELOG.md +++ b/packages/errors/CHANGELOG.md @@ -3,6 +3,28 @@ 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/errors@0.1.12...@thi.ng/errors@1.0.0) (2019-01-21) + + +### Build System + +* update package build scripts & outputs, imports in ~50 packages ([b54b703](https://github.com/thi-ng/umbrella/commit/b54b703)) + + +### BREAKING CHANGES + +* enabled multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols. + + + + + ## [0.1.12](https://github.com/thi-ng/umbrella/compare/@thi.ng/errors@0.1.11...@thi.ng/errors@0.1.12) (2018-12-15) **Note:** Version bump only for package @thi.ng/errors diff --git a/packages/errors/package.json b/packages/errors/package.json index f4a0d0ab91..86dd0db302 100644 --- a/packages/errors/package.json +++ b/packages/errors/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/errors", - "version": "0.1.12", + "version": "1.0.0", "description": "Custom error types and helper fns.", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,19 +14,21 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn run clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module errors", + "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 run build && yarn publish --access public", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "keywords": [ @@ -34,5 +38,13 @@ ], "publishConfig": { "access": "public" - } + }, + "browserslist": [ + "since 2018-07" + ], + "browser": { + "process": false, + "setTimeout": false + }, + "sideEffects": false } diff --git a/packages/errors/src/illegal-arguments.ts b/packages/errors/src/illegal-arguments.ts index 2f4ff7f5bb..5ecdd637ee 100644 --- a/packages/errors/src/illegal-arguments.ts +++ b/packages/errors/src/illegal-arguments.ts @@ -4,6 +4,7 @@ export class IllegalArgumentError extends Error { } } -export function illegalArgs(msg?: any): never { - throw new IllegalArgumentError(msg); -} +export const illegalArgs = + (msg?: any): never => { + throw new IllegalArgumentError(msg); + }; diff --git a/packages/errors/src/illegal-arity.ts b/packages/errors/src/illegal-arity.ts index 4f0d5e1301..e2c4af81a4 100644 --- a/packages/errors/src/illegal-arity.ts +++ b/packages/errors/src/illegal-arity.ts @@ -4,6 +4,7 @@ export class IllegalArityError extends Error { } } -export function illegalArity(n): never { - throw new IllegalArityError(n); -} +export const illegalArity = + (n): never => { + throw new IllegalArityError(n); + }; diff --git a/packages/errors/src/illegal-state.ts b/packages/errors/src/illegal-state.ts index 3553868bfc..7552f97b36 100644 --- a/packages/errors/src/illegal-state.ts +++ b/packages/errors/src/illegal-state.ts @@ -4,6 +4,7 @@ export class IllegalStateError extends Error { } } -export function illegalState(msg?: any): never { - throw new IllegalStateError(msg); -} +export const illegalState = + (msg?: any): never => { + throw new IllegalStateError(msg); + }; diff --git a/packages/errors/src/unsupported.ts b/packages/errors/src/unsupported.ts index e0534a6d92..71687717e0 100644 --- a/packages/errors/src/unsupported.ts +++ b/packages/errors/src/unsupported.ts @@ -4,6 +4,7 @@ export class UnsupportedOperationError extends Error { } } -export function unsupported(msg?: any): never { - throw new UnsupportedOperationError(msg); -} +export const unsupported = + (msg?: any): never => { + throw new UnsupportedOperationError(msg); + }; diff --git a/packages/errors/test/tsconfig.json b/packages/errors/test/tsconfig.json index bcf29ace54..2c9c12a650 100644 --- a/packages/errors/test/tsconfig.json +++ b/packages/errors/test/tsconfig.json @@ -1,10 +1,11 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", "../src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/errors/tsconfig.json b/packages/errors/tsconfig.json index bd6481a5a6..bcf03f18b4 100644 --- a/packages/errors/tsconfig.json +++ b/packages/errors/tsconfig.json @@ -1,9 +1,11 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/fsm/.npmignore b/packages/fsm/.npmignore new file mode 100644 index 0000000000..67d0c55714 --- /dev/null +++ b/packages/fsm/.npmignore @@ -0,0 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz +build +coverage +dev +doc +src* +test +tsconfig.json diff --git a/packages/fsm/CHANGELOG.md b/packages/fsm/CHANGELOG.md new file mode 100644 index 0000000000..f938776a5d --- /dev/null +++ b/packages/fsm/CHANGELOG.md @@ -0,0 +1,38 @@ +# Change Log + +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/fsm@0.1.0...@thi.ng/fsm@1.0.0) (2019-01-21) + + +### Build System + +* update package build scripts & outputs, imports in ~50 packages ([b54b703](https://github.com/thi-ng/umbrella/commit/b54b703)) + + +### BREAKING CHANGES + +* enabled multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols. + + + + + +# 0.1.0 (2019-01-04) + + +### Features + +* **fsm:** add always(), lit(), not(), cleanup imports ([992f31a](https://github.com/thi-ng/umbrella/commit/992f31a)) +* **fsm:** add never(), optimize alts(), add docs for all matchers ([81e3fc7](https://github.com/thi-ng/umbrella/commit/81e3fc7)) +* **fsm:** add repeat(), success(), refactor all matchers ([55671fc](https://github.com/thi-ng/umbrella/commit/55671fc)) +* **fsm:** add support for lookahead-1, add docs ([4a9bb3d](https://github.com/thi-ng/umbrella/commit/4a9bb3d)) +* **fsm:** import fsm package ([e03390b](https://github.com/thi-ng/umbrella/commit/e03390b)) +* **fsm:** update not() ([a933607](https://github.com/thi-ng/umbrella/commit/a933607)) diff --git a/packages/fsm/LICENSE b/packages/fsm/LICENSE new file mode 100644 index 0000000000..8dada3edaf --- /dev/null +++ b/packages/fsm/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/fsm/README.md b/packages/fsm/README.md new file mode 100644 index 0000000000..4f347df284 --- /dev/null +++ b/packages/fsm/README.md @@ -0,0 +1,114 @@ +# @thi.ng/fsm + +[![npm (scoped)](https://img.shields.io/npm/v/@thi.ng/fsm.svg)](https://www.npmjs.com/package/@thi.ng/fsm) +![npm downloads](https://img.shields.io/npm/dm/@thi.ng/fsm.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) +- [Status](#status) +- [Installation](#installation) +- [Dependencies](#dependencies) +- [Usage examples](#usage-examples) +- [API](#api) + - [Matchers](#matchers) + - [FSM transducer](#fsm-transducer) +- [Authors](#authors) +- [License](#license) + + + +## About + +Functional & composable primitives for building declarative, +[transducer](https://github.com/thi-ng/umbrella/tree/master/packages/transducers) +based Finite-State machines and parsers for arbitrary input data streams +(not necessarily string based). + +See the [minimal markdown parser +example](https://github.com/thi-ng/umbrella/tree/master/examples/markdown) +for a concrete use case. + +## Status + +**ALPHA**. This package will be merged with and update the existing +[@thi.ng/transducers-fsm](https://github.com/thi-ng/umbrella/tree/master/packages/transducers-fsm) +package. + +## Installation + +```bash +yarn add @thi.ng/fsm +``` + +## Dependencies + +- [@thi.ng/api](https://github.com/thi-ng/umbrella/tree/master/packages/api) +- [@thi.ng/equiv](https://github.com/thi-ng/umbrella/tree/master/packages/equiv) +- [@thi.ng/errors](https://github.com/thi-ng/umbrella/tree/master/packages/errors) +- [@thi.ng/transducers](https://github.com/thi-ng/umbrella/tree/master/packages/transducers) + +## Usage examples + +Checkout the minimal Markdown parser example: + +[Source code](https://github.com/thi-ng/umbrella/tree/master/examples/markdown) | +[Live demo](https://demo.thi.ng/umbrella/markdown/) + +The parser itself is defined here: +[@thi.ng/hiccup-markdown](https://github.com/thi-ng/umbrella/tree/master/packages/hiccup-markdown/src/parse.ts) + +```ts +import * as fsm from "@thi.ng/fsm"; +``` + +## API + +There're two key concepts provided by this package: + +### Matchers + +Matchers are composable functions which receive a single input value and +attempt to match it to their configured criteria / patterns. Matchers +also support optional user callbacks, which are executed when a match +was made and are responsible for state transitions, state update and +production of any result values. + +- [`alts()`](https://github.com/thi-ng/umbrella/tree/master/packages/fsm/src/alts.ts) +- [`always()`](https://github.com/thi-ng/umbrella/tree/master/packages/fsm/src/always.ts) +- [`lit()`](https://github.com/thi-ng/umbrella/tree/master/packages/fsm/src/lit.ts) +- [`never()`](https://github.com/thi-ng/umbrella/tree/master/packages/fsm/src/never.ts) +- [`not()`](https://github.com/thi-ng/umbrella/tree/master/packages/fsm/src/not.ts) +- [`repeat()`](https://github.com/thi-ng/umbrella/tree/master/packages/fsm/src/repeat.ts) +- [`seq()`](https://github.com/thi-ng/umbrella/tree/master/packages/fsm/src/seq.ts) +- [`str()`](https://github.com/thi-ng/umbrella/tree/master/packages/fsm/src/str.ts) +- [`until()`](https://github.com/thi-ng/umbrella/tree/master/packages/fsm/src/until.ts) + +See docs strings in `/src` folder for now. + +### FSM transducer + +The +[`fsm()`](https://github.com/thi-ng/umbrella/tree/master/packages/fsm/src/fsm.ts) +function is a Finite-state machine transducer w/ support for single +lookahead value. It takes an object of `states` and their matchers, an +arbitrary context object which will be uses as state container for the +various matchers and an `initial` state ID. + +The returned transducer consumes inputs of type `T` and produces results +of type `R`. The results are produced by callbacks of the given state +matchers. For each input consumed, the callbacks can produce any number +of result values. If a callback returns a result wrapped w/ `reduced()`, +the FSM causes early termination of the overall transducer pipeline. + +## Authors + +- Karsten Schmidt + +## License + +© 2018 Karsten Schmidt // Apache Software License 2.0 diff --git a/packages/fsm/package.json b/packages/fsm/package.json new file mode 100644 index 0000000000..608a0d2882 --- /dev/null +++ b/packages/fsm/package.json @@ -0,0 +1,58 @@ +{ + "name": "@thi.ng/fsm", + "version": "1.0.0", + "description": "Composable primitives for building declarative, transducer based Finite-State machines & parsers for arbitrary data streams", + "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/fsm", + "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 fsm api equiv errors transducers", + "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.5", + "@types/node": "^10.12.15", + "mocha": "^5.2.0", + "nyc": "^13.1.0", + "typedoc": "^0.14.0", + "typescript": "^3.2.2" + }, + "dependencies": { + "@thi.ng/api": "^5.0.0", + "@thi.ng/equiv": "^1.0.0", + "@thi.ng/errors": "^1.0.0", + "@thi.ng/transducers": "^3.0.0" + }, + "keywords": [ + "ES6", + "composition", + "declarative", + "finite state machine", + "FSM", + "functional", + "parser", + "pattern match", + "regex", + "string", + "transducers", + "typescript" + ], + "publishConfig": { + "access": "public" + }, + "sideEffects": false +} diff --git a/packages/fsm/src/alts.ts b/packages/fsm/src/alts.ts new file mode 100644 index 0000000000..13fcdddb41 --- /dev/null +++ b/packages/fsm/src/alts.ts @@ -0,0 +1,59 @@ +import { + Match, + Matcher, + MatcherInst, + MatchResult, + RES_FAIL, + RES_PARTIAL, + ResultBody +} from "./api"; +import { result } from "./result"; + +/** + * Returns a composed matcher which applies inputs to all given child + * matchers (`opts`) until either all have failed or one of them returns + * a full match. If successful, calls `callback` with the context, the + * child matcher's result and an array of all processed inputs thus far. + * The result of `alts` is the result of this callback (else undefined). + * + * Note: Matchers are always processed in reverse order, therefore + * attention must be paid to the given ordering of supplied matchers. + * + * If none of the matchers succeed the optional `fallback` callback will + * be executed and given a chance to produce a state transition. It too + * will be given an array of all processed inputs thus far. + * + * @param opts + * @param fallback + * @param callback + */ +export const alts = ( + opts: Matcher[], + fallback?: (ctx: C, buf: T[]) => ResultBody, + callback?: (ctx: C, next: ResultBody, buf: T[]) => ResultBody +): Matcher => + () => { + const alts = opts.map((o) => o()); + const buf: T[] = []; + let active = alts.length; + return (ctx, x) => { + for (let i = alts.length, a: MatcherInst, next: MatchResult; --i >= 0;) { + if (!(a = alts[i])) continue; + next = a(ctx, x); + if (next.type >= Match.FULL) { + return callback ? + result(callback(ctx, next.body, buf), next.type) : + next; + } else if (next.type === Match.FAIL) { + alts[i] = null; + active--; + } + } + fallback && buf.push(x); + return active ? + RES_PARTIAL : + fallback ? + result(fallback(ctx, buf)) : + RES_FAIL; + }; + }; diff --git a/packages/fsm/src/always.ts b/packages/fsm/src/always.ts new file mode 100644 index 0000000000..dd674cd853 --- /dev/null +++ b/packages/fsm/src/always.ts @@ -0,0 +1,14 @@ +import { LitCallback, Matcher } from "./api"; +import { result } from "./result"; + +/** + * Returns a matcher which always succeeds (produces a `Match.FULL` result) for + * any given input. Use `never()` for the opposite effect. + * + * @param callback + */ +export const always = + (callback?: LitCallback): Matcher => + () => + (ctx, x) => + result(callback && callback(ctx, x)); diff --git a/packages/fsm/src/api.ts b/packages/fsm/src/api.ts new file mode 100644 index 0000000000..67383fa3af --- /dev/null +++ b/packages/fsm/src/api.ts @@ -0,0 +1,46 @@ +export const enum Match { + /** + * Partial match + */ + PARTIAL = 0, + /** + * Full match + */ + FULL = 1, + /** + * Full match (No Consume), i.e. didn't consume last input. The + * result will be treated like `FULL`, but the last input will be + * processed further. + */ + FULL_NC = 2, + /** + * Failed match. + */ + FAIL = -1 +} + +export interface MatchResult { + type: Match; + body?: ResultBody; +} + +export type Matcher = + () => MatcherInst; + +export type MatcherInst = + (ctx: C, x: T) => MatchResult; + +export type ResultBody = + [number | string, T[]?]; + +export type AltCallback = + (ctx: C, next: ResultBody, x: T[]) => ResultBody; + +export type LitCallback = + (ctx: C, x: T) => ResultBody; + +export type SeqCallback = + (ctx: C, buf: T[]) => ResultBody; + +export const RES_PARTIAL = Object.freeze({ type: Match.PARTIAL }); +export const RES_FAIL = Object.freeze({ type: Match.FAIL }); diff --git a/packages/fsm/src/fsm.ts b/packages/fsm/src/fsm.ts new file mode 100644 index 0000000000..52133a1b45 --- /dev/null +++ b/packages/fsm/src/fsm.ts @@ -0,0 +1,73 @@ +import { IObjectOf } from "@thi.ng/api"; +import { illegalArgs, illegalState } from "@thi.ng/errors"; +import { + ensureReduced, + isReduced, + reduced, + Reducer, + Transducer, + unreduced +} from "@thi.ng/transducers"; +import { Match, Matcher } from "./api"; + +/** + * Finite-state machine transducer w/ support for single lookahead + * value. Takes an object of `states` and their matchers, an arbitrary + * context object and an `initial` state ID. + * + * The returned transducer consumes inputs of type `T` and produces + * results of type `R`. The results are produced by callbacks of the + * given state matchers. Each can produce any number of values. If a + * callback returns a result wrapped w/ `reduced()`, the FSM causes + * early termination of the overall transducer pipeline. + * + * @param states + * @param ctx + * @param initialState + */ +export const fsm = ( + states: IObjectOf>, + ctx: C, + initialState: string | number = "start" +): Transducer => + ([init, complete, reduce]: Reducer) => { + let currID = initialState; + let curr = states[initialState] ? + states[initialState]() : + illegalArgs(`invalid initial state: ${initialState}`); + return [ + init, + complete, + (acc, x) => { + while (true) { + const { type, body } = curr(ctx, x); + if (type >= Match.FULL) { + const next = body && states[body[0]]; + if (next) { + currID = body[0]; + curr = next(); + } else { + illegalState(`unknown tx: ${currID} -> ${body && body[0]}`); + } + const res = body[1]; + if (res) { + for (let y of unreduced(res)) { + acc = reduce(acc, y); + if (isReduced(acc)) { + break; + } + } + isReduced(res) && (acc = ensureReduced(acc)); + } + if (type === Match.FULL_NC && !isReduced(acc)) { + continue; + } + } else if (type === Match.FAIL) { + return reduced(acc); + } + break; + } + return acc; + } + ]; + }; diff --git a/packages/fsm/src/index.ts b/packages/fsm/src/index.ts new file mode 100644 index 0000000000..498b4322bd --- /dev/null +++ b/packages/fsm/src/index.ts @@ -0,0 +1,13 @@ +export * from "./api"; + +export * from "./alts"; +export * from "./always"; +export * from "./fsm"; +export * from "./lit"; +export * from "./never"; +export * from "./not"; +export * from "./range"; +export * from "./repeat"; +export * from "./seq"; +export * from "./str"; +export * from "./until"; diff --git a/packages/fsm/src/lit.ts b/packages/fsm/src/lit.ts new file mode 100644 index 0000000000..8145f56235 --- /dev/null +++ b/packages/fsm/src/lit.ts @@ -0,0 +1,26 @@ +import { Predicate2 } from "@thi.ng/api"; +import { equiv as _equiv } from "@thi.ng/equiv"; +import { + Matcher, + RES_FAIL, + RES_PARTIAL, + SeqCallback +} from "./api"; +import { result } from "./result"; + +export const lit = ( + match: T[], + callback?: SeqCallback, + equiv: Predicate2 = _equiv +): Matcher => + () => { + const buf: T[] = []; + const n = match.length; + let i = 0; + return (state, x) => + equiv((buf.push(x), x), match[i++]) ? + i === n ? + result(callback && callback(state, buf)) : + RES_PARTIAL : + RES_FAIL; + }; diff --git a/packages/fsm/src/never.ts b/packages/fsm/src/never.ts new file mode 100644 index 0000000000..df9707421f --- /dev/null +++ b/packages/fsm/src/never.ts @@ -0,0 +1,12 @@ +import { LitCallback, Match, Matcher } from "./api"; +import { result } from "./result"; + +/** + * Returns a matcher which always fails (produces a `Match.FAIL` result) + * for any given input. Use `always()` for the opposite effect. + */ +export const never = + (callback?: LitCallback): Matcher => + () => + (ctx, x) => + result(callback && callback(ctx, x), Match.FAIL); diff --git a/packages/fsm/src/not.ts b/packages/fsm/src/not.ts new file mode 100644 index 0000000000..4de741ef4f --- /dev/null +++ b/packages/fsm/src/not.ts @@ -0,0 +1,36 @@ +import { + Match, + Matcher, + RES_FAIL, + RES_PARTIAL, + SeqCallback +} from "./api"; +import { result } from "./result"; + +/** + * Takes an existing matcher `match` and returns new matcher which + * inverts the result of `match`. I.e. If `match` returns `Match.FULL`, + * the new matcher returns `Match.FAIL` and vice versa. `Match.PARTIAL` + * results remain as is. + * + * @param match + * @param callback + */ +export const not = ( + match: Matcher, + callback?: SeqCallback +): Matcher => + () => { + let m = match(); + const buf: T[] = []; + return (ctx, x) => { + buf.push(x); + const { type } = m(ctx, x); + return type === Match.FAIL ? + result(callback && callback(ctx, buf)) : + type !== Match.PARTIAL ? + // TODO Match.FULL_NC handling? + RES_FAIL : + RES_PARTIAL; + } + }; diff --git a/packages/fsm/src/range.ts b/packages/fsm/src/range.ts new file mode 100644 index 0000000000..800dd34345 --- /dev/null +++ b/packages/fsm/src/range.ts @@ -0,0 +1,71 @@ +import { alts } from "./alts"; +import { + AltCallback, + LitCallback, + Matcher, + RES_FAIL +} from "./api"; +import { result } from "./result"; +import { str } from "./str"; + +/** + * Returns a single input matcher which returns `Match.FULL` if the + * input is within the closed interval given by [`min`,`max`]. + * + * @param min + * @param max + * @param callback + */ +export const range = ( + min: T, + max: T, + callback?: LitCallback +): Matcher => + () => + (ctx, x) => + x >= min && x <= max ? + result(callback && callback(ctx, x)) : + RES_FAIL; + +/** + * Matcher for single digit characters (0-9). + * + * @param callback + */ +export const digit = + (callback?: LitCallback): Matcher => + range("0", "9", callback); + +/** + * Matcher for single A-Z or a-z characters. + * + * @param callback + */ +export const alpha = + (callback?: AltCallback): Matcher => + alts( + [range("a", "z"), range("A", "Z")], + null, + callback + ); + +/** + * Combination of `digit()` and `alpha()`. + * + * @param callback + */ +export const alphaNum = + (callback?: AltCallback): Matcher => + alts([alpha(), digit()], null, callback); + +const WS: Matcher[] = + [str("\r"), str("\n"), str("\t"), str(" ")]; + +/** + * Matcher for single whitespace characters. + * + * @param callback + */ +export const whitespace = + (callback?: AltCallback): Matcher => + alts(WS, null, callback); diff --git a/packages/fsm/src/repeat.ts b/packages/fsm/src/repeat.ts new file mode 100644 index 0000000000..bfe6d62c88 --- /dev/null +++ b/packages/fsm/src/repeat.ts @@ -0,0 +1,47 @@ +import { + Match, + Matcher, + RES_PARTIAL, + SeqCallback +} from "./api"; +import { result } from "./result"; + +/** + * Takes a matcher and `min` / `max` repeats. Returns new matcher which + * only returns `Match.FULL` if `match` succeeded at least `min` times + * or once `max` repetitions have been found. + * + * @param match + * @param min + * @param max + * @param callback + */ +export const repeat = ( + match: Matcher, + min: number, + max: number, + callback?: SeqCallback +): Matcher => + () => { + let m = match(); + let i = 0; + const buf: T[] = []; + return (ctx, x) => { + buf.push(x); + const r = m(ctx, x); + if (r.type === Match.FULL) { + i++; + if (i === max) { + return result(callback && callback(ctx, buf)); + } + m = match(); + return RES_PARTIAL; + } else if (r.type === Match.FAIL) { + if (i >= min) { + buf.pop(); + return result(callback && callback(ctx, buf), Match.FULL_NC); + } + } + return r; + }; + }; diff --git a/packages/fsm/src/result.ts b/packages/fsm/src/result.ts new file mode 100644 index 0000000000..d61db87611 --- /dev/null +++ b/packages/fsm/src/result.ts @@ -0,0 +1,5 @@ +import { Match, MatchResult, ResultBody } from "./api"; + +export const result = + (body: ResultBody, type = Match.FULL): MatchResult => + ({ type, body }); diff --git a/packages/fsm/src/seq.ts b/packages/fsm/src/seq.ts new file mode 100644 index 0000000000..dc2ee4cc9c --- /dev/null +++ b/packages/fsm/src/seq.ts @@ -0,0 +1,47 @@ +import { + Match, + Matcher, + RES_FAIL, + RES_PARTIAL, + SeqCallback +} from "./api"; +import { result } from "./result"; + +/** + * Takes an array of matchers and returns new matcher which applies them + * in sequence. If any of the given matchers fails, returns + * `Match.FAIL`. + * + * @param matches + * @param callback + */ +export const seq = ( + matches: Matcher[], + callback?: SeqCallback +): Matcher => + () => { + let i = 0; + let m = matches[i](); + const n = matches.length - 1; + const buf: T[] = []; + return (state, x) => { + if (i > n) return RES_FAIL; + callback && buf.push(x); + while (i <= n) { + const { type } = m(state, x); + if (type >= Match.FULL) { + if (i === n) { + return result(callback && callback(state, buf)); + } + m = matches[++i](); + if (type === Match.FULL_NC) { + continue; + } + } + return type === Match.FAIL ? + RES_FAIL : + RES_PARTIAL; + } + return RES_FAIL; + } + }; diff --git a/packages/fsm/src/str.ts b/packages/fsm/src/str.ts new file mode 100644 index 0000000000..017994ac92 --- /dev/null +++ b/packages/fsm/src/str.ts @@ -0,0 +1,28 @@ +import { + LitCallback, + Matcher, + RES_FAIL, + RES_PARTIAL +} from "./api"; +import { result } from "./result"; + +/** + * String-only version of `seq()`. Returns `Match.FULL` once the entire + * given string could be matched. + * + * @param str + * @param callback + */ +export const str = ( + str: string, + callback?: LitCallback +): Matcher => + () => { + let buf = ""; + return (state, x) => + (buf += x) === str ? + result(callback && callback(state, buf)) : + str.indexOf(buf) === 0 ? + RES_PARTIAL : + RES_FAIL; + }; diff --git a/packages/fsm/src/until.ts b/packages/fsm/src/until.ts new file mode 100644 index 0000000000..5f1588c632 --- /dev/null +++ b/packages/fsm/src/until.ts @@ -0,0 +1,25 @@ +import { LitCallback, Matcher, RES_PARTIAL } from "./api"; +import { result } from "./result"; + +/** + * String only. Returns a matcher which consumes input until the given + * string could be matched. If successful, calls `callback` with string + * recorded so far (excluding the matched terminator string) and returns + * `Match.FULL` result. Else `Match.PARTIAL`. + * + * @param str + * @param callback + */ +export const until = ( + str: string, + callback?: LitCallback +): Matcher => + () => { + let buf = ""; + return (ctx, x) => { + buf += x; + return buf.endsWith(str) ? + result(callback && callback(ctx, buf.substr(0, buf.length - str.length))) : + RES_PARTIAL; + }; + }; diff --git a/packages/fsm/test/index.ts b/packages/fsm/test/index.ts new file mode 100644 index 0000000000..b089705eea --- /dev/null +++ b/packages/fsm/test/index.ts @@ -0,0 +1,6 @@ +// import * as assert from "assert"; +// import * as f from "../src/index"; + +describe("fsm", () => { + it("tests pending"); +}); diff --git a/packages/fsm/test/tsconfig.json b/packages/fsm/test/tsconfig.json new file mode 100644 index 0000000000..2c9c12a650 --- /dev/null +++ b/packages/fsm/test/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../../tsconfig.json", + "compilerOptions": { + "outDir": "../build", + "module": "commonjs", + }, + "include": [ + "./**/*.ts", + "../src/**/*.ts" + ] +} \ No newline at end of file diff --git a/packages/fsm/tsconfig.json b/packages/fsm/tsconfig.json new file mode 100644 index 0000000000..bcf03f18b4 --- /dev/null +++ b/packages/fsm/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": ".", + "module": "es6", + "target": "es6" + }, + "include": [ + "./src/**/*.ts" + ] +} \ No newline at end of file diff --git a/packages/geom-accel/.npmignore b/packages/geom-accel/.npmignore index d703bda97a..67d0c55714 100644 --- a/packages/geom-accel/.npmignore +++ b/packages/geom-accel/.npmignore @@ -1,10 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/geom-accel/CHANGELOG.md b/packages/geom-accel/CHANGELOG.md index e358ad5f98..b3623efc00 100644 --- a/packages/geom-accel/CHANGELOG.md +++ b/packages/geom-accel/CHANGELOG.md @@ -3,6 +3,28 @@ 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/geom-accel@0.1.11...@thi.ng/geom-accel@1.0.0) (2019-01-21) + + +### Build System + +* update package build scripts & outputs, imports in ~50 packages ([b54b703](https://github.com/thi-ng/umbrella/commit/b54b703)) + + +### BREAKING CHANGES + +* enabled multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols. + + + + + ## [0.1.11](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom-accel@0.1.10...@thi.ng/geom-accel@0.1.11) (2019-01-02) **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 e4f3f3aeb4..3e9e9b0c08 100644 --- a/packages/geom-accel/package.json +++ b/packages/geom-accel/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/geom-accel", - "version": "0.1.11", + "version": "1.0.0", "description": "TODO", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,26 +14,29 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn run clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module geomAccel api heaps math transducers vectors", + "test": "rimraf build && tsc -p test/tsconfig.json && nyc mocha build/test/*.js", + "clean": "rimraf *.js *.d.ts .nyc_output build coverage doc lib internal", "cover": "yarn test && nyc report --reporter=lcov", "doc": "node_modules/.bin/typedoc --mode modules --out doc src", - "pub": "yarn run build && yarn publish --access public", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/api": "^4.2.4", - "@thi.ng/heaps": "^0.3.1", - "@thi.ng/math": "^0.2.2", - "@thi.ng/vectors": "^1.4.12" + "@thi.ng/api": "^5.0.0", + "@thi.ng/heaps": "^1.0.0", + "@thi.ng/math": "^1.0.0", + "@thi.ng/transducers": "^3.0.0", + "@thi.ng/vectors": "^2.0.0" }, "keywords": [ "ES6", @@ -45,5 +50,6 @@ ], "publishConfig": { "access": "public" - } + }, + "sideEffects": false } diff --git a/packages/geom-accel/src/kdtree.ts b/packages/geom-accel/src/kdtree.ts index 5cd86491f3..895f4aefcc 100644 --- a/packages/geom-accel/src/kdtree.ts +++ b/packages/geom-accel/src/kdtree.ts @@ -1,23 +1,21 @@ -import { ICopy, IEmpty, Pair } from "@thi.ng/api/api"; -import { Heap } from "@thi.ng/heaps/heap"; -import { EPS } from "@thi.ng/math/api"; -import { ensureArray } from "@thi.ng/transducers/func/ensure-array"; -import { IDistance } from "@thi.ng/vectors/api"; - -export type KdIndexable = IDistance & IEmpty; +import { ICopy, Pair } from "@thi.ng/api"; +import { Heap } from "@thi.ng/heaps"; +import { EPS } from "@thi.ng/math"; +import { ensureArray } from "@thi.ng/transducers"; +import { distSq, empty, ReadonlyVec } from "@thi.ng/vectors"; const CMP = (a, b) => b[0] - a[0]; -export class KdNode, V> { +export class KdNode { parent: KdNode; l: KdNode; r: KdNode; d: number; - k: Readonly; + k: K; v: V; - constructor(parent: KdNode, dim: number, key: Readonly, val: V) { + constructor(parent: KdNode, dim: number, key: K, val: V) { this.parent = parent; this.d = dim; this.k = key; @@ -62,7 +60,7 @@ export class KdNode, V> { * https://github.com/ubilabs/kd-tree-javascript * */ -export class KdTree, V> +export class KdTree implements ICopy> { root: KdNode; @@ -96,11 +94,11 @@ export class KdTree, V> return new KdTree(this.dim, this); } - add(p: Readonly, v: V, eps = EPS) { + add(p: K, v: V, eps = EPS) { eps *= eps; const search = (node: KdNode, parent: KdNode): KdNode | false => node ? - p.distSq(node.k) > eps ? + distSq(p, node.k) > eps ? search( p[node.d] < node.k[node.d] ? node.l : node.r, node @@ -217,14 +215,14 @@ export class KdTree, V> * @param node * @param epsSq squared epsilon / tolerance */ -const find = , V>(p: K, node: KdNode, epsSq: number) => { +const find = (p: K, node: KdNode, epsSq: number) => { if (!node) return; - return p.distSq(node.k) <= epsSq ? + return distSq(p, node.k) <= epsSq ? node : find(p, p[node.d] < node.k[node.d] ? node.l : node.r, epsSq); }; -const findMin = , V>(node: KdNode, dim: number): KdNode => { +const findMin = (node: KdNode, dim: number): KdNode => { if (!node) return; if (node.d === dim) { return node.l ? @@ -249,7 +247,7 @@ const findMin = , V>(node: KdNode, dim: number): * * @param node */ -const remove = , V>(node: KdNode) => { +const remove = (node: KdNode) => { if (!node.l && !node.r) { if (!node.parent) { return true; @@ -276,9 +274,9 @@ const remove = , V>(node: KdNode) => { } }; -const nearest = , V>(q: K, acc: Heap<[number, KdNode]>, dims: number, maxNum: number, node: KdNode) => { +const nearest = (q: K, acc: Heap<[number, KdNode]>, dims: number, maxNum: number, node: KdNode) => { const p = node.k; - const ndist = q.distSq(p); + const ndist = distSq(p, q); if (!node.l && !node.r) { if (ndist < acc.peek()[0]) { if (acc.length >= maxNum) { @@ -290,11 +288,11 @@ const nearest = , V>(q: K, acc: Heap<[number, KdNode= 0;) { tp[i] = i === ndim ? q[i] : p[i]; } - const tdist = tp.distSq(p); + const tdist = distSq(p, tp); let best = !node.r ? node.l : diff --git a/packages/geom-accel/test/tsconfig.json b/packages/geom-accel/test/tsconfig.json index bcf29ace54..2c9c12a650 100644 --- a/packages/geom-accel/test/tsconfig.json +++ b/packages/geom-accel/test/tsconfig.json @@ -1,10 +1,11 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", "../src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/geom-accel/tsconfig.json b/packages/geom-accel/tsconfig.json index bd6481a5a6..bcf03f18b4 100644 --- a/packages/geom-accel/tsconfig.json +++ b/packages/geom-accel/tsconfig.json @@ -1,9 +1,11 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/geom/.npmignore b/packages/geom/.npmignore index d703bda97a..67d0c55714 100644 --- a/packages/geom/.npmignore +++ b/packages/geom/.npmignore @@ -1,10 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/geom/CHANGELOG.md b/packages/geom/CHANGELOG.md index 75e96a8045..879213da37 100644 --- a/packages/geom/CHANGELOG.md +++ b/packages/geom/CHANGELOG.md @@ -3,6 +3,28 @@ 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/geom@0.2.11...@thi.ng/geom@1.0.0) (2019-01-21) + + +### Build System + +* update package build scripts & outputs, imports in ~50 packages ([b54b703](https://github.com/thi-ng/umbrella/commit/b54b703)) + + +### BREAKING CHANGES + +* enabled multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols. + + + + + ## [0.2.11](https://github.com/thi-ng/umbrella/compare/@thi.ng/geom@0.2.10...@thi.ng/geom@0.2.11) (2019-01-02) **Note:** Version bump only for package @thi.ng/geom diff --git a/packages/geom/README.md b/packages/geom/README.md index 61c8f20ce5..296526de6e 100644 --- a/packages/geom/README.md +++ b/packages/geom/README.md @@ -1,6 +1,8 @@ # @thi.ng/geom [![npm (scoped)](https://img.shields.io/npm/v/@thi.ng/geom.svg)](https://www.npmjs.com/package/@thi.ng/geom) +![npm downloads](https://img.shields.io/npm/dm/@thi.ng/geom.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. @@ -8,11 +10,9 @@ This project is part of the - [About](#about) -- [Status](#status) - [Installation](#installation) +- [Dependencies](#dependencies) - [Usage examples](#usage-examples) - - [Tessellations](#tessellations) - - [Subdivision curves](#subdivision-curves) - [Authors](#authors) - [License](#license) @@ -20,19 +20,7 @@ This project is part of the ## About -This package is a partial WIP port of selected features of the -[Clojure/ClojureScript version of -thi.ng/geom](https://github.com/thi-ng/geom), as well as -[c.thi.ng](https://github.com/thi-ng/c-thing). Currently only 2D shapes -& operations are supported. - -**This package will soon be replaced by the currently still unreleased -[@thi.ng/geom2](https://github.com/thi-ng/umbrella/tree/feature/vec-refactor/packages/geom2) -package** - -## Status - -ALPHA - major breaking changes forthcoming... +[up-to-date feature matrix spreadsheet](https://docs.google.com/spreadsheets/d/1GxJm-zOQaGECui2MJUmy3gQPTF-T6BJ6vhNlUnPsmDs/edit?usp=sharing) ## Installation @@ -40,57 +28,26 @@ ALPHA - major breaking changes forthcoming... yarn add @thi.ng/geom ``` -## Usage examples - -### Tessellations +## 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/compose](https://github.com/thi-ng/umbrella/tree/master/packages/compose) +- [@thi.ng/defmulti](https://github.com/thi-ng/umbrella/tree/master/packages/defmulti) +- [@thi.ng/equiv](https://github.com/thi-ng/umbrella/tree/master/packages/equiv) +- [@thi.ng/errors](https://github.com/thi-ng/umbrella/tree/master/packages/errors) +- [@thi.ng/hiccup](https://github.com/thi-ng/umbrella/tree/master/packages/hiccup) +- [@thi.ng/hiccup-svg](https://github.com/thi-ng/umbrella/tree/master/packages/hiccup-svg) +- [@thi.ng/math](https://github.com/thi-ng/umbrella/tree/master/packages/math) +- [@thi.ng/matrices](https://github.com/thi-ng/umbrella/tree/master/packages/matrices) +- [@thi.ng/random](https://github.com/thi-ng/umbrella/tree/master/packages/random) +- [@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) -![sample output](../../assets/geom/tessel.svg) +## Usage examples ```ts import * as g from "@thi.ng/geom"; -import * as v from "@thi.ng/vectors"; -import * as h from "@thi.ng/hiccup"; -import * as svg from "@thi.ng/hiccup-svg"; -import * as fs from "fs"; - -const tintedPoly = (points) => { - const p = g.polygon2(points); - const c = p.centroid().toPolar(); - p.attribs = { fill: `hsl(${v.deg(c.y)},${c.x}%,${100-c.x/2}%)` }; - return p; -}; - -fs.writeFileSync( - "tessel.svg", - h.serialize( - svg.svg( - { - width: 1000, height: 1000, - viewBox: "-100 -100 200 200", - fill: "none", - stroke: "#000", - "stroke-width": 0.5, - }, - svg.convertTree( - g.circle2(100) - .toPolygon(6) - .tessellate([g.quadFan, g.triFan, g.edgeSplit, g.quadFan]) - .map((pts) => tintedPoly(pts).toHiccup()) - ) - ) - ) -); -``` - -### Subdivision curves - -| Chaikin (closed) | Chaikin (open) | -|---------------------------------------------------------|-----------------------------------------------------| -| ![chaikin closed](../../assets/geom/chaikin-closed.svg) | ![chaikin open](../../assets/geom/chaikin-open.svg) | - -```ts -g.polygon2([-100,-100, 0,100, 100,-100, 0,0]).subdivide(g.CHAIKIN_CLOSED, 4); -g.polyline2([-100,100, -100,-100, 0,0, 100,-100, 100,100]).subdivide(g.CHAIKIN_OPEN, 4); ``` ## Authors @@ -99,4 +56,4 @@ g.polyline2([-100,100, -100,-100, 0,0, 100,-100, 100,100]).subdivide(g.CHAIKIN_O ## License -© 2013 - 2018 Karsten Schmidt // Apache Software License 2.0 +© 2018 Karsten Schmidt // Apache Software License 2.0 diff --git a/packages/geom/package.json b/packages/geom/package.json index 91fc8bfb92..37ebbee985 100644 --- a/packages/geom/package.json +++ b/packages/geom/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/geom", - "version": "0.2.11", - "description": "2D/3D geometry primitives", - "main": "./index.js", + "version": "1.0.0", + "description": "TODO", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,38 +14,44 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn run clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc internal", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module geom api checks compose defmulti equiv errors hiccup hiccup-svg math matrices random transducers vectors", + "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 run build && yarn publish --access public", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/api": "^4.2.4", - "@thi.ng/checks": "^1.5.14", - "@thi.ng/math": "^0.2.2", - "@thi.ng/transducers": "^2.3.2", - "@thi.ng/vectors": "^1.4.12" + "@thi.ng/api": "^5.0.0", + "@thi.ng/checks": "^2.0.0", + "@thi.ng/compose": "^1.0.0", + "@thi.ng/defmulti": "^1.0.0", + "@thi.ng/equiv": "^1.0.0", + "@thi.ng/errors": "^1.0.0", + "@thi.ng/hiccup": "^3.0.0", + "@thi.ng/hiccup-svg": "^3.0.0", + "@thi.ng/math": "^1.0.0", + "@thi.ng/matrices": "^0.1.0", + "@thi.ng/random": "^1.0.0", + "@thi.ng/transducers": "^3.0.0", + "@thi.ng/vectors": "^2.0.0" }, "keywords": [ "ES6", - "geometry", - "2d", - "3d", - "shapes", - "intersection", "typescript" ], "publishConfig": { "access": "public" - } + }, + "sideEffects": false } diff --git a/packages/geom/src/api.ts b/packages/geom/src/api.ts index 333cf71b61..dd764ccec6 100644 --- a/packages/geom/src/api.ts +++ b/packages/geom/src/api.ts @@ -1,15 +1,59 @@ -import { IObjectOf } from "@thi.ng/api/api"; -import { IVector, ReadonlyVec, Vec } from "@thi.ng/vectors/api"; -import { Vec2 } from "@thi.ng/vectors/vec2"; +import { ICopy, IObjectOf, IToHiccup } from "@thi.ng/api"; +import { isNumber } from "@thi.ng/checks"; +import { equiv } from "@thi.ng/equiv"; +import { illegalState } from "@thi.ng/errors"; +import { + add2, + add3, + maddN2, + ReadonlyVec, + set, + Vec +} from "@thi.ng/vectors"; +import { arcPointAt, arcPointAtTheta } from "./internal/arc-point"; +import { copyPoints } from "./internal/copy-points"; -export const DEFAULT_SAMPLES = 32; - -export type Attribs = IObjectOf; +export const enum SegmentType { + MOVE, + LINE, + POLYLINE, + ARC, + CUBIC, + QUADRATIC, + CLOSE, +} -export type Tessellator> = - (points: ReadonlyArray) => T[][]; +export const enum Type { + AABB = 1, + ARC, + CIRCLE, + CUBIC, + CUBIC3, + ELLIPSE, + GROUP, + LINE, + LINE3, + PATH, + POINTS, + POINTS3, + POLYGON, + POLYGON3, + POLYLINE, + POLYLINE3, + QUAD, + QUAD3, + QUADRATIC, + QUADRATIC3, + RECT, + SPHERE, + TRIANGLE, + TRIANGLE3, + RAY, + RAY3, +} -export const enum LineIntersectionType { +export const enum IntersectionType { + NONE, PARALLEL, COINCIDENT, COINCIDENT_NO_INTERSECT, @@ -17,26 +61,40 @@ export const enum LineIntersectionType { INTERSECT_OUTSIDE, } -export const enum SegmentType { - MOVE, - LINE, - POLYLINE, - ARC, - CUBIC, - QUADRATIC, - CLOSE, +export const DEFAULT_SAMPLES = 20; + +export type Attribs = IObjectOf; + +export type Tessellator = (points: Vec[]) => Vec[][]; + +export type VecPair = [Vec, Vec]; + +export interface IShape extends + ICopy { + + readonly type: number | string; + attribs?: Attribs; } -export interface CollateOpts { - buf: Vec; - start: number; - cstride: number; - estride: number; +export interface AABBLike extends IShape { + pos: Vec; + size: Vec; + + max(): Vec; } -export interface LineIntersection { - type: LineIntersectionType; - isec?: T; +export interface IHiccupShape extends IShape, IToHiccup { } + +export interface IHiccupPathSegment { + toHiccupPathSegments(): any[]; +} + +export interface IntersectionResult { + type: IntersectionType; +} + +export interface LineIntersection extends IntersectionResult { + isec?: Vec; det?: number; alpha?: number; beta?: number; @@ -44,8 +102,16 @@ export interface LineIntersection { export interface PathSegment { type: SegmentType; - point?: Vec2; - geo?: IBoundsRaw & IVertices & IHiccupPathSegment & IToCubic; + point?: Vec; + geo?: IShape & IHiccupPathSegment; +} + +export interface PCLike extends IShape { + points: Vec[]; +} + +export interface PCLikeConstructor { + new(pts: Vec[], attribs: Attribs): PCLike; } export interface SamplingOpts { @@ -67,8 +133,8 @@ export interface SamplingOpts { /** * Currently only used by these types: * - * - Arc2 - * - Circle2 + * - Arc + * - Circle * * Defines the target angle between sampled points. If greater than * the actual range of the arc, only the two end points will be @@ -98,170 +164,540 @@ export interface SamplingOpts { last: boolean; } -export interface SubdivKernel> { - fn: (pts: T[], i: number, nump: number) => T[]; +export interface SubdivKernel { + fn: (pts: ReadonlyVec[], i: number, nump: number) => Vec[]; + iter?: (pts: ReadonlyVec[]) => Iterable; size: number; } -export interface IArea { - /** - * Computes and returns area. For types where orientation is taken - * into account, setting `signed` to false will always return the - * absolute area (default is `true`). - * - * @param unsigned - */ - area(signed?: boolean): number; -} +export abstract class APC implements + PCLike { -export interface IArcLength { - /** - * Returns arc length, or for closed shapes, circumference. - */ - arcLength(): number; -} + points: Vec[]; + attribs: Attribs; -export interface IBoundsRaw { - /** - * @return min / max points - */ - boundsRaw(): [V, V]; -} + constructor(points: Vec[], attribs?: Attribs) { + this.points = points; + this.attribs = attribs; + } -export interface IBounds { - /** - * Bounding shape - */ - bounds(): T; -} + abstract get type(): number | string; + abstract copy(): IShape; -export interface ICentroid { - /** - * Computes & returns centroid. If `c` is given it MUST be a zero - * vector and will be used to store result. - * - * @param c - */ - centroid(c?: T): T; + *[Symbol.iterator]() { + yield* this.points; + } } -export interface ICenter { - center(origin?: Readonly): this; -} +export class AABB implements + AABBLike { -export interface IClassifyPoint { - classifyPoint(p: Readonly): number; -} + pos: Vec; + size: Vec; + attribs: Attribs; -export interface IPointInside { - pointInside(p: Readonly): boolean; -} + constructor(pos: Vec = [0, 0, 0], size: Vec = [1, 1, 1], attribs?: Attribs) { + this.pos = pos; + this.size = size; + this.attribs = attribs; + } -export interface ICollate { - /** - * Collates all points into a single buffer and remaps existing - * vertices (by default). Points will written from given `start` - * index, using layout defined by `cstride` and `estride`. - * - * @param opts - */ - collate(opts?: Partial): Vec; -} + get type() { + return Type.AABB; + } -export interface IEdges { - edges(opts?: any): Iterable; -} + copy() { + return new AABB(set([], this.pos), set([], this.size), { ...this.attribs }); + } -export interface IHiccupPathSegment { - toHiccupPathSegments(): any[]; + max() { + return add3([], this.pos, this.size); + } } -export interface IPointMap { - mapPoint(p: Readonly, out?: B): B; - unmapPoint(p: Readonly, out?: A): A; -} -export interface IToCubic { - toCubic(): Iterable; -} +export class Arc implements + IHiccupShape, + IHiccupPathSegment { -export interface IToPolygon { - // FIXME return type should be interface - toPolygon(opts?: O): any; -} + pos: Vec; + r: Vec; + start: number; + end: number; + axis: number; + xl: boolean; + cw: boolean; + attribs: Attribs; + + constructor( + pos: Vec, + r: Vec, + axis: number, + start: number, + end: number, + xl = false, + cw = false, + attribs?: Attribs) { + + this.pos = pos; + this.r = r; + this.axis = axis; + this.start = start; + this.end = end; + this.xl = xl; + this.cw = cw; + this.attribs = attribs; + } + + get type() { + return Type.ARC; + } + + copy() { + return new Arc( + set([], this.pos), + set([], this.r), + this.axis, + this.start, + this.end, + this.xl, + this.cw, + { ...this.attribs } + ); + } + + equiv(o: any) { + return o instanceof Arc && + equiv(this.pos, o.pos) && + equiv(this.r, o.r) && + this.start === o.start && + this.end === o.end && + this.axis === o.axis && + this.xl === o.xl && + this.cw && o.cw; + } + + pointAt(t: number, out: Vec = []) { + return arcPointAt(this.pos, this.r, this.axis, this.start, this.end, t, out); + } + + pointAtTheta(theta: number, out: Vec = []) { + return arcPointAtTheta(this.pos, this.r, this.axis, theta, out); + } + + toHiccup() { + return ["path", this.attribs, [ + ["M", this.pointAt(0)], + ...this.toHiccupPathSegments() + ]]; + } + + toHiccupPathSegments() { + return [ + [ + "A", + this.r[0], + this.r[1], + this.axis, + this.xl, + this.cw, + this.pointAt(1) + ] + ]; + } +} + +export class Circle implements + IHiccupShape { -export interface ITessellateable> { - tessellate(tessel: Tessellator, iter?: number): T[][]; - tessellate(tessel: Iterable>): T[][]; -} + pos: Vec; + r: number; + attribs: Attribs; -export interface ITransformable { - transform(mat: M): this; -} + constructor(pos: Vec = [0, 0], r = 1, attribs?: Attribs) { + this.pos = pos; + this.r = r; + this.attribs = attribs; + } -export interface IUnion { - union(x: T): T; -} + get type() { + return Type.CIRCLE; + } -export interface IVertices { - vertices(opts?: O): Iterable; + copy() { + return new Circle(set([], this.pos), this.r, { ...this.attribs }); + } + + toHiccup() { + return ["circle", this.attribs, this.pos, this.r]; + } } -export interface JsonShape { - type: string; - attribs?: Attribs; +export class Cubic extends APC implements + IHiccupPathSegment { + + get type() { + return Type.CUBIC; + } + + copy() { + return new Cubic(copyPoints(this.points), { ...this.attribs }); + } + + toHiccup() { + return ["path", this.attribs, + [ + ["M", this.points[0]], + ...this.toHiccupPathSegments() + ] + ]; + } + + toHiccupPathSegments() { + const pts = this.points; + return [["C", pts[1], pts[2], pts[3]]]; + } } -export interface JsonArc2 extends JsonShape { +export class Ellipse implements + IHiccupShape { + pos: Vec; r: Vec; - axis: number; - start: number; - end: number; - xl: boolean; - clockwise: boolean; -} + attribs: Attribs; -export interface JsonCircle2 extends JsonShape { - pos: Vec; - r: number; -} + constructor(pos: Vec = [0, 0], r: number | Vec = [1, 1], attribs?: Attribs) { + this.pos = pos; + this.r = isNumber(r) ? [r, r] : r; + this.attribs = attribs; + } + + get type() { + return Type.ELLIPSE; + } + + copy() { + return new Ellipse(set([], this.pos), set([], this.r), { ...this.attribs }); + } + + toHiccup() { + return ["ellipse", this.attribs, this.pos, this.r]; + } +} + +export class Group implements + IHiccupShape { + + children: IHiccupShape[]; + attribs: Attribs; + + constructor(children: IHiccupShape[], attribs?: Attribs) { + this.children = children; + this.attribs = attribs; + } + + get type() { + return Type.GROUP; + } + + *[Symbol.iterator]() { + yield* this.children; + } + + copy() { + return new Group( + this.children.map((c) => c.copy()), + { ...this.attribs } + ); + } + + equiv(o: any) { + return o instanceof Group && + equiv(this.children, o.children); + } + + toHiccup() { + return ["g", this.attribs, ...this.children.map((x) => x.toHiccup())]; + } +} + +export class Line extends APC implements + IHiccupShape, + IHiccupPathSegment { + + get type() { + return Type.LINE; + } + + copy() { + return new Line(copyPoints(this.points), { ...this.attribs }); + } + + toHiccup() { + return ["line", this.attribs, this.points[0], this.points[1]]; + } + + toHiccupPathSegments() { + const [a, b] = this.points; + return [ + a[0] === b[0] ? + ["V", b[1]] : + a[1] === b[1] ? + ["H", b[0]] : + ["L", b] + ]; + } +} + +export class Path implements + IHiccupShape { + + segments: PathSegment[]; + closed: boolean; + attribs: Attribs; + + constructor(segments?: PathSegment[], attribs?: Attribs) { + this.segments = segments || []; + this.attribs = attribs; + this.closed = false; + } + + get type() { + return Type.PATH; + } + + *[Symbol.iterator]() { + yield* this.segments; + } + + copy() { + const p = new Path([...this.segments], { ...this.attribs }); + p.closed = this.closed; + return p; + } -export interface JsonCubic2 extends JsonShape { - points: Vec[]; -} + equiv(o: any) { + return o instanceof Path && + equiv(this.segments, o.segments); + } + + add(s: PathSegment) { + if (this.closed) illegalState("path already closed"); + this.segments.push(s); + } + + toHiccup() { + let dest: any[] = []; + const segments = this.segments; + const n = segments.length; + if (n > 1) { + dest.push(["M", segments[0].point]); + for (let i = 1; i < n; i++) { + dest = dest.concat(segments[i].geo.toHiccupPathSegments()); + } + if (this.closed) { + dest.push(["Z"]); + } + } + return ["path", this.attribs || {}, dest]; + } +} + +export class Points extends APC implements + IHiccupShape { + + get type() { + return Type.POINTS; + } + + copy() { + return new Points(copyPoints(this.points), { ...this.attribs }); + } + + toHiccup() { + return ["points", this.attribs, this.points]; + } +} + +export class Polygon extends APC implements + IHiccupShape { + + get type() { + return Type.POLYGON; + } + + copy() { + return new Polygon(copyPoints(this.points), { ...this.attribs }); + } + + toHiccup() { + return ["polygon", this.attribs, this.points]; + } +} + +export class Polyline extends APC implements + IHiccupShape, + IHiccupPathSegment { + + get type() { + return Type.POLYLINE; + } + + copy() { + return new Polyline(copyPoints(this.points), { ...this.attribs }); + } -export interface JsonQuadratic2 extends JsonShape { - points: Vec[]; + toHiccup() { + return ["polyline", { ...this.attribs, fill: "none" }, this.points]; + } + + toHiccupPathSegments() { + const res: any[] = []; + for (let pts = this.points, n = pts.length, i = 1; i < n; i++) { + res.push(["L", pts[i]]); + } + return res; + } +} + +export class Quad extends APC implements + IHiccupShape { + + get type() { + return Type.QUAD; + } + + copy() { + return new Quad(copyPoints(this.points), { ...this.attribs }); + } + + toHiccup() { + return ["polygon", this.attribs, this.points]; + } } -export interface JsonPolygon2 extends JsonShape { - points: Vec[]; +export class Quadratic extends APC implements + IHiccupShape, + IHiccupPathSegment { + + get type() { + return Type.QUADRATIC; + } + + copy() { + return new Quadratic(copyPoints(this.points), { ...this.attribs }); + } + + toHiccup() { + return ["path", this.attribs, + [ + ["M", this.points[0]], + ...this.toHiccupPathSegments() + ] + ]; + } + + toHiccupPathSegments() { + const pts = this.points; + return [["Q", pts[1], pts[2]]]; + } } -export interface JsonPolyline2 extends JsonShape { - points: Vec[]; +export class Ray implements + IHiccupShape { + + pos: Vec; + dir: Vec; + attribs: Attribs; + + constructor(pos: Vec, dir: Vec, attribs?: Attribs) { + this.pos = pos; + this.dir = dir; + this.attribs = attribs; + } + + get type() { + return Type.RAY; + } + + copy() { + return new Ray(set([], this.pos), set([], this.dir), { ...this.attribs }); + } + + toHiccup() { + return ["line", this.attribs, this.pos, maddN2([], this.pos, this.dir, 1e6)]; + } } -export interface JsonRect2 extends JsonShape { +export class Rect implements + AABBLike, + IHiccupShape { + pos: Vec; - size: Vec[]; + size: Vec; + attribs: Attribs; + + constructor(pos: Vec = [0, 0], size: number | Vec = [1, 1], attribs?: Attribs) { + this.pos = pos; + this.size = isNumber(size) ? [size, size] : size; + this.attribs = attribs; + } + + get type() { + return Type.RECT; + } + + copy() { + return new Rect(set([], this.pos), set([], this.size), { ...this.attribs }); + } + + max() { + return add2([], this.pos, this.size); + } + + toHiccup() { + return ["rect", this.attribs, this.pos, this.size]; + } } -export type HiccupArc2 = - ["arc", Attribs, ReadonlyVec, ReadonlyVec, number, number, number, boolean, boolean]; +export class Sphere implements + IHiccupShape { -export type HiccupCircle2 = - ["circle", Attribs, ReadonlyVec, number]; + pos: Vec; + r: number; + attribs: Attribs; + + constructor(pos: Vec = [0, 0, 0], r = 1, attribs?: Attribs) { + this.pos = pos; + this.r = r; + this.attribs = attribs; + } + + get type() { + return Type.SPHERE; + } -export type HiccupLine2 = - ["line", Attribs, ReadonlyVec, ReadonlyVec]; + copy() { + return new Sphere(set([], this.pos), this.r, { ...this.attribs }); + } -export type HiccupPolygon2 = - ["polygon", Attribs, number[] | number[][]]; + toHiccup() { + return ["sphere", this.attribs, this.pos, this.r]; + } +} + +export class Triangle extends APC implements + IHiccupShape { -export type HiccupPolyline2 = - ["polyline", Attribs, number[] | number[][]]; + get type() { + return Type.TRIANGLE; + } -export type HiccupRect2 = - ["rect", Attribs, ReadonlyVec, number, number, number?]; + copy() { + return new Triangle(copyPoints(this.points), { ...this.attribs }); + } + + toHiccup() { + return ["polygon", this.attribs, this.points]; + } +} diff --git a/packages/geom/src/arc2.ts b/packages/geom/src/arc2.ts deleted file mode 100644 index 2916ef26e9..0000000000 --- a/packages/geom/src/arc2.ts +++ /dev/null @@ -1,304 +0,0 @@ -import { ICopy } from "@thi.ng/api"; -import { isNumber } from "@thi.ng/checks/is-number"; -import { isPlainObject } from "@thi.ng/checks/is-plain-object"; -import { sincos } from "@thi.ng/math/angle"; -import { - EPS, - HALF_PI, - PI, - TAU -} from "@thi.ng/math/api"; -import { inRange } from "@thi.ng/math/interval"; -import { mix } from "@thi.ng/math/mix"; -import { roundEps } from "@thi.ng/math/prec"; -import { range } from "@thi.ng/transducers/iter/range"; -import { push } from "@thi.ng/transducers/rfn/push"; -import { transduce } from "@thi.ng/transducers/transduce"; -import { filter } from "@thi.ng/transducers/xform/filter"; -import { map } from "@thi.ng/transducers/xform/map"; -import { Vec } from "@thi.ng/vectors/api"; -import { - add2, - asVec2, - rotate2, - setS2, - Vec2 -} from "@thi.ng/vectors/vec2"; -import { - Attribs, - DEFAULT_SAMPLES, - HiccupArc2, - IBounds, - IBoundsRaw, - IEdges, - IVertices, - JsonArc2, - SamplingOpts -} from "./api"; -import { Cubic2 } from "./bezier2"; -import { bounds } from "./internal/bounds"; -import { edges } from "./internal/edges"; -import { Rect2 } from "./rect2"; -import { Sampler } from "./sampler"; - -export class Arc2 implements - IBounds, - IBoundsRaw, - ICopy, - IEdges, - IVertices> { - - static fromJSON(spec: JsonArc2) { - return new Arc2( - new Vec2(spec.pos), - new Vec2(spec.r), - spec.axis, - spec.start, - spec.end, - spec.xl, - spec.clockwise, - spec.attribs - ); - } - - static fromHiccup(spec: HiccupArc2) { - return new Arc2( - asVec2(spec[2]), - asVec2(spec[3]), - spec[4], - spec[5], - spec[6], - spec[7], - spec[8], - spec[1] - ); - } - - static from2Points( - a: Readonly, - b: Readonly, - radii: Readonly, - axisTheta = 0, - large = false, - clockwise = true) { - - const r = radii.copy().abs(); - const co = Math.cos(axisTheta); - const si = Math.sin(axisTheta); - const m = a.subNew(b).mulN(0.5); - const px = co * m.x + si * m.y; - const py = -si * m.x + co * m.y; - const px2 = px * px; - const py2 = py * py; - - const l = px2 / (r.x * r.x) + py2 / (r.y * r.y); - l > 1 && r.mulN(Math.sqrt(l)); - - const rx2 = r.x * r.x; - const ry2 = r.y * r.y; - const rxpy = rx2 * py2; - const rypx = ry2 * px2; - const rad = ((large === clockwise) ? -1 : 1) * - Math.sqrt(Math.max(0, rx2 * ry2 - rxpy - rypx) / (rxpy + rypx)); - - const tc = new Vec2([rad * r.x / r.y * py, rad * -r.y / r.x * px]); - const c = new Vec2([co * tc.x - si * tc.y + (a.x + b.x) / 2, si * tc.x + co * tc.y + (a.y + b.y) / 2]); - const d1 = new Vec2([(px - tc.x) / r.x, (py - tc.y) / r.y]); - const d2 = new Vec2([(-px - tc.x) / r.x, (-py - tc.y) / r.y]); - - const theta = Vec2.X_AXIS.angleBetween(d1, true); - let delta = d1.angleBetween(d2, true); - - if (clockwise && delta < 0) { - delta += TAU; - } else if (!clockwise && delta > 0) { - delta -= TAU; - } - - return new Arc2(c, r, axisTheta, theta, theta + delta, large, clockwise); - } - - pos: Vec2; - r: Vec2; - axis: number; - start: number; - end: number; - xl: boolean; - clockwise: boolean; - attribs: Attribs; - - constructor( - pos: Vec2, - r: Vec2, - axis: number, - start: number, - end: number, - xl = false, - clockwise = false, - attribs?: Attribs) { - - this.pos = pos; - this.r = r; - this.axis = axis; - this.start = start; - this.end = end; - this.clockwise = clockwise; - this.xl = xl; - this.attribs = attribs; - } - - copy() { - return new Arc2( - this.pos.copy(), - this.r.copy(), - this.axis, - this.start, - this.end, - this.xl, - this.clockwise, - { ...this.attribs } - ); - } - - boundsRaw() { - // https://stackoverflow.com/a/1336739/294515 - const pts = transduce( - map(this.pointAtTheta.bind(this)), - push(), - [ - this.start, - this.end, - // multiples of HALF_PI in arc range - ...filter( - (t: number) => inRange(t, this.start, this.end), - range(-3 * PI, 3.01 * PI, HALF_PI) - ) - ] - ); - return bounds(pts, Vec2.MAX.copy(), Vec2.MIN.copy()); - } - - bounds() { - return Rect2.fromMinMax(...this.boundsRaw()); - } - - edges(opts?: number | Partial) { - return edges(this.vertices(opts)); - } - - pointAt(t: number) { - return this.pointAtTheta(mix(this.start, this.end, t)); - } - - pointAtTheta(theta: number, pos?: Vec2) { - return (pos || new Vec2()) - .setS(Math.cos(theta), Math.sin(theta)) - .mul(this.r) - .rotate(this.axis) - .add(this.pos); - } - - vertices(opts?: number | Partial): Vec2[] { - if (isPlainObject(opts) && (opts).dist !== undefined) { - return new Sampler(this.vertices((opts).num || DEFAULT_SAMPLES)) - .sampleUniform((opts).dist, (opts).last !== false); - } - opts = isNumber(opts) ? - { num: opts, last: true } : - { num: DEFAULT_SAMPLES, ...opts }; - let num: number; - const start = this.start; - let delta = this.end - start; - num = opts.theta ? - Math.round(delta / opts.theta) : - opts.num; - delta /= num; - opts.last !== false && num++; - const pts: Vec = new Array(num * 2); - const pos = this.pos; - const [rx, ry] = this.r; - const axis = this.axis; - for (let i = 0, j = 0; i < num; i++ , j += 2) { - const t = start + i * delta; - setS2(pts, Math.cos(t) * rx, Math.sin(t) * ry, j); - rotate2(pts, axis, j); - add2(pts, pos.buf, j, pos.i, 1, pos.s); - } - return Vec2.mapBuffer(pts, num); - } - - toCubic() { - const p = this.pointAtTheta(this.start); - const q = this.pointAtTheta(this.end); - const [rx, ry] = this.r; - const [sphi, cphi] = sincos(this.axis); - const dx = cphi * (p.x - q.x) / 2 + sphi * (p.y - q.y) / 2; - const dy = -sphi * (p.x - q.x) / 2 + cphi * (p.y - q.y) / 2; - if ((dx === 0 && dy === 0) || this.r.magSq() < EPS) { - return [Cubic2.fromLine(p, q, { ...this.attribs })]; - } - - const mapP = (x, y) => { - x *= rx; - y *= ry; - return new Vec2([ - cphi * x - sphi * y, - sphi * x + cphi * y - ]).add(this.pos); - }; - - const res: Cubic2[] = []; - const delta = this.end - this.start; - const n = Math.max(roundEps(Math.abs(delta) / HALF_PI), 1); - // https://github.com/chromium/chromium/blob/master/third_party/blink/renderer/core/svg/svg_path_parser.cc#L253 - const d = delta / n; - const t = 8 / 6 * Math.tan(0.25 * d); - if (!isFinite(t)) { - return [Cubic2.fromLine(p, q)]; - } - for (let i = n, theta = this.start; i > 0; i-- , theta += d) { - const [s1, c1] = sincos(theta); - const [s2, c2] = sincos(theta + d); - const curve = new Cubic2([ - mapP(c1, s1), - mapP(c1 - s1 * t, s1 + c1 * t), - mapP(c2 + s2 * t, s2 - c2 * t), - mapP(c2, s2), - ]); - res.push(curve); - } - return res; - } - - toHiccup() { - return ["path", this.attribs, [ - ["M", this.pointAtTheta(this.start)], - ...this.toHiccupPathSegments() - ]]; - } - - toHiccupPathSegments() { - return [["A", - this.r.x, - this.r.y, - this.axis, - this.xl, - this.clockwise, - this.pointAtTheta(this.end) - ]]; - } - - toJSON(): JsonArc2 { - return { - type: "arc2", - pos: this.pos.toJSON(), - r: this.r.toJSON(), - start: this.start, - end: this.end, - axis: this.axis, - xl: this.xl, - clockwise: this.clockwise, - attribs: this.attribs, - }; - } -} diff --git a/packages/geom/src/bezier2.ts b/packages/geom/src/bezier2.ts deleted file mode 100644 index b3e6da3469..0000000000 --- a/packages/geom/src/bezier2.ts +++ /dev/null @@ -1,315 +0,0 @@ -import { ICopy } from "@thi.ng/api"; -import { isNumber } from "@thi.ng/checks/is-number"; -import { isPlainObject } from "@thi.ng/checks/is-plain-object"; -import { clamp01 } from "@thi.ng/math/interval"; -import { mixCubic as _mixC, mixQuadratic as _mixQ } from "@thi.ng/math/mix"; -import { IMath, ReadonlyVec, Vec } from "@thi.ng/vectors/api"; -import { Vec2 } from "@thi.ng/vectors/vec2"; -import { - Attribs, - DEFAULT_SAMPLES, - IToCubic, - IVertices, - JsonCubic2, - JsonQuadratic2, - SamplingOpts -} from "./api"; -import { PointContainer2 } from "./container2"; -import { args3, args4 } from "./internal/args"; -import { Sampler } from "./sampler"; - -export const mixQuadratic = & IMath>(a: T, b: T, c: T, t: number) => { - const s = 1 - t; - return a.mulNewN(s * s) - .maddN(b, 2 * s * t) - .maddN(c, t * t); -}; - -export const mixCubic = & IMath>(a: T, b: T, c: T, d: T, t: number) => { - const t2 = t * t; - const s = 1 - t; - const s2 = s * s; - return a.mulNewN(s2 * s) - .maddN(b, 3 * s2 * t) - .maddN(c, 3 * t2 * s) - .maddN(d, t2 * t); -}; - -const cubicAxisBounds = (pa: number, pb: number, pc: number, pd: number) => { - let a = 3 * pd - 9 * pc + 9 * pb - 3 * pa; - let b = 6 * pa - 12 * pb + 6 * pc; - let c = 3 * pb - 3 * pa; - let disc = b * b - 4 * a * c; - let l = pa; - let h = pa; - - const bounds = (t: number) => { - if (t > 0 && t < 1) { - const x = _mixC(pa, pb, pc, pd, t); - x < l && (l = x); - x > h && (h = x); - } - }; - - pd < l && (l = pd); - pd > h && (h = pd); - if (disc >= 0) { - disc = Math.sqrt(disc); - a *= 2; - bounds((-b + disc) / a); - bounds((-b - disc) / a); - } - return [l, h]; -}; - -export class Cubic2 extends PointContainer2 implements - IToCubic, - IVertices> { - - static fromJSON(spec: JsonCubic2) { - return cubic2(spec.points, spec.attribs); - } - - static fromLine(a: Vec2, b: Vec2, attribs?: Attribs) { - return new Cubic2([a, a.mixNewN(b, 1 / 3), b.mixNewN(a, 1 / 3), b], attribs); - } - - copy() { - return new Cubic2(this._copy(), this.attribs); - } - - boundsRaw(): [Vec2, Vec2] { - // https://stackoverflow.com/a/24814530/294515 - // https://iquilezles.org/www/articles/bezierbbox/bezierbbox.htm - const [a, b, c, d] = this.points; - const x = cubicAxisBounds(a.x, b.x, c.x, d.x); - const y = cubicAxisBounds(a.y, b.y, c.y, d.y); - return Vec2.mapBuffer([x[0], y[0], x[1], y[1]], 2); - } - - pointAt(t: number) { - const pts = this.points; - return mixCubic(pts[0], pts[1], pts[2], pts[3], t); - } - - /** - * Splits curve into 2 sub-curves at position `t`. - * - * http://en.wikipedia.org/wiki/De_Casteljau%27s_algorithm - * - * @param t - */ - splitAt(t: number): [Cubic2, Cubic2] { - const [a, b, c, d] = this.points; - if (t <= 0 || t >= 1) { - const p = t <= 0 ? a : d; - const c1 = new Cubic2(Vec2.mapBuffer([p.x, p.y, p.x, p.y, p.x, p.y], 4)); - const c2 = new Cubic2(Vec2.mapBuffer([a.x, a.y, b.x, b.y, c.x, c.y, d.x, d.y], 4)); - return t <= 0 ? [c1, c2] : [c2, c1]; - } - const ab = a.mixNewN(b, t); - const bc = b.mixNewN(c, t); - const cd = c.mixNewN(d, t); - const abc = ab.mixNewN(bc, t); - const bcd = bc.mixNewN(cd, t); - const p = abc.mixNewN(bcd, t); - return [ - new Cubic2(Vec2.mapBuffer([a.x, a.y, ab.x, ab.y, abc.x, abc.y, p.x, p.y], 4)), - new Cubic2(Vec2.mapBuffer([p.x, p.y, bcd.x, bcd.y, cd.x, cd.y, d.x, d.y], 4)) - ]; - } - - vertices(opts?: Partial) { - if (isPlainObject(opts) && (opts).dist !== undefined) { - return new Sampler(this.vertices((opts).num || DEFAULT_SAMPLES)) - .sampleUniform((opts).dist, (opts).last !== false); - } - opts = isNumber(opts) ? - { - num: opts, - last: true - } : - { - num: DEFAULT_SAMPLES, - ...opts - }; - const res: number[] = []; - const [a, b, c, d] = this.points; - const delta = 1 / opts.num; - for (let t = 0; t < opts.num; t++) { - res.push( - _mixC(a.x, b.x, c.x, d.x, t * delta), - _mixC(a.y, b.y, c.y, d.y, t * delta) - ); - } - opts.last && res.push(d.x, d.y); - return Vec2.mapBuffer(res); - } - - toCubic() { - return [this]; - } - - toHiccup() { - return ["path", this.attribs, - [ - ["M", this.points[0]], - ...this.toHiccupPathSegments() - ] - ]; - } - - toHiccupPathSegments() { - const pts = this.points; - return [["C", pts[1], pts[2], pts[3]]]; - } - - toJSON() { - return this._toJSON("cubic2"); - } -} - -export class Quadratic2 extends PointContainer2 implements - IToCubic, - IVertices> { - - static fromJSON(spec: JsonQuadratic2) { - return quadratic2(spec.points, spec.attribs); - } - - static fromLine(a: Vec2, b: Vec2, attribs?: Attribs) { - return new Quadratic2([a, a.mixNewN(b), b], attribs); - } - - copy() { - return new Quadratic2(this._copy(), this.attribs); - } - - boundsRaw(): [Vec2, Vec2] { - const [a, b, c] = this.points; - const mi = a.copy().min(c); - const ma = a.copy().max(c); - const solve = (a, b, c) => { - const t = clamp01((a - b) / (a - 2.0 * b + c)); - const s = 1 - t; - return s * s * a + 2.0 * s * t * b + t * t * c; - }; - if (b.x < mi.x || b.x > ma.x || b.y < mi.y || b.y > ma.y) { - const q = new Vec2([ - solve(a.x, b.x, c.x), - solve(a.y, b.y, c.y), - ]); - mi.min(q); - ma.max(q); - } - return [mi, ma]; - } - - pointAt(t: number) { - const pts = this.points; - return mixQuadratic(pts[0], pts[1], pts[2], t); - } - - /** - * Splits curve into 2 sub-curves at position `t`. - * - * http://en.wikipedia.org/wiki/De_Casteljau%27s_algorithm - * - * @param t - */ - splitAt(t: number): [Quadratic2, Quadratic2] { - const [a, b, c] = this.points; - if (t == 0) { - return [ - new Quadratic2(this._copy([a, a, a])), - new Quadratic2(this._copy([a, b, c])) - ]; - } - if (t == 1) { - return [ - new Quadratic2(this._copy([a, b, c])), - new Quadratic2(this._copy([c, c, c])) - ]; - } - const ab = a.mixNewN(b, t); - const bc = b.mixNewN(c, t); - const p = ab.mixNewN(bc, t); - return [ - new Quadratic2([a.copy(), ab, p]), - new Quadratic2([p, bc, c.copy()]) - ]; - } - - vertices(opts?: number | Partial) { - if (isPlainObject(opts) && (opts).dist !== undefined) { - return new Sampler(this.vertices((opts).num || DEFAULT_SAMPLES)) - .sampleUniform((opts).dist, (opts).last !== false); - } - opts = isNumber(opts) ? - { - num: opts, - last: true - } : - { - num: DEFAULT_SAMPLES, - ...opts - }; - const res: number[] = []; - const delta = 1 / opts.num; - const [a, b, c] = this.points; - for (let t = 0; t < opts.num; t++) { - res.push( - _mixQ(a.x, b.x, c.x, t * delta), - _mixQ(a.y, b.y, c.y, t * delta) - ); - } - opts.last && res.push(c.x, c.y); - return Vec2.mapBuffer(res); - } - - toCubic() { - const [a, b, c] = this.points; - return [ - new Cubic2([ - a.copy(), - a.mulNewN(1 / 3).maddN(b, 2 / 3), - c.mulNewN(1 / 3).maddN(b, 2 / 3), - c.copy() - ]) - ]; - } - - toHiccup() { - return ["path", this.attribs, - [ - ["M", this.points[0]], - ...this.toHiccupPathSegments() - ] - ]; - } - - toHiccupPathSegments() { - const pts = this.points; - return [["Q", pts[1], pts[2]]]; - } - - toJSON() { - return this._toJSON("quadratic2"); - } -} - -export function cubic2(points: Vec, start?: number, cstride?: number, estride?: number, attribs?: Attribs): Cubic2; -export function cubic2(a: ReadonlyVec, b: ReadonlyVec, c: ReadonlyVec, d: ReadonlyVec, attribs?: Attribs): Cubic2; -export function cubic2(points: ReadonlyVec[], attribs?: Attribs): Cubic2; -export function cubic2(...args: any[]) { - const [points, attribs] = args4(args); - return new Cubic2(points, attribs); -} - -export function quadratic2(points: Vec, start?: number, cstride?: number, estride?: number, attribs?: Attribs): Quadratic2; -export function quadratic2(a: Vec2 | ReadonlyVec, b: Vec2 | ReadonlyVec, c: Vec2 | ReadonlyVec, attribs?: Attribs): Quadratic2; -export function quadratic2(points: ReadonlyVec[], attribs?: Attribs): Quadratic2; -export function quadratic2(...args: any[]) { - const [points, attribs] = args3(args); - return new Quadratic2(points, attribs); -} diff --git a/packages/geom/src/circle2.ts b/packages/geom/src/circle2.ts deleted file mode 100644 index edbec805e1..0000000000 --- a/packages/geom/src/circle2.ts +++ /dev/null @@ -1,193 +0,0 @@ -import { IToHiccup } from "@thi.ng/api/api"; -import { isArrayLike } from "@thi.ng/checks/is-arraylike"; -import { isNumber } from "@thi.ng/checks/is-number"; -import { isPlainObject } from "@thi.ng/checks/is-plain-object"; -import { PI, TAU } from "@thi.ng/math/api"; -import { eqDelta } from "@thi.ng/math/eqdelta"; -import { ReadonlyVec, Vec } from "@thi.ng/vectors/api"; -import { - asVec2, - setS2, - toCartesian2, - Vec2 -} from "@thi.ng/vectors/vec2"; -import { - Attribs, - DEFAULT_SAMPLES, - HiccupCircle2, - IArcLength, - IBounds, - IBoundsRaw, - ICentroid, - IClassifyPoint, - IPointInside, - IToPolygon, - IVertices, - JsonCircle2, - SamplingOpts -} from "./api"; -import { circumCenter } from "./internal/circumcenter"; -import { edges } from "./internal/edges"; -import { Polygon2 } from "./polygon2"; -import { Rect2 } from "./rect2"; - -export class Circle2 implements - IArcLength, - IBoundsRaw, - IBounds, - ICentroid, - IClassifyPoint, - IPointInside, - IToHiccup, - IToPolygon>, - IVertices> { - - static fromJSON(spec: JsonCircle2) { - return new Circle2( - new Vec2(spec.pos), - spec.r, - spec.attribs - ); - } - - static fromHiccup(spec: HiccupCircle2) { - return new Circle2(asVec2(spec[2]), spec[3], spec[1]); - } - - static from2Points(a: Readonly, b: Readonly, attribs?: Attribs) { - return new Circle2(a.mixNewN(b), a.dist(b) / 2, attribs); - } - static from3Points(a: Readonly, b: Readonly, c: Readonly, attribs?: Attribs) { - const o = circumCenter(a, b, c); - if (o) { - return new Circle2(o, a.dist(o), attribs); - } - } - - pos: Vec2; - r: number; - attribs: Attribs; - - constructor(pos: Vec2, r = 1, attribs?: Attribs) { - this.pos = pos; - this.r = r; - this.attribs = attribs; - } - - copy() { - return new Circle2(this.pos.copy(), this.r, { ...this.attribs }); - } - - edges(opts?: Partial) { - return edges(this.vertices(opts)); - } - - vertices(opts?: number | Partial) { - let [num, last] = isNumber(opts) ? - [opts, false] : - [ - opts.theta ? - Math.floor(TAU / opts.theta) : - opts.dist ? - Math.floor(TAU / (opts.dist / this.r)) : - opts.num || DEFAULT_SAMPLES, - opts.last === true - ]; - const buf: Vec = []; - const pos = this.pos.buf; - const po = this.pos.i; - const ps = this.pos.s; - const r = this.r; - const delta = TAU / num; - last && num++; - for (let i = 0; i < num; i++) { - toCartesian2( - setS2(buf, r, i * delta, i * 2), - pos, i * 2, po, 1, ps - ); - } - return Vec2.mapBuffer(buf, num); - } - - area() { - return PI * this.r * this.r; - } - - arcLength() { - return TAU * this.r; - } - - boundsRaw(): [Vec2, Vec2] { - return [ - this.pos.subNewN(this.r), - this.pos.addNewN(this.r) - ]; - } - - bounds(): Rect2 { - return new Rect2( - this.pos.subNewN(this.r), - new Vec2([this.r, this.r]) - ); - } - - centroid(c?: Vec2) { - return c ? c.set(this.pos) : this.pos; - } - - classifyPoint(p: Readonly) { - const d = p.distSq(this.pos); - const r = this.r * this.r; - return eqDelta(d, r) ? 0 : d < r ? 1 : -1; - } - - pointInside(p: Readonly) { - return this.classifyPoint(p) >= 0; - } - - toPolygon(opts?: number | Partial) { - return new Polygon2(this.vertices(opts)); - } - - toHiccup(): HiccupCircle2 { - return ["circle", this.attribs || {}, this.pos, this.r]; - } - - toJSON() { - return { - type: "circle2", - pos: this.pos.toJSON(), - r: this.r, - attribs: this.attribs, - }; - } -} - -export function circle2(r: number, attribs?: Attribs): Circle2; -export function circle2(x: number, y: number, attribs?: Attribs): Circle2; -export function circle2(x: number, y: number, r: number, attribs?: Attribs): Circle2; -export function circle2(pos: ReadonlyVec, attribs?: Attribs): Circle2; -export function circle2(pos: ReadonlyVec, r: number, attribs?: Attribs): Circle2; -export function circle2(...args: any[]) { - let attribs; - let n = args.length - 1; - if (isPlainObject(args[n]) || args[n] == null) { - attribs = args[n]; - n--; - } - if (isArrayLike(args[0])) { - return new Circle2( - asVec2(args[0]), - n === 1 ? args[n] : 1, - attribs - ); - } - if (n > 0) { - return new Circle2( - new Vec2([args[0], args[1]]), - n === 2 ? args[n] : 1, - attribs - ); - } - return new Circle2(new Vec2(), args[0], attribs); -} diff --git a/packages/geom/src/container2.ts b/packages/geom/src/container2.ts deleted file mode 100644 index d3f8c066fa..0000000000 --- a/packages/geom/src/container2.ts +++ /dev/null @@ -1,134 +0,0 @@ -import { Mat23 } from "@thi.ng/vectors/mat23"; -import { Vec2 } from "@thi.ng/vectors/vec2"; -import { - Attribs, - CollateOpts, - IBounds, - IBoundsRaw, - ICenter, - ICentroid, - ICollate, - IVertices -} from "./api"; -import { fitIntoBounds2 } from "./fit"; -import { bounds } from "./internal/bounds"; -import { centroid } from "./internal/centroid"; -import { collateWith } from "./internal/collate"; -import { convexHull } from "./internal/graham-scan"; -import { Rect2 } from "./rect2"; - -export class PointContainer2 implements - IBoundsRaw, - IBounds, - ICentroid, - ICenter, - ICollate, - IVertices { - - points: Vec2[]; - attribs: Attribs; - - constructor(pts: Vec2[], attribs?: Attribs) { - this.points = pts; - this.attribs = attribs; - } - - *[Symbol.iterator]() { - yield* this.vertices(); - } - - collate(opts?: Partial) { - return collateWith(Vec2.intoBuffer, this.points, opts, 2); - } - - vertices() { - return this.points; - } - - boundsRaw() { - return bounds(this.points, Vec2.MAX.copy(), Vec2.MIN.copy()); - } - - bounds(): Rect2 { - return Rect2.fromMinMax(...this.boundsRaw()); - } - - convextHull() { - return convexHull(this.points); - } - - centroid(c?: Vec2) { - return centroid(this.points, c || new Vec2()); - } - - center(origin?: Readonly) { - const d = this.centroid().neg(); - return this.translate(origin ? d.add(origin) : d); - } - - flip() { - this.points.reverse(); - return this; - } - - fit(bounds: Rect2) { - fitIntoBounds2(this, bounds); - return this; - } - - rotate(theta: number) { - const pts = this.points; - for (let i = pts.length; --i >= 0;) { - pts[i].rotate(theta); - } - return this; - } - - scale(v: Readonly) { - const pts = this.points; - for (let i = pts.length; --i >= 0;) { - pts[i].mul(v); - } - return this; - } - - scaleN(n: number) { - const pts = this.points; - for (let i = pts.length; --i >= 0;) { - pts[i].mulN(n); - } - return this; - } - - translate(v: Readonly) { - const pts = this.points; - for (let i = pts.length; --i >= 0;) { - pts[i].add(v); - } - return this; - } - - transform(mat: Readonly) { - const pts = this.points; - for (let i = pts.length; --i >= 0;) { - mat.mulV(pts[i]); - } - return this; - } - - protected _copy(pts = this.points) { - return Vec2.mapBuffer(Vec2.intoBuffer([], pts), pts.length); - } - - protected _toJSON(type: string) { - return { - type, - attribs: this.attribs, - points: this.points.map((p) => p.toJSON()) - }; - } - - protected _toHiccup(type: string) { - return [type, this.attribs, this.points]; - } -} diff --git a/packages/geom/src/container3.ts b/packages/geom/src/container3.ts deleted file mode 100644 index c8149bfad0..0000000000 --- a/packages/geom/src/container3.ts +++ /dev/null @@ -1,109 +0,0 @@ -import { illegalArgs } from "@thi.ng/errors/illegal-arguments"; -import { Mat44 } from "@thi.ng/vectors/mat44"; -import { Vec3, vec3 } from "@thi.ng/vectors/vec3"; -import { - Attribs, - CollateOpts, - IBounds, - IBoundsRaw, - ICenter, - ICentroid, - ICollate, - IVertices -} from "./api"; -import { bounds } from "./internal/bounds"; -import { collateWith } from "./internal/collate"; - -export class PointContainer3 implements - IBoundsRaw, - IBounds, // TODO - ICentroid, - ICenter, - ICollate, - IVertices { - - points: Vec3[]; - attribs: Attribs; - - constructor(pts: Vec3[], attribs?: Attribs) { - this.points = pts; - this.attribs = attribs; - } - - *[Symbol.iterator]() { - yield* this.vertices(); - } - - collate(opts?: Partial) { - return collateWith(Vec3.intoBuffer, this.points, opts, 3); - } - - vertices() { - return this.points; - } - - boundsRaw() { - return bounds(this.points, Vec3.MAX.copy(), Vec3.MIN.copy()); - } - - bounds() { - return this.boundsRaw(); - } - - centroid(c?: Vec3): Vec3 { - const pts = this.points; - const num = pts.length; - !num && illegalArgs("no points available"); - !c && (c = vec3()); - for (let i = num; --i >= 0;) { - c.add(pts[i]); - } - return c.divN(num); - } - - center(p?: Readonly) { - const d = this.centroid().neg(); - return this.translate(p ? d.add(p) : d); - } - - flip() { - this.points.reverse(); - return this; - } - - scale(v: Readonly) { - const pts = this.points; - for (let i = pts.length; --i >= 0;) { - pts[i].mul(v); - } - return this; - } - - translate(v: Readonly) { - const pts = this.points; - for (let i = pts.length; --i >= 0;) { - pts[i].add(v); - } - return this; - } - - transform(mat: Readonly) { - const pts = this.points; - for (let i = pts.length; --i >= 0;) { - mat.mulV3(pts[i]); - } - return this; - } - - protected _copy() { - return Vec3.mapBuffer(Vec3.intoBuffer([], this.points), this.points.length); - } - - protected _toJSON(type: string) { - return { - type, - attribs: this.attribs, - points: this.points.map((p) => p.toJSON()) - }; - } -} diff --git a/packages/geom/src/ctors/arc.ts b/packages/geom/src/ctors/arc.ts new file mode 100644 index 0000000000..9878354394 --- /dev/null +++ b/packages/geom/src/ctors/arc.ts @@ -0,0 +1,96 @@ +import { isNumber } from "@thi.ng/checks"; +import { EPS, TAU } from "@thi.ng/math"; +import { + abs2, + angleBetween2, + div2, + eqDelta2, + mulN2, + neg, + powN2, + ReadonlyVec, + sub2, + submN2, + Vec, + X2 +} from "@thi.ng/vectors"; +import { Arc } from "../api"; + +export const arc = ( + pos: Vec, + r: number | Vec, + axis: number, + start: number, + end: number, + xl = false, + clockwise = false +) => new Arc(pos, isNumber(r) ? [r, r] : r, axis, start, end, xl, clockwise); + +/** + * https://svgwg.org/svg2-draft/implnote.html#ArcConversionEndpointToCenter + * + * Returns undefined if `a` & `b` are equal or any `radii` component is + * zero. + * + * @param a start point + * @param b end point + * @param radii ellipse radii + * @param axisTheta in radians + * @param xl large arc flag + * @param cw clockwise flag + */ +export const arcFrom2Points = ( + a: ReadonlyVec, + b: ReadonlyVec, + radii: ReadonlyVec, + axisTheta = 0, + xl = false, + cw = false +) => { + + const r = abs2([], radii); + if (eqDelta2(a, b) || r[0] < EPS || r[1] < EPS) { + return; + } + axisTheta %= TAU; + const d = submN2([], a, b, 0.5); + const c = Math.cos(axisTheta); + const s = Math.sin(axisTheta); + // transformed point + const tp = [ + c * d[0] + s * d[1], + -s * d[0] + c * d[1] + ]; + const [tx2, ty2] = powN2([], tp, 2); + // ensure radii + const rc = tx2 / (r[0] * r[0]) + ty2 / (r[1] * r[1]); + rc > 1 && mulN2(r, r, Math.sqrt(rc)); + const [rx, ry] = r; + const rx2 = rx * rx; + const ry2 = ry * ry; + // transformed center + const radicant = Math.max(0, (rx2 * ry2 - rx2 * ty2 - ry2 * tx2) / (rx2 * ty2 + ry2 * tx2)); + const coeff = (xl !== cw ? 1 : -1) * Math.sqrt(radicant); + const tc = [ + coeff * ((rx * tp[1]) / ry), + coeff * (-(ry * tp[0]) / rx) + ]; + // actual center + const center = [ + c * tc[0] - s * tc[1] + (a[0] + b[0]) / 2, + s * tc[0] + c * tc[1] + (a[1] + b[1]) / 2 + ]; + // transformed end points & angles + const ta = div2(null, sub2([], tp, tc), r); + const tb = div2(null, sub2(null, neg([], tp), tc), r); + const start = angleBetween2(X2, ta); + let sweep = angleBetween2(ta, tb); + if (!cw && sweep > 0) { + sweep -= TAU; + } else if (cw && sweep < 0) { + sweep += TAU; + } + sweep %= TAU; + + return new Arc(center, r, axisTheta, start, start + sweep, xl, cw); +}; diff --git a/packages/geom/src/ctors/circle.ts b/packages/geom/src/ctors/circle.ts new file mode 100644 index 0000000000..9eda53bf3e --- /dev/null +++ b/packages/geom/src/ctors/circle.ts @@ -0,0 +1,27 @@ +import { + dist, + mixN2, + ReadonlyVec, + Vec +} from "@thi.ng/vectors"; +import { Attribs, Circle } from "../api"; +import { argsVN } from "../internal/args"; +import { circumCenter } from "../internal/circumcenter"; + +export function circle(pos: Vec, r: number, attribs?: Attribs): Circle; +export function circle(pos: Vec, attribs?: Attribs): Circle; +export function circle(r: number, attribs?: Attribs): Circle; +export function circle(attribs?: Attribs): Circle; +export function circle(...args: any[]) { + return new Circle(...argsVN(args)); +} + +export const circleFrom2Points = + (a: ReadonlyVec, b: ReadonlyVec, attribs?: Attribs) => + new Circle(mixN2([], a, b, 0.5), dist(a, b) / 2, attribs); + +export const circleFrom3Points = + (a: ReadonlyVec, b: ReadonlyVec, c: ReadonlyVec, attribs?: Attribs) => { + const o = circumCenter(a, b, c); + return o ? new Circle(o, dist(a, o), attribs) : undefined; + }; diff --git a/packages/geom/src/ctors/cubic.ts b/packages/geom/src/ctors/cubic.ts new file mode 100644 index 0000000000..2eb1b32c94 --- /dev/null +++ b/packages/geom/src/ctors/cubic.ts @@ -0,0 +1,90 @@ +import { + EPS, + HALF_PI, + roundEps, + sincos +} from "@thi.ng/math"; +import { + add2, + magSq2, + mixN2, + set2, + Vec +} from "@thi.ng/vectors"; +import { Arc, Attribs, Cubic } from "../api"; +import { argAttribs } from "../internal/args"; + +export function cubic(a: Vec, b: Vec, c: Vec, d: Vec, attribs?: Attribs): Cubic; +export function cubic(pts: Vec[], attribs?: Attribs): Cubic; +export function cubic(...args: any[]) { + const attr = argAttribs(args); + return new Cubic(args.length === 1 ? args[0] : args, attr); +} + +export const cubicFromArc = + (arc: Arc) => { + const p = arc.pointAtTheta(arc.start); + const q = arc.pointAtTheta(arc.end); + const [rx, ry] = arc.r; + const [sphi, cphi] = sincos(arc.axis); + const dx = cphi * (p[0] - q[0]) / 2 + sphi * (p[1] - q[1]) / 2; + const dy = -sphi * (p[0] - q[0]) / 2 + cphi * (p[1] - q[1]) / 2; + if ((dx === 0 && dy === 0) || magSq2(arc.r) < EPS) { + return [cubicFromLine(p, q, { ...arc.attribs })]; + } + + // TODO use mat23 + const mapP = (x: number, y: number) => { + x *= rx; + y *= ry; + return add2( + null, + [ + cphi * x - sphi * y, + sphi * x + cphi * y + ], + arc.pos + ); + }; + + const res: Cubic[] = []; + const delta = arc.end - arc.start; + const n = Math.max(roundEps(Math.abs(delta) / HALF_PI), 1); + // https://github.com/chromium/chromium/blob/master/third_party/blink/renderer/core/svg/svg_path_parser.cc#L253 + const d = delta / n; + const t = 8 / 6 * Math.tan(0.25 * d); + if (!isFinite(t)) { + return [cubicFromLine(p, q, { ...arc.attribs })]; + } + for (let i = n, theta = arc.start; i > 0; i-- , theta += d) { + const [s1, c1] = sincos(theta); + const [s2, c2] = sincos(theta + d); + const curve = new Cubic( + [ + mapP(c1, s1), + mapP(c1 - s1 * t, s1 + c1 * t), + mapP(c2 + s2 * t, s2 - c2 * t), + mapP(c2, s2), + ], + { ...arc.attribs } + ); + res.push(curve); + } + return res; + }; + +export const cubicFromLine = + (a: Vec, b: Vec, attribs?: Attribs) => + new Cubic([a, mixN2([], a, b, 1 / 3), mixN2([], b, a, 1 / 3), b], attribs); + +export const cubicFromQuadratic = + (a: Vec, b: Vec, c: Vec, attribs?: Attribs) => + new Cubic( + [ + set2([], a), + mixN2([], a, b, 2 / 3), + mixN2([], c, b, 2 / 3), + set2([], c) + ], + attribs + ); diff --git a/packages/geom/src/ctors/ellipse.ts b/packages/geom/src/ctors/ellipse.ts new file mode 100644 index 0000000000..08b1c166f1 --- /dev/null +++ b/packages/geom/src/ctors/ellipse.ts @@ -0,0 +1,10 @@ +import { Vec } from "@thi.ng/vectors"; +import { Attribs, Ellipse } from "../api"; +import { argsVV } from "../internal/args"; + +export function ellipse(pos: Vec, r: number | Vec, attribs?: Attribs): Ellipse; +export function ellipse(r: number | Vec, attribs?: Attribs): Ellipse; +export function ellipse(attribs?: Attribs): Ellipse; +export function ellipse(...args: any[]) { + return new Ellipse(...argsVV(args)); +} diff --git a/packages/geom/src/ctors/group.ts b/packages/geom/src/ctors/group.ts new file mode 100644 index 0000000000..97c9a9eabc --- /dev/null +++ b/packages/geom/src/ctors/group.ts @@ -0,0 +1,5 @@ +import { IHiccupShape, Attribs, Group } from "../api"; + +export const group = + (children: IHiccupShape[], attribs?: Attribs) => + new Group(children, attribs); diff --git a/packages/geom/src/ctors/line.ts b/packages/geom/src/ctors/line.ts new file mode 100644 index 0000000000..69cc98b97a --- /dev/null +++ b/packages/geom/src/ctors/line.ts @@ -0,0 +1,26 @@ +import { Vec } from "@thi.ng/vectors"; +import { + Attribs, + Line, + Rect, + VecPair +} from "../api"; +import { argAttribs } from "../internal/args"; +import { liangBarsky } from "../internal/liang-barsky"; + +export function line(a: Vec, b: Vec, attribs?: Attribs): Line; +export function line(pts: Vec[], attribs?: Attribs): Line; +export function line(...args: any[]) { + const attr = argAttribs(args); + return new Line(args.length === 1 ? args[0] : args, attr); +} + +export const clippedLine = + (l: Line, bounds: VecPair | Rect) => { + const res = bounds instanceof Rect ? + liangBarsky(l.points[0], l.points[1], bounds.pos, bounds.max()) : + liangBarsky(l.points[0], l.points[1], bounds[0], bounds[1]); + if (res) { + return new Line([res[0], res[1]], { ...l.attribs }); + } + }; diff --git a/packages/geom/src/ctors/path.ts b/packages/geom/src/ctors/path.ts new file mode 100644 index 0000000000..1526ec6908 --- /dev/null +++ b/packages/geom/src/ctors/path.ts @@ -0,0 +1,388 @@ +import { isNumber } from "@thi.ng/checks"; +import { eqDelta, rad } from "@thi.ng/math"; +import { map, mapcat, peek } from "@thi.ng/transducers"; +import { + add2, + copy, + maddN2, + mulN2, + set2, + sub2, + Vec, + zeroes +} from "@thi.ng/vectors"; +import { + Attribs, + Cubic, + Line, + Path, + PathSegment, + Quadratic, + SegmentType +} from "../api"; +import { asCubic } from "../ops/as-cubic"; +import { arcFrom2Points } from "./arc"; + +export const path = + (segments: PathSegment[], attribs?: Attribs) => + new Path(segments, attribs); + +export const normalizedPath = + (path: Path) => + new Path( + [...mapcat((s) => + s.geo ? + map( + (c) => ({ type: SegmentType.CUBIC, geo: c }), + asCubic(s.geo) + ) : + [{ ...s }], + path.segments + )], + path.attribs + ); + +export const roundedRect = + (pos: Vec, size: Vec, r: number | Vec) => { + r = isNumber(r) ? [r, r] : r; + const b = new PathBuilder(); + const [w, h] = maddN2([], size, r, -2); + b.moveTo([pos[0] + r[0], pos[1]]); + b.hlineTo(w, true); + b.arcTo(r, r, 0, false, true, true); + b.vlineTo(h, true); + b.arcTo([-r[0], r[1]], r, 0, false, true, true); + b.hlineTo(-w, true); + b.arcTo([-r[0], -r[1]], r, 0, false, true, true); + b.vlineTo(-h, true); + b.arcTo([r[0], -r[1]], r, 0, false, true, true); + return b.curr; + }; + +export class PathBuilder { + + paths: Path[]; + curr: Path; + protected currP: Vec; + protected bezierP: Vec; + protected startP: Vec; + + constructor() { + this.paths = []; + this.newPath(); + } + + *[Symbol.iterator]() { + yield* this.paths; + } + + newPath() { + this.curr = new Path(); + this.paths.push(this.curr); + this.currP = zeroes(2); + this.bezierP = zeroes(2); + this.startP = zeroes(2); + } + + moveTo(p: Vec, relative = false): PathBuilder { + if (this.curr.segments.length > 0) { + this.curr = new Path(); + this.paths.push(this.curr); + } + p = this.updateCurrent(p, relative); + set2(this.startP, p); + set2(this.bezierP, p); + this.curr.add({ + point: p, + type: SegmentType.MOVE, + }); + return this; + } + + lineTo(p: Vec, relative = false): PathBuilder { + this.curr.add({ + geo: new Line([ + copy(this.currP), + this.updateCurrent(p, relative) + ]), + type: SegmentType.LINE, + }); + set2(this.bezierP, this.currP); + return this; + } + + hlineTo(x: number, relative = false): PathBuilder { + const prev = copy(this.currP); + this.currP[0] = relative ? this.currP[0] + x : x; + set2(this.bezierP, this.currP); + this.curr.add({ + geo: new Line([prev, copy(this.currP)]), + type: SegmentType.LINE, + }); + return this; + } + + vlineTo(y: number, relative = false): PathBuilder { + const prev = copy(this.currP); + this.currP[1] = relative ? this.currP[1] + y : y; + set2(this.bezierP, this.currP); + this.curr.add({ + geo: new Line([prev, copy(this.currP)]), + type: SegmentType.LINE, + }); + return this; + } + + // https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/d#Cubic_B%C3%A9zier_Curve + cubicTo(cp1: Vec, cp2: Vec, p: Vec, relative = false) { + const c2 = this.absPoint(cp2, relative); + set2(this.bezierP, c2); + this.curr.add({ + geo: new Cubic([ + copy(this.currP), + this.absPoint(cp1, relative), + c2, + this.updateCurrent(p, relative), + ]), + type: SegmentType.CUBIC, + }); + return this; + } + + // https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/d#Quadratic_B%C3%A9zier_Curve + quadraticTo(cp: Vec, p: Vec, relative = false) { + const c1 = this.absPoint(cp, relative); + set2(this.bezierP, c1); + this.curr.add({ + geo: new Quadratic([ + copy(this.currP), + c1, + this.updateCurrent(p, relative), + ]), + type: SegmentType.QUADRATIC, + }); + return this; + } + + cubicChainTo(cp2: Vec, p: Vec, relative = false) { + const prevMode = peek(this.curr.segments).type; + const c1 = copy(this.currP); + if (prevMode === SegmentType.CUBIC) { + add2(null, sub2([], c1, this.bezierP), c1); + } + const c2 = this.absPoint(cp2, relative); + set2(this.bezierP, c2); + this.curr.add({ + geo: new Cubic([ + copy(this.currP), + c1, + c2, + this.updateCurrent(p, relative), + ]), + type: SegmentType.CUBIC, + }); + return this; + } + + quadraticChainTo(p: Vec, relative = false) { + const prevMode = peek(this.curr.segments).type; + const c1 = copy(this.currP); + if (prevMode === SegmentType.QUADRATIC) { + sub2(null, mulN2(null, c1, 2), this.bezierP); + } + set2(this.bezierP, c1); + this.curr.add({ + geo: new Quadratic([ + copy(this.currP), + c1, + this.updateCurrent(p, relative), + ]), + type: SegmentType.CUBIC, + }); + return this; + } + + arcTo(p: Vec, r: Vec, xaxis: number, xl: boolean, clockwise: boolean, relative = false) { + if (eqDelta(r[0], 0) || eqDelta(r[1], 0)) { + return this.lineTo(p, relative); + } + const prev = copy(this.currP); + this.curr.add({ + geo: arcFrom2Points( + prev, + this.updateCurrent(p, relative), + r, + xaxis, + xl, + clockwise + ), + type: SegmentType.ARC, + }); + set2(this.bezierP, this.currP); + return this; + } + + closePath() { + this.curr.add({ + geo: new Line([copy(this.currP), copy(this.startP)]), + type: SegmentType.LINE, + }); + this.curr.closed = true; + return this; + } + + protected updateCurrent(p: Vec, relative: boolean) { + p = copy(relative ? add2(null, this.currP, p) : set2(this.currP, p)); + return p; + } + + protected absPoint(p: Vec, relative: boolean) { + return relative ? add2(null, p, this.currP) : p; + } +} + +export const pathBuilder = + () => new PathBuilder(); + +const CMD_RE = /[achlmqstvz]/i; + +export const pathFromSvg = (svg: string) => { + const b = new PathBuilder(); + try { + let cmd: string; + for (let n = svg.length, i = 0; i < n;) { + i = skipWS(svg, i); + const c = svg.charAt(i); + if (CMD_RE.test(c)) { + cmd = c; + i++; + } + let p, pa, pb, t1, t2, t3; + switch (cmd.toLowerCase()) { + case "m": + [p, i] = readPoint(svg, i); + b.moveTo(p, cmd === "m"); + break; + case "l": + [p, i] = readPoint(svg, i); + b.lineTo(p, cmd === "l"); + break; + case "h": + [p, i] = readFloat(svg, i); + b.hlineTo(p, cmd === "h"); + break; + case "v": + [p, i] = readFloat(svg, i); + b.vlineTo(p, cmd === "v"); + break; + case "q": + [pa, i] = readPoint(svg, i); + [p, i] = readPoint(svg, i); + // console.log("quadratic", pa.toString(), p.toString()); + b.quadraticTo(pa, p, cmd === "q"); + break; + case "c": + [pa, i] = readPoint(svg, i); + [pb, i] = readPoint(svg, i); + [p, i] = readPoint(svg, i); + // console.log("cubic", pa.toString(), pb.toString(), p.toString()); + b.cubicTo(pa, pb, p, cmd === "c"); + break; + case "s": + [pa, i] = readPoint(svg, i); + [p, i] = readPoint(svg, i); + // console.log("cubicChain", pa.toString(), p.toString()); + b.cubicChainTo(pa, p, cmd === "s"); + break; + case "t": + [p, i] = readPoint(svg, i); + // console.log("quadraticChain", p.toString()); + b.quadraticChainTo(p, cmd === "t"); + break; + case "a": { + [pa, i] = readPoint(svg, i); + [t1, i] = readFloat(svg, i); + [t2, i] = readFloat(svg, i); + [t3, i] = readFloat(svg, i); + [pb, i] = readPoint(svg, i); + // console.log("arc", pa.toString(), rad(t1), t2, t3, pb.toString()); + b.arcTo(pb, pa, rad(t1), !!t2, !!t3, cmd === "a"); + break; + } + case "z": + b.closePath(); + break; + default: + throw new Error(`unsupported segment type: ${c} @ pos ${i}`); + } + } + return b.paths; + } catch (e) { + throw e instanceof Error ? e : new Error(`illegal char '${svg.charAt(e)}' @ ${e}`); + } +}; + +const readPoint = + (src: string, index: number): [Vec, number] => { + let x, y; + [x, index] = readFloat(src, index); + index = skipWS(src, index); + [y, index] = readFloat(src, index); + return [[x, y], index]; + }; + +const isWS = + (c: string) => c === " " || c === "\n" || c === "\r" || c === "\t"; + +const skipWS = + (src: string, i: number) => { + const n = src.length; + while (i < n && isWS(src.charAt(i))) i++; + return i; + }; + +const readFloat = + (src: string, index: number) => { + index = skipWS(src, index); + let signOk = true; + let dotOk = true; + let expOk = false; + let commaOk = false; + let i = index; + for (let n = src.length; i < n; i++) { + const c = src.charAt(i); + // console.log("float", src.substring(index, i + 1)); + if ("0" <= c && c <= "9") { + expOk = true; + commaOk = true; + signOk = false; + continue; + } + if (c === "-" || c === "+") { + if (!signOk) break; + signOk = false; + continue; + } + if (c === ".") { + if (!dotOk) break; + dotOk = false; + continue; + } + if (c === "e") { + if (!expOk) throw i; + expOk = false; + dotOk = false; + signOk = true; + continue; + } + if (c === ",") { + if (!commaOk) throw i; + i++; + } + break; + } + if (i === index) { + throw new Error(`expected coordinate @ pos: ${i}`); + } + return [parseFloat(src.substring(index, i)), i]; + }; diff --git a/packages/geom/src/ctors/points.ts b/packages/geom/src/ctors/points.ts new file mode 100644 index 0000000000..a53c656773 --- /dev/null +++ b/packages/geom/src/ctors/points.ts @@ -0,0 +1,5 @@ +import { Attribs, Points } from "../api"; +import { Vec } from "@thi.ng/vectors"; + +export const points = (pts?: Vec[], attribs?: Attribs) => + new Points(pts, attribs); diff --git a/packages/geom/src/ctors/polygon.ts b/packages/geom/src/ctors/polygon.ts new file mode 100644 index 0000000000..a77f6c987e --- /dev/null +++ b/packages/geom/src/ctors/polygon.ts @@ -0,0 +1,26 @@ +import { TAU } from "@thi.ng/math"; +import { + cycle, + map, + normRange, + push, + transduce, + tuples +} from "@thi.ng/transducers"; +import { cartesian2, Vec } from "@thi.ng/vectors"; +import { Attribs, Polygon } from "../api"; + +export const polygon = + (pts: Vec[], attribs?: Attribs) => + new Polygon(pts, attribs); + +export const star = + (r: number, n: number, profile: number[], attribs?: Attribs) => + new Polygon( + transduce( + map(([i, p]) => cartesian2(null, [r * p, i * TAU])), + push(), + tuples(normRange(n * profile.length, false), cycle(profile)) + ), + attribs + ); diff --git a/packages/geom/src/ctors/polyline.ts b/packages/geom/src/ctors/polyline.ts new file mode 100644 index 0000000000..ec16a1e6da --- /dev/null +++ b/packages/geom/src/ctors/polyline.ts @@ -0,0 +1,6 @@ +import { Vec } from "@thi.ng/vectors"; +import { Attribs, Polyline } from "../api"; + +export const polyline = + (pts: Vec[], attribs?: Attribs) => + new Polyline(pts, attribs); diff --git a/packages/geom/src/ctors/quad.ts b/packages/geom/src/ctors/quad.ts new file mode 100644 index 0000000000..5ead1128c5 --- /dev/null +++ b/packages/geom/src/ctors/quad.ts @@ -0,0 +1,10 @@ +import { Vec } from "@thi.ng/vectors"; +import { Attribs, Quad } from "../api"; +import { argAttribs } from "../internal/args"; + +export function quad(a: Vec, b: Vec, c: Vec, d: Vec, attribs?: Attribs): Quad; +export function quad(pts: Vec[], attribs?: Attribs): Quad; +export function quad(...args: any[]) { + const attr = argAttribs(args); + return new Quad(args.length === 1 ? args[0] : args, attr); +} diff --git a/packages/geom/src/ctors/quadratic.ts b/packages/geom/src/ctors/quadratic.ts new file mode 100644 index 0000000000..dc99330542 --- /dev/null +++ b/packages/geom/src/ctors/quadratic.ts @@ -0,0 +1,14 @@ +import { mixN, Vec } from "@thi.ng/vectors"; +import { Attribs, Quadratic } from "../api"; +import { argAttribs } from "../internal/args"; + +export function quadratic(a: Vec, b: Vec, c: Vec, attribs?: Attribs): Quadratic; +export function quadratic(pts: Vec[], attribs?: Attribs): Quadratic; +export function quadratic(...args: any[]) { + const attr = argAttribs(args); + return new Quadratic(args.length === 1 ? args[0] : args, attr); +} + +export const quadraticFromLine = + (a: Vec, b: Vec, attribs?: Attribs) => + new Quadratic([a, mixN([], a, b, 0.5), b], attribs) diff --git a/packages/geom/src/ctors/ray.ts b/packages/geom/src/ctors/ray.ts new file mode 100644 index 0000000000..a7a2e8ac12 --- /dev/null +++ b/packages/geom/src/ctors/ray.ts @@ -0,0 +1,6 @@ +import { normalize as _norm, Vec } from "@thi.ng/vectors"; +import { Attribs, Ray } from "../api"; + +export const ray = + (pos: Vec, dir: Vec, attribs?: Attribs, normalize = true) => + new Ray(pos, normalize ? _norm(null, dir) : dir, attribs); diff --git a/packages/geom/src/ctors/rect.ts b/packages/geom/src/ctors/rect.ts new file mode 100644 index 0000000000..52db20475e --- /dev/null +++ b/packages/geom/src/ctors/rect.ts @@ -0,0 +1,14 @@ +import { sub2, Vec } from "@thi.ng/vectors"; +import { Attribs, Rect } from "../api"; +import { argsVV } from "../internal/args"; + +export function rect(pos: Vec, size: number | Vec, attribs?: Attribs): Rect; +export function rect(size: number | Vec, attribs?: Attribs): Rect; +export function rect(attribs?: Attribs): Rect; +export function rect(...args: any[]) { + return new Rect(...argsVV(args)); +} + +export const rectFromMinMax = + (min: Vec, max: Vec, attribs?: Attribs) => + new Rect(min, sub2([], max, min), attribs); diff --git a/packages/geom/src/ctors/triangle.ts b/packages/geom/src/ctors/triangle.ts new file mode 100644 index 0000000000..d24312f251 --- /dev/null +++ b/packages/geom/src/ctors/triangle.ts @@ -0,0 +1,25 @@ +import { THIRD_PI } from "@thi.ng/math"; +import { + maddN2, + mag, + normalize, + perpendicularLeft2, + sub2, + Vec +} from "@thi.ng/vectors"; +import { Attribs, Triangle } from "../api"; +import { argAttribs } from "../internal/args"; + +export function triangle(a: Vec, b: Vec, c: Vec, attribs?: Attribs): Triangle; +export function triangle(pts: Vec[], attribs?: Attribs): Triangle; +export function triangle(...args: any[]) { + const attr = argAttribs(args); + 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); + }; diff --git a/packages/geom/src/fit.ts b/packages/geom/src/fit.ts deleted file mode 100644 index 2c7828dcbb..0000000000 --- a/packages/geom/src/fit.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { Mat23 } from "@thi.ng/vectors/mat23"; -import { Vec2 } from "@thi.ng/vectors/vec2"; -import { IBounds, ICentroid, ITransformable } from "./api"; -import { collBounds } from "./internal/bounds"; -import { Rect2 } from "./rect2"; - -const translateScale = (shape: ITransformable, c1: Vec2, c2: Vec2, smat: Mat23) => - shape.transform( - Mat23.concat( - Mat23.translation(c1), - smat, - Mat23.translation(c2) - ) - ); - -export const fitIntoBounds2 = & ITransformable>(shape: T, bounds: Rect2) => { - const obounds = shape.bounds(); - const tscale = bounds.size.copy().divNew(obounds.size); - const scale = Math.min(tscale.x, tscale.y); - return translateScale( - shape, - bounds.centroid(), - obounds.centroid().neg(), - Mat23.scale(scale) - ); -} - -export const fitAllIntoBounds2 = & ICentroid & ITransformable>(shapes: T[], dest: Rect2) => { - const src: Rect2 = collBounds(shapes); - const w = dest.size.x / src.size.x; - const h = dest.size.y / src.size.y; - const s = w > 0 && h > 0 ? Math.min(w, h) : w > 0 ? w : h; - const b = src.copy().scaleN(s).center(dest.centroid()); - const smat = Mat23.scale(s); - for (let i = shapes.length; --i >= 0;) { - const s = shapes[i]; - const c1 = s.centroid(); - const c2 = b.unmapPoint(src.mapPoint(c1)); - translateScale(s, c2, c1.neg(), smat); - } - return shapes; -}; diff --git a/packages/geom/src/index.ts b/packages/geom/src/index.ts index 46762d01db..bd89097857 100644 --- a/packages/geom/src/index.ts +++ b/packages/geom/src/index.ts @@ -1,22 +1,85 @@ export * from "./api"; -export * from "./container2"; -export * from "./container3"; -export * from "./arc2"; -export * from "./bezier2"; -export * from "./circle2"; -export * from "./container2"; -export * from "./container3"; -export * from "./line2"; -export * from "./path2"; -export * from "./polygon2"; -export * from "./polyline2"; -export * from "./quad2"; -export * from "./rect2"; -export * from "./sampler"; -export * from "./triangle2"; +export * from "./ctors/arc"; +export * from "./ctors/circle"; +export * from "./ctors/cubic"; +export * from "./ctors/ellipse"; +export * from "./ctors/group"; +export * from "./ctors/line"; +export * from "./ctors/path"; +export * from "./ctors/points"; +export * from "./ctors/polygon"; +export * from "./ctors/polyline"; +export * from "./ctors/quad"; +export * from "./ctors/quadratic"; +export * from "./ctors/ray"; +export * from "./ctors/rect"; +export * from "./ctors/triangle"; -export * from "./fit"; -export * from "./subdiv-curve"; -export * from "./tessellate"; -export * from "./warp"; +export * from "./ops/arc-length"; +export * from "./ops/area"; +export * from "./ops/as-cubic"; +export * from "./ops/as-polygon"; +export * from "./ops/as-svg"; +export * from "./ops/bounds"; +export * from "./ops/center"; +export * from "./ops/centroid"; +export * from "./ops/classify-point"; +export * from "./ops/clip-convex"; +export * from "./ops/closest-point"; +export * from "./ops/convex-hull"; +export * from "./ops/edges"; +export * from "./ops/fit-into-bounds"; +export * from "./ops/flip"; +export * from "./ops/intersects"; +export * from "./ops/map-point"; +export * from "./ops/point-at"; +export * from "./ops/point-inside"; +export * from "./ops/resample"; +export * from "./ops/scatter"; +export * from "./ops/simplify"; +export * from "./ops/split-at"; +export * from "./ops/split-near"; +export * from "./ops/subdiv-curve"; +export * from "./ops/tangent-at"; +export * from "./ops/tessellate"; +export * from "./ops/transform"; +export * from "./ops/translate"; +export * from "./ops/union"; +export * from "./ops/unmap-point"; +export * from "./ops/vertices"; +export * from "./ops/warp-points"; +export * from "./ops/with-attribs"; + +export * from "./internal/arc-point"; +export * from "./internal/bounds"; +export * from "./internal/centroid"; +export * from "./internal/circumcenter"; +export * from "./internal/clockwise"; +export * from "./internal/closest-point"; +export * from "./internal/copy-points"; +export * from "./internal/corner"; +export * from "./internal/douglas–peucker"; +export * from "./internal/edges"; +export * from "./internal/graham-scan"; +export * from "./internal/liang-barsky"; +export * from "./internal/poly-arc-length"; +export * from "./internal/poly-area"; +export * from "./internal/poly-centroid"; +export * from "./internal/poly-point-inside"; +export * from "./internal/sampler"; +export * from "./internal/split"; +export * from "./internal/subdiv-curve"; +export * from "./internal/sutherland-hodgeman"; +export * from "./internal/tessellate"; +export * from "./internal/transform-points"; +export * from "./internal/triangle-point-inside"; +export * from "./internal/union-bounds"; + +export * from "./isec/circle-circle"; +export * from "./isec/line-line"; +export * from "./isec/ray-circle"; +export * from "./isec/ray-line"; +export * from "./isec/ray-poly"; +export * from "./isec/rect-circle"; +export * from "./isec/rect-rect"; diff --git a/packages/geom/src/internal/arc-length.ts b/packages/geom/src/internal/arc-length.ts deleted file mode 100644 index 31ed1e0fbe..0000000000 --- a/packages/geom/src/internal/arc-length.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { IVector } from "@thi.ng/vectors/api"; - -export const arcLength = >(pts: ReadonlyArray, closed = false) => { - const num = pts.length; - if (num < 2) return 0; - let res = 0; - let p = pts[0]; - let q = pts[1]; - for (let i = 1; i < num; i++ , p = q, q = pts[i]) { - res += p.dist(q); - } - closed && (res += p.dist(pts[0])); - return res; -}; diff --git a/packages/geom/src/internal/arc-point.ts b/packages/geom/src/internal/arc-point.ts new file mode 100644 index 0000000000..0986f8113c --- /dev/null +++ b/packages/geom/src/internal/arc-point.ts @@ -0,0 +1,28 @@ +import { cossin, fit01 } from "@thi.ng/math"; +import { + add2, + mul2, + ReadonlyVec, + rotateZ, + Vec +} from "@thi.ng/vectors"; + +export const arcPointAt = ( + pos: ReadonlyVec, + r: ReadonlyVec, + axis: number, + start: number, + end: number, + t: number, + out: Vec = [] +) => + arcPointAtTheta(pos, r, axis, fit01(t, start, end), out); + +export const arcPointAtTheta = ( + pos: ReadonlyVec, + r: ReadonlyVec, + axis: number, + theta: number, + out: Vec = [] +) => + add2(null, rotateZ(null, mul2(out, cossin(theta), r), axis), pos); diff --git a/packages/geom/src/internal/area.ts b/packages/geom/src/internal/area.ts deleted file mode 100644 index 73b8d795b9..0000000000 --- a/packages/geom/src/internal/area.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Vec2 } from "@thi.ng/vectors/vec2"; - -export const polygonArea = (pts: ReadonlyArray) => { - let res = 0; - for (let n = pts.length - 1, i = n, j = 0; n >= 0; i = j, j++ , n--) { - res += pts[i].cross(pts[j]); - } - return res / 2; -}; diff --git a/packages/geom/src/internal/args.ts b/packages/geom/src/internal/args.ts index 8d430d07b3..7bf1bba99f 100644 --- a/packages/geom/src/internal/args.ts +++ b/packages/geom/src/internal/args.ts @@ -1,76 +1,49 @@ -import { isArrayLike } from "@thi.ng/checks/is-arraylike"; -import { isNumber } from "@thi.ng/checks/is-number"; -import { illegalArgs } from "@thi.ng/errors/illegal-arguments"; -import { ReadonlyVec } from "@thi.ng/vectors/api"; -import { asVec2, Vec2 } from "@thi.ng/vectors/vec2"; +import { isNumber, isPlainObject } from "@thi.ng/checks"; +import { peek } from "@thi.ng/transducers"; -export const args3 = (args: any[]) => { - let points = args[0], attribs; - if (isArrayLike(points[0])) { - points = (points).map(asVec2); - attribs = args[1]; - } else if (args.length >= 3 && - isArrayLike(points) && - isArrayLike(args[1]) && - isArrayLike(args[2])) { - points = [asVec2(points), asVec2(args[1]), asVec2(args[2])]; - attribs = args[3]; - } else if (isNumber(points[0])) { - points = Vec2.mapBuffer( - points, - 3, - args[1] || 0, - args[2] || 1, - args[3] || 2 - ); - attribs = args[4]; - } else { - illegalArgs(); - } - return [points, attribs]; -}; +/** + * Takes an array of arguments, checks if last element is a plain object + * and if so, removes it from array and returns it. Else returns + * `undefined`. + * + * @param args + */ +export const argAttribs = + (args: any[]) => + isPlainObject(peek(args)) ? + args.pop() : + undefined; -export const args4 = (args: any[]) => { - let points = args[0], attribs; - if (isArrayLike(points[0])) { - points = (points).map(asVec2); - attribs = args[1]; - } else if (args.length >= 4 && - isArrayLike(points) && - isArrayLike(args[1]) && - isArrayLike(args[2]) && - isArrayLike(args[3])) { - points = [asVec2(points), asVec2(args[1]), asVec2(args[2]), asVec2(args[3])]; - attribs = args[4]; - } else if (isNumber(points[0])) { - points = Vec2.mapBuffer( - points, - 4, - args[1] || 0, - args[2] || 1, - args[3] || 2 - ); - attribs = args[4]; - } else { - illegalArgs(); - } - return [points, attribs]; -}; +/** + * Args parser for functions expecting up to 2 vector args and optional + * attribs object. Returns 3-tuple of re-structured args. + * + * @param args + */ +export const argsVV = + (args: any[]) => { + const attr = argAttribs(args); + return args.length ? + args.length === 2 ? + [args[0], args[1], attr] : + [undefined, args[0], attr] : + [undefined, undefined, attr]; + }; -export const argsN = (args: any[]) => { - let points = args[0], attribs; - if (isNumber(points[0])) { - points = Vec2.mapBuffer( - points, - args[1] || points.length / 2, - args[2] || 0, - args[3] || 1, - args[4] || 2 - ); - attribs = args[5]; - } else if (isArrayLike(points[0])) { - points = (points).map(asVec2); - attribs = args[1]; - } - return [points, attribs]; -}; +/** + * Args parser for functions expecting a vector, numeric and/or optional + * attribs object. Returns 3-tuple of re-structured args. + * + * @param args + */ +export const argsVN = + (args: any[]) => { + const attr = argAttribs(args); + return args.length ? + args.length === 2 ? + [args[0], args[1], attr] : + isNumber(args[0]) ? + [undefined, args[0], attr] : + [args[0], undefined, attr] : + [undefined, undefined, attr]; + }; diff --git a/packages/geom/src/internal/barycentric.ts b/packages/geom/src/internal/barycentric.ts index 0eb94072f0..0d31c5462a 100644 --- a/packages/geom/src/internal/barycentric.ts +++ b/packages/geom/src/internal/barycentric.ts @@ -1,25 +1,29 @@ -import { IVector } from "@thi.ng/vectors/api"; -import { Vec3 } from "@thi.ng/vectors/vec3"; +import { + addW3, + dot, + magSq, + ReadonlyVec, + setC3, + sub, + Vec +} from "@thi.ng/vectors"; export const toBarycentric = - > - (a: Readonly, b: Readonly, c: Readonly, p: Readonly, out = new Vec3()) => { - - const u = b.subNew(a); - const v = c.subNew(a); - const w = p.subNew(a); - const uu = u.magSq(); - const vv = v.magSq(); - const uv = u.dot(v); - const uw = u.dot(w); - const vw = v.dot(w); + (a: ReadonlyVec, b: ReadonlyVec, c: ReadonlyVec, p: ReadonlyVec, out: Vec = []) => { + const u = sub([], b, a); + const v = sub([], c, a); + const w = sub([], p, a); + const uu = magSq(u); + const vv = magSq(v); + const uv = dot(u, v); + const uw = dot(u, w); + const vw = dot(v, w); const d = 1 / (uv * uv - uu * vv); const s = d * (uv * vw - vv * uw); const t = d * (uv * uw - uu * vw); - return out.setS(1 - (s + t), s, t); + return setC3(out, 1 - (s + t), s, t); }; export const fromBarycentric = - > - (a: Readonly, b: Readonly, c: Readonly, p: Readonly, out?: T) => - a.mulNewN(p.x, out).maddN(b, p.y).maddN(c, p.z); + (a: ReadonlyVec, b: ReadonlyVec, c: ReadonlyVec, p: ReadonlyVec, out?: Vec) => + addW3(out, a, b, c, p[0], p[1], p[2]); diff --git a/packages/geom/src/internal/bounds.ts b/packages/geom/src/internal/bounds.ts index 5d4cb1118d..b4060e4349 100644 --- a/packages/geom/src/internal/bounds.ts +++ b/packages/geom/src/internal/bounds.ts @@ -1,40 +1,139 @@ -import { IVector } from "@thi.ng/vectors/api"; -import { IBounds, IUnion } from "../api"; - -export const axisBounds = - > - (points: ReadonlyArray, axis: number): [number, number] => { - - let min = Infinity; - let max = -Infinity; - for (let i = points.length; --i >= 0;) { - const x = points[i][axis]; - x < min && (min = x); - x > max && (max = x); - } - return [min, max]; - }; +import { Fn } from "@thi.ng/api"; +import { clamp01, mixCubic as _mixCubic } from "@thi.ng/math"; +import { max, min, Vec } from "@thi.ng/vectors"; +import { + max2, + max3, + min2, + min3, + ReadonlyVec +} from "@thi.ng/vectors"; +import { VecPair } from "../api"; +import { AABBLike, IShape } from "../api"; +import { unionBounds } from "./union-bounds"; -export const bounds = - > - (pts: ReadonlyArray, vmin: T, vmax: T): [T, T] => { +/** + * Computes the nD bounds of given vectors. `vmin` should be initialized + * to `+Infinity` and `vmax` to `-Infinity` (e.g. use copies of `MIN*` / + * `MAX*` constants defined in thi.ng/vectors). + * + * Returns 2-tuple of modified `[vmin, vmax]`. + * + * @param pts + * @param vmin + * @param vmax + */ +export const boundsRaw = + (pts: ReadonlyArray, vmin: Vec, vmax: Vec): VecPair => { for (let i = pts.length; --i >= 0;) { const p = pts[i]; - vmin.min(p); - vmax.max(p); + min(null, vmin, p); + max(null, vmax, p); } return [vmin, vmax]; }; +/** + * Computes the total bounds for the given shape collection, which + * should either contain only 2D or 3D types. No mixed dimensions are + * allowed! Currently the `bounds` function must be passed in as arg to + * avoid circular module dependencies. + * + * @param shapes + * @param bounds + */ export const collBounds = - , B extends IBounds & IUnion> - (shapes: T[]) => { - + (shapes: IShape[], bounds: Fn) => { let n = shapes.length - 1; - let res: B = n > 0 ? shapes[n].bounds() : undefined; + if (n < 0) return; + let { pos, size } = bounds(shapes[n]); for (; --n >= 0;) { - res = res.union(shapes[n].bounds()); + const b = bounds(shapes[n]); + [pos, size] = unionBounds(pos, size, b.pos, b.size); + } + return [pos, size]; + }; + +const cubicAxisBounds = + (pa: number, pb: number, pc: number, pd: number) => { + let a = 3 * pd - 9 * pc + 9 * pb - 3 * pa; + let b = 6 * pa - 12 * pb + 6 * pc; + let c = 3 * pb - 3 * pa; + let disc = b * b - 4 * a * c; + let l = pa; + let h = pa; + + const bounds = (t: number) => { + if (t > 0 && t < 1) { + const x = _mixCubic(pa, pb, pc, pd, t); + x < l && (l = x); + x > h && (h = x); + } + }; + + pd < l && (l = pd); + pd > h && (h = pd); + if (disc >= 0) { + disc = Math.sqrt(disc); + a *= 2; + bounds((-b + disc) / a); + bounds((-b - disc) / a); + } + return [l, h]; + }; + +export const cubicBounds2 = + (a: ReadonlyVec, b: ReadonlyVec, c: ReadonlyVec, d: ReadonlyVec): VecPair => { + const x = cubicAxisBounds(a[0], b[0], c[0], d[0]); + const y = cubicAxisBounds(a[1], b[1], c[1], d[1]); + return [[x[0], y[0]], [x[1], y[1]]]; + }; + +export const cubicBounds3 = + (a: ReadonlyVec, b: ReadonlyVec, c: ReadonlyVec, d: ReadonlyVec): VecPair => { + const x = cubicAxisBounds(a[0], b[0], c[0], d[0]); + const y = cubicAxisBounds(a[1], b[1], c[1], d[1]); + const z = cubicAxisBounds(a[2], b[2], c[2], d[2]); + return [[x[0], y[0], z[0]], [x[1], y[1], z[1]]]; + }; + +const solveQuadratic = + (a: number, b: number, c: number) => { + const t = clamp01((a - b) / (a - 2.0 * b + c)); + const s = 1 - t; + return s * s * a + 2.0 * s * t * b + t * t * c; + }; + +export const quadraticBounds2 = + (a: ReadonlyVec, b: ReadonlyVec, c: ReadonlyVec): VecPair => { + const mi = min2([], a, c); + const ma = max2([], a, c); + if (b[0] < mi[0] || b[0] > ma[0] || b[1] < mi[1] || b[1] > ma[1]) { + const q = [ + solveQuadratic(a[0], b[0], c[0]), + solveQuadratic(a[1], b[1], c[1]), + ]; + min2(null, mi, q); + max2(null, ma, q); + } + return [mi, ma]; + }; + +export const quadraticBounds3 = + (a: ReadonlyVec, b: ReadonlyVec, c: ReadonlyVec): VecPair => { + const mi = min3([], a, c); + const ma = max3([], a, c); + if (b[0] < mi[0] || b[0] > ma[0] || + b[1] < mi[1] || b[1] > ma[1] || + b[2] < mi[2] || b[2] > ma[2]) { + const q = [ + solveQuadratic(a[0], b[0], c[0]), + solveQuadratic(a[1], b[1], c[1]), + solveQuadratic(a[2], b[2], c[2]), + ]; + min3(null, mi, q); + max3(null, ma, q); } - return res; + return [mi, ma]; }; diff --git a/packages/geom/src/internal/centroid.ts b/packages/geom/src/internal/centroid.ts index e84643f1ef..bdb15b9a1d 100644 --- a/packages/geom/src/internal/centroid.ts +++ b/packages/geom/src/internal/centroid.ts @@ -1,29 +1,19 @@ -import { illegalArgs } from "@thi.ng/errors/illegal-arguments"; -import { IVector } from "@thi.ng/vectors/api"; -import { Vec2 } from "@thi.ng/vectors/vec2"; +import { illegalArgs } from "@thi.ng/errors"; +import { + add, + divN, + empty, + ReadonlyVec, + Vec +} from "@thi.ng/vectors"; -export const centroid = >(pts: ReadonlyArray, c?: T) => { - const num = pts.length; - !num && illegalArgs("no points available"); - !c && (c = pts[0].empty()); - for (let i = num; --i >= 0;) { - c.add(pts[i]); - } - return c.divN(num); -}; - -export const centerOfWeight = (pts: Vec2[], c?: Vec2) => { - let area = 0; - let x = 0; - let y = 0; - for (let n = pts.length - 1, i = pts[n], j = pts[0], k = 0; k <= n; k++ , i = j, j = pts[k]) { - const z = i.cross(j); - area += z; - x += (i.x + j.x) * z; - y += (i.y + j.y) * z; - } - area = 1 / (area * 3); - x *= area; - y *= area; - return c ? c.setS(x, y) : new Vec2([x, y]); -}; +export const centroidRaw = + (pts: ReadonlyVec[], out?: Vec) => { + const num = pts.length; + !num && illegalArgs("no points available"); + !out && (out = empty(pts[0])); + for (let i = num; --i >= 0;) { + add(out, out, pts[i]); + } + return divN(null, out, num); + }; diff --git a/packages/geom/src/internal/circumcenter.ts b/packages/geom/src/internal/circumcenter.ts index 65517cf648..ddb8986c7c 100644 --- a/packages/geom/src/internal/circumcenter.ts +++ b/packages/geom/src/internal/circumcenter.ts @@ -1,43 +1,43 @@ -import { EPS } from "@thi.ng/math/api"; -import { Vec2 } from "@thi.ng/vectors/vec2"; +import { EPS } from "@thi.ng/math"; +import { ReadonlyVec } from "@thi.ng/vectors"; export const circumCenter = - (a: Readonly, b: Readonly, c: Readonly, eps = EPS) => { + (a: ReadonlyVec, b: ReadonlyVec, c: ReadonlyVec, eps = EPS) => { - const deltaAB = Math.abs(a.y - b.y); - const deltaBC = Math.abs(b.y - c.y); - if (deltaAB < eps && deltaBC < eps) { - return null; - } - const ax = a.x, ay = a.y; - const bx = b.x, by = b.y; - const cx = c.x, cy = c.y; + const deltaAB = Math.abs(a[1] - b[1]); + const deltaBC = Math.abs(b[1] - c[1]); + + if (deltaAB < eps && deltaBC < eps) return; + + const ax = a[0], ay = a[1]; + const bx = b[0], by = b[1]; + const cx = c[0], cy = c[1]; let m1, m2, mx1, mx2, my1, my2, xc, yc; + if (deltaAB < eps) { - m2 = - (cx - bx) / (cy - by); + m2 = -(cx - bx) / (cy - by); mx2 = (bx + cx) / 2; my2 = (by + cy) / 2; xc = (bx + ax) / 2; yc = m2 * (xc - mx2) + my2; } else if (deltaBC < eps) { - m1 = - (bx - ax) / (by - ay); + m1 = -(bx - ax) / (by - ay); mx1 = (ax + bx) / 2; my1 = (ay + by) / 2; xc = (cx + bx) / 2; yc = m1 * (xc - mx1) + my1; } else { - m1 = - (bx - ax) / (by - ay); - m2 = - (cx - bx) / (cy - by); + m1 = -(bx - ax) / (by - ay); + m2 = -(cx - bx) / (cy - by); mx1 = (ax + bx) / 2; my1 = (ay + by) / 2; mx2 = (bx + cx) / 2; my2 = (by + cy) / 2; xc = (m1 * mx1 - m2 * mx2 + my2 - my1) / (m1 - m2); - if (deltaAB > deltaBC) { - yc = m1 * (xc - mx1) + my1; - } else { - yc = m2 * (xc - mx2) + my2; - } + yc = deltaAB > deltaBC ? + m1 * (xc - mx1) + my1 : + m2 * (xc - mx2) + my2; } - return new Vec2(xc, yc); + + return [xc, yc]; }; diff --git a/packages/geom/src/internal/clockwise.ts b/packages/geom/src/internal/clockwise.ts new file mode 100644 index 0000000000..a19299b57f --- /dev/null +++ b/packages/geom/src/internal/clockwise.ts @@ -0,0 +1,5 @@ +import { ReadonlyVec, signedArea2 } from "@thi.ng/vectors"; + +export const clockwise2 = + (a: ReadonlyVec, b: ReadonlyVec, c: ReadonlyVec) => + signedArea2(a, b, c) < 0; diff --git a/packages/geom/src/internal/closest-point.ts b/packages/geom/src/internal/closest-point.ts index ca8db6d33f..dfe42ced2c 100644 --- a/packages/geom/src/internal/closest-point.ts +++ b/packages/geom/src/internal/closest-point.ts @@ -1,12 +1,28 @@ -import { IVector } from "@thi.ng/vectors/api"; +import { Fn } from "@thi.ng/api"; +import { partial } from "@thi.ng/compose"; +import { fit01 } from "@thi.ng/math"; +import { + distSq, + dot, + empty, + magSq, + mixCubic, + mixN, + mixQuadratic, + ReadonlyVec, + set, + sub, + Vec +} from "@thi.ng/vectors"; +import { arcPointAtTheta } from "./arc-point"; -export const closestPoint = - >(p: T, pts: T[]) => { +export const closestPointArray = + (p: ReadonlyVec, pts: Vec[]) => { let minD = Infinity; - let closest: T; + let closest: Vec; for (let i = pts.length; --i >= 0;) { - const d = pts[i].distSq(p); + const d = distSq(pts[i], p); if (d < minD) { minD = d; closest = pts[i]; @@ -16,33 +32,44 @@ export const closestPoint = }; export const closestCoeff = - >(p: T, a: T, b: T) => { + (p: ReadonlyVec, a: ReadonlyVec, b: ReadonlyVec) => { - const d = b.subNew(a); - const l = d.magSq(); - if (l > 1e-6) { - return p.subNew(a).dot(d) / l; - } + const d = sub([], b, a); + const l = magSq(d); + return l > 1e-6 ? + dot(sub([], p, a), d) / l : + undefined; }; +/** + * Returns closest point to `p` on segment `a` -> `b`. By default, if + * the result point lies outside the segment, returns a copy of the + * closest end point. However, if `insideOnly` is true, only returns the + * closest point if it actually is inside the segment (incl. end + * points). + * + * @param p + * @param a + * @param b + * @param out + */ export const closestPointSegment = - >(p: T, a: T, b: T, out: T) => { + (p: ReadonlyVec, a: ReadonlyVec, b: ReadonlyVec, out?: Vec, insideOnly = false) => { const t = closestCoeff(p, a, b); - if (t !== undefined) { - return t <= 0.0 ? - out.set(a) : - t >= 1.0 ? - out.set(b) : - a.mixNewN(b, t, out); + if (t !== undefined && (!insideOnly || t >= 0 && t <= 1)) { + out = out || empty(p); + return t <= 0 ? + set(out, a) : + t >= 1 ? + set(out, b) : + mixN(out, a, b, t); } }; export const closestPointPolyline = - >(p: Readonly, pts: ReadonlyArray, closed = false) => { - - const closest = pts[0].empty(); - const tmp = closest.empty(); + (p: ReadonlyVec, pts: ReadonlyArray, closed = false, out: Vec = []) => { + const tmp = []; const n = pts.length - 1; let minD = Infinity, i, j; if (closed) { @@ -54,21 +81,21 @@ export const closestPointPolyline = } for (; j <= n; i = j, j++) { if (closestPointSegment(p, pts[i], pts[j], tmp)) { - const d = p.distSq(tmp); + const d = distSq(p, tmp); if (d < minD) { minD = d; - closest.set(tmp); + set(out, tmp); } } } - return closest; + return out; }; /** * Returns the index of the start point containing the segment in the * polyline array `points` farthest away from `p` with regards to the * line segment `a` to `b`. `points` is only checked between indices - * `from` and `to`. + * `from` and `to` (not including the latter). * * @param a * @param b @@ -77,19 +104,13 @@ export const closestPointPolyline = * @param to */ export const farthestPointSegment = - >( - a: T, - b: T, - points: T[], - from = 0, - to = points.length) => { - + (a: ReadonlyVec, b: ReadonlyVec, points: ReadonlyVec[], from = 0, to = points.length) => { let maxD = -1; let maxIdx; - const tmp = a.empty(); + const tmp = empty(a); for (let i = from; i < to; i++) { const p = points[i]; - const d = p.distSq(closestPointSegment(p, a, b, tmp) || a); + const d = distSq(p, closestPointSegment(p, a, b, tmp) || a); if (d > maxD) { maxD = d; maxIdx = i; @@ -97,3 +118,111 @@ export const farthestPointSegment = } return [maxIdx, Math.sqrt(maxD)]; }; + +export const closestPointArc = ( + p: ReadonlyVec, + o: ReadonlyVec, + r: ReadonlyVec, + axis: number, + start: number, + end: number, + out: Vec = [], + res?: number, + iter?: number +) => { + const fn = (t: number) => arcPointAtTheta(o, r, axis, fit01(t, start, end), out); + return fn(findClosestT(fn, p, res, iter)); +}; + +/** + * Performs recursive search for closest point to `p` on cubic curve + * defined by control points `a`,`b`,`c`,`d`. The `res` and `recur` + * params are used to control the recursion behavior. See `closestT`. + * + * @param p + * @param a + * @param b + * @param c + * @param d + * @param res + * @param iter + */ +export const closestPointCubic = ( + p: ReadonlyVec, + a: ReadonlyVec, + b: ReadonlyVec, + c: ReadonlyVec, + d: ReadonlyVec, + out: Vec = [], + res?: number, + iter?: number +) => { + const fn = partial(mixCubic, out, a, b, c, d); + return fn(findClosestT(fn, p, res, iter)); +}; + +/** + * Performs recursive search for closest point to `p` on quadratic curve + * defined by control points `a`,`b`,`c`. The `res` and `recur` params + * are used to control the recursion behavior. See `closestT`. + * + * @param p + * @param a + * @param b + * @param c + * @param res + * @param iter + */ +export const closestPointQuadratic = ( + p: ReadonlyVec, + a: ReadonlyVec, + b: ReadonlyVec, + c: ReadonlyVec, + out: Vec = [], + res?: number, + iter?: number +) => { + const fn = partial(mixQuadratic, out, a, b, c); + return fn(findClosestT(fn, p, res, iter)); +}; + +/** + * Recursively evaluates function `fn` for `res` uniformly spaced values + * `t` in the closed interval `[start,end]` to compute points and + * returns the `t` of the point producing the minimum distance to query + * point `p`. At each level of recursion the search interval is + * increasingly narrowed / centered around the currently best `t`. + * + * @param fn + * @param p + * @param res + * @param iter + * @param start + * @param end + */ +export const findClosestT = ( + fn: Fn, + p: ReadonlyVec, + res = 8, + iter = 4, + start = 0, + end = 1 +) => { + if (iter <= 0) return (start + end) / 2; + const delta = (end - start) / res; + let minT = start; + let minD = Infinity; + for (let i = 0; i <= res; i++) { + const t = start + i * delta; + const d = distSq(p, fn(t)); + if (d < minD) { + minD = d; + minT = t; + } + } + return findClosestT( + fn, p, res, iter - 1, + Math.max(minT - delta, 0), + Math.min(minT + delta, 1) + ); +}; diff --git a/packages/geom/src/internal/collate.ts b/packages/geom/src/internal/collate.ts index c29f1e1a28..4de74bc651 100644 --- a/packages/geom/src/internal/collate.ts +++ b/packages/geom/src/internal/collate.ts @@ -1,22 +1,34 @@ -import { Vec, IVec } from "@thi.ng/vectors/api"; -import { CollateOpts } from "../api"; +import { Vec, StridedVec } from "@thi.ng/vectors"; -export const remap = (buf: Vec, pts: IVec[], start: number, cstride: number, estride: number) => { +export interface CollateOpts { + buf: Vec; + start: number; + cstride: number; + estride: number; +} + +export const remap = ( + buf: Vec, + pts: StridedVec[], + start: number, + cstride: number, + estride: number +) => { for (let i = pts.length; --i >= 0;) { const p = pts[i]; p.buf = buf; - p.i = start + i * estride; - p.s = cstride; + p.offset = start + i * estride; + p.stride = cstride; } return buf; }; -export const collateWith = ( - fn: (buf: Vec, src: Iterable>, start, cstride, estride) => Vec, - pts: T[], +export const collateWith = ( + fn: (buf: Vec, src: Iterable>, start, cstride, estride) => Vec, + pts: StridedVec[], opts: Partial, - stride: number) => { - + stride: number +) => { opts = { start: 0, cstride: 1, diff --git a/packages/geom/src/internal/copy-points.ts b/packages/geom/src/internal/copy-points.ts new file mode 100644 index 0000000000..619e082842 --- /dev/null +++ b/packages/geom/src/internal/copy-points.ts @@ -0,0 +1,4 @@ +import { ReadonlyVec, set } from "@thi.ng/vectors"; + +export const copyPoints = + (pts: ReadonlyVec[]) => pts.map((p) => set([], p)); diff --git a/packages/geom/src/internal/corner.ts b/packages/geom/src/internal/corner.ts index 8bf3274009..5bee360c37 100644 --- a/packages/geom/src/internal/corner.ts +++ b/packages/geom/src/internal/corner.ts @@ -1,38 +1,14 @@ -import { sign } from "@thi.ng/math/abs"; -import { EPS } from "@thi.ng/math/api"; -import { Vec2 } from "@thi.ng/vectors/vec2"; - +import { EPS, sign } from "@thi.ng/math"; +import { ReadonlyVec, signedArea2 } from "@thi.ng/vectors"; + +/** + * Syntax sugar for `sign(signedArea2(a,b,c))`. + * + * @param a + * @param b + * @param c + * @param eps + */ export const corner = - (a: Readonly, b: Readonly, c: Readonly) => { - const ax = a.x; - const ay = a.y; - return (b.x - ax) * (c.y - ay) - (c.x - ax) * (b.y - ay); - }; - -export const classify = - (a: Readonly, b: Readonly, c: Readonly, eps = EPS) => - sign(corner(a, b, c), eps); - -export const clockwise2 = - (a: Readonly, b: Readonly, c: Readonly) => - corner(a, b, c) < 0; - -export const classifyPointInTriangle2 = - (p: Readonly, a: Readonly, b: Readonly, c: Readonly) => { - const s = clockwise2(a, b, c) ? 1 : -1; - return sign( - Math.min( - s * corner(a, c, p), - s * corner(b, a, p), - s * corner(c, b, p) - ) - ); - }; - -export const pointInTriangle2 = - (p: Readonly, a: Readonly, b: Readonly, c: Readonly) => { - const s = clockwise2(a, b, c) ? 1 : -1; - return s * corner(a, c, p) >= 0 && - s * corner(b, a, p) >= 0 && - s * corner(c, b, p) >= 0; - }; + (a: ReadonlyVec, b: ReadonlyVec, c: ReadonlyVec, eps = EPS) => + sign(signedArea2(a, b, c), eps); diff --git a/packages/geom/src/internal/direction.ts b/packages/geom/src/internal/direction.ts new file mode 100644 index 0000000000..50c1ed205e --- /dev/null +++ b/packages/geom/src/internal/direction.ts @@ -0,0 +1,19 @@ +import { + normalize, + perpendicularLeft2, + perpendicularRight2, + ReadonlyVec, + sub +} from "@thi.ng/vectors"; + +export const direction = + (a: ReadonlyVec, b: ReadonlyVec, n = 1) => + normalize(null, sub([], b, a), n); + +export const normalL2 = + (a: ReadonlyVec, b: ReadonlyVec, n = 1) => + perpendicularLeft2(null, direction(a, b, n)); + +export const normalR2 = + (a: ReadonlyVec, b: ReadonlyVec, n = 1) => + perpendicularRight2(null, direction(a, b, n)); diff --git a/packages/geom/src/internal/dispatch.ts b/packages/geom/src/internal/dispatch.ts new file mode 100644 index 0000000000..09f4da1a3d --- /dev/null +++ b/packages/geom/src/internal/dispatch.ts @@ -0,0 +1,5 @@ +import { IShape } from "../api"; + +export const dispatch = (x: IShape) => x.type; + +export const dispatch2 = (a: IShape, b: IShape) => a.type + "-" + b.type; diff --git "a/packages/geom/src/internal/douglas\342\200\223peucker.ts" "b/packages/geom/src/internal/douglas\342\200\223peucker.ts" index b2a7061dc1..fe57791efb 100644 --- "a/packages/geom/src/internal/douglas\342\200\223peucker.ts" +++ "b/packages/geom/src/internal/douglas\342\200\223peucker.ts" @@ -1,18 +1,17 @@ -import { peek } from "@thi.ng/transducers/func/peek"; -import { IVector } from "@thi.ng/vectors/api"; +import { EPS } from "@thi.ng/math"; +import { peek } from "@thi.ng/transducers"; +import { eqDelta, Vec } from "@thi.ng/vectors"; import { farthestPointSegment } from "./closest-point"; // https://en.wikipedia.org/wiki/Ramer%E2%80%93Douglas%E2%80%93Peucker_algorithm -export const simplifyPolyline = - >(pts: T[], eps = 0, closed = false) => { +export const douglasPeucker = + (pts: Vec[], eps = 0, closed = false) => { let num = pts.length; const visited: boolean[] = []; - if (num <= 2) { - return pts.slice(); - } - if (closed && !pts[0].eqDelta(peek(pts))) { + if (num <= 2) return pts.slice(); + if (closed && !eqDelta(pts[0], peek(pts), EPS)) { pts = pts.slice(); pts.push(pts[0]); num++; @@ -33,7 +32,7 @@ export const simplifyPolyline = $(0, num - 1); - const res: T[] = []; + const res: Vec[] = []; for (let i = 0, n = closed ? num - 1 : num; i < n; i++) { if (visited[i]) { res.push(pts[i]); diff --git a/packages/geom/src/internal/edges.ts b/packages/geom/src/internal/edges.ts index fe9bed6d49..7885d613ec 100644 --- a/packages/geom/src/internal/edges.ts +++ b/packages/geom/src/internal/edges.ts @@ -1,6 +1,12 @@ -import { wrap } from "@thi.ng/transducers/iter/wrap"; -import { partition } from "@thi.ng/transducers/xform/partition"; +import { partition, wrap } from "@thi.ng/transducers"; +import { ReadonlyVec } from "@thi.ng/vectors"; +import { VecPair } from "../api"; -export const edges = (vertices: Iterable, closed = false) => { - return partition(2, 1, closed ? wrap(vertices, 1, false, true) : vertices); -}; +export const edgeIterator = + (vertices: Iterable, closed = false) => + >partition( + 2, 1, + closed ? + wrap(vertices, 1, false, true) : + vertices + ); diff --git a/packages/geom/src/internal/eq-delta.ts b/packages/geom/src/internal/eq-delta.ts deleted file mode 100644 index 657aea90b1..0000000000 --- a/packages/geom/src/internal/eq-delta.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { EPS } from "@thi.ng/math/api"; -import { IVector } from "@thi.ng/vectors/api"; - -export const containsDelta = >(pts: Iterable, q: Readonly, eps = EPS) => { - for (let p of pts) { - if (p.eqDelta(q, eps)) { - return true; - } - } - return false; -}; diff --git a/packages/geom/src/internal/graham-scan.ts b/packages/geom/src/internal/graham-scan.ts index eb446aa0b4..dabb288107 100644 --- a/packages/geom/src/internal/graham-scan.ts +++ b/packages/geom/src/internal/graham-scan.ts @@ -1,5 +1,5 @@ -import { Vec2 } from "@thi.ng/vectors/vec2"; -import { corner } from "./corner"; +import { EPS } from "@thi.ng/math"; +import { ReadonlyVec, Vec } from "@thi.ng/vectors"; /** * Returns array of points defining the 2D Convex Hull of `pts` using @@ -9,29 +9,79 @@ import { corner } from "./corner"; * * @param pts */ -export const convexHull = (pts: ReadonlyArray) => { - const num = pts.length; - const res: Vec2[] = []; - let h = 0, i; - pts = pts.slice().sort(Vec2.comparator(0, 1)); - - const scan = (p: Vec2, thresh: number) => { - while (h >= thresh && corner(res[h - 2], res[h - 1], p) >= 0) { - res.pop(); - h--; +export const grahamScan2 = + (pts: ReadonlyVec[], eps = EPS) => { + const num = pts.length; + if (num <= 3) return pts.slice(); + let h = 1, i, p, q, r, rx, ry; + // find min YX index + const min = findMin(pts); + [rx, ry] = pts[min]; + const sorted = []; + // compute & sort by polar ordering relative to min + for (i = 0; i < num; i++) { + p = pts[i]; + sorted[i] = { p, t: Math.atan2(p[1] - ry, p[0] - rx) }; + } + sorted.sort( + (a, b) => + a.t !== b.t ? + a.t - b.t : + a.p[0] - b.p[0] + ); + const hull: Vec[] = [sorted[0].p]; + for (i = 1; i < num; i++) { + p = hull[h - 2]; + q = hull[h - 1]; + r = sorted[i].p; + rx = r[0]; + ry = r[1]; + while ((h > 1 && notCCW(p[0], p[1], q[0], q[1], rx, ry, eps)) || + (h === 1 && q[0] === rx && q[1] === ry)) { + h--; + q = p; + p = hull[h - 2]; + } + hull[h++] = r; } - res[h++] = p; + hull.length = h; + return hull; }; - for (i = 0; i < num; i++) { - scan(pts[i], 2); - } - res.pop(); - h--; - const h2 = h + 2; - for (i = num - 1; i >= 0; i--) { - scan(pts[i], h2); - } - res.pop(); - return res; -}; +/** + * Returns true, if triangle defined by ABC is NOT counter clockwise, + * i.e. clockwise or colinear. + * + * @see thi.ng/vectors/signedArea2 + * + * @param ax + * @param ay + * @param bx + * @param by + * @param cx + * @param cy + */ +const notCCW = (ax: number, ay: number, bx: number, by: number, cx: number, cy: number, eps: number) => + (by - ay) * (cx - ax) >= (bx - ax) * (cy - ay) - eps; + +/** + * Returns index of point with lowest YX coords. + * + * @param pts + */ +const findMin = + (pts: ReadonlyVec[]) => { + let n = pts.length - 1; + let minID = n; + let min = pts[n][1]; + let p, y; + for (; --n >= 0;) { + p = pts[n]; + y = p[1]; + if (y < min || (y === min && p[0] < pts[minID][0])) { + min = y; + minID = n; + } + } + return minID; + }; diff --git a/packages/geom/src/internal/liang-barsky.ts b/packages/geom/src/internal/liang-barsky.ts index 9106f6faf3..8caa3e02c0 100644 --- a/packages/geom/src/internal/liang-barsky.ts +++ b/packages/geom/src/internal/liang-barsky.ts @@ -1,50 +1,75 @@ -import { EPS } from "@thi.ng/math/api"; -import { Vec2 } from "@thi.ng/vectors/vec2"; +import { EPS } from "@thi.ng/math"; +import { Vec } from "@thi.ng/vectors"; -// https://en.wikipedia.org/wiki/Liang%E2%80%93Barsky_algorithm -// https://github.com/thi-ng/c-thing/blob/master/src/geom/clip/liangbarsky.c +/** + * Performs Liang-Barsky clipping with given line endpoints `la`, `lb` + * and clipping rect defined by top-left `tr` and bottom-right `br` + * points. The optional `ca` and `cb` vectors can be given to store the + * result (clipped points). If omitted creates new vectors. Returns a + * tuple of `[ca, cb, a, b]`, where the latter two values represent the + * normalized distances of the clipped points relative to original given + * line segment. Returns `undefined` iff the line lies completely + * outside the rect. + * + * https://en.wikipedia.org/wiki/Liang%E2%80%93Barsky_algorithm + * https://github.com/thi-ng/c-thing/blob/master/src/geom/clip/liangbarsky.c + * + * @param la + * @param lb + * @param tl + * @param br + * @param ca + * @param cb + */ +export const liangBarsky = ( + la: Vec, + lb: Vec, + tl: Vec, + br: Vec, + ca: Vec = [], + cb: Vec = [] +): [Vec, Vec, number, number] => { + const lax = la[0]; + const lay = la[1]; + const dx = lb[0] - lax; + const dy = lb[1] - lay; + let a = 0; + let b = 1; -export const liangBarsky2 = - (la: Vec2, lb: Vec2, tl: Vec2, br: Vec2, ca?: Vec2, cb?: Vec2): [Vec2, Vec2, number, number] => { - const [lax, lay] = la; - const dx = lb.x - lax; - const dy = lb.y - lay; - let a = 0; - let b = 1; - - const clip = (p: number, q: number) => { - if (q < 0 && Math.abs(p) < EPS) { - return 0; + const clip = (p: number, q: number) => { + if (q < 0 && Math.abs(p) < EPS) { + return 0; + } + const r = q / p; + if (p < 0) { + if (r > b) { + return false; + } else if (r > a) { + a = r; } - const r = q / p; - if (p < 0) { - if (r > b) { - return false; - } else if (r > a) { - a = r; - } - } else if (p > 0) { - if (r < a) { - return false; - } else if (r < b) { - b = r; - } + } else { + if (r < a) { + return false; + } else if (r < b) { + b = r; } - return true; - }; - - if (!(clip(-dx, -(tl.x - lax)) && - clip(dx, br.x - lax) && - clip(-dy, -(tl.y - lay)) && - clip(dy, br.y - lay))) { - return; } + return true; + }; - !ca && (ca = new Vec2()); - !cb && (cb = new Vec2()); + if (!( + clip(-dx, -(tl[0] - lax)) && + clip(dx, br[0] - lax) && + clip(-dy, -(tl[1] - lay)) && + clip(dy, br[1] - lay) + )) { + return; + } - ca.setS(a * dx + lax, a * dy + lay); - cb.setS(b * dx + lax, b * dy + lay); + ca[0] = a * dx + lax; + ca[1] = a * dy + lay; + cb[0] = b * dx + lax; + cb[1] = b * dy + lay; - return [ca, cb, a, b]; - }; + return [ca, cb, a, b]; +}; diff --git a/packages/geom/src/internal/line-intersection.ts b/packages/geom/src/internal/line-intersection.ts deleted file mode 100644 index 583a098dd4..0000000000 --- a/packages/geom/src/internal/line-intersection.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { Vec2 } from "@thi.ng/vectors/vec2"; -import { LineIntersection, LineIntersectionType } from "../api"; - -export const intersectLines2 = (a: Vec2, b: Vec2, c: Vec2, d: Vec2) => { - const bax = b.x - a.x; - const bay = b.y - a.y; - const dcx = d.x - c.x; - const dcy = d.y - c.y; - const acx = a.x - c.x; - const acy = a.y - c.y; - const det = dcy * bax - dcx * bay; - let alpha = dcx * acy - dcy * acx; - let beta = bax * acy - bay * acx; - if (det === 0) { - if (alpha === 0 && beta === 0) { - return { type: LineIntersectionType.COINCIDENT }; - } - return { type: LineIntersectionType.PARALLEL }; - } - alpha /= det; - beta /= det; - return >{ - type: (0 <= alpha && alpha <= 1) && (0 <= beta && beta <= 1) ? - LineIntersectionType.INTERSECT : - LineIntersectionType.INTERSECT_OUTSIDE, - isec: a.mixNewN(b, alpha), - alpha, - beta, - det, - }; -}; diff --git a/packages/geom/src/internal/point-in-array.ts b/packages/geom/src/internal/point-in-array.ts new file mode 100644 index 0000000000..28f6683105 --- /dev/null +++ b/packages/geom/src/internal/point-in-array.ts @@ -0,0 +1,12 @@ +import { EPS } from "@thi.ng/math"; +import { eqDelta, ReadonlyVec } from "@thi.ng/vectors"; + +export const pointInArray = + (points: ReadonlyVec[], p: ReadonlyVec, eps = EPS) => { + for (let i = points.length; --i >= 0;) { + if (eqDelta(p, points[i], eps)) { + return true; + } + } + return false; + }; diff --git a/packages/geom/src/internal/poly-arc-length.ts b/packages/geom/src/internal/poly-arc-length.ts new file mode 100644 index 0000000000..83405f5f09 --- /dev/null +++ b/packages/geom/src/internal/poly-arc-length.ts @@ -0,0 +1,15 @@ +import { ReadonlyVec, dist } from "@thi.ng/vectors"; + +export const polyArcLength = + (pts: ReadonlyVec[], num = pts.length, closed = false) => { + if (num < 2) return 0; + let res = 0; + let p = pts[0]; + let q = pts[1]; + for (let i = 1; i < num; p = q, q = pts[++i]) { + res += dist(p, q); + } + return closed ? + res + dist(p, pts[0]) : + res; + }; diff --git a/packages/geom/src/internal/poly-area.ts b/packages/geom/src/internal/poly-area.ts new file mode 100644 index 0000000000..197f9c19fa --- /dev/null +++ b/packages/geom/src/internal/poly-area.ts @@ -0,0 +1,16 @@ +import { cross2, ReadonlyVec } from "@thi.ng/vectors"; + +/** + * Interprets given points as closed 2D polygon and computes signed + * area. + * + * @param pts + */ +export const polyArea = + (pts: ReadonlyVec[]) => { + let res = 0; + for (let n = pts.length - 1, i = n, j = 0; n >= 0; i = j, j++ , n--) { + res += cross2(pts[i], pts[j]); + } + return res / 2; + }; diff --git a/packages/geom/src/internal/poly-centroid.ts b/packages/geom/src/internal/poly-centroid.ts new file mode 100644 index 0000000000..7479b496ac --- /dev/null +++ b/packages/geom/src/internal/poly-centroid.ts @@ -0,0 +1,18 @@ +import { cross2, ReadonlyVec, Vec } from "@thi.ng/vectors"; + +export const polyCentroid = + (pts: ReadonlyVec[], c: Vec = []) => { + let area = 0; + let x = 0; + let y = 0; + for (let n = pts.length - 1, i = pts[n], j = pts[0], k = 0; k <= n; i = j, j = pts[++k]) { + const z = cross2(i, j); + area += z; + x += (i[0] + j[0]) * z; + y += (i[1] + j[1]) * z; + } + area = 1 / (area * 3); + c[0] = x * area; + c[1] = y * area; + return c; + }; diff --git a/packages/geom/src/internal/poly-point-inside.ts b/packages/geom/src/internal/poly-point-inside.ts new file mode 100644 index 0000000000..d90a2af5a4 --- /dev/null +++ b/packages/geom/src/internal/poly-point-inside.ts @@ -0,0 +1,20 @@ +import { ReadonlyVec } from "@thi.ng/vectors"; + +export const polyPointInside = + (pts: ReadonlyVec[], { 0: px, 1: py }: ReadonlyVec) => { + let inside = 0; + for (let n = pts.length - 1, i = n, j = 0; j <= n; i = j, j++) { + inside = polyPointInsidePair(pts[i], pts[j], px, py, inside); + } + return inside; + }; + +const polyPointInsidePair = + (a: ReadonlyVec, b: ReadonlyVec, px: number, py: number, inside: number) => { + if (((a[1] < py && b[1] >= py) || + (b[1] < py && a[1] >= py)) && + (a[0] <= px || b[0] <= px)) { + inside ^= (((a[0] + (py - a[1]) / (b[1] - a[1]) * (b[0] - a[0])) < px) ? 1 : 0); + } + return inside; + }; diff --git a/packages/geom/src/internal/sampler.ts b/packages/geom/src/internal/sampler.ts new file mode 100644 index 0000000000..88e8fc69af --- /dev/null +++ b/packages/geom/src/internal/sampler.ts @@ -0,0 +1,188 @@ +import { isPlainObject } from "@thi.ng/checks"; +import { peek } from "@thi.ng/transducers"; +import { + dist, + mixN, + normalize, + ReadonlyVec, + sub, + Vec, + eqDelta, + set, + distSq +} from "@thi.ng/vectors"; +import { DEFAULT_SAMPLES, SamplingOpts, VecPair } from "../api"; +import { copyPoints } from "./copy-points"; +import { closestPointSegment, closestCoeff } from "./closest-point"; +import { fit01 } from "@thi.ng/math"; + +export const resamplePoints = + (pts: ReadonlyVec[], opts: number | Partial, closed = false, copy = false) => { + if (opts !== undefined) { + const sampler = new Sampler(pts, false); + return isPlainObject(opts) ? + closed ? + opts.dist ? + sampler.sampleUniform(opts.dist, opts.last) : + sampler.sampleFixedNum(opts.num, opts.last) : + opts.dist ? + sampler.sampleUniform(opts.dist, opts.last !== false) : + sampler.sampleFixedNum(opts.num, opts.last !== false) : + sampler.sampleFixedNum(opts || DEFAULT_SAMPLES, !closed); + } + return copy ? + copyPoints(pts) : + pts; + }; + +export class Sampler { + + points: ReadonlyVec[]; + index: number[]; + + constructor(points: ReadonlyVec[], closed = false) { + if (closed) { + this.points = points.slice(); + this.points.push(points[0]); + } else { + this.points = points; + } + this.buildIndex(); + } + + pointAt(t: number) { + const pts = this.points; + const n = pts.length - 1; + if (n < 0) { + return; + } + if (n === 0 || t <= 0) { + return pts[0]; + } + if (t >= 1) { + return pts[n]; + } + const idx = this.index; + const t0 = t * idx[n]; + for (let i = 1; i <= n; i++) { + if (idx[i] >= t0) { + return mixN([], pts[i - 1], pts[i], (t0 - idx[i - 1]) / (idx[i] - idx[i - 1])); + } + } + } + + closestT(p: ReadonlyVec) { + const pts = this.points; + const idx = this.index; + const tmp = []; + const closest = []; + let minD = Infinity; + let minI; + for (let i = 0; i < this.index.length - 1; i++) { + if (closestPointSegment(p, pts[i], pts[i + 1], tmp)) { + const d = distSq(p, tmp); + if (d < minD) { + minD = d; + minI = i; + set(closest, tmp); + } + } + } + return fit01( + closestCoeff(p, pts[minI], pts[minI + 1]), + idx[minI], + idx[minI + 1] + ) / peek(idx); + } + + segmentAt(t: number): VecPair { + let i = this.indexAt(t); + if (i === undefined) { + return; + } + i = Math.max(1, i); + return [this.points[i - 1], this.points[i]]; + } + + tangentAt(t: number, n = 1) { + const seg = this.segmentAt(t); + return seg ? + normalize(null, sub([], seg[1], seg[0]), n) : + undefined; + } + + splitAt(t: number) { + if (t <= 0 || t >= 1) { + return [this.points]; + } + const p = this.pointAt(t); + 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)) { + head.push(p); + } + if (!eqDelta(tail[0], p)) { + tail.unshift(p); + } + return [head, tail]; + } + + splitNear(p: ReadonlyVec) { + return this.splitAt(this.closestT(p)); + } + + indexAt(t: number) { + const pts = this.points; + const n = pts.length - 1; + if (n < 0) { + return; + } + if (n === 0 || t <= 0) { + return 0; + } + if (t >= 1) { + return n; + } + const idx = this.index; + const t0 = t * idx[n]; + for (let i = 1; i <= n; i++) { + if (idx[i] >= t0) { + return i; + } + } + } + + sampleUniform(dist: number, includeLast = false, result: Vec[] = []) { + const index = this.index; + const pts = this.points; + const total = peek(index); + const delta = dist / total; + const n = index.length; + for (let t = 0, i = 1; t < 1; t += delta) { + const ct = t * total; + while (ct >= index[i] && i < n) { i++; } + if (i >= n) break; + const p = index[i - 1]; + result.push(mixN([], pts[i - 1], pts[i], (ct - p) / (index[i] - p))); + } + if (includeLast) { + result.push(set([], peek(pts))); + } + return result; + } + + sampleFixedNum(num: number, includeLast = false, result?: Vec[]) { + return this.sampleUniform(peek(this.index) / num, includeLast, result); + } + + protected buildIndex() { + const idx: number[] = [0]; + const pts = this.points; + const n = pts.length; + for (let i = 0, j = 1; j < n; i = j, j++) { + idx[j] = idx[i] + dist(pts[i], pts[j]); + } + this.index = idx; + } +} diff --git a/packages/geom/src/internal/split.ts b/packages/geom/src/internal/split.ts new file mode 100644 index 0000000000..a8400c0b1e --- /dev/null +++ b/packages/geom/src/internal/split.ts @@ -0,0 +1,81 @@ +import { mixN, set, Vec, ReadonlyVec, mixCubic, mixQuadratic } from "@thi.ng/vectors"; +import { VecPair } from "../api"; +import { partial } from "@thi.ng/compose"; +import { findClosestT } from "./closest-point"; + +export const splitLine = + (a: Vec, b: Vec, t: number): [VecPair, VecPair] => { + const p = mixN([], a, b, t); + return [[a, p], [set([], p), b]]; + }; + +export const splitCubic = + (a: ReadonlyVec, b: ReadonlyVec, c: ReadonlyVec, d: ReadonlyVec, t: number) => { + if (t <= 0 || t >= 1) { + const p = t <= 0 ? a : d; + const c1 = [set([], p), set([], p), set([], p), set([], p)]; + const c2 = [set([], a), set([], b), set([], c), set([], d)]; + return t <= 0 ? [c1, c2] : [c2, c1]; + } + const ab = mixN([], a, b, t); + const bc = mixN([], b, c, t); + const cd = mixN([], c, d, t); + const abc = mixN([], ab, bc, t); + const bcd = mixN([], bc, cd, t); + const p = mixN([], abc, bcd, t); + return [ + [set([], a), ab, abc, set([], p)], + [p, bcd, cd, set([], d)] + ]; + }; + +export const splitQuadratic = + (a: ReadonlyVec, b: ReadonlyVec, c: ReadonlyVec, t: number) => { + if (t <= 0 || t >= 1) { + const p = t <= 0 ? a : c; + const c1 = [set([], p), set([], p), set([], p)]; + const c2 = [set([], a), set([], b), set([], c)]; + return t <= 0 ? [c1, c2] : [c2, c1]; + } + const ab = mixN([], a, b, t); + const bc = mixN([], b, c, t); + const p = mixN([], ab, bc, t); + return [[set([], a), ab, p], [p, bc, set([], c)]]; + }; + +export const splitCubicNear = ( + p: ReadonlyVec, + a: ReadonlyVec, + b: ReadonlyVec, + c: ReadonlyVec, + d: ReadonlyVec, + res?: number, + iter?: number +) => + splitCubic( + a, b, c, d, + findClosestT( + partial(mixCubic, [], a, b, c, d), + p, + res, + iter + ) + ); + +export const splitQuadraticNear = ( + p: ReadonlyVec, + a: ReadonlyVec, + b: ReadonlyVec, + c: ReadonlyVec, + res?: number, + iter?: number +) => + splitQuadratic( + a, b, c, + findClosestT( + partial(mixQuadratic, [], a, b, c), + p, + res, + iter + ) + ); diff --git a/packages/geom/src/internal/subdiv-curve.ts b/packages/geom/src/internal/subdiv-curve.ts new file mode 100644 index 0000000000..d0cf194d86 --- /dev/null +++ b/packages/geom/src/internal/subdiv-curve.ts @@ -0,0 +1,64 @@ +import { + comp, + indexed, + mapcat, + partition, + push, + transduce +} from "@thi.ng/transducers"; +import { + addW2, + addW3, + addW5, + ReadonlyVec, + Vec +} from "@thi.ng/vectors"; +import { SubdivKernel } from "../api"; + +export const subdivKernel2 = + ([ua, ub]: number[], [va, vb]: number[]) => + ([a, b]: ReadonlyVec[]) => [ + addW2([], a, b, ua, ub), + addW2([], a, b, va, vb), + ]; + +export const subdivKernel3 = + ([ua, ub, uc]: number[], [va, vb, vc]: number[]) => + ([a, b, c]: ReadonlyVec[]) => [ + addW3([], a, b, c, ua, ub, uc), + addW3([], a, b, c, va, vb, vc), + ]; + +export const subdivKernel5 = + ([ua, ub, uc, ud, ue]: number[], [va, vb, vc, vd, ve]: number[]) => + ([a, b, c, d, e]: ReadonlyVec[]) => [ + addW5([], a, b, c, d, e, ua, ub, uc, ud, ue), + addW5([], a, b, c, d, e, va, vb, vc, vd, ve), + ]; + +/** + * http://algorithmicbotany.org/papers/subgpu.sig2003.pdf + * + * @param kernel subdivision scheme + * @param pts source points + * @param recurse number of iterations + */ +export const subdivCurvePoints = ( + pts: ReadonlyVec[], + { fn, iter, size }: SubdivKernel, + recurse = 1) => { + + while (--recurse >= 0) { + const nump = pts.length; + pts = transduce( + comp( + partition(size, 1), + indexed(), + mapcat(([i, pts]) => fn(pts, i, nump)) + ), + push(), + iter ? iter(pts) : pts + ); + } + return pts; +}; diff --git a/packages/geom/src/internal/sutherland-hodgeman.ts b/packages/geom/src/internal/sutherland-hodgeman.ts index fe4b1ea771..48e3d15ef2 100644 --- a/packages/geom/src/internal/sutherland-hodgeman.ts +++ b/packages/geom/src/internal/sutherland-hodgeman.ts @@ -1,6 +1,6 @@ -import { Vec2 } from "@thi.ng/vectors/vec2"; -import { classify } from "./corner"; -import { intersectLines2 } from "./line-intersection"; +import { ReadonlyVec } from "@thi.ng/vectors"; +import { corner } from "./corner"; +import { intersectLineLine } from "../isec/line-line"; /** * Extended version of Sutherland-Hodgeman convex polygon clipping @@ -9,35 +9,36 @@ import { intersectLines2 } from "./line-intersection"; * * https://en.wikipedia.org/wiki/Sutherland%E2%80%93Hodgman_algorithm * - * @param poly subject poly - * @param bounds clipping boundary + * @param pts subject poly vertices + * @param bounds clipping boundary vertices * @param bc pre-computed boundary centroid * @param eps edge classification tolerance */ -export const clipConvex = (poly: Vec2[], bounds: Vec2[], bc: Vec2, eps = 1e-4) => { - for (let ne = bounds.length, j = ne - 1, i = 0; i < ne; j = i, i++) { - const clipped = []; - const ca = bounds[j]; - const cb = bounds[i]; - const sign = classify(ca, cb, bc, eps); - for (let np = poly.length, k = np - 1, l = 0; l < np; k = l, l++) { - const p = poly[k]; - const q = poly[l]; - const cqsign = classify(ca, cb, q, eps); - if (classify(ca, cb, p, eps) === sign) { - clipped.push( - cqsign !== sign ? - intersectLines2(ca, cb, p, q).isec : - q - ); - } else if (cqsign === sign) { - clipped.push(intersectLines2(ca, cb, p, q).isec, q); +export const sutherlandHodgeman = + (pts: ReadonlyVec[], bounds: ReadonlyVec[], bc: ReadonlyVec, eps = 1e-4) => { + for (let ne = bounds.length, j = ne - 1, i = 0; i < ne; j = i, i++) { + const clipped = []; + const ca = bounds[j]; + const cb = bounds[i]; + const sign = corner(ca, cb, bc, eps); + for (let np = pts.length, k = np - 1, l = 0; l < np; k = l, l++) { + const p = pts[k]; + const q = pts[l]; + const cqsign = corner(ca, cb, q, eps); + if (corner(ca, cb, p, eps) === sign) { + clipped.push( + cqsign !== sign ? + intersectLineLine(ca, cb, p, q).isec : + q + ); + } else if (cqsign === sign) { + clipped.push(intersectLineLine(ca, cb, p, q).isec, q); + } } + if (clipped.length < 2) { + return []; + } + pts = clipped; } - if (clipped.length < 2) { - return []; - } - poly = clipped; - } - return poly; -}; + return pts; + }; diff --git a/packages/geom/src/internal/tessellate.ts b/packages/geom/src/internal/tessellate.ts new file mode 100644 index 0000000000..ee68e24c15 --- /dev/null +++ b/packages/geom/src/internal/tessellate.ts @@ -0,0 +1,179 @@ +import { isFunction } from "@thi.ng/checks"; +import { + comp, + last, + map, + mapcat, + partition, + push, + range, + reducer, + repeat, + scan, + transduce, + tuples, + wrap +} from "@thi.ng/transducers"; +import { + mixN, + ReadonlyVec, + signedArea2, + Vec +} from "@thi.ng/vectors"; +import { Tessellator } from "../api"; +import { centroidRaw } from "../internal/centroid"; +import { pointInTriangle2 } from "../internal/triangle-point-inside"; +import { polyArea } from "../internal/poly-area"; + +const snip = ( + points: ReadonlyVec[], + u: number, + v: number, + w: number, + n: number, + ids: number[] +) => { + const a = points[ids[u]]; + const b = points[ids[v]]; + const c = points[ids[w]]; + if (signedArea2(a, b, c) > 0) { + for (let i = 0; i < n; i++) { + if (i !== u && i !== v && i !== w) { + if (pointInTriangle2(points[ids[i]], a, b, c)) { + return; + } + } + } + return [a, b, c]; + } +}; + +export const tesselEarCut = + (points: ReadonlyVec[]) => { + const tris: Vec[][] = []; + let n = points.length; + const ids = [ + ...(polyArea(points) > 0 ? + range(n) : + range(n - 1, -1, -1)) + ]; + let count = 2 * n - 1; + let v = n - 1, u, w, t; + while (count > 0 && n > 2) { + u = n <= v ? 0 : v; + v = u + 1; + v = n <= v ? 0 : v; + w = v + 1; + w = n <= w ? 0 : w; + t = snip(points, u, v, w, n, ids); + if (t !== undefined) { + tris.push(t); + ids.splice(v, 1); + n--; + count = 2 * n; + } else { + count--; + } + } + return tris; + }; + +export const tesselTriFan = + (points: ReadonlyVec[]) => { + const c = centroidRaw(points); + return transduce( + comp( + partition(2, 1), + map(([a, b]) => [a, b, c]) + ), + push(), + wrap(points, 1, false, true) + ); + }; + +export const tesselQuadFan = + (points: ReadonlyVec[]) => { + const p = centroidRaw(points); + return transduce( + comp( + partition(3, 1), + map(([a, b, c]) => [mixN([], a, b, 0.5), b, mixN([], b, c, 0.5), p]) + ), + push(), + wrap(points, 1, true, true) + ); + }; + +export const tesselEdgeSplit = + (points: ReadonlyVec[]) => { + const c = centroidRaw(points); + return transduce( + comp( + partition(2, 1), + mapcat(([a, b]) => { + const m = mixN([], a, b, 0.5); + return [[a, m, c], [m, b, c]]; + })), + push(), + wrap(points, 1, false, true) + ); + }; + +export const tesselRimTris = + (points: ReadonlyVec[]) => { + const edgeCentroids = transduce( + comp( + partition(2, 1), + map((e) => mixN([], e[0], e[1], 0.5)) + ), + push(), + wrap(points, 1, false, true) + ); + return transduce( + comp( + partition(2, 1), + map((t) => [t[0][0], t[1][1], t[1][0]]) + ), + push(), + [edgeCentroids], + wrap([...tuples(edgeCentroids, points)], 1, true, false) + ); + }; + +export const tesselInset = + (inset = 0.5, keepInterior = false) => + (points: ReadonlyVec[]) => { + const c = centroidRaw(points); + const inner = points.map((p) => mixN([], p, c, inset)); + return transduce( + comp( + partition(2, 1), + map(([[a, b], [c, d]]) => [a, b, d, c]) + ), + push(), + keepInterior ? [inner] : [], + wrap([...tuples(points, inner)], 1, false, true) + ); + }; + +export function tessellatePoints(points: ReadonlyVec[], tessFn: Tessellator, iter?: number): Vec[][]; +export function tessellatePoints(points: ReadonlyVec[], tessFns: Iterable): Vec[][]; +export function tessellatePoints(...args): Vec[][] { + return transduce( + scan( + reducer( + () => [args[0]], + (acc: Vec[][], fn: Tessellator) => + transduce( + mapcat(fn), + push(), + acc + ) + ) + ), + last(), + isFunction(args[1]) ? + repeat(args[1], args[2] || 1) : + args[1] + ); +} diff --git a/packages/geom/src/internal/transform-points.ts b/packages/geom/src/internal/transform-points.ts new file mode 100644 index 0000000000..21b6988e7b --- /dev/null +++ b/packages/geom/src/internal/transform-points.ts @@ -0,0 +1,10 @@ +import { mulV, ReadonlyMat } from "@thi.ng/matrices"; +import { ReadonlyVec } from "@thi.ng/vectors"; + +export const transformPoints = + (pts: ReadonlyVec[], mat: ReadonlyMat) => + (pts.forEach((p) => mulV(null, mat, p)), pts); + +export const transformedPoints = + (pts: ReadonlyVec[], mat: ReadonlyMat) => + pts.map((p) => mulV([], mat, p)); diff --git a/packages/geom/src/internal/translate-points.ts b/packages/geom/src/internal/translate-points.ts new file mode 100644 index 0000000000..946768b7ef --- /dev/null +++ b/packages/geom/src/internal/translate-points.ts @@ -0,0 +1,5 @@ +import { add, ReadonlyVec } from "@thi.ng/vectors"; + +export const translatedPoints = + (pts: ReadonlyVec[], delta: ReadonlyVec) => + pts.map((x) => add([], x, delta)); diff --git a/packages/geom/src/internal/triangle-point-inside.ts b/packages/geom/src/internal/triangle-point-inside.ts new file mode 100644 index 0000000000..b959efb9cb --- /dev/null +++ b/packages/geom/src/internal/triangle-point-inside.ts @@ -0,0 +1,24 @@ +import { EPS, sign } from "@thi.ng/math"; +import { ReadonlyVec, signedArea2 } from "@thi.ng/vectors"; +import { clockwise2 } from "./clockwise"; + +export const classifyPointInTriangle2 = + (p: ReadonlyVec, a: ReadonlyVec, b: ReadonlyVec, c: ReadonlyVec, eps = EPS) => { + const s = clockwise2(a, b, c) ? 1 : -1; + return sign( + Math.min( + s * signedArea2(a, c, p), + s * signedArea2(b, a, p), + s * signedArea2(c, b, p) + ), + eps + ); + }; + +export const pointInTriangle2 = + (p: ReadonlyVec, a: ReadonlyVec, b: ReadonlyVec, c: ReadonlyVec) => { + const s = clockwise2(a, b, c) ? 1 : -1; + return s * signedArea2(a, c, p) >= 0 && + s * signedArea2(b, a, p) >= 0 && + s * signedArea2(c, b, p) >= 0; + }; diff --git a/packages/geom/src/internal/union-bounds.ts b/packages/geom/src/internal/union-bounds.ts new file mode 100644 index 0000000000..d0dd42cb08 --- /dev/null +++ b/packages/geom/src/internal/union-bounds.ts @@ -0,0 +1,25 @@ +import { + add, + max, + min, + ReadonlyVec, + sub +} from "@thi.ng/vectors"; +import { VecPair } from "../api"; + +/** + * Takes the position and size vectors of 2 `AABBLike`s and returns + * 2-tuple of `[pos,size]` of their union bounds. + * + * @param apos + * @param asize + * @param bpos + * @param bsize + */ +export const unionBounds = + (apos: ReadonlyVec, asize: ReadonlyVec, bpos: ReadonlyVec, bsize: ReadonlyVec): VecPair => { + const p = add([], apos, asize); + const q = add([], bpos, bsize); + const pos = min([], apos, bpos); + return [pos, sub(null, max(null, p, q), pos)]; + }; diff --git a/packages/geom/src/isec/circle-circle.ts b/packages/geom/src/isec/circle-circle.ts new file mode 100644 index 0000000000..548285d71d --- /dev/null +++ b/packages/geom/src/isec/circle-circle.ts @@ -0,0 +1,28 @@ +import { ReadonlyVec, distSq, mag, sub, maddN, perpendicularLeft2, mulN, add } from "@thi.ng/vectors"; +import { eqDeltaFixed } from "@thi.ng/math"; +import { IntersectionType } from "../api"; + +export const intersectCircleCircle = + (a: ReadonlyVec, b: ReadonlyVec, ar: number, br: number) => { + const delta = sub([], b, a); + const d = mag(delta); + if (eqDeltaFixed(d, 0)) { + return { type: IntersectionType.COINCIDENT }; + } + if (d <= ar + br && d >= Math.abs(ar - br)) { + 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); + return { + type: IntersectionType.INTERSECT, + isec: [add([], p, t), sub([], p, t)] + }; + } + return { type: IntersectionType.NONE }; + }; + +export const testCircleCircle = + (a: ReadonlyVec, b: ReadonlyVec, ar: number, br: number) => + distSq(a, b) <= Math.pow(ar + br, 2); diff --git a/packages/geom/src/isec/line-line.ts b/packages/geom/src/isec/line-line.ts new file mode 100644 index 0000000000..9ce5f369c6 --- /dev/null +++ b/packages/geom/src/isec/line-line.ts @@ -0,0 +1,56 @@ +import { EPS, eqDeltaFixed } from "@thi.ng/math"; +import { mixN2, ReadonlyVec } from "@thi.ng/vectors"; +import { IntersectionType, LineIntersection } from "../api"; +import { closestPointSegment } from "../internal/closest-point"; + +export const intersectLineLine = + (a: ReadonlyVec, b: ReadonlyVec, c: ReadonlyVec, d: ReadonlyVec, eps = EPS): LineIntersection => { + + const bax = b[0] - a[0]; + const bay = b[1] - a[1]; + const dcx = d[0] - c[0]; + const dcy = d[1] - c[1]; + const acx = a[0] - c[0]; + const acy = a[1] - c[1]; + const det = dcy * bax - dcx * bay; + let alpha = dcx * acy - dcy * acx; + let beta = bax * acy - bay * acx; + if (eqDeltaFixed(det, 0, eps)) { + if (eqDeltaFixed(alpha, 0, eps) && eqDeltaFixed(beta, 0, eps)) { + let isec = closestPointSegment(c, a, b, undefined, true) || + closestPointSegment(d, a, b, undefined, true); + return { + type: isec ? + IntersectionType.COINCIDENT : + IntersectionType.COINCIDENT_NO_INTERSECT, + isec, + }; + } + return { type: IntersectionType.PARALLEL }; + } + alpha /= det; + beta /= det; + const ieps = 1 - eps; + return { + type: (eps < alpha && alpha < ieps) && (eps < beta && beta < ieps) ? + IntersectionType.INTERSECT : + IntersectionType.INTERSECT_OUTSIDE, + isec: mixN2([], a, b, alpha), + alpha, + beta, + det, + }; + }; + +/** + * 2D only. Returns true if line `a`,`b` is parallel (or coincident) to + * line `c`,`d`. + * + * @param a + * @param b + * @param c + * @param d + */ +export const isParallelLine = + (a: ReadonlyVec, b: ReadonlyVec, c: ReadonlyVec, d: ReadonlyVec) => + eqDeltaFixed((d[1] - c[1]) * (b[0] - a[0]) - (d[0] - c[0]) * (b[1] - a[1]), 0); diff --git a/packages/geom/src/isec/ray-circle.ts b/packages/geom/src/isec/ray-circle.ts new file mode 100644 index 0000000000..4094683e31 --- /dev/null +++ b/packages/geom/src/isec/ray-circle.ts @@ -0,0 +1,22 @@ +import { sub, dot, magSq, maddN, ReadonlyVec } from "@thi.ng/vectors"; + +export const intersectRayCircle = + (rpos: ReadonlyVec, dir: ReadonlyVec, spos: ReadonlyVec, r: number) => { + const delta = sub([], spos, rpos); + const w = dot(delta, dir); + let d = r * r + w * w - magSq(delta); + if (d >= 0) { + d = Math.sqrt(d); + const a = w + d; + const b = w - d; + return 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)] : + b >= 0 ? + [maddN(delta, rpos, dir, b)] : + undefined; + } + }; diff --git a/packages/geom/src/isec/ray-line.ts b/packages/geom/src/isec/ray-line.ts new file mode 100644 index 0000000000..e5ff243470 --- /dev/null +++ b/packages/geom/src/isec/ray-line.ts @@ -0,0 +1,17 @@ +import { eqDeltaFixed } from "@thi.ng/math"; +import { ReadonlyVec } from "@thi.ng/vectors"; + +export const intersectRayLine = + (rpos: ReadonlyVec, dir: ReadonlyVec, a: ReadonlyVec, b: ReadonlyVec) => { + const bax = b[0] - a[0]; + const bay = b[1] - a[1]; + const d = dir[0] * bay - dir[1] * bax; + if (eqDeltaFixed(d, 0)) return; + const arx = a[0] - rpos[0]; + const ary = a[1] - rpos[1]; + const t = (bay * arx - bax * ary) / d; + const s = (dir[1] * arx - dir[0] * ary) / d; + return t >= 0 && s >= 0 && s <= 1 ? + t : + undefined; + }; diff --git a/packages/geom/src/isec/ray-poly.ts b/packages/geom/src/isec/ray-poly.ts new file mode 100644 index 0000000000..c9ef8134b2 --- /dev/null +++ b/packages/geom/src/isec/ray-poly.ts @@ -0,0 +1,56 @@ +import { maddN2, ReadonlyVec } from "@thi.ng/vectors"; +import { IntersectionType } from "../api"; +import { intersectRayLine } from "./ray-line"; + +export const intersectRayPolyline = + (rpos: ReadonlyVec, dir: ReadonlyVec, pts: ReadonlyVec[], closed = false) => { + const n = pts.length - 1; + let minD = Infinity; + let cross = 0; + let i, j; + if (closed) { + i = pts[n]; + j = pts[0]; + } else { + i = pts[0]; + j = pts[1]; + } + for (let k = 0; k <= n; i = j, j = pts[++k]) { + const d = intersectRayLine(rpos, dir, i, j); + if (d !== undefined) { + cross++; + if (d < minD) minD = d; + } + } + return cross > 0 ? + { + type: IntersectionType.INTERSECT, + isec: maddN2([], rpos, dir, minD), + dist: minD, + inside: !(cross & 1) + } : + { + type: IntersectionType.NONE + }; + }; + +export const intersectRayPolylineAll = + (rpos: ReadonlyVec, dir: ReadonlyVec, pts: ReadonlyVec[], closed = false) => { + const n = pts.length - 1; + let i, j; + if (closed) { + i = pts[n]; + j = pts[0]; + } else { + i = pts[0]; + j = pts[1]; + } + const res = []; + for (let k = 0; k <= n; i = j, j = pts[++k]) { + const d = intersectRayLine(rpos, dir, i, j); + if (d !== undefined) { + res.push([d, maddN2([], rpos, dir, d)]); + } + } + return res.sort((a, b) => a[0] - b[0]); + }; diff --git a/packages/geom/src/isec/rect-circle.ts b/packages/geom/src/isec/rect-circle.ts new file mode 100644 index 0000000000..eb7a9eecc5 --- /dev/null +++ b/packages/geom/src/isec/rect-circle.ts @@ -0,0 +1,34 @@ +export const intersectRectCircle = ( + rx: number, + ry: number, + w: number, + h: number, + cx: number, + cy: number, + r: number +) => + (rcAxis(cx, rx, w) + rcAxis(cy, ry, h)) <= r * r; + +export const intersectAABBSphere = ( + rx: number, + ry: number, + rz: number, + w: number, + h: number, + d: number, + cx: number, + cy: number, + cz: number, + r: number +) => ( + rcAxis(cx, rx, w) + + rcAxis(cy, ry, h) + + rcAxis(cz, rz, d) +) <= r * r; + +const rcAxis = (a: number, b: number, c: number) => + a < b ? + Math.pow(a - b, 2) : + a > b + c ? + Math.pow(a - b - c, 2) : + 0; diff --git a/packages/geom/src/isec/rect-rect.ts b/packages/geom/src/isec/rect-rect.ts new file mode 100644 index 0000000000..123898d054 --- /dev/null +++ b/packages/geom/src/isec/rect-rect.ts @@ -0,0 +1,6 @@ +export const testRectRect = + (ax: number, ay: number, aw: number, ah: number, bx: number, by: number, bw: number, bh: number) => + !((ax > bx + bw) || + (bx > ax + aw) || + (ay > by + bh) || + (by > ay + ah)); diff --git a/packages/geom/src/line2.ts b/packages/geom/src/line2.ts deleted file mode 100644 index 0b98609b26..0000000000 --- a/packages/geom/src/line2.ts +++ /dev/null @@ -1,107 +0,0 @@ -import { isArrayLike } from "@thi.ng/checks/is-arraylike"; -import { isNumber } from "@thi.ng/checks/is-number"; -import { isPlainObject } from "@thi.ng/checks/is-plain-object"; -import { ReadonlyVec, Vec } from "@thi.ng/vectors/api"; -import { asVec2, Vec2 } from "@thi.ng/vectors/vec2"; -import { - Attribs, - HiccupLine2, - IToCubic, - SamplingOpts -} from "./api"; -import { Cubic2 } from "./bezier2"; -import { PointContainer2 } from "./container2"; -import { liangBarsky2 } from "./internal/liang-barsky"; -import { intersectLines2 } from "./internal/line-intersection"; -import { Rect2 } from "./rect2"; -import { Sampler } from "./sampler"; - -export class Line2 extends PointContainer2 implements - IToCubic { - - constructor(points: Vec2[], attribs?: Attribs) { - if (points.length > 2) { - points = points.slice(0, 2); - } - super(points, attribs); - } - - copy() { - return new Line2(this._copy(), { ...this.attribs }); - } - - edges() { - return this.points.slice(0, 2); - } - - area() { - return 0; - } - - arcLength() { - const pts = this.points; - return pts[0].dist(pts[1]); - } - - vertices(opts?: number | Partial) { - const sampler = new Sampler(this.points); - if (opts !== undefined) { - if (isPlainObject(opts)) { - return opts.dist ? - sampler.sampleUniform(opts.dist, opts.last !== false) : - sampler.sampleFixedNum(opts.num, opts.last !== false); - } - return sampler.sampleFixedNum(opts, true); - } else { - return this.points; - } - } - - intersectLine(l: Line2) { - return intersectLines2(this.points[0], this.points[1], l.points[0], l.points[1]); - } - - clipRect(bounds: [Vec2, Vec2] | Rect2) { - const res = bounds instanceof Rect2 ? - liangBarsky2(this.points[0], this.points[1], bounds.pos, bounds.pos.addNew(bounds.size)) : - liangBarsky2(this.points[0], this.points[1], bounds[0], bounds[1]); - if (res) { - return new Line2([res[0], res[1]], { ...this.attribs }); - } - } - - toCubic() { - return [Cubic2.fromLine(this.points[0], this.points[1], { ...this.attribs })]; - } - - toHiccup(): HiccupLine2 { - return ["line", this.attribs || {}, this.points[0], this.points[1]]; - } - - toHiccupPathSegments() { - return [["L", this.points[1]]]; - } - - toJSON() { - return this._toJSON("line2"); - } -} - -export function line2(points: Vec, start?: number, cstride?: number, estride?: number, attribs?: Attribs): Line2; -export function line2(x1: number, y1: number, x2: number, y2: number, attribs?: Attribs): Line2; -export function line2(a: ReadonlyVec, b: ReadonlyVec, attribs?: Attribs): Line2; -export function line2(...args: any[]) { - let points = args[0], attribs; - let n = args.length - 1; - if (isPlainObject(args[n]) || args[n] == null) { - attribs = args[n]; - n--; - } - if (isNumber(points)) { - return new Line2(Vec2.mapBuffer(args.slice(0, 4), 2), attribs); - } - if (isArrayLike(points)) { - return new Line2([asVec2(points), asVec2(args[1])], attribs); - } - return new Line2(Vec2.mapBuffer(points, 2, args[1] || 0, args[2] || 1, args[3] || 2), attribs); -} diff --git a/packages/geom/src/ops/arc-length.ts b/packages/geom/src/ops/arc-length.ts new file mode 100644 index 0000000000..2f273f03fe --- /dev/null +++ b/packages/geom/src/ops/arc-length.ts @@ -0,0 +1,79 @@ +import { defmulti, MultiFn1 } from "@thi.ng/defmulti"; +import { PI, TAU } from "@thi.ng/math"; +import { dist } from "@thi.ng/vectors"; +import { + Circle, + Ellipse, + Group, + IShape, + Line, + Polygon, + Rect, + Type, + Triangle +} from "../api"; +import { dispatch } from "../internal/dispatch"; +import { polyArcLength } from "../internal/poly-arc-length"; + +/** + * Returns the arc length / perimeter / circumference of the given + * shape. For groups calls `arcLength()` for each child and returns the + * sum of results. + * + * Implemented for: + * + * - Circle + * - Ellipse + * - Group + * - Line + * - Polygon + * - Polyline + * - Quad + * - Rect + * - Triangle + * + */ +export const arcLength: MultiFn1 = defmulti(dispatch); + +arcLength.addAll({ + + [Type.CIRCLE]: + ($: Circle) => + TAU * $.r, + + [Type.ELLIPSE]: + ({ r: [a, b] }: Ellipse) => + // Ramanujan approximation + // https://www.mathsisfun.com/geometry/ellipse-perimeter.html + PI * ((3 * (a + b)) - Math.sqrt((3 * a + b) * (3 * b + a))), + + [Type.GROUP]: + ({ children }: Group) => + children.reduce((sum, $) => sum + arcLength($), 0), + + [Type.LINE]: + ({ points }: Line) => + dist(points[0], points[1]), + + [Type.POLYGON]: + ({ points }: Polygon) => + polyArcLength(points, points.length, true), + + [Type.POLYLINE]: + ({ points }: Polygon) => + polyArcLength(points, points.length), + + [Type.RECT]: + ({ size }: Rect) => + 2 * (size[0] + size[1]), + + [Type.TRIANGLE]: + ({ points }: Triangle) => + dist(points[0], points[1]) + + dist(points[1], points[2]) + + dist(points[2], points[0]), + +}); + +arcLength.isa(Type.QUAD, Type.POLYGON); +arcLength.isa(Type.TRIANGLE, Type.POLYGON); diff --git a/packages/geom/src/ops/area.ts b/packages/geom/src/ops/area.ts new file mode 100644 index 0000000000..844c0dc648 --- /dev/null +++ b/packages/geom/src/ops/area.ts @@ -0,0 +1,101 @@ +import { defmulti, MultiFn1O } from "@thi.ng/defmulti"; +import { PI } from "@thi.ng/math"; +import { signedArea2, Vec } from "@thi.ng/vectors"; +import { + AABB, + Circle, + Ellipse, + Group, + IShape, + Polygon, + Rect, + Triangle, + Type, + Arc +} from "../api"; +import { dispatch } from "../internal/dispatch"; +import { polyArea } from "../internal/poly-area"; + +/** + * Returns the possibly signed (unsigned by default) surface area of given + * `shape`. For groups calls `area()` for each child and returns sum of + * unsigned areas. + * + * In general, for polygons and triangles, the sign of the result can be + * used as indication of the shapes orientation (clockwise / + * counterclockwise). + * + * For curves, lines, point clouds and rays the function returns 0. + * + * Implemented for: + * + * - AABB + * - Circle + * - Cubic + * - Ellipse + * - Group + * - Line + * - Points + * - Polygon + * - Polyline + * - Quad + * - Quadratic + * - Ray + * - Rect + * - Triangle + * + * @param shape + * @param signed true, if signed area + */ +export const area: MultiFn1O = defmulti(dispatch); + +area.addAll({ + + [Type.AABB]: + ({ size: [w, h, d] }: AABB) => + 2 * ((w * h) + (w * d) + (h * d)), + + [Type.ARC]: + // http://cut-the-knot.org/Generalization/Cavalieri2.shtml + ($: Arc) => 0.5 * Math.abs($.start - $.end) * $.r[0] * $.r[1], + + [Type.CIRCLE]: + ($: Circle) => + PI * $.r * $.r, + + [Type.ELLIPSE]: + ($: Ellipse) => + PI * $.r[0] * $.r[1], + + [Type.GROUP]: + ({ children }: Group) => + children.reduce((sum, $) => sum + area($, false), 0), + + [Type.POINTS]: + () => 0, + + [Type.POLYGON]: + ($: Polygon, signed?) => { + const area = polyArea($.points); + return signed ? area : Math.abs(area); + }, + + [Type.RECT]: + ($: Rect) => + $.size[0] * $.size[1], + + [Type.TRIANGLE]: + ($: Triangle, signed?) => { + const area = 0.5 * signedArea2(...<[Vec, Vec, Vec]>$.points); + return signed ? area : Math.abs(area); + }, + +}); + +area.isa(Type.ARC, Type.POINTS); +area.isa(Type.CUBIC, Type.POINTS); +area.isa(Type.LINE, Type.POINTS); +area.isa(Type.POLYLINE, Type.POINTS); +area.isa(Type.QUAD, Type.POLYGON); +area.isa(Type.QUADRATIC, Type.POINTS); +area.isa(Type.RAY, Type.POINTS); diff --git a/packages/geom/src/ops/as-cubic.ts b/packages/geom/src/ops/as-cubic.ts new file mode 100644 index 0000000000..766c6c5086 --- /dev/null +++ b/packages/geom/src/ops/as-cubic.ts @@ -0,0 +1,92 @@ +import { defmulti } from "@thi.ng/defmulti"; +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, + IShape, + Line, + Path, + Quadratic, + Type +} from "../api"; +import { cubicFromLine, cubicFromQuadratic } from "../ctors/cubic"; +import { dispatch } from "../internal/dispatch"; + +export const asCubic = defmulti(dispatch); + +asCubic.addAll({ + + [Type.ARC]: + ($: Arc) => { + const p = $.pointAtTheta($.start); + const q = $.pointAtTheta($.end); + const [rx, ry] = $.r; + const [sphi, cphi] = sincos($.axis); + const dx = cphi * (p[0] - q[0]) / 2 + sphi * (p[1] - q[1]) / 2; + const dy = -sphi * (p[0] - q[0]) / 2 + cphi * (p[1] - q[1]) / 2; + if ((dx === 0 && dy === 0) || magSq2($.r) < EPS) { + return [cubicFromLine(p, q, { ...$.attribs })]; + } + + const mapP = (x: number, y: number) => { + x *= rx; + y *= ry; + return add2( + null, + [ + cphi * x - sphi * y, + sphi * x + cphi * y + ], + $.pos + ); + }; + + const res: Cubic[] = []; + const delta = $.end - $.start; + const n = Math.max(roundEps(Math.abs(delta) / HALF_PI, 1e-3), 1); + // https://github.com/chromium/chromium/blob/master/third_party/blink/renderer/core/svg/svg_path_parser.cc#L253 + const d = delta / n; + const t = 8 / 6 * Math.tan(0.25 * d); + if (!isFinite(t)) { + return [cubicFromLine(p, q)]; + } + for (let i = n, theta = $.start; i > 0; i-- , theta += d) { + const [s1, c1] = sincos(theta); + const [s2, c2] = sincos(theta + d); + const curve = new Cubic( + [ + mapP(c1, s1), + mapP(c1 - s1 * t, s1 + c1 * t), + mapP(c2 + s2 * t, s2 - c2 * t), + mapP(c2, s2), + ], + { ...$.attribs } + ); + res.push(curve); + } + return res; + }, + + [Type.CUBIC]: + ($: Cubic) => [$], + + [Type.LINE]: + ({ attribs, points }: Line) => + [cubicFromLine(points[0], points[1], { ...attribs })], + + [Type.PATH]: + ($: Path) => + [...mapcat((s) => s.geo ? asCubic(s.geo) : null, $.segments)], + + [Type.QUADRATIC]: + ({ attribs, points }: Quadratic) => + [cubicFromQuadratic(points[0], points[1], points[2], { ...attribs })], + +}); diff --git a/packages/geom/src/ops/as-polygon.ts b/packages/geom/src/ops/as-polygon.ts new file mode 100644 index 0000000000..5a82145e28 --- /dev/null +++ b/packages/geom/src/ops/as-polygon.ts @@ -0,0 +1,28 @@ +import { defmulti, MultiFn1O } from "@thi.ng/defmulti"; +import { + IShape, + Polygon, + SamplingOpts, + Type +} from "../api"; +import { dispatch } from "../internal/dispatch"; +import { vertices } from "./vertices"; + +export const asPolygon: MultiFn1O, Polygon> = defmulti(dispatch); + +asPolygon.addAll({ + + [Type.POINTS]: + ($, opts) => new Polygon(vertices($, opts), { ...$.attribs }), + +}); + +asPolygon.isa(Type.CIRCLE, Type.POINTS); +asPolygon.isa(Type.ELLIPSE, Type.POINTS); +asPolygon.isa(Type.LINE, Type.POINTS); +asPolygon.isa(Type.PATH, Type.POINTS); +asPolygon.isa(Type.POLYGON, Type.POINTS); +asPolygon.isa(Type.POLYLINE, Type.POINTS); +asPolygon.isa(Type.QUAD, Type.POINTS); +asPolygon.isa(Type.RECT, Type.POINTS); +asPolygon.isa(Type.TRIANGLE, Type.POINTS); diff --git a/packages/geom/src/ops/as-svg.ts b/packages/geom/src/ops/as-svg.ts new file mode 100644 index 0000000000..8b3322bbb0 --- /dev/null +++ b/packages/geom/src/ops/as-svg.ts @@ -0,0 +1,27 @@ +import { serialize } from "@thi.ng/hiccup"; +import { convertTree, ff, svg } from "@thi.ng/hiccup-svg"; +import { Attribs, IShape } from "../api"; +import { bounds } from "./bounds"; +import { collBounds } from "../internal/bounds"; + +export const asSvg = + (...args: any[]) => + args + .map((x) => serialize(convertTree(x))) + .join(""); + +export const svgDoc = + (attribs: Attribs, ...xs: IShape[]) => { + if (xs.length > 0) { + if (!attribs || !attribs.viewBox) { + const [pos, size] = collBounds(xs, bounds); + attribs = { + width: ff(size[0]), + height: ff(size[1]), + viewBox: `${ff(pos[0])} ${ff(pos[1])} ${ff(size[0])} ${ff(size[1])}`, + ...attribs + }; + } + } + return svg(attribs, ...xs); + }; diff --git a/packages/geom/src/ops/bounds.ts b/packages/geom/src/ops/bounds.ts new file mode 100644 index 0000000000..477a3eccf7 --- /dev/null +++ b/packages/geom/src/ops/bounds.ts @@ -0,0 +1,133 @@ +import { defmulti } from "@thi.ng/defmulti"; +import { HALF_PI, inRange, PI } from "@thi.ng/math"; +import { + comp, + filter, + iterator1, + map, + push, + range, + transduce +} from "@thi.ng/transducers"; +import { + max, + MAX2, + min, + MIN2, + mul2, + mulN2, + set2, + sub2, + subN2, + Vec +} from "@thi.ng/vectors"; +import { + AABBLike, + Arc, + Circle, + Cubic, + Ellipse, + Group, + IShape, + Line, + Path, + PathSegment, + PCLike, + Quadratic, + Rect, + Type +} from "../api"; +import { rectFromMinMax } from "../ctors/rect"; +import { + boundsRaw, + collBounds, + cubicBounds2, + quadraticBounds2 +} from "../internal/bounds"; +import { dispatch } from "../internal/dispatch"; + +export const bounds = defmulti(dispatch); + +bounds.addAll({ + + [Type.ARC]: + (arc: Arc) => { + const pts = transduce( + map(arc.pointAtTheta.bind(arc)), + push(), + [ + arc.start, + arc.end, + // multiples of HALF_PI in arc range + ...filter( + (t: number) => inRange(t, arc.start, arc.end), + range(-3 * PI, 3.01 * PI, HALF_PI) + ) + ] + ); + return rectFromMinMax(...boundsRaw(pts, set2([], MAX2), set2([], MIN2))); + }, + + [Type.CIRCLE]: + ($: Circle) => + new Rect( + subN2([], $.pos, $.r), + mulN2(null, [2, 2], $.r) + ), + + [Type.CUBIC]: + ({ points }: Cubic) => + rectFromMinMax( + ...cubicBounds2(points[0], points[1], points[2], points[3]) + ), + + [Type.ELLIPSE]: + ($: Ellipse) => + new Rect( + sub2([], $.pos, $.r), + mul2(null, [2, 2], $.r) + ), + + [Type.GROUP]: + ($: Group) => + new Rect(...collBounds($.children, bounds)), + + [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.POINTS]: + ($: PCLike) => + rectFromMinMax(...boundsRaw($.points, set2([], MAX2), set2([], MIN2))), + + [Type.QUADRATIC]: + ({ points }: Quadratic) => + rectFromMinMax( + ...quadraticBounds2(points[0], points[1], points[2]) + ), + + [Type.RECT]: + ($: IShape) => $.copy(), + +}); + +bounds.isa(Type.AABB, Type.RECT); +bounds.isa(Type.POLYGON, Type.POINTS); +bounds.isa(Type.POLYLINE, Type.POINTS); +bounds.isa(Type.QUAD, Type.POINTS); +bounds.isa(Type.TRIANGLE, Type.POINTS); diff --git a/packages/geom/src/ops/center.ts b/packages/geom/src/ops/center.ts new file mode 100644 index 0000000000..4f7efec67b --- /dev/null +++ b/packages/geom/src/ops/center.ts @@ -0,0 +1,48 @@ +import { DEFAULT, defmulti, MultiFn1O } from "@thi.ng/defmulti"; +import { + ReadonlyVec, + set2, + set3, + submN, + ZERO2, + ZERO3 +} from "@thi.ng/vectors"; +import { + Arc, + Circle, + Ellipse, + IShape, + Sphere, + Type +} from "../api"; +import { dispatch } from "../internal/dispatch"; +import { centroid } from "./centroid"; +import { translate } from "./translate"; + +export const center: MultiFn1O = defmulti(dispatch); + +center.add( + DEFAULT, + ($, origin = ZERO3) => + translate($, submN(null, centroid($), origin, -1)) +); + +center.addAll({ + + [Type.ARC]: + ($: Arc, origin = ZERO2) => + new Arc(set2([], origin), set2([], $.r), $.axis, $.start, $.end, $.xl, $.cw, { ...$.attribs }), + + [Type.CIRCLE]: + ($: Circle, origin = ZERO2) => + new Circle(set2([], origin), $.r, { ...$.attribs }), + + [Type.ELLIPSE]: + ($: Ellipse, origin = ZERO2) => + new Ellipse(set2([], origin), set2([], $.r), { ...$.attribs }), + + [Type.SPHERE]: + ($: Sphere, origin = ZERO3) => + new Sphere(set3([], origin), $.r, { ...$.attribs }), + +}); diff --git a/packages/geom/src/ops/centroid.ts b/packages/geom/src/ops/centroid.ts new file mode 100644 index 0000000000..8781fd4187 --- /dev/null +++ b/packages/geom/src/ops/centroid.ts @@ -0,0 +1,65 @@ +import { defmulti, MultiFn1O } from "@thi.ng/defmulti"; +import { + add, + divN, + maddN, + mixN, + set, + Vec +} from "@thi.ng/vectors"; +import { + AABBLike, + Circle, + Group, + IShape, + Line, + PCLike, + Polygon, + Triangle, + Type +} from "../api"; +import { centroidRaw } from "../internal/centroid"; +import { dispatch } from "../internal/dispatch"; +import { polyCentroid } from "../internal/poly-centroid"; +import { bounds } from "./bounds"; + +export const centroid: MultiFn1O = defmulti(dispatch); + +centroid.addAll({ + + [Type.CIRCLE]: + ($: Circle, out?) => + set(out || [], $.pos), + + [Type.GROUP]: + ($: Group) => + centroid(bounds($)), + + [Type.LINE]: + ({ points }: Line, out?) => + mixN(out || [], points[0], points[1], 0.5), + + [Type.POINTS]: + ($: PCLike, out?) => + centroidRaw($.points, out), + + [Type.POLYGON]: + ($: Polygon, out?) => polyCentroid($.points, out), + + [Type.RECT]: + ($: AABBLike, out?) => maddN(out || [], $.pos, $.size, 0.5), + + [Type.TRIANGLE]: + ({ points }: Triangle, out?) => + divN(null, add(null, add(out || [], points[0], points[1]), points[2]), 3) + +}); + +centroid.isa(Type.ARC, Type.CIRCLE); +centroid.isa(Type.AABB, Type.RECT); +centroid.isa(Type.ELLIPSE, Type.CIRCLE); +centroid.isa(Type.LINE3, Type.LINE); +centroid.isa(Type.POLYLINE, Type.POINTS); +centroid.isa(Type.QUAD, Type.POLYGON); +centroid.isa(Type.SPHERE, Type.CIRCLE); +centroid.isa(Type.TRIANGLE3, Type.TRIANGLE); diff --git a/packages/geom/src/ops/classify-point.ts b/packages/geom/src/ops/classify-point.ts new file mode 100644 index 0000000000..6c0b28b2f2 --- /dev/null +++ b/packages/geom/src/ops/classify-point.ts @@ -0,0 +1,20 @@ +import { defmulti, MultiFn2O } from "@thi.ng/defmulti"; +import { EPS, sign } from "@thi.ng/math"; +import { ReadonlyVec, distSq } from "@thi.ng/vectors"; +import { Circle, IShape, Type, Triangle } from "../api"; +import { dispatch } from "../internal/dispatch"; +import { classifyPointInTriangle2 } from "../internal/triangle-point-inside"; + +export const classifyPoint: MultiFn2O = defmulti(dispatch); + +classifyPoint.addAll({ + + [Type.CIRCLE]: + ($: Circle, p: ReadonlyVec, eps = EPS) => + sign($.r * $.r - distSq($.pos, p), eps), + + [Type.TRIANGLE]: + ({ points }: Triangle, p: ReadonlyVec, eps = EPS) => + classifyPointInTriangle2(p, points[0], points[1], points[2], eps), + +}); diff --git a/packages/geom/src/ops/clip-convex.ts b/packages/geom/src/ops/clip-convex.ts new file mode 100644 index 0000000000..cc4da93295 --- /dev/null +++ b/packages/geom/src/ops/clip-convex.ts @@ -0,0 +1,31 @@ +import { defmulti } from "@thi.ng/defmulti"; +import { IShape, Polygon, Type } from "../api"; +import { dispatch } from "../internal/dispatch"; +import { sutherlandHodgeman } from "../internal/sutherland-hodgeman"; +import { vertices } from "./vertices"; +import { centroid } from "./centroid"; + +export const clipConvex = defmulti(dispatch); + +clipConvex.addAll({ + + [Type.POLYGON]: + ($: Polygon, boundary: IShape) => + new Polygon( + sutherlandHodgeman($.points, vertices(boundary), centroid(boundary)), + { ...$.attribs } + ), + + [Type.RECT]: + ($, boundary: IShape) => + new Polygon( + sutherlandHodgeman(vertices($), vertices(boundary), centroid(boundary)), + { ...$.attribs } + ) +}); + +clipConvex.isa(Type.CIRCLE, Type.RECT); +clipConvex.isa(Type.ELLIPSE, Type.RECT); +clipConvex.isa(Type.PATH, Type.RECT); +clipConvex.isa(Type.QUAD, Type.POLYGON); +clipConvex.isa(Type.TRIANGLE, Type.POLYGON); diff --git a/packages/geom/src/ops/closest-point.ts b/packages/geom/src/ops/closest-point.ts new file mode 100644 index 0000000000..0817e4963a --- /dev/null +++ b/packages/geom/src/ops/closest-point.ts @@ -0,0 +1,75 @@ +import { defmulti, MultiFn2O } from "@thi.ng/defmulti"; +import { + add, + normalize, + ReadonlyVec, + set, + sub, + Vec +} from "@thi.ng/vectors"; +import { + Arc, + Circle, + Cubic, + IShape, + Line, + PCLike, + Quadratic, + Type +} from "../api"; +import { + closestPointArc, + closestPointArray, + closestPointCubic, + closestPointPolyline, + closestPointQuadratic, + closestPointSegment +} from "../internal/closest-point"; +import { dispatch } from "../internal/dispatch"; +import { vertices } from "./vertices"; + +export const closestPoint: MultiFn2O = defmulti(dispatch); + +closestPoint.addAll({ + + [Type.ARC]: + ($: Arc, p, out = []) => + closestPointArc(p, $.pos, $.r, $.axis, $.start, $.end, out), + + [Type.CIRCLE]: + ($: Circle, p, out = []) => + add(null, normalize(null, sub(out, p, $.pos), $.r), $.pos), + + [Type.CUBIC]: + ({ points }: Cubic, p, out = []) => + closestPointCubic(p, points[0], points[1], points[2], points[3], out), + + [Type.LINE]: + ({ points }: Line, p, out = []) => + closestPointSegment(p, points[0], points[1], out), + + [Type.POINTS]: + ($: PCLike, p, out) => + set(out, closestPointArray(p, $.points)), + + [Type.POLYGON]: + ($: PCLike, p, out = []) => + closestPointPolyline(p, $.points, true, out), + + [Type.POLYLINE]: + ($: PCLike, p, out = []) => + closestPointPolyline(p, $.points, false, out), + + [Type.QUADRATIC]: + ({ points }: Quadratic, p, out = []) => + closestPointQuadratic(p, points[0], points[1], points[2], out), + + [Type.RECT]: + ($, p, out = []) => + closestPointPolyline(p, vertices($), true, out), + +}); + +closestPoint.isa(Type.QUAD, Type.POLYGON); +closestPoint.isa(Type.SPHERE, Type.CIRCLE); +closestPoint.isa(Type.TRIANGLE, Type.POLYGON); diff --git a/packages/geom/src/ops/convex-hull.ts b/packages/geom/src/ops/convex-hull.ts new file mode 100644 index 0000000000..c8a16791c8 --- /dev/null +++ b/packages/geom/src/ops/convex-hull.ts @@ -0,0 +1,34 @@ +import { defmulti } from "@thi.ng/defmulti"; +import { + IShape, + PCLike, + Polygon, + Type +} from "../api"; +import { dispatch } from "../internal/dispatch"; +import { grahamScan2 } from "../internal/graham-scan"; +import { vertices } from "./vertices"; + +export const convexHull = defmulti(dispatch); + +convexHull.addAll({ + + [Type.GROUP]: + ($) => + new Polygon(vertices($), { ...$.attribs }), + + [Type.POINTS]: + ($: PCLike) => + new Polygon(grahamScan2($.points), { ...$.attribs }), + + [Type.TRIANGLE]: + ($) => $.copy(), + +}); + +convexHull.isa(Type.CIRCLE, Type.TRIANGLE); +convexHull.isa(Type.ELLIPSE, Type.TRIANGLE); +convexHull.isa(Type.POLYGON, Type.POINTS); +convexHull.isa(Type.POLYLINE, Type.POINTS); +convexHull.isa(Type.QUAD, Type.POINTS); +convexHull.isa(Type.RECT, Type.TRIANGLE); diff --git a/packages/geom/src/ops/edges.ts b/packages/geom/src/ops/edges.ts new file mode 100644 index 0000000000..9d3f1220ef --- /dev/null +++ b/packages/geom/src/ops/edges.ts @@ -0,0 +1,35 @@ +import { defmulti, MultiFn1O } from "@thi.ng/defmulti"; +import { + IShape, + Polygon, + Polyline, + SamplingOpts, + Type, + VecPair, + Rect +} from "../api"; +import { dispatch } from "../internal/dispatch"; +import { edgeIterator } from "../internal/edges"; +import { vertices } from "./vertices"; + +export const edges: MultiFn1O, Iterable> = defmulti(dispatch); + +edges.addAll({ + + [Type.POLYGON]: + ($: Polygon) => + edgeIterator($.points, true), + + [Type.POLYLINE]: + ($: Polyline) => + edgeIterator($.points), + + [Type.RECT]: + ($: Rect) => + edgeIterator(vertices($), true), + +}); + +edges.isa(Type.LINE, Type.POLYLINE); +edges.isa(Type.QUAD, Type.POLYGON); +edges.isa(Type.TRIANGLE, Type.POLYGON); diff --git a/packages/geom/src/ops/fit-into-bounds.ts b/packages/geom/src/ops/fit-into-bounds.ts new file mode 100644 index 0000000000..7ef4e0765b --- /dev/null +++ b/packages/geom/src/ops/fit-into-bounds.ts @@ -0,0 +1,57 @@ +import { + concat, + ReadonlyMat, + scale23, + translation23 +} from "@thi.ng/matrices"; +import { div2, neg, ReadonlyVec } from "@thi.ng/vectors"; +import { IShape, Rect } from "../api"; +import { collBounds } from "../internal/bounds"; +import { bounds } from "./bounds"; +import { center } from "./center"; +import { centroid } from "./centroid"; +import { mapPoint } from "./map-point"; +import { transform } from "./transform"; +import { unmapPoint } from "./unmap-point"; + +const translateScale2 = + (shape: IShape, c1: ReadonlyVec, c2: ReadonlyVec, smat: ReadonlyMat) => + transform( + shape, + concat( + translation23([], c1), + smat, + translation23([], c2) + ) + ); + +export const fitIntoBounds2 = + (shape: IShape, dest: Rect) => { + const src = bounds(shape); + const tscale = div2([], dest.size, src.size); + const scale = Math.min(tscale[0], tscale[1]); + return translateScale2( + shape, + centroid(dest), + neg(null, centroid(src)), + scale23([], scale) + ); + }; + +export const fitAllIntoBounds2 = + (shapes: IShape[], dest: Rect) => { + const src = new Rect(...collBounds(shapes, bounds)); + 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 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)); + } + return res; + }; diff --git a/packages/geom/src/ops/flip.ts b/packages/geom/src/ops/flip.ts new file mode 100644 index 0000000000..b1b3c19263 --- /dev/null +++ b/packages/geom/src/ops/flip.ts @@ -0,0 +1,59 @@ +import { DEFAULT, defmulti } from "@thi.ng/defmulti"; +import { neg } from "@thi.ng/vectors"; +import { + Arc, + Group, + IShape, + Path, + PCLike, + Ray, + Type +} from "../api"; +import { dispatch } from "../internal/dispatch"; + +export const flip = defmulti(dispatch); +flip.add(DEFAULT, ($) => $); + +flip.addAll({ + + [Type.ARC]: + ($: Arc) => { + const t = $.start; + $.start = $.end; + $.end = t; + $.cw = !$.cw; + return $; + }, + + [Type.GROUP]: + ($: Group) => { + $.children.forEach(flip); + return $; + }, + + [Type.PATH]: + ($: Path) => { + // TODO + return $; + }, + + [Type.POINTS]: + ($: PCLike) => { + $.points.reverse(); + return $; + }, + + [Type.RAY]: + ($: Ray) => { + $.dir = neg(null, $.dir); + return $; + } +}); + +flip.isa(Type.CUBIC, Type.POINTS); +flip.isa(Type.LINE, Type.POINTS); +flip.isa(Type.POLYGON, Type.POINTS); +flip.isa(Type.POLYLINE, Type.POINTS); +flip.isa(Type.QUAD, Type.POINTS); +flip.isa(Type.QUADRATIC, Type.POINTS); +flip.isa(Type.TRIANGLE, Type.POINTS); diff --git a/packages/geom/src/ops/intersects.ts b/packages/geom/src/ops/intersects.ts new file mode 100644 index 0000000000..3ac9ed634a --- /dev/null +++ b/packages/geom/src/ops/intersects.ts @@ -0,0 +1,70 @@ +import { defmulti, MultiFn2O } from "@thi.ng/defmulti"; +import { + Circle, + IntersectionResult, + IntersectionType, + IShape, + Line, + PCLike, + Ray, + Rect, + Sphere, + Type +} from "../api"; +import { dispatch2 } from "../internal/dispatch"; +import { intersectCircleCircle } from "../isec/circle-circle"; +import { intersectLineLine } from "../isec/line-line"; +import { intersectRayCircle } from "../isec/ray-circle"; +import { intersectRayPolyline } from "../isec/ray-poly"; +import { intersectRectCircle } from "../isec/rect-circle"; +import { testRectRect } from "../isec/rect-rect"; + +export const intersects: MultiFn2O = defmulti(dispatch2); + +intersects.addAll({ + + [`${Type.CIRCLE}-${Type.CIRCLE}`]: + (a: Sphere, b: Sphere) => + intersectCircleCircle(a.pos, b.pos, a.r, b.r), + + [`${Type.LINE}-${Type.LINE}`]: + ({ points: a }: Line, { points: b }: Line) => + intersectLineLine(a[0], a[1], b[0], b[1]), + + [`${Type.RAY}-${Type.CIRCLE}`]: + (ray: Ray, sphere: Sphere) => { + const isec = intersectRayCircle(ray.pos, ray.dir, sphere.pos, sphere.r); + return isec ? + { type: IntersectionType.INTERSECT, isec } : + { type: IntersectionType.NONE }; + }, + + [`${Type.RAY}-${Type.POLYGON}`]: + (ray: Ray, poly: PCLike) => + intersectRayPolyline(ray.pos, ray.dir, poly.points, true), + + [`${Type.RAY}-${Type.POLYLINE}`]: + (ray: Ray, poly: PCLike) => + intersectRayPolyline(ray.pos, ray.dir, poly.points, false), + + [`${Type.RECT}-${Type.CIRCLE}`]: + ({ pos: rp, size }: Rect, { pos: cp, r }: Circle) => ({ + type: intersectRectCircle(rp[0], rp[1], size[0], size[1], cp[0], cp[1], r) ? + IntersectionType.INTERSECT : + IntersectionType.NONE + }), + + [`${Type.RECT}-${Type.RECT}`]: + ({ pos: ap, size: as }: Rect, + { pos: bp, size: bs }: Rect) => ({ + type: testRectRect(ap[0], ap[1], as[0], as[1], bp[0], bp[1], bs[0], bs[1]) ? + IntersectionType.INTERSECT : + IntersectionType.NONE + }), + +}); + +intersects.isa(`${Type.RAY}-${Type.SPHERE}`, `${Type.RAY}-${Type.CIRCLE}`); +intersects.isa(`${Type.RAY}-${Type.QUAD}`, `${Type.RAY}-${Type.POLYGON}`); +intersects.isa(`${Type.RAY}-${Type.TRIANGLE}`, `${Type.RAY}-${Type.POLYGON}`); +intersects.isa(`${Type.SPHERE}-${Type.SPHERE}`, `${Type.CIRCLE}-${Type.CIRCLE}`); diff --git a/packages/geom/src/ops/map-point.ts b/packages/geom/src/ops/map-point.ts new file mode 100644 index 0000000000..7a03dc00c5 --- /dev/null +++ b/packages/geom/src/ops/map-point.ts @@ -0,0 +1,21 @@ +import { defmulti, MultiFn2O } from "@thi.ng/defmulti"; +import { + ReadonlyVec, + Vec, + sub, + div +} from "@thi.ng/vectors"; +import { IShape, Rect, Type } from "../api"; +import { dispatch } from "../internal/dispatch"; + +export const mapPoint: MultiFn2O = defmulti(dispatch); + +mapPoint.addAll({ + + [Type.RECT]: + ($: Rect, p: ReadonlyVec, out: Vec = []) => + div(null, sub(out, p, $.pos), $.size), + +}); + +mapPoint.isa(Type.AABB, Type.RECT); diff --git a/packages/geom/src/ops/point-at.ts b/packages/geom/src/ops/point-at.ts new file mode 100644 index 0000000000..3025afef8b --- /dev/null +++ b/packages/geom/src/ops/point-at.ts @@ -0,0 +1,76 @@ +import { defmulti } from "@thi.ng/defmulti"; +import { cossin, fit01, TAU } from "@thi.ng/math"; +import { + cartesian2, + madd2, + maddN, + mixCubic, + mixN2, + mixQuadratic, + Vec +} from "@thi.ng/vectors"; +import { + Arc, + Circle, + Cubic, + Ellipse, + IShape, + Line, + Polygon, + Quadratic, + Ray, + Rect, + Type +} from "../api"; +import { dispatch } from "../internal/dispatch"; +import { Sampler } from "../internal/sampler"; +import { vertices } from "./vertices"; + +export const pointAt = defmulti(dispatch); + +pointAt.addAll({ + + [Type.ARC]: + ($: Arc, t: number) => + $.pointAtTheta(fit01(t, $.start, $.end)), + + [Type.CIRCLE]: + ($: Circle, t) => + cartesian2(null, [$.r, TAU * t], $.pos), + + [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.LINE]: + ({ points }: Line, t) => + mixN2([], points[0], points[1], t), + + [Type.POLYGON]: + ($: Polygon, t) => + new Sampler($.points, true).pointAt(t), + + [Type.POLYLINE]: + ($: Polygon, t) => + new Sampler($.points).pointAt(t), + + [Type.QUADRATIC]: + ({ points }: Quadratic, t) => + mixQuadratic([], points[0], points[1], points[2], t), + + [Type.RAY]: + ($: Ray, t) => + maddN([], $.pos, $.dir, t), + + [Type.RECT]: + ($: Rect, t) => + new Sampler(vertices($), true).pointAt(t), + +}); + +pointAt.isa(Type.QUAD, Type.POLYGON); +pointAt.isa(Type.TRIANGLE, Type.POLYGON); diff --git a/packages/geom/src/ops/point-inside.ts b/packages/geom/src/ops/point-inside.ts new file mode 100644 index 0000000000..a4086ef9ef --- /dev/null +++ b/packages/geom/src/ops/point-inside.ts @@ -0,0 +1,51 @@ +import { defmulti } from "@thi.ng/defmulti"; +import { distSq, ReadonlyVec, Vec } from "@thi.ng/vectors"; +import { + AABB, + Circle, + IShape, + Points, + Polygon, + Rect, + Triangle, + Type +} from "../api"; +import { dispatch } from "../internal/dispatch"; +import { pointInArray } from "../internal/point-in-array"; +import { polyPointInside } from "../internal/poly-point-inside"; +import { pointInTriangle2 } from "../internal/triangle-point-inside"; + +export const pointInside = defmulti(dispatch); + +pointInside.addAll({ + + [Type.AABB]: + ({ pos, size }: AABB, [x, y, z]: ReadonlyVec) => + x >= pos[0] && x <= pos[0] + size[0] && + y >= pos[1] && y <= pos[1] + size[1] && + z >= pos[2] && z <= pos[2] + size[2], + + [Type.CIRCLE]: + ($: Circle, p) => + distSq($.pos, p) <= $.r * $.r, + + [Type.POINTS]: + ({ points }: Points, p) => + pointInArray(points, p), + + [Type.POLYGON]: + ($: Polygon, p) => + polyPointInside($.points, p) > 0, + + [Type.RECT]: + ({ pos, size }: Rect, [x, y]: ReadonlyVec) => + x >= pos[0] && x <= pos[0] + size[0] && + y >= pos[1] && y <= pos[1] + size[1], + + [Type.TRIANGLE]: + (tri: Triangle, p: ReadonlyVec) => + pointInTriangle2(p, ...<[Vec, Vec, Vec]>tri.points), +}); + +pointInside.isa(Type.SPHERE, Type.CIRCLE); +pointInside.isa(Type.QUAD, Type.POLYGON); diff --git a/packages/geom/src/ops/resample.ts b/packages/geom/src/ops/resample.ts new file mode 100644 index 0000000000..16d4d56e2b --- /dev/null +++ b/packages/geom/src/ops/resample.ts @@ -0,0 +1,35 @@ +import { defmulti } from "@thi.ng/defmulti"; +import { + IShape, + PCLike, + Polygon, + Polyline, + SamplingOpts, + Type +} from "../api"; +import { dispatch } from "../internal/dispatch"; +import { resamplePoints } from "../internal/sampler"; +import { asPolygon } from "./as-polygon"; + +export const resample = defmulti, IShape>(dispatch); + +resample.addAll({ + + [Type.CIRCLE]: + ($, opts) => asPolygon($, opts), + + [Type.POLYGON]: + ($: PCLike, opts) => + new Polygon(resamplePoints($.points, opts, true, true), { ...$.attribs }), + + [Type.POLYLINE]: + ($: PCLike, opts) => + new Polyline(resamplePoints($.points, opts, false, true), { ...$.attribs }), + +}); + +resample.isa(Type.ELLIPSE, Type.CIRCLE); +resample.isa(Type.LINE, Type.POLYLINE); +resample.isa(Type.QUAD, Type.POLYGON); +resample.isa(Type.TRIANGLE, Type.POLYGON); +resample.isa(Type.RECT, Type.CIRCLE); diff --git a/packages/geom/src/ops/scatter.ts b/packages/geom/src/ops/scatter.ts new file mode 100644 index 0000000000..45331f8991 --- /dev/null +++ b/packages/geom/src/ops/scatter.ts @@ -0,0 +1,22 @@ +import { IShape } from "../api"; +import { Vec, randMinMax } from "@thi.ng/vectors"; +import { SYSTEM } from "@thi.ng/random"; +import { bounds } from "./bounds"; +import { pointInside } from "./point-inside"; + +export const scatter = + (shape: IShape, num: number, rnd = SYSTEM, out: Vec[] = []) => { + const b = bounds(shape); + const mi = b.pos; + const mx = b.max(); + for (; --num >= 0;) { + while (true) { + const p = randMinMax([], mi, mx, rnd); + if (pointInside(shape, p)) { + out.push(p); + break; + } + } + } + return out; + }; diff --git a/packages/geom/src/ops/simplify.ts b/packages/geom/src/ops/simplify.ts new file mode 100644 index 0000000000..b623550177 --- /dev/null +++ b/packages/geom/src/ops/simplify.ts @@ -0,0 +1,70 @@ +import { defmulti } from "@thi.ng/defmulti"; +import { peek } from "@thi.ng/transducers"; +import { Vec } from "@thi.ng/vectors"; +import { + IShape, + Path, + PathSegment, + Polygon, + Polyline, + SegmentType, + Type +} from "../api"; +import { dispatch } from "../internal/dispatch"; +import { vertices } from "./vertices"; +import { douglasPeucker } from "../internal/douglas–peucker"; + +export const simplify = defmulti(dispatch); + +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; + for (let i = 0; i < n; i++) { + const s = orig[i]; + if (s.type === SegmentType.LINE || s.type === SegmentType.POLYLINE) { + points = points ? + points.concat(vertices(s.geo)) : + vertices(s.geo); + lastP = peek(points); + } else if (points) { + points.push(lastP); + res.push({ + geo: new Polyline(douglasPeucker(points, eps)), + type: SegmentType.POLYLINE, + }); + points = null; + } else { + res.push({ ...s }); + } + } + if (points) { + points.push(lastP); + res.push({ + geo: new Polyline(points), + type: SegmentType.POLYLINE, + }); + } + return new Path(res, { ...path.attribs }); + }, + + [Type.POLYGON]: + (poly: Polygon, eps = 0.1) => + new Polygon( + douglasPeucker(poly.points, eps, true), + { ...poly.attribs } + ), + + [Type.POLYLINE]: + (poly: Polyline, eps = 0.1) => + new Polyline( + douglasPeucker(poly.points, eps), + { ...poly.attribs } + ), + +}); diff --git a/packages/geom/src/ops/split-at.ts b/packages/geom/src/ops/split-at.ts new file mode 100644 index 0000000000..ba7f1cc601 --- /dev/null +++ b/packages/geom/src/ops/split-at.ts @@ -0,0 +1,52 @@ +import { defmulti } from "@thi.ng/defmulti"; +import { fit01 } from "@thi.ng/math"; +import { set } from "@thi.ng/vectors"; +import { + Arc, + Cubic, + IShape, + Line, + Polyline, + Quadratic, + Type +} from "../api"; +import { copyPoints } from "../internal/copy-points"; +import { dispatch } from "../internal/dispatch"; +import { Sampler } from "../internal/sampler"; +import { splitCubic, splitLine, splitQuadratic } from "../internal/split"; + +export const splitAt = defmulti(dispatch); + +splitAt.addAll({ + + [Type.ARC]: + ($: Arc, t: number) => { + const theta = fit01(t, $.start, $.end); + return [ + new Arc(set([], $.pos), set([], $.r), $.axis, $.start, theta, $.xl, $.cw, { ...$.attribs }), + new Arc(set([], $.pos), set([], $.r), $.axis, theta, $.end, $.xl, $.cw, { ...$.attribs }), + ]; + }, + + [Type.CUBIC]: + ({ attribs, points }: Cubic, t: number) => + splitCubic(points[0], points[1], points[2], points[3], t) + .map((pts) => new Cubic(pts, { ...attribs })), + + [Type.LINE]: + ({ attribs, points }: Line, t) => + splitLine(points[0], points[1], t) + .map((pts) => new Line(pts, { ...attribs })), + + [Type.POLYLINE]: + ($: Polyline, t) => + new Sampler($.points) + .splitAt(t) + .map((pts) => new Polyline(copyPoints(pts), { ...$.attribs })), + + [Type.QUADRATIC]: + ({ attribs, points }: Quadratic, t: number) => + splitQuadratic(points[0], points[1], points[2], t) + .map((pts) => new Quadratic(pts, { ...attribs })), + +}); diff --git a/packages/geom/src/ops/split-near.ts b/packages/geom/src/ops/split-near.ts new file mode 100644 index 0000000000..51c08647b8 --- /dev/null +++ b/packages/geom/src/ops/split-near.ts @@ -0,0 +1,62 @@ +import { defmulti } from "@thi.ng/defmulti"; +import { clamp01 } from "@thi.ng/math"; +import { ReadonlyVec } from "@thi.ng/vectors"; +import { + Cubic, + IShape, + Line, + Polyline, + Quadratic, + Type +} from "../api"; +import { closestCoeff } from "../internal/closest-point"; +import { copyPoints } from "../internal/copy-points"; +import { dispatch } from "../internal/dispatch"; +import { Sampler } from "../internal/sampler"; +import { splitCubicNear, splitLine, splitQuadraticNear } from "../internal/split"; + +/** + * Similar to `splitAt`, but instead of taking a normalized parametric + * split position, splits the given curve at the closest point to `p`. + * Returns tuple of split shapes of same type as `shape`. + * + * Implemented for: + * + * - Cubic + * - Line + * - Polyline + * - Quadratic + * + * @see splitAt + * + * @param shape + * @param p + */ +export const splitNearPoint = defmulti(dispatch); + +splitNearPoint.addAll({ + + [Type.CUBIC]: + ({ points, attribs }: Cubic, p) => + splitCubicNear(p, points[0], points[1], points[2], points[3]) + .map((pts) => new Cubic(pts, { ...attribs })), + + [Type.LINE]: + ($: Line, p) => { + const t = closestCoeff(p, $.points[0], $.points[1]) || 0; + return splitLine($.points[0], $.points[1], clamp01(t)) + .map((pts) => new Line(pts, { ...$.attribs })); + }, + + [Type.POLYLINE]: + ($: Polyline, p) => + new Sampler($.points) + .splitNear(p) + .map((pts) => new Polyline(copyPoints(pts), { ...$.attribs })), + + [Type.QUADRATIC]: + ({ points, attribs }: Quadratic, p) => + splitQuadraticNear(p, points[0], points[1], points[2]) + .map((pts) => new Quadratic(pts, { ...attribs })), + +}); diff --git a/packages/geom/src/ops/subdiv-curve.ts b/packages/geom/src/ops/subdiv-curve.ts new file mode 100644 index 0000000000..2ba9bf7416 --- /dev/null +++ b/packages/geom/src/ops/subdiv-curve.ts @@ -0,0 +1,87 @@ +import { defmulti, MultiFn2O } from "@thi.ng/defmulti"; +import { wrap } from "@thi.ng/transducers"; +import { mixN, ReadonlyVec } from "@thi.ng/vectors"; +import { + IShape, + Polygon, + Polyline, + SubdivKernel, + Type +} from "../api"; +import { dispatch } from "../internal/dispatch"; +import { subdivCurvePoints, subdivKernel3 } from "../internal/subdiv-curve"; + +const CHAIKIN_FIRST = subdivKernel3([1 / 2, 1 / 2, 0], [0, 3 / 4, 1 / 4]); +const CHAIKIN_MAIN = subdivKernel3([1 / 4, 3 / 4, 0], [0, 3 / 4, 1 / 4]); +const CHAIKIN_LAST = subdivKernel3([1 / 4, 3 / 4, 0], [0, 1 / 2, 1 / 2]); +const CUBIC_MAIN = subdivKernel3([1 / 8, 3 / 4, 1 / 8], [0, 1 / 2, 1 / 2]); + +const MIDP = ([a, b]: ReadonlyVec[]) => [a, mixN([], a, b, 0.5)]; +const THIRDS = ([a, b]: ReadonlyVec[]) => [a, mixN([], a, b, 1 / 3), mixN([], a, b, 2 / 3)]; + +const wrap2 = (pts: ReadonlyVec[]) => wrap(pts, 1, false, true); +const wrap3 = (pts: ReadonlyVec[]) => wrap(pts, 1, true, true); + +export const SUBDIV_MID_OPEN: SubdivKernel = { + fn: (pts, i, n) => i < n - 2 ? MIDP(pts) : [...MIDP(pts), pts[1]], + size: 2 +}; + +export const SUBDIV_MID_CLOSED: SubdivKernel = { + fn: MIDP, + iter: wrap2, + size: 2 +}; + +export const SUBDIV_THIRDS_OPEN: SubdivKernel = { + fn: (pts, i, n) => i < n - 2 ? THIRDS(pts) : [...THIRDS(pts), pts[1]], + size: 2 +}; + +export const SUBDIV_THIRDS_CLOSED: SubdivKernel = { + fn: THIRDS, + iter: wrap2, + size: 2 +}; + +export const SUBDIV_CHAIKIN_OPEN: SubdivKernel = { + fn: (pts, i, n) => + i == 0 ? + [pts[0], ...CHAIKIN_FIRST(pts)] : + i === n - 3 ? + [...CHAIKIN_LAST(pts), pts[2]] : + CHAIKIN_MAIN(pts), + size: 3 +}; + +export const SUBDIV_CHAIKIN_CLOSED: SubdivKernel = { + fn: CHAIKIN_MAIN, + iter: wrap3, + size: 3 +}; + +export const SUBDIV_CUBIC_CLOSED: SubdivKernel = { + fn: CUBIC_MAIN, + iter: wrap3, + size: 3 +}; + +export const subdivCurve: MultiFn2O = defmulti(dispatch); + +subdivCurve.addAll({ + + [Type.POLYGON]: + (poly: Polygon, kernel, iter = 1) => + new Polygon( + subdivCurvePoints(poly.points, kernel, iter), + { ...poly.attribs } + ), + + [Type.POLYLINE]: + (line: Polyline, kernel, iter = 1) => + new Polyline( + subdivCurvePoints(line.points, kernel, iter), + { ...line.attribs } + ), + +}); diff --git a/packages/geom/src/ops/tangent-at.ts b/packages/geom/src/ops/tangent-at.ts new file mode 100644 index 0000000000..53c0d7b066 --- /dev/null +++ b/packages/geom/src/ops/tangent-at.ts @@ -0,0 +1,43 @@ +import { defmulti } from "@thi.ng/defmulti"; +import { cossin, HALF_PI, TAU } from "@thi.ng/math"; +import { Vec } from "@thi.ng/vectors"; +import { + IShape, + Line, + PCLike, + Rect, + Type +} from "../api"; +import { direction } from "../internal/direction"; +import { dispatch } from "../internal/dispatch"; +import { Sampler } from "../internal/sampler"; +import { vertices } from "./vertices"; + +export const tangentAt = defmulti(dispatch); + +tangentAt.addAll({ + + [Type.CIRCLE]: + (_, t) => + cossin(TAU * t + HALF_PI), + + [Type.LINE]: + ({ points }: Line) => + direction(points[0], points[1]), + + [Type.POLYGON]: + ($: PCLike, t) => + new Sampler($.points, true).tangentAt(t), + + [Type.POLYLINE]: + ($: PCLike, t) => + new Sampler($.points).tangentAt(t), + + [Type.RECT]: + ($: Rect, t) => + new Sampler(vertices($), true).tangentAt(t), + +}); + +tangentAt.isa(Type.QUAD, Type.POLYGON); +tangentAt.isa(Type.TRIANGLE, Type.POLYGON); diff --git a/packages/geom/src/ops/tessellate.ts b/packages/geom/src/ops/tessellate.ts new file mode 100644 index 0000000000..966a207191 --- /dev/null +++ b/packages/geom/src/ops/tessellate.ts @@ -0,0 +1,10 @@ +import { DEFAULT, defmulti } from "@thi.ng/defmulti"; +import { Vec } from "@thi.ng/vectors"; +import { IShape, Tessellator } from "../api"; +import { dispatch } from "../internal/dispatch"; +import { tessellatePoints } from "../internal/tessellate"; +import { vertices } from "./vertices"; + +export const tessellate = defmulti(dispatch); + +tessellate.add(DEFAULT, ($, fns) => tessellatePoints(vertices($), fns)); diff --git a/packages/geom/src/ops/transform.ts b/packages/geom/src/ops/transform.ts new file mode 100644 index 0000000000..605a7df89a --- /dev/null +++ b/packages/geom/src/ops/transform.ts @@ -0,0 +1,64 @@ +import { defmulti } from "@thi.ng/defmulti"; +import { ReadonlyMat } from "@thi.ng/matrices"; +import { + Group, + IHiccupShape, + IShape, + Line, + PCLike, + PCLikeConstructor, + Points, + Polygon, + Polyline, + Quad, + Triangle, + Type, + Cubic, + Quadratic +} from "../api"; +import { dispatch } from "../internal/dispatch"; +import { transformedPoints, transformPoints } from "../internal/transform-points"; +import { vertices } from "./vertices"; + +const tx = (ctor: PCLikeConstructor) => + ($: PCLike, mat: ReadonlyMat) => + new ctor(transformedPoints($.points, mat), { ...$.attribs }); + +export const transform = defmulti(dispatch); + +transform.addAll({ + + [Type.CIRCLE]: + ($, mat) => + new Polygon( + transformPoints(vertices($), mat), + { ...$.attribs } + ), + + [Type.CUBIC]: tx(Cubic), + + [Type.GROUP]: + ($: Group, mat) => + new Group( + $.children.map((x) => transform(x, mat)), + { ...$.attribs } + ), + + [Type.LINE]: tx(Line), + + [Type.POINTS]: tx(Points), + + [Type.POLYGON]: tx(Polygon), + + [Type.POLYLINE]: tx(Polyline), + + [Type.QUAD]: tx(Quad), + + [Type.QUADRATIC]: tx(Quadratic), + + [Type.TRIANGLE]: tx(Triangle), + +}); + +transform.isa(Type.ELLIPSE, Type.CIRCLE); +transform.isa(Type.RECT, Type.CIRCLE); diff --git a/packages/geom/src/ops/translate.ts b/packages/geom/src/ops/translate.ts new file mode 100644 index 0000000000..a600ca716c --- /dev/null +++ b/packages/geom/src/ops/translate.ts @@ -0,0 +1,127 @@ +import { defmulti } from "@thi.ng/defmulti"; +import { + add2, + add3, + ReadonlyVec, + set2, + set3 +} from "@thi.ng/vectors"; +import { + AABB, + Arc, + Circle, + Ellipse, + Group, + IHiccupShape, + IShape, + Line, + Path, + PCLike, + PCLikeConstructor, + Points, + Polygon, + Polyline, + Quad, + Ray, + Rect, + Sphere, + Triangle, + Type +} from "../api"; +import { dispatch } from "../internal/dispatch"; +import { translatedPoints } from "../internal/translate-points"; + +const tx = (ctor: PCLikeConstructor) => + ($: PCLike, mat: ReadonlyVec) => + new ctor(translatedPoints($.points, mat), { ...$.attribs }); + +export const translate = defmulti(dispatch); + +translate.addAll({ + + [Type.AABB]: + ($: AABB, delta) => + new AABB( + add3([], $.pos, delta), set3([], $.size), + { ...$.attribs } + ), + + [Type.ARC]: + ($: Arc, delta) => { + const a = $.copy(); + add2(null, a.pos, delta); + return a; + }, + + [Type.CIRCLE]: + ($: Circle, delta) => + new Circle( + add2([], $.pos, delta), $.r, + { ...$.attribs } + ), + + [Type.ELLIPSE]: + ($: Ellipse, delta) => + new Ellipse( + add2([], $.pos, delta), set2([], $.r), + { ...$.attribs } + ), + + [Type.GROUP]: + ($: Group, delta) => + new Group( + $.children.map((s) => translate(s, delta)), + { ...$.attribs } + ), + + [Type.LINE]: tx(Line), + + [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) + } + ), + { ...$.attribs } + ), + + [Type.POINTS]: tx(Points), + + [Type.POLYGON]: tx(Polygon), + + [Type.POLYLINE]: tx(Polyline), + + [Type.QUAD]: tx(Quad), + + [Type.RAY]: + ($: Ray, delta) => + new Ray( + add2([], $.pos, delta), $.dir, + { ...$.attribs } + ), + + [Type.RECT]: + ($: Rect, delta) => + new Rect( + add2([], $.pos, delta), set2([], $.size), + { ...$.attribs } + ), + + [Type.SPHERE]: + ($: Sphere, delta) => + new Sphere( + add3([], $.pos, delta), $.r, + { ...$.attribs } + ), + + [Type.TRIANGLE]: tx(Triangle), + +}); diff --git a/packages/geom/src/ops/union.ts b/packages/geom/src/ops/union.ts new file mode 100644 index 0000000000..0f5e407ff6 --- /dev/null +++ b/packages/geom/src/ops/union.ts @@ -0,0 +1,18 @@ +import { defmulti } from "@thi.ng/defmulti"; +import { dispatch } from "../internal/dispatch"; +import { IShape, Type, Rect, AABB } from "../api"; +import { unionBounds } from "../internal/union-bounds"; + +export const union = defmulti(dispatch); + +union.addAll({ + + [Type.AABB]: + (a: AABB, b: AABB) => + [new AABB(...unionBounds(a.pos, a.size, b.pos, b.size))], + + [Type.RECT]: + (a: Rect, b: Rect) => + [new Rect(...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 new file mode 100644 index 0000000000..4f1750e7c2 --- /dev/null +++ b/packages/geom/src/ops/unmap-point.ts @@ -0,0 +1,47 @@ +import { defmulti, MultiFn2O } from "@thi.ng/defmulti"; +import { + madd, + mixBilinear, + ReadonlyVec, + Vec +} from "@thi.ng/vectors"; +import { + IShape, + Quad, + Rect, + Type +} from "../api"; +import { dispatch } from "../internal/dispatch"; + +/** + * Projects given point `uv` (normalized coords) into the target space + * defined by `shape` and writes result to `out` (or returns new + * vector). See `mapPoint` for reverse operation. Both functions + * together can be used to warp points from one shape into another. + * + * Currently only implemented for these shape types: + * + * - AABB + * - Quad + * - Rect + * + * @param shape + * @param uv + * @param out + */ +export const unmapPoint: MultiFn2O = defmulti(dispatch); + +unmapPoint.addAll({ + + [Type.QUAD]: + ({ points }: Quad, uv, out = []) => + mixBilinear(out, points[0], points[1], points[3], points[2], uv[0], uv[1]), + + [Type.RECT]: + ($: Rect, uv: ReadonlyVec, out = []) => + madd(out, $.pos, $.size, uv), + +}); + +unmapPoint.isa(Type.AABB, Type.RECT); +unmapPoint.isa(Type.QUAD3, Type.QUAD); diff --git a/packages/geom/src/ops/vertices.ts b/packages/geom/src/ops/vertices.ts new file mode 100644 index 0000000000..f56ef58e48 --- /dev/null +++ b/packages/geom/src/ops/vertices.ts @@ -0,0 +1,196 @@ +import { isNumber, isPlainObject } from "@thi.ng/checks"; +import { defmulti, MultiFn1O } from "@thi.ng/defmulti"; +import { cossin, TAU } from "@thi.ng/math"; +import { + add2, + cartesian2, + madd2, + mixCubic, + mixQuadratic, + set2, + Vec +} from "@thi.ng/vectors"; +import { + Arc, + Circle, + Cubic, + DEFAULT_SAMPLES, + Ellipse, + Group, + IShape, + Path, + Points, + Polygon, + Polyline, + Quadratic, + Rect, + SamplingOpts, + Type +} from "../api"; +import { dispatch } from "../internal/dispatch"; +import { resamplePoints, Sampler } from "../internal/sampler"; + +export const vertices: MultiFn1O, Vec[]> = defmulti(dispatch); + +vertices.addAll({ + + [Type.ARC]: + (arc: Arc, opts?: number | Partial): Vec[] => { + if (isPlainObject(opts) && (opts).dist !== undefined) { + return new Sampler(vertices(arc, (opts).num || DEFAULT_SAMPLES)) + .sampleUniform((opts).dist, (opts).last !== false); + } + opts = isNumber(opts) ? + { num: opts, last: true } : + { num: DEFAULT_SAMPLES, ...opts }; + const start = arc.start; + let delta = arc.end - start; + let num = opts.theta ? + Math.round(delta / opts.theta) : + opts.num; + delta /= num; + opts.last !== false && num++; + const pts: Vec[] = new Array(num); + for (let i = 0; i < num; i++) { + pts[i] = arc.pointAtTheta(start + i * delta); + } + return pts; + }, + + [Type.CIRCLE]: + ($: Circle, opts = DEFAULT_SAMPLES) => { + const pos = $.pos; + const r = $.r; + let [num, last] = circleOpts(opts, r); + const delta = TAU / num; + last && num++; + const buf: Vec[] = new Array(num); + for (let i = 0; i < num; i++) { + buf[i] = cartesian2(null, [r, i * delta], pos); + } + return buf; + }, + + [Type.CUBIC]: + ($: Cubic, opts?: number | Partial) => { + if (isPlainObject(opts) && (opts).dist !== undefined) { + return new Sampler(vertices($, (opts).num || DEFAULT_SAMPLES)) + .sampleUniform((opts).dist, (opts).last !== false); + } + opts = isNumber(opts) ? + { + num: opts, + last: true + } : + { + num: DEFAULT_SAMPLES, + ...opts + }; + const res: Vec[] = []; + const [a, b, c, d] = $.points; + 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([d[0], d[1]]); + return res; + }, + + [Type.ELLIPSE]: + ($: Ellipse, opts = DEFAULT_SAMPLES) => { + const buf: Vec[] = []; + const pos = $.pos; + const r = $.r; + let [num, last] = circleOpts(opts, Math.max($.r[0], $.r[1])); + const delta = TAU / num; + last && num++; + for (let i = 0; i < num; i++) { + buf[i] = madd2([], pos, cossin(i * delta), r); + } + return buf; + }, + + [Type.GROUP]: + ({ children }: Group) => + children.reduce((acc, $) => acc.concat(vertices($)), []), + + [Type.PATH]: + ($: Path, opts?: number | Partial) => { + const _opts = isNumber(opts) ? + { num: opts } : + opts; + let verts: Vec[] = []; + for (let segs = $.segments, n = segs.length - 1, i = 0; i <= n; i++) { + const s = segs[i]; + if (s.geo) { + verts = verts.concat( + vertices(s.geo, { ..._opts, last: i === n && !$.closed }) + ); + } + } + return verts; + }, + + [Type.POINTS]: + ($: Points) => $.points, + + [Type.POLYGON]: + ($: Polygon, opts?) => + resamplePoints($.points, opts, true), + + [Type.POLYLINE]: + ($: Polyline, opts?) => + resamplePoints($.points, opts), + + [Type.QUADRATIC]: + ($: Quadratic, opts?: number | Partial) => { + if (isPlainObject(opts) && (opts).dist !== undefined) { + return new Sampler(vertices($, (opts).num || DEFAULT_SAMPLES)) + .sampleUniform((opts).dist, (opts).last !== false); + } + opts = isNumber(opts) ? + { + num: opts, + last: true + } : + { + num: DEFAULT_SAMPLES, + ...opts + }; + const res: Vec[] = []; + const delta = 1 / opts.num; + const [a, b, c] = $.points; + for (let t = 0; t < opts.num; t++) { + res.push(mixQuadratic([], a, b, c, t * delta)); + } + opts.last && res.push([c[0], c[1]]); + return res; + }, + + [Type.RECT]: + ($: Rect, opts) => { + const p = $.pos; + const q = add2([], p, $.size); + const verts = [set2([], p), [q[0], p[1]], q, [p[0], q[1]]]; + return opts != null ? + vertices(new Polygon(verts), opts) : + verts; + } +}); + +vertices.isa(Type.LINE, Type.POLYLINE); +vertices.isa(Type.QUAD, Type.POLYGON); +vertices.isa(Type.TRIANGLE, Type.POLYGON); + +const circleOpts = + (opts: number | Partial, r: number): [number, boolean] => + isNumber(opts) ? + [opts, false] : + [ + opts.theta ? + Math.floor(TAU / opts.theta) : + opts.dist ? + Math.floor(TAU / (opts.dist / r)) : + opts.num || DEFAULT_SAMPLES, + opts.last === true + ]; diff --git a/packages/geom/src/ops/warp-points.ts b/packages/geom/src/ops/warp-points.ts new file mode 100644 index 0000000000..e5665fb95d --- /dev/null +++ b/packages/geom/src/ops/warp-points.ts @@ -0,0 +1,13 @@ +import { ReadonlyVec, Vec } from "@thi.ng/vectors"; +import { IShape } from "../api"; +import { mapPoint } from "./map-point"; +import { unmapPoint } from "./unmap-point"; + +export const warpPoints = + (pts: ReadonlyVec[], dest: IShape, src: IShape) => { + const res: Vec[] = []; + for (let n = pts.length, i = 0; i < n; i++) { + res.push(unmapPoint(dest, mapPoint(src, pts[i]))); + } + return res; + }; diff --git a/packages/geom/src/ops/with-attribs.ts b/packages/geom/src/ops/with-attribs.ts new file mode 100644 index 0000000000..2b8649f836 --- /dev/null +++ b/packages/geom/src/ops/with-attribs.ts @@ -0,0 +1,10 @@ +import { Attribs, IShape } from "../api"; + +export const withAttribs = ( + shape: T, + attribs: Attribs, + replace = true +) => { + shape.attribs = replace ? attribs : { ...shape.attribs, ...attribs }; + return shape; +}; diff --git a/packages/geom/src/path2.ts b/packages/geom/src/path2.ts deleted file mode 100644 index f826489522..0000000000 --- a/packages/geom/src/path2.ts +++ /dev/null @@ -1,481 +0,0 @@ -import { isNumber } from "@thi.ng/checks/is-number"; -import { implementsFunction } from "@thi.ng/checks/implements-function"; -import { rad } from "@thi.ng/math/angle"; -import { eqDelta } from "@thi.ng/math/eqdelta"; -import { ensureArray } from "@thi.ng/transducers/func/ensure-array"; -import { peek } from "@thi.ng/transducers/func/peek"; -import { Vec2 } from "@thi.ng/vectors/vec2"; -import { - Attribs, - IBounds, - IBoundsRaw, - IToPolygon, - IVertices, - PathSegment, - SamplingOpts, - SegmentType -} from "./api"; -import { Arc2 } from "./arc2"; -import { Cubic2, Quadratic2 } from "./bezier2"; -import { Line2 } from "./line2"; -import { Polygon2 } from "./polygon2"; -import { Polyline2 } from "./polyline2"; -import { Rect2 } from "./rect2"; -import { simplifyPolyline } from "./internal/douglas–peucker"; -import { mapcat } from "@thi.ng/transducers/xform/mapcat"; -import { map } from "@thi.ng/transducers/xform/map"; - -export class Path2 implements - Iterable, - IBoundsRaw, - IBounds, - IToPolygon, - IVertices { - - segments: PathSegment[]; - closed: boolean; - attribs: Attribs; - - constructor(segments?: PathSegment[], attribs?: Attribs) { - this.segments = segments || []; - this.attribs = attribs; - this.closed = false; - } - - *[Symbol.iterator]() { - yield* (this.segments); - } - - add(s: PathSegment) { - this.segments.push(s); - } - - boundsRaw(): [Vec2, Vec2] { - const min = Vec2.MAX.copy(); - const max = Vec2.MIN.copy(); - for (let s of this.segments) { - if (s.geo) { - const b = s.geo.boundsRaw(); - min.min(b[0]); - max.max(b[1]); - } - } - return [min, max]; - } - - bounds() { - return Rect2.fromMinMax(...this.boundsRaw()); - } - - simplify(eps = 0.01): Path2 { - const res: PathSegment[] = []; - const orig = this.segments; - const n = orig.length; - let points: Vec2[]; - let lastP: Vec2; - for (let i = 0; i < n; i++) { - const s = orig[i]; - if (s.type === SegmentType.LINE || s.type === SegmentType.POLYLINE) { - points = (points || []).concat(ensureArray(s.geo.vertices())); - lastP = peek(points); - } else if (points) { - points.push(lastP); - res.push({ - geo: new Polyline2(simplifyPolyline(points, eps)), - type: SegmentType.POLYLINE, - }); - points = null; - } else { - res.push({ ...s }); - } - } - if (points) { - points.push(lastP); - res.push({ - geo: new Polyline2(points), - type: SegmentType.POLYLINE, - }); - } - return new Path2(res); - } - - vertices(opts?: number | Partial) { - const _opts = isNumber(opts) ? { num: opts } : opts; - let verts: Vec2[] = []; - for (let segs = this.segments, n = segs.length - 1, i = 0; i <= n; i++) { - const s = segs[i]; - if (s.geo) { - const v = ensureArray(s.geo.vertices({ ..._opts, last: i === n && !this.closed })); - verts = verts.concat(v); - } - } - return verts; - } - - normalize() { - return new Path2([...mapcat( - (s) => - implementsFunction(s.geo, "toCubic") ? - map( - (c) => ({ type: SegmentType.CUBIC, geo: c }), - s.geo.toCubic() - ) : - [s], - this.segments - )]); - } - - toPolygon(opts?: number | Partial) { - return new Polygon2(this.vertices(opts)); - } - - toPolyline(res = 10) { - return new Polyline2(this.vertices(res)); - } - - toHiccup() { - const dest: any[] = []; - const res: any[] = ["path", this.attribs || {}, dest]; - const src = this.segments; - const n = src.length; - if (n > 1) { - dest.push(["M", src[0].point]); - for (let i = 1; i < n; i++) { - dest.push(...src[i].geo.toHiccupPathSegments()); - } - if (this.closed) { - dest.push(["Z"]); - } - } - return res; - } -} - -const CMD_RE = /[achlmqstvz]/i; - -export class PathBuilder { - - static roundedRect(pos: Vec2, size: Vec2, r: Vec2) { - const b = new PathBuilder(), - w = size.x - 2 * r.x, - h = size.y - 2 * r.y; - b.moveTo(new Vec2([pos.x + r.x, pos.y])); - b.hlineTo(w, true); - b.arcTo(r, r, 0, false, true, true); - b.vlineTo(h, true); - b.arcTo(new Vec2([-r.x, r.y]), r, 0, false, true, true); - b.hlineTo(-w, true); - b.arcTo(new Vec2([-r.x, -r.y]), r, 0, false, true, true); - b.vlineTo(-h, true); - b.arcTo(new Vec2([r.x, -r.y]), r, 0, false, true, true); - return b.curr; - } - - static fromSVG(svg: string) { - const b = new PathBuilder(); - try { - let cmd: string; - for (let n = svg.length, i = 0; i < n;) { - i = skipWS(svg, i); - const c = svg.charAt(i); - if (CMD_RE.test(c)) { - cmd = c; - i++; - } - let p, pa, pb, t1, t2, t3; - switch (cmd.toLowerCase()) { - case "m": - [p, i] = readPoint(svg, i); - b.moveTo(p, cmd === "m"); - break; - case "l": - [p, i] = readPoint(svg, i); - b.lineTo(p, cmd === "l"); - break; - case "h": - [p, i] = readFloat(svg, i); - b.hlineTo(p, cmd === "h"); - break; - case "v": - [p, i] = readFloat(svg, i); - b.vlineTo(p, cmd === "v"); - break; - case "q": - [pa, i] = readPoint(svg, i); - [p, i] = readPoint(svg, i); - // console.log("quadratic", pa.toString(), p.toString()); - b.quadraticTo(pa, p, cmd === "q"); - break; - case "c": - [pa, i] = readPoint(svg, i); - [pb, i] = readPoint(svg, i); - [p, i] = readPoint(svg, i); - // console.log("cubic", pa.toString(), pb.toString(), p.toString()); - b.cubicTo(pa, pb, p, cmd === "c"); - break; - case "s": - [pa, i] = readPoint(svg, i); - [p, i] = readPoint(svg, i); - // console.log("cubicChain", pa.toString(), p.toString()); - b.cubicChainTo(pa, p, cmd === "s"); - break; - case "t": - [p, i] = readPoint(svg, i); - // console.log("quadraticChain", p.toString()); - b.quadraticChainTo(p, cmd === "t"); - break; - case "a": { - [pa, i] = readPoint(svg, i); - [t1, i] = readFloat(svg, i); - [t2, i] = readFloat(svg, i); - [t3, i] = readFloat(svg, i); - [pb, i] = readPoint(svg, i); - // console.log("arc", pa.toString(), rad(t1), t2, t3, pb.toString()); - b.arcTo(pb, pa, rad(t1), !!t2, !!t3, cmd === "a"); - break; - } - case "z": - b.closePath(); - break; - default: - throw new Error(`unsupported segment type: ${c} @ pos ${i}`); - } - } - return b.paths; - } catch (e) { - throw e instanceof Error ? e : new Error(`illegal char '${svg.charAt(e)}' @ ${e}`); - } - } - - paths: Path2[]; - protected curr: Path2; - protected currP: Vec2; - protected bezierP: Vec2; - protected startP: Vec2; - - constructor() { - this.paths = []; - this.newPath(); - } - - *[Symbol.iterator]() { - yield* this.paths; - } - - newPath() { - this.curr = new Path2(); - this.paths.push(this.curr); - this.currP = new Vec2(); - this.bezierP = new Vec2(); - this.startP = new Vec2(); - } - - moveTo(p: Vec2, relative = false): PathBuilder { - if (this.curr.segments.length > 0) { - this.curr = new Path2(); - this.paths.push(this.curr); - } - p = this.updateCurrent(p, relative); - this.startP.set(p); - this.bezierP.set(p); - this.curr.add({ - point: p, - type: SegmentType.MOVE, - }); - return this; - } - - lineTo(p: Vec2, relative = false): PathBuilder { - this.curr.add({ - geo: new Line2([ - this.currP.copy(), - this.updateCurrent(p, relative) - ]), - type: SegmentType.LINE, - }); - this.bezierP.set(this.currP); - return this; - } - - hlineTo(x: number, relative = false): PathBuilder { - const prev = this.currP.copy(); - this.currP.x = relative ? this.currP.x + x : x; - this.bezierP.set(this.currP); - this.curr.add({ - geo: new Line2([prev, this.currP.copy()]), - type: SegmentType.LINE, - }); - return this; - } - - vlineTo(y: number, relative = false): PathBuilder { - const prev = this.currP.copy(); - this.currP.y = relative ? this.currP.y + y : y; - this.bezierP.set(this.currP); - this.curr.add({ - geo: new Line2([prev, this.currP.copy()]), - type: SegmentType.LINE, - }); - return this; - } - - cubicTo(cp1: Vec2, cp2: Vec2, p: Vec2, relative = false) { - const c2 = this.absPoint(cp2, relative); - this.bezierP.set(c2); - this.curr.add({ - geo: new Cubic2([ - this.currP.copy(), - this.absPoint(cp1, relative), - c2, - this.updateCurrent(p, relative), - ]), - type: SegmentType.CUBIC, - }); - return this; - } - - quadraticTo(cp: Vec2, p: Vec2, relative = false) { - const c1 = this.absPoint(cp, relative); - this.bezierP.set(c1); - this.curr.add({ - geo: new Quadratic2([ - this.currP.copy(), - c1, - this.updateCurrent(p, relative), - ]), - type: SegmentType.QUADRATIC, - }); - return this; - } - - cubicChainTo(cp2: Vec2, p: Vec2, relative = false) { - const prevMode = peek(this.curr.segments).type; - const c1 = this.currP.copy(); - if (prevMode === SegmentType.CUBIC) { - c1.add(c1.subNew(this.bezierP)); - } - const c2 = this.absPoint(cp2, relative); - this.bezierP.set(c2); - this.curr.add({ - geo: new Cubic2([ - this.currP.copy(), - c1, - c2, - this.updateCurrent(p, relative), - ]), - type: SegmentType.CUBIC, - }); - return this; - } - - quadraticChainTo(p: Vec2, relative = false) { - const prevMode = peek(this.curr.segments).type; - const c1 = this.currP.copy(); - if (prevMode === SegmentType.QUADRATIC) { - c1.mulN(2).sub(this.bezierP); - } - this.bezierP.set(c1); - this.curr.add({ - geo: new Quadratic2([ - this.currP.copy(), - c1, - this.updateCurrent(p, relative), - ]), - type: SegmentType.CUBIC, - }); - return this; - } - - arcTo(p: Vec2, r: Vec2, xaxis: number, xl: boolean, clockwise: boolean, relative = false) { - if (eqDelta(r.x, 0) || eqDelta(r.y, 0)) { - return this.lineTo(p, relative); - } - const prev = this.currP.copy(); - const arc = Arc2.from2Points(prev, this.updateCurrent(p, relative), r, xaxis, xl, clockwise); - this.curr.add({ - geo: arc, - type: SegmentType.ARC, - }); - this.bezierP.set(this.currP); - return this; - } - - closePath() { - this.curr.add({ - geo: new Line2([this.currP.copy(), this.startP.copy()]), - type: SegmentType.LINE, - }); - this.curr.closed = true; - return this; - } - - protected updateCurrent(p: Vec2, relative: boolean) { - p = (relative ? this.currP.add(p) : this.currP.set(p)).copy(); - return p; - } - - protected absPoint(p: Vec2, relative: boolean) { - return relative ? p.add(this.currP) : p; - } -} - -const readPoint = (src: string, index: number): [Vec2, number] => { - let x, y; - [x, index] = readFloat(src, index); - index = skipWS(src, index); - [y, index] = readFloat(src, index); - return [new Vec2([x, y]), index]; -}; - -const isWS = (c: string) => c === " " || c === "\n" || c === "\r" || c === "\t"; - -const skipWS = (src: string, i: number) => { - const n = src.length; - while (i < n && isWS(src.charAt(i))) i++; - return i; -}; - -const readFloat = (src: string, index: number) => { - index = skipWS(src, index); - let signOk = true; - let dotOk = true; - let expOk = false; - let commaOk = false; - let i = index; - for (let n = src.length; i < n; i++) { - const c = src.charAt(i); - // console.log("float", src.substring(index, i + 1)); - if ("0" <= c && c <= "9") { - expOk = true; - commaOk = true; - signOk = false; - continue; - } - if (c === "-" || c === "+") { - if (!signOk) break; - signOk = false; - continue; - } - if (c === ".") { - if (!dotOk) break; - dotOk = false; - continue; - } - if (c === "e") { - if (!expOk) throw i; - expOk = false; - dotOk = false; - signOk = true; - continue; - } - if (c === ",") { - if (!commaOk) throw i; - i++; - } - break; - } - if (i === index) { - throw new Error(`expected coordinate @ pos: ${i}`); - } - return [parseFloat(src.substring(index, i)), i]; -} diff --git a/packages/geom/src/polygon2.ts b/packages/geom/src/polygon2.ts deleted file mode 100644 index 3fbb535288..0000000000 --- a/packages/geom/src/polygon2.ts +++ /dev/null @@ -1,161 +0,0 @@ -import { ICopy, IToHiccup } from "@thi.ng/api/api"; -import { isNumber } from "@thi.ng/checks/is-number"; -import { isPlainObject } from "@thi.ng/checks/is-plain-object"; -import { TAU } from "@thi.ng/math/api"; -import { cycle } from "@thi.ng/transducers/iter/cycle"; -import { normRange } from "@thi.ng/transducers/iter/norm-range"; -import { tuples } from "@thi.ng/transducers/iter/tuples"; -import { push } from "@thi.ng/transducers/rfn/push"; -import { transduce } from "@thi.ng/transducers/transduce"; -import { map } from "@thi.ng/transducers/xform/map"; -import { ReadonlyVec, Vec } from "@thi.ng/vectors/api"; -import { asVec2, toCartesian2, Vec2 } from "@thi.ng/vectors/vec2"; -import { - Attribs, - HiccupPolygon2, - IArcLength, - IArea, - IEdges, - IPointInside, - ITessellateable, - SamplingOpts, - SubdivKernel, - Tessellator -} from "./api"; -import { PointContainer2 } from "./container2"; -import { arcLength } from "./internal/arc-length"; -import { polygonArea } from "./internal/area"; -import { argsN } from "./internal/args"; -import { centerOfWeight, centroid } from "./internal/centroid"; -import { closestPointPolyline } from "./internal/closest-point"; -import { edges } from "./internal/edges"; -import { containsDelta } from "./internal/eq-delta"; -import { clipConvex } from "./internal/sutherland-hodgeman"; -import { Sampler } from "./sampler"; -import { subdivideCurve } from "./subdiv-curve"; -import { tessellate } from "./tessellate"; -import { simplifyPolyline } from "./internal/douglas–peucker"; - -export class Polygon2 extends PointContainer2 implements - IArcLength, - IArea, - ICopy, - IEdges, - IPointInside, - ITessellateable, - IToHiccup { - - static fromHiccup([_, attribs, pts]: HiccupPolygon2) { - return new Polygon2( - isNumber(pts[0]) ? - Vec2.mapBuffer(pts) : - (pts).map(asVec2), - attribs - ); - } - - static star(r: number, n: number, profile: number[]) { - const total = n * profile.length; - const pts = transduce( - map(([i, p]) => new Vec2(toCartesian2([r * p, i * TAU]))), - push(), - tuples(normRange(total, false), cycle(profile)) - ); - return new Polygon2(pts); - } - - copy() { - return new Polygon2(this._copy(), { ...this.attribs }); - } - - edges() { - return edges(this.points, true); - } - - area(signed = true) { - const area = polygonArea(this.points); - return signed ? area : Math.abs(area); - } - - arcLength() { - return arcLength(this.points, true); - } - - centroid(c?: Vec2): Vec2 { - return centerOfWeight(this.points, c); - } - - closestPoint(p: Readonly) { - return closestPointPolyline(p, this.points, true); - } - - pointInside(p: Readonly) { - const pts = this.points; - if (containsDelta(pts, p)) return true; - const px = p.x; - const py = p.y; - let inside = false; - for (let n = pts.length - 1, i = n, j = 0; j < n; i = j, j++) { - const [ax, ay] = pts[i]; - const [bx, by] = pts[j]; - (((by < py && ay >= py) || (ay < py && by >= py)) && - ((py - by) / (ay - by) * (ax - bx) + bx) < px) && - (inside = !inside); - } - return inside; - } - - simplify(eps: number) { - return new Polygon2(simplifyPolyline(this.points, eps, true), { ...this.attribs }); - } - - vertices(opts?: number | Partial) { - const sampler = new Sampler(this.points, true); - if (opts !== undefined) { - return isPlainObject(opts) ? - opts.dist ? - sampler.sampleUniform(opts.dist, opts.last) : - sampler.sampleFixedNum(opts.num, opts.last) : - sampler.sampleFixedNum(opts, false); - } else { - return this.points; - } - } - - clipConvex(boundary: Polygon2 | Vec2[]) { - let bpts, bc; - if (boundary instanceof Polygon2) { - bpts = boundary.points; - bc = boundary.centroid(); - } else { - bpts = boundary; - bc = centroid(bpts, new Vec2()); - } - return new Polygon2(clipConvex(this.points, bpts, bc), { ...this.attribs }); - } - - subdivide(kernel: SubdivKernel, iter = 1) { - return new Polygon2(subdivideCurve(kernel, this.points, iter, true), { ...this.attribs }); - } - - tessellate(tessel: Tessellator, iter?: number): Vec2[][]; - tessellate(tessel: Iterable>): Vec2[][]; - tessellate(...args: any[]) { - return tessellate.apply(null, [this.points, ...args]); - } - - toHiccup() { - return this._toHiccup("polygon"); - } - - toJSON() { - return this._toJSON("polygon2"); - } -} - -export function polygon2(points: Vec, num?: number, start?: number, cstride?: number, estride?: number, attribs?: Attribs): Polygon2; -export function polygon2(points: ReadonlyVec[], attribs?: Attribs): Polygon2; -export function polygon2(...args: any[]) { - const [points, attribs] = argsN(args); - return new Polygon2(points, attribs); -} diff --git a/packages/geom/src/polyline2.ts b/packages/geom/src/polyline2.ts deleted file mode 100644 index 37c159e4a1..0000000000 --- a/packages/geom/src/polyline2.ts +++ /dev/null @@ -1,102 +0,0 @@ -import { ICopy, IToHiccup } from "@thi.ng/api/api"; -import { isPlainObject } from "@thi.ng/checks/is-plain-object"; -import { map } from "@thi.ng/transducers/xform/map"; -import { partition } from "@thi.ng/transducers/xform/partition"; -import { ReadonlyVec, Vec } from "@thi.ng/vectors/api"; -import { Vec2 } from "@thi.ng/vectors/vec2"; -import { - Attribs, - IArcLength, - IArea, - IEdges, - IToCubic, - IVertices, - SamplingOpts, - SubdivKernel -} from "./api"; -import { Cubic2 } from "./bezier2"; -import { PointContainer2 } from "./container2"; -import { arcLength } from "./internal/arc-length"; -import { argsN } from "./internal/args"; -import { closestPointPolyline } from "./internal/closest-point"; -import { edges } from "./internal/edges"; -import { Sampler } from "./sampler"; -import { subdivideCurve } from "./subdiv-curve"; - -export class Polyline2 extends PointContainer2 implements - IArcLength, - IArea, - ICopy, - IEdges, - IVertices>, - IToCubic, - IToHiccup { - - copy() { - return new Polyline2(this._copy(), { ...this.attribs }); - } - - edges() { - return edges(this.points); - } - - area() { - return 0; - } - - arcLength() { - return arcLength(this.points); - } - - closestPoint(p: Readonly) { - return closestPointPolyline(p, this.points, false); - } - - subdivide(kernel: SubdivKernel, iter = 1) { - return new Polyline2(subdivideCurve(kernel, this.points, iter, false), { ...this.attribs }); - } - - vertices(opts?: number | Partial) { - const sampler = new Sampler(this.points); - if (opts !== undefined) { - if (isPlainObject(opts)) { - return opts.dist ? - sampler.sampleUniform(opts.dist, opts.last !== false) : - sampler.sampleFixedNum(opts.num, opts.last !== false); - } - return sampler.sampleFixedNum(opts, true); - } else { - return this.points; - } - } - - toCubic() { - return map( - ([a, b]) => Cubic2.fromLine(a, b, { ...this.attribs }), - partition(2, 1, this.points) - ); - } - - toHiccup() { - return this._toHiccup("polyline"); - } - - toHiccupPathSegments() { - const res: any[] = []; - for (let pts = this.points, n = pts.length, i = 1; i < n; i++) { - res.push(["L", pts[i]]); - } - return res; - } - - toJSON() { - return this._toJSON("polyline2"); - } -} - -export function polyline2(points: Vec, num?: number, start?: number, cstride?: number, estride?: number, attribs?: Attribs): Polyline2; -export function polyline2(points: ReadonlyVec[], attribs?: Attribs): Polyline2; -export function polyline2(...args: any[]) { - const [points, attribs] = argsN(args); - return new Polyline2(points, attribs); -} diff --git a/packages/geom/src/quad2.ts b/packages/geom/src/quad2.ts deleted file mode 100644 index 4a2c07dbbc..0000000000 --- a/packages/geom/src/quad2.ts +++ /dev/null @@ -1,77 +0,0 @@ -import { ICopy } from "@thi.ng/api"; -import { ReadonlyVec, Vec } from "@thi.ng/vectors/api"; -import { Vec2 } from "@thi.ng/vectors/vec2"; -import { - Attribs, - IArcLength, - IArea, - IEdges, - IPointMap, - ITessellateable, - Tessellator -} from "./api"; -import { PointContainer2 } from "./container2"; -import { arcLength } from "./internal/arc-length"; -import { args4 } from "./internal/args"; -import { corner } from "./internal/corner"; -import { edges } from "./internal/edges"; -import { tessellate } from "./tessellate"; - -export class Quad2 extends PointContainer2 implements - IArea, - IArcLength, - ICopy, - IEdges, - IPointMap, - ITessellateable { - - copy() { - return new Quad2(this._copy(), { ...this.attribs }); - } - - arcLength() { - return arcLength(this.points, true); - } - - area(signed = true) { - const [a, b, c, d] = this.points; - const area = 0.5 * (corner(a, b, c) + corner(a, c, d)); - return signed ? area : Math.abs(area); - } - - edges() { - return edges(this.points, true); - } - - mapPoint(_: Readonly, __?: Vec2): Vec2 { - throw new Error("TODO"); - } - - unmapPoint(q: Readonly, out?: Vec2) { - const p = this.points; - const res = Vec2.mixBilinear(p[0], p[1], p[3], p[2], q.x, q.y); - return out ? out.set(res) : res; - } - - tessellate(tessel: Tessellator, iter?: number): Vec2[][]; - tessellate(tessel: Iterable>): Vec2[][]; - tessellate(...args: any[]) { - return tessellate.apply(null, [this.points, ...args]); - } - - toHiccup() { - return this._toHiccup("polygon"); - } - - toJSON() { - return this._toJSON("quad2"); - } -} - -export function quad2(points: Vec, start?: number, cstride?: number, estride?: number, attribs?: Attribs): Quad2; -export function quad2(a: ReadonlyVec, b: ReadonlyVec, c: ReadonlyVec, d: ReadonlyVec, attribs?: Attribs): Quad2; -export function quad2(points: ReadonlyVec[], attribs?: Attribs): Quad2; -export function quad2(...args: any[]) { - const [points, attribs] = args4(args); - return new Quad2(points, attribs); -} diff --git a/packages/geom/src/rect2.ts b/packages/geom/src/rect2.ts deleted file mode 100644 index b6d3527645..0000000000 --- a/packages/geom/src/rect2.ts +++ /dev/null @@ -1,201 +0,0 @@ -import { ICopy } from "@thi.ng/api"; -import { isArrayLike } from "@thi.ng/checks/is-arraylike"; -import { isNumber } from "@thi.ng/checks/is-number"; -import { isPlainObject } from "@thi.ng/checks/is-plain-object"; -import { ReadonlyVec } from "@thi.ng/vectors/api"; -import { asVec2, Vec2 } from "@thi.ng/vectors/vec2"; -import { - Attribs, - CollateOpts, - IArcLength, - IArea, - IBounds, - IBoundsRaw, - ICenter, - ICentroid, - ICollate, - IPointInside, - IPointMap, - ITessellateable, - IVertices, - Tessellator -} from "./api"; -import { collateWith } from "./internal/collate"; -import { edges } from "./internal/edges"; -import { tessellate } from "./tessellate"; - -export class Rect2 implements - IArea, - IArcLength, - IBoundsRaw, - IBounds, - ICentroid, - ICenter, - ICollate, - ICopy, - IPointInside, - IPointMap, - ITessellateable, - IVertices { - - static fromMinMax(min: Vec2, max: Vec2) { - return new Rect2(min, max.subNew(min)); - } - - pos: Vec2; - size: Vec2; - attribs: Attribs; - - constructor(pos: Vec2, size: Vec2, attribs?: any) { - this.pos = pos; - this.size = size; - this.attribs = attribs; - } - - copy() { - const buf = Vec2.intoBuffer([], [this.pos, this.size]); - return new Rect2(new Vec2(buf, 0), new Vec2(buf, 2), { ...this.attribs }) - } - - collate(opts?: Partial) { - return collateWith(Vec2.intoBuffer, [this.pos, this.size], opts, 2); - } - - area() { - return this.size.x * this.size.y; - } - - arcLength() { - return 2 * (this.size.x + this.size.y); - } - - boundsRaw(): [Vec2, Vec2] { - return [this.pos.copy(), this.pos.addNew(this.size)]; - } - - bounds() { - return this; - } - - centroid(c?: Vec2) { - return this.pos.maddNewN(this.size, 0.5, c); - } - - center(origin?: Readonly) { - const d = this.centroid().neg(); - this.pos.add(origin ? d.add(origin) : d); - return this; - } - - pointInside(p: Readonly) { - const px = p.x; - const py = p.y; - const x1 = this.pos.x; - const y1 = this.pos.y; - const x2 = x1 + this.size.x; - const y2 = y1 + this.size.y; - return px >= x1 && px <= x2 && py >= y1 && py <= y2; - } - - mapPoint(p: Readonly, out?: Vec2) { - return p.subNew(this.pos, out).div(this.size); - } - - unmapPoint(p: Readonly, out?: Vec2) { - return (out ? out.set(this.pos) : this.pos.copy()).madd(this.size, p); - } - - tessellate(tessel: Tessellator, iter?: number): Vec2[][]; - tessellate(tessel: Iterable>): Vec2[][]; - tessellate(...args: any[]) { - return tessellate.apply(null, [this.vertices(), ...args]); - } - - scale(v: Readonly) { - this.pos.mul(v); - this.size.mul(v); - return this; - } - - scaleN(n: number) { - this.pos.mulN(n); - this.size.mulN(n); - return this; - } - - translate(v: Readonly) { - this.pos.add(v); - return this; - } - - union(r: Rect2) { - const p = this.pos.addNew(this.size); - const q = r.pos.addNew(r.size); - this.pos.min(r.pos); - this.size.set(p.max(q).sub(this.pos)); - return this; - } - - edges() { - return edges(this.vertices(), true); - } - - vertices() { - const [x, y] = this.pos; - const [w, h] = this.size; - return Vec2.mapBuffer([x, y, x + w, y, x + w, y + h, x, y + h], 4); - } - - toHiccup() { - return ["rect", this.attribs, this.pos, this.size.x, this.size.y]; - } - - toJSON() { - return { - type: "rect2", - pos: this.pos.toJSON(), - size: this.size.toJSON(), - }; - } -} - -export function rect2(x: number, y: number, w: number, h: number, attribs?: Attribs): Rect2; -export function rect2(x: number, y: number, w: number, attribs?: Attribs): Rect2; -export function rect2(w: number, h: number, attribs?: Attribs): Rect2; -export function rect2(pos: ReadonlyVec, w: number, attribs?: Attribs): Rect2; -export function rect2(pos: ReadonlyVec, size: ReadonlyVec, attribs?: Attribs): Rect2; -export function rect2(w: number, attribs?: Attribs): Rect2; -export function rect2(...args: any[]) { - let attribs; - let n = args.length - 1; - if (isPlainObject(args[n]) || args[n] == null) { - attribs = args[n]; - n--; - } - if (isArrayLike(args[0])) { - const size = args[1]; - return new Rect2( - asVec2(args[0]), - isNumber(size) ? - new Vec2([size, size]) : - asVec2(size), - attribs - ); - } - if (n > 1) { - return new Rect2( - new Vec2([args[0], args[1]]), - new Vec2( - n === 2 ? - [args[2], args[2]] : - [args[2], args[3]] - ), - attribs - ); - } - return new Rect2( - new Vec2([0, 0]), - new Vec2(n > 0 ? [args[0], args[1]] : [args[0], args[0]]), - attribs - ); -}; diff --git a/packages/geom/src/sampler.ts b/packages/geom/src/sampler.ts deleted file mode 100644 index 2f6a6a3c18..0000000000 --- a/packages/geom/src/sampler.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { peek } from "@thi.ng/transducers/func/peek"; -import { IVector } from "@thi.ng/vectors/api"; - -export class Sampler> { - - points: T[]; - index: number[]; - - constructor(points: ReadonlyArray, closed = false) { - if (closed) { - this.points = points.slice(); - this.points.push(points[0]); - } else { - this.points = points; - } - this.buildIndex(); - } - - pointAt(t: number) { - const pts = this.points; - const n = pts.length - 1; - if (n < 0) { - return; - } - if (n === 0 || t <= 0) { - return pts[0]; - } - if (t >= 1) { - return pts[n]; - } - const idx = this.index; - const t0 = t * idx[n]; - for (let i = 1; i <= n; i++) { - if (idx[i] >= t0) { - return pts[i - 1].mixNewN(pts[i], (t0 - idx[i - 1]) / (idx[i] - idx[i - 1])); - } - } - } - - sampleUniform(dist: number, includeLast = false, result: T[] = []) { - const index = this.index; - const total = peek(index); - const delta = dist / total; - const n = index.length; - for (let t = 0, i = 1; t < 1; t += delta) { - const ct = t * total; - while (ct >= index[i] && i < n) { i++; } - if (i >= n) break; - const p = index[i - 1]; - result.push(this.points[i - 1].mixNewN(this.points[i], (ct - p) / (index[i] - p))); - } - if (includeLast) { - result.push(this.points[this.points.length - 1].copy()); - } - return result; - } - - sampleFixedNum(num: number, includeLast = false, result?: T[]) { - return this.sampleUniform(peek(this.index) / num, includeLast, result); - } - - protected buildIndex() { - const idx: number[] = [0]; - const pts = this.points; - const n = pts.length; - for (let i = 0, j = 1; j < n; i = j, j++) { - idx[j] = idx[i] + pts[i].dist(pts[j]); - } - this.index = idx; - } -} diff --git a/packages/geom/src/subdiv-curve.ts b/packages/geom/src/subdiv-curve.ts deleted file mode 100644 index 31b3e93ebd..0000000000 --- a/packages/geom/src/subdiv-curve.ts +++ /dev/null @@ -1,104 +0,0 @@ -import { comp } from "@thi.ng/transducers/func/comp"; -import { wrap } from "@thi.ng/transducers/iter/wrap"; -import { push } from "@thi.ng/transducers/rfn/push"; -import { transduce } from "@thi.ng/transducers/transduce"; -import { indexed } from "@thi.ng/transducers/xform/indexed"; -import { mapcat } from "@thi.ng/transducers/xform/mapcat"; -import { partition } from "@thi.ng/transducers/xform/partition"; -import { IVector } from "@thi.ng/vectors/api"; -import { SubdivKernel } from "./api"; - -const madd2 = - > - (a: Readonly, b: Readonly, ua: number, ub: number) => - a.mulNewN(ua).maddN(b, ub); - -const madd3 = - > - (a: Readonly, b: Readonly, c: Readonly, ua: number, ub: number, uc: number) => - a.mulNewN(ua).maddN(b, ub).maddN(c, uc); - -const madd5 = - > - (a: Readonly, b: Readonly, c: Readonly, d: Readonly, e: Readonly, - ua: number, ub: number, uc: number, ud: number, ue: number) => - a.mulNewN(ua).maddN(b, ub).maddN(c, uc).maddN(d, ud).maddN(e, ue); - -export const subdivKernel2 = - ([ua, ub]: number[], [va, vb]: number[]) => - >([a, b]: T[]) => [ - madd2(a, b, ua, ub), - madd2(a, b, va, vb), - ]; - -export const subdivKernel3 = - ([ua, ub, uc]: number[], [va, vb, vc]: number[]) => - >([a, b, c]: T[]) => [ - madd3(a, b, c, ua, ub, uc), - madd3(a, b, c, va, vb, vc), - ]; - -export const subdivKernel5 = - ([ua, ub, uc, ud, ue]: number[], [va, vb, vc, vd, ve]: number[]) => - >([a, b, c, d, e]: T[]) => [ - madd5(a, b, c, d, e, ua, ub, uc, ud, ue), - madd5(a, b, c, d, e, va, vb, vc, vd, ve), - ]; - -/** - * http://algorithmicbotany.org/papers/subgpu.sig2003.pdf - * - * @param kernel subdivision scheme - * @param pts source points - * @param iter number of iterations - * @param closed true, if closed input geometry - */ -export const subdivideCurve = - >( - { fn, size }: SubdivKernel, - pts: T[], - iter = 1, - closed = false) => { - - while (--iter >= 0) { - const nump = pts.length; - pts = transduce( - comp( - partition(size, 1), - indexed(), - mapcat(([i, pts]) => fn(pts, i, nump)) - ), - push(), - closed ? - wrap(pts, size >> 1, true, true) : - pts - ); - } - return pts; - }; - -const CHAIKIN_FIRST = subdivKernel3([1 / 2, 1 / 2, 0], [0, 3 / 4, 1 / 4]); -const CHAIKIN_MAIN = subdivKernel3([1 / 4, 3 / 4, 0], [0, 3 / 4, 1 / 4]); -const CHAIKIN_LAST = subdivKernel3([1 / 4, 3 / 4, 0], [0, 1 / 2, 1 / 2]); - -const CUBIC_MAIN = subdivKernel3([1 / 8, 3 / 4, 1 / 8], [0, 1 / 2, 1 / 2]); - -export const CHAIKIN_CLOSED: SubdivKernel = { - fn: CHAIKIN_MAIN, - size: 3 -}; - -export const CHAIKIN_OPEN: SubdivKernel = { - fn: (pts, i, n) => - i == 0 ? - [pts[0], ...CHAIKIN_FIRST(pts)] : - i === n - 3 ? - [...CHAIKIN_LAST(pts), pts[2]] : - CHAIKIN_MAIN(pts), - size: 3 -}; - -export const CUBIC_CLOSED: SubdivKernel = { - fn: CUBIC_MAIN, - size: 3 -}; diff --git a/packages/geom/src/tessellate.ts b/packages/geom/src/tessellate.ts deleted file mode 100644 index dc100dc8e8..0000000000 --- a/packages/geom/src/tessellate.ts +++ /dev/null @@ -1,164 +0,0 @@ -import { isFunction } from "@thi.ng/checks/is-function"; -import { comp } from "@thi.ng/transducers/func/comp"; -import { range } from "@thi.ng/transducers/iter/range"; -import { repeat } from "@thi.ng/transducers/iter/repeat"; -import { tuples } from "@thi.ng/transducers/iter/tuples"; -import { wrap } from "@thi.ng/transducers/iter/wrap"; -import { reducer } from "@thi.ng/transducers/reduce"; -import { last } from "@thi.ng/transducers/rfn/last"; -import { push } from "@thi.ng/transducers/rfn/push"; -import { transduce } from "@thi.ng/transducers/transduce"; -import { map } from "@thi.ng/transducers/xform/map"; -import { mapcat } from "@thi.ng/transducers/xform/mapcat"; -import { partition } from "@thi.ng/transducers/xform/partition"; -import { scan } from "@thi.ng/transducers/xform/scan"; -import { IVector } from "@thi.ng/vectors/api"; -import { Vec2 } from "@thi.ng/vectors/vec2"; -import { Tessellator } from "./api"; -import { polygonArea } from "./internal/area"; -import { centroid } from "./internal/centroid"; -import { corner, pointInTriangle2 } from "./internal/corner"; - -const snip = (points: ReadonlyArray, u: number, v: number, w: number, n: number, ids: number[]) => { - const a = points[ids[u]]; - const b = points[ids[v]]; - const c = points[ids[w]]; - if (corner(a, b, c) > 0) { - for (let i = 0; i < n; i++) { - if (i !== u && i !== v && i !== w) { - if (pointInTriangle2(points[ids[i]], a, b, c)) { - return; - } - } - } - return [a, b, c]; - } -}; - -export const earCut = (points: ReadonlyArray) => { - const tris: Vec2[][] = []; - let n = points.length; - const ids = [ - ...(polygonArea(points) > 0 ? - range(n) : - range(n - 1, -1, -1)) - ]; - let count = 2 * n - 1; - let v = n - 1, u, w, t; - while (count > 0 && n > 2) { - u = n <= v ? 0 : v; - v = u + 1; - v = n <= v ? 0 : v; - w = v + 1; - w = n <= w ? 0 : w; - t = snip(points, u, v, w, n, ids); - if (t !== undefined) { - tris.push(t); - ids.splice(v, 1); - n--; - count = 2 * n; - } else { - count--; - } - } - return tris; -}; - -export const triFan = >(points: ReadonlyArray) => { - const c = centroid(points); - return transduce( - comp( - partition(2, 1), - map(([a, b]) => [a, b, c]) - ), - push(), - wrap(points, 1, false, true) - ); -}; - -export const quadFan = >(points: ReadonlyArray) => { - const p = centroid(points); - return transduce( - comp( - partition(3, 1), - map(([a, b, c]) => [a.mixNewN(b, 0.5), b, b.mixNewN(c, 0.5), p]) - ), - push(), - wrap(points, 1, true, true) - ); -}; - -export const edgeSplit = >(points: ReadonlyArray) => { - const c = centroid(points); - return transduce( - comp( - partition(2, 1), - mapcat(([a, b]) => { - const m = a.mixNewN(b, 0.5); - return [[a, m, c], [m, b, c]]; - })), - push(), - wrap(points, 1, false, true) - ); -}; - -export const rimTris = >(points: ReadonlyArray) => { - const edgeCentroids = transduce( - comp( - partition(2, 1), - map((e) => e[0].mixNewN(e[1], 0.5)) - ), - push(), - wrap(points, 1, false, true) - ); - return transduce( - comp( - partition(2, 1), - map((t) => [t[0][0], t[1][1], t[1][0]]) - ), - push(), - [edgeCentroids], - wrap([...tuples(edgeCentroids, points)], 1, true, false) - ); -}; - -export const inset = (inset = 0.5, keepInterior = false) => - >(points: ReadonlyArray) => { - const c = centroid(points); - const inner = points.map((p) => p.mixNewN(c, inset)); - return transduce( - comp( - partition(2, 1), - map(([[a, b], [c, d]]) => [a, b, d, c]) - ), - push(), - keepInterior ? [inner] : [], - wrap([...tuples(points, inner)], 1, false, true) - ); - }; - -export function tessellate>(points: T[], tessFn: Tessellator, iter?: number): T[][]; -export function tessellate>(points: T[], tessFns: Iterable>): T[][]; -export function tessellate>(...args): T[][] { - return transduce( - scan( - reducer( - () => [args[0]], - (acc: T[][], fn: Tessellator) => - transduce( - mapcat(fn), - push(), - acc - ) - ) - ), - last(), - isFunction(args[1]) ? - repeat(args[1], args[2] || 1) : - args[1] - ); -} - -/* -v=require("@thi.ng/vectors"); g=require("@thi.ng/geom"); h=require("@thi.ng/hiccup"); svg=require("@thi.ng/hiccup-svg"); s=require("@thi.ng/strings"); tx=require("@thi.ng/transducers"); fs=require("fs"); -*/ \ No newline at end of file diff --git a/packages/geom/src/triangle2.ts b/packages/geom/src/triangle2.ts deleted file mode 100644 index faa20596c1..0000000000 --- a/packages/geom/src/triangle2.ts +++ /dev/null @@ -1,93 +0,0 @@ -import { ICopy } from "@thi.ng/api"; -import { PI } from "@thi.ng/math/api"; -import { ReadonlyVec, Vec } from "@thi.ng/vectors/api"; -import { Vec2 } from "@thi.ng/vectors/vec2"; -import { Vec3 } from "@thi.ng/vectors/vec3"; -import { - Attribs, - IArcLength, - IArea, - IClassifyPoint, - IPointInside, - IPointMap, - ITessellateable, - Tessellator -} from "./api"; -import { PointContainer2 } from "./container2"; -import { arcLength } from "./internal/arc-length"; -import { args3 } from "./internal/args"; -import { fromBarycentric, toBarycentric } from "./internal/barycentric"; -import { classifyPointInTriangle2, corner, pointInTriangle2 } from "./internal/corner"; -import { tessellate } from "./tessellate"; - -export class Triangle2 extends PointContainer2 implements - IArea, - IArcLength, - IClassifyPoint, - ICopy, - IPointInside, - IPointMap, - ITessellateable { - - static equilateral(a: Vec2, b: Vec2) { - const dir = b.subNew(a); - const c = dir.perpendicularLeft().normalize(dir.mag() * Math.sin(PI / 3)); - return new Triangle2([a, b, c.maddN(dir, 0.5)]); - } - - copy() { - return new Triangle2(this._copy(), { ...this.attribs }); - } - - classifyPoint(p: Readonly): number { - const [a, b, c] = this.points; - return classifyPointInTriangle2(p, a, b, c); - } - - pointInside(p: Readonly): boolean { - const [a, b, c] = this.points; - return pointInTriangle2(p, a, b, c); - } - - arcLength(): number { - return arcLength(this.points, true); - } - - area(signed = true) { - const [a, b, c] = this.points; - const area = 0.5 * corner(a, b, c); - return signed ? area : Math.abs(area); - } - - mapPoint(p: Readonly, out?: Vec3): Vec3 { - const [a, b, c] = this.points; - return toBarycentric(a, b, c, p, out); - } - - unmapPoint(p: Readonly, out?: Vec2): Vec2 { - const [a, b, c] = this.points; - return fromBarycentric(a, b, c, p, out); - } - - tessellate(tessel: Tessellator, iter?: number): Vec2[][]; - tessellate(tessel: Iterable>): Vec2[][]; - tessellate(...args: any[]) { - return tessellate.apply(null, [this.points, ...args]); - } - - toHiccup() { - return this._toHiccup("polygon"); - } - - toJSON() { - return this._toJSON("triangle2"); - } -} - -export function triangle2(points: Vec, start?: number, cstride?: number, estride?: number, attribs?: Attribs): Triangle2; -export function triangle2(a: ReadonlyVec, b: ReadonlyVec, c: ReadonlyVec, attribs?: Attribs): Triangle2; -export function triangle2(points: ReadonlyVec[], attribs?: Attribs): Triangle2; -export function triangle2(...args: any[]) { - const [points, attribs] = args3(args); - return new Triangle2(points, attribs); -} \ No newline at end of file diff --git a/packages/geom/src/warp.ts b/packages/geom/src/warp.ts deleted file mode 100644 index 839d58c47d..0000000000 --- a/packages/geom/src/warp.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { IPointMap } from "./api"; -import { IVector } from "@thi.ng/vectors/api"; - -export const warpPoints = - , V2 extends IVector, A extends IPointMap, B extends IPointMap> - (dest: B, src: ReadonlyArray, srcBounds: A) => { - const res: V[] = []; - for (let n = src.length, i = 0; i < n; i++) { - res.push(dest.unmapPoint(srcBounds.mapPoint(src[i]))); - } - return res; - }; diff --git a/packages/geom/test/circle2.ts b/packages/geom/test/circle2.ts deleted file mode 100644 index 4ab293f658..0000000000 --- a/packages/geom/test/circle2.ts +++ /dev/null @@ -1,125 +0,0 @@ -import { equiv } from "@thi.ng/equiv"; -import { PI, TAU, HALF_PI } from "@thi.ng/math/api"; -import { eqDelta2array, vec2 } from "@thi.ng/vectors/vec2"; -import * as assert from "assert"; -import { circle2, Circle2, HiccupCircle2 } from "../src"; - -describe("circle2", () => { - - it("ctor1", () => { - const c = circle2(10, 20); - assert(c instanceof Circle2); - assert(equiv(c.pos, [10, 20])); - assert.equal(c.r, 1); - assert.strictEqual(c.attribs, undefined); - }); - - it("ctor2", () => { - const c = circle2(10, 20, 5); - assert(equiv(c.pos, [10, 20])); - assert.equal(c.r, 5); - assert.strictEqual(c.attribs, undefined); - }); - - it("ctor3", () => { - const c = circle2(10, 20, 5, { a: 1 }); - assert(equiv(c.pos, [10, 20])); - assert.equal(c.r, 5); - assert.deepEqual(c.attribs, { a: 1 }); - }); - - it("ctor4", () => { - const c = circle2(vec2(10, 20)); - assert(equiv(c.pos, [10, 20])); - assert.equal(c.r, 1); - assert.strictEqual(c.attribs, undefined); - }); - - it("ctor5", () => { - const c = circle2(vec2(10, 20), 5); - assert(equiv(c.pos, [10, 20])); - assert.equal(c.r, 5); - assert.strictEqual(c.attribs, undefined); - }); - - it("ctor6", () => { - const c = circle2(vec2(10, 20), { a: 1 }); - assert(equiv(c.pos, [10, 20])); - assert.equal(c.r, 1); - assert.deepEqual(c.attribs, { a: 1 }); - }); - - - it("ctor7", () => { - const c = circle2(vec2(10, 20), 5, { a: 1 }); - assert(equiv(c.pos, [10, 20])); - assert.equal(c.r, 5); - assert.deepEqual(c.attribs, { a: 1 }); - }); - - it("ctor8", () => { - const c = circle2(5); - assert(equiv(c.pos, [0, 0])); - assert.equal(c.r, 5); - assert.strictEqual(c.attribs, undefined); - }); - - it("ctor9", () => { - const c = circle2(5, { a: 1 }); - assert(equiv(c.pos, [0, 0])); - assert.equal(c.r, 5); - assert.deepEqual(c.attribs, { a: 1 }); - }); - - it("hiccup", () => { - const src: HiccupCircle2 = ["circle", { a: 1 }, [10, 20], 5]; - const c = Circle2.fromHiccup(src); - assert(equiv(c.pos, [10, 20])); - assert.equal(c.r, 5); - assert.deepEqual(c.attribs, { a: 1 }); - assert(equiv(c.toHiccup(), src)); - }); - - it("area", () => { - assert.equal(circle2(10).area(), PI * 100); - }); - - it("arclength", () => { - assert.equal(circle2(10).arcLength(), TAU * 10); - }); - - it("vertices (num)", () => { - assert(eqDelta2array( - circle2(10).vertices(4), - [[10, 0], [0, 10], [-10, 0], [0, -10]] - )) - }); - - it("vertices ({ num })", () => { - assert(eqDelta2array( - circle2(10).vertices({ num: 4 }), - [[10, 0], [0, 10], [-10, 0], [0, -10]] - )) - }); - - it("vertices ({ num, last: true })", () => { - assert(eqDelta2array( - circle2(10).vertices({ num: 4, last: true }), - [[10, 0], [0, 10], [-10, 0], [0, -10], [10, 0]] - )) - }); - - it("vertices ({ theta })", () => { - assert(eqDelta2array( - circle2(10).vertices({ theta: HALF_PI }), - [[10, 0], [0, 10], [-10, 0], [0, -10]] - )) - }); - - it("vertices ({ dist })", () => { - assert(eqDelta2array( - circle2(10).vertices({ dist: TAU * 10 / 4 }), - [[10, 0], [0, 10], [-10, 0], [0, -10]] - )) - }); -}); diff --git a/packages/geom/test/index.ts b/packages/geom/test/index.ts new file mode 100644 index 0000000000..f5862820cb --- /dev/null +++ b/packages/geom/test/index.ts @@ -0,0 +1,6 @@ +// import * as assert from "assert"; +// import * as g from "../src/index"; + +describe("geom", () => { + it("tests pending"); +}); diff --git a/packages/geom/test/poly2.ts b/packages/geom/test/poly2.ts deleted file mode 100644 index 292b81f86e..0000000000 --- a/packages/geom/test/poly2.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { equiv } from "@thi.ng/equiv"; -import * as assert from "assert"; -import { polygon2, Polygon2, HiccupPolygon2 } from "../src/index"; - -describe("polygon2", () => { - - it("area", () => { - const a = polygon2([0, 0, 100, 0, 100, 100, 0, 100]); - assert.equal(a.area(), 100 * 100); - a.points.pop() - assert.equal(a.area(), 100 * 100 / 2); - }); - - it("circumference", () => { - const a = polygon2([0, 0, 100, 0, 100, 100, 0, 100]); - assert.equal(a.arcLength(), 400); - a.points.pop() - assert.equal(a.arcLength(), 200 + Math.sqrt(2) * 100); - }); - - it("hiccup", () => { - const src: HiccupPolygon2 = ["polygon", { fill: "red" }, [[0, 0], [100, 0], [100, 100], [0, 100]]]; - const src2: HiccupPolygon2 = ["polygon", { fill: "red" }, [0, 0, 100, 0, 100, 100, 0, 100]]; - let a = Polygon2.fromHiccup(src); - assert(equiv(a.points, src[2])); - assert.deepEqual(a.attribs, src[1]); - a = Polygon2.fromHiccup(src2); - assert(equiv(a.points, src[2])); - assert.deepEqual(a.attribs, src2[1]); - assert( - equiv( - a.toHiccup(), - src - ) - ); - }); -}); diff --git a/packages/geom/test/tsconfig.json b/packages/geom/test/tsconfig.json index bcf29ace54..f6e63560dd 100644 --- a/packages/geom/test/tsconfig.json +++ b/packages/geom/test/tsconfig.json @@ -1,7 +1,8 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs" }, "include": [ "./**/*.ts", diff --git a/packages/geom/tsconfig.json b/packages/geom/tsconfig.json index f6c291a0a0..faed4e5fe7 100644 --- a/packages/geom/tsconfig.json +++ b/packages/geom/tsconfig.json @@ -1,7 +1,10 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6", + "preserveConstEnums": false }, "include": [ "./src/**/*.ts" diff --git a/packages/hdom-canvas/.npmignore b/packages/hdom-canvas/.npmignore index d703bda97a..67d0c55714 100644 --- a/packages/hdom-canvas/.npmignore +++ b/packages/hdom-canvas/.npmignore @@ -1,10 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/hdom-canvas/CHANGELOG.md b/packages/hdom-canvas/CHANGELOG.md index ab27843848..0b5b916dc7 100644 --- a/packages/hdom-canvas/CHANGELOG.md +++ b/packages/hdom-canvas/CHANGELOG.md @@ -3,6 +3,33 @@ 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/hdom-canvas@0.1.20...@thi.ng/hdom-canvas@1.0.0) (2019-01-21) + + +### Build System + +* update package scripts, outputs, imports in remaining packages ([f912a84](https://github.com/thi-ng/umbrella/commit/f912a84)) + + +### Features + +* **hdom-canvas:** add ellipse() / ellipticArc(), update readme ([9a50769](https://github.com/thi-ng/umbrella/commit/9a50769)) + + +### BREAKING CHANGES + +* enable multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols + + + + + ## [0.1.20](https://github.com/thi-ng/umbrella/compare/@thi.ng/hdom-canvas@0.1.19...@thi.ng/hdom-canvas@0.1.20) (2018-12-21) **Note:** Version bump only for package @thi.ng/hdom-canvas diff --git a/packages/hdom-canvas/README.md b/packages/hdom-canvas/README.md index f52ab7b9fe..72bf02358a 100644 --- a/packages/hdom-canvas/README.md +++ b/packages/hdom-canvas/README.md @@ -7,41 +7,42 @@ This project is part of the [@thi.ng/umbrella](https://github.com/thi-ng/umbrella/) monorepo. - - -- [@thi.ng/hdom-canvas](#thinghdom-canvas) - - [About](#about) - - [Status](#status) - - [Installation](#installation) - - [Dependencies](#dependencies) - - [Usage examples](#usage-examples) - - [How it works](#how-it-works) - - [Restrictions & behavior controls](#restrictions--behavior-controls) - - [HDPI support](#hdpi-support) - - [SVG conversion](#svg-conversion) - - [Supported shape types](#supported-shape-types) - - [Group](#group) - - [Definition group](#definition-group) - - [Circle](#circle) - - [Rect](#rect) - - [Arc](#arc) - - [Line](#line) - - [Horizontal Line](#horizontal-line) - - [Vertical Line](#vertical-line) - - [Polyline / Polygon](#polyline--polygon) - - [Path](#path) - - [Points](#points) - - [Text](#text) - - [Image](#image) - - [Gradients](#gradients) - - [Attributes](#attributes) - - [Coordinate transformations](#coordinate-transformations) - - [Transform matrix](#transform-matrix) - - [Translation](#translation) - - [Scaling](#scaling) - - [Rotation](#rotation) - - [Authors](#authors) - - [License](#license) + + +- [About](#about) + - [Status](#status) +- [Installation](#installation) +- [Dependencies](#dependencies) +- [Usage examples](#usage-examples) +- [How it works](#how-it-works) + - [Restrictions & behavior controls](#restrictions--behavior-controls) + - [HDPI support](#hdpi-support) +- [SVG conversion](#svg-conversion) +- [Supported shape types](#supported-shape-types) + - [Group](#group) + - [Definition group](#definition-group) + - [Circle](#circle) + - [Ellipse](#ellipse) + - [Rect](#rect) + - [Arc](#arc) + - [Line](#line) + - [Horizontal Line](#horizontal-line) + - [Vertical Line](#vertical-line) + - [Polyline / Polygon](#polyline--polygon) + - [Path](#path) + - [SVG paths with arc segments](#svg-paths-with-arc-segments) + - [Points](#points) + - [Text](#text) + - [Image](#image) + - [Gradients](#gradients) +- [Attributes](#attributes) +- [Coordinate transformations](#coordinate-transformations) + - [Transform matrix](#transform-matrix) + - [Translation](#translation) + - [Scaling](#scaling) + - [Rotation](#rotation) +- [Authors](#authors) +- [License](#license) @@ -94,6 +95,32 @@ start(() => { }); ``` +Usage with +[@thi.ng/geom](https://github.com/thi-ng/umbrella/tree/master/packages/geom) +shape primitives: + +```ts +import { start } from "@thi.ng/hdom"; +import { canvas } from "@thi.ng/hdom-canvas"; +import * as g from "@thi.ng/geom"; + +start(() => { + const t = Date.now() * 0.001; + return [canvas, { width: 100, height: 100 }, + g.group( + [ + g.withAttribs( + g.asPolygon(g.circle(50), 6), + { rotate: t % Math.PI, stroke: "red" } + ), + g.star(25 + 25 * Math.sin(t), 6, [0.5, 1], { stroke: "blue" }), + ], + { translate: [50, 50], fill: "none" } + ) + ]; +}); +``` + ## How it works The package provides a `canvas` component which uses the branch-local @@ -105,8 +132,11 @@ component, but are then translated into canvas API draw commands during the hdom update process. Any embedded shape component functions receive the user context object as first arg, just like normal hdom components. -Shape components are expressed in standard hiccup syntax, however with -the following... +Shape components are expressed in standard hiccup syntax (or as objects +implementing the `IToHiccup()` interface, like the shape types provided +by +[@thi.ng/geom](https://github.com/thi-ng/umbrella/tree/master/packages/geom)), +and with the following... ### Restrictions & behavior controls @@ -172,7 +202,7 @@ first be normalized (if not already) using hdom-canvas' `normalizeTree()`. ```ts -import { serialize } from "@thi.ng/hiccup/serialize"; +import { serialize } from "@thi.ng/hiccup"; import { convertTree, svg } from "@thi.ng/hiccup-svg"; import { normalizeTree } from "@thi.ng/hdom-canvas"; @@ -236,6 +266,12 @@ used, should always come first in a scene tree. ["circle", attribs, [x, y], radius] ``` +### Ellipse + +```ts +["ellipse", attribs, [x, y], [rx,ry], axisTheta?, start?, end?, ccw?] +``` + ### Rect ```ts @@ -251,6 +287,9 @@ clamped to `Math.min(w, h)/2`. ["arc", attribs, [x, y], radius, startAngle, endAngle, anticlockwise?] ``` +Only circular arcs are supported in this format. Please see [note about +differences to SVG](#svg-paths-with-arc-segments). + ### Line ```ts @@ -305,6 +344,27 @@ relative to the end point of the previous segment. | `["A", [x1,y1], [x2, y2], r]` | Arc | | `["Z"]` | Close (sub)path | +#### SVG paths with arc segments + +**IMPORTANT:** Due to differences between SVG and canvas API arc +handling, SVG paths containing arc segments are **NOT** compatible with +the above format. To draw such paths reliably, these should first be +converted to use cubics. E.g. here using +[@thi.ng/geom](https://github.com/thi-ng/umbrella/tree/master/packages/geom): + +```ts +import { normalizedPath, pathFromSVG } from "@thi.ng/geom"; + +// path w/ ac segments +const a = pathFromSvg("M0,0H80A20,20,0,0,1,100,20V30A20,20,0,0,1,80,50")[0]; + +// normalized to only use cubic curves +const b = normalizedPath(a); + +asSvg(b); +// +``` + ### Points ```ts diff --git a/packages/hdom-canvas/package.json b/packages/hdom-canvas/package.json index 5fd0782d65..278631c758 100644 --- a/packages/hdom-canvas/package.json +++ b/packages/hdom-canvas/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/hdom-canvas", - "version": "0.1.20", + "version": "1.0.0", "description": "Declarative canvas scenegraph & visualization for @thi.ng/hdom", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,26 +14,28 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn run clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module hdomCanvas api checks diff hdom", + "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 run build && yarn publish --access public", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/api": "^4.2.4", - "@thi.ng/checks": "^1.5.14", - "@thi.ng/diff": "^2.0.2", - "@thi.ng/hdom": "^6.1.0" + "@thi.ng/api": "^5.0.0", + "@thi.ng/checks": "^2.0.0", + "@thi.ng/diff": "^3.0.0", + "@thi.ng/hdom": "^7.0.0" }, "keywords": [ "ES6", @@ -46,5 +50,6 @@ ], "publishConfig": { "access": "public" - } + }, + "sideEffects": false } diff --git a/packages/hdom-canvas/src/index.ts b/packages/hdom-canvas/src/index.ts index 30f88e22eb..bfb4f6e495 100644 --- a/packages/hdom-canvas/src/index.ts +++ b/packages/hdom-canvas/src/index.ts @@ -1,11 +1,12 @@ -import { IObjectOf } from "@thi.ng/api/api"; -import { isArray } from "@thi.ng/checks/is-array"; -import { isArrayLike } from "@thi.ng/checks/is-arraylike"; -import { isNotStringAndIterable } from "@thi.ng/checks/is-not-string-iterable"; -import { DiffMode } from "@thi.ng/diff/api"; -import { diffArray } from "@thi.ng/diff/array"; -import { HDOMImplementation, HDOMOpts } from "@thi.ng/hdom/api"; -import { equiv, releaseTree } from "@thi.ng/hdom/diff"; +import { IObjectOf } from "@thi.ng/api"; +import { isArray, isArrayLike, isNotStringAndIterable } from "@thi.ng/checks"; +import { diffArray, DiffMode } from "@thi.ng/diff"; +import { + equiv, + HDOMImplementation, + HDOMOpts, + releaseTree +} from "@thi.ng/hdom"; interface DrawState { attribs: IObjectOf; @@ -274,6 +275,9 @@ const walk = case "circle": circularArc(ctx, attribs, shape[2], shape[3]); break; + case "ellipse": + ellipticArc(ctx, attribs, shape[2], shape[3], shape[4], shape[5], shape[6]); + break; case "arc": circularArc(ctx, attribs, shape[2], shape[3], shape[4], shape[5]); break; @@ -504,29 +508,31 @@ const path = ( ctx.lineTo(b[0], b[1]); a = b; break; - // horizontal line + // horizontal line rel case "h": b = [a[0] + b, a[1]]; ctx.lineTo(b[0], b[1]); a = b; break; + // horizontal line abs case "H": b = [b, a[1]]; ctx.lineTo(b[0], b[1]); a = b; break; - // vertical line + // vertical line rel case "v": b = [a[0], a[1] + b]; ctx.lineTo(b[0], b[1]); a = b; break; + // vertical line abs case "V": b = [a[0], b]; ctx.lineTo(b[0], b[1]); a = b; break; - // cubic / bezier curve to + // cubic curve rel case "c": c = s[2]; d = s[3]; @@ -538,6 +544,7 @@ const path = ( ); a = d; break; + // cubic curve abs case "C": c = s[2]; d = s[3]; @@ -548,7 +555,7 @@ const path = ( ); a = d; break; - // quadratic curve to + // quadratic curve rel case "q": c = s[2]; c = [a[0] + c[0], a[1] + c[1]]; @@ -558,6 +565,7 @@ const path = ( ); a = c; break; + // quadratic curve abs case "Q": c = s[2]; ctx.quadraticCurveTo( @@ -566,7 +574,8 @@ const path = ( ); a = c; break; - // arc to + // circular arc rel + // Note: NOT compatible w/ SVG arc segments case "a": c = s[2]; c = [a[0] + c[0], a[1] + c[1]]; @@ -577,6 +586,8 @@ const path = ( ); a = c; break; + // circular arc abs + // Note: NOT compatible w/ SVG arc segments case "A": c = s[2]; ctx.arcTo( @@ -610,6 +621,21 @@ const circularArc = ( endShape(ctx, attribs); }; +const ellipticArc = ( + ctx: CanvasRenderingContext2D, + attribs: IObjectOf, + pos: ReadonlyVec, + r: ReadonlyVec, + axis = 0, + start = 0, + end = TAU, + ccw = false +) => { + ctx.beginPath(); + ctx.ellipse(pos[0], pos[1], r[0], r[1], axis, start, end, ccw); + endShape(ctx, attribs); +}; + const rect = (ctx: CanvasRenderingContext2D, attribs: IObjectOf, pos: ReadonlyVec, diff --git a/packages/hdom-canvas/test/tsconfig.json b/packages/hdom-canvas/test/tsconfig.json index bcf29ace54..2c9c12a650 100644 --- a/packages/hdom-canvas/test/tsconfig.json +++ b/packages/hdom-canvas/test/tsconfig.json @@ -1,10 +1,11 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", "../src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/hdom-canvas/tsconfig.json b/packages/hdom-canvas/tsconfig.json index bd6481a5a6..bcf03f18b4 100644 --- a/packages/hdom-canvas/tsconfig.json +++ b/packages/hdom-canvas/tsconfig.json @@ -1,9 +1,11 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/hdom-components/.npmignore b/packages/hdom-components/.npmignore index d703bda97a..67d0c55714 100644 --- a/packages/hdom-components/.npmignore +++ b/packages/hdom-components/.npmignore @@ -1,10 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/hdom-components/CHANGELOG.md b/packages/hdom-components/CHANGELOG.md index 1de99ff2fd..526aa9657e 100644 --- a/packages/hdom-components/CHANGELOG.md +++ b/packages/hdom-components/CHANGELOG.md @@ -3,6 +3,28 @@ 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/hdom-components@2.4.6...@thi.ng/hdom-components@3.0.0) (2019-01-21) + + +### Build System + +* update package scripts, outputs, imports in remaining packages ([f912a84](https://github.com/thi-ng/umbrella/commit/f912a84)) + + +### BREAKING CHANGES + +* enable multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols + + + + + ## [2.4.6](https://github.com/thi-ng/umbrella/compare/@thi.ng/hdom-components@2.4.5...@thi.ng/hdom-components@2.4.6) (2019-01-02) **Note:** Version bump only for package @thi.ng/hdom-components diff --git a/packages/hdom-components/adr/0002-component-configuration.md b/packages/hdom-components/adr/0002-component-configuration.md index a68e2c4ca6..34cd9e4630 100644 --- a/packages/hdom-components/adr/0002-component-configuration.md +++ b/packages/hdom-components/adr/0002-component-configuration.md @@ -86,7 +86,7 @@ component](../src/button.ts). ```ts // button.ts -import { IObjectOf } from "@thi.ng/api/api"; +import { IObjectOf } from "@thi.ng/api"; export interface ButtonOpts { /** diff --git a/packages/hdom-components/package.json b/packages/hdom-components/package.json index 448c4b3ab6..296dd44b78 100644 --- a/packages/hdom-components/package.json +++ b/packages/hdom-components/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/hdom-components", - "version": "2.4.6", + "version": "3.0.0", "description": "Raw, skinnable UI & SVG components for @thi.ng/hdom", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,27 +14,29 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn run clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module hdomComponents api checks math transducers transducers-stats", + "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 run build && yarn publish --access public", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/api": "^4.2.4", - "@thi.ng/checks": "^1.5.14", - "@thi.ng/math": "^0.2.2", - "@thi.ng/transducers": "^2.3.2", - "@thi.ng/transducers-stats": "^0.4.23", + "@thi.ng/api": "^5.0.0", + "@thi.ng/checks": "^2.0.0", + "@thi.ng/math": "^1.0.0", + "@thi.ng/transducers": "^3.0.0", + "@thi.ng/transducers-stats": "^1.0.0", "@types/webgl2": "^0.0.4" }, "keywords": [ @@ -41,5 +45,6 @@ ], "publishConfig": { "access": "public" - } + }, + "sideEffects": false } diff --git a/packages/hdom-components/src/button-group.ts b/packages/hdom-components/src/button-group.ts index ad4f6d5109..294ab5cbfc 100644 --- a/packages/hdom-components/src/button-group.ts +++ b/packages/hdom-components/src/button-group.ts @@ -1,6 +1,5 @@ -import { IObjectOf } from "@thi.ng/api/api"; - -import { ButtonArgs, Button } from "./button"; +import { IObjectOf } from "@thi.ng/api"; +import { Button, ButtonArgs } from "./button"; import { mergeAttribs } from "./utils/merge-attribs"; /** diff --git a/packages/hdom-components/src/button.ts b/packages/hdom-components/src/button.ts index 96c4490fe1..e188584ccb 100644 --- a/packages/hdom-components/src/button.ts +++ b/packages/hdom-components/src/button.ts @@ -1,4 +1,4 @@ -import { IObjectOf } from "@thi.ng/api/api"; +import { IObjectOf } from "@thi.ng/api"; import { mergeAttribs } from "./utils/merge-attribs"; export interface ButtonOpts { diff --git a/packages/hdom-components/src/fps-counter.ts b/packages/hdom-components/src/fps-counter.ts index 695272d16e..9110b09785 100644 --- a/packages/hdom-components/src/fps-counter.ts +++ b/packages/hdom-components/src/fps-counter.ts @@ -1,5 +1,5 @@ -import { sma } from "@thi.ng/transducers-stats/sma"; -import { step } from "@thi.ng/transducers/step"; +import { step } from "@thi.ng/transducers"; +import { sma } from "@thi.ng/transducers-stats"; import { sparkline, SparklineOpts } from "./sparkline"; export interface FpsCounterOpts { diff --git a/packages/hdom-components/src/link.ts b/packages/hdom-components/src/link.ts index 3c8992ecd0..ff365e4246 100644 --- a/packages/hdom-components/src/link.ts +++ b/packages/hdom-components/src/link.ts @@ -1,4 +1,4 @@ -import { isString } from "@thi.ng/checks/is-string"; +import { isString } from "@thi.ng/checks"; export const link = (attribs: any, body: any) => ["a", isString(attribs) ? { href: attribs } : attribs, body]; diff --git a/packages/hdom-components/src/notification.ts b/packages/hdom-components/src/notification.ts index ce84778af9..94992beece 100644 --- a/packages/hdom-components/src/notification.ts +++ b/packages/hdom-components/src/notification.ts @@ -1,4 +1,4 @@ -import { IObjectOf } from "@thi.ng/api/api"; +import { IObjectOf } from "@thi.ng/api"; import { appLink } from "./link"; export interface NotificationOpts { diff --git a/packages/hdom-components/src/pager.ts b/packages/hdom-components/src/pager.ts index e729868f3f..a7a3426179 100644 --- a/packages/hdom-components/src/pager.ts +++ b/packages/hdom-components/src/pager.ts @@ -1,5 +1,4 @@ -import { range } from "@thi.ng/transducers/iter/range"; -import { map } from "@thi.ng/transducers/xform/map"; +import { map, range } from "@thi.ng/transducers"; /** * Configuration options for pager components. diff --git a/packages/hdom-components/src/sparkline.ts b/packages/hdom-components/src/sparkline.ts index d322b3e6b5..6938ed664b 100644 --- a/packages/hdom-components/src/sparkline.ts +++ b/packages/hdom-components/src/sparkline.ts @@ -1,6 +1,5 @@ -import { fitClamped } from "@thi.ng/math/fit"; -import { str } from "@thi.ng/transducers/rfn/str"; -import { mapIndexed } from "@thi.ng/transducers/xform/map-indexed"; +import { fitClamped } from "@thi.ng/math"; +import { mapIndexed, str } from "@thi.ng/transducers"; export interface SparklineOpts { /** diff --git a/packages/hdom-components/test/tsconfig.json b/packages/hdom-components/test/tsconfig.json index bcf29ace54..2c9c12a650 100644 --- a/packages/hdom-components/test/tsconfig.json +++ b/packages/hdom-components/test/tsconfig.json @@ -1,10 +1,11 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", "../src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/hdom-components/tsconfig.json b/packages/hdom-components/tsconfig.json index bd6481a5a6..bcf03f18b4 100644 --- a/packages/hdom-components/tsconfig.json +++ b/packages/hdom-components/tsconfig.json @@ -1,9 +1,11 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/hdom-mock/.npmignore b/packages/hdom-mock/.npmignore index ec83d74c9d..67d0c55714 100644 --- a/packages/hdom-mock/.npmignore +++ b/packages/hdom-mock/.npmignore @@ -1,11 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc -export src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/hdom-mock/CHANGELOG.md b/packages/hdom-mock/CHANGELOG.md index 5d9850d6e6..3d5c4f982b 100644 --- a/packages/hdom-mock/CHANGELOG.md +++ b/packages/hdom-mock/CHANGELOG.md @@ -3,6 +3,28 @@ 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/hdom-mock@0.1.5...@thi.ng/hdom-mock@1.0.0) (2019-01-21) + + +### Build System + +* update package scripts, outputs, imports in remaining packages ([f912a84](https://github.com/thi-ng/umbrella/commit/f912a84)) + + +### BREAKING CHANGES + +* enable multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols + + + + + ## [0.1.5](https://github.com/thi-ng/umbrella/compare/@thi.ng/hdom-mock@0.1.4...@thi.ng/hdom-mock@0.1.5) (2018-12-21) **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 595762896a..71156c44df 100644 --- a/packages/hdom-mock/package.json +++ b/packages/hdom-mock/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/hdom-mock", - "version": "0.1.5", - "description": "TODO", - "main": "./index.js", + "version": "1.0.0", + "description": "Mock base implementation for @thi.ng/hdom API", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,24 +14,27 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn run clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module hdomMock api checks hdom", + "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 run build && yarn publish --access public", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/api": "^4.2.4", - "@thi.ng/hdom": "^6.1.0" + "@thi.ng/api": "^5.0.0", + "@thi.ng/checks": "^2.0.0", + "@thi.ng/hdom": "^7.0.0" }, "keywords": [ "ES6", @@ -37,5 +42,6 @@ ], "publishConfig": { "access": "public" - } + }, + "sideEffects": false } diff --git a/packages/hdom-mock/src/index.ts b/packages/hdom-mock/src/index.ts index 5c9cc3f1f9..dce84334cd 100644 --- a/packages/hdom-mock/src/index.ts +++ b/packages/hdom-mock/src/index.ts @@ -1,9 +1,13 @@ -import { IObjectOf } from "@thi.ng/api/api"; -import { isFunction } from "@thi.ng/checks/is-function"; -import { HDOMImplementation, HDOMOpts } from "@thi.ng/hdom/api"; -import { diffTree } from "@thi.ng/hdom/diff"; -import { createTree, hydrateTree } from "@thi.ng/hdom/dom"; -import { normalizeTree } from "@thi.ng/hdom/normalize"; +import { IObjectOf } from "@thi.ng/api"; +import { isFunction } from "@thi.ng/checks"; +import { + createTree, + diffTree, + HDOMImplementation, + HDOMOpts, + hydrateTree, + normalizeTree +} from "@thi.ng/hdom"; export const TEXT = Symbol(); diff --git a/packages/hdom-mock/test/tsconfig.json b/packages/hdom-mock/test/tsconfig.json index bcf29ace54..2c9c12a650 100644 --- a/packages/hdom-mock/test/tsconfig.json +++ b/packages/hdom-mock/test/tsconfig.json @@ -1,10 +1,11 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", "../src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/hdom-mock/tsconfig.json b/packages/hdom-mock/tsconfig.json index bd6481a5a6..bcf03f18b4 100644 --- a/packages/hdom-mock/tsconfig.json +++ b/packages/hdom-mock/tsconfig.json @@ -1,9 +1,11 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/hdom/.npmignore b/packages/hdom/.npmignore index d703bda97a..67d0c55714 100644 --- a/packages/hdom/.npmignore +++ b/packages/hdom/.npmignore @@ -1,10 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/hdom/CHANGELOG.md b/packages/hdom/CHANGELOG.md index ae3cc921ba..3ae0dec008 100644 --- a/packages/hdom/CHANGELOG.md +++ b/packages/hdom/CHANGELOG.md @@ -3,6 +3,28 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [7.0.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/hdom@6.1.0...@thi.ng/hdom@7.0.0) (2019-01-21) + + +### Build System + +* update package scripts, outputs, imports in remaining packages ([f912a84](https://github.com/thi-ng/umbrella/commit/f912a84)) + + +### BREAKING CHANGES + +* enable multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols + + + + + # [6.1.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/hdom@6.0.4...@thi.ng/hdom@6.1.0) (2018-12-21) diff --git a/packages/hdom/README.md b/packages/hdom/README.md index 9eed05fdf8..5b1e185052 100644 --- a/packages/hdom/README.md +++ b/packages/hdom/README.md @@ -100,7 +100,7 @@ Benefits: [standalone example](https://github.com/thi-ng/umbrella/tree/master/examples/hdom-basics) ```ts -import * as hdom from "@thi.ng/hdom"; +import { start, renderOnce } from "@thi.ng/hdom"; // stateless component w/ params // the first arg is an auto-injected context object @@ -120,10 +120,10 @@ const app = () => { }; // start RAF update & diff loop -hdom.start(app(), { root: document.body }); +start(app(), { root: document.body }); // alternatively create DOM tree only once -hdom.renderOnce(app(), { root: document.body }); +renderOnce(app(), { root: document.body }); ``` Alternatively, use the same component for browser or server side HTML @@ -150,9 +150,9 @@ diffing via RAF). [standalone example](https://github.com/thi-ng/umbrella/tree/master/examples/transducers-hdom) ```ts -import { fromInterval, stream, sync } from "@thi.ng/rstream/stream"; -import { updateDOM } from "@thi.ng/rstream/transducers-hdom"; -import * as tx from "@thi.ng/rstream/transducers"; +import { fromInterval, stream, sync } from "@thi.ng/rstream"; +import { updateDOM } from "@thi.ng/transducers-hdom"; +import { map, scan } from "@thi.ng/transducers"; // root component function const app = ({ ticks, clicks }) => @@ -164,7 +164,7 @@ const app = ({ ticks, clicks }) => ]; // transformed stream to count clicks -const clickStream = stream().transform(tx.scan(tx.count(-1))); +const clickStream = stream().transform(scan(tx.count(-1))); // seed clickStream.next(0); @@ -179,7 +179,7 @@ sync({ }, }).transform( // transform tuple into hdom component - tx.map(app), + map(app), // apply hdom tree to real DOM updateDOM({ root: document.body }) ); diff --git a/packages/hdom/package.json b/packages/hdom/package.json index 42ecb96614..3b3e6b5d58 100644 --- a/packages/hdom/package.json +++ b/packages/hdom/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/hdom", - "version": "6.1.0", + "version": "7.0.0", "description": "Lightweight vanilla ES6 UI component trees with customizable branch-local behaviors", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,36 +14,43 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module hdom api checks diff equiv errors hiccup", + "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", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { - "@thi.ng/atom": "^1.5.8", + "@thi.ng/atom": "^2.0.0", "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/api": "^4.2.4", - "@thi.ng/checks": "^1.5.14", - "@thi.ng/diff": "^2.0.2", - "@thi.ng/equiv": "^0.1.15", - "@thi.ng/hiccup": "^2.7.2" + "@thi.ng/api": "^5.0.0", + "@thi.ng/checks": "^2.0.0", + "@thi.ng/diff": "^3.0.0", + "@thi.ng/equiv": "^1.0.0", + "@thi.ng/errors": "^1.0.0", + "@thi.ng/hiccup": "^3.0.0" }, "keywords": [ "browser", "components", + "data driven", + "declarative", "diff", "DOM", "ES6", + "functional", "IOC", + "iterators", "reactive", "typescript", "UI", @@ -49,5 +58,6 @@ ], "publishConfig": { "access": "public" - } + }, + "sideEffects": false } diff --git a/packages/hdom/src/api.ts b/packages/hdom/src/api.ts index 4432edda9f..05a1f643d4 100644 --- a/packages/hdom/src/api.ts +++ b/packages/hdom/src/api.ts @@ -1,4 +1,4 @@ -import { IObjectOf } from "@thi.ng/api/api"; +import { IObjectOf } from "@thi.ng/api"; export interface ILifecycle { /** diff --git a/packages/hdom/src/diff.ts b/packages/hdom/src/diff.ts index d8717af3cd..aa29cdda68 100644 --- a/packages/hdom/src/diff.ts +++ b/packages/hdom/src/diff.ts @@ -1,7 +1,5 @@ -import { IObjectOf, SEMAPHORE } from "@thi.ng/api/api"; -import { DiffMode } from "@thi.ng/diff/api"; -import { diffArray } from "@thi.ng/diff/array"; -import { diffObject } from "@thi.ng/diff/object"; +import { IObjectOf, SEMAPHORE } from "@thi.ng/api"; +import { diffArray, DiffMode, diffObject } from "@thi.ng/diff"; import { equiv as _equiv, equivArrayLike, diff --git a/packages/hdom/src/dom.ts b/packages/hdom/src/dom.ts index 712823ff9d..06aa938878 100644 --- a/packages/hdom/src/dom.ts +++ b/packages/hdom/src/dom.ts @@ -1,11 +1,10 @@ -import * as isa from "@thi.ng/checks/is-array"; -import * as isi from "@thi.ng/checks/is-not-string-iterable"; -import { SVG_NS, SVG_TAGS } from "@thi.ng/hiccup/api"; -import { css } from "@thi.ng/hiccup/css"; +import { isArray as isa, isNotStringAndIterable as isi } from "@thi.ng/checks"; +import { SVG_NS, SVG_TAGS } from "@thi.ng/hiccup"; +import { css } from "@thi.ng/hiccup"; import { HDOMImplementation, HDOMOpts } from "./api"; -const isArray = isa.isArray; -const isNotStringAndIterable = isi.isNotStringAndIterable +const isArray = isa; +const isNotStringAndIterable = isi; /** * See `HDOMImplementation` interface for further details. diff --git a/packages/hdom/src/index.ts b/packages/hdom/src/index.ts index e33ab1e275..deb7075b81 100644 --- a/packages/hdom/src/index.ts +++ b/packages/hdom/src/index.ts @@ -5,3 +5,5 @@ export * from "./dom"; export * from "./normalize"; export * from "./render-once"; export * from "./start"; + +export * from "./utils"; diff --git a/packages/hdom/src/normalize.ts b/packages/hdom/src/normalize.ts index 2cd36f3422..575fa7c46c 100644 --- a/packages/hdom/src/normalize.ts +++ b/packages/hdom/src/normalize.ts @@ -1,13 +1,11 @@ -import * as isa from "@thi.ng/checks/is-array"; -import * as insi from "@thi.ng/checks/is-not-string-iterable"; -import * as iso from "@thi.ng/checks/is-plain-object"; -import { illegalArgs } from "@thi.ng/errors/illegal-arguments"; -import { NO_SPANS, TAG_REGEXP } from "@thi.ng/hiccup/api"; +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"; -const isArray = isa.isArray; -const isNotStringAndIterable = insi.isNotStringAndIterable; -const isPlainObject = iso.isPlainObject; +const isArray = isa; +const isNotStringAndIterable = isi; +const isPlainObject = iso; /** * Expands single hiccup element/component into its canonical form: diff --git a/packages/hdom/src/render-once.ts b/packages/hdom/src/render-once.ts index 740f558a29..63bc0b9985 100644 --- a/packages/hdom/src/render-once.ts +++ b/packages/hdom/src/render-once.ts @@ -1,4 +1,4 @@ -import { derefContext } from "@thi.ng/hiccup/deref"; +import { derefContext } from "@thi.ng/hiccup"; import { HDOMImplementation, HDOMOpts } from "./api"; import { DEFAULT_IMPL } from "./default"; import { resolveRoot } from "./utils"; diff --git a/packages/hdom/src/start.ts b/packages/hdom/src/start.ts index 6478803a9a..7efa32557c 100644 --- a/packages/hdom/src/start.ts +++ b/packages/hdom/src/start.ts @@ -1,4 +1,4 @@ -import { derefContext } from "@thi.ng/hiccup/deref"; +import { derefContext } from "@thi.ng/hiccup"; import { HDOMImplementation, HDOMOpts } from "./api"; import { DEFAULT_IMPL } from "./default"; import { resolveRoot } from "./utils"; diff --git a/packages/hdom/src/utils.ts b/packages/hdom/src/utils.ts index c2b1cdf99c..465f06addd 100644 --- a/packages/hdom/src/utils.ts +++ b/packages/hdom/src/utils.ts @@ -1,4 +1,4 @@ -import { isString } from "@thi.ng/checks/is-string"; +import { isString } from "@thi.ng/checks"; import { HDOMImplementation } from "./api"; export const resolveRoot = diff --git a/packages/hdom/test/index.ts b/packages/hdom/test/index.ts index 020c098d77..67d343e5bb 100644 --- a/packages/hdom/test/index.ts +++ b/packages/hdom/test/index.ts @@ -1,18 +1,15 @@ +import { Atom } from "@thi.ng/atom"; +import { derefContext } from "@thi.ng/hiccup"; +import { map, range } from "@thi.ng/iterators"; import * as assert from "assert"; - -import { Atom } from "@thi.ng/atom/atom"; -import { map } from "@thi.ng/iterators/map"; -import { range } from "@thi.ng/iterators/range"; import { normalizeTree } from "../src/normalize"; -import { derefContext } from "@thi.ng/hiccup/deref"; -function _check(a, b, ctx = null) { - assert.deepEqual(normalizeTree({ ctx, keys: false, span: false }, a), b); -} +const _check = + (a, b, ctx = null) => + assert.deepEqual(normalizeTree({ ctx, keys: false, span: false }, a), b); -function check(id, a, b) { - it(id, () => _check(a, b)); -} +const check = + (id, a, b) => it(id, () => _check(a, b)); describe("hdom", () => { diff --git a/packages/hdom/test/tsconfig.json b/packages/hdom/test/tsconfig.json index bcf29ace54..2c9c12a650 100644 --- a/packages/hdom/test/tsconfig.json +++ b/packages/hdom/test/tsconfig.json @@ -1,10 +1,11 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", "../src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/hdom/tsconfig.json b/packages/hdom/tsconfig.json index bd6481a5a6..bcf03f18b4 100644 --- a/packages/hdom/tsconfig.json +++ b/packages/hdom/tsconfig.json @@ -1,9 +1,11 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/heaps/.npmignore b/packages/heaps/.npmignore index d703bda97a..67d0c55714 100644 --- a/packages/heaps/.npmignore +++ b/packages/heaps/.npmignore @@ -1,10 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/heaps/CHANGELOG.md b/packages/heaps/CHANGELOG.md index 056704c073..fa1d779d45 100644 --- a/packages/heaps/CHANGELOG.md +++ b/packages/heaps/CHANGELOG.md @@ -3,6 +3,28 @@ 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/heaps@0.3.1...@thi.ng/heaps@1.0.0) (2019-01-21) + + +### Build System + +* update package build scripts & outputs, imports in ~50 packages ([b54b703](https://github.com/thi-ng/umbrella/commit/b54b703)) + + +### BREAKING CHANGES + +* enabled multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols. + + + + + ## [0.3.1](https://github.com/thi-ng/umbrella/compare/@thi.ng/heaps@0.3.0...@thi.ng/heaps@0.3.1) (2018-12-15) **Note:** Version bump only for package @thi.ng/heaps diff --git a/packages/heaps/package.json b/packages/heaps/package.json index e01313a5a0..e0f21658dd 100644 --- a/packages/heaps/package.json +++ b/packages/heaps/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/heaps", - "version": "0.3.1", + "version": "1.0.0", "description": "Generic binary heap & d-ary heap implementations with customizable ordering", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,24 +14,26 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn run clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module heaps api compare", + "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 run build && yarn publish --access public", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/api": "^4.2.4", - "@thi.ng/compare": "^0.1.12" + "@thi.ng/api": "^5.0.0", + "@thi.ng/compare": "^1.0.0" }, "keywords": [ "data structure", @@ -42,5 +46,6 @@ ], "publishConfig": { "access": "public" - } + }, + "sideEffects": false } diff --git a/packages/heaps/src/api.ts b/packages/heaps/src/api.ts index 18b1b4466b..ebdd8abf85 100644 --- a/packages/heaps/src/api.ts +++ b/packages/heaps/src/api.ts @@ -1,4 +1,4 @@ -import { Comparator } from "@thi.ng/api/api"; +import { Comparator } from "@thi.ng/api"; export interface HeapOpts { compare: Comparator; diff --git a/packages/heaps/src/dheap.ts b/packages/heaps/src/dheap.ts index 87c5dea5b1..acfa8a7bf8 100644 --- a/packages/heaps/src/dheap.ts +++ b/packages/heaps/src/dheap.ts @@ -1,4 +1,4 @@ -import { ICopy, IEmpty } from "@thi.ng/api/api"; +import { ICopy, IEmpty } from "@thi.ng/api"; import { compare } from "@thi.ng/compare"; import { DHeapOpts } from "./api"; diff --git a/packages/heaps/src/heap.ts b/packages/heaps/src/heap.ts index a32d49cd46..f396ba8fd1 100644 --- a/packages/heaps/src/heap.ts +++ b/packages/heaps/src/heap.ts @@ -3,7 +3,7 @@ import { ICopy, IEmpty, ILength -} from "@thi.ng/api/api"; +} from "@thi.ng/api"; import { compare } from "@thi.ng/compare"; import { HeapOpts } from "./api"; diff --git a/packages/heaps/test/tsconfig.json b/packages/heaps/test/tsconfig.json index bcf29ace54..2c9c12a650 100644 --- a/packages/heaps/test/tsconfig.json +++ b/packages/heaps/test/tsconfig.json @@ -1,10 +1,11 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", "../src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/heaps/tsconfig.json b/packages/heaps/tsconfig.json index bd6481a5a6..bcf03f18b4 100644 --- a/packages/heaps/tsconfig.json +++ b/packages/heaps/tsconfig.json @@ -1,9 +1,11 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/hiccup-carbon-icons/.gitignore b/packages/hiccup-carbon-icons/.gitignore new file mode 100644 index 0000000000..2d19fc766d --- /dev/null +++ b/packages/hiccup-carbon-icons/.gitignore @@ -0,0 +1 @@ +*.html diff --git a/packages/hiccup-carbon-icons/.npmignore b/packages/hiccup-carbon-icons/.npmignore index 8c71fc307f..67d0c55714 100644 --- a/packages/hiccup-carbon-icons/.npmignore +++ b/packages/hiccup-carbon-icons/.npmignore @@ -1,13 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc -export src* test -.nyc_output tsconfig.json -*.tgz -*.html - -convert-icons diff --git a/packages/hiccup-carbon-icons/CHANGELOG.md b/packages/hiccup-carbon-icons/CHANGELOG.md index d42079d733..7239c89aab 100644 --- a/packages/hiccup-carbon-icons/CHANGELOG.md +++ b/packages/hiccup-carbon-icons/CHANGELOG.md @@ -3,6 +3,28 @@ 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/hiccup-carbon-icons@0.1.2...@thi.ng/hiccup-carbon-icons@1.0.0) (2019-01-21) + + +### Build System + +* update package build scripts & outputs, imports in ~50 packages ([b54b703](https://github.com/thi-ng/umbrella/commit/b54b703)) + + +### BREAKING CHANGES + +* enabled multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols. + + + + + ## [0.1.2](https://github.com/thi-ng/umbrella/compare/@thi.ng/hiccup-carbon-icons@0.1.1...@thi.ng/hiccup-carbon-icons@0.1.2) (2018-12-20) **Note:** Version bump only for package @thi.ng/hiccup-carbon-icons diff --git a/packages/hiccup-carbon-icons/README.md b/packages/hiccup-carbon-icons/README.md index 2fd951f55e..036e5d5455 100644 --- a/packages/hiccup-carbon-icons/README.md +++ b/packages/hiccup-carbon-icons/README.md @@ -53,7 +53,7 @@ None. ```ts import { renderOnce } from "@thi.ng/hdom"; -import { CODE } from "@thi.ng/hiccup-carbon-icons/code"; +import { CODE } from "@thi.ng/hiccup-carbon-icons"; // using tachyons css classes for brevity const iconButton = (icon, onclick, label?) => diff --git a/packages/hiccup-carbon-icons/package.json b/packages/hiccup-carbon-icons/package.json index 526910afb1..0e4d36efd3 100644 --- a/packages/hiccup-carbon-icons/package.json +++ b/packages/hiccup-carbon-icons/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/hiccup-carbon-icons", - "version": "0.1.2", + "version": "1.0.0", "description": "TODO", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,27 +14,38 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn run clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module hiccupCarbonIcons", + "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 run build && yarn publish --access public", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { - "@thi.ng/hiccup": "^2.7.2", + "@thi.ng/hiccup": "^3.0.0", "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "keywords": [ + "assets", + "carbon", "ES6", - "typescript" + "hdom", + "hiccup", + "IBM", + "icons", + "svg", + "typescript", + "UI" ], "publishConfig": { "access": "public" - } + }, + "sideEffects": false } diff --git a/packages/hiccup-carbon-icons/test/tsconfig.json b/packages/hiccup-carbon-icons/test/tsconfig.json index bcf29ace54..2c9c12a650 100644 --- a/packages/hiccup-carbon-icons/test/tsconfig.json +++ b/packages/hiccup-carbon-icons/test/tsconfig.json @@ -1,10 +1,11 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", "../src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/hiccup-carbon-icons/tsconfig.json b/packages/hiccup-carbon-icons/tsconfig.json index bd6481a5a6..bcf03f18b4 100644 --- a/packages/hiccup-carbon-icons/tsconfig.json +++ b/packages/hiccup-carbon-icons/tsconfig.json @@ -1,9 +1,11 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/hiccup-css/.npmignore b/packages/hiccup-css/.npmignore index d703bda97a..67d0c55714 100644 --- a/packages/hiccup-css/.npmignore +++ b/packages/hiccup-css/.npmignore @@ -1,10 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/hiccup-css/CHANGELOG.md b/packages/hiccup-css/CHANGELOG.md index 83c82328a8..aadbde1d55 100644 --- a/packages/hiccup-css/CHANGELOG.md +++ b/packages/hiccup-css/CHANGELOG.md @@ -3,6 +3,28 @@ 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/hiccup-css@0.3.5...@thi.ng/hiccup-css@1.0.0) (2019-01-21) + + +### Build System + +* update package build scripts & outputs, imports in ~50 packages ([b54b703](https://github.com/thi-ng/umbrella/commit/b54b703)) + + +### BREAKING CHANGES + +* enabled multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols. + + + + + ## [0.3.5](https://github.com/thi-ng/umbrella/compare/@thi.ng/hiccup-css@0.3.4...@thi.ng/hiccup-css@0.3.5) (2019-01-02) **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 4beedffabe..7c7c2c4a78 100644 --- a/packages/hiccup-css/package.json +++ b/packages/hiccup-css/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/hiccup-css", - "version": "0.3.5", + "version": "1.0.0", "description": "CSS from nested JS data structures", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,26 +14,28 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module hiccupCss api checks errors transducers", + "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", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/api": "^4.2.4", - "@thi.ng/checks": "^1.5.14", - "@thi.ng/errors": "^0.1.12", - "@thi.ng/transducers": "^2.3.2" + "@thi.ng/api": "^5.0.0", + "@thi.ng/checks": "^2.0.0", + "@thi.ng/errors": "^1.0.0", + "@thi.ng/transducers": "^3.0.0" }, "keywords": [ "clojure", @@ -49,5 +53,6 @@ ], "publishConfig": { "access": "public" - } + }, + "sideEffects": false } diff --git a/packages/hiccup-css/src/api.ts b/packages/hiccup-css/src/api.ts index c604a121a3..6dcb8741dd 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/api"; +import { IObjectOf } from "@thi.ng/api"; /** * Function type used by `at_xxx()` functions or any diff --git a/packages/hiccup-css/src/comment.ts b/packages/hiccup-css/src/comment.ts index e11364c2dd..55c2cd07bd 100644 --- a/packages/hiccup-css/src/comment.ts +++ b/packages/hiccup-css/src/comment.ts @@ -1,16 +1,17 @@ import { RuleFn } from "./api"; import { indent } from "./impl"; -export function comment(body: string, force = false): RuleFn { - return (acc, opts) => { - const space = indent(opts); - const inner = indent(opts, opts.depth + 1); - if (opts.format.comments || force) { - Array.prototype.push.apply( - acc, - [space + "/*", body.split("\n").map((l) => inner + l).join("\n"), space + "*/"] - ); - } - return acc; - }; -} +export const comment = + (body: string, force = false): RuleFn => + (acc, opts) => { + const space = indent(opts); + const inner = indent(opts, opts.depth + 1); + if (opts.format.comments || force) { + acc.push( + space + "/*", + body.split("\n").map((l) => inner + l).join("\n"), + space + "*/" + ); + } + return acc; + }; diff --git a/packages/hiccup-css/src/conditional.ts b/packages/hiccup-css/src/conditional.ts index 9ed2642a90..40bba5d43e 100644 --- a/packages/hiccup-css/src/conditional.ts +++ b/packages/hiccup-css/src/conditional.ts @@ -1,39 +1,39 @@ -import { isString } from "@thi.ng/checks/is-string"; - +import { isString } from "@thi.ng/checks"; import { Conditional, CSSOpts, RuleFn } from "./api"; import { expand, indent } from "./impl"; -export function conditional(type: string, cond: Conditional, rules: any[]): RuleFn { - return (acc: string[], opts: CSSOpts) => { - const space = indent(opts); - acc.push(`${space}${type} ${formatCond(cond)}${opts.format.declStart}`); - opts.depth++; - expand(acc, [], rules, opts); - opts.depth--; - acc.push(space + opts.format.declEnd); - return acc; - }; -} +export const conditional = + (type: string, cond: Conditional, rules: any[]): RuleFn => + (acc: string[], opts: CSSOpts) => { + const space = indent(opts); + acc.push(`${space}${type} ${formatCond(cond)}${opts.format.declStart}`); + opts.depth++; + expand(acc, [], rules, opts); + opts.depth--; + acc.push(space + opts.format.declEnd); + return acc; + }; -function formatCond(cond: any) { - if (isString(cond)) { - return cond; - } - const acc = []; - for (let c in cond) { - if (cond.hasOwnProperty(c)) { - let v = cond[c]; - if (v === true) { - v = c; - } else if (v === false) { - v = "not " + c; - } else if (v === "only") { - v += " " + c; - } else { - v = `(${c}:${v})`; +const formatCond = + (cond: any) => { + if (isString(cond)) { + return cond; + } + const acc = []; + for (let c in cond) { + if (cond.hasOwnProperty(c)) { + let v = cond[c]; + if (v === true) { + v = c; + } else if (v === false) { + v = "not " + c; + } else if (v === "only") { + v += " " + c; + } else { + v = `(${c}:${v})`; + } + acc.push(v); } - acc.push(v); } - } - return acc.join(" and "); -} + return acc.join(" and "); + }; diff --git a/packages/hiccup-css/src/css.ts b/packages/hiccup-css/src/css.ts index ae61dc10d3..b161242cd3 100644 --- a/packages/hiccup-css/src/css.ts +++ b/packages/hiccup-css/src/css.ts @@ -1,33 +1,35 @@ -import { isArray } from "@thi.ng/checks/is-array"; -import { isFunction } from "@thi.ng/checks/is-function"; -import { isIterable } from "@thi.ng/checks/is-iterable"; -import { isPlainObject } from "@thi.ng/checks/is-plain-object"; -import { isString } from "@thi.ng/checks/is-string"; - +import { + isArray, + isFunction, + isIterable, + isPlainObject, + isString +} from "@thi.ng/checks"; import { COMPACT, CSSOpts, DEFAULT_VENDORS } from "./api"; import { expand, formatDecls } from "./impl"; -export function css(rules: any, opts?: Partial) { - opts = { - format: COMPACT, - vendors: DEFAULT_VENDORS, - fns: {}, - depth: 0, - ...opts +export const css = + (rules: any, opts?: Partial) => { + opts = { + format: COMPACT, + vendors: DEFAULT_VENDORS, + fns: {}, + depth: 0, + ...opts + }; + if (isPlainObject(rules)) { + return formatDecls(rules, opts); + } + if (isArray(opts.autoprefix)) { + opts.autoprefix = new Set(opts.autoprefix); + } + if (isIterable(rules) && !isString(rules)) { + rules = [...rules]; + } + if (isArray(rules)) { + return expand([], [], rules, opts).join(opts.format.rules); + } + if (isFunction(rules)) { + return rules([], opts).join(opts.format.rules); + } }; - if (isPlainObject(rules)) { - return formatDecls(rules, opts); - } - if (isArray(opts.autoprefix)) { - opts.autoprefix = new Set(opts.autoprefix); - } - if (isIterable(rules) && !isString(rules)) { - rules = [...rules]; - } - if (isArray(rules)) { - return expand([], [], rules, opts).join(opts.format.rules); - } - if (isFunction(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 02766d4398..b9f01d1487 100644 --- a/packages/hiccup-css/src/impl.ts +++ b/packages/hiccup-css/src/impl.ts @@ -1,120 +1,130 @@ -import { isArray } from "@thi.ng/checks/is-array"; -import { isFunction } from "@thi.ng/checks/is-function"; -import { isIterable } from "@thi.ng/checks/is-iterable"; -import { isPlainObject } from "@thi.ng/checks/is-plain-object"; -import { isString } from "@thi.ng/checks/is-string"; -import { illegalArgs } from "@thi.ng/errors/illegal-arguments"; -import { Transducer } from "@thi.ng/transducers/api"; -import { comp } from "@thi.ng/transducers/func/comp"; -import { permutations } from "@thi.ng/transducers/iter/permutations"; -import { repeat } from "@thi.ng/transducers/iter/repeat"; -import { str } from "@thi.ng/transducers/rfn/str"; -import { transduce } from "@thi.ng/transducers/transduce"; -import { flatten } from "@thi.ng/transducers/xform/flatten"; -import { map } from "@thi.ng/transducers/xform/map"; - +import { + isArray, + isFunction, + isIterable, + isPlainObject, + isString +} from "@thi.ng/checks"; +import { illegalArgs } from "@thi.ng/errors"; +import { + comp, + flatten, + map, + permutations, + repeat, + str, + transduce, + Transducer +} from "@thi.ng/transducers"; import { CSSOpts } from "./api"; const EMPTY = new Set(); const NO_SPACES = ":["; -const xfSel = comp( - flatten(), - map((x: string) => NO_SPACES.indexOf(x.charAt(0)) >= 0 ? x : " " + x) -); +const xfSel = + comp( + flatten(), + map((x: string) => NO_SPACES.indexOf(x.charAt(0)) >= 0 ? x : " " + x) + ); -const withScope = (xf: Transducer, scope: string) => - comp(xf, map((x) => isString(x) && x.indexOf(" .") == 0 ? x + scope : x)); +const withScope = + (xf: Transducer, scope: string) => + comp(xf, map((x) => isString(x) && x.indexOf(" .") == 0 ? x + scope : x)); -export function expand(acc: string[], parent: any[], rules: any[], opts: CSSOpts) { - const n = rules.length; - const sel: string[] = []; - let curr: any, isFn; +export const expand = + (acc: string[], parent: any[], rules: any[], opts: CSSOpts) => { + const n = rules.length; + const sel: string[] = []; + let curr: any, isFn; - function process(i, r) { - 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]) { - if (!parent.length) { - if (opts.fns[r]) { - opts.fns[r].apply(null, rules.slice(i + 1))(acc, opts); - return true; + const process = (i, r) => { + 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]) { + if (!parent.length) { + if (opts.fns[r]) { + opts.fns[r].apply(null, rules.slice(i + 1))(acc, opts); + return true; + } + r(acc, opts); + } else if (isFn) { + process(i, r()); + } else { + illegalArgs(`quoted fn ('${r}') only allowed at head position`); } - r(acc, opts); - } else if (isFn) { - process(i, r()); - } else { - illegalArgs(`quoted fn ('${r}') only allowed at head position`); + } else if (isPlainObject(r)) { + curr = Object.assign(curr || {}, r); + } else if (r != null) { + sel.push(r); } - } else if (isPlainObject(r)) { - curr = Object.assign(curr || {}, r); - } else if (r != null) { - sel.push(r); - } - } + }; - for (let i = 0; i < n; i++) { - if (process(i, rules[i])) { - return acc; + for (let i = 0; i < n; i++) { + if (process(i, rules[i])) { + return acc; + } } - } - if (curr) { - acc.push(formatRule(parent, sel, curr, opts)); - } - return acc; -} + curr && acc.push(formatRule(parent, sel, curr, opts)); + return acc; + }; -function makeSelector(parent: any[], curr: any[]) { - return parent.length ? - [...permutations(parent, curr)] : - curr; -} +const makeSelector = + (parent: any[], curr: any[]) => + parent.length ? + [...permutations(parent, curr)] : + curr; -function formatRule(parent: any[], sel: any[], curr: any, opts: CSSOpts) { - const f = opts.format; - const space = indent(opts); - const xf = opts.scope ? withScope(xfSel, opts.scope) : xfSel; - return [ - space, - transduce( - map((sel: any[]) => transduce(xf, str(), isArray(sel) ? sel : [sel]).trim()), - str(f.ruleSep), - makeSelector(parent, sel)), - f.declStart, - formatDecls(curr, opts), - space, - f.declEnd - ].join(""); -} +const formatRule = + (parent: any[], sel: any[], curr: any, opts: CSSOpts) => { + const f = opts.format; + const space = indent(opts); + const xf = opts.scope ? withScope(xfSel, opts.scope) : xfSel; + return [ + space, + transduce( + map((sel: any[]) => transduce(xf, str(), isArray(sel) ? sel : [sel]).trim()), + str(f.ruleSep), + makeSelector(parent, sel)), + f.declStart, + formatDecls(curr, opts), + space, + f.declEnd + ].join(""); + }; -export function formatDecls(rules: any, opts: CSSOpts) { - const f = opts.format; - const prefixes = >(opts.autoprefix || EMPTY); - const space = indent(opts, opts.depth + 1); - const acc = []; - for (let r in rules) { - if (rules.hasOwnProperty(r)) { - let val = rules[r]; - if (isFunction(val)) { - val = val(rules); - } - if (isArray(val)) { - val = val.map((v) => isArray(v) ? v.join(" ") : v).join(f.ruleSep); - } - if (prefixes.has(r)) { - for (let v of opts.vendors) { - acc.push(`${space}${v}${r}:${f.valSep}${val};`); +export const formatDecls = + (rules: any, opts: CSSOpts) => { + const f = opts.format; + const prefixes = >(opts.autoprefix || EMPTY); + const space = indent(opts, opts.depth + 1); + const acc = []; + for (let r in rules) { + if (rules.hasOwnProperty(r)) { + let val = rules[r]; + if (isFunction(val)) { + val = val(rules); + } + if (isArray(val)) { + val = val.map((v) => isArray(v) ? v.join(" ") : v).join(f.ruleSep); + } + if (prefixes.has(r)) { + for (let v of opts.vendors) { + acc.push(`${space}${v}${r}:${f.valSep}${val};`); + } } + acc.push(`${space}${r}:${f.valSep}${val};`); } - acc.push(`${space}${r}:${f.valSep}${val};`); } - } - return acc.join(f.decls) + f.decls; -} + return acc.join(f.decls) + f.decls; + }; -export function indent(opts: CSSOpts, d = opts.depth) { - return d > 1 ? [...repeat(opts.format.indent, d)].join("") : d > 0 ? opts.format.indent : ""; -} \ No newline at end of file +export const indent = + (opts: CSSOpts, d = opts.depth) => + d > 1 ? + [...repeat(opts.format.indent, d)].join("") : + d > 0 ? + opts.format.indent : + ""; diff --git a/packages/hiccup-css/src/import.ts b/packages/hiccup-css/src/import.ts index 62de0a2c1e..72c56d7ae0 100644 --- a/packages/hiccup-css/src/import.ts +++ b/packages/hiccup-css/src/import.ts @@ -1,12 +1,12 @@ import { RuleFn } from "./api"; -export function at_import(url: string, ...queries: string[]): RuleFn { - return (acc, opts) => ( - acc.push( - queries.length ? - `@import url(${url}) ${queries.join(opts.format.ruleSep)};` : - `@import url(${url});` - ), - acc - ); -} +export const at_import = + (url: string, ...queries: string[]): RuleFn => + (acc, opts) => ( + acc.push( + queries.length ? + `@import url(${url}) ${queries.join(opts.format.ruleSep)};` : + `@import url(${url});` + ), + acc + ); diff --git a/packages/hiccup-css/src/inject.ts b/packages/hiccup-css/src/inject.ts index b2cbdc4940..3603e0c70c 100644 --- a/packages/hiccup-css/src/inject.ts +++ b/packages/hiccup-css/src/inject.ts @@ -9,19 +9,20 @@ * @param css * @param first */ -export const injectStyleSheet = (css: string, first = false) => { - const head = document.getElementsByTagName("head")[0]; - const sheet = document.createElement("style"); - sheet.setAttribute("type", "text/css"); - if ((sheet).styleSheet !== undefined) { - (sheet).styleSheet.cssText = css; - } else { - sheet.textContent = css; - } - if (first) { - head.insertBefore(sheet, head.firstChild); - } else { - head.appendChild(sheet); - } - return sheet; -}; +export const injectStyleSheet = + (css: string, first = false) => { + const head = document.getElementsByTagName("head")[0]; + const sheet = document.createElement("style"); + sheet.setAttribute("type", "text/css"); + if ((sheet).styleSheet !== undefined) { + (sheet).styleSheet.cssText = css; + } else { + sheet.textContent = css; + } + if (first) { + head.insertBefore(sheet, head.firstChild); + } else { + head.appendChild(sheet); + } + return sheet; + }; diff --git a/packages/hiccup-css/src/media.ts b/packages/hiccup-css/src/media.ts index 9bd6b129bf..1ceb027a31 100644 --- a/packages/hiccup-css/src/media.ts +++ b/packages/hiccup-css/src/media.ts @@ -1,6 +1,6 @@ import { Conditional, RuleFn } from "./api"; import { conditional } from "./conditional"; -export function at_media(cond: Conditional, rules: any[]): RuleFn { - return conditional("@media", cond, rules); -} +export const at_media = + (cond: Conditional, rules: any[]): RuleFn => + conditional("@media", cond, rules); diff --git a/packages/hiccup-css/src/supports.ts b/packages/hiccup-css/src/supports.ts index 8d8aaa4bed..8f12929cf4 100644 --- a/packages/hiccup-css/src/supports.ts +++ b/packages/hiccup-css/src/supports.ts @@ -1,6 +1,6 @@ import { Conditional, RuleFn } from "./api"; import { conditional } from "./conditional"; -export function at_supports(cond: Conditional, rules: any[]): RuleFn { - return conditional("@supports", cond, rules); -} +export const at_supports = + (cond: Conditional, rules: any[]): RuleFn => + conditional("@supports", cond, rules); diff --git a/packages/hiccup-css/test/tsconfig.json b/packages/hiccup-css/test/tsconfig.json index 13d45669e5..2c9c12a650 100644 --- a/packages/hiccup-css/test/tsconfig.json +++ b/packages/hiccup-css/test/tsconfig.json @@ -1,7 +1,8 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", diff --git a/packages/hiccup-css/tsconfig.json b/packages/hiccup-css/tsconfig.json index bd6481a5a6..bcf03f18b4 100644 --- a/packages/hiccup-css/tsconfig.json +++ b/packages/hiccup-css/tsconfig.json @@ -1,9 +1,11 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/hiccup-markdown/.npmignore b/packages/hiccup-markdown/.npmignore index ec83d74c9d..67d0c55714 100644 --- a/packages/hiccup-markdown/.npmignore +++ b/packages/hiccup-markdown/.npmignore @@ -1,11 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc -export src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/hiccup-markdown/CHANGELOG.md b/packages/hiccup-markdown/CHANGELOG.md index 1b0f8c8844..36d8250a46 100644 --- a/packages/hiccup-markdown/CHANGELOG.md +++ b/packages/hiccup-markdown/CHANGELOG.md @@ -3,6 +3,44 @@ 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/hiccup-markdown@0.2.0...@thi.ng/hiccup-markdown@1.0.0) (2019-01-21) + + +### Bug Fixes + +* **hiccup-markdown:** re-export TagFactories interface ([b198c19](https://github.com/thi-ng/umbrella/commit/b198c19)) + + +### Build System + +* update package build scripts & outputs, imports in ~50 packages ([b54b703](https://github.com/thi-ng/umbrella/commit/b54b703)) + + +### BREAKING CHANGES + +* enabled multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols. + + + + + +# [0.2.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/hiccup-markdown@0.1.2...@thi.ng/hiccup-markdown@0.2.0) (2019-01-04) + + +### Features + +* **hiccup-markdown:** add & refactor markdown parser (from example), update docs ([35db07f](https://github.com/thi-ng/umbrella/commit/35db07f)) + + + + + ## [0.1.2](https://github.com/thi-ng/umbrella/compare/@thi.ng/hiccup-markdown@0.1.1...@thi.ng/hiccup-markdown@0.1.2) (2019-01-02) **Note:** Version bump only for package @thi.ng/hiccup-markdown diff --git a/packages/hiccup-markdown/README.md b/packages/hiccup-markdown/README.md index c06acd7117..dd5328cde5 100644 --- a/packages/hiccup-markdown/README.md +++ b/packages/hiccup-markdown/README.md @@ -10,10 +10,18 @@ This project is part of the - [About](#about) - - [Behaviors](#behaviors) - [Installation](#installation) - [Dependencies](#dependencies) -- [Usage examples](#usage-examples) +- [Parser](#parser) + - [Features](#features) + - [Limitations](#limitations) + - [Other parser features](#other-parser-features) + - [Serializing to HTML](#serializing-to-html) + - [Customizing tags](#customizing-tags) +- [Serializer](#serializer) + - [Features](#features-1) + - [Behaviors](#behaviors) + - [Usage examples](#usage-examples) - [Authors](#authors) - [License](#license) @@ -21,12 +29,164 @@ This project is part of the ## About -This package provides an extensible serializer of HTML-ish -[@thi.ng/hiccup](https://github.com/thi-ng/umbrella/tree/master/packages/hiccup) -trees to Markdown format. Currently supports most standard (applicable) -Markdown features: +This package provides both a customizable +[Markdown](https://en.wikipedia.org/wiki/Markdown)-to-[Hiccup](https://github.com/thi-ng/umbrella/tree/master/packages/hiccup) +parser and an extensible Hiccup-to-Markdown serializer. + +## Installation + +```bash +yarn add @thi.ng/hiccup-markdown +``` + +## Dependencies + +- [@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/errors](https://github.com/thi-ng/umbrella/tree/master/packages/errors) +- [@thi.ng/fsm](https://github.com/thi-ng/umbrella/tree/master/packages/fsm) +- [@thi.ng/hiccup](https://github.com/thi-ng/umbrella/tree/master/packages/hiccup) +- [@thi.ng/strings](https://github.com/thi-ng/umbrella/tree/master/packages/strings) + +## Parser + +**Try out the [Markdown editor demo](https://demo.thi.ng/umbrella/markdown/)** +([Source code](https://github.com/thi-ng/umbrella/tree/master/examples/markdown)) + +### Features + +The parser itself is not aimed at supporting **all** of Markdown's +quirky syntax features, but restricts itself to a sane subset of +features: + +| Feature | Comments | +|-------------|-----------------------------------------------------------------------------------------------------| +| Heading | ATX only (`#` line prefix), levels 1-6, then downgrade to paragraph | +| Paragraph | no support for `\` line breaks | +| Blockquote | Respects newlines | +| Format | **bold**, _emphasis_, `code`, ~~strikethrough~~ in paragraphs, headings, lists, blockquotes, tables | +| Link | no support for inline formats in label | +| Image | no image links | +| List | only unordered (`- ` line prefix), no nesting, supports line breaks | +| Table | no support for column alignment | +| Code block | GFM only (triple backtick prefix), w/ optional language hint | +| Horiz. Rule | only dash supported (e.g. `---`), min 3 chars required | + +Note: Currently, the last heading, paragraph, blockquote, list or table requires an additional newline. + +### Limitations + +These MD features (and probably many more) are **not** supported: + +- inline HTML +- nested inline formats (e.g. **bold** inside _italic_) +- inline formats within link labels +- image links +- footnotes +- link references +- nested / ordered / numbered / todo lists + +Some of these are considered, though currently not high priority... Pull +requests are welcome, though! + +### Other parser features + +- **Functional:** parser entirely built using + [transducers](https://github.com/thi-ng/umbrella/tree/master/packages/transducers) + & function composition. Use the parser in a transducer pipeline to + easily apply post-processing of the emitted results +- **Declarative:** parsing rules defined declaratively with only minimal + state/context handling needed +- **No regex:** consumes input character-wise and produces an iterator + of hiccup-style tree nodes, ready to be used with + [@thi.ng/hdom](https://github.com/thi-ng/umbrella/tree/master/packages/hdom), + [@thi.ng/hiccup](https://github.com/thi-ng/umbrella/tree/master/packages/hiccup) + or the serializer of this package for back conversion to MD +- **Customizable:** supports custom tag factory functions to override + default behavior / representation of each parsed result element +- **Fast (enough):** parses this markdown file (5.8KB) in ~5ms on MBP2016 / Chrome 71 +- **Small:** minified + gzipped ~2.6KB (parser sub-module incl. deps) + +### Serializing to HTML + +```ts +import { iterator } from "@thi.ng/transducers"; +import { serialize } from "@thi.ng/hiccup"; + +import { parse } from "@thi.ng/hiccup-markdown"; + +const src = ` +# Hello world + +[This](http://example.com) is a _test_. + +`; + +// convert to hiccup tree +[...iterator(parse(), src)] +// [ [ 'h1', ' Hello world ' ], +// [ 'p', +// [ 'a', { href: 'http://example.com' }, 'This' ], +// ' is a ', +// [ 'em', 'test' ], +// '. ' ] ] + +// or serialize to HTML +serialize(iterator(parse(), src)); + +//

Hello world

+``` + +### Customizing tags -- Headings (level 1-6) +The following interface defines factory functions for all supported +elements. User implementations / overrides can be given to the +`parse()` transducer to customize output. + +```ts +interface TagFactories { + blockquote(...children: any[]): any[]; + code(body: string): any[]; + codeblock(lang: string, body: string): any[]; + em(body: string): any[]; + heading(level, children: any[]): any[]; + hr(): any[]; + img(src: string, alt: string): any[]; + li(children: any[]): any[]; + link(href: string, body: string): any[]; + list(type: string, items: any[]): any[]; + paragraph(children: any[]): any[]; + strike(body: string): any[]; + strong(body: string): any[]; + table(rows: any[]): any[]; + td(i: number, children: any[]): any[]; + tr(i: number, cells: any[]): any[]; +} +``` + +Example with custom link elements: + +```ts +const tags = { + link: (href, body) => ["a.link.blue", { href }, body] +}; + +serialize(iterator(parse(tags), src)); + +//

Hello world

+//

This is a test.

+``` + +## Serializer + +For the reverse operation, the `serialize()` function can be used to +convert an hiccup component tree into Markdown. Currently supports most +standard (applicable) Markdown features: + +### Features + +- ATX-style headings (level 1-6) - Paragraphs - Forced line breaks - Inline styles: strong, italic, code @@ -47,9 +207,10 @@ Not (yet) supported: ### Behaviors -- Unless needed for serialization, all other element attribs are ignored -- Code blocks are always output in GFM w/ optional language hint (via - `lang` attrib) +- Unless needed for serialization, all other hiccup element attribs are + ignored +- Code blocks are always output in GFM flavor w/ optional language hint + (via `lang` attrib) - Images use the optional `alt` attrib as label - Forced line breaks are realized via `["br"]` elements in the hiccup tree @@ -61,21 +222,7 @@ implementation to the exported `serializeElement` [multi-method](https://github.com/thi-ng/umbrella/tree/master/packages/defmulti). See source code for reference. -## Installation - -```bash -yarn add @thi.ng/hiccup-markdown -``` - -## Dependencies - -- [@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/errors](https://github.com/thi-ng/umbrella/tree/master/packages/errors) -- [@thi.ng/hiccup](https://github.com/thi-ng/umbrella/tree/master/packages/hiccup) -- [@thi.ng/strings](https://github.com/thi-ng/umbrella/tree/master/packages/strings) - -## Usage examples +### Usage examples ```ts import { serialize } from "@thi.ng/hiccup-markdown"; diff --git a/packages/hiccup-markdown/package.json b/packages/hiccup-markdown/package.json index fac4c405c5..6e37750985 100644 --- a/packages/hiccup-markdown/package.json +++ b/packages/hiccup-markdown/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/hiccup-markdown", - "version": "0.1.2", + "version": "1.0.0", "description": "Markdown serialization of hiccup DOM trees", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,38 +14,46 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn run clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module hiccupMarkdown checks defmulti errors fsm hiccup strings transducers", + "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 run build && yarn publish --access public", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/checks": "^1.5.14", - "@thi.ng/defmulti": "^0.7.0", - "@thi.ng/errors": "^0.1.12", - "@thi.ng/hiccup": "^2.7.2", - "@thi.ng/strings": "^0.7.1" + "@thi.ng/checks": "^2.0.0", + "@thi.ng/defmulti": "^1.0.0", + "@thi.ng/errors": "^1.0.0", + "@thi.ng/fsm": "^1.0.0", + "@thi.ng/hiccup": "^3.0.0", + "@thi.ng/strings": "^1.0.0", + "@thi.ng/transducers": "^3.0.0" }, "keywords": [ "ES6", + "ast", "converter", "DOM", "hiccup", "markdown", + "parser", "serialize", + "transducers", "typescript" ], "publishConfig": { "access": "public" - } + }, + "sideEffects": false } diff --git a/packages/hiccup-markdown/src/api.ts b/packages/hiccup-markdown/src/api.ts new file mode 100644 index 0000000000..5a016f90c9 --- /dev/null +++ b/packages/hiccup-markdown/src/api.ts @@ -0,0 +1,18 @@ +export interface TagFactories { + blockquote(...children: any[]): any[]; + code(body: string): any[]; + codeblock(lang: string, body: string): any[]; + em(body: string): any[]; + heading(level, children: any[]): any[]; + hr(): any[]; + img(src: string, alt: string): any[]; + li(children: any[]): any[]; + link(href: string, body: string): any[]; + list(type: string, items: any[]): any[]; + paragraph(children: any[]): any[]; + strike(body: string): any[]; + strong(body: string): any[]; + table(rows: any[]): any[]; + td(i: number, children: any[]): any[]; + tr(i: number, cells: any[]): any[]; +} diff --git a/packages/hiccup-markdown/src/index.ts b/packages/hiccup-markdown/src/index.ts index 397bf0ebb3..6bfb5018e7 100644 --- a/packages/hiccup-markdown/src/index.ts +++ b/packages/hiccup-markdown/src/index.ts @@ -1,152 +1,3 @@ -import { implementsFunction } from "@thi.ng/checks/implements-function"; -import { isFunction } from "@thi.ng/checks/is-function"; -import { isNotStringAndIterable } from "@thi.ng/checks/is-not-string-iterable"; -import { isString } from "@thi.ng/checks/is-string"; -import { DEFAULT, defmulti, MultiFn3 } from "@thi.ng/defmulti"; -import { illegalArgs } from "@thi.ng/errors/illegal-arguments"; -import { normalize } from "@thi.ng/hiccup/serialize"; -import { repeat } from "@thi.ng/strings/repeat"; -import { wrap } from "@thi.ng/strings/wrap"; - -export const serialize = (tree: any, ctx) => - _serialize(tree, ctx, { indent: 0, sep: "" }); - -const _serialize = (tree: any, ctx, state) => { - if (tree == null) return ""; - if (Array.isArray(tree)) { - if (!tree.length) { - return ""; - } - let tag = tree[0]; - if (isFunction(tag)) { - return _serialize(tag.apply(null, [ctx, ...tree.slice(1)]), ctx, state); - } - if (implementsFunction(tag, "render")) { - return _serialize(tag.render.apply(null, [ctx, ...tree.slice(1)]), ctx, state); - } - if (isString(tag)) { - tree = normalize(tree); - const attribs = tree[1]; - if (attribs.__skip || attribs.__serialize === false) { - return ""; - } - tag = tree[0]; - return serializeElement(tree, ctx, state); - } - if (isNotStringAndIterable(tree)) { - return serializeIter(tree, ctx, state); - } - illegalArgs(`invalid tree node: ${tree}`); - } - if (isFunction(tree)) { - return _serialize(tree(ctx), ctx, state); - } - if (implementsFunction(tree, "toHiccup")) { - return _serialize(tree.toHiccup(ctx), ctx, state); - } - if (implementsFunction(tree, "deref")) { - return _serialize(tree.deref(), ctx, state); - } - if (isNotStringAndIterable(tree)) { - return serializeIter(tree, ctx, state); - } - return tree.toString(); -}; - -const serializeIter = ( - iter: Iterable, - ctx: any, - state: any -) => { - if (!iter) return ""; - const res = []; - for (let i of iter) { - res.push(_serialize(i, ctx, state)); - } - return res.join(state.sep); -}; - -const header = - (level) => - (el, ctx, state) => - repeat("#", level) + " " + body(el, ctx, state) + "\n\n"; - -const body = (el, ctx, state) => - serializeIter(el[2], ctx, state); - -export const serializeElement: MultiFn3 = defmulti((el) => el[0]); -serializeElement.add(DEFAULT, body); -serializeElement.add("h1", header(1)); -serializeElement.add("h2", header(2)); -serializeElement.add("h3", header(3)); -serializeElement.add("h4", header(4)); -serializeElement.add("h5", header(5)); -serializeElement.add("h6", header(6)); - -serializeElement.add("p", (el, ctx, state) => - `\n${body(el, ctx, state)}\n` -); - -serializeElement.add("img", (el) => - `![${el[1].alt || ""}](${el[1].src})` -); - -serializeElement.add("a", (el, ctx, state) => - `[${body(el, ctx, state)}](${el[1].href})` -); - -serializeElement.add("em", (el, ctx, state) => - `_${body(el, ctx, state)}_` -); - -serializeElement.add("strong", (el, ctx, state) => - `**${body(el, ctx, state)}**` -); - -serializeElement.add("pre", (el, ctx, state) => - `\n\`\`\`${el[1].lang || ""}\n${body(el, ctx, { ...state, pre: true, sep: "\n" })}\n\`\`\`\n` -); - -serializeElement.add("code", (el, ctx, state) => - state.pre ? - el[2][0] : - `\`${body(el, ctx, state)}\`` -); - -serializeElement.add("ul", (el, ctx, state) => { - const cstate = { - ...state, - indent: state.indent + 4, - sep: "\n" - }; - return wrap(state.indent === 0 ? "\n" : "")( - body(el, ctx, cstate) - ); -}); - -serializeElement.add("ol", (el, ctx, state) => { - const cstate = { - ...state, - indent: state.indent + 4, - id: 0, - sep: "\n" - }; - return wrap(state.indent === 0 ? "\n" : "")( - body(el, ctx, cstate) - ); -}); - -serializeElement.add("li", (el, ctx, state) => - repeat(" ", state.indent - 4) + - (state.id != null ? (++state.id) + "." : "-") + - " " + - body(el, ctx, { ...state, sep: "" }) -); - -serializeElement.add("blockquote", (el, ctx, state) => - `\n> ${body(el, ctx, state)}\n` -); - -serializeElement.add("br", () => "\\\n"); - -serializeElement.add("hr", () => "\n---\n"); +export * from "./api"; +export * from "./parse"; +export * from "./serialize"; diff --git a/packages/hiccup-markdown/src/parse.ts b/packages/hiccup-markdown/src/parse.ts new file mode 100644 index 0000000000..937537c9e8 --- /dev/null +++ b/packages/hiccup-markdown/src/parse.ts @@ -0,0 +1,402 @@ +import { + alts, + fsm, + not, + repeat, + ResultBody, + seq, + str, + until, + whitespace +} from "@thi.ng/fsm"; +import { peek } from "@thi.ng/transducers"; +import { TagFactories } from "./api"; + +type ParseResult = ResultBody; + +/** + * Parser state IDs + */ +const enum State { + BLOCKQUOTE, + CODE, + CODEBLOCK, + EMPHASIS, + END_BLOCKQUOTE, + END_LI, + END_PARA, + END_HEADING, + END_TABLE, + HEADING, + IMG, + LINK, + LI, + PARA, + START, + START_CODEBLOCK, + STRIKE, + STRONG, + TABLE, +} + +/** + * Parser context / state + */ +interface FSMCtx { + stack: any[]; + container?: any[]; + children?: any[]; + body?: string; + title?: string; + href?: string; + lang?: string; + hd?: number; +} + +/** + * Default hiccup element factories + */ +const DEFAULT_TAGS: TagFactories = { + blockquote: (...xs) => ["blockquote", ...xs], + code: (body) => ["code", body], + codeblock: (lang, body) => ["pre", { lang }, body], + em: (body) => ["em", body], + heading: (level, xs) => [level < 7 ? `h${level}` : "p", ...xs], + hr: () => ["hr"], + img: (src, alt) => ["img", { src, alt }], + li: (xs: any[]) => ["li", ...xs], + link: (href, body) => ["a", { href }, body], + list: (type, xs) => [type, ...xs], + paragraph: (xs) => ["p", ...xs], + strong: (body) => ["strong", body], + strike: (body) => ["del", body], + table: (rows) => ["table", ["tbody", ...rows]], + td: (_, xs) => ["td", ...xs], + tr: (_, xs) => ["tr", ...xs], +}; + +const BQUOTE = ">"; +const CODE = "`"; +const CODEBLOCK = "```"; +const CODEBLOCK_END = "\n```\n"; +const EM = "_"; +const HD = "#"; +const HR = "-"; +const IMG = "!["; +const LI = "- "; +const LINK_LABEL = "["; +const LINK_LABEL_END = "]"; +const LINK_HREF = "("; +const LINK_HREF_END = ")"; +const NL = "\n"; +const STRIKE = "~~"; +const STRONG = "**"; +const TD = "|"; + +// state / context handling helpers + +const transition = + (ctx: FSMCtx, id: State): ParseResult => ( + ctx.children = [], + ctx.body = "", + [id] + ); + +const push = + (id: State, next: State) => + (ctx: FSMCtx): ParseResult => ( + ctx.stack.push({ id, children: ctx.children.concat(ctx.body) }), + transition(ctx, next) + ); + +const pop = + (result) => + (ctx, body): ParseResult => { + const { id, children } = ctx.stack.pop(); + children.push(result(ctx, body)); + ctx.children = children; + ctx.body = ""; + return [id]; + }; + +const collectChildren = + (ctx: FSMCtx) => + (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 collectAndRestart = + (tag: (xs: any[]) => any[]) => + (ctx): ParseResult => + [State.START, [tag(collectChildren(ctx))]]; + +const collectBlockQuote = + (ctx): 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 collectLi = + (ctx: FSMCtx, tag: (xs: any[]) => any[]) => + 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)]] + ); + +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) + ), + transition(ctx, State.TABLE) + ); + +const collectTR = + (tag: (i: number, xs: any[]) => any[]) => + (ctx: FSMCtx) => { + const rows = peek(ctx.stack).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 rows = ctx.stack.pop().container; + rows.splice(1, 1); + return [State.START, [tag(rows)]]; + }; + +const collectInline = + (fn: (body: string) => any[]) => + pop((ctx, body: string) => fn(ctx.body + body.trim())); + +const heading = + (ctx: FSMCtx, body: string[]): ParseResult => ( + ctx.hd = body.length, + transition(ctx, State.HEADING) + ); + +const matchInline = + (id: State) => [ + str("![", push(id, State.IMG)), + str(LINK_LABEL, push(id, State.LINK)), + str(STRIKE, push(id, State.STRIKE)), + str(STRONG, push(id, State.STRONG)), + str(EM, push(id, State.EMPHASIS)), + str(CODE, push(id, State.CODE)) + ]; + +const matchLink = + (result: (href, body) => any[]) => + seq( + [ + until(LINK_LABEL_END, (ctx, body) => (ctx.title = body, null)), + str(LINK_HREF), + until(LINK_HREF_END, (ctx, body) => (ctx.href = body, null)), + ], + pop((ctx) => result(ctx.href, ctx.title)) + ); + +const matchPara = + (id: State, next: State) => + alts( + [ + ...matchInline(id), + str(NL, (ctx: FSMCtx) => (ctx.body += " ", [next])), + ], + collect(id), + ); + +const newPara = + (ctx: FSMCtx, buf: string[]): ParseResult => ( + ctx.body = buf.join(""), + ctx.children = [], + [State.PARA] + ); + +const newParaInline = + (next: State) => + (ctx: FSMCtx): ParseResult => ( + ctx.stack.push({ id: State.PARA, children: [] }), + transition(ctx, next) + ); + +const newParaCode = + (ctx: FSMCtx, x: string[]): ParseResult => ( + ctx.body = x[1], + ctx.stack.push({ id: State.PARA, children: [] }), + [State.CODE] + ); + +const newList = + (ctx: FSMCtx): ParseResult => ( + ctx.container = [], + transition(ctx, State.LI) + ); + +const newTable = + (ctx: FSMCtx) => ( + ctx.stack.push({ id: State.TABLE, container: [] }), + ctx.container = [], + transition(ctx, State.TABLE) + ); + +/** + * Main parser / transducer. Defines state map with the various Markdown + * 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 }; + return fsm( + { + [State.START]: + alts( + [ + whitespace(() => [State.START]), + repeat(str(HD), 1, Infinity, heading), + str(BQUOTE, (ctx) => transition(ctx, State.BLOCKQUOTE)), + str(LI, newList), + alts( + [ + seq([str(CODE), not(str(CODE))], newParaCode), + str(CODEBLOCK, () => [State.START_CODEBLOCK]) + ], + null, (_, next) => next + ), + seq( + [repeat(str(HR), 3, Infinity), str(NL)], + () => [State.START, [tags.hr()]] + ), + str(IMG, newParaInline(State.IMG)), + str(LINK_LABEL, newParaInline(State.LINK)), + str(STRONG, newParaInline(State.STRONG)), + str(STRIKE, newParaInline(State.STRIKE)), + str(EM, newParaInline(State.EMPHASIS)), + str(TD, newTable), + ], + newPara, + ), + + [State.PARA]: + matchPara(State.PARA, State.END_PARA), + + [State.END_PARA]: + alts( + [ + ...matchInline(State.PARA), + str(NL, collectAndRestart(tags.paragraph)), + ], + collect(State.PARA) + ), + + [State.BLOCKQUOTE]: + matchPara(State.BLOCKQUOTE, State.END_BLOCKQUOTE), + + [State.END_BLOCKQUOTE]: + alts( + [ + ...matchInline(State.BLOCKQUOTE), + str(BQUOTE, collectBlockQuote), + str(NL, collectAndRestart(tags.blockquote)), + ], + collect(State.BLOCKQUOTE) + ), + + [State.HEADING]: + matchPara(State.HEADING, State.END_HEADING), + + [State.END_HEADING]: + alts( + [ + ...matchInline(State.HEADING), + str(NL, collectHeading(tags.heading)), + ], + collect(State.HEADING) + ), + + [State.START_CODEBLOCK]: + until(NL, (ctx, lang) => (ctx.lang = lang, [State.CODEBLOCK])), + + [State.CODEBLOCK]: + until(CODEBLOCK_END, collectCodeBlock(tags.codeblock)), + + [State.LI]: + matchPara(State.LI, State.END_LI), + + [State.END_LI]: + alts( + [ + str(NL, collectList("ul", tags.list, tags.li)), + str(LI, (ctx) => (collectLi(ctx, tags.li), transition(ctx, State.LI))) + ], + collect(State.LI) + ), + + [State.LINK]: + matchLink(tags.link), + + [State.IMG]: + matchLink(tags.img), + + [State.STRONG]: + until(STRONG, collectInline(tags.strong)), + + [State.STRIKE]: + until(STRIKE, collectInline(tags.strike)), + + [State.EMPHASIS]: + until(EM, collectInline(tags.em)), + + [State.CODE]: + until(CODE, collectInline(tags.code)), + + [State.TABLE]: + alts( + [ + ...matchInline(State.TABLE), + str(TD, collectTD(tags.td)), + str(NL, collectTR(tags.tr)) + ], + collect(State.TABLE) + ), + + [State.END_TABLE]: + alts( + [ + str(NL, collectTable(tags.table)), + str(TD, () => [State.TABLE]) + ], + ) + }, + { stack: [] }, + State.START + ); +}; diff --git a/packages/hiccup-markdown/src/serialize.ts b/packages/hiccup-markdown/src/serialize.ts new file mode 100644 index 0000000000..96f516e3e8 --- /dev/null +++ b/packages/hiccup-markdown/src/serialize.ts @@ -0,0 +1,153 @@ +import { + implementsFunction, + isFunction, + isNotStringAndIterable, + isString +} from "@thi.ng/checks"; +import { DEFAULT, defmulti, MultiFn3 } from "@thi.ng/defmulti"; +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) => + _serialize(tree, ctx, { indent: 0, sep: "" }); + +const _serialize = (tree: any, ctx, state) => { + if (tree == null) return ""; + if (Array.isArray(tree)) { + if (!tree.length) { + return ""; + } + let tag = tree[0]; + if (isFunction(tag)) { + return _serialize(tag.apply(null, [ctx, ...tree.slice(1)]), ctx, state); + } + if (implementsFunction(tag, "render")) { + return _serialize(tag.render.apply(null, [ctx, ...tree.slice(1)]), ctx, state); + } + if (isString(tag)) { + tree = normalize(tree); + const attribs = tree[1]; + if (attribs.__skip || attribs.__serialize === false) { + return ""; + } + tag = tree[0]; + return serializeElement(tree, ctx, state); + } + if (isNotStringAndIterable(tree)) { + return serializeIter(tree, ctx, state); + } + illegalArgs(`invalid tree node: ${tree}`); + } + if (isFunction(tree)) { + return _serialize(tree(ctx), ctx, state); + } + if (implementsFunction(tree, "toHiccup")) { + return _serialize(tree.toHiccup(ctx), ctx, state); + } + if (implementsFunction(tree, "deref")) { + return _serialize(tree.deref(), ctx, state); + } + if (isNotStringAndIterable(tree)) { + return serializeIter(tree, ctx, state); + } + return tree.toString(); +}; + +const serializeIter = ( + iter: Iterable, + ctx: any, + state: any +) => { + if (!iter) return ""; + const res = []; + for (let i of iter) { + res.push(_serialize(i, ctx, state)); + } + return res.join(state.sep); +}; + +const header = + (level) => + (el, ctx, state) => + repeat("#", level) + " " + body(el, ctx, state) + "\n\n"; + +const body = (el, ctx, state) => + serializeIter(el[2], ctx, state); + +export const serializeElement: MultiFn3 = defmulti((el) => el[0]); +serializeElement.add(DEFAULT, body); +serializeElement.add("h1", header(1)); +serializeElement.add("h2", header(2)); +serializeElement.add("h3", header(3)); +serializeElement.add("h4", header(4)); +serializeElement.add("h5", header(5)); +serializeElement.add("h6", header(6)); + +serializeElement.add("p", (el, ctx, state) => + `\n${body(el, ctx, state)}\n` +); + +serializeElement.add("img", (el) => + `![${el[1].alt || ""}](${el[1].src})` +); + +serializeElement.add("a", (el, ctx, state) => + `[${body(el, ctx, state)}](${el[1].href})` +); + +serializeElement.add("em", (el, ctx, state) => + `_${body(el, ctx, state)}_` +); + +serializeElement.add("strong", (el, ctx, state) => + `**${body(el, ctx, state)}**` +); + +serializeElement.add("pre", (el, ctx, state) => + `\n\`\`\`${el[1].lang || ""}\n${body(el, ctx, { ...state, pre: true, sep: "\n" })}\n\`\`\`\n` +); + +serializeElement.add("code", (el, ctx, state) => + state.pre ? + el[2][0] : + `\`${body(el, ctx, state)}\`` +); + +serializeElement.add("ul", (el, ctx, state) => { + const cstate = { + ...state, + indent: state.indent + 4, + sep: "\n" + }; + return wrap(state.indent === 0 ? "\n" : "")( + body(el, ctx, cstate) + ); +}); + +serializeElement.add("ol", (el, ctx, state) => { + const cstate = { + ...state, + indent: state.indent + 4, + id: 0, + sep: "\n" + }; + return wrap(state.indent === 0 ? "\n" : "")( + body(el, ctx, cstate) + ); +}); + +serializeElement.add("li", (el, ctx, state) => + repeat(" ", state.indent - 4) + + (state.id != null ? (++state.id) + "." : "-") + + " " + + body(el, ctx, { ...state, sep: "" }) +); + +serializeElement.add("blockquote", (el, ctx, state) => + `\n> ${body(el, ctx, state)}\n` +); + +serializeElement.add("br", () => "\\\n"); + +serializeElement.add("hr", () => "\n---\n"); diff --git a/packages/hiccup-markdown/test/tsconfig.json b/packages/hiccup-markdown/test/tsconfig.json index bcf29ace54..2c9c12a650 100644 --- a/packages/hiccup-markdown/test/tsconfig.json +++ b/packages/hiccup-markdown/test/tsconfig.json @@ -1,10 +1,11 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", "../src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/hiccup-markdown/tsconfig.json b/packages/hiccup-markdown/tsconfig.json index bd6481a5a6..bcf03f18b4 100644 --- a/packages/hiccup-markdown/tsconfig.json +++ b/packages/hiccup-markdown/tsconfig.json @@ -1,9 +1,11 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/hiccup-svg/.npmignore b/packages/hiccup-svg/.npmignore index d703bda97a..67d0c55714 100644 --- a/packages/hiccup-svg/.npmignore +++ b/packages/hiccup-svg/.npmignore @@ -1,10 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/hiccup-svg/CHANGELOG.md b/packages/hiccup-svg/CHANGELOG.md index e131eaa00a..84f6e8a32b 100644 --- a/packages/hiccup-svg/CHANGELOG.md +++ b/packages/hiccup-svg/CHANGELOG.md @@ -3,6 +3,44 @@ 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/hiccup-svg@2.0.10...@thi.ng/hiccup-svg@3.0.0) (2019-01-21) + + +### Bug Fixes + +* **hiccup-svg:** convert path arc segment axis theta to degrees ([370f928](https://github.com/thi-ng/umbrella/commit/370f928)) + + +### Build System + +* update package build scripts & outputs, imports in ~50 packages ([b54b703](https://github.com/thi-ng/umbrella/commit/b54b703)) + + +### Features + +* **hiccup-svg:** add ellipse shape type, update convert() ([a39811c](https://github.com/thi-ng/umbrella/commit/a39811c)) +* **hiccup-svg:** add toHiccup() support in convertTree() ([e197f90](https://github.com/thi-ng/umbrella/commit/e197f90)) + + +### Reverts + +* **hiccup-svg:** undo merge mistake in convert.ts ([82f8ef2](https://github.com/thi-ng/umbrella/commit/82f8ef2)) + + +### BREAKING CHANGES + +* enabled multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols. + + + + + ## [2.0.10](https://github.com/thi-ng/umbrella/compare/@thi.ng/hiccup-svg@2.0.9...@thi.ng/hiccup-svg@2.0.10) (2018-12-20) **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 db8c978d28..1bc10d8ca2 100644 --- a/packages/hiccup-svg/package.json +++ b/packages/hiccup-svg/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/hiccup-svg", - "version": "2.0.10", + "version": "3.0.0", "description": "SVG element functions for @thi.ng/hiccup & @thi.ng/hdom", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,35 +14,42 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn run clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module hiccupSvg checks hiccup", + "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 run build && yarn publish --access public", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/hiccup": "^2.7.2" + "@thi.ng/checks": "^2.0.0", + "@thi.ng/hiccup": "^3.0.0" }, "keywords": [ "components", + "convert", "ES6", + "generator", "hiccup", "hdom", "SVG", + "serialize", "typescript", "UI", "visualization" ], "publishConfig": { "access": "public" - } + }, + "sideEffects": false } diff --git a/packages/hiccup-svg/src/circle.ts b/packages/hiccup-svg/src/circle.ts index bde7615028..a902c298d3 100644 --- a/packages/hiccup-svg/src/circle.ts +++ b/packages/hiccup-svg/src/circle.ts @@ -1,10 +1,11 @@ import { Vec2Like } from "./api"; import { ff } from "./format"; -export const circle = (p: Vec2Like, r: number, attribs?: any): any[] => - ["circle", { - cx: ff(p[0]), - cy: ff(p[1]), - r: ff(r), - ...attribs - }]; +export const circle = + (p: Vec2Like, r: number, attribs?: any): any[] => + ["circle", { + cx: ff(p[0]), + cy: ff(p[1]), + r: ff(r), + ...attribs + }]; diff --git a/packages/hiccup-svg/src/convert.ts b/packages/hiccup-svg/src/convert.ts index 9b409f3ed9..7fc5346d2e 100644 --- a/packages/hiccup-svg/src/convert.ts +++ b/packages/hiccup-svg/src/convert.ts @@ -1,8 +1,11 @@ -import { isArray } from "@thi.ng/checks/is-array"; -import { isArrayLike } from "@thi.ng/checks/is-arraylike"; - -import { PathSegment } from "./api"; +import { + implementsFunction, + isArray, + isArrayLike, + isString +} from "@thi.ng/checks"; import { circle } from "./circle"; +import { ellipse } from "./ellipse"; import { ff } from "./format"; import { linearGradient, radialGradient } from "./gradients"; import { image } from "./image"; @@ -10,6 +13,7 @@ import { hline, line, vline } from "./line"; import { path } from "./path"; import { points } from "./points"; import { polygon } from "./polygon"; +import { polyline } from "./polyline"; import { roundedRect } from "./rect"; import { text } from "./text"; @@ -32,157 +36,183 @@ const TEXT_ALIGN = { }; /** - * Takes a normalized hiccup tree of hdom-canvas shape definitions and - * recursively converts it into an hiccup flavor which is ready for SVG - * serialization. This conversion also involves translation & reorg of - * various attributes. Returns new tree. The original remains untouched, - * as will any unrecognized tree/shape nodes. + * Takes a normalized hiccup tree of thi.ng/geom or thi.ng/hdom-canvas + * shape definitions and recursively converts it into an hiccup flavor + * which is compatible for SVG serialization. This conversion also + * involves translation & reorg of various attributes. Returns new tree. + * The original remains untouched, as will any unrecognized tree/shape + * nodes. * * @param tree */ -export const convertTree = (tree: any[]): any[] => { - const type = tree[0]; - if (isArray(type)) { - return tree.map(convertTree); - } - let attribs = convertAttribs(tree[1]); - switch (tree[0]) { - case "svg": - case "defs": - case "g": { - const res: any[] = [type, attribs]; - for (let i = 2, n = tree.length; i < n; i++) { - const c = convertTree(tree[i]); - c != null && res.push(c); - } - return res; +export const convertTree = + (tree: any): any[] => { + if (implementsFunction(tree, "toHiccup")) { + return convertTree(tree.toHiccup()); } - case "linearGradient": - return linearGradient( - attribs.id, - attribs.from, - attribs.to, - tree[2], - { - gradientUnits: attribs.gradientUnits || "userSpaceOnUse", - gradientTransform: attribs.gradientTransform, - } - ); - case "radialGradient": - return radialGradient( - attribs.id, - attribs.from, - attribs.to, - attribs.r1, - attribs.r2, - tree[2], - { - gradientUnits: attribs.gradientUnits || "userSpaceOnUse", - gradientTransform: attribs.gradientTransform, + const type = tree[0]; + if (isArray(type)) { + return tree.map(convertTree); + } + let attribs = convertAttribs(tree[1]); + switch (tree[0]) { + case "svg": + case "defs": + case "g": { + const res: any[] = [type, attribs]; + for (let i = 2, n = tree.length; i < n; i++) { + const c = convertTree(tree[i]); + c != null && res.push(c); } - ); - case "circle": - return circle(tree[2], tree[3], attribs); - case "rect": { - const r = tree[5] || 0; - return roundedRect(tree[2], tree[3], tree[4], r, r, attribs); + return res; + } + case "linearGradient": + return linearGradient( + attribs.id, + attribs.from, + attribs.to, + tree[2], + { + gradientUnits: attribs.gradientUnits || "userSpaceOnUse", + gradientTransform: attribs.gradientTransform, + } + ); + case "radialGradient": + return radialGradient( + attribs.id, + attribs.from, + attribs.to, + attribs.r1, + attribs.r2, + tree[2], + { + gradientUnits: attribs.gradientUnits || "userSpaceOnUse", + gradientTransform: attribs.gradientTransform, + } + ); + case "circle": + return circle(tree[2], tree[3], attribs); + case "ellipse": + return ellipse(tree[2], tree[3][0], tree[3][1], attribs); + case "rect": { + const r = tree[5] || 0; + return roundedRect(tree[2], tree[3][0], tree[3][1], r, r, attribs); + } + case "line": + return line(tree[2], tree[3], attribs); + case "hline": + return hline(tree[2], attribs); + case "vline": + return vline(tree[2], attribs); + case "polyline": + return polyline(tree[2], attribs); + case "polygon": + return polygon(tree[2], attribs); + case "path": + return path(tree[2], attribs); + case "text": + return text(tree[2], tree[3], attribs); + case "img": + return image(tree[2], tree[3].src, attribs); + case "points": + return points(tree[2], attribs.shape, attribs.size, attribs); + default: + return tree; } - case "line": - return line(tree[2], tree[3], attribs); - case "hline": - return hline(tree[2], attribs); - case "vline": - return vline(tree[2], attribs); - case "polyline": - case "polygon": - return polygon(tree[2], attribs); - case "path": { - let segments: PathSegment[] = []; - for (let seg of tree[2]) { - switch (seg[0].toLowerCase()) { - case "s": - case "t": - // TODO compute reflected control point - // https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/d#Cubic_B%C3%A9zier_Curve - // https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/d#Quadratic_B%C3%A9zier_Curve + }; + +const convertAttribs = + (attribs: any) => { + const res: any = convertTransforms(attribs); + for (let id in attribs) { + const v = attribs[id]; + if (ATTRIB_ALIASES[id]) { + res[ATTRIB_ALIASES[id]] = v; + } else { + switch (id) { + case "fill": + case "stroke": + res[id] = v[0] === "$" ? `url(#${v.substr(1)})` : v; + break; + case "font": { + const i = v.indexOf(" "); + res["font-size"] = v.substr(0, i); + res["font-family"] = v.substr(i + 1); + break; + } + case "align": + res["text-anchor"] = TEXT_ALIGN[v]; + break; + case "baseline": + // no SVG support? + break; + case "filter": + // TODO needs to be translated into def first + // https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/filter + // https://developer.mozilla.org/en-US/docs/Web/SVG/Element/filter + break; + case "transform": + case "translate": + case "rotate": + case "scale": break; default: - segments.push(seg); + res[id] = v; } } - return path(segments, attribs); } - case "text": - return text(tree[2], tree[3], attribs); - case "img": - return image(tree[2], tree[3].src, attribs); - case "points": - return points(tree[2], attribs.shape, attribs.size, attribs); - default: - return tree; - } -}; + return res; + }; -const convertAttribs = (attribs: any) => { - const res: any = convertTransforms(attribs); - for (let id in attribs) { - const v = attribs[id]; - if (ATTRIB_ALIASES[id]) { - res[ATTRIB_ALIASES[id]] = v; - } else { - switch (id) { - case "fill": - case "stroke": - res[id] = v[0] === "$" ? `url(#${v.substr(1)})` : v; - break; - case "font": { - const i = v.indexOf(" "); - res["font-size"] = v.substr(0, i); - res["font-family"] = v.substr(i + 1); - break; +/** + * Converts any transformation related attribs, i.e. `transform`, + * `rotate`, `scale`, `translate`. If the element has a `transform` + * attrib, conversion of the other attribs will be skipped, else the + * values are assumed to be either strings or: + * + * - `transform`: Mat23 or 6-element numeric array + * - `translate`: 2-element array + * - `rotate`: number (angle in radians) + * - `scale`: number (uniform scale) or 2-elem array + * + * If no `transform` is given, the resulting transformation order will + * always be TRS. Any string values given will used as-is and therefore + * need to be complete, e.g. `{ rotate: "rotate(60)" }` + * + * @param attribs + */ +const convertTransforms = + (attribs: any) => { + const res: any = {}; + if (!attribs) return res; + let v: any; + if ((v = attribs.transform) || + attribs.translate || + attribs.scale || + attribs.rotate) { + if (v) { + res.transform = !isString(v) ? + `matrix(${[...v].map(ff).join(" ")})` : + v; + } else { + const tx: string[] = []; + if (v = attribs.translate) { + tx.push(isString(v) ? v : `translate(${ff(v[0])} ${ff(v[1])})`); } - case "align": - res["text-anchor"] = TEXT_ALIGN[v]; - break; - case "baseline": - // no SVG support? - case "filter": - // TODO needs to be translated into def first - // https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/filter - // https://developer.mozilla.org/en-US/docs/Web/SVG/Element/filter - case "transform": - case "translate": - case "rotate": - case "scale": - break; - default: - res[id] = v; + if (v = attribs.rotate) { + tx.push(isString(v) ? v : `rotate(${ff(v * 180 / Math.PI)})`); + } + if (v = attribs.scale) { + tx.push( + isString(v) ? + v : + isArrayLike(v) ? + `scale(${ff(v[0])} ${ff(v[1])})` : + `scale(${ff(v)})` + ); + } + res.transform = tx.join(" "); } } - } - return res; -}; - -const convertTransforms = (attribs: any) => { - const res: any = {}; - if (!attribs) return res; - let v: any; - if ((v = attribs.transform) || - attribs.translate || - attribs.scale || - attribs.rotate) { - - const tx: string[] = []; - (v = attribs.transform) && tx.push(`matrix(${[...v].map(ff).join(" ")})`); - (v = attribs.translate) && tx.push(`translate(${ff(v[0])} ${ff(v[1])})`); - (v = attribs.rotate) && tx.push(`rotate(${ff(v * 180 / Math.PI)})`); - (v = attribs.scale) && - tx.push( - isArrayLike(v) ? - `scale(${ff(v[0])} ${ff(v[1])})` : - `scale(${ff(v)})` - ); - res.transform = tx.join(" "); - } - return res; -}; + return res; + }; diff --git a/packages/hiccup-svg/src/defs.ts b/packages/hiccup-svg/src/defs.ts index fb03902b40..90966fb709 100644 --- a/packages/hiccup-svg/src/defs.ts +++ b/packages/hiccup-svg/src/defs.ts @@ -1,2 +1,3 @@ -export const defs = (...defs: any[]): any[] => - ["defs", {}, ...defs]; +export const defs = + (...defs: any[]): any[] => + ["defs", {}, ...defs]; diff --git a/packages/hiccup-svg/src/ellipse.ts b/packages/hiccup-svg/src/ellipse.ts new file mode 100644 index 0000000000..c5f6ec9668 --- /dev/null +++ b/packages/hiccup-svg/src/ellipse.ts @@ -0,0 +1,12 @@ +import { Vec2Like } from "./api"; +import { ff } from "./format"; + +export const ellipse = + (p: Vec2Like, rx: number, ry: number, attribs?: any): any[] => + ["ellipse", { + cx: ff(p[0]), + cy: ff(p[1]), + rx: ff(rx), + ry: ff(ry), + ...attribs + }]; diff --git a/packages/hiccup-svg/src/format.ts b/packages/hiccup-svg/src/format.ts index fd1359f41b..dceba79fbf 100644 --- a/packages/hiccup-svg/src/format.ts +++ b/packages/hiccup-svg/src/format.ts @@ -2,10 +2,14 @@ import { Vec2Like } from "./api"; let PRECISION = 2; -export const setPrecision = (n: number) => (PRECISION = n); +export const setPrecision = + (n: number) => (PRECISION = n); -export const ff = (x: number) => x.toFixed(PRECISION); +export const ff = + (x: number) => x.toFixed(PRECISION); -export const fpoint = (p: Vec2Like) => ff(p[0]) + "," + ff(p[1]); +export const fpoint = + (p: Vec2Like) => ff(p[0]) + "," + ff(p[1]); -export const fpoints = (pts: Vec2Like[], sep = " ") => pts ? pts.map(fpoint).join(sep) : ""; +export const fpoints = + (pts: Vec2Like[], sep = " ") => pts ? pts.map(fpoint).join(sep) : ""; diff --git a/packages/hiccup-svg/src/gradients.ts b/packages/hiccup-svg/src/gradients.ts index f754ab6fe1..cc2131f266 100644 --- a/packages/hiccup-svg/src/gradients.ts +++ b/packages/hiccup-svg/src/gradients.ts @@ -3,24 +3,26 @@ import { ff } from "./format"; const RE_ALPHA_COLOR = /(rgb|hsl)a\(([a-z0-9.-]+),([0-9.%]+),([0-9.%]+),([0-9.]+)\)/; -const gradient = (type: string, attribs: any, stops: GradientStop[]): any[] => - [ - type, - attribs, - ...stops.map(gradientStop) - ]; +const gradient = + (type: string, attribs: any, stops: GradientStop[]): any[] => + [ + type, + attribs, + ...stops.map(gradientStop) + ]; -const gradientStop = ([offset, col]: GradientStop) => { - // use stop-opacity attrib for safari compatibility - // https://stackoverflow.com/a/26220870/294515 - let opacity: string; - const parts = RE_ALPHA_COLOR.exec(col); - if (parts) { - col = `${parts[1]}(${parts[2]},${parts[3]},${parts[4]})`; - opacity = parts[5]; - } - return ["stop", { offset, "stop-color": col, "stop-opacity": opacity }]; -}; +const gradientStop = + ([offset, col]: GradientStop) => { + // use stop-opacity attrib for safari compatibility + // https://stackoverflow.com/a/26220870/294515 + let opacity: string; + const parts = RE_ALPHA_COLOR.exec(col); + if (parts) { + col = `${parts[1]}(${parts[2]},${parts[3]},${parts[4]})`; + opacity = parts[5]; + } + return ["stop", { offset, "stop-color": col, "stop-opacity": opacity }]; + }; export const linearGradient = ( id: string, diff --git a/packages/hiccup-svg/src/group.ts b/packages/hiccup-svg/src/group.ts index 3795760626..49129ef197 100644 --- a/packages/hiccup-svg/src/group.ts +++ b/packages/hiccup-svg/src/group.ts @@ -1,2 +1,3 @@ -export const group = (attr: any, ...body: any[]): any[] => - ["g", attr, ...body]; +export const group = + (attr: any, ...body: any[]): any[] => + ["g", attr, ...body]; diff --git a/packages/hiccup-svg/src/image.ts b/packages/hiccup-svg/src/image.ts index 02b18d907a..c3536c7aaf 100644 --- a/packages/hiccup-svg/src/image.ts +++ b/packages/hiccup-svg/src/image.ts @@ -1,10 +1,11 @@ import { Vec2Like } from "./api"; import { ff } from "./format"; -export const image = (pos: Vec2Like, url: string, attribs?: any): any[] => - ["image", { - // TODO replace w/ SVG2 `href` once Safari supports it - "xlink:href": url, - x: ff(pos[0]), y: ff(pos[1]), - ...attribs - }]; +export const image = + (pos: Vec2Like, url: string, attribs?: any): any[] => + ["image", { + // TODO replace w/ SVG2 `href` once Safari supports it + "xlink:href": url, + x: ff(pos[0]), y: ff(pos[1]), + ...attribs + }]; diff --git a/packages/hiccup-svg/src/line.ts b/packages/hiccup-svg/src/line.ts index 791009211d..de925124e1 100644 --- a/packages/hiccup-svg/src/line.ts +++ b/packages/hiccup-svg/src/line.ts @@ -1,17 +1,20 @@ import { Vec2Like } from "./api"; import { ff } from "./format"; -export const line = (a: Vec2Like, b: Vec2Like, attribs?: any): any[] => - ["line", { - x1: ff(a[0]), - y1: ff(a[1]), - x2: ff(b[0]), - y2: ff(b[1]), - ...attribs - }]; +export const line = + (a: Vec2Like, b: Vec2Like, attribs?: any): any[] => + ["line", { + x1: ff(a[0]), + y1: ff(a[1]), + x2: ff(b[0]), + y2: ff(b[1]), + ...attribs + }]; -export const hline = (y: number, attribs?: any) => - line([-1e6, y], [1e6, y], attribs); +export const hline = + (y: number, attribs?: any) => + line([-1e6, y], [1e6, y], attribs); -export const vline = (x: number, attribs?: any) => - line([x, -1e6], [x, 1e6], attribs); +export const vline = + (x: number, attribs?: any) => + line([x, -1e6], [x, 1e6], attribs); diff --git a/packages/hiccup-svg/src/path.ts b/packages/hiccup-svg/src/path.ts index daffdf041c..e47588cba5 100644 --- a/packages/hiccup-svg/src/path.ts +++ b/packages/hiccup-svg/src/path.ts @@ -1,35 +1,44 @@ import { PathSegment } from "./api"; import { ff, fpoint, fpoints } from "./format"; -export const path = (segments: PathSegment[], attribs?: any): any[] => { - let res = []; - for (let seg of segments) { - res.push(seg[0]); - switch (seg[0].toLowerCase()) { - case "a": - res.push([ - ff(seg[1]), - ff(seg[2]), - ff(seg[3]), - seg[4] ? 1 : 0, - seg[5] ? 1 : 0, - ff(seg[6][0]), - ff(seg[6][1]), - ].join(",")); - break; - case "h": - case "v": - res.push(ff(seg[1])); - break; - case "m": - case "l": - res.push(fpoint(seg[1])); - break; - case "z": - break; - default: - res.push(fpoints((seg).slice(1), ",")); +const DEG = 180 / Math.PI; + +export const path = + (segments: PathSegment[], attribs?: any): any[] => { + let res = []; + for (let seg of segments) { + res.push(seg[0]); + switch (seg[0].toLowerCase()) { + case "a": + res.push([ + // rx + ff(seg[1]), + // ry + ff(seg[2]), + // x-axis (theta) + ff(seg[3] * DEG), + // xl + seg[4] ? 1 : 0, + // clockwise + seg[5] ? 1 : 0, + // target xy + ff(seg[6][0]), + ff(seg[6][1]), + ].join(",")); + break; + case "h": + case "v": + res.push(ff(seg[1])); + break; + case "m": + case "l": + res.push(fpoint(seg[1])); + break; + case "z": + break; + default: + res.push(fpoints((seg).slice(1), ",")); + } } - } - return ["path", { ...attribs, d: res.join("") }]; -}; + return ["path", { ...attribs, d: res.join("") }]; + }; diff --git a/packages/hiccup-svg/src/points.ts b/packages/hiccup-svg/src/points.ts index bcf110be8d..9e27d618b5 100644 --- a/packages/hiccup-svg/src/points.ts +++ b/packages/hiccup-svg/src/points.ts @@ -12,24 +12,25 @@ import { ff } from "./format"; * @param size * @param attribs */ -export const points = (pts: Iterable, shape: string, size = 1, attribs?: any): any[] => { - const group = ["g", attribs]; - let href: string; - if (!shape || shape[0] !== "#") { - const r = ff(size); - href = "_" + ((Math.random() * 1e6) | 0).toString(36); - group.push(["g", { opacity: 0 }, - shape === "circle" ? - ["circle", { id: href, cx: 0, cy: 0, r: r }] : - ["rect", { id: href, x: 0, y: 0, width: r, height: r }] - ]); - href = "#" + href; - } else { - href = shape; - } - for (let p of pts) { - // TODO replace w/ SVG2 `href` once Safari supports it - group.push(["use", { "xlink:href": href, x: ff(p[0]), y: ff(p[1]) }]); - } - return group; -}; +export const points = + (pts: Iterable, shape: string, size = 1, attribs?: any): any[] => { + const group = ["g", attribs]; + let href: string; + if (!shape || shape[0] !== "#") { + const r = ff(size); + href = "_" + ((Math.random() * 1e6) | 0).toString(36); + group.push(["g", { opacity: 0 }, + shape === "circle" ? + ["circle", { id: href, cx: 0, cy: 0, r: r }] : + ["rect", { id: href, x: 0, y: 0, width: r, height: r }] + ]); + href = "#" + href; + } else { + href = shape; + } + for (let p of pts) { + // TODO replace w/ SVG2 `href` once Safari supports it + group.push(["use", { "xlink:href": href, x: ff(p[0]), y: ff(p[1]) }]); + } + return group; + }; diff --git a/packages/hiccup-svg/src/polygon.ts b/packages/hiccup-svg/src/polygon.ts index 566b13786a..f3b593ae2f 100644 --- a/packages/hiccup-svg/src/polygon.ts +++ b/packages/hiccup-svg/src/polygon.ts @@ -1,5 +1,6 @@ import { Vec2Like } from "./api"; import { fpoints } from "./format"; -export const polygon = (pts: Vec2Like[], attribs?: any): any[] => - ["polygon", { points: fpoints(pts), ...attribs }]; +export const polygon = + (pts: Vec2Like[], attribs?: any): any[] => + ["polygon", { points: fpoints(pts), ...attribs }]; diff --git a/packages/hiccup-svg/src/polyline.ts b/packages/hiccup-svg/src/polyline.ts index d27a056443..5ea000444a 100644 --- a/packages/hiccup-svg/src/polyline.ts +++ b/packages/hiccup-svg/src/polyline.ts @@ -1,5 +1,6 @@ import { Vec2Like } from "./api"; import { fpoints } from "./format"; -export const polyline = (pts: Vec2Like[], attribs?: any): any[] => - ["polyline", { points: fpoints(pts), ...attribs }]; +export const polyline = + (pts: Vec2Like[], attribs?: any): any[] => + ["polyline", { points: fpoints(pts), ...attribs }]; diff --git a/packages/hiccup-svg/src/rect.ts b/packages/hiccup-svg/src/rect.ts index 65decabbc3..81338dcd45 100644 --- a/packages/hiccup-svg/src/rect.ts +++ b/packages/hiccup-svg/src/rect.ts @@ -1,8 +1,9 @@ import { Vec2Like } from "./api"; import { ff } from "./format"; -export const rect = (p: Vec2Like, width: number, height: number, attribs?: any) => - roundedRect(p, width, height, 0, 0, attribs); +export const rect = + (p: Vec2Like, width: number, height: number, attribs?: any) => + roundedRect(p, width, height, 0, 0, attribs); export const roundedRect = ( p: Vec2Like, diff --git a/packages/hiccup-svg/src/svg.ts b/packages/hiccup-svg/src/svg.ts index ba20816ee1..365191fce6 100644 --- a/packages/hiccup-svg/src/svg.ts +++ b/packages/hiccup-svg/src/svg.ts @@ -1,4 +1,4 @@ -import { SVG_NS, XLINK_NS } from "@thi.ng/hiccup/api"; +import { SVG_NS, XLINK_NS } from "@thi.ng/hiccup"; /** * Defines an root element with default XML namespaces. By default @@ -8,10 +8,11 @@ import { SVG_NS, XLINK_NS } from "@thi.ng/hiccup/api"; * @param attribs * @param body */ -export const svg = (attribs: any, ...body: any[]): any[] => - ["svg", { - version: "1.1", - xmlns: SVG_NS, - "xmlns:xlink": XLINK_NS, - ...attribs - }, ...body]; +export const svg = + (attribs: any, ...body: any[]): any[] => + ["svg", { + version: "1.1", + xmlns: SVG_NS, + "xmlns:xlink": XLINK_NS, + ...attribs + }, ...body]; diff --git a/packages/hiccup-svg/src/text.ts b/packages/hiccup-svg/src/text.ts index b453a33c58..9ee29591f9 100644 --- a/packages/hiccup-svg/src/text.ts +++ b/packages/hiccup-svg/src/text.ts @@ -1,9 +1,10 @@ import { Vec2Like } from "./api"; import { ff } from "./format"; -export const text = (p: Vec2Like, body: string, attribs?: any): any[] => - ["text", { - x: ff(p[0]), - y: ff(p[1]), - ...attribs - }, body]; +export const text = + (p: Vec2Like, body: string, attribs?: any): any[] => + ["text", { + x: ff(p[0]), + y: ff(p[1]), + ...attribs + }, body]; diff --git a/packages/hiccup-svg/test/tsconfig.json b/packages/hiccup-svg/test/tsconfig.json index bcf29ace54..2c9c12a650 100644 --- a/packages/hiccup-svg/test/tsconfig.json +++ b/packages/hiccup-svg/test/tsconfig.json @@ -1,10 +1,11 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", "../src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/hiccup-svg/tsconfig.json b/packages/hiccup-svg/tsconfig.json index bd6481a5a6..bcf03f18b4 100644 --- a/packages/hiccup-svg/tsconfig.json +++ b/packages/hiccup-svg/tsconfig.json @@ -1,9 +1,11 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/hiccup/.npmignore b/packages/hiccup/.npmignore index d703bda97a..67d0c55714 100644 --- a/packages/hiccup/.npmignore +++ b/packages/hiccup/.npmignore @@ -1,10 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/hiccup/CHANGELOG.md b/packages/hiccup/CHANGELOG.md index 177698e40f..ff3a004dac 100644 --- a/packages/hiccup/CHANGELOG.md +++ b/packages/hiccup/CHANGELOG.md @@ -3,6 +3,28 @@ 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/hiccup@2.7.2...@thi.ng/hiccup@3.0.0) (2019-01-21) + + +### Build System + +* update package build scripts & outputs, imports in ~50 packages ([b54b703](https://github.com/thi-ng/umbrella/commit/b54b703)) + + +### BREAKING CHANGES + +* enabled multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols. + + + + + ## [2.7.2](https://github.com/thi-ng/umbrella/compare/@thi.ng/hiccup@2.7.1...@thi.ng/hiccup@2.7.2) (2018-12-20) **Note:** Version bump only for package @thi.ng/hiccup diff --git a/packages/hiccup/package.json b/packages/hiccup/package.json index 9f8bfdc599..8abd498f15 100644 --- a/packages/hiccup/package.json +++ b/packages/hiccup/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/hiccup", - "version": "2.7.2", + "version": "3.0.0", "description": "HTML/SVG/XML serialization of nested data structures, iterables & closures", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,25 +14,27 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module hiccup checks errors", + "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", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { - "@thi.ng/atom": "^1.5.8", + "@thi.ng/atom": "^2.0.0", "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/checks": "^1.5.14", - "@thi.ng/errors": "^0.1.12" + "@thi.ng/checks": "^2.0.0", + "@thi.ng/errors": "^1.0.0" }, "keywords": [ "clojure", @@ -48,5 +52,6 @@ ], "publishConfig": { "access": "public" - } + }, + "sideEffects": false } diff --git a/packages/hiccup/src/css.ts b/packages/hiccup/src/css.ts index dee596eb47..afb0f76a07 100644 --- a/packages/hiccup/src/css.ts +++ b/packages/hiccup/src/css.ts @@ -1,4 +1,4 @@ -import { isFunction } from "@thi.ng/checks/is-function"; +import { isFunction } from "@thi.ng/checks"; export const css = (rules: any) => { diff --git a/packages/hiccup/src/deref.ts b/packages/hiccup/src/deref.ts index b6b18427a6..76bf890fc3 100644 --- a/packages/hiccup/src/deref.ts +++ b/packages/hiccup/src/deref.ts @@ -1,4 +1,4 @@ -import { implementsFunction } from "@thi.ng/checks/implements-function"; +import { implementsFunction } from "@thi.ng/checks"; /** * Takes an arbitrary `ctx` object and array of `keys`. Attempts to call diff --git a/packages/hiccup/src/serialize.ts b/packages/hiccup/src/serialize.ts index a776ef49d2..801be8ac6d 100644 --- a/packages/hiccup/src/serialize.ts +++ b/packages/hiccup/src/serialize.ts @@ -1,9 +1,11 @@ -import { implementsFunction } from "@thi.ng/checks/implements-function"; -import { isFunction } from "@thi.ng/checks/is-function"; -import { isNotStringAndIterable } from "@thi.ng/checks/is-not-string-iterable"; -import { isPlainObject } from "@thi.ng/checks/is-plain-object"; -import { isString } from "@thi.ng/checks/is-string"; -import { illegalArgs } from "@thi.ng/errors/illegal-arguments"; +import { + implementsFunction, + isFunction, + isNotStringAndIterable, + isPlainObject, + isString +} from "@thi.ng/checks"; +import { illegalArgs } from "@thi.ng/errors"; import { COMMENT, NO_SPANS, diff --git a/packages/hiccup/test/tsconfig.json b/packages/hiccup/test/tsconfig.json index 13d45669e5..2c9c12a650 100644 --- a/packages/hiccup/test/tsconfig.json +++ b/packages/hiccup/test/tsconfig.json @@ -1,7 +1,8 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", diff --git a/packages/hiccup/tsconfig.json b/packages/hiccup/tsconfig.json index f6c291a0a0..bcf03f18b4 100644 --- a/packages/hiccup/tsconfig.json +++ b/packages/hiccup/tsconfig.json @@ -1,7 +1,9 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" diff --git a/packages/iges/.npmignore b/packages/iges/.npmignore index d703bda97a..67d0c55714 100644 --- a/packages/iges/.npmignore +++ b/packages/iges/.npmignore @@ -1,10 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/iges/CHANGELOG.md b/packages/iges/CHANGELOG.md index 0a66d5283c..c7855c10f5 100644 --- a/packages/iges/CHANGELOG.md +++ b/packages/iges/CHANGELOG.md @@ -3,6 +3,28 @@ 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/iges@0.2.30...@thi.ng/iges@1.0.0) (2019-01-21) + + +### Build System + +* update package build scripts & outputs, imports in ~50 packages ([b54b703](https://github.com/thi-ng/umbrella/commit/b54b703)) + + +### BREAKING CHANGES + +* enabled multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols. + + + + + ## [0.2.30](https://github.com/thi-ng/umbrella/compare/@thi.ng/iges@0.2.29...@thi.ng/iges@0.2.30) (2019-01-02) **Note:** Version bump only for package @thi.ng/iges diff --git a/packages/iges/package.json b/packages/iges/package.json index 527316b229..b488c84179 100644 --- a/packages/iges/package.json +++ b/packages/iges/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/iges", - "version": "0.2.30", + "version": "1.0.0", "description": "IGES 5.3 serializer for (currently only) polygonal geometry, both open & closed", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,26 +14,28 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn run clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module iges api defmulti strings transducers", + "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 run build && yarn publish --access public", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/api": "^4.2.4", - "@thi.ng/defmulti": "^0.7.0", - "@thi.ng/strings": "^0.7.1", - "@thi.ng/transducers": "^2.3.2" + "@thi.ng/api": "^5.0.0", + "@thi.ng/defmulti": "^1.0.0", + "@thi.ng/strings": "^1.0.0", + "@thi.ng/transducers": "^3.0.0" }, "keywords": [ "CAD", @@ -44,5 +48,6 @@ ], "publishConfig": { "access": "public" - } + }, + "sideEffects": false } diff --git a/packages/iges/src/index.ts b/packages/iges/src/index.ts index ad47f45b24..0323c74ba3 100644 --- a/packages/iges/src/index.ts +++ b/packages/iges/src/index.ts @@ -1,16 +1,16 @@ import { defmulti } from "@thi.ng/defmulti"; -import { float } from "@thi.ng/strings/float"; -import { padLeft } from "@thi.ng/strings/pad-left"; -import { padRight } from "@thi.ng/strings/pad-right"; -import { comp } from "@thi.ng/transducers/func/comp"; -import { wrap } from "@thi.ng/transducers/iter/wrap"; -import { push } from "@thi.ng/transducers/rfn/push"; -import { transduce } from "@thi.ng/transducers/transduce"; -import { map } from "@thi.ng/transducers/xform/map"; -import { mapIndexed } from "@thi.ng/transducers/xform/map-indexed"; -import { mapcat } from "@thi.ng/transducers/xform/mapcat"; -import { partition } from "@thi.ng/transducers/xform/partition"; -import { wordWrap } from "@thi.ng/transducers/xform/word-wrap"; +import { float, padLeft, padRight } from "@thi.ng/strings"; +import { + comp, + map, + mapcat, + mapIndexed, + partition, + push, + transduce, + wordWrap, + wrap +} from "@thi.ng/transducers"; import { DEFAULT_GLOBALS, DictEntry, diff --git a/packages/iges/test/tsconfig.json b/packages/iges/test/tsconfig.json index bcf29ace54..2c9c12a650 100644 --- a/packages/iges/test/tsconfig.json +++ b/packages/iges/test/tsconfig.json @@ -1,10 +1,11 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", "../src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/iges/tsconfig.json b/packages/iges/tsconfig.json index bd6481a5a6..bcf03f18b4 100644 --- a/packages/iges/tsconfig.json +++ b/packages/iges/tsconfig.json @@ -1,9 +1,11 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/interceptors/.npmignore b/packages/interceptors/.npmignore index d703bda97a..67d0c55714 100644 --- a/packages/interceptors/.npmignore +++ b/packages/interceptors/.npmignore @@ -1,10 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/interceptors/CHANGELOG.md b/packages/interceptors/CHANGELOG.md index 1422eddafe..7402e9341d 100644 --- a/packages/interceptors/CHANGELOG.md +++ b/packages/interceptors/CHANGELOG.md @@ -3,6 +3,28 @@ 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/interceptors@1.9.2...@thi.ng/interceptors@2.0.0) (2019-01-21) + + +### Build System + +* update package build scripts & outputs, imports in ~50 packages ([b54b703](https://github.com/thi-ng/umbrella/commit/b54b703)) + + +### BREAKING CHANGES + +* enabled multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols. + + + + + ## [1.9.2](https://github.com/thi-ng/umbrella/compare/@thi.ng/interceptors@1.9.1...@thi.ng/interceptors@1.9.2) (2018-12-15) **Note:** Version bump only for package @thi.ng/interceptors diff --git a/packages/interceptors/package.json b/packages/interceptors/package.json index afeb94fa89..ab184f010d 100644 --- a/packages/interceptors/package.json +++ b/packages/interceptors/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/interceptors", - "version": "1.9.2", + "version": "2.0.0", "description": "Interceptor based event bus, side effect & immutable state handling", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,27 +14,29 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn run clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module interceptors api atom checks errors paths", + "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 run build && yarn publish --access public", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/api": "^4.2.4", - "@thi.ng/atom": "^1.5.8", - "@thi.ng/checks": "^1.5.14", - "@thi.ng/errors": "^0.1.12", - "@thi.ng/paths": "^1.6.6" + "@thi.ng/api": "^5.0.0", + "@thi.ng/atom": "^2.0.0", + "@thi.ng/checks": "^2.0.0", + "@thi.ng/errors": "^1.0.0", + "@thi.ng/paths": "^2.0.0" }, "keywords": [ "ES6", @@ -40,5 +44,6 @@ ], "publishConfig": { "access": "public" - } + }, + "sideEffects": false } diff --git a/packages/interceptors/src/api.ts b/packages/interceptors/src/api.ts index 94718cd81a..f95cb5f824 100644 --- a/packages/interceptors/src/api.ts +++ b/packages/interceptors/src/api.ts @@ -1,4 +1,4 @@ -import { ReadonlyAtom } from "@thi.ng/atom/api"; +import { ReadonlyAtom } from "@thi.ng/atom"; export type InterceptorFn = (state: any, e: Event, bus?: IDispatch, ctx?: InterceptorContext) => InterceptorContext | void; export type InterceptorPredicate = (state: any, e: Event, bus?: IDispatch, ctx?: InterceptorContext) => boolean; diff --git a/packages/interceptors/src/event-bus.ts b/packages/interceptors/src/event-bus.ts index ce00512b2c..8fd413b629 100644 --- a/packages/interceptors/src/event-bus.ts +++ b/packages/interceptors/src/event-bus.ts @@ -1,13 +1,13 @@ -import { IDeref, IObjectOf } from "@thi.ng/api/api"; -import { IAtom } from "@thi.ng/atom/api"; -import { Atom } from "@thi.ng/atom/atom"; -import { implementsFunction } from "@thi.ng/checks/implements-function"; -import { isArray } from "@thi.ng/checks/is-array"; -import { isFunction } from "@thi.ng/checks/is-function"; -import { isPromise } from "@thi.ng/checks/is-promise"; -import { illegalArgs } from "@thi.ng/errors/illegal-arguments"; +import { IDeref, IObjectOf } from "@thi.ng/api"; +import { Atom, IAtom } from "@thi.ng/atom"; +import { + implementsFunction, + isArray, + isFunction, + isPromise +} 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; diff --git a/packages/interceptors/src/interceptors.ts b/packages/interceptors/src/interceptors.ts index e085687a4d..6361d7c5f4 100644 --- a/packages/interceptors/src/interceptors.ts +++ b/packages/interceptors/src/interceptors.ts @@ -14,7 +14,6 @@ import { InterceptorPredicate } from "./api"; - /** * Debug interceptor to log the current event to the console. */ diff --git a/packages/interceptors/test/tsconfig.json b/packages/interceptors/test/tsconfig.json index bcf29ace54..2c9c12a650 100644 --- a/packages/interceptors/test/tsconfig.json +++ b/packages/interceptors/test/tsconfig.json @@ -1,10 +1,11 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", "../src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/interceptors/tsconfig.json b/packages/interceptors/tsconfig.json index bd6481a5a6..bcf03f18b4 100644 --- a/packages/interceptors/tsconfig.json +++ b/packages/interceptors/tsconfig.json @@ -1,9 +1,11 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/intervals/.npmignore b/packages/intervals/.npmignore index ec83d74c9d..67d0c55714 100644 --- a/packages/intervals/.npmignore +++ b/packages/intervals/.npmignore @@ -1,11 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc -export src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/intervals/CHANGELOG.md b/packages/intervals/CHANGELOG.md index 85cca15c44..423e18d0f7 100644 --- a/packages/intervals/CHANGELOG.md +++ b/packages/intervals/CHANGELOG.md @@ -3,6 +3,28 @@ 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/intervals@0.2.0...@thi.ng/intervals@1.0.0) (2019-01-21) + + +### Build System + +* update package build scripts & outputs, imports in ~50 packages ([b54b703](https://github.com/thi-ng/umbrella/commit/b54b703)) + + +### BREAKING CHANGES + +* enabled multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols. + + + + + # [0.2.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/intervals@0.1.0...@thi.ng/intervals@0.2.0) (2018-12-19) diff --git a/packages/intervals/package.json b/packages/intervals/package.json index 23d375080a..5a24e48e5f 100644 --- a/packages/intervals/package.json +++ b/packages/intervals/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/intervals", - "version": "0.2.0", + "version": "1.0.0", "description": "Closed/open/semi-open interval data type, queries & operations", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,24 +14,26 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn run clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module intervals api errors", + "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 run build && yarn publish --access public", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/api": "^4.2.4", - "@thi.ng/errors": "^0.1.12" + "@thi.ng/api": "^5.0.0", + "@thi.ng/errors": "^1.0.0" }, "keywords": [ "ES6", @@ -45,5 +49,6 @@ ], "publishConfig": { "access": "public" - } + }, + "sideEffects": false } diff --git a/packages/intervals/src/index.ts b/packages/intervals/src/index.ts index 9b3abe4ae7..72568bc93f 100644 --- a/packages/intervals/src/index.ts +++ b/packages/intervals/src/index.ts @@ -1,5 +1,11 @@ -import { ICopy, IEquiv, IContains, Fn, ICompare } from "@thi.ng/api/api"; -import { illegalArgs } from "@thi.ng/errors/illegal-arguments"; +import { + Fn, + ICompare, + IContains, + ICopy, + IEquiv +} from "@thi.ng/api"; +import { illegalArgs } from "@thi.ng/errors"; export const enum Classifier { DISJOINT_LEFT, diff --git a/packages/intervals/test/tsconfig.json b/packages/intervals/test/tsconfig.json index bcf29ace54..2c9c12a650 100644 --- a/packages/intervals/test/tsconfig.json +++ b/packages/intervals/test/tsconfig.json @@ -1,10 +1,11 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", "../src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/intervals/tsconfig.json b/packages/intervals/tsconfig.json index bd6481a5a6..bcf03f18b4 100644 --- a/packages/intervals/tsconfig.json +++ b/packages/intervals/tsconfig.json @@ -1,9 +1,11 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/iterators/.npmignore b/packages/iterators/.npmignore index d703bda97a..67d0c55714 100644 --- a/packages/iterators/.npmignore +++ b/packages/iterators/.npmignore @@ -1,10 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/iterators/CHANGELOG.md b/packages/iterators/CHANGELOG.md index d3189930c0..d9d7574138 100644 --- a/packages/iterators/CHANGELOG.md +++ b/packages/iterators/CHANGELOG.md @@ -3,6 +3,28 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [5.0.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/iterators@4.2.4...@thi.ng/iterators@5.0.0) (2019-01-21) + + +### Build System + +* update package build scripts & outputs, imports in ~50 packages ([b54b703](https://github.com/thi-ng/umbrella/commit/b54b703)) + + +### BREAKING CHANGES + +* enabled multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols. + + + + + ## [4.2.4](https://github.com/thi-ng/umbrella/compare/@thi.ng/iterators@4.2.3...@thi.ng/iterators@4.2.4) (2019-01-02) **Note:** Version bump only for package @thi.ng/iterators diff --git a/packages/iterators/README.md b/packages/iterators/README.md index c027d8c14a..dc2896e8e5 100644 --- a/packages/iterators/README.md +++ b/packages/iterators/README.md @@ -29,7 +29,7 @@ case*, whereas function names are in *Camel case*. // import all import * as ti from "@thi.ng/iterators"; // single function (ES6 / TS) -import { partitionBy } from "@thi.ng/iterators/partition-by"; +import { partitionBy } from "@thi.ng/iterators"; ``` ## Dependencies diff --git a/packages/iterators/package.json b/packages/iterators/package.json index 4e03af5d71..f59521f120 100644 --- a/packages/iterators/package.json +++ b/packages/iterators/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/iterators", - "version": "4.2.4", + "version": "5.0.0", "description": "clojure.core inspired, composable ES6 iterators & generators", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,25 +14,27 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module iterators api dcons errors", + "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", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/api": "^4.2.4", - "@thi.ng/dcons": "^1.1.23", - "@thi.ng/errors": "^0.1.12" + "@thi.ng/api": "^5.0.0", + "@thi.ng/dcons": "^2.0.0", + "@thi.ng/errors": "^1.0.0" }, "keywords": [ "clojure", @@ -45,5 +49,6 @@ ], "publishConfig": { "access": "public" - } + }, + "sideEffects": false } diff --git a/packages/iterators/src/cached.ts b/packages/iterators/src/cached.ts index c979d7e73e..6a8057d7aa 100644 --- a/packages/iterators/src/cached.ts +++ b/packages/iterators/src/cached.ts @@ -1,27 +1,28 @@ import { iterator } from "./iterator"; -export function cached(input: Iterable) { - let cache: T[] = []; - let iter = iterator(input); - let done = false; - return function () { - let i = 0; - return { - [Symbol.iterator](): IterableIterator { return this; }, - next(): IteratorResult { - if (i < cache.length) { - return { done: false, value: cache[i++] }; - } else if (!done) { - let v = iter.next(); - if (!v.done) { - i++; - cache.push(v.value); - return { done: false, value: v.value }; +export const cached = + (input: Iterable) => { + let cache: T[] = []; + let iter = iterator(input); + let done = false; + return function () { + let i = 0; + return { + [Symbol.iterator](): IterableIterator { return this; }, + next(): IteratorResult { + if (i < cache.length) { + return { done: false, value: cache[i++] }; + } else if (!done) { + let v = iter.next(); + if (!v.done) { + i++; + cache.push(v.value); + return { done: false, value: v.value }; + } + done = true; } - done = true; + return { done, value: undefined }; } - return { done, value: undefined }; - } + }; }; }; -} diff --git a/packages/iterators/src/constantly.ts b/packages/iterators/src/constantly.ts index dfd4499078..101e2ed56f 100644 --- a/packages/iterators/src/constantly.ts +++ b/packages/iterators/src/constantly.ts @@ -1,3 +1,3 @@ -export function constantly(x: T): (...args: any[]) => T { - return () => x; -} +export const constantly = + (x: T): (...args: any[]) => T => + () => x; diff --git a/packages/iterators/src/consume.ts b/packages/iterators/src/consume.ts index 37bc6f85dc..3f8f59af16 100644 --- a/packages/iterators/src/consume.ts +++ b/packages/iterators/src/consume.ts @@ -1,4 +1,5 @@ -export function consume(iter: Iterator, n = Infinity) { - while (n-- > 0 && !iter.next().done) { } - return iter; -} +export const consume = + (iter: Iterator, n = Infinity) => { + while (n-- > 0 && !iter.next().done) { } + return iter; + }; diff --git a/packages/iterators/src/dedupe-with.ts b/packages/iterators/src/dedupe-with.ts index 7e3f603e24..45a6431d57 100644 --- a/packages/iterators/src/dedupe-with.ts +++ b/packages/iterators/src/dedupe-with.ts @@ -1,5 +1,4 @@ -import { Predicate2 } from "@thi.ng/api/api"; - +import { Predicate2 } from "@thi.ng/api"; import { iterator } from "./iterator"; export function* dedupeWith(equiv: Predicate2, input: Iterable) { diff --git a/packages/iterators/src/dense.ts b/packages/iterators/src/dense.ts index d62cd06de3..d56d80a956 100644 --- a/packages/iterators/src/dense.ts +++ b/packages/iterators/src/dense.ts @@ -1,5 +1,5 @@ import { filter } from "./filter"; -export function dense(input: Iterable) { - return filter(x => x != null, input); -} +export const dense = + (input: Iterable) => + filter(x => x != null, input); diff --git a/packages/iterators/src/drop-while.ts b/packages/iterators/src/drop-while.ts index b3711238b1..21d94b41c7 100644 --- a/packages/iterators/src/drop-while.ts +++ b/packages/iterators/src/drop-while.ts @@ -1,5 +1,4 @@ -import { Predicate } from "@thi.ng/api/api"; - +import { Predicate } from "@thi.ng/api"; import { ensureIterator } from "./ensure"; export function* dropWhile(pred: Predicate, input: Iterable) { diff --git a/packages/iterators/src/ensure.ts b/packages/iterators/src/ensure.ts index d56748c40e..6dfe8a38f1 100644 --- a/packages/iterators/src/ensure.ts +++ b/packages/iterators/src/ensure.ts @@ -1,14 +1,11 @@ -import { illegalArgs } from "@thi.ng/errors/illegal-arguments"; - +import { illegalArgs } from "@thi.ng/errors"; import { iterator } from "./iterator"; -export function ensureIterable(x: any): IterableIterator { - if (!(x != null && x[Symbol.iterator])) { - illegalArgs(`value is not iterable: ${x}`); - } - return x; -} +export const ensureIterable = + (x: any): IterableIterator => + (!(x != null && x[Symbol.iterator])) ? + illegalArgs(`value is not iterable: ${x}`) : + x; -export function ensureIterator(x: any) { - return ensureIterable(iterator(x)); -} +export const ensureIterator = + (x: any) => ensureIterable(iterator(x)); diff --git a/packages/iterators/src/every.ts b/packages/iterators/src/every.ts index 4149542b83..c63a6cfe98 100644 --- a/packages/iterators/src/every.ts +++ b/packages/iterators/src/every.ts @@ -1,16 +1,16 @@ -import { Predicate } from "@thi.ng/api/api"; - +import { Predicate } from "@thi.ng/api"; import { iterator } from "./iterator"; -export function every(pred: Predicate, input: Iterable) { - let iter = iterator(input); - let v: IteratorResult; - let empty = true; - while (((v = iter.next()), !v.done)) { - if (pred(v.value) !== true) { - return false; +export const every = + (pred: Predicate, input: Iterable) => { + let iter = iterator(input); + let v: IteratorResult; + let empty = true; + while (((v = iter.next()), !v.done)) { + if (pred(v.value) !== true) { + return false; + } + empty = false; } - empty = false; - } - return !empty; -} + return !empty; + }; diff --git a/packages/iterators/src/filter.ts b/packages/iterators/src/filter.ts index 91b41b5332..566c288ee5 100644 --- a/packages/iterators/src/filter.ts +++ b/packages/iterators/src/filter.ts @@ -1,5 +1,4 @@ -import { Predicate } from "@thi.ng/api/api"; - +import { Predicate } from "@thi.ng/api"; import { iterator } from "./iterator"; export function* filter(pred: Predicate, input: Iterable) { diff --git a/packages/iterators/src/flatten.ts b/packages/iterators/src/flatten.ts index 6ab857b428..8f11f1ff2a 100644 --- a/packages/iterators/src/flatten.ts +++ b/packages/iterators/src/flatten.ts @@ -2,13 +2,13 @@ import { flattenWith } from "./flatten-with"; import { maybeIterator } from "./iterator"; import { maybeObjectIterator } from "./object-iterator"; -export function flatten(input: Iterable, includeObjects = true) { - return flattenWith( - (x) => - (typeof x !== "string" && - (maybeIterator(x) || - (includeObjects && maybeObjectIterator(x)))) || - undefined, - input - ); -} +export const flatten = + (input: Iterable, includeObjects = true) => + flattenWith( + (x) => + (typeof x !== "string" && + (maybeIterator(x) || + (includeObjects && maybeObjectIterator(x)))) || + undefined, + input + ); diff --git a/packages/iterators/src/fnil.ts b/packages/iterators/src/fnil.ts index a0643a91ae..2564d156f5 100644 --- a/packages/iterators/src/fnil.ts +++ b/packages/iterators/src/fnil.ts @@ -1,39 +1,40 @@ import { illegalArity } from "@thi.ng/errors"; -export function fnil(fn: (...args: any[]) => any, ...ctors: (() => any)[]) { - let [cta, ctb, ctc] = ctors; - switch (ctors.length) { - case 1: - return (...args: any[]) => { - if (args[0] == null) { - args[0] = cta(); - } - return fn.apply(null, args); - }; - case 2: - return (...args: any[]) => { - if (args[0] == null) { - args[0] = cta(); - } - if (args[1] == null) { - args[1] = ctb(); - } - return fn.apply(null, args); - }; - case 3: - return (...args: any[]) => { - if (args[0] == null) { - args[0] = cta(); - } - if (args[1] == null) { - args[1] = ctb(); - } - if (args[2] == null) { - args[2] = ctc(); - } - return fn.apply(null, args); - }; - default: - illegalArity(ctors.length); - } -} +export const fnil = + (fn: (...args: any[]) => any, ...ctors: (() => any)[]) => { + let [cta, ctb, ctc] = ctors; + switch (ctors.length) { + case 1: + return (...args: any[]) => { + if (args[0] == null) { + args[0] = cta(); + } + return fn.apply(null, args); + }; + case 2: + return (...args: any[]) => { + if (args[0] == null) { + args[0] = cta(); + } + if (args[1] == null) { + args[1] = ctb(); + } + return fn.apply(null, args); + }; + case 3: + return (...args: any[]) => { + if (args[0] == null) { + args[0] = cta(); + } + if (args[1] == null) { + args[1] = ctb(); + } + if (args[2] == null) { + args[2] = ctc(); + } + return fn.apply(null, args); + }; + default: + illegalArity(ctors.length); + } + }; diff --git a/packages/iterators/src/fork.ts b/packages/iterators/src/fork.ts index 422a79b3c0..54e80ab5bc 100644 --- a/packages/iterators/src/fork.ts +++ b/packages/iterators/src/fork.ts @@ -1,51 +1,51 @@ import { DCons } from "@thi.ng/dcons"; - import { iterator } from "./iterator"; -export function fork(src: Iterable, cacheLimit = 16) { - const iter = iterator(src); - const cache = new DCons(); - const forks = []; - let done = false; - let total = 0; +export const fork = + (src: Iterable, cacheLimit = 16) => { + const iter = iterator(src); + const cache = new DCons(); + const forks = []; + let done = false; + let total = 0; - function consume() { - if (!done) { - if (cache.length === cacheLimit) { - cache.drop(); - for (let i = forks.length - 1; i >= 0; i--) { - forks[i] = Math.max(forks[i] - 1, 0); + const consume = () => { + if (!done) { + if (cache.length === cacheLimit) { + cache.drop(); + for (let i = forks.length - 1; i >= 0; i--) { + forks[i] = Math.max(forks[i] - 1, 0); + } } + const v = iter.next(); + if (!v.done) { + cache.push(v.value); + total++; + } + done = v.done; + return v.value; } - const v = iter.next(); - if (!v.done) { - cache.push(v.value); - total++; - } - done = v.done; - return v.value; - } - } + }; - return function () { - const id = forks.length; - forks.push(0); - return >{ - [Symbol.iterator](): Iterator { return this; }, - next() { - if (forks[id] < cache.length) { - if (forks[id] < total) { - return { done: false, value: cache.nth(forks[id]++) }; + return function () { + const id = forks.length; + forks.push(0); + return >{ + [Symbol.iterator](): Iterator { return this; }, + next() { + if (forks[id] < cache.length) { + if (forks[id] < total) { + return { done: false, value: cache.nth(forks[id]++) }; + } } - } - else { - const value = consume(); - if (!done) { - forks[id]++; + else { + const value = consume(); + if (!done) { + forks[id]++; + } + return { done, value }; } - return { done, value }; } - } + }; }; }; -} diff --git a/packages/iterators/src/group-by.ts b/packages/iterators/src/group-by.ts index 39b6cfc289..a90924c011 100644 --- a/packages/iterators/src/group-by.ts +++ b/packages/iterators/src/group-by.ts @@ -1,17 +1,18 @@ import { iterator } from "./iterator"; -export function groupBy(key: (v) => any, input: Iterable): { [id: string]: T[] } { - let groups = {}; - let iter = iterator(input); - let v: IteratorResult; - while (((v = iter.next()), !v.done)) { - let id = JSON.stringify(key(v.value)); - let g = groups[id]; - if (g) { - g.push(v.value); - } else { - groups[id] = [v.value]; +export const groupBy = + (key: (v) => any, input: Iterable): { [id: string]: T[] } => { + let groups = {}; + let iter = iterator(input); + let v: IteratorResult; + while (((v = iter.next()), !v.done)) { + let id = JSON.stringify(key(v.value)); + let g = groups[id]; + if (g) { + g.push(v.value); + } else { + groups[id] = [v.value]; + } } - } - return groups; -} + return groups; + }; diff --git a/packages/iterators/src/identity.ts b/packages/iterators/src/identity.ts index 79137c560f..74efbc8cf1 100644 --- a/packages/iterators/src/identity.ts +++ b/packages/iterators/src/identity.ts @@ -1,3 +1 @@ -export function identity(x: T) { - return x; -} +export const identity = (x: T) => x; diff --git a/packages/iterators/src/indexed.ts b/packages/iterators/src/indexed.ts index 0ee1b9c449..946741e60e 100644 --- a/packages/iterators/src/indexed.ts +++ b/packages/iterators/src/indexed.ts @@ -1,5 +1,5 @@ import { mapIndexed } from "./map-indexed"; -export function indexed(input: Iterable): IterableIterator<[number, T]> { - return mapIndexed((i, x) => [i, x], input); -} +export const indexed = + (input: Iterable): IterableIterator<[number, T]> => + mapIndexed((i, x) => [i, x], input); diff --git a/packages/iterators/src/interleave.ts b/packages/iterators/src/interleave.ts index bc830f399b..890c10a828 100644 --- a/packages/iterators/src/interleave.ts +++ b/packages/iterators/src/interleave.ts @@ -1,5 +1,4 @@ -import { illegalArity } from "@thi.ng/errors/illegal-arity"; - +import { illegalArity } from "@thi.ng/errors"; import { cycle } from "./cycle"; import { iterator } from "./iterator"; import { map } from "./map"; diff --git a/packages/iterators/src/iterator.ts b/packages/iterators/src/iterator.ts index 70d1f7b660..6655106305 100644 --- a/packages/iterators/src/iterator.ts +++ b/packages/iterators/src/iterator.ts @@ -1,7 +1,8 @@ -export function iterator(x: Iterable) { - return x[Symbol.iterator](); -} +export const iterator = + (x: Iterable) => + x[Symbol.iterator](); -export function maybeIterator(x: any) { - return (x != null && x[Symbol.iterator] && x[Symbol.iterator]()) || undefined; -} +export const maybeIterator = + (x: any) => + (x != null && x[Symbol.iterator] && x[Symbol.iterator]()) || + undefined; diff --git a/packages/iterators/src/juxt.ts b/packages/iterators/src/juxt.ts index 3d29dcd95d..97a2c31897 100644 --- a/packages/iterators/src/juxt.ts +++ b/packages/iterators/src/juxt.ts @@ -1,9 +1,9 @@ -export function juxt(...fns: ((x: T) => any)[]) { - return function (x: T) { - let res = []; - for (let i = 0; i < fns.length; i++) { - res[i] = fns[i](x); - } - return res; - }; -} +export const juxt = + (...fns: ((x: T) => any)[]) => + (x: T) => { + let res = []; + for (let i = 0; i < fns.length; i++) { + res[i] = fns[i](x); + } + return res; + }; diff --git a/packages/iterators/src/last.ts b/packages/iterators/src/last.ts index ca6c42f49c..a90c788fba 100644 --- a/packages/iterators/src/last.ts +++ b/packages/iterators/src/last.ts @@ -1,11 +1,12 @@ import { iterator } from "./iterator"; -export function last(input: Iterable) { - let iter = iterator(input); - let v: IteratorResult; - let prev: T; - while (((v = iter.next()), !v.done)) { - prev = v.value; - } - return prev; -} +export const last = + (input: Iterable) => { + let iter = iterator(input); + let v: IteratorResult; + let prev: T; + while (((v = iter.next()), !v.done)) { + prev = v.value; + } + return prev; + }; diff --git a/packages/iterators/src/map-indexed.ts b/packages/iterators/src/map-indexed.ts index 38701ee3ab..f335b97a53 100644 --- a/packages/iterators/src/map-indexed.ts +++ b/packages/iterators/src/map-indexed.ts @@ -1,6 +1,9 @@ import { map } from "./map"; import { range } from "./range"; -export function mapIndexed(fn: (i: number, ...args: any[]) => T[], ...inputs: Iterable[]): IterableIterator { - return map.apply(null, ([fn, range()] as any[]).concat(inputs)); -} +export const mapIndexed = ( + fn: (i: number, ...args: any[]) => T[], + ...inputs: Iterable[] +): IterableIterator => + + map.apply(null, ([fn, range()] as any[]).concat(inputs)); diff --git a/packages/iterators/src/object-iterator.ts b/packages/iterators/src/object-iterator.ts index 631986dabf..c74e07976e 100644 --- a/packages/iterators/src/object-iterator.ts +++ b/packages/iterators/src/object-iterator.ts @@ -1,14 +1,14 @@ import { map } from "./map"; -export function objectIterator(x: any) { - return map((k) => [k, x[k]], Object.keys(x)); -} +export const objectIterator = + (x: any) => + map((k) => [k, x[k]], Object.keys(x)); -export function maybeObjectIterator(x: any) { - return ( - x != null && - typeof x === "object" && - Object.prototype.toString.call(x) !== "[object Generator]" && - objectIterator(x) - ) || undefined; -} +export const maybeObjectIterator = + (x: any) => + ( + x != null && + typeof x === "object" && + Object.prototype.toString.call(x) !== "[object Generator]" && + objectIterator(x) + ) || undefined; diff --git a/packages/iterators/src/partition.ts b/packages/iterators/src/partition.ts index 0a5e110e79..ed8fdfa439 100644 --- a/packages/iterators/src/partition.ts +++ b/packages/iterators/src/partition.ts @@ -1,5 +1,4 @@ -import { illegalArgs } from "@thi.ng/errors/illegal-arguments"; - +import { illegalArgs } from "@thi.ng/errors"; import { consume } from "./consume"; import { iterator } from "./iterator"; diff --git a/packages/iterators/src/reduce.ts b/packages/iterators/src/reduce.ts index 5d6613956d..bc8a5b51be 100644 --- a/packages/iterators/src/reduce.ts +++ b/packages/iterators/src/reduce.ts @@ -8,7 +8,12 @@ export class ReducedValue { } } -export function reduce(rfn: (acc: B, x: A) => B | ReducedValue, acc: B, input: Iterable) { +export const reduce = ( + rfn: (acc: B, x: A) => B | ReducedValue, + acc: B, + input: Iterable +) => { + let iter = iterator(input); let v: IteratorResult; let _acc: B | ReducedValue = acc; @@ -19,8 +24,7 @@ export function reduce(rfn: (acc: B, x: A) => B | ReducedValue, acc: B, } } return _acc; -} +}; -export function reduced(x: T) { - return new ReducedValue(x); -} +export const reduced = + (x: T) => new ReducedValue(x); diff --git a/packages/iterators/src/run.ts b/packages/iterators/src/run.ts index d0104bb041..9b79273ea4 100644 --- a/packages/iterators/src/run.ts +++ b/packages/iterators/src/run.ts @@ -1,9 +1,10 @@ import { iterator } from "./iterator"; -export function run(fn: (x: T) => any, input: Iterable) { - let iter = iterator(input); - let v: IteratorResult; - while (((v = iter.next()), !v.done)) { - fn(v.value); - } -} +export const run = + (fn: (x: T) => any, input: Iterable) => { + let iter = iterator(input); + let v: IteratorResult; + while (((v = iter.next()), !v.done)) { + fn(v.value); + } + }; diff --git a/packages/iterators/src/some.ts b/packages/iterators/src/some.ts index b4b2ccbbef..21490541c6 100644 --- a/packages/iterators/src/some.ts +++ b/packages/iterators/src/some.ts @@ -1,13 +1,13 @@ -import { Predicate } from "@thi.ng/api/api"; - +import { Predicate } from "@thi.ng/api"; import { iterator } from "./iterator"; -export function some(pred: Predicate, input: Iterable) { - let iter = iterator(input); - let v: IteratorResult; - while (((v = iter.next()), !v.done)) { - if (pred(v.value) === true) { - return v.value; +export const some = + (pred: Predicate, input: Iterable) => { + let iter = iterator(input); + let v: IteratorResult; + while (((v = iter.next()), !v.done)) { + if (pred(v.value) === true) { + return v.value; + } } - } -} + }; diff --git a/packages/iterators/src/take-while.ts b/packages/iterators/src/take-while.ts index e7dcfc106c..5390b8953b 100644 --- a/packages/iterators/src/take-while.ts +++ b/packages/iterators/src/take-while.ts @@ -1,5 +1,4 @@ -import { Predicate } from "@thi.ng/api/api"; - +import { Predicate } from "@thi.ng/api"; import { iterator } from "./iterator"; export function* takeWhile(pred: Predicate, input: Iterable) { diff --git a/packages/iterators/src/walk.ts b/packages/iterators/src/walk.ts index c5acc57cc5..177dd4fec5 100644 --- a/packages/iterators/src/walk.ts +++ b/packages/iterators/src/walk.ts @@ -1,10 +1,12 @@ +import { Fn } from "@thi.ng/api"; import { iterator, maybeIterator } from "./iterator"; import { maybeObjectIterator } from "./object-iterator"; -import { Fn } from "@thi.ng/api/api"; -export function walkable(x) { - return typeof x !== "string" ? maybeIterator(x) || maybeObjectIterator(x) : undefined; -} +export const walkable = + (x) => + typeof x !== "string" ? + maybeIterator(x) || maybeObjectIterator(x) : + undefined; export function walk(fn: Fn, input: any, postOrder?: boolean); export function walk(fn: Fn, children: Fn, input: any, postOrder?: boolean); diff --git a/packages/iterators/src/zip.ts b/packages/iterators/src/zip.ts index e313460e66..89a1dc9c5c 100644 --- a/packages/iterators/src/zip.ts +++ b/packages/iterators/src/zip.ts @@ -1,17 +1,18 @@ import { iterator } from "./iterator"; -export function zip(keys: Iterable, vals: Iterable, target?: any) { - let kiter = iterator(keys); - let viter = iterator(vals); - let k: IteratorResult; - let v: IteratorResult; - target = target || {}; - while (true) { - k = kiter.next(); - v = viter.next(); - if (k.done || v.done) { - return target; +export const zip = + (keys: Iterable, vals: Iterable, target?: any) => { + let kiter = iterator(keys); + let viter = iterator(vals); + let k: IteratorResult; + let v: IteratorResult; + target = target || {}; + while (true) { + k = kiter.next(); + v = viter.next(); + if (k.done || v.done) { + return target; + } + target[k.value] = v.value; } - target[k.value] = v.value; - } -} + }; diff --git a/packages/iterators/test/tsconfig.json b/packages/iterators/test/tsconfig.json index 13d45669e5..2c9c12a650 100644 --- a/packages/iterators/test/tsconfig.json +++ b/packages/iterators/test/tsconfig.json @@ -1,7 +1,8 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", diff --git a/packages/iterators/tsconfig.json b/packages/iterators/tsconfig.json index f6c291a0a0..bcf03f18b4 100644 --- a/packages/iterators/tsconfig.json +++ b/packages/iterators/tsconfig.json @@ -1,7 +1,9 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" diff --git a/packages/malloc/.npmignore b/packages/malloc/.npmignore index ec83d74c9d..67d0c55714 100644 --- a/packages/malloc/.npmignore +++ b/packages/malloc/.npmignore @@ -1,11 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc -export src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/malloc/CHANGELOG.md b/packages/malloc/CHANGELOG.md index 0a1c97fe9a..91990e02f5 100644 --- a/packages/malloc/CHANGELOG.md +++ b/packages/malloc/CHANGELOG.md @@ -3,6 +3,28 @@ 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/malloc@0.2.1...@thi.ng/malloc@1.0.0) (2019-01-21) + + +### Build System + +* update package build scripts & outputs, imports in ~50 packages ([b54b703](https://github.com/thi-ng/umbrella/commit/b54b703)) + + +### BREAKING CHANGES + +* enabled multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols. + + + + + ## [0.2.1](https://github.com/thi-ng/umbrella/compare/@thi.ng/malloc@0.2.0...@thi.ng/malloc@0.2.1) (2018-12-15) **Note:** Version bump only for package @thi.ng/malloc diff --git a/packages/malloc/package.json b/packages/malloc/package.json index f0c8bc4f21..91825e72a9 100644 --- a/packages/malloc/package.json +++ b/packages/malloc/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/malloc", - "version": "0.2.1", + "version": "1.0.0", "description": "ArrayBuffer based malloc() impl for hybrid JS/WASM use cases, based on thi.ng/tinyalloc", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,26 +14,28 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn run clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module malloc api binary checks errors", + "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 run build && yarn publish --access public", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/api": "^4.2.4", - "@thi.ng/binary": "^0.1.2", - "@thi.ng/checks": "^1.5.14", - "@thi.ng/errors": "^0.1.12" + "@thi.ng/api": "^5.0.0", + "@thi.ng/binary": "^1.0.0", + "@thi.ng/checks": "^2.0.0", + "@thi.ng/errors": "^1.0.0" }, "keywords": [ "ES6", @@ -39,5 +43,6 @@ ], "publishConfig": { "access": "public" - } + }, + "sideEffects": false } diff --git a/packages/malloc/src/api.ts b/packages/malloc/src/api.ts new file mode 100644 index 0000000000..261372617d --- /dev/null +++ b/packages/malloc/src/api.ts @@ -0,0 +1,81 @@ +import { IRelease, TypedArray } from "@thi.ng/api"; + +export const enum Type { + U8, + U8C, + I8, + U16, + I16, + U32, + I32, + F32, + F64 +}; + +export const SIZEOF = { + [Type.U8]: 1, + [Type.U8C]: 1, + [Type.I8]: 1, + [Type.U16]: 2, + [Type.I16]: 2, + [Type.U32]: 4, + [Type.I32]: 4, + [Type.F32]: 4, + [Type.F64]: 8, +}; + +export interface MemBlock { + addr: number; + size: number; + next: MemBlock; +} + +export interface MemPoolOpts { + start: number; + end: number; + compact: boolean; + split: boolean; + minSplit: number; +} + +export interface MemPoolStats { + /** + * Free block stats. + */ + free: { count: number, size: number }; + /** + * Used block stats. + */ + used: { count: number, size: number }; + /** + * Current top address. + */ + top: number; + /** + * Bytes available + */ + available: number; + /** + * Total pool size. + */ + total: number; +} + +export interface IMemPool extends IRelease { + malloc(size: number): number; + + calloc(size: number): number; + + mallocAs(type: Type, num: number): TypedArray; + + callocAs(type: Type, num: number): TypedArray; + + free(ptr: number | TypedArray): boolean; + + freeAll(); + + stats(): MemPoolStats; +} + +export type BlockCtor = + (buf: ArrayBuffer, addr: number, num: number) => TypedArray; diff --git a/packages/malloc/src/index.ts b/packages/malloc/src/index.ts index b99cca4c6f..3d894796d0 100644 --- a/packages/malloc/src/index.ts +++ b/packages/malloc/src/index.ts @@ -1,287 +1,3 @@ -import { IObjectOf, IRelease, TypedArray } from "@thi.ng/api"; -import { align } from "@thi.ng/binary/align"; -import { isNumber } from "@thi.ng/checks/is-number"; -import { illegalArgs } from "@thi.ng/errors/illegal-arguments"; - -export const enum Type { - U8, - U8C, - I8, - U16, - I16, - U32, - I32, - F32, - F64 -}; - -type BlockCtor = (buf: ArrayBuffer, addr: number, num: number) => TypedArray; - -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), -}; - -const SIZEOF = { - [Type.U8]: 1, - [Type.U8C]: 1, - [Type.I8]: 1, - [Type.U16]: 2, - [Type.I16]: 2, - [Type.U32]: 4, - [Type.I32]: 4, - [Type.F32]: 4, - [Type.F64]: 8, -}; - -export interface MemBlock { - addr: number; - size: number; - next: MemBlock; -} - -export interface MemPoolOpts { - start: number; - end: number; - compact: boolean; - split: boolean; - minSplit: number; -} -export class MemPool implements - IRelease { - - buf: ArrayBuffer; - protected top: number; - protected start: number; - protected end: number; - protected doCompact: boolean; - protected doSplit: boolean; - protected minSplit: number; - protected _free: MemBlock; - protected _used: MemBlock; - - protected u8: Uint8Array; - - constructor(buf: number | ArrayBuffer, opts: Partial = {}) { - this.buf = isNumber(buf) ? new ArrayBuffer(buf) : buf; - this.u8 = new Uint8Array(this.buf); - this.start = opts.start != null ? - align(Math.max(opts.start, 8), 8) : - 8; - this.end = opts.end != null ? - Math.min(opts.end, this.buf.byteLength) : - this.buf.byteLength; - if (this.start >= this.end) { - illegalArgs(`invalid address range (0x${this.start.toString(16)} - 0x${this.end.toString(16)})`); - } - this.top = this.start; - this.doCompact = opts.compact !== false; - this.doSplit = opts.split !== false; - this.minSplit = opts.minSplit || 16; - this._free = null; - this._used = null; - } - - stats() { - const listStats = (block: MemBlock) => { - let count = 0; - let size = 0; - while (block) { - count++; - size += block.size; - block = block.next; - } - return { count, size }; - }; - return { - free: listStats(this._free), - used: listStats(this._used), - top: this.top, - available: this.end - this.top, - total: this.buf.byteLength - }; - } - - callocAs(type: Type, num: number): TypedArray { - const block = this.mallocAs(type, num); - block && block.fill(0); - return block; - } - - mallocAs(type: Type, num: number): TypedArray { - const addr = this.malloc(num * SIZEOF[type]); - return addr ? - CTORS[type](this.buf, addr, num) : - null; - } - - calloc(size: number): number { - const addr = this.malloc(size); - addr && this.u8.fill(0, addr, align(addr + size, 8)); - return addr; - } - - malloc(size: number): number { - if (size <= 0) { - return 0; - } - size = align(size, 8); - let top = this.top; - const end = this.end; - let block = this._free; - let prev = null; - while (block) { - const isTop = block.addr + block.size >= top; - if (isTop || block.size >= size) { - if (isTop && this.doCompact && block.addr + size > end) { - return 0; - } - if (prev) { - prev.next = block.next; - } else { - this._free = block.next; - } - block.next = this._used; - this._used = block; - if (isTop) { - block.size = size; - this.top = block.addr + size; - } else if (this.doSplit) { - const excess = block.size - size; - if (excess >= this.minSplit) { - block.size = size; - this.insert({ - addr: block.addr + size, - size: excess, - next: null - }); - this.doCompact && this.compact(); - } - } - return block.addr; - } - prev = block; - block = block.next; - } - const addr = align(top, 8); - top = addr + size; - if (top <= end) { - block = { - addr, - size, - next: this._used - }; - this._used = block; - this.top = top; - return addr; - } - return 0; - } - - free(ptr: number | TypedArray) { - let addr: number; - if (!isNumber(ptr)) { - if (ptr.buffer !== this.buf) { - return false; - } - addr = ptr.byteOffset; - } else { - addr = ptr; - } - let block = this._used; - let prev: MemBlock = null; - while (block) { - if (block.addr === addr) { - if (prev) { - prev.next = block.next; - } else { - this._used = block.next; - } - this.insert(block); - this.doCompact && this.compact(); - return true; - } - prev = block; - block = block.next; - } - return false; - } - - freeAll() { - this._free = null; - this._used = null; - this.top = this.start; - } - - release() { - delete this._free; - delete this._used; - delete this.u8; - delete this.buf; - delete this.top; - delete this.start; - delete this.end; - return true; - } - - protected compact() { - let block = this._free; - let prev: MemBlock; - let scan: MemBlock; - let res = false; - while (block) { - prev = block; - scan = block.next; - while (scan && prev.addr + prev.size === scan.addr) { - // console.log("merge:", scan.addr, scan.size); - prev = scan; - scan = scan.next; - } - if (prev !== block) { - const newSize = prev.addr - block.addr + prev.size; - // console.log("merged size:", newSize); - block.size = newSize; - const next = prev.next; - let tmp = block.next; - while (tmp !== prev.next) { - // console.log("release:", tmp.addr); - const tn = tmp.next; - tmp.next = null; - tmp = tn; - } - block.next = next; - res = true; - } - block = block.next; - } - return res; - } - - protected insert(block: MemBlock) { - let ptr = this._free; - if (!this.doCompact) { - block.next = ptr; - this._free = block; - return; - } - let prev: MemBlock = null; - while (ptr) { - if (block.addr <= ptr.addr) break; - prev = ptr; - ptr = ptr.next; - } - if (prev) { - prev.next = block; - } else { - this._free = block; - } - block.next = ptr; - } -} +export * from "./api"; +export * from "./pool"; +export * from "./wrap"; diff --git a/packages/malloc/src/pool.ts b/packages/malloc/src/pool.ts new file mode 100644 index 0000000000..14b866c33b --- /dev/null +++ b/packages/malloc/src/pool.ts @@ -0,0 +1,246 @@ +import { TypedArray } from "@thi.ng/api"; +import { align } from "@thi.ng/binary"; +import { isNumber } from "@thi.ng/checks"; +import { illegalArgs } from "@thi.ng/errors"; +import { + IMemPool, + MemBlock, + MemPoolOpts, + MemPoolStats, + SIZEOF, + Type, +} from "./api"; +import { wrap } from "./wrap"; + +export class MemPool implements + IMemPool { + + buf: ArrayBuffer; + protected top: number; + protected start: number; + protected end: number; + protected doCompact: boolean; + protected doSplit: boolean; + protected minSplit: number; + protected _free: MemBlock; + protected _used: MemBlock; + + protected u8: Uint8Array; + + constructor(buf: number | ArrayBuffer, opts: Partial = {}) { + this.buf = isNumber(buf) ? new ArrayBuffer(buf) : buf; + this.u8 = new Uint8Array(this.buf); + this.start = opts.start != null ? + align(Math.max(opts.start, 8), 8) : + 8; + this.end = opts.end != null ? + Math.min(opts.end, this.buf.byteLength) : + this.buf.byteLength; + if (this.start >= this.end) { + illegalArgs(`invalid address range (0x${this.start.toString(16)} - 0x${this.end.toString(16)})`); + } + this.top = this.start; + this.doCompact = opts.compact !== false; + this.doSplit = opts.split !== false; + this.minSplit = opts.minSplit || 16; + this._free = null; + this._used = null; + } + + stats(): MemPoolStats { + const listStats = (block: MemBlock) => { + let count = 0; + let size = 0; + while (block) { + count++; + size += block.size; + block = block.next; + } + return { count, size }; + }; + const free = listStats(this._free); + return { + free, + used: listStats(this._used), + top: this.top, + available: this.end - this.top + free.size, + total: this.buf.byteLength + }; + } + + callocAs(type: Type, num: number): TypedArray { + const block = this.mallocAs(type, num); + block && block.fill(0); + return block; + } + + mallocAs(type: Type, num: number): TypedArray { + const addr = this.malloc(num * SIZEOF[type]); + return addr ? + wrap(type, this.buf, addr, num) : + null; + } + + calloc(size: number): number { + const addr = this.malloc(size); + addr && this.u8.fill(0, addr, align(addr + size, 8)); + return addr; + } + + malloc(size: number): number { + if (size <= 0) { + return 0; + } + size = align(size, 8); + let top = this.top; + const end = this.end; + let block = this._free; + let prev = null; + while (block) { + const isTop = block.addr + block.size >= top; + if (isTop || block.size >= size) { + if (isTop && this.doCompact && block.addr + size > end) { + return 0; + } + if (prev) { + prev.next = block.next; + } else { + this._free = block.next; + } + block.next = this._used; + this._used = block; + if (isTop) { + block.size = size; + this.top = block.addr + size; + } else if (this.doSplit) { + const excess = block.size - size; + if (excess >= this.minSplit) { + block.size = size; + this.insert({ + addr: block.addr + size, + size: excess, + next: null + }); + this.doCompact && this.compact(); + } + } + return block.addr; + } + prev = block; + block = block.next; + } + const addr = align(top, 8); + top = addr + size; + if (top <= end) { + block = { + addr, + size, + next: this._used + }; + this._used = block; + this.top = top; + return addr; + } + return 0; + } + + free(ptr: number | TypedArray) { + let addr: number; + if (!isNumber(ptr)) { + if (ptr.buffer !== this.buf) { + return false; + } + addr = ptr.byteOffset; + } else { + addr = ptr; + } + let block = this._used; + let prev: MemBlock = null; + while (block) { + if (block.addr === addr) { + if (prev) { + prev.next = block.next; + } else { + this._used = block.next; + } + this.insert(block); + this.doCompact && this.compact(); + return true; + } + prev = block; + block = block.next; + } + return false; + } + + freeAll() { + this._free = null; + this._used = null; + this.top = this.start; + } + + release() { + delete this._free; + delete this._used; + delete this.u8; + delete this.buf; + delete this.top; + delete this.start; + delete this.end; + return true; + } + + protected compact() { + let block = this._free; + let prev: MemBlock; + let scan: MemBlock; + let res = false; + while (block) { + prev = block; + scan = block.next; + while (scan && prev.addr + prev.size === scan.addr) { + // console.log("merge:", scan.addr, scan.size); + prev = scan; + scan = scan.next; + } + if (prev !== block) { + const newSize = prev.addr - block.addr + prev.size; + // console.log("merged size:", newSize); + block.size = newSize; + const next = prev.next; + let tmp = block.next; + while (tmp !== prev.next) { + // console.log("release:", tmp.addr); + const tn = tmp.next; + tmp.next = null; + tmp = tn; + } + block.next = next; + res = true; + } + block = block.next; + } + return res; + } + + protected insert(block: MemBlock) { + let ptr = this._free; + if (!this.doCompact) { + block.next = ptr; + this._free = block; + return; + } + let prev: MemBlock = null; + while (ptr) { + if (block.addr <= ptr.addr) break; + prev = ptr; + ptr = ptr.next; + } + if (prev) { + prev.next = block; + } else { + this._free = block; + } + block.next = ptr; + } +} diff --git a/packages/malloc/src/wrap.ts b/packages/malloc/src/wrap.ts new file mode 100644 index 0000000000..d88b95fff6 --- /dev/null +++ b/packages/malloc/src/wrap.ts @@ -0,0 +1,18 @@ +import { IObjectOf } from "@thi.ng/api"; +import { BlockCtor, Type } 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 const wrap = + (type: Type, buf: ArrayBuffer, addr: number, num: number) => + CTORS[type](buf, addr, num); \ No newline at end of file diff --git a/packages/malloc/test/tsconfig.json b/packages/malloc/test/tsconfig.json index bcf29ace54..2c9c12a650 100644 --- a/packages/malloc/test/tsconfig.json +++ b/packages/malloc/test/tsconfig.json @@ -1,10 +1,11 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", "../src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/malloc/tsconfig.json b/packages/malloc/tsconfig.json index bd6481a5a6..bcf03f18b4 100644 --- a/packages/malloc/tsconfig.json +++ b/packages/malloc/tsconfig.json @@ -1,9 +1,11 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/math/.npmignore b/packages/math/.npmignore index d703bda97a..67d0c55714 100644 --- a/packages/math/.npmignore +++ b/packages/math/.npmignore @@ -1,10 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/math/CHANGELOG.md b/packages/math/CHANGELOG.md index d038224957..b8aeb22b22 100644 --- a/packages/math/CHANGELOG.md +++ b/packages/math/CHANGELOG.md @@ -3,6 +3,36 @@ 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/math@0.2.2...@thi.ng/math@1.0.0) (2019-01-21) + + +### Build System + +* update package build scripts & outputs, imports in ~50 packages ([b54b703](https://github.com/thi-ng/umbrella/commit/b54b703)) + + +### Features + +* **math:** add absInnerAngle() ([a78bd87](https://github.com/thi-ng/umbrella/commit/a78bd87)) +* **math:** add constants ([8fa05c3](https://github.com/thi-ng/umbrella/commit/8fa05c3)) +* **math:** add cossin(), add opt scale arg for sincos() ([0043fb5](https://github.com/thi-ng/umbrella/commit/0043fb5)) +* **math:** update eqDelta w/ adaptive eps, rename old => eqDeltaFixed ([5018009](https://github.com/thi-ng/umbrella/commit/5018009)) + + +### BREAKING CHANGES + +* enabled multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols. + + + + + ## [0.2.2](https://github.com/thi-ng/umbrella/compare/@thi.ng/math@0.2.1...@thi.ng/math@0.2.2) (2018-12-15) **Note:** Version bump only for package @thi.ng/math diff --git a/packages/math/package.json b/packages/math/package.json index e49132b2bf..34d4ff5bde 100644 --- a/packages/math/package.json +++ b/packages/math/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/math", - "version": "0.2.2", + "version": "1.0.0", "description": "Assorted common math functions & utilities", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,19 +14,21 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn run clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module math", + "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 run build && yarn publish --access public", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "keywords": [ @@ -38,5 +42,6 @@ ], "publishConfig": { "access": "public" - } + }, + "sideEffects": false } diff --git a/packages/math/src/abs.ts b/packages/math/src/abs.ts index c173dcb4b4..90ba7bc709 100644 --- a/packages/math/src/abs.ts +++ b/packages/math/src/abs.ts @@ -1,7 +1,9 @@ import { EPS } from "./api"; -export const absDiff = (x: number, y: number) => - Math.abs(x - y); +export const absDiff = + (x: number, y: number) => + Math.abs(x - y); -export const sign = (x: number, eps = EPS) => - x > eps ? 1 : x < -eps ? -1 : 0; +export const sign = + (x: number, eps = EPS) => + x > eps ? 1 : x < -eps ? -1 : 0; diff --git a/packages/math/src/angle.ts b/packages/math/src/angle.ts index a2f4200922..538d2aa628 100644 --- a/packages/math/src/angle.ts +++ b/packages/math/src/angle.ts @@ -6,33 +6,44 @@ import { TAU } from "./api"; -export const sincos = (theta: number) => - [Math.sin(theta), Math.cos(theta)]; +export const sincos = (theta: number, n = 1) => + [Math.sin(theta) * n, Math.cos(theta) * n]; -export const absTheta = (theta: number) => - (theta %= TAU, theta < 0 ? TAU + theta : theta); +export const cossin = (theta: number, n = 1) => + [Math.cos(theta) * n, Math.sin(theta) * n]; -export const angleDist = (a: number, b: number) => - (a = absTheta((b % TAU) - (a % TAU)), a > PI ? TAU - a : a); +export const absTheta = + (theta: number) => + (theta %= TAU, theta < 0 ? TAU + theta : theta); -export const atan2Abs = (y: number, x: number) => - absTheta(Math.atan2(y, x)); +export const absInnerAngle = + (x: number) => + (x = Math.abs(x), x > PI ? TAU - x : x); -export const quadrant = (theta: number) => - (absTheta(theta) / HALF_PI) | 0; +export const angleDist = + (a: number, b: number) => + absInnerAngle(absTheta((b % TAU) - (a % TAU))); + +export const atan2Abs = + (y: number, x: number) => + absTheta(Math.atan2(y, x)); + +export const quadrant = + (theta: number) => + (absTheta(theta) / HALF_PI) | 0; /** * Converts angle to degrees. * * @param x angle in radians */ -export const deg = (x: number) => - x * RAD2DEG; +export const deg = + (x: number) => x * RAD2DEG; /** * Converts angle to radians. * * @param x angle in degrees */ -export const rad = (x: number) => - x * DEG2RAD; +export const rad = + (x: number) => x * DEG2RAD; diff --git a/packages/math/src/api.ts b/packages/math/src/api.ts index 3382fb9122..af3a19daf2 100644 --- a/packages/math/src/api.ts +++ b/packages/math/src/api.ts @@ -11,4 +11,8 @@ export const RAD2DEG = 180 / PI; export const SQRT2 = Math.SQRT2; export const SQRT3 = Math.sqrt(3); +export const THIRD = 1 / 3; +export const TWO_THIRD = 2 / 3; +export const SIXTH = 1 / 6; + export let EPS = 1e-6; diff --git a/packages/math/src/eqdelta.ts b/packages/math/src/eqdelta.ts index 50eb9c196e..f4b4641927 100644 --- a/packages/math/src/eqdelta.ts +++ b/packages/math/src/eqdelta.ts @@ -1,13 +1,33 @@ import { EPS } from "./api"; +const abs = Math.abs; +const max = Math.max; + +/** + * Checks if `|a - b| <= ε` and adapts given epsilon value to the given + * arguments: + * + * ε is factored with the largest absolute value of `a` or `b` (but + * never lesser than the given `eps` value): + * + * `ε = ε * max(1, |a|, |b|)` + * + * @param a left value + * @param b right value + * @param eps epsilon / tolerance, default `1e-6` + */ +export const eqDelta = + (a: number, b: number, eps = EPS) => + abs(a - b) <= eps * max(1, abs(a), abs(b)); + /** - * Checks if `|a - b| <= ε`. + * Similar to `eqDelta()`, but used given `eps` as is. * * @param a left value * @param b right value - * @param eps epsilon / tolerance + * @param eps epsilon / tolerance, default `1e-6` */ -export const eqDelta = (a: number, b: number, eps = EPS) => { - const d = a - b; - return (d < 0 ? -d : d) <= eps; -}; +export const eqDeltaFixed = + (a: number, b: number, eps = EPS) => + abs(a - b) <= eps; + diff --git a/packages/math/src/fit.ts b/packages/math/src/fit.ts index 6ec0810343..390d5e6b3e 100644 --- a/packages/math/src/fit.ts +++ b/packages/math/src/fit.ts @@ -8,20 +8,26 @@ import { clamp01, clamp11 } from "./interval"; * @param a * @param b */ -export const norm = (x: number, a: number, b: number) => - b !== a ? (x - a) / (b - a) : 0; +export const norm = + (x: number, a: number, b: number) => + b !== a ? (x - a) / (b - a) : 0; -export const fit = (x: number, a: number, b: number, c: number, d: number) => - c + (d - c) * norm(x, a, b); +export const fit = + (x: number, a: number, b: number, c: number, d: number) => + c + (d - c) * norm(x, a, b); -export const fitClamped = (x: number, a: number, b: number, c: number, d: number) => - c + (d - c) * clamp01(norm(x, a, b)); +export const fitClamped = + (x: number, a: number, b: number, c: number, d: number) => + c + (d - c) * clamp01(norm(x, a, b)); -export const fit01 = (x: number, a: number, b: number) => - a + (b - a) * clamp01(x); +export const fit01 = + (x: number, a: number, b: number) => + a + (b - a) * clamp01(x); -export const fit10 = (x: number, a: number, b: number) => - b + (a - b) * clamp01(x); +export const fit10 = + (x: number, a: number, b: number) => + b + (a - b) * clamp01(x); -export const fit11 = (x: number, a: number, b: number) => - a + (b - a) * (0.5 + 0.5 * clamp11(x)); +export const fit11 = + (x: number, a: number, b: number) => + a + (b - a) * (0.5 + 0.5 * clamp11(x)); diff --git a/packages/math/src/interval.ts b/packages/math/src/interval.ts index cd4a6ebb8e..0ceb5cd698 100644 --- a/packages/math/src/interval.ts +++ b/packages/math/src/interval.ts @@ -5,57 +5,69 @@ * @param min lower bound * @param max upper bound */ -export const clamp = (x: number, min: number, max: number) => - x < min ? min : x > max ? max : x; - -export const clamp01 = (x: number) => - x < 0 ? 0 : x > 1 ? 1 : x; - -export const clamp11 = (x: number) => - x < -1 ? -1 : x > 1 ? 1 : x; - -export const wrap = (x: number, min: number, max: number) => - x < min ? x - min + max : x >= max ? x - max + min : x; - -export const wrap01 = (x: number) => - x < 0 ? x + 1 : x >= 1 ? x - 1 : x; - -export const wrap11 = (x: number) => - x < -1 ? x + 2 : x >= 1 ? x - 2 : x; - -export const min2id = (a: number, b: number) => - a <= b ? 0 : 1; - -export const min3id = (a: number, b: number, c: number) => - (a <= b) ? - (a <= c ? 0 : 2) : - (b <= c ? 1 : 2); - -export const min4id = (a: number, b: number, c: number, d: number) => - a <= b ? - (a <= c ? - (a <= d ? 0 : 3) : - (c <= d ? 2 : 3)) : - (b <= c ? - (b <= d ? 1 : 3) : - (c <= d ? 2 : 3)); - -export const max2id = (a: number, b: number) => - a >= b ? 0 : 1; - -export const max3id = (a: number, b: number, c: number) => - (a >= b) ? - (a >= c ? 0 : 2) : - (b >= c ? 1 : 2); - -export const max4id = (a: number, b: number, c: number, d: number) => - a >= b ? - (a >= c ? - (a >= d ? 0 : 3) : - (c >= d ? 2 : 3)) : - (b >= c ? - (b >= d ? 1 : 3) : - (c >= d ? 2 : 3)); +export const clamp = + (x: number, min: number, max: number) => + x < min ? min : x > max ? max : x; + +export const clamp01 = + (x: number) => + x < 0 ? 0 : x > 1 ? 1 : x; + +export const clamp11 = + (x: number) => + x < -1 ? -1 : x > 1 ? 1 : x; + +export const wrap = + (x: number, min: number, max: number) => + x < min ? x - min + max : x >= max ? x - max + min : x; + +export const wrap01 = + (x: number) => + x < 0 ? x + 1 : x >= 1 ? x - 1 : x; + +export const wrap11 = + (x: number) => + x < -1 ? x + 2 : x >= 1 ? x - 2 : x; + +export const min2id = + (a: number, b: number) => + a <= b ? 0 : 1; + +export const min3id = + (a: number, b: number, c: number) => + (a <= b) ? + (a <= c ? 0 : 2) : + (b <= c ? 1 : 2); + +export const min4id = + (a: number, b: number, c: number, d: number) => + a <= b ? + (a <= c ? + (a <= d ? 0 : 3) : + (c <= d ? 2 : 3)) : + (b <= c ? + (b <= d ? 1 : 3) : + (c <= d ? 2 : 3)); + +export const max2id = + (a: number, b: number) => + a >= b ? 0 : 1; + +export const max3id = + (a: number, b: number, c: number) => + (a >= b) ? + (a >= c ? 0 : 2) : + (b >= c ? 1 : 2); + +export const max4id = + (a: number, b: number, c: number, d: number) => + a >= b ? + (a >= c ? + (a >= d ? 0 : 3) : + (c >= d ? 2 : 3)) : + (b >= c ? + (b >= d ? 1 : 3) : + (c >= d ? 2 : 3)); /** * See `smax()`. @@ -64,8 +76,9 @@ export const max4id = (a: number, b: number, c: number, d: number) => * @param b * @param k smooth exponent (MUST be > 0) */ -export const smin = (a: number, b: number, k: number) => - smax(a, b, -k); +export const smin = + (a: number, b: number, k: number) => + smax(a, b, -k); /** * Smooth maximum. Note: Result values will be slightly larger than max @@ -78,11 +91,12 @@ export const smin = (a: number, b: number, k: number) => * @param b * @param k smooth exponent (MUST be > 0) */ -export const smax = (a: number, b: number, k: number) => { - const ea = Math.exp(a * k); - const eb = Math.exp(b * k); - return (a * ea + b * eb) / (ea + eb); -}; +export const smax = + (a: number, b: number, k: number) => { + const ea = Math.exp(a * k); + const eb = Math.exp(b * k); + return (a * ea + b * eb) / (ea + eb); + }; /** * Same as `smin(smax(x, min, k), max, k)`. @@ -92,14 +106,17 @@ export const smax = (a: number, b: number, k: number) => { * @param max * @param k */ -export const sclamp = (x: number, min: number, max: number, k: number) => - smin(smax(x, min, k), max, k); +export const sclamp = + (x: number, min: number, max: number, k: number) => + smin(smax(x, min, k), max, k); -export const absMin = (a: number, b: number) => - Math.abs(a) < Math.abs(b) ? a : b; +export const absMin = + (a: number, b: number) => + Math.abs(a) < Math.abs(b) ? a : b; -export const absMax = (a: number, b: number) => - Math.abs(a) > Math.abs(b) ? a : b; +export const absMax = + (a: number, b: number) => + Math.abs(a) > Math.abs(b) ? a : b; /** * http://www.musicdsp.org/showone.php?id=203 @@ -107,10 +124,11 @@ export const absMax = (a: number, b: number) => * @param e * @param x */ -export const foldback = (e: number, x: number) => - (x < -e || x > e) ? - Math.abs(Math.abs((x - e) % (4 * e)) - 2 * e) - e : - x; +export const foldback = + (e: number, x: number) => + (x < -e || x > e) ? + Math.abs(Math.abs((x - e) % (4 * e)) - 2 * e) - e : + x; /** * Returns true iff `x` is in closed interval `[min .. max]` @@ -119,8 +137,9 @@ export const foldback = (e: number, x: number) => * @param min * @param max */ -export const inRange = (x: number, min: number, max: number) => - x >= min && x <= max; +export const inRange = + (x: number, min: number, max: number) => + x >= min && x <= max; /** * Returns true iff `x` is in open interval `(min .. max)` @@ -129,5 +148,6 @@ export const inRange = (x: number, min: number, max: number) => * @param min * @param max */ -export const inOpenRange = (x: number, min: number, max: number) => - x > min && x < max; +export const inOpenRange = + (x: number, min: number, max: number) => + x > min && x < max; diff --git a/packages/math/src/mix.ts b/packages/math/src/mix.ts index 4ee6ecd528..2909f375c0 100644 --- a/packages/math/src/mix.ts +++ b/packages/math/src/mix.ts @@ -1,7 +1,8 @@ import { PI, HALF_PI } from "./api"; -export const mix = (a: number, b: number, t: number) => - a + (b - a) * t; +export const mix = + (a: number, b: number, t: number) => + a + (b - a) * t; /** * ``` @@ -19,44 +20,52 @@ export const mix = (a: number, b: number, t: number) => * @param u 1st interpolation factor * @param v 2nd interpolation factor */ -export const mixBilinear = (a: number, b: number, c: number, d: number, u: number, v: number) => - mix(mix(a, b, u), mix(c, d, u), v); +export const mixBilinear = + (a: number, b: number, c: number, d: number, u: number, v: number) => + mix(mix(a, b, u), mix(c, d, u), v); -export const mixQuadratic = (a: number, b: number, c: number, t: number) => { - const s = 1 - t; - return a * s * s + b * 2 * s * t + c * t * t; -}; +export const mixQuadratic = + (a: number, b: number, c: number, t: number) => { + const s = 1 - t; + return a * s * s + b * 2 * s * t + c * t * t; + }; -export const mixCubic = (a: number, b: number, c: number, d: number, t: number) => { - const t2 = t * t; - const s = 1 - t; - const s2 = s * s; - return a * s2 * s + b * 3 * s2 * t + c * 3 * t2 * s + d * t2 * t; -}; +export const mixCubic = + (a: number, b: number, c: number, d: number, t: number) => { + const t2 = t * t; + const s = 1 - t; + const s2 = s * s; + return a * s2 * s + b * 3 * s2 * t + c * 3 * t2 * s + d * t2 * t; + }; -export const tween = (f: (t: number) => number, from: number, to: number) => - (t: number) => mix(from, to, f(t)); +export const tween = + (f: (t: number) => number, from: number, to: number) => + (t: number) => mix(from, to, f(t)); /** * Circular interpolation: `sqrt(1 - (1 - t)^2)` * * @param t interpolation factor (0.0 .. 1.0) */ -export const circular = (t: number) => { - t = 1 - t; - return Math.sqrt(1 - t * t); -}; +export const circular = + (t: number) => { + t = 1 - t; + return Math.sqrt(1 - t * t); + }; -export const cosine = (t: number): number => - 1 - (Math.cos(t * PI) * 0.5 + 0.5); +export const cosine = + (t: number): number => + 1 - (Math.cos(t * PI) * 0.5 + 0.5); -export const decimated = (n: number, t: number) => - Math.floor(t * n) / n; +export const decimated = + (n: number, t: number) => + Math.floor(t * n) / n; -export const bounce = (k: number, amp: number, t: number) => { - const tk = t * k; - return 1 - amp * Math.sin(tk) / tk * Math.cos(t * HALF_PI); -}; +export const bounce = + (k: number, amp: number, t: number) => { + const tk = t * k; + return 1 - amp * Math.sin(tk) / tk * Math.cos(t * HALF_PI); + }; /** * HOF exponential easing. @@ -68,35 +77,41 @@ export const bounce = (k: number, amp: number, t: number) => { * @param ease easing behavior [0.0 .. ∞] * @param t */ -export const ease = (ease: number, t: number) => - Math.pow(t, ease); +export const ease = + (ease: number, t: number) => + Math.pow(t, ease); /** * HOF impulse generator. Peaks at `t=1/k` * * @param k impulse width (higher values => shorter impulse) */ -export const impulse = (k: number, t: number) => { - const h = k * t; - return h * Math.exp(1 - h); -}; +export const impulse = + (k: number, t: number) => { + const h = k * t; + return h * Math.exp(1 - h); + }; -export const gain = (k: number, t: number) => - t < 0.5 ? - 0.5 * Math.pow(2 * t, k) : - 1 - 0.5 * Math.pow(2 - 2 * t, k); +export const gain = + (k: number, t: number) => + t < 0.5 ? + 0.5 * Math.pow(2 * t, k) : + 1 - 0.5 * Math.pow(2 - 2 * t, k); -export const parabola = (k: number, t: number) => - Math.pow(4.0 * t * (1.0 - t), k); +export const parabola = + (k: number, t: number) => + Math.pow(4.0 * t * (1.0 - t), k); -export const cubicPulse = (w: number, c: number, t: number) => { - t = Math.abs(t - c); - return t > w ? - 0 : - (t /= w, 1 - t * t * (3 - 2 * t)); -}; +export const cubicPulse = + (w: number, c: number, t: number) => { + t = Math.abs(t - c); + return t > w ? + 0 : + (t /= w, 1 - t * t * (3 - 2 * t)); + }; -export const sinc = (k: number, t: number) => { - t = PI * (k * t - 1.0); - return Math.sin(t) / t; -}; +export const sinc = + (k: number, t: number) => { + t = PI * (k * t - 1.0); + return Math.sin(t) / t; + }; diff --git a/packages/math/src/prec.ts b/packages/math/src/prec.ts index a8ffd2f347..2f3fb56536 100644 --- a/packages/math/src/prec.ts +++ b/packages/math/src/prec.ts @@ -6,17 +6,21 @@ import { EPS } from "./api"; * @param a * @param b */ -export const fmod = (a: number, b: number) => - a - b * Math.floor(a / b); +export const fmod = + (a: number, b: number) => + a - b * Math.floor(a / b); -export const fract = (x: number) => - x - Math.floor(x); +export const fract = + (x: number) => + x - Math.floor(x); -export const trunc = (x: number) => - x < 0 ? Math.ceil(x) : Math.floor(x); +export const trunc = + (x: number) => + x < 0 ? Math.ceil(x) : Math.floor(x); -export const roundTo = (x: number, prec = 1) => - Math.round(x / prec) * prec; +export const roundTo = + (x: number, prec = 1) => + Math.round(x / prec) * prec; /** * Only rounds `x` to nearest int if `fract(x)` < `eps` or > `1-eps`. @@ -24,9 +28,10 @@ export const roundTo = (x: number, prec = 1) => * @param x * @param eps */ -export const roundEps = (x: number, eps = EPS) => { - const f = fract(x); - return f <= eps || f >= 1 - eps ? - Math.round(x) : - x; -}; +export const roundEps = + (x: number, eps = EPS) => { + const f = fract(x); + return f <= eps || f >= 1 - eps ? + Math.round(x) : + x; + }; diff --git a/packages/math/src/solve.ts b/packages/math/src/solve.ts index fab6df7f0f..0c91b2e781 100644 --- a/packages/math/src/solve.ts +++ b/packages/math/src/solve.ts @@ -16,9 +16,9 @@ import { EPS } from "./api"; * @param fn * @param eps */ -export const derivative = (f: (x: number) => number, eps = EPS) => { - return (x: number) => (f(x + eps) - f(x)) / eps; -} +export const derivative = + (f: (x: number) => number, eps = EPS) => + (x: number) => (f(x + eps) - f(x)) / eps; /** * Computes solution for linear equation: `ax + b = 0`. @@ -28,8 +28,8 @@ export const derivative = (f: (x: number) => number, eps = EPS) => { * @param a slope * @param b constant offset */ -export const solveLinear = (a: number, b: number) => - -b / a; +export const solveLinear = + (a: number, b: number) => -b / a; /** * Computes solutions for quadratic equation: `ax^2 + bx + c = 0`. @@ -45,15 +45,16 @@ export const solveLinear = (a: number, b: number) => * @param c constant offset * @param eps tolerance to determine multiple roots */ -export const solveQuadratic = (a: number, b: number, c: number, eps = 1e-9) => { - const d = 2 * a; - let r = b * b - 4 * a * c; - return r < 0 ? - [] : - r < eps ? - [-b / d] : - (r = Math.sqrt(r), [(-b - r) / d, (-b + r) / d]); -}; +export const solveQuadratic = + (a: number, b: number, c: number, eps = 1e-9) => { + const d = 2 * a; + let r = b * b - 4 * a * c; + return r < 0 ? + [] : + r < eps ? + [-b / d] : + (r = Math.sqrt(r), [(-b - r) / d, (-b + r) / d]); + }; /** * Computes solutions for quadratic equation: `ax^3 + bx^2 + c*x + d = 0`. @@ -69,38 +70,39 @@ export const solveQuadratic = (a: number, b: number, c: number, eps = 1e-9) => { * @param d constant offset * @param eps tolerance to determine multiple roots */ -export const solveCubic = (a: number, b: number, c: number, d: number, eps = 1e-9) => { - const aa = a * a; - const bb = b * b; - const ba3 = b / (3 * a); - const p = (3 * a * c - bb) / (3 * aa); - const q = (2 * bb * b - 9 * a * b * c + 27 * aa * d) / (27 * aa * a); +export const solveCubic = + (a: number, b: number, c: number, d: number, eps = 1e-9) => { + const aa = a * a; + const bb = b * b; + const ba3 = b / (3 * a); + const p = (3 * a * c - bb) / (3 * aa); + const q = (2 * bb * b - 9 * a * b * c + 27 * aa * d) / (27 * aa * a); - if (Math.abs(p) < eps) { - return [Math.cbrt(-q) - ba3]; - } else if (Math.abs(q) < eps) { - return p < 0 ? - [ - -Math.sqrt(-p) - ba3, - -ba3, Math.sqrt(-p) - ba3 - ] : - [-ba3]; - } else { - const denom = q * q / 4 + p * p * p / 27; - if (Math.abs(denom) < eps) { - return [-1.5 * q / p - ba3, 3 * q / p - ba3]; - } else if (denom > 0) { - const u = Math.cbrt(-q / 2 - Math.sqrt(denom)); - return [u - p / (3 * u) - ba3]; + if (Math.abs(p) < eps) { + return [Math.cbrt(-q) - ba3]; + } else if (Math.abs(q) < eps) { + return p < 0 ? + [ + -Math.sqrt(-p) - ba3, + -ba3, Math.sqrt(-p) - ba3 + ] : + [-ba3]; } else { - const u = 2 * Math.sqrt(-p / 3), - t = Math.acos(3 * q / p / u) / 3, - k = 2 * Math.PI / 3; - return [ - u * Math.cos(t) - ba3, - u * Math.cos(t - k) - ba3, - u * Math.cos(t - 2 * k) - ba3 - ]; + const denom = q * q / 4 + p * p * p / 27; + if (Math.abs(denom) < eps) { + return [-1.5 * q / p - ba3, 3 * q / p - ba3]; + } else if (denom > 0) { + const u = Math.cbrt(-q / 2 - Math.sqrt(denom)); + return [u - p / (3 * u) - ba3]; + } else { + const u = 2 * Math.sqrt(-p / 3), + t = Math.acos(3 * q / p / u) / 3, + k = 2 * Math.PI / 3; + return [ + u * Math.cos(t) - ba3, + u * Math.cos(t - k) - ba3, + u * Math.cos(t - 2 * k) - ba3 + ]; + } } - } -} + }; diff --git a/packages/math/src/step.ts b/packages/math/src/step.ts index 292c302df2..51e2f44c27 100644 --- a/packages/math/src/step.ts +++ b/packages/math/src/step.ts @@ -7,8 +7,9 @@ import { clamp01 } from "./interval"; * @param x test value * @returns 0, if `x < e`, else 1 */ -export const step = (edge: number, x: number) => - x < edge ? 0 : 1; +export const step = + (edge: number, x: number) => + x < edge ? 0 : 1; /** * GLSL-style smoothStep threshold function. @@ -18,10 +19,11 @@ export const step = (edge: number, x: number) => * @param x test value * @returns 0, if `x < edge1`, 1 if `x > edge2`, else sigmoid interpolation */ -export const smoothStep = (edge: number, edge2: number, x: number) => { - x = clamp01((x - edge) / (edge2 - edge)); - return (3 - 2 * x) * x * x; -}; +export const smoothStep = + (edge: number, edge2: number, x: number) => { + x = clamp01((x - edge) / (edge2 - edge)); + return (3 - 2 * x) * x * x; + }; /** * Similar to `smoothStep()` but using different polynomial. @@ -30,10 +32,11 @@ export const smoothStep = (edge: number, edge2: number, x: number) => { * @param edge2 * @param x */ -export const smootherStep = (edge: number, edge2: number, x: number) => { - x = clamp01((x - edge) / (edge2 - edge)); - return x * x * x * (x * (x * 6 - 15) + 10); -}; +export const smootherStep = + (edge: number, edge2: number, x: number) => { + x = clamp01((x - edge) / (edge2 - edge)); + return x * x * x * (x * (x * 6 - 15) + 10); + }; /** * Exponential ramp with variable shape, e.g. @@ -47,5 +50,6 @@ export const smootherStep = (edge: number, edge2: number, x: number) => { * @param n * @param x */ -export const expStep = (k: number, n: number, x: number) => - 1 - Math.exp(-k * Math.pow(x, n)); +export const expStep = + (k: number, n: number, x: number) => + 1 - Math.exp(-k * Math.pow(x, n)); diff --git a/packages/math/test/tsconfig.json b/packages/math/test/tsconfig.json index bcf29ace54..2c9c12a650 100644 --- a/packages/math/test/tsconfig.json +++ b/packages/math/test/tsconfig.json @@ -1,10 +1,11 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", "../src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/math/tsconfig.json b/packages/math/tsconfig.json index bd6481a5a6..bcf03f18b4 100644 --- a/packages/math/tsconfig.json +++ b/packages/math/tsconfig.json @@ -1,9 +1,11 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/matrices/.npmignore b/packages/matrices/.npmignore new file mode 100644 index 0000000000..67d0c55714 --- /dev/null +++ b/packages/matrices/.npmignore @@ -0,0 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz +build +coverage +dev +doc +src* +test +tsconfig.json diff --git a/packages/matrices/CHANGELOG.md b/packages/matrices/CHANGELOG.md new file mode 100644 index 0000000000..7ec878a352 --- /dev/null +++ b/packages/matrices/CHANGELOG.md @@ -0,0 +1,33 @@ +# 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-01-21) + + +### Bug Fixes + +* **matrices:** inject default output handling code ([0b07ac8](https://github.com/thi-ng/umbrella/commit/0b07ac8)) +* **matrices:** re-add persp divide in mulV344() ([4c6fe06](https://github.com/thi-ng/umbrella/commit/4c6fe06)) +* **matrices:** scaleWithCenter* (add missing concat() arg) ([4f02491](https://github.com/thi-ng/umbrella/commit/4f02491)) + + +### Features + +* **matrices:** add cwise matrix multiply, rename mul* => mulM*, move mulQ ([ae7a039](https://github.com/thi-ng/umbrella/commit/ae7a039)) +* **matrices:** add m22 & m23 matrix converters ([2aceab9](https://github.com/thi-ng/umbrella/commit/2aceab9)) +* **matrices:** add M44 factories ([f1a5cf1](https://github.com/thi-ng/umbrella/commit/f1a5cf1)) +* **matrices:** add more matrix ops ([35babfc](https://github.com/thi-ng/umbrella/commit/35babfc)) +* **matrices:** add more matrix ops, optimize & simplify ([f04e79e](https://github.com/thi-ng/umbrella/commit/f04e79e)) +* **matrices:** add quaternion fns ([b03b919](https://github.com/thi-ng/umbrella/commit/b03b919)) +* **matrices:** add quatToMat33, update readme ([52fb939](https://github.com/thi-ng/umbrella/commit/52fb939)) +* **matrices:** add rotationAroundAxis33/44() ([27f65f9](https://github.com/thi-ng/umbrella/commit/27f65f9)) +* **matrices:** add trace() ([16d56a3](https://github.com/thi-ng/umbrella/commit/16d56a3)) +* **matrices:** add viewport(), project/unproject(), update invert() ([d9e1b2e](https://github.com/thi-ng/umbrella/commit/d9e1b2e)) +* **matrices:** extract matrix ops to own package ([f940672](https://github.com/thi-ng/umbrella/commit/f940672)) + + +### Performance Improvements + +* **matrices:** use setC6() for M23 ops ([d462ae0](https://github.com/thi-ng/umbrella/commit/d462ae0)) diff --git a/packages/matrices/LICENSE b/packages/matrices/LICENSE new file mode 100644 index 0000000000..8dada3edaf --- /dev/null +++ b/packages/matrices/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/matrices/README.md b/packages/matrices/README.md new file mode 100644 index 0000000000..5820f86cc6 --- /dev/null +++ b/packages/matrices/README.md @@ -0,0 +1,180 @@ +# @thi.ng/matrices + +[![npm (scoped)](https://img.shields.io/npm/v/@thi.ng/matrices.svg)](https://www.npmjs.com/package/@thi.ng/matrices) +![npm downloads](https://img.shields.io/npm/dm/@thi.ng/matrices.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) + - [Related packages](#related-packages) +- [Installation](#installation) +- [Dependencies](#dependencies) +- [Usage examples](#usage-examples) +- [API](#api) + - [Constants](#constants) + - [Matrix creation](#matrix-creation) + - [Matrix conversion](#matrix-conversion) + - [Setters](#setters) + - [Row & column accessors](#row--column-accessors) + - [Componentwise matrix - matrix](#componentwise-matrix---matrix) + - [Componentwise matrix - scalar](#componentwise-matrix---scalar) + - [Matrix multiplication](#matrix-multiplication) + - [Matrix - vector multiplication](#matrix---vector-multiplication) + - [Determinant & inversion](#determinant--inversion) + - [Matrix transposition](#matrix-transposition) + - [Quaternion](#quaternion) +- [Authors](#authors) +- [License](#license) + + + +## About + +This package provides 160+ matrix & quaternion operations for 2D/3D +geometry processing and acts as companion package for +[@thi.ng/vectors](https://github.com/thi-ng/umbrella/tree/master/packages/vectors). +Like with the vectors package, most functions are defined as +multi-method dispatching to optimized implementations based on matrix +size (which themselves are exposed for direct use too). + +Any `ArrayLike` type can be used as matrix containers (e.g. JS arrays, +typed arrays, custom impls) and hence many other functions provided by +the vectors package can also be used directly with matrices (where +sensible). + +### Related packages + +- [@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/vectors](https://github.com/thi-ng/umbrella/tree/master/packages/vectors) - optimized 2d/3d/4d and arbitrary length vector ops +- [@thi.ng/vector-pools](https://github.com/thi-ng/umbrella/tree/master/packages/vector-pools) - operations on memory mapped data + +## Installation + +```bash +yarn add @thi.ng/matrices +``` + +## 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/math](https://github.com/thi-ng/umbrella/tree/master/packages/math) +- [@thi.ng/vectors](https://github.com/thi-ng/umbrella/tree/master/packages/vectors) + +## Usage examples + +```ts +import * as m from "@thi.ng/matrices"; +``` + +## API + +### Constants + +- `IDENT22` / `IDENT23` / `IDENT33` / `IDENT44` + +### Matrix creation + +- `rotation22` / `rotation23` +- `rotationAroundAxis33` / `rotationAroundAxis44` +- `rotationX33` / `rotationX44` +- `rotationY33` / `rotationY44` +- `rotationZ33` / `rotationZ44` +- `scale22` / `scale23` / `scale33` / `scale44` +- `scaleWithCenter23` / `scaleWithCenter44` +- `shearX22` / `shearY22` +- `shearX23` / `shearY23` +- `shearXY33` / `shearXZ33` / `shearYX33` / `shearYZ33` / `shearZX33` / `shearZY33` +- `shearXY44` / `shearXZ44` / `shearYX44` / `shearYZ44` / `shearZX44` / `shearZY44` +- `skewX22` / `skewY22` +- `skewX23` / `skewY23` +- `skewXY33` / `skewXZ33` / `skewYX33` / `skewYZ33` / `skewZX33` / `skewZY33` +- `skewXY44` / `skewXZ44` / `skewYX44` / `skewYZ44` / `skewZX44` / `skewZY44` +- `translation23` / `translation44` + +#### WebGL related + +- `frustum` / `frustumBounds` +- `lookAt` +- `ortho` +- `perspective` +- `viewport` + +### Matrix conversion + +- `mat33to44` / `mat44to33` +- `normal44` + +### Setters + +- `set` / `set22` / `set23` / `set33` / `set44` +- `identity` / `identity22` / `identity23` / `identity33` / `identity44` + +### Row & column accessors + +- `column` / `column22` / `column23` / `column33` / `column44` +- `row` / `row22` / `row23` / `row33` / `row44` + +### Componentwise matrix - matrix + +- `add` / `add22` / `add23` / `add33` / `add44` +- `div` / `div22` / `div23` / `div33` / `div44` +- `mul` / `mul22` / `mul23` / `mul33` / `mul44` +- `sub` / `sub22` / `sub23` / `sub33` / `sub44` + +### Componentwise matrix - scalar + +- `addN` / `addN22` / `addN23` / `addN33` / `addN44` +- `divN` / `divN22` / `divN23` / `divN33` / `divN44` +- `mulN` / `mulN22` / `mulN23` / `mulN33` / `mulN44` +- `subN` / `subN22` / `subN23` / `subN33` / `subN44` + +### Matrix multiplication + +- `mulM` / `mulM22` / `mulM23` / `mulM33` / `mulM44` +- `concat` + +### Matrix - vector multiplication + +- `mulV` / `mulV22` / `mulV23` / `mulV33` / `mulV344` / `mulV44` +- `project` +- `unproject` + +### Determinant & inversion + +- `det22` / `det23` / `det33` / `det44` +- `det44FromCoeffs` / `detCoeffs44` +- `diag` / `diag22` / `diag23` / `diag33` / `diag44` +- `invert` / `invert22` / `invert23` / `invert33` / `invert44` +- `trace` + +### Matrix transposition + +- `transpose22` / `transpose33` / `transpose44` + +### Quaternion + +- `alignmentQuat` +- `conjugateQ` +- `invertQ` +- `mixQ` +- `mulQ` +- `mulVQ` +- `quatFromAxisAngle` +- `quatFromEuler` +- `quatToAxisAngle` +- `quatToMat33` +- `quatToMat44` + +## Authors + +- Karsten Schmidt + +## License + +© 2018 Karsten Schmidt // Apache Software License 2.0 diff --git a/packages/matrices/package.json b/packages/matrices/package.json new file mode 100644 index 0000000000..94d7fbbf9b --- /dev/null +++ b/packages/matrices/package.json @@ -0,0 +1,81 @@ +{ + "name": "@thi.ng/matrices", + "version": "0.1.0", + "description": "Matrix & quaternion operations for 2D/3D geometry processing", + "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/matrices", + "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 matrices api checks math vectors", + "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": "typedoc --mode modules --out doc src", + "pub": "yarn build && yarn publish --access public" + }, + "devDependencies": { + "@types/mocha": "^5.2.5", + "@types/node": "^10.12.15", + "mocha": "^5.2.0", + "nyc": "^13.1.0", + "typedoc": "^0.14.0", + "typescript": "^3.2.2" + }, + "dependencies": { + "@thi.ng/api": "^5.0.0", + "@thi.ng/checks": "^2.0.0", + "@thi.ng/math": "^1.0.0", + "@thi.ng/vectors": "^2.0.0" + }, + "keywords": [ + "2D", + "3D", + "ES6", + "code generator", + "conversion", + "column", + "euler angles", + "frustum", + "geometry", + "invert", + "linear algebra", + "lookat", + "math", + "matrix", + "ortho", + "perspective", + "projection", + "quaternion", + "rotation", + "row", + "scale", + "shear", + "skew", + "translation", + "transformation", + "typescript", + "vector", + "webgl" + ], + "publishConfig": { + "access": "public" + }, + "browserslist": [ + "since 2018-07" + ], + "browser": { + "process": false, + "setTimeout": false + }, + "sideEffects": false +} diff --git a/packages/matrices/src/add.ts b/packages/matrices/src/add.ts new file mode 100644 index 0000000000..4a704f8eb7 --- /dev/null +++ b/packages/matrices/src/add.ts @@ -0,0 +1,17 @@ +import { add as _add, add4 } from "@thi.ng/vectors"; +import { MatOpMM, MultiMatOpMM } from "./api"; +import { defMath } from "./internal/codegen"; + +/** + * Componentwise matrix addition. If `out` is not given, writes result + * in `a`. + * + * out = a + b + * + * @param out + * @param a + * @param b + */ +export const add: MultiMatOpMM = _add; +export const add22: MatOpMM = add4; +export const [add23, add33, add44] = defMath(add, "+"); diff --git a/packages/matrices/src/addn.ts b/packages/matrices/src/addn.ts new file mode 100644 index 0000000000..4b4da795bb --- /dev/null +++ b/packages/matrices/src/addn.ts @@ -0,0 +1,17 @@ +import { addN as _addN, addN4 } from "@thi.ng/vectors"; +import { MatOpMN, MultiMatOpMN } from "./api"; +import { defMathN } from "./internal/codegen"; + +/** + * Adds single scalar componentwise to matrix. If `out` is not given, + * writes result in `mat`. + * + * out = mat + n + * + * @param out + * @param mat + * @param n + */ +export const addN: MultiMatOpMN = _addN; +export const addN22: MatOpMN = addN4; +export const [addN23, addN33, addN44] = defMathN(addN, "+"); diff --git a/packages/matrices/src/alignment-quat.ts b/packages/matrices/src/alignment-quat.ts new file mode 100644 index 0000000000..53ee7ca13a --- /dev/null +++ b/packages/matrices/src/alignment-quat.ts @@ -0,0 +1,30 @@ +import { + cross3, + dot3, + mag, + normalize as _normalize, + ReadonlyVec +} from "@thi.ng/vectors"; +import { quatFromAxisAngle } from "./quat-axis-angle"; + +/** + * Returns quaternion describing the rotation from direction vector + * `from` -> `to`. If `normalize` is true (default), first normalizes + * the vectors (not modifying original). + * + * @param from + * @param to + * @param normalize + */ +export const alignmentQuat = + (from: ReadonlyVec, to: ReadonlyVec, normalize = true) => { + if (normalize) { + from = _normalize([], from); + to = _normalize([], to); + } + const axis = cross3([], from, to); + return quatFromAxisAngle( + axis, + Math.atan2(mag(axis), dot3(from, to)) + ) + }; diff --git a/packages/matrices/src/api.ts b/packages/matrices/src/api.ts new file mode 100644 index 0000000000..04b1fc68ba --- /dev/null +++ b/packages/matrices/src/api.ts @@ -0,0 +1,50 @@ +import { Vec, ReadonlyVec, IVector, MultiVecOp } from "@thi.ng/vectors"; + +export type Mat = Vec; +export type ReadonlyMat = ReadonlyVec; +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 VecOpM = (out: Vec, a: ReadonlyMat) => Vec; +export type VecOpMN = (out: Vec, a: ReadonlyMat, n: number) => Vec; + +export interface MultiMatOp1 extends MatOp1, MultiMatOp { } +export interface MultiMatOpM extends MatOpM, MultiMatOp { } +export interface MultiMatOpN extends MatOpN, MultiMatOp { } +export interface MultiMatOpMM extends MatOpMM, MultiMatOp { } +export interface MultiMatOpMV extends MatOpMV, MultiMatOp { } +export interface MultiMatOpMN extends MatOpMN, MultiMatOp { } + +export interface MultiVecOpM extends VecOpM, MultiMatOp { } +export interface MultiVecOpMN extends VecOpMN, MultiMatOp { } + +export const IDENT22 = [ + 1, 0, + 0, 1 +]; + +export const IDENT23 = [ + 1, 0, + 0, 1, + 0, 0 +]; + +export const IDENT33 = [ + 1, 0, 0, + 0, 1, 0, + 0, 0, 1 +]; + +export const IDENT44 = [ + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 +]; diff --git a/packages/matrices/src/column.ts b/packages/matrices/src/column.ts new file mode 100644 index 0000000000..5d334c226e --- /dev/null +++ b/packages/matrices/src/column.ts @@ -0,0 +1,29 @@ +import { + setS2, + setS3, + setS4, + vop +} from "@thi.ng/vectors"; +import { MultiVecOpMN, VecOpMN } from "./api"; + +/** + * Extracts column vector from given matrix and writes result to `out`. + * If `out` is null, creates new vector. + * + * @param out + * @param mat + * @param column + */ +export const column: MultiVecOpMN = vop(1); + +export const column22: VecOpMN = + column.add(4, (out, m, n) => setS2(out, m, 0, n * 2)); + +export const column23: VecOpMN = + column.add(6, column22); + +export const column33: VecOpMN = + column.add(9, (out, m, n) => setS3(out, m, 0, n * 3)); + +export const column44: VecOpMN = + column.add(16, (out, m, n) => setS4(out, m, 0, n * 4)); diff --git a/packages/matrices/src/concat.ts b/packages/matrices/src/concat.ts new file mode 100644 index 0000000000..e8c3d4390f --- /dev/null +++ b/packages/matrices/src/concat.ts @@ -0,0 +1,19 @@ +import { Mat, ReadonlyMat } from "./api"; +import { mulM } from "./mulm"; + +/** + * Concatenates / multiplies given matrices in left-to-right order. A + * minimum of 2 input matrices must be given. If `out` is null, writes + * result into `a`. + * + * @param out + * @param a + * @param b + * @param xs + */ +export const concat = + (out: Mat, a: ReadonlyMat, b: ReadonlyMat, ...xs: ReadonlyMat[]) => + xs.reduce( + (acc: Mat, x) => mulM(acc, acc, x), + mulM(out, a, b) + ); diff --git a/packages/matrices/src/conjugate.ts b/packages/matrices/src/conjugate.ts new file mode 100644 index 0000000000..bcc893ac42 --- /dev/null +++ b/packages/matrices/src/conjugate.ts @@ -0,0 +1,11 @@ +import { ReadonlyVec, setC4, Vec } from "@thi.ng/vectors"; + +export const conjugateQ = + (out: Vec, a: ReadonlyVec) => + setC4( + out || a, + -a[0], + -a[1], + -a[2], + a[3] + ); diff --git a/packages/matrices/src/determinant.ts b/packages/matrices/src/determinant.ts new file mode 100644 index 0000000000..5bec25d4f6 --- /dev/null +++ b/packages/matrices/src/determinant.ts @@ -0,0 +1,57 @@ +import { dotC4, dotC6 } from "@thi.ng/vectors"; +import { ReadonlyMat } from "./api"; + +const dp4 = dotC4; +const dp6 = dotC6; + +export const det22 = + (m: ReadonlyMat) => + dp4(m[0], m[3], -m[1], m[2]); + +export const det23 = det22; + +export const det33 = + (m: ReadonlyMat) => { + 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); + const d21 = dp4(m21, m10, -m11, m20); + return dp6(m00, d01, m01, d11, m02, d21); + }; + +export const detCoeffs44 = + (m: ReadonlyMat) => { + const [ + m00, m01, m02, m03, + m10, m11, m12, m13, + m20, m21, m22, m23, + m30, m31, m32, m33 + ] = m; + return [ + dp4(m00, m11, -m01, m10), + dp4(m00, m12, -m02, m10), + dp4(m00, m13, -m03, m10), + dp4(m01, m12, -m02, m11), + dp4(m01, m13, -m03, m11), + dp4(m02, m13, -m03, m12), + dp4(m20, m31, -m21, m30), + dp4(m20, m32, -m22, m30), + dp4(m20, m33, -m23, m30), + dp4(m21, m32, -m22, m31), + dp4(m21, m33, -m23, m31), + dp4(m22, m33, -m23, m32) + ]; + }; + +export const det44FromCoeffs = + (d: number[]) => + dp6(d[0], d[11], -d[1], d[10], d[2], d[9]) + + dp6(d[3], d[8], -d[4], d[7], d[5], d[6]); + +export const det44 = + (m: ReadonlyMat) => + det44FromCoeffs(detCoeffs44(m)); diff --git a/packages/matrices/src/diag.ts b/packages/matrices/src/diag.ts new file mode 100644 index 0000000000..46ff4affc3 --- /dev/null +++ b/packages/matrices/src/diag.ts @@ -0,0 +1,22 @@ +import { vop, setS2, setS3, setS4 } from "@thi.ng/vectors"; +import { MultiVecOpM } from "./api"; + +/** + * Extracts matrix diagonal into `out`. + * + * @param out + * @param mat + */ +export const diag: MultiVecOpM = vop(1); + +export const diag22 = + diag.add(4, (out, m) => setS2(out, m, 0, 0, 1, 3)); + +export const diag23 = + diag.add(6, diag22); + +export const diag33 = + diag.add(9, (out, m) => setS3(out, m, 0, 0, 1, 4)); + +export const diag44 = + diag.add(16, (out, m) => setS4(out, m, 0, 0, 1, 5)); diff --git a/packages/matrices/src/div.ts b/packages/matrices/src/div.ts new file mode 100644 index 0000000000..3174d93880 --- /dev/null +++ b/packages/matrices/src/div.ts @@ -0,0 +1,17 @@ +import { div as _div, div4 } from "@thi.ng/vectors"; +import { MatOpMM, MultiMatOpMM } from "./api"; +import { defMath } from "./internal/codegen"; + +/** + * Componentwise matrix division. If `out` is not given, writes result + * in `a`. + * + * out = a / b + * + * @param out + * @param a + * @param b + */ +export const div: MultiMatOpMM = _div; +export const div22: MatOpMM = div4; +export const [div23, div33, div44] = defMath(div, "/"); diff --git a/packages/matrices/src/divn.ts b/packages/matrices/src/divn.ts new file mode 100644 index 0000000000..244a36b3d9 --- /dev/null +++ b/packages/matrices/src/divn.ts @@ -0,0 +1,17 @@ +import { divN as _divN, divN4 } from "@thi.ng/vectors"; +import { MatOpMN, MultiMatOpMN } from "./api"; +import { defMathN } from "./internal/codegen"; + +/** + * Componentwise matrix division by single scalar. If `out` is not + * given, writes result in `mat`. + * + * out = mat / n + * + * @param out + * @param mat + * @param n + */ +export const divN: MultiMatOpMN = _divN; +export const divN22: MatOpMN = divN4; +export const [divN23, divN33, divN44] = defMathN(divN, "/"); diff --git a/packages/matrices/src/frustum.ts b/packages/matrices/src/frustum.ts new file mode 100644 index 0000000000..59d273fc5d --- /dev/null +++ b/packages/matrices/src/frustum.ts @@ -0,0 +1,55 @@ +import { DEG2RAD } from "@thi.ng/math"; +import { setC } from "@thi.ng/vectors"; +import { Mat } from "./api"; + +/** + * Constructs a M44 representing the given view frustum. + * + * @param out + * @param left + * @param right + * @param bottom + * @param top + * @param near + * @param far + */ +export const frustum = ( + out: Mat, + left: number, + right: number, + bottom: number, + top: number, + near: number, + far: number) => { + + const dx = 1 / (right - left); + const dy = 1 / (top - bottom); + const dz = 1 / (far - near); + + return setC( + out || [], + near * 2 * dx, 0, 0, 0, + 0, near * 2 * dy, 0, 0, + (right + left) * dx, (top + bottom) * dy, -(far + near) * dz, -1, + 0, 0, -(far * near * 2) * dz, 0, + ); +}; + +export const frustumBounds = ( + fovy: number, + aspect: number, + near: number, + far: number) => { + + const top = near * Math.tan(fovy * DEG2RAD / 2); + const right = top * aspect; + + return { + left: -right, + right, + bottom: -top, + top, + near, + far + }; +}; diff --git a/packages/matrices/src/identity.ts b/packages/matrices/src/identity.ts new file mode 100644 index 0000000000..406a42610d --- /dev/null +++ b/packages/matrices/src/identity.ts @@ -0,0 +1,26 @@ +import { vop } from "@thi.ng/vectors"; +import { + IDENT22, + IDENT23, + IDENT33, + IDENT44, + MultiMatOp1 +} from "./api"; +import { set } from "./set"; + +/** + * Writes identity matrix into given matrix. + */ +export const identity: MultiMatOp1 = vop(); + +export const identity22 = + identity.add(4, (m) => set(m, IDENT22)); + +export const identity23 = + identity.add(6, (m) => set(m, IDENT23)); + +export const identity33 = + identity.add(9, (m) => set(m, IDENT33)); + +export const identity44 = + identity.add(9, (m) => set(m, IDENT44)); diff --git a/packages/matrices/src/index.ts b/packages/matrices/src/index.ts new file mode 100644 index 0000000000..d1ad224c37 --- /dev/null +++ b/packages/matrices/src/index.ts @@ -0,0 +1,50 @@ +export * from "./api"; +export * from "./internal/codegen"; + +export * from "./add"; +export * from "./addn"; +export * from "./alignment-quat"; +export * from "./column"; +export * from "./concat"; +export * from "./conjugate"; +export * from "./determinant"; +export * from "./diag"; +export * from "./div"; +export * from "./divn"; +export * from "./frustum"; +export * from "./identity"; +export * from "./invert"; +export * from "./lookat"; +export * from "./m22-m23"; +export * from "./m23-m22"; +export * from "./m23-m44"; +export * from "./m33-m44"; +export * from "./m44-m33"; +export * from "./mixq"; +export * from "./mul"; +export * from "./mulm"; +export * from "./muln"; +export * from "./mulq"; +export * from "./mulv"; +export * from "./normal-mat"; +export * from "./ortho"; +export * from "./perspective"; +export * from "./project"; +export * from "./quat-axis-angle"; +export * from "./quat-euler"; +export * from "./quat-m33"; +export * from "./quat-m44"; +export * from "./rotation-around-axis"; +export * from "./rotation"; +export * from "./row"; +export * from "./scale"; +export * from "./scale-center"; +export * from "./set"; +export * from "./shear"; +export * from "./skew"; +export * from "./sub"; +export * from "./subn"; +export * from "./trace"; +export * from "./translation"; +export * from "./transpose"; +export * from "./viewport"; diff --git a/packages/matrices/src/internal/codegen.ts b/packages/matrices/src/internal/codegen.ts new file mode 100644 index 0000000000..c6436e5528 --- /dev/null +++ b/packages/matrices/src/internal/codegen.ts @@ -0,0 +1,19 @@ +import { + ARGS_VN, + ARGS_VV, + compile, + DEFAULT_OUT, + MATH, + MATH_N +} from "@thi.ng/vectors"; +import { MultiMatOpMM, MultiMatOpMN } from "../api"; + +const DEFAULT_SIZES = [6, 9, 16]; + +export const defMath = + (fn: MultiMatOpMM, op: string, sizes = DEFAULT_SIZES) => + sizes.map((n) => fn.add(n, compile(n, MATH(op), ARGS_VV, undefined, "o", "", DEFAULT_OUT))); + +export const defMathN = + (fn: MultiMatOpMN, op: string, sizes = DEFAULT_SIZES) => + sizes.map((n) => fn.add(n, compile(n, MATH_N(op), ARGS_VN, "o,a", "o", "", DEFAULT_OUT))); diff --git a/packages/matrices/src/invert.ts b/packages/matrices/src/invert.ts new file mode 100644 index 0000000000..7085e37457 --- /dev/null +++ b/packages/matrices/src/invert.ts @@ -0,0 +1,118 @@ +import { + dotC4, + dotC6, + magSq4, + ReadonlyVec, + setC, + setC4, + setC6, + Vec, + vop +} from "@thi.ng/vectors"; +import { MatOpM, MultiMatOpM } from "./api"; +import { det44FromCoeffs, detCoeffs44 } from "./determinant"; + +const dp4 = dotC4; +const dp6 = dotC6; + +/** + * Matrix inversion. + */ +export const invert: MultiMatOpM = vop(1); + +export const invert22: MatOpM = + invert.add(4, (out, m) => { + const [m00, m01, m10, m11] = m; + let det = dp4(m00, m11, -m01, m10); + if (det === 0) return; + det = 1.0 / det; + return setC4( + out || m, + m11 * det, + -m01 * det, + -m10 * det, + m00 * det, + ); + }); + +export const invert23: MatOpM = + invert.add(6, (out, m) => { + const [m00, m01, m10, m11, m20, m21] = m; + let det = dp4(m00, m11, -m01, m10); + if (det === 0) return; + det = 1.0 / det; + return setC6( + out || m, + m11 * det, + -m01 * det, + -m10 * det, + m00 * det, + dp4(m10, m21, -m11, m20) * det, + dp4(m01, m20, -m00, m21) * det + ); + }); + +export const invert33: MatOpM = + 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); + const d21 = dp4(m21, m10, -m11, m20); + let det = dp6(m00, d01, m01, d11, m02, d21); + if (det === 0) return; + det = 1.0 / det; + return setC( + out || m, + d01 * det, + dp4(-m22, m01, m02, m21) * det, + dp4(m12, m01, -m02, m11) * det, + d11 * det, + dp4(m22, m00, -m02, m20) * det, + dp4(-m12, m00, m02, m10) * det, + d21 * det, + dp4(-m21, m00, m01, m20) * det, + dp4(m11, m00, -m01, m10) * det, + ); + }); + +export const invert44: MatOpM = + invert.add(16, (out, m) => { + const coeffs = detCoeffs44(m); + let det = det44FromCoeffs(coeffs); + if (det === 0) return; + det = 1.0 / det; + const [m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33] = m; + const [d00, d01, d02, d03, d04, d05, d06, d07, d08, d09, d10, d11] = coeffs; + return setC( + out || m, + dp6(m11, d11, -m12, d10, m13, d09) * det, + dp6(-m01, d11, m02, d10, -m03, d09) * det, + dp6(m31, d05, - m32, d04, m33, d03) * det, + dp6(-m21, d05, m22, d04, -m23, d03) * det, + dp6(-m10, d11, m12, d08, -m13, d07) * det, + dp6(m00, d11, -m02, d08, m03, d07) * det, + dp6(-m30, d05, m32, d02, -m33, d01) * det, + dp6(m20, d05, -m22, d02, m23, d01) * det, + dp6(m10, d10, -m11, d08, m13, d06) * det, + dp6(-m00, d10, m01, d08, -m03, d06) * det, + dp6(m30, d04, -m31, d02, m33, d00) * det, + dp6(-m20, d04, m21, d02, -m23, d00) * det, + dp6(-m10, d09, m11, d07, -m12, d06) * det, + dp6(m00, d09, -m01, d07, m02, d06) * det, + dp6(-m30, d03, m31, d01, -m32, d00) * det, + dp6(m20, d03, -m21, d01, m22, d00) * det + ); + }); + +export const invertQ = + (out: Vec, 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 + ); + }; \ No newline at end of file diff --git a/packages/matrices/src/lookat.ts b/packages/matrices/src/lookat.ts new file mode 100644 index 0000000000..e1eb49f9f4 --- /dev/null +++ b/packages/matrices/src/lookat.ts @@ -0,0 +1,37 @@ +import { + cross3, + dot3, + normalize, + ReadonlyVec, + setC, + sub3 +} from "@thi.ng/vectors"; +import { Mat } from "./api"; + +/** + * Constructs a M44 camera matrix for given `eye` position, look-at `target` + * (both in world space) and `up` vector. + * + * @param out + * @param eye + * @param target + * @param up + */ +export const lookAt = ( + out: Mat, + eye: ReadonlyVec, + target: ReadonlyVec, + up: ReadonlyVec) => { + + const z = normalize(null, sub3([], eye, target)); + const x = normalize(null, cross3([], up, z)); + const y = normalize(null, cross3([], z, x)); + + return setC( + out || [], + x[0], y[0], z[0], 0, + x[1], y[1], z[1], 0, + x[2], y[2], z[2], 0, + -dot3(eye, x), -dot3(eye, y), -dot3(eye, z), 1, + ); +}; diff --git a/packages/matrices/src/m22-m23.ts b/packages/matrices/src/m22-m23.ts new file mode 100644 index 0000000000..c35b2a4ac2 --- /dev/null +++ b/packages/matrices/src/m22-m23.ts @@ -0,0 +1,16 @@ +import { set4 } from "@thi.ng/vectors"; +import { MatOpM } from "./api"; + +/** + * Converts M22 to M23 and writes result to `out`. + * + * @param out + * @param m22 + */ +export const mat22to23: MatOpM = + (out, m22) => ( + !out && (out = []), + set4(out, m22), + out[4] = out[5] = 0, + out + ); diff --git a/packages/matrices/src/m23-m22.ts b/packages/matrices/src/m23-m22.ts new file mode 100644 index 0000000000..d2e7b0f2b2 --- /dev/null +++ b/packages/matrices/src/m23-m22.ts @@ -0,0 +1,11 @@ +import { set4 } from "@thi.ng/vectors"; +import { MatOpM } from "./api"; + +/** + * Converts M23 to M22 and writes result to `out`. + * + * @param out + * @param m23 + */ +export const mat23to22: MatOpM = + (out, m23) => set4(out || [], m23); diff --git a/packages/matrices/src/m23-m44.ts b/packages/matrices/src/m23-m44.ts new file mode 100644 index 0000000000..f3e2506fe6 --- /dev/null +++ b/packages/matrices/src/m23-m44.ts @@ -0,0 +1,21 @@ +import { MatOpM } from "./api"; + +/** + * Converts M23 to M44 and writes result to `out`. + * + * @param out + * @param m23 + */ +export const mat23to44: MatOpM = + (out, m23) => ( + !out && (out = []), + out[0] = m23[0], + out[1] = m23[1], + out[4] = m23[2], + out[5] = m23[3], + out[12] = m23[4], + out[13] = m23[5], + out[10] = out[15] = 1, + out[2] = out[3] = out[6] = out[7] = out[8] = out[9] = out[11] = out[14] = 0, + out + ); diff --git a/packages/matrices/src/m33-m44.ts b/packages/matrices/src/m33-m44.ts new file mode 100644 index 0000000000..fb5863b65b --- /dev/null +++ b/packages/matrices/src/m33-m44.ts @@ -0,0 +1,18 @@ +import { setS3, setS4, ZERO4 } from "@thi.ng/vectors"; +import { MatOpM } from "./api"; + +/** + * Converts M33 to M44 and writes result to `out`. + * + * @param out + * @param m33 + */ +export const mat33to44: MatOpM = + (out, m33) => ( + !out && (out = []), + setS3(out, m33, 0, 0), + setS3(out, m33, 4, 3), + setS3(out, m33, 8, 6), + setS3(out, ZERO4, 12), + setS4(out, [0, 0, 0, 1], 3, 0, 4) + ); diff --git a/packages/matrices/src/m44-m33.ts b/packages/matrices/src/m44-m33.ts new file mode 100644 index 0000000000..4185a2e036 --- /dev/null +++ b/packages/matrices/src/m44-m33.ts @@ -0,0 +1,16 @@ +import { setS3 } from "@thi.ng/vectors"; +import { MatOpM } from "./api"; + +/** + * Converts M44 to M33 and writes result to `out`. + * + * @param out + * @param m44 + */ +export const mat44to33: MatOpM = + (out, m44) => ( + !out && (out = []), + setS3(out, m44), + setS3(out, m44, 3, 4), + setS3(out, m44, 6, 8) + ); diff --git a/packages/matrices/src/mixq.ts b/packages/matrices/src/mixq.ts new file mode 100644 index 0000000000..1aac7433a7 --- /dev/null +++ b/packages/matrices/src/mixq.ts @@ -0,0 +1,38 @@ +import { + dot4, + maddN4, + mulN4, + ReadonlyVec, + set4, + Vec +} from "@thi.ng/vectors"; + +/** + * Interpolates quaternion `a` to `b` by given amount `t`, using SLERP. + * Writes result to `out`. The optional `eps` (default 1e-3) is used to + * switch to linear interpolation if the angular difference is very + * small. + * + * @param out + * @param a + * @param b + * @param t + * @param eps + */ +export const mixQ = + (out: Vec, a: ReadonlyVec, b: ReadonlyVec, t: number, eps = 1e-3) => { + const d = dot4(a, b); + if (Math.abs(d) < 1.0) { + const theta = Math.acos(d); + const stheta = Math.sqrt(1 - d * d); + let u: number, v: number; + if (Math.abs(stheta) < eps) { + u = v = 0.5; + } else { + u = Math.sin(theta * (1 - t)) / stheta; + v = Math.sin(theta * t) / stheta; + } + return maddN4(null, mulN4(out, a, u), b, v); + } + return a !== out ? set4(out, a) : out; + }; diff --git a/packages/matrices/src/mul.ts b/packages/matrices/src/mul.ts new file mode 100644 index 0000000000..c9fe8fbca6 --- /dev/null +++ b/packages/matrices/src/mul.ts @@ -0,0 +1,17 @@ +import { mul as _mul, mul4 } from "@thi.ng/vectors"; +import { MatOpMM, MultiMatOpMM } from "./api"; +import { defMath } from "./internal/codegen"; + +/** + * Componentwise matrix addition. Use `mulM` for actual matrix-matrix + * multiplication. If `out` is not given, writes result in `a`. + * + * out = a * b + * + * @param out + * @param a + * @param b + */ +export const mul: MultiMatOpMM = _mul; +export const mul22: MatOpMM = mul4; +export const [mul23, mul33, mul44] = defMath(mul, "*"); diff --git a/packages/matrices/src/mulm.ts b/packages/matrices/src/mulm.ts new file mode 100644 index 0000000000..f7ba591fd0 --- /dev/null +++ b/packages/matrices/src/mulm.ts @@ -0,0 +1,83 @@ +import { + dotS2, + dotS3, + dotS4, + setC, + setC4, + setC6, + vop +} from "@thi.ng/vectors"; +import { MultiMatOpMM } from "./api"; + +/** + * Performs matrix-matrix multiplication. If `out` is not given, writes + * result in `a`. + * + * @param out + * @param a + * @param b + */ +export const mulM: MultiMatOpMM = vop(1); + +export const mulM22 = + mulM.add(4, (out, a, b) => + setC4( + out || a, + dotS2(a, b, 0, 0, 2), + dotS2(a, b, 1, 0, 2), + dotS2(a, b, 0, 2, 2), + dotS2(a, b, 1, 2, 2) + ) + ); + +export const mulM23 = + mulM.add(6, (out, a, b) => + setC6( + out || a, + dotS2(a, b, 0, 0, 2), + dotS2(a, b, 1, 0, 2), + dotS2(a, b, 0, 2, 2), + dotS2(a, b, 1, 2, 2), + dotS2(a, b, 0, 4, 2) + a[4], + dotS2(a, b, 1, 4, 2) + a[5] + ) + ); + +export const mulM33 = + mulM.add(9, (out, a, b) => + setC( + out || a, + dotS3(a, b, 0, 0, 3), + dotS3(a, b, 1, 0, 3), + dotS3(a, b, 2, 0, 3), + dotS3(a, b, 0, 3, 3), + dotS3(a, b, 1, 3, 3), + dotS3(a, b, 2, 3, 3), + dotS3(a, b, 0, 6, 3), + dotS3(a, b, 1, 6, 3), + dotS3(a, b, 2, 6, 3) + ) + ); + +export const mulM44 = + mulM.add(16, (out, a, b) => + setC( + out || a, + dotS4(a, b, 0, 0, 4), + dotS4(a, b, 1, 0, 4), + dotS4(a, b, 2, 0, 4), + dotS4(a, b, 3, 0, 4), + dotS4(a, b, 0, 4, 4), + dotS4(a, b, 1, 4, 4), + dotS4(a, b, 2, 4, 4), + dotS4(a, b, 3, 4, 4), + dotS4(a, b, 0, 8, 4), + dotS4(a, b, 1, 8, 4), + dotS4(a, b, 2, 8, 4), + dotS4(a, b, 3, 8, 4), + dotS4(a, b, 0, 12, 4), + dotS4(a, b, 1, 12, 4), + dotS4(a, b, 2, 12, 4), + dotS4(a, b, 3, 12, 4) + ) + ); diff --git a/packages/matrices/src/muln.ts b/packages/matrices/src/muln.ts new file mode 100644 index 0000000000..72b7224ce9 --- /dev/null +++ b/packages/matrices/src/muln.ts @@ -0,0 +1,17 @@ +import { mulN as _mulN, mulN4 } from "@thi.ng/vectors"; +import { MatOpMN, MultiMatOpMN } from "./api"; +import { defMathN } from "./internal/codegen"; + +/** + * Multiplies matrix componentwise with single scalar. If `out` is not + * given, writes result in `mat`. + * + * out = mat * n + * + * @param out + * @param mat + * @param n + */ +export const mulN: MultiMatOpMN = _mulN; +export const mulN22: MatOpMN = mulN4; +export const [mulN23, mulN33, mulN44] = defMathN(mulN, "*"); diff --git a/packages/matrices/src/mulq.ts b/packages/matrices/src/mulq.ts new file mode 100644 index 0000000000..d3841f4d9b --- /dev/null +++ b/packages/matrices/src/mulq.ts @@ -0,0 +1,22 @@ +import { ReadonlyVec, setC4, Vec } from "@thi.ng/vectors"; + +/** + * Performs quaternion multiplication of `a` and `b` and writes result + * to `out`. If `out` is null, writes result into `a`. + * + * @param out + * @param a + * @param b + */ +export const mulQ = + (out: Vec, a: ReadonlyVec, b: ReadonlyVec) => { + const { 0: ax, 1: ay, 2: az, 3: aw } = a; + const { 0: bx, 1: by, 2: bz, 3: bw } = b; + return setC4( + out || a, + ax * bw + aw * bx + ay * bz - az * by, + ay * bw + aw * by + az * bx - ax * bz, + az * bw + aw * bz + ax * by - ay * bx, + aw * bw - ax * bx - ay * by - az * bz + ); + }; diff --git a/packages/matrices/src/mulv.ts b/packages/matrices/src/mulv.ts new file mode 100644 index 0000000000..c145b2338c --- /dev/null +++ b/packages/matrices/src/mulv.ts @@ -0,0 +1,137 @@ +import { + dotS2, + dotS3, + dotS4, + ReadonlyVec, + setC2, + setC3, + setC4, + Vec, + vop +} from "@thi.ng/vectors"; +import { MatOpMV, MultiMatOpMV } from "./api"; + +/** + * Matrix-vector multiplication. Supports in-place modification, i.e. if + * `out === v`. + * + * @param out + * @param m + * @param v + */ +export const mulV: MultiMatOpMV = vop(1); + +/** + * Multiplies M22 `m` with 2D vector `v`. Supports in-place + * modification, i.e. if `out === v`. + * + * @param out + * @param m + * @param v + */ +export const mulV22: MatOpMV = + mulV.add(4, (out, m, v) => + setC2( + out || v, + dotS2(m, v, 0, 0, 2), + dotS2(m, v, 1, 0, 2) + ) + ); + +/** + * Multiplies M23 `m` with 2D vector `v`. Supports in-place + * modification, i.e. if `out === v`. + * + * @param out + * @param m + * @param v + */ +export const mulV23: MatOpMV = + mulV.add(6, (out, m, v) => + setC2( + out || v, + dotS2(m, v, 0, 0, 2) + m[4], + dotS2(m, v, 1, 0, 2) + m[5] + ) + ); + +/** + * Multiplies M33 `m` with 3D vector `v`. Supports in-place + * modification, i.e. if `out === v`. + * + * @param out + * @param m + * @param v + */ +export const mulV33: MatOpMV = + mulV.add(9, (out, m, v) => + setC3( + out || v, + dotS3(m, v, 0, 0, 3), + dotS3(m, v, 1, 0, 3), + dotS3(m, v, 2, 0, 3) + ) + ); + +/** + * Multiplies M44 `m` with 4D vector `v`. Supports in-place + * modification, i.e. if `out === v`. + * + * @param out + * @param m + * @param v + */ +export const mulV44: MatOpMV = + mulV.add(16, (out, m, v) => + setC4( + out || v, + dotS4(m, v, 0, 0, 4), + dotS4(m, v, 1, 0, 4), + dotS4(m, v, 2, 0, 4), + dotS4(m, v, 3, 0, 4) + ) + ); + +/** + * Multiplies M44 `m` with 3D vector `v` and assumes `w=1`, i.e. the + * vector is interpreted as `[x,y,z,1]`. After transformation applies + * perspective divide of the resulting XYZ components. + * + * @param out + * @param m + * @param v + */ +export const mulV344: MatOpMV = + (out, m, v) => { + const w = dotS3(m, v, 3, 0, 4) || 1; + return setC3( + out || v, + (dotS3(m, v, 0, 0, 4) + m[12]) / w, + (dotS3(m, v, 1, 0, 4) + m[13]) / w, + (dotS3(m, v, 2, 0, 4) + m[14]) / w + ); + }; + +/** + * Multiplies quaternion `q` with 3D vector `v`. Returns transformed + * vector or modifies in-place if `out` is null or `v`. + * + * @param out + * @param q + * @param v + */ +export const mulVQ = + (out: Vec, q: ReadonlyVec, v: ReadonlyVec) => { + 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; + const iy = qw * py + qz * px - qx * pz; + const iz = qw * pz + qx * py - qy * px; + const iw = -qx * px - qy * py - qz * pz; + return setC3( + out || v, + ix * qw + iw * -qx + iy * -qz - iz * -qy, + iy * qw + iw * -qy + iz * -qx - ix * -qz, + iz * qw + iw * -qz + ix * -qy - iy * -qx + ); + }; diff --git a/packages/matrices/src/normal-mat.ts b/packages/matrices/src/normal-mat.ts new file mode 100644 index 0000000000..9d911aba28 --- /dev/null +++ b/packages/matrices/src/normal-mat.ts @@ -0,0 +1,15 @@ +import { MatOpM } from "./api"; +import { mat44to33 } from "./m44-m33"; +import { invert33 } from "./invert"; +import { transpose33 } from "./transpose"; + +/** + * Converts given M44 to a M33 normal matrix, i.e. the transposed + * inverted version of its upper-left 3x3 region. + * + * @param out + * @param m + */ +export const normal44: MatOpM = + (out, m) => + transpose33(null, invert33(null, mat44to33(out, m))); diff --git a/packages/matrices/src/ortho.ts b/packages/matrices/src/ortho.ts new file mode 100644 index 0000000000..e9567572ca --- /dev/null +++ b/packages/matrices/src/ortho.ts @@ -0,0 +1,35 @@ +import { setC } from "@thi.ng/vectors"; +import { Mat } from "./api"; + +/** + * Computes a M44 orthographic projection matrix and writes result to + * `out`. + * + * @param out + * @param left + * @param right + * @param bottom + * @param top + * @param near + * @param far + */ +export const ortho = ( + out: Mat, + left: number, + right: number, + bottom: number, + top: number, + near: number, + far: number) => { + + const dx = 1 / (right - left); + const dy = 1 / (top - bottom); + const dz = 1 / (far - near); + return setC( + out || [], + 2 * dx, 0, 0, 0, + 0, 2 * dy, 0, 0, + 0, 0, -2 * dz, 0, + -(left + right) * dx, -(top + bottom) * dy, -(far + near) * dz, 1, + ); +}; diff --git a/packages/matrices/src/perspective.ts b/packages/matrices/src/perspective.ts new file mode 100644 index 0000000000..899648e628 --- /dev/null +++ b/packages/matrices/src/perspective.ts @@ -0,0 +1,23 @@ +import { Mat } from "./api"; +import { frustum, frustumBounds } from "./frustum"; + +/** + * Computes a M44 perspective projection matrix and writes result to + * `out`. + * + * @param out + * @param fov + * @param aspect + * @param near + * @param far + */ +export const perspective = ( + out: Mat, + fov: number, + aspect: number, + near: number, + far: number) => { + + const f = frustumBounds(fov, aspect, near, far); + return frustum(out, f.left, f.right, f.bottom, f.top, f.near, f.far); +}; diff --git a/packages/matrices/src/project.ts b/packages/matrices/src/project.ts new file mode 100644 index 0000000000..2281004a21 --- /dev/null +++ b/packages/matrices/src/project.ts @@ -0,0 +1,51 @@ +import { + divN3, + dotC6, + fromHomogeneous4, + ReadonlyVec, + Vec +} from "@thi.ng/vectors"; +import { ReadonlyMat } from "./api"; +import { invert23, invert44 } from "./invert"; +import { mulV23, mulV344, mulV44 } from "./mulv"; + +/** + * Transforms given point `p` (4D, homogeneous) with M44 `mvp`, applies + * perspective divide and then transforms XY components with M23 `view` + * matrix. Returns 3D vector. The result Z component can be used for + * depth sorting. + * + * @param out + * @param mvp + * @param view + * @param p + */ +export const project = + (out: Vec, mvp: ReadonlyMat, view: ReadonlyMat, p: ReadonlyVec) => + mulV23(out, view, fromHomogeneous4(out, mulV44([], mvp, p))); + +/** + * Reverse operation of project. If `invert` is true (default: false), + * both `mvp` and `view` matrices will be inverted first + * (non-destructively), else they're both assumed to be inverted + * already. + * + * @param out + * @param mvp + * @param view + * @param p + * @param invert + */ +export const unproject = + (out: Vec, mvp: ReadonlyMat, view: ReadonlyMat, p: ReadonlyVec, doInvert = false) => { + if (doInvert) { + mvp = invert44([], mvp); + view = invert23([], view); + } + const q = [...mulV23([], view, p), p[2] * 2 - 1]; + return divN3( + out, + mulV344(out, mvp, q), + dotC6(q[0], mvp[3], q[1], mvp[7], q[2], mvp[11]) + mvp[15] + ); + }; diff --git a/packages/matrices/src/quat-axis-angle.ts b/packages/matrices/src/quat-axis-angle.ts new file mode 100644 index 0000000000..a0d6215dd0 --- /dev/null +++ b/packages/matrices/src/quat-axis-angle.ts @@ -0,0 +1,35 @@ +import { EPS } from "@thi.ng/math"; +import { normalize, ReadonlyVec } from "@thi.ng/vectors"; + +/** + * Computes a quaternion representing the rotation `theta` around + * `axis`. + * + * @param axis + * @param theta + */ +export const quatFromAxisAngle = + (axis: ReadonlyVec, theta: number) => { + theta /= 2; + return normalize( + [0, 0, 0, Math.cos(theta)], + axis, + Math.sin(theta) + ); + }; + +/** + * Decomposes quaternion into `[axis, theta]` tuple. + * + * @param quat + */ +export const quatToAxisAngle = + (quat: ReadonlyVec) => { + const n = normalize([], quat); + const w = n[3]; + const m = Math.sqrt(1 - w * w); + const theta = 2 * Math.acos(w); + return m > EPS ? + [[n[0] / m, n[1] / m, n[2] / m], theta] : + [[n[0], n[1], n[2]], theta]; + }; diff --git a/packages/matrices/src/quat-euler.ts b/packages/matrices/src/quat-euler.ts new file mode 100644 index 0000000000..8a9227efd2 --- /dev/null +++ b/packages/matrices/src/quat-euler.ts @@ -0,0 +1,32 @@ +import { X3, Y3, Z3 } from "@thi.ng/vectors"; +import { mulQ } from "./mulq"; +import { quatFromAxisAngle } from "./quat-axis-angle"; + +const axisOrder = { + "xyz": [X3, Y3, Z3], + "yxz": [Y3, X3, Z3], + "xzy": [X3, Z3, Y3], + "zxy": [Z3, X3, Y3], + "yzx": [Y3, Z3, X3], + "zyx": [Z3, Y3, X3], +}; + +/** + * Constructs a quaternion from given rotation angles in specified + * `order`. + * + * @param order + * @param a + * @param b + * @param c + */ +export const quatFromEuler = + (order: keyof typeof axisOrder, a: number, b: number, c: number) => { + const [aa, ab, ac] = axisOrder[order]; + return mulQ(null, + mulQ([], + quatFromAxisAngle(aa, a), + quatFromAxisAngle(ab, b)), + quatFromAxisAngle(ac, c) + ); + }; diff --git a/packages/matrices/src/quat-m33.ts b/packages/matrices/src/quat-m33.ts new file mode 100644 index 0000000000..e28d1a7a6f --- /dev/null +++ b/packages/matrices/src/quat-m33.ts @@ -0,0 +1,30 @@ +import { ReadonlyVec, setC, Vec } from "@thi.ng/vectors"; + +/** + * Converts quaternion into M33 and writes result to `out`. + * + * @param out + * @param q + */ +export const quatToMat33 = + (out: Vec, q: ReadonlyVec) => { + const [x, y, z, w] = q; + const x2 = x + x; + const y2 = y + y; + const z2 = z + z; + const xx = x * x2; + const xy = x * y2; + const xz = x * z2; + const yy = y * y2; + const yz = y * z2; + const zz = z * z2; + const wx = w * x2; + const wy = w * y2; + const wz = w * z2; + return setC( + out || [], + 1 - yy - zz, xy + wz, xz - wy, + xy - wz, 1 - xx - zz, yz + wx, + xz + wy, yz - wx, 1 - xx - yy + ); + }; diff --git a/packages/matrices/src/quat-m44.ts b/packages/matrices/src/quat-m44.ts new file mode 100644 index 0000000000..9b95a8c35e --- /dev/null +++ b/packages/matrices/src/quat-m44.ts @@ -0,0 +1,37 @@ +import { + ReadonlyVec, + setC, + Vec, + ZERO3 +} from "@thi.ng/vectors"; + +/** + * Converts quaternion into M44 with optional translation offset `t`, + * then writes result to `out`. + * + * @param out + * @param q + */ +export const quatToMat44 = + (out: Vec, a: ReadonlyVec, t: ReadonlyVec = ZERO3) => { + const [x, y, z, w] = a; + const x2 = x + x; + const y2 = y + y; + const z2 = z + z; + const xx = x * x2; + const xy = x * y2; + const xz = x * z2; + const yy = y * y2; + const yz = y * z2; + const zz = z * z2; + const wx = w * x2; + const wy = w * y2; + const wz = w * z2; + return setC( + out || [], + 1 - yy - zz, xy + wz, xz - wy, 0, + xy - wz, 1 - xx - zz, yz + wx, 0, + xz + wy, yz - wx, 1 - xx - yy, 0, + t[0], t[1], t[2], 1 + ); + }; diff --git a/packages/matrices/src/rotation-around-axis.ts b/packages/matrices/src/rotation-around-axis.ts new file mode 100644 index 0000000000..eca484859d --- /dev/null +++ b/packages/matrices/src/rotation-around-axis.ts @@ -0,0 +1,47 @@ +import { normalize as _normalize, ReadonlyVec, setC } from "@thi.ng/vectors"; +import { Mat } from "./api"; +import { mat33to44 } from "./m33-m44"; + +/** + * Constructs a M33 representing a rotation of `theta` around `axis` and + * writes result to `out`. If `normalize` is true (default false), + * non-destructively first normalizes axis vector. + * + * @param out + * @param axis + * @param theta + * @param normalize + */ +export const rotationAroundAxis33 = + (out: Mat, axis: ReadonlyVec, theta: number, normalize = false) => { + const [x, y, z] = normalize ? _normalize([], axis) : axis; + const s = Math.sin(theta); + const c = Math.cos(theta); + const t = 1 - c; + return setC( + out || [], + x * x * t + c, + y * x * t + z * s, + z * x * t - y * s, + x * y * t - z * s, + y * y * t + c, + z * y * t + x * s, + x * z * t + y * s, + y * z * t - x * s, + z * z * t + c + ); + }; + +/** + * Constructs a M44 representing a rotation of `theta` around `axis` and + * writes result to `out`. If `normalize` is true (default false), + * non-destructively first normalizes axis vector. + * + * @param out + * @param axis + * @param theta + * @param normalize + */ +export const rotationAroundAxis44 = + (out: Mat, axis: ReadonlyVec, theta: number, normalize = false) => + mat33to44(out, rotationAroundAxis33([], axis, theta, normalize)); diff --git a/packages/matrices/src/rotation.ts b/packages/matrices/src/rotation.ts new file mode 100644 index 0000000000..d2f75545a2 --- /dev/null +++ b/packages/matrices/src/rotation.ts @@ -0,0 +1,141 @@ +import { sincos } from "@thi.ng/math"; +import { setC, setC4, setC6 } from "@thi.ng/vectors"; +import { Mat } from "./api"; + +/** + * Constructs a M22 rotation matrix for given `theta`. + * + * @param out + * @param theta + */ +export const rotation22 = + (out: Mat, theta: number) => { + const [s, c] = sincos(theta); + return setC4( + out || [], + c, s, + -s, c, + ); + }; + +/** + * Constructs a M23 rotation matrix for given `theta`. + * + * @param out + * @param theta + */ +export const rotation23 = + (out: Mat, theta: number) => { + const [s, c] = sincos(theta); + return setC6( + out || [], + c, s, + -s, c, + 0, 0 + ); + }; + +/** + * Constructs a M33 X rotation matrix for given `theta`. + * + * @param out + * @param theta + */ +export const rotationX33 = + (out: Mat, theta: number) => { + const [s, c] = sincos(theta); + return setC( + out || [], + 1, 0, 0, + 0, c, s, + 0, -s, c, + ); + }; + +/** + * Constructs a M33 Y rotation matrix for given `theta`. + * + * @param out + * @param theta + */ +export const rotationY33 = + (out: Mat, theta: number) => { + const [s, c] = sincos(theta); + return setC( + out || [], + c, 0, -s, + 0, 1, 0, + s, 0, c, + ); + }; + +/** + * Constructs a M33 Z rotation matrix for given `theta`. + * + * @param out + * @param theta + */ +export const rotationZ33 = + (out: Mat, theta: number) => { + const [s, c] = sincos(theta); + return setC( + out || [], + c, s, 0, + -s, c, 0, + 0, 0, 1, + ); + }; + +/** + * Constructs a M44 X rotation matrix for given `theta`. + * + * @param out + * @param theta + */ +export const rotationX44 = + (out: Mat, 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 + ); + }; + +/** + * Constructs a M44 Y rotation matrix for given `theta`. + * + * @param out + * @param theta + */ +export const rotationY44 = + (out: Mat, 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 + ); + }; + +/** + * Constructs a M44 Z rotation matrix for given `theta`. + * + * @param out + * @param theta + */ +export const rotationZ44 = + (out: Mat, 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/row.ts b/packages/matrices/src/row.ts new file mode 100644 index 0000000000..c15c8621c4 --- /dev/null +++ b/packages/matrices/src/row.ts @@ -0,0 +1,29 @@ +import { + setS2, + setS3, + setS4, + vop +} from "@thi.ng/vectors"; +import { MultiVecOpMN } from "./api"; + +/** + * Extracts row vector from given matrix and writes result to `out`. If + * `out` is null, creates new vector. + * + * @param out + * @param mat + * @param column + */ +export const row: MultiVecOpMN = vop(1); + +export const row22 = + row.add(4, (out, m, n) => setS2(out, m, 0, n, 1, 2)); + +export const row23 = + row.add(6, (out, m, n) => setS3(out, m, 0, n, 1, 2)); + +export const row33 = + row.add(9, (out, m, n) => setS3(out, m, 0, n, 1, 3)); + +export const row44 = + row.add(16, (out, m, n) => setS4(out, m, 0, n, 1, 4)); diff --git a/packages/matrices/src/scale-center.ts b/packages/matrices/src/scale-center.ts new file mode 100644 index 0000000000..97a5098dc5 --- /dev/null +++ b/packages/matrices/src/scale-center.ts @@ -0,0 +1,35 @@ +import { neg, ReadonlyVec } from "@thi.ng/vectors"; +import { Mat } from "./api"; +import { concat } from "./concat"; +import { scale23, scale44 } from "./scale"; +import { translation23, translation44 } from "./translation"; + +/** + * Computes a M23 representing a scale operation with origin `p` and + * writes result to `out`. + * + * @param out + * @param m + */ +export const scaleWithCenter23 = (m: Mat, p: ReadonlyVec, s: number | ReadonlyVec) => + concat( + m, + translation23([], p), + scale23([], s), + translation23([], neg([], p)) + ); + +/** + * Computes a M44 representing a scale operation with origin `p` and + * writes result to `out`. + * + * @param out + * @param m + */ +export const scaleWithCenter44 = (m: Mat, p: ReadonlyVec, s: number | ReadonlyVec) => + concat( + m, + translation44([], p), + scale44([], s), + translation44([], neg([], p)) + ); diff --git a/packages/matrices/src/scale.ts b/packages/matrices/src/scale.ts new file mode 100644 index 0000000000..f66d91c6ee --- /dev/null +++ b/packages/matrices/src/scale.ts @@ -0,0 +1,80 @@ +import { isNumber } from "@thi.ng/checks"; +import { + ReadonlyVec, + setC, + setC4, + setC6 +} from "@thi.ng/vectors"; +import { Mat } from "./api"; + +/** + * Computes M22 scale matrix and writes result to `out`. If `s` is a + * number, scaling will be uniform. + * + * @param m + * @param s + */ +export const scale22 = + (m: Mat, s: number | ReadonlyVec) => ( + s = isNumber(s) ? [s, s] : s, + setC4( + m || [], + s[0], 0, + 0, s[1] + ) + ); + +/** + * Computes M23 scale matrix and writes result to `out`. If `s` is a + * number, scaling will be uniform. + * + * @param m + * @param s + */ +export const scale23 = + (m: Mat, s: number | ReadonlyVec) => ( + s = isNumber(s) ? [s, s] : s, + setC6( + m || [], + s[0], 0, + 0, s[1], + 0, 0 + ) + ); + +/** + * Computes M33 scale matrix and writes result to `out`. If `s` is a + * number, scaling will be uniform. + * + * @param m + * @param s + */ +export const scale33 = + (m: Mat, s: number | ReadonlyVec) => ( + s = isNumber(s) ? [s, s, s] : s, + setC( + m || [], + s[0], 0, 0, + 0, s[1], 0, + 0, 0, s[2] + ) + ); + +/** + * Computes M44 scale matrix and writes result to `out`. If `s` is a + * number, scaling will be uniform. + * + * @param m + * @param s + */ +export const scale44 = + (m: Mat, s: number | ReadonlyVec) => ( + s = isNumber(s) ? [s, s, s] : s, + setC( + m || [], + s[0], 0, 0, 0, + 0, s[1], 0, 0, + 0, 0, s[2], 0, + 0, 0, 0, s[3] !== undefined ? s[3] : 1 + ) + ); diff --git a/packages/matrices/src/set.ts b/packages/matrices/src/set.ts new file mode 100644 index 0000000000..3743920377 --- /dev/null +++ b/packages/matrices/src/set.ts @@ -0,0 +1,15 @@ +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")); + +export const set: MatOpM = _set; +export const set22: MatOpM = set4; +export const set23: MatOpM = $(6); +export const set33: MatOpM = $(9); +export const set44: MatOpM = $(16); diff --git a/packages/matrices/src/shear.ts b/packages/matrices/src/shear.ts new file mode 100644 index 0000000000..95510530e6 --- /dev/null +++ b/packages/matrices/src/shear.ts @@ -0,0 +1,35 @@ +import { Mat, MatOp1 } from "./api"; +import { identity33, identity44, identity23, identity22 } from "./identity"; + +const $ = + (f: MatOp1) => + (i: number) => + (m: Mat, x: number) => + (f(m), m[i] = x, m); + +const $22 = $(identity22); +const $23 = $(identity23); +const $33 = $(identity33); +const $44 = $(identity44); + +// https://stackoverflow.com/a/13211288/294515 + +export const shearX22 = $22(2); +export const shearY22 = $22(1); + +export const shearX23 = $23(2); +export const shearY23 = $23(1); + +export const shearXY33 = $33(3); +export const shearXZ33 = $33(6); +export const shearYX33 = $33(1); +export const shearYZ33 = $33(7); +export const shearZX33 = $33(2); +export const shearZY33 = $33(5); + +export const shearXY44 = $44(4); +export const shearXZ44 = $44(8); +export const shearYX44 = $44(1); +export const shearYZ44 = $44(9); +export const shearZX44 = $44(2); +export const shearZY44 = $44(6); diff --git a/packages/matrices/src/skew.ts b/packages/matrices/src/skew.ts new file mode 100644 index 0000000000..57119778e9 --- /dev/null +++ b/packages/matrices/src/skew.ts @@ -0,0 +1,44 @@ +import { Mat, MatOpN } from "./api"; +import { + shearX22, + shearX23, + shearXY33, + shearXY44, + shearXZ33, + shearXZ44, + shearY22, + shearY23, + shearYX33, + shearYX44, + shearYZ33, + shearYZ44, + shearZX33, + shearZX44, + shearZY33, + shearZY44 +} from "./shear"; + +const $ = + (f: MatOpN) => + (m: Mat, theta: number) => + f(m, Math.tan(theta)); + +export const skewX22 = $(shearX22); +export const skewY22 = $(shearY22); + +export const skewX23 = $(shearX23); +export const skewY23 = $(shearY23); + +export const skewXY33 = $(shearXY33); +export const skewXZ33 = $(shearXZ33); +export const skewYX33 = $(shearYX33); +export const skewYZ33 = $(shearYZ33); +export const skewZX33 = $(shearZX33); +export const skewZY33 = $(shearZY33); + +export const skewXY44 = $(shearXY44); +export const skewXZ44 = $(shearXZ44); +export const skewYX44 = $(shearYX44); +export const skewYZ44 = $(shearYZ44); +export const skewZX44 = $(shearZX44); +export const skewZY44 = $(shearZY44); \ No newline at end of file diff --git a/packages/matrices/src/sub.ts b/packages/matrices/src/sub.ts new file mode 100644 index 0000000000..65935210a4 --- /dev/null +++ b/packages/matrices/src/sub.ts @@ -0,0 +1,17 @@ +import { sub as _sub, sub4 } from "@thi.ng/vectors"; +import { MatOpMM, MultiMatOpMM } from "./api"; +import { defMath } from "./internal/codegen"; + +/** + * Componentwise matrix subtraction. If `out` is not + * given, writes result in `a`. + * + * out = a - b + * + * @param out + * @param a + * @param b + */ +export const sub: MultiMatOpMM = _sub; +export const sub22: MatOpMM = sub4; +export const [sub23, sub33, sub44] = defMath(sub, "-"); diff --git a/packages/matrices/src/subn.ts b/packages/matrices/src/subn.ts new file mode 100644 index 0000000000..b8243f7546 --- /dev/null +++ b/packages/matrices/src/subn.ts @@ -0,0 +1,17 @@ +import { subN as _subN, subN4 } from "@thi.ng/vectors"; +import { MatOpMN, MultiMatOpMN } from "./api"; +import { defMathN } from "./internal/codegen"; + +/** + * Subtracts matrix componentwise with single scalar. If `out` is not + * given, writes result in `mat`. + * + * out = mat - n + * + * @param out + * @param mat + * @param n + */ +export const subN: MultiMatOpMN = _subN; +export const subN22: MatOpMN = subN4; +export const [subN23, subN33, subN44] = defMathN(subN, "-"); diff --git a/packages/matrices/src/trace.ts b/packages/matrices/src/trace.ts new file mode 100644 index 0000000000..e25257df39 --- /dev/null +++ b/packages/matrices/src/trace.ts @@ -0,0 +1,11 @@ +import { sum } from "@thi.ng/vectors"; +import { diag } from "./diag"; +import { ReadonlyMat } from "./api"; + +/** + * Returns matrix trace of `m`, i.e. component sum of `diag(m)`. + * + * @param m + */ +export const trace = + (m: ReadonlyMat) => sum(diag([], m)); diff --git a/packages/matrices/src/translation.ts b/packages/matrices/src/translation.ts new file mode 100644 index 0000000000..76078636fe --- /dev/null +++ b/packages/matrices/src/translation.ts @@ -0,0 +1,28 @@ +import { ReadonlyVec, setC, setC6 } from "@thi.ng/vectors"; +import { Mat } from "./api"; + +/** + * Constructs a M23 translation matrix. + * + * @param out + * @param v + */ +export const translation23 = + (m: Mat, v: ReadonlyVec) => + setC6(m || [], 1, 0, 0, 1, v[0], v[1]); + +/** + * Constructs a M44 translation matrix. + * + * @param out + * @param v + */ +export const translation44 = + (m: Mat, 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/transpose.ts b/packages/matrices/src/transpose.ts new file mode 100644 index 0000000000..6dbaff5029 --- /dev/null +++ b/packages/matrices/src/transpose.ts @@ -0,0 +1,47 @@ +import { setC, setC4 } from "@thi.ng/vectors"; +import { MatOpM } from "./api"; + +/** + * Writes transposition of M22 `m` to `out`. + * + * @param out + * @param m + */ +export const transpose22: MatOpM = + (out, m) => + setC4( + out || [], + m[0], m[2], + m[1], m[3], + ); + +/** + * Writes transposition of M33 `m` to `out`. + * + * @param out + * @param m + */ +export const transpose33: MatOpM = + (out, m) => + setC( + out || [], + m[0], m[3], m[6], + m[1], m[4], m[7], + m[2], m[5], m[8], + ); + +/** + * Writes transposition of M44 `m` to `out`. + * + * @param out + * @param m + */ +export const transpose44: MatOpM = + (out, m) => + setC( + out || [], + m[0], m[4], m[8], m[12], + m[1], m[5], m[9], m[13], + m[2], m[6], m[10], m[14], + m[3], m[7], m[11], m[15], + ); diff --git a/packages/matrices/src/viewport.ts b/packages/matrices/src/viewport.ts new file mode 100644 index 0000000000..2aaf77caee --- /dev/null +++ b/packages/matrices/src/viewport.ts @@ -0,0 +1,23 @@ +import { Mat } from "./api"; +import { mulM23 } from "./mulm"; +import { scale23 } from "./scale"; +import { translation23 } from "./translation"; + +/** + * Produces a M23 viewport matrix to transform projected coordinates to + * screen space. + * + * @param out + * @param left + * @param right + * @param bottom + * @param top + */ +export const viewport = + (out: Mat, left: number, right: number, bottom: number, top: number) => { + const x = (left + right) / 2; + const y = (bottom + top) / 2; + const w = (right - left) / 2; + const h = (top - bottom) / 2; + return mulM23(null, translation23(out, [x, y]), scale23([], [w, h])); + }; diff --git a/packages/matrices/test/index.ts b/packages/matrices/test/index.ts new file mode 100644 index 0000000000..e020e6a654 --- /dev/null +++ b/packages/matrices/test/index.ts @@ -0,0 +1,6 @@ +// import * as assert from "assert"; +// import * as m from "../src/index"; + +describe("matrices", () => { + it("tests pending"); +}); diff --git a/packages/matrices/test/tsconfig.json b/packages/matrices/test/tsconfig.json new file mode 100644 index 0000000000..2c9c12a650 --- /dev/null +++ b/packages/matrices/test/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../../tsconfig.json", + "compilerOptions": { + "outDir": "../build", + "module": "commonjs", + }, + "include": [ + "./**/*.ts", + "../src/**/*.ts" + ] +} \ No newline at end of file diff --git a/packages/matrices/tsconfig.json b/packages/matrices/tsconfig.json new file mode 100644 index 0000000000..bcf03f18b4 --- /dev/null +++ b/packages/matrices/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": ".", + "module": "es6", + "target": "es6" + }, + "include": [ + "./src/**/*.ts" + ] +} \ No newline at end of file diff --git a/packages/memoize/.npmignore b/packages/memoize/.npmignore index d703bda97a..67d0c55714 100644 --- a/packages/memoize/.npmignore +++ b/packages/memoize/.npmignore @@ -1,10 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/memoize/CHANGELOG.md b/packages/memoize/CHANGELOG.md index 0ff46c457b..3c66f548a1 100644 --- a/packages/memoize/CHANGELOG.md +++ b/packages/memoize/CHANGELOG.md @@ -3,6 +3,28 @@ 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/memoize@0.2.6...@thi.ng/memoize@1.0.0) (2019-01-21) + + +### Build System + +* update package build scripts & outputs, imports in ~50 packages ([b54b703](https://github.com/thi-ng/umbrella/commit/b54b703)) + + +### BREAKING CHANGES + +* enabled multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols. + + + + + ## [0.2.6](https://github.com/thi-ng/umbrella/compare/@thi.ng/memoize@0.2.5...@thi.ng/memoize@0.2.6) (2018-12-15) **Note:** Version bump only for package @thi.ng/memoize diff --git a/packages/memoize/package.json b/packages/memoize/package.json index d79213265a..82e5631915 100644 --- a/packages/memoize/package.json +++ b/packages/memoize/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/memoize", - "version": "0.2.6", + "version": "1.0.0", "description": "Function memoization with configurable caches", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,23 +14,25 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn run clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module memoize api", + "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 run build && yarn publish --access public", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/api": "^4.2.4" + "@thi.ng/api": "^5.0.0" }, "keywords": [ "cache", @@ -39,5 +43,6 @@ ], "publishConfig": { "access": "public" - } + }, + "sideEffects": false } diff --git a/packages/memoize/src/defonce.ts b/packages/memoize/src/defonce.ts index 3546379952..cf28036be7 100644 --- a/packages/memoize/src/defonce.ts +++ b/packages/memoize/src/defonce.ts @@ -1,4 +1,4 @@ -import { Fn0 } from "@thi.ng/memoize/src/api"; +import { Fn0 } from "./api"; const cache: any = {}; @@ -16,8 +16,8 @@ const cache: any = {}; * @param id * @param factory */ -export function defonce(id: string, factory: Fn0): T { - return cache.hasOwnProperty(id) ? - cache[id] : - (cache[id] = factory()); -} +export const defonce = + (id: string, factory: Fn0): T => + cache.hasOwnProperty(id) ? + cache[id] : + (cache[id] = factory()); diff --git a/packages/memoize/src/memoizej.ts b/packages/memoize/src/memoizej.ts index e3cb361313..cb7508be4e 100644 --- a/packages/memoize/src/memoizej.ts +++ b/packages/memoize/src/memoizej.ts @@ -1,4 +1,4 @@ -import { IObjectOf } from "@thi.ng/api/api"; +import { IObjectOf } from "@thi.ng/api"; import { Fn1, Fn2, Fn3, Fn4, FnAny } from "./api"; /** diff --git a/packages/memoize/test/tsconfig.json b/packages/memoize/test/tsconfig.json index bcf29ace54..2c9c12a650 100644 --- a/packages/memoize/test/tsconfig.json +++ b/packages/memoize/test/tsconfig.json @@ -1,10 +1,11 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", "../src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/memoize/tsconfig.json b/packages/memoize/tsconfig.json index bd6481a5a6..bcf03f18b4 100644 --- a/packages/memoize/tsconfig.json +++ b/packages/memoize/tsconfig.json @@ -1,9 +1,11 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/morton/.npmignore b/packages/morton/.npmignore index d703bda97a..67d0c55714 100644 --- a/packages/morton/.npmignore +++ b/packages/morton/.npmignore @@ -1,10 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/morton/CHANGELOG.md b/packages/morton/CHANGELOG.md index 9d7c059b4b..c18e39cfe8 100644 --- a/packages/morton/CHANGELOG.md +++ b/packages/morton/CHANGELOG.md @@ -3,6 +3,28 @@ 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/morton@0.2.2...@thi.ng/morton@1.0.0) (2019-01-21) + + +### Build System + +* update package build scripts & outputs, imports in ~50 packages ([b54b703](https://github.com/thi-ng/umbrella/commit/b54b703)) + + +### BREAKING CHANGES + +* enabled multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols. + + + + + ## [0.2.2](https://github.com/thi-ng/umbrella/compare/@thi.ng/morton@0.2.1...@thi.ng/morton@0.2.2) (2018-12-15) **Note:** Version bump only for package @thi.ng/morton diff --git a/packages/morton/package.json b/packages/morton/package.json index 61ce6211aa..823c9196e0 100644 --- a/packages/morton/package.json +++ b/packages/morton/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/morton", - "version": "0.2.2", + "version": "1.0.0", "description": "Z-order-curve / Morton encoding & decoding for 1D, 2D, 3D", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,25 +14,27 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn run clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module morton binary errors math", + "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 run build && yarn publish --access public", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/binary": "^0.1.2", - "@thi.ng/errors": "^0.1.12", - "@thi.ng/math": "^0.2.2" + "@thi.ng/binary": "^1.0.0", + "@thi.ng/errors": "^1.0.0", + "@thi.ng/math": "^1.0.0" }, "keywords": [ "binary", @@ -43,5 +47,6 @@ ], "publishConfig": { "access": "public" - } + }, + "sideEffects": false } diff --git a/packages/morton/src/index.ts b/packages/morton/src/index.ts index c368dea5b7..8cc52f4ce5 100644 --- a/packages/morton/src/index.ts +++ b/packages/morton/src/index.ts @@ -1,8 +1,6 @@ -import { MASKS } from "@thi.ng/binary/api"; -import { ceilPow2 } from "@thi.ng/binary/pow"; -import { illegalArgs } from "@thi.ng/errors/illegal-arguments"; -import { fit, fit01 } from "@thi.ng/math/fit"; -import { inRange } from "@thi.ng/math/interval"; +import { ceilPow2, MASKS } from "@thi.ng/binary"; +import { illegalArgs } from "@thi.ng/errors"; +import { fit, fit01, inRange } from "@thi.ng/math"; const MIN = [0, 0, 0]; const MAX = [1, 1, 1]; diff --git a/packages/morton/test/tsconfig.json b/packages/morton/test/tsconfig.json index bcf29ace54..2c9c12a650 100644 --- a/packages/morton/test/tsconfig.json +++ b/packages/morton/test/tsconfig.json @@ -1,10 +1,11 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", "../src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/morton/tsconfig.json b/packages/morton/tsconfig.json index bd6481a5a6..bcf03f18b4 100644 --- a/packages/morton/tsconfig.json +++ b/packages/morton/tsconfig.json @@ -1,9 +1,11 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/paths/.npmignore b/packages/paths/.npmignore index d703bda97a..67d0c55714 100644 --- a/packages/paths/.npmignore +++ b/packages/paths/.npmignore @@ -1,10 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/paths/CHANGELOG.md b/packages/paths/CHANGELOG.md index e72a2d9f58..91168ca78a 100644 --- a/packages/paths/CHANGELOG.md +++ b/packages/paths/CHANGELOG.md @@ -3,6 +3,28 @@ 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/paths@1.6.6...@thi.ng/paths@2.0.0) (2019-01-21) + + +### Build System + +* update package build scripts & outputs, imports in ~50 packages ([b54b703](https://github.com/thi-ng/umbrella/commit/b54b703)) + + +### BREAKING CHANGES + +* enabled multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols. + + + + + ## [1.6.6](https://github.com/thi-ng/umbrella/compare/@thi.ng/paths@1.6.5...@thi.ng/paths@1.6.6) (2018-12-15) **Note:** Version bump only for package @thi.ng/paths diff --git a/packages/paths/package.json b/packages/paths/package.json index 8be8fa10e8..546413873c 100644 --- a/packages/paths/package.json +++ b/packages/paths/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/paths", - "version": "1.6.6", + "version": "2.0.0", "description": "immutable, optimized path-based object property / array accessors", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,29 +14,32 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn run clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module paths checks errors", + "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 run build && yarn publish --access public", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/checks": "^1.5.14", - "@thi.ng/errors": "^0.1.12" + "@thi.ng/checks": "^2.0.0", + "@thi.ng/errors": "^1.0.0" }, "keywords": [ "accessors", "array", "ES6", + "delete", "getter", "immutable", "nested", @@ -42,9 +47,18 @@ "path", "property", "setter", - "typescript" + "typescript", + "update" ], "publishConfig": { "access": "public" - } + }, + "browserslist": [ + "since 2018-07" + ], + "browser": { + "process": false, + "setTimeout": false + }, + "sideEffects": false } diff --git a/packages/paths/src/index.ts b/packages/paths/src/index.ts index fe34929594..f7efef715a 100644 --- a/packages/paths/src/index.ts +++ b/packages/paths/src/index.ts @@ -1,14 +1,16 @@ -import { isArray } from "@thi.ng/checks/is-array"; -import { isString } from "@thi.ng/checks/is-string"; -import { illegalArgs } from "@thi.ng/errors/illegal-arguments"; +import { isString } from "@thi.ng/checks"; +import { illegalArgs } from "@thi.ng/errors"; export type Path = PropertyKey | PropertyKey[]; export type UpdateFn = (curr: T, ...args: any[]) => T; -const _copy = (s) => Array.isArray(s) ? s.slice() : { ...s }; +const isa = Array.isArray; +const iss = isString; -const compS = (k, f) => (s, v) => { s = _copy(s); s[k] = f ? f(s[k], v) : v; return s; } +const _copy = (s) => isa(s) ? s.slice() : { ...s }; + +const compS = (k, f) => (s, v) => (s = _copy(s), s[k] = (f ? f(s[k], v) : v), s); const compG = (k, f) => (s) => s ? f(s[k]) : undefined; @@ -28,9 +30,17 @@ const compG = (k, f) => (s) => s ? f(s[k]) : undefined; * * @param path */ -export function toPath(path: Path) { - return isArray(path) ? path : isString(path) ? path.length > 0 ? path.split(".") : [] : path != null ? [path] : []; -} +export const toPath = + (path: Path) => + isa(path) ? + path : + iss(path) ? + path.length > 0 ? + path.split(".") : + [] : + path != null ? + [path] : + []; /** * Takes an arbitrary object and lookup path. Descends into object along @@ -41,23 +51,24 @@ export function toPath(path: Path) { * @param obj * @param path */ -export const exists = (obj: any, path: Path) => { - if (obj == null) { - return false; - } - path = toPath(path); - for (let n = path.length - 1, i = 0; i <= n; i++) { - const k = path[i]; - if (!obj.hasOwnProperty(k)) { +export const exists = + (obj: any, path: Path) => { + if (obj == null) { return false; } - obj = obj[k]; - if (obj == null && i < n) { - return false; + path = toPath(path); + for (let n = path.length - 1, i = 0; i <= n; i++) { + const k = path[i]; + if (!obj.hasOwnProperty(k)) { + return false; + } + obj = obj[k]; + if (obj == null && i < n) { + return false; + } } - } - return true; -}; + return true; + }; /** * Composes a getter function for given nested lookup path. Optimized @@ -89,29 +100,30 @@ export const exists = (obj: any, path: Path) => { * * @param path */ -export function getter(path: Path) { - const ks = toPath(path); - let [a, b, c, d] = ks; - switch (ks.length) { - case 0: - return (s) => s; - case 1: - return (s) => s ? s[a] : undefined; - case 2: - return (s) => s ? (s = s[a]) ? s[b] : undefined : undefined; - case 3: - return (s) => s ? (s = s[a]) ? (s = s[b]) ? s[c] : undefined : undefined : undefined; - case 4: - return (s) => s ? (s = s[a]) ? (s = s[b]) ? (s = s[c]) ? s[d] : undefined : undefined : undefined : undefined; - default: - const kl = ks[ks.length - 1]; - let f = (s) => s ? s[kl] : undefined; - for (let i = ks.length - 2; i >= 0; i--) { - f = compG(ks[i], f); - } - return f; - } -} +export const getter = + (path: Path) => { + const ks = toPath(path); + let [a, b, c, d] = ks; + switch (ks.length) { + case 0: + return (s) => s; + case 1: + return (s) => s ? s[a] : undefined; + case 2: + return (s) => s ? (s = s[a]) ? s[b] : undefined : undefined; + case 3: + return (s) => s ? (s = s[a]) ? (s = s[b]) ? s[c] : undefined : undefined : undefined; + case 4: + return (s) => s ? (s = s[a]) ? (s = s[b]) ? (s = s[c]) ? s[d] : undefined : undefined : undefined : undefined; + default: + const kl = ks[ks.length - 1]; + let f = (s) => s ? s[kl] : undefined; + for (let i = ks.length - 1; --i >= 0;) { + f = compG(ks[i], f); + } + return f; + } + }; /** * Composes a setter function for given nested update path. Optimized @@ -166,28 +178,29 @@ export function getter(path: Path) { * * @param path */ -export function setter(path: Path): (s: any, v: any) => any { - const ks = toPath(path); - let [a, b, c, d] = ks; - switch (ks.length) { - case 0: - return (_, v) => v; - case 1: - return (s, v) => (s = _copy(s), s[a] = v, s); - case 2: - return (s, v) => { let x; s = _copy(s); s[a] = x = _copy(s[a]); x[b] = v; return s; }; - case 3: - return (s, v) => { let x, y; s = _copy(s); s[a] = x = _copy(s[a]); x[b] = y = _copy(x[b]); y[c] = v; return s; }; - case 4: - return (s, v) => { let x, y, z; s = _copy(s); s[a] = x = _copy(s[a]); x[b] = y = _copy(x[b]); y[c] = z = _copy(y[c]); z[d] = v; return s; }; - default: - let f; - for (let i = ks.length - 1; i >= 0; i--) { - f = compS(ks[i], f); - } - return f; - } -} +export const setter = + (path: Path): (s: any, v: any) => any => { + const ks = toPath(path); + let [a, b, c, d] = ks; + switch (ks.length) { + case 0: + return (_, v) => v; + case 1: + return (s, v) => (s = _copy(s), s[a] = v, s); + case 2: + return (s, v) => { let x; s = _copy(s); s[a] = x = _copy(s[a]); x[b] = v; return s; }; + case 3: + return (s, v) => { let x, y; s = _copy(s); s[a] = x = _copy(s[a]); x[b] = y = _copy(x[b]); y[c] = v; return s; }; + case 4: + return (s, v) => { let x, y, z; s = _copy(s); s[a] = x = _copy(s[a]); x[b] = y = _copy(x[b]); y[c] = z = _copy(y[c]); z[d] = v; return s; }; + default: + let f; + for (let i = ks.length; --i >= 0;) { + f = compS(ks[i], f); + } + return f; + } + }; /** * Immediate use getter, i.e. same as: `getter(path)(state)`. @@ -200,9 +213,9 @@ export function setter(path: Path): (s: any, v: any) => any { * @param state * @param path */ -export function getIn(state: any, path: Path) { - return getter(path)(state); -} +export const getIn = + (state: any, path: Path) => + getter(path)(state); /** * Immediate use setter, i.e. same as: `setter(path)(state, val)`. @@ -215,9 +228,9 @@ export function getIn(state: any, path: Path) { * @param state * @param path */ -export function setIn(state: any, path: Path, val: any) { - return setter(path)(state, val); -} +export const setIn = + (state: any, path: Path, val: any) => + setter(path)(state, val); /** * Like `setIn()`, but takes any number of path-value pairs and applies @@ -233,16 +246,15 @@ export function setIn(state: any, path: Path, val: any) { * @param state * @param pairs */ -export function setInMany(state: any, ...pairs: any[]) { - const n = pairs.length; - if ((n & 1)) { - illegalArgs(`require an even number of args (got ${pairs.length})`); - } - for (let i = 0; i < n; i += 2) { - state = setIn(state, pairs[i], pairs[i + 1]); - } - return state; -} +export const setInMany = + (state: any, ...pairs: any[]) => { + const n = pairs.length; + (n & 1) && illegalArgs(`require even number of args (got ${pairs.length})`); + for (let i = 0; i < n; i += 2) { + state = setIn(state, pairs[i], pairs[i + 1]); + } + return state; + }; /** * Similar to `setter()`, returns a function to update values at given @@ -262,12 +274,13 @@ export function setInMany(state: any, ...pairs: any[]) { * @param path * @param fn */ -export function 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))); -}; +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))); + }; /** * Similar to `setIn()`, but applies given function to current path @@ -284,9 +297,12 @@ export function updater(path: Path, fn: UpdateFn) { * @param state * @param path */ -export function updateIn(state: any, path: Path, fn: UpdateFn, ...args: any[]) { - return setter(path)(state, fn.apply(null, (args.unshift(getter(path)(state)), args))); -} +export const updateIn = + (state: any, path: Path, fn: UpdateFn, ...args: any[]) => + setter(path)( + state, + fn.apply(null, (args.unshift(getter(path)(state)), args)) + ); /** * Uses `updateIn()` and returns updated state with key for given path @@ -302,13 +318,14 @@ export function updateIn(state: any, path: Path, fn: UpdateFn, ...args: any * @param state * @param path */ -export function deleteIn(state: any, path: Path) { - const ks = [...toPath(path)]; - if (ks.length > 0) { - const k = ks.pop(); - return updateIn(state, ks, (x) => { x = { ...x }; delete x[k]; return x; }); - } -} +export const deleteIn = + (state: any, path: Path) => { + const ks = [...toPath(path)]; + if (ks.length > 0) { + const k = ks.pop(); + return updateIn(state, ks, (x) => (x = { ...x }, delete x[k], x)); + } + }; /** * Higher-order function, similar to `setter()`. Returns function which @@ -321,32 +338,33 @@ export function deleteIn(state: any, path: Path) { * * @param path */ -export function mutator(path: Path) { - const ks = toPath(path); - let [a, b, c, d] = ks; - switch (ks.length) { - case 0: - return (_, x) => x; - case 1: - return (s, x) => s ? (s[a] = x, s) : undefined; - case 2: - return (s, x) => { let t; return s ? (t = s[a]) ? (t[b] = x, s) : undefined : undefined }; - case 3: - return (s, x) => { let t; return s ? (t = s[a]) ? (t = t[b]) ? (t[c] = x, s) : undefined : undefined : undefined }; - case 4: - return (s, x) => { let t; return s ? (t = s[a]) ? (t = t[b]) ? (t = t[c]) ? (t[d] = x, s) : undefined : undefined : undefined : undefined }; - default: - return (s, x) => { - let t = s; - const n = ks.length - 1; - for (let k = 0; k < n; k++) { - if (!(t = t[ks[k]])) return; +export const mutator = + (path: Path) => { + const ks = toPath(path); + let [a, b, c, d] = ks; + switch (ks.length) { + case 0: + return (_, x) => x; + case 1: + return (s, x) => s ? (s[a] = x, s) : undefined; + case 2: + return (s, x) => { let t; return s ? (t = s[a]) ? (t[b] = x, s) : undefined : undefined }; + case 3: + return (s, x) => { let t; return s ? (t = s[a]) ? (t = t[b]) ? (t[c] = x, s) : undefined : undefined : undefined }; + case 4: + return (s, x) => { let t; return s ? (t = s[a]) ? (t = t[b]) ? (t = t[c]) ? (t[d] = x, s) : undefined : undefined : undefined : undefined }; + default: + return (s, x) => { + let t = s; + const n = ks.length - 1; + for (let k = 0; k < n; k++) { + if (!(t = t[ks[k]])) return; + } + t[ks[n]] = x; + return s; } - t[ks[n]] = x; - return s; - } - } -} + } + }; /** * Immediate use mutator, i.e. same as: `mutator(path)(state, val)`. @@ -364,9 +382,9 @@ export function mutator(path: Path) { * @param path * @param val */ -export function mutIn(state: any, path: Path, val: any) { - return mutator(path)(state, val); -} +export const mutIn = + (state: any, path: Path, val: any) => + mutator(path)(state, val); /** * Like `mutIn()`, but takes any number of path-value pairs and applies @@ -381,13 +399,12 @@ export function mutIn(state: any, path: Path, val: any) { * @param state * @param pairs */ -export function mutInMany(state: any, ...pairs: any[]) { - const n = pairs.length; - if ((n & 1)) { - illegalArgs(`require an even number of args (got ${pairs.length})`); - } - for (let i = 0; i < n && state; i += 2) { - state = mutIn(state, pairs[i], pairs[i + 1]); - } - return state; -} +export const mutInMany = + (state: any, ...pairs: any[]) => { + const n = pairs.length; + (n & 1) && illegalArgs(`require even number of args (got ${pairs.length})`); + for (let i = 0; i < n && state; i += 2) { + state = mutIn(state, pairs[i], pairs[i + 1]); + } + return state; + }; diff --git a/packages/paths/test/index.ts b/packages/paths/test/index.ts index 0b4567d410..b4de130c80 100644 --- a/packages/paths/test/index.ts +++ b/packages/paths/test/index.ts @@ -157,25 +157,25 @@ describe("paths", () => { a, { x: { y: { z: 1 } }, u: { v: 2 } } ); - assert(a.x === b.x); - assert(a.x.y === b.x.y); - assert(a.u === b.u); + assert.ok(a.x === b.x); + assert.ok(a.x.y === b.x.y); + assert.ok(a.u === b.u); }); it("exists", () => { const a = { a: { b: null } }; const b = { x: { y: { z: [1, 2, { u: 3, v: undefined }] } } }; - assert(!exists(null, "x.y.z"), "x.y.z"); - assert(!exists(0, "x.y.z"), "x.y.z"); - assert(exists("", "length"), "length"); - assert(exists(a, "a.b"), "a.b"); - assert(!exists(a, "a.b.c"), "a.b.c"); - assert(exists(b, "x"), "x"); - assert(exists(b, "x.y.z"), "x.y.z"); - assert(exists(b, "x.y.z.2.u"), "x.y.z.2.u"); - assert(exists(b, "x.y.z.2.v"), "x.y.z.2.v"); - assert(!exists(b, "x.y.z.3"), "x.y.z.3"); - assert(!exists(b, "x.y.z.3.u"), "x.y.z.3.u"); - assert(!exists(b, "x.z.y.2.u"), "x.z.y.2.u"); + 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"); + assert.ok(exists(a, "a.b"), "a.b"); + assert.ok(!exists(a, "a.b.c"), "a.b.c"); + assert.ok(exists(b, "x"), "x"); + assert.ok(exists(b, "x.y.z"), "x.y.z"); + assert.ok(exists(b, "x.y.z.2.u"), "x.y.z.2.u"); + assert.ok(exists(b, "x.y.z.2.v"), "x.y.z.2.v"); + assert.ok(!exists(b, "x.y.z.3"), "x.y.z.3"); + assert.ok(!exists(b, "x.y.z.3.u"), "x.y.z.3.u"); + assert.ok(!exists(b, "x.z.y.2.u"), "x.z.y.2.u"); }) }); diff --git a/packages/paths/test/tsconfig.json b/packages/paths/test/tsconfig.json index bcf29ace54..2c9c12a650 100644 --- a/packages/paths/test/tsconfig.json +++ b/packages/paths/test/tsconfig.json @@ -1,10 +1,11 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", "../src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/paths/tsconfig.json b/packages/paths/tsconfig.json index bd6481a5a6..bcf03f18b4 100644 --- a/packages/paths/tsconfig.json +++ b/packages/paths/tsconfig.json @@ -1,9 +1,11 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/pointfree-lang/.npmignore b/packages/pointfree-lang/.npmignore index d703bda97a..67d0c55714 100644 --- a/packages/pointfree-lang/.npmignore +++ b/packages/pointfree-lang/.npmignore @@ -1,10 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/pointfree-lang/CHANGELOG.md b/packages/pointfree-lang/CHANGELOG.md index b8854e36b3..c65c889e0f 100644 --- a/packages/pointfree-lang/CHANGELOG.md +++ b/packages/pointfree-lang/CHANGELOG.md @@ -3,6 +3,33 @@ 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/pointfree-lang@0.2.27...@thi.ng/pointfree-lang@1.0.0) (2019-01-21) + + +### Bug Fixes + +* **pointfree-lang:** update NodeType handling ([227be4b](https://github.com/thi-ng/umbrella/commit/227be4b)) + + +### Build System + +* update package build scripts & outputs, imports in ~50 packages ([b54b703](https://github.com/thi-ng/umbrella/commit/b54b703)) + + +### BREAKING CHANGES + +* enabled multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols. + + + + + ## [0.2.27](https://github.com/thi-ng/umbrella/compare/@thi.ng/pointfree-lang@0.2.26...@thi.ng/pointfree-lang@0.2.27) (2018-12-27) **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 f6349f4718..a4b69be362 100644 --- a/packages/pointfree-lang/package.json +++ b/packages/pointfree-lang/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/pointfree-lang", - "version": "0.2.27", + "version": "1.0.0", "description": "Forth style syntax layer/compiler for the @thi.ng/pointfree DSL", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,27 +14,29 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn clean && tsc --declaration && yarn peg", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration && yarn peg", + "build:bundle": "../../scripts/bundle-module pointfreeLang api errors pointfree", + "test": "rimraf build && tsc -p test/tsconfig.json && yarn pegtest && nyc mocha build/test/*.js", + "peg": "pegjs -f es -o parser.js src/grammar.pegjs", + "pegtest": "pegjs -o build/src/parser.js src/grammar.pegjs", + "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", - "peg": "pegjs -o parser.js src/grammar.pegjs", - "pegtest": "pegjs -o build/src/parser.js src/grammar.pegjs", - "pub": "yarn build && yarn publish --access public", - "test": "rm -rf build && tsc -p test && yarn pegtest && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", - "pegjs": "^0.10.0", - "typedoc": "^0.13.0", + "pegjs": "^0.11.0-dev.325", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/api": "^4.2.4", - "@thi.ng/errors": "^0.1.12", - "@thi.ng/pointfree": "^0.8.15" + "@thi.ng/api": "^5.0.0", + "@thi.ng/errors": "^1.0.0", + "@thi.ng/pointfree": "^1.0.0" }, "keywords": [ "concatenative", @@ -49,5 +53,6 @@ ], "publishConfig": { "access": "public" - } + }, + "sideEffects": false } diff --git a/packages/pointfree-lang/src/api.ts b/packages/pointfree-lang/src/api.ts index 66e48dab41..b5070a1184 100644 --- a/packages/pointfree-lang/src/api.ts +++ b/packages/pointfree-lang/src/api.ts @@ -1,4 +1,4 @@ -import { IObjectOf } from "@thi.ng/api/api"; +import { IObjectOf } from "@thi.ng/api"; import * as pf from "@thi.ng/pointfree"; export interface ASTNode { @@ -34,7 +34,7 @@ export const enum NodeType { /** * Reverse lookup for `NodeType` enums */ -export const __NodeType = (exports).NodeType; +// export const __NodeType = (exports).NodeType; export const ALIASES: IObjectOf = { "?drop": pf.dropif, diff --git a/packages/pointfree-lang/src/grammar.pegjs b/packages/pointfree-lang/src/grammar.pegjs index 0b628fee70..7176fc2892 100644 --- a/packages/pointfree-lang/src/grammar.pegjs +++ b/packages/pointfree-lang/src/grammar.pegjs @@ -1,19 +1,19 @@ { - const __NodeType = require("./api").__NodeType; - - // const __NodeType = {}; - // __NodeType[__NodeType["SYM"] = 1] = "SYM"; - // __NodeType[__NodeType["WORD"] = 2] = "WORD"; - // __NodeType[__NodeType["VAR_DEREF"] = 3] = "VAR_DEREF"; - // __NodeType[__NodeType["VAR_STORE"] = 4] = "VAR_STORE"; - // __NodeType[__NodeType["NIL"] = 5] = "NIL"; - // __NodeType[__NodeType["NUMBER"] = 6] = "NUMBER"; - // __NodeType[__NodeType["BOOLEAN"] = 7] = "BOOLEAN"; - // __NodeType[__NodeType["STRING"] = 8] = "STRING"; - // __NodeType[__NodeType["ARRAY"] = 9] = "ARRAY"; - // __NodeType[__NodeType["OBJ"] = 10] = "OBJ"; - // __NodeType[__NodeType["COMMENT"] = 11] = "COMMENT"; - // __NodeType[__NodeType["STACK_COMMENT"] = 12] = "STACK_COMMENT"; + // const __NodeType = require("./api").__NodeType; + + const NodeType = {}; + NodeType[NodeType["SYM"] = 1] = "SYM"; + NodeType[NodeType["WORD"] = 2] = "WORD"; + NodeType[NodeType["VAR_DEREF"] = 3] = "VAR_DEREF"; + NodeType[NodeType["VAR_STORE"] = 4] = "VAR_STORE"; + NodeType[NodeType["NIL"] = 5] = "NIL"; + NodeType[NodeType["NUMBER"] = 6] = "NUMBER"; + NodeType[NodeType["BOOLEAN"] = 7] = "BOOLEAN"; + NodeType[NodeType["STRING"] = 8] = "STRING"; + NodeType[NodeType["ARRAY"] = 9] = "ARRAY"; + NodeType[NodeType["OBJ"] = 10] = "OBJ"; + NodeType[NodeType["COMMENT"] = 11] = "COMMENT"; + NodeType[NodeType["STACK_COMMENT"] = 12] = "STACK_COMMENT"; const ast = (node) => { const loc = location().start; @@ -42,7 +42,7 @@ NonWordExpr Word = ":" __ id:Sym locals:LocalVars? body:NonWordExpr+ ";" { - return { type: __NodeType.WORD, id: id.id, locals, body}; + return { type: NodeType.WORD, id: id.id, locals, body}; } LocalVars @@ -55,12 +55,12 @@ SymList Array = "[" body:NonWordExpr* "]" { - return { type: __NodeType.ARRAY, body }; + return { type: NodeType.ARRAY, body }; } Obj = "{" _ body:ObjPair* "}" { - return { type: __NodeType.OBJ, body }; + return { type: NodeType.OBJ, body }; } ObjPair @@ -92,17 +92,17 @@ Atom Nil = "nil" { - return {type: __NodeType.NIL, body: null}; + return {type: NodeType.NIL, body: null}; } Boolean = $("T" / "F") { - return {type: __NodeType.BOOLEAN, body: text() == "T"}; + return {type: NodeType.BOOLEAN, body: text() == "T"}; } Sym = id:$((Alpha / SymChars) (AlphaNum / SymChars)*) { - return {type: __NodeType.SYM, id}; + return {type: NodeType.SYM, id}; } SymChars @@ -114,35 +114,35 @@ Var VarDeref = "@" id:Sym { - return {type: __NodeType.VAR_DEREF, id: id.id} + return {type: NodeType.VAR_DEREF, id: id.id} } VarStore = id:Sym "!" { - return {type: __NodeType.VAR_STORE, id: id.id} + return {type: NodeType.VAR_STORE, id: id.id} } LitQuote = "'" body:NonWordExpr { - return {type: __NodeType.ARRAY, body: [body]}; + return {type: NodeType.ARRAY, body: [body]}; } Comment = "("+ body:$(!")" .)* ")" { return body.indexOf("--") > 0 ? { - type: __NodeType.STACK_COMMENT, + type: NodeType.STACK_COMMENT, body: body.split("--").map(x => x.trim()) } : { - type: __NodeType.COMMENT, + type: NodeType.COMMENT, body: body.trim() }; } String = "\"" body:$(!"\"" .)* "\"" { - return {type: __NodeType.STRING, body }; + return {type: NodeType.STRING, body }; } Number @@ -154,12 +154,12 @@ Sign = [-+] Binary = "0b" n:$[01]+ { - return {type: __NodeType.NUMBER, radix: 2, body: parseInt(n, 2)}; + return {type: NodeType.NUMBER, radix: 2, body: parseInt(n, 2)}; } Hex = "0x" n:$[0-9a-fA-F]+ { - return {type: __NodeType.NUMBER, radix: 16, body: parseInt(n, 16)}; + return {type: NodeType.NUMBER, radix: 16, body: parseInt(n, 16)}; } Int @@ -170,7 +170,7 @@ Uint Decimal = Int ("." Uint?)? ("e" Int)? { - return {type: __NodeType.NUMBER, body: parseFloat(text())}; + return {type: NodeType.NUMBER, body: parseFloat(text())}; } AlphaNum diff --git a/packages/pointfree-lang/src/index.ts b/packages/pointfree-lang/src/index.ts index 18035ecbcd..29186c09ff 100644 --- a/packages/pointfree-lang/src/index.ts +++ b/packages/pointfree-lang/src/index.ts @@ -1,10 +1,8 @@ -import { IObjectOf } from "@thi.ng/api/api"; -import { illegalArgs } from "@thi.ng/errors/illegal-arguments"; -import { illegalState } from "@thi.ng/errors/illegal-state"; +import { IObjectOf } from "@thi.ng/api"; +import { illegalArgs, illegalState } from "@thi.ng/errors"; import * as pf from "@thi.ng/pointfree"; import { - __NodeType, ALIASES, ASTNode, NodeType, @@ -187,7 +185,7 @@ const endvar = (id: string) => (ctx: pf.StackContext) => { * @param state */ const visit = (node: ASTNode, ctx: pf.StackContext, state: VisitorState) => { - DEBUG && console.log("visit", __NodeType[node.type], node, ctx[0].toString()); + DEBUG && console.log("visit", node.type, node, ctx[0].toString()); switch (node.type) { case NodeType.SYM: return visitSym(node, ctx, state); diff --git a/packages/pointfree-lang/test/tsconfig.json b/packages/pointfree-lang/test/tsconfig.json index bcf29ace54..2c9c12a650 100644 --- a/packages/pointfree-lang/test/tsconfig.json +++ b/packages/pointfree-lang/test/tsconfig.json @@ -1,10 +1,11 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", "../src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/pointfree-lang/tsconfig.json b/packages/pointfree-lang/tsconfig.json index bd6481a5a6..faed4e5fe7 100644 --- a/packages/pointfree-lang/tsconfig.json +++ b/packages/pointfree-lang/tsconfig.json @@ -1,9 +1,12 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6", + "preserveConstEnums": false }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/pointfree/.npmignore b/packages/pointfree/.npmignore index d8b97762a7..67d0c55714 100644 --- a/packages/pointfree/.npmignore +++ b/packages/pointfree/.npmignore @@ -1,11 +1,13 @@ -bench +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/pointfree/CHANGELOG.md b/packages/pointfree/CHANGELOG.md index e8c495ec94..4fbff911cd 100644 --- a/packages/pointfree/CHANGELOG.md +++ b/packages/pointfree/CHANGELOG.md @@ -3,6 +3,28 @@ 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/pointfree@0.8.15...@thi.ng/pointfree@1.0.0) (2019-01-21) + + +### Build System + +* update package build scripts & outputs, imports in ~50 packages ([b54b703](https://github.com/thi-ng/umbrella/commit/b54b703)) + + +### BREAKING CHANGES + +* enabled multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols. + + + + + ## [0.8.15](https://github.com/thi-ng/umbrella/compare/@thi.ng/pointfree@0.8.14...@thi.ng/pointfree@0.8.15) (2018-12-27) **Note:** Version bump only for package @thi.ng/pointfree diff --git a/packages/pointfree/package.json b/packages/pointfree/package.json index 235e21c7ad..cb89eb2cb1 100644 --- a/packages/pointfree/package.json +++ b/packages/pointfree/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/pointfree", - "version": "0.8.15", + "version": "1.0.0", "description": "Pointfree functional composition / Forth style stack execution engine", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,27 +14,29 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn run clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module pointfree api checks compose equiv errors", + "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 run build && yarn publish --access public", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/api": "^4.2.4", - "@thi.ng/checks": "^1.5.14", - "@thi.ng/compose": "^0.3.0", - "@thi.ng/equiv": "^0.1.15", - "@thi.ng/errors": "^0.1.12" + "@thi.ng/api": "^5.0.0", + "@thi.ng/checks": "^2.0.0", + "@thi.ng/compose": "^1.0.0", + "@thi.ng/equiv": "^1.0.0", + "@thi.ng/errors": "^1.0.0" }, "keywords": [ "composition", @@ -50,5 +54,6 @@ ], "publishConfig": { "access": "public" - } + }, + "sideEffects": false } diff --git a/packages/pointfree/src/index.ts b/packages/pointfree/src/index.ts index bd97041471..9c816b4e44 100644 --- a/packages/pointfree/src/index.ts +++ b/packages/pointfree/src/index.ts @@ -1,11 +1,8 @@ -import { IObjectOf } from "@thi.ng/api/api"; -import { isArray } from "@thi.ng/checks/is-array"; -import { isFunction } from "@thi.ng/checks/is-function"; -import { isPlainObject } from "@thi.ng/checks/is-plain-object"; -import { compL } from "@thi.ng/compose/comp"; +import { IObjectOf } from "@thi.ng/api"; +import { isArray, isFunction, isPlainObject } from "@thi.ng/checks"; +import { compL } from "@thi.ng/compose"; import { equiv as _equiv } from "@thi.ng/equiv"; -import { illegalArgs } from "@thi.ng/errors/illegal-arguments"; -import { illegalState } from "@thi.ng/errors/illegal-state"; +import { illegalArgs, illegalState } from "@thi.ng/errors"; import { Stack, StackContext, @@ -15,7 +12,6 @@ import { StackProgram } from "./api"; - let SAFE = true; export const safeMode = (state: boolean) => (SAFE = state); diff --git a/packages/pointfree/test/tsconfig.json b/packages/pointfree/test/tsconfig.json index bcf29ace54..2c9c12a650 100644 --- a/packages/pointfree/test/tsconfig.json +++ b/packages/pointfree/test/tsconfig.json @@ -1,10 +1,11 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", "../src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/pointfree/tsconfig.json b/packages/pointfree/tsconfig.json index bd6481a5a6..bcf03f18b4 100644 --- a/packages/pointfree/tsconfig.json +++ b/packages/pointfree/tsconfig.json @@ -1,9 +1,11 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/random/.npmignore b/packages/random/.npmignore index ec83d74c9d..67d0c55714 100644 --- a/packages/random/.npmignore +++ b/packages/random/.npmignore @@ -1,11 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc -export src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/random/CHANGELOG.md b/packages/random/CHANGELOG.md index 1dfc3f5d48..9330e00463 100644 --- a/packages/random/CHANGELOG.md +++ b/packages/random/CHANGELOG.md @@ -3,6 +3,28 @@ 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/random@0.1.1...@thi.ng/random@1.0.0) (2019-01-21) + + +### Build System + +* update package build scripts & outputs, imports in ~50 packages ([b54b703](https://github.com/thi-ng/umbrella/commit/b54b703)) + + +### BREAKING CHANGES + +* enabled multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols. + + + + + ## [0.1.1](https://github.com/thi-ng/umbrella/compare/@thi.ng/random@0.1.0...@thi.ng/random@0.1.1) (2018-12-15) **Note:** Version bump only for package @thi.ng/random diff --git a/packages/random/README.md b/packages/random/README.md index 66e404c459..866ea00c82 100644 --- a/packages/random/README.md +++ b/packages/random/README.md @@ -43,9 +43,9 @@ yarn add @thi.ng/random ## Usage examples ```ts -import * as r from "@thi.ng/random"; +import { Smush32 } from "@thi.ng/random"; -const rnd = new r.Smush32(0xdecafbad); +const rnd = new Smush32(0xdecafbad); // the following methods are available for all generators diff --git a/packages/random/package.json b/packages/random/package.json index 57c04c321c..00ba040dbb 100644 --- a/packages/random/package.json +++ b/packages/random/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/random", - "version": "0.1.1", + "version": "1.0.0", "description": "Pseudo-random number generators w/ unified API", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,23 +14,25 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn run clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module random api", + "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 run build && yarn publish --access public", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/api": "^4.2.4" + "@thi.ng/api": "^5.0.0" }, "keywords": [ "ES6", @@ -39,5 +43,6 @@ ], "publishConfig": { "access": "public" - } + }, + "sideEffects": false } diff --git a/packages/random/src/api.ts b/packages/random/src/api.ts index 078cc71f35..3cc92b0296 100644 --- a/packages/random/src/api.ts +++ b/packages/random/src/api.ts @@ -1,4 +1,4 @@ -import { ICopy } from "@thi.ng/api/api"; +import { ICopy } from "@thi.ng/api"; export interface IRandom { int(): number; diff --git a/packages/random/src/smush32.ts b/packages/random/src/smush32.ts index 48cf7df311..0cf7a3f2e3 100644 --- a/packages/random/src/smush32.ts +++ b/packages/random/src/smush32.ts @@ -1,4 +1,4 @@ -import { IBuffered, ICopy } from "@thi.ng/api/api"; +import { IBuffered, ICopy } from "@thi.ng/api"; import { ARandom, ISeedable } from "./api"; // https://github.com/thi-ng/ct-head/blob/master/random.h diff --git a/packages/random/src/xorshift128.ts b/packages/random/src/xorshift128.ts index f30f24f21c..ef36fd480b 100644 --- a/packages/random/src/xorshift128.ts +++ b/packages/random/src/xorshift128.ts @@ -1,4 +1,4 @@ -import { IBuffered, ICopy } from "@thi.ng/api/api"; +import { IBuffered, ICopy } from "@thi.ng/api"; import { ARandom, ISeedable } from "./api"; // https://en.wikipedia.org/wiki/Xorshift diff --git a/packages/random/src/xorwow.ts b/packages/random/src/xorwow.ts index 8ac281751b..2fb7f3635a 100644 --- a/packages/random/src/xorwow.ts +++ b/packages/random/src/xorwow.ts @@ -1,4 +1,4 @@ -import { IBuffered, ICopy } from "@thi.ng/api/api"; +import { IBuffered, ICopy } from "@thi.ng/api"; import { ARandom, ISeedable } from "./api"; // https://en.wikipedia.org/wiki/Xorshift#xorwow diff --git a/packages/random/src/xsadd.ts b/packages/random/src/xsadd.ts index 2bf75a106f..479416e8ee 100644 --- a/packages/random/src/xsadd.ts +++ b/packages/random/src/xsadd.ts @@ -1,4 +1,4 @@ -import { IBuffered, ICopy } from "@thi.ng/api/api"; +import { IBuffered, ICopy } from "@thi.ng/api"; import { ARandom, ISeedable } from "./api"; // https://github.com/MersenneTwister-Lab/XSadd/blob/master/xsadd.h diff --git a/packages/random/test/tsconfig.json b/packages/random/test/tsconfig.json index bcf29ace54..2c9c12a650 100644 --- a/packages/random/test/tsconfig.json +++ b/packages/random/test/tsconfig.json @@ -1,10 +1,11 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", "../src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/random/tsconfig.json b/packages/random/tsconfig.json index bd6481a5a6..bcf03f18b4 100644 --- a/packages/random/tsconfig.json +++ b/packages/random/tsconfig.json @@ -1,9 +1,11 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/range-coder/.npmignore b/packages/range-coder/.npmignore index 538f8b608d..67d0c55714 100644 --- a/packages/range-coder/.npmignore +++ b/packages/range-coder/.npmignore @@ -1,14 +1,13 @@ -bench/* -build/* -dev/* -node_modules -src* -test* -bundle.* -tsconfig.json -webpack.config.js +.cache +.meta +.nyc_output +*.gz *.html *.tgz -!doc/* -!*.d.ts -!*.js +build +coverage +dev +doc +src* +test +tsconfig.json diff --git a/packages/range-coder/CHANGELOG.md b/packages/range-coder/CHANGELOG.md index 7d2972e050..b96cd8d8cb 100644 --- a/packages/range-coder/CHANGELOG.md +++ b/packages/range-coder/CHANGELOG.md @@ -3,6 +3,28 @@ 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/range-coder@0.1.28...@thi.ng/range-coder@1.0.0) (2019-01-21) + + +### Build System + +* update package build scripts & outputs, imports in ~50 packages ([b54b703](https://github.com/thi-ng/umbrella/commit/b54b703)) + + +### BREAKING CHANGES + +* enabled multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols. + + + + + ## [0.1.28](https://github.com/thi-ng/umbrella/compare/@thi.ng/range-coder@0.1.27...@thi.ng/range-coder@0.1.28) (2019-01-02) **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 59216429c8..6f82c68a65 100644 --- a/packages/range-coder/package.json +++ b/packages/range-coder/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/range-coder", - "version": "0.1.28", + "version": "1.0.0", "description": "Binary data range encoder / decoder", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,24 +14,26 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module rangeCoder bitstream", + "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", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { - "@thi.ng/transducers": "^2.3.2", + "@thi.ng/transducers": "^3.0.0", "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/bitstream": "^0.4.21" + "@thi.ng/bitstream": "^1.0.0" }, "keywords": [ "ES6", @@ -41,5 +45,6 @@ ], "publishConfig": { "access": "public" - } + }, + "sideEffects": false } diff --git a/packages/range-coder/test/index.ts b/packages/range-coder/test/index.ts index 1c9d6abba8..3709477bdd 100644 --- a/packages/range-coder/test/index.ts +++ b/packages/range-coder/test/index.ts @@ -21,6 +21,6 @@ describe("range-coder", () => { }); }); -function randomArray(n: number, len: number) { - return 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/range-coder/test/tsconfig.json b/packages/range-coder/test/tsconfig.json index 13d45669e5..2c9c12a650 100644 --- a/packages/range-coder/test/tsconfig.json +++ b/packages/range-coder/test/tsconfig.json @@ -1,7 +1,8 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", diff --git a/packages/range-coder/tsconfig.json b/packages/range-coder/tsconfig.json index fe4ca75067..bcf03f18b4 100644 --- a/packages/range-coder/tsconfig.json +++ b/packages/range-coder/tsconfig.json @@ -1,9 +1,11 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ - "./src/**/*.ts", + "./src/**/*.ts" ] } \ No newline at end of file diff --git a/packages/resolve-map/.npmignore b/packages/resolve-map/.npmignore index d703bda97a..67d0c55714 100644 --- a/packages/resolve-map/.npmignore +++ b/packages/resolve-map/.npmignore @@ -1,10 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/resolve-map/CHANGELOG.md b/packages/resolve-map/CHANGELOG.md index f8a225ad7d..794844be41 100644 --- a/packages/resolve-map/CHANGELOG.md +++ b/packages/resolve-map/CHANGELOG.md @@ -3,6 +3,28 @@ 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/resolve-map@3.0.16...@thi.ng/resolve-map@4.0.0) (2019-01-21) + + +### Build System + +* update package build scripts & outputs, imports in ~50 packages ([b54b703](https://github.com/thi-ng/umbrella/commit/b54b703)) + + +### BREAKING CHANGES + +* enabled multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols. + + + + + ## [3.0.16](https://github.com/thi-ng/umbrella/compare/@thi.ng/resolve-map@3.0.15...@thi.ng/resolve-map@3.0.16) (2018-12-15) **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 76d4ad8207..68b0af4480 100644 --- a/packages/resolve-map/package.json +++ b/packages/resolve-map/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/resolve-map", - "version": "3.0.16", + "version": "4.0.0", "description": "DAG resolution of vanilla objects & arrays with internally linked values", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,23 +14,27 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn run clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module resolveMap api checks errors paths", + "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 run build && yarn publish --access public", - "test": "rm -rf build && tsc -p test && mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/checks": "^1.5.14", - "@thi.ng/errors": "^0.1.12", - "@thi.ng/paths": "^1.6.6" + "@thi.ng/api": "^5.0.0", + "@thi.ng/checks": "^2.0.0", + "@thi.ng/errors": "^1.0.0", + "@thi.ng/paths": "^2.0.0" }, "keywords": [ "configuration", @@ -41,5 +47,6 @@ ], "publishConfig": { "access": "public" - } + }, + "sideEffects": false } diff --git a/packages/resolve-map/src/index.ts b/packages/resolve-map/src/index.ts index ec3ab991c0..5e8985a905 100644 --- a/packages/resolve-map/src/index.ts +++ b/packages/resolve-map/src/index.ts @@ -1,9 +1,11 @@ -import { SEMAPHORE } from "@thi.ng/api/api"; -import { isArray } from "@thi.ng/checks/is-array"; -import { isFunction } from "@thi.ng/checks/is-function"; -import { isPlainObject } from "@thi.ng/checks/is-plain-object"; -import { isString } from "@thi.ng/checks/is-string"; -import { illegalArgs } from "@thi.ng/errors/illegal-arguments"; +import { SEMAPHORE } from "@thi.ng/api"; +import { + isArray, + isFunction, + isPlainObject, + isString +} from "@thi.ng/checks"; +import { illegalArgs } from "@thi.ng/errors"; import { exists, getIn, mutIn } from "@thi.ng/paths"; const RE_ARGS = /^(function\s+\w+)?\s*\(\{([\w\s,:]+)\}/ @@ -91,16 +93,23 @@ export type LookupPath = PropertyKey[]; * * @param root */ -export const resolve = (root: any) => { - if (isPlainObject(root)) { - return resolveMap(root); - } else if (isArray(root)) { - return resolveArray(root); - } - return root; -}; +export const resolve = + (root: any) => { + if (isPlainObject(root)) { + return resolveMap(root); + } else if (isArray(root)) { + return resolveArray(root); + } + return root; + }; -const resolveMap = (obj: any, root?: any, path: LookupPath = [], resolved: any = {}, stack: string[] = []) => { +const resolveMap = ( + obj: any, + root?: any, + path: LookupPath = [], + resolved: any = {}, + stack: string[] = [] +) => { root = root || obj; for (let k in obj) { _resolve(root, [...path, k], resolved, stack); @@ -108,7 +117,13 @@ const resolveMap = (obj: any, root?: any, path: LookupPath = [], resolved: any = return obj; }; -const resolveArray = (arr: any[], root?: any, path: LookupPath = [], resolved: any = {}, stack: string[] = []) => { +const resolveArray = ( + arr: any[], + root?: any, + path: LookupPath = [], + resolved: any = {}, + stack: string[] = [] +) => { root = root || arr; for (let k = 0, n = arr.length; k < n; k++) { _resolve(root, [...path, k], resolved, stack); @@ -127,7 +142,12 @@ const resolveArray = (arr: any[], root?: any, path: LookupPath = [], resolved: a * @param resolved * @param stack */ -const _resolve = (root: any, path: LookupPath, resolved: any, stack: string[]) => { +const _resolve = ( + root: any, + path: LookupPath, + resolved: any, + stack: string[] +) => { const pathID = path.join("/"); if (stack.indexOf(pathID) >= 0) { illegalArgs(`cyclic references not allowed: ${pathID}`); @@ -175,7 +195,12 @@ const _resolve = (root: any, path: LookupPath, resolved: any, stack: string[]) = * @param path * @param resolved */ -const resolvePath = (root: any, path: LookupPath, resolved: any, stack: string[] = []) => { +const resolvePath = ( + root: any, + path: LookupPath, + resolved: any, + stack: string[] = [] +) => { // temporarily remove current path to avoid cycle detection let pathID = stack.pop() let v; @@ -204,7 +229,12 @@ const resolvePath = (root: any, path: LookupPath, resolved: any, stack: string[] * @param pathID current base path for marking * @param resolved */ -const resolveFunction = (fn: (x: any, r?: ResolveFn) => any, resolve: ResolveFn, pathID: string, resolved: any) => { +const resolveFunction = ( + fn: (x: any, r?: ResolveFn) => any, + resolve: ResolveFn, + pathID: string, + resolved: any +) => { const match = RE_ARGS.exec(fn.toString()); let res; if (match) { @@ -222,33 +252,36 @@ const resolveFunction = (fn: (x: any, r?: ResolveFn) => any, resolve: ResolveFn, return res; }; -const markResolved = (v: any, path: string, resolved: any) => { - resolved[path] = true; - if (isPlainObject(v)) { - markObjResolved(v, path, resolved); - } - else if (isArray(v)) { - markArrayResolved(v, path, resolved); - } -}; +const markResolved = + (v: any, path: string, resolved: any) => { + resolved[path] = true; + if (isPlainObject(v)) { + markObjResolved(v, path, resolved); + } + else if (isArray(v)) { + markArrayResolved(v, path, resolved); + } + }; -const markObjResolved = (obj: any, path: string, resolved: any) => { - let v, p; - for (let k in obj) { - v = obj[k]; - p = path + "/" + k; - markResolved(v, p, resolved); - } -}; +const markObjResolved = + (obj: any, path: string, resolved: any) => { + let v, p; + for (let k in obj) { + v = obj[k]; + p = path + "/" + k; + markResolved(v, p, resolved); + } + }; -const markArrayResolved = (arr: any[], path: string, resolved: any) => { - let v, p; - for (let i = 0, n = arr.length; i < n; i++) { - v = arr[i]; - p = path + "/" + i; - markResolved(v, p, resolved); - } -}; +const markArrayResolved = + (arr: any[], path: string, resolved: any) => { + let v, p; + for (let i = 0, n = arr.length; i < n; i++) { + v = arr[i]; + p = path + "/" + i; + markResolved(v, p, resolved); + } + }; /** * Takes the path for the current key and a lookup path string. Converts @@ -258,20 +291,21 @@ const markArrayResolved = (arr: any[], path: string, resolved: any) => { * @param path * @param idx */ -export const absPath = (curr: LookupPath, path: string, idx = 1): PropertyKey[] => { - if (path.charAt(idx) === "/") { - return path.substr(idx + 1).split("/"); - } - curr = curr.slice(0, curr.length - 1); - const sub = path.substr(idx).split("/"); - for (let i = 0, n = sub.length; i < n; i++) { - if (sub[i] === "..") { - !curr.length && illegalArgs(`invalid lookup path: ${path}`); - curr.pop(); - } else { - return curr.concat(sub.slice(i)); +export const absPath = + (curr: LookupPath, path: string, idx = 1): PropertyKey[] => { + if (path.charAt(idx) === "/") { + return path.substr(idx + 1).split("/"); } - } - !curr.length && illegalArgs(`invalid lookup path: ${path}`); - return curr; -}; + curr = curr.slice(0, curr.length - 1); + const sub = path.substr(idx).split("/"); + for (let i = 0, n = sub.length; i < n; i++) { + if (sub[i] === "..") { + !curr.length && illegalArgs(`invalid lookup path: ${path}`); + curr.pop(); + } else { + return curr.concat(sub.slice(i)); + } + } + !curr.length && illegalArgs(`invalid lookup path: ${path}`); + return curr; + }; diff --git a/packages/resolve-map/test/tsconfig.json b/packages/resolve-map/test/tsconfig.json index bcf29ace54..2c9c12a650 100644 --- a/packages/resolve-map/test/tsconfig.json +++ b/packages/resolve-map/test/tsconfig.json @@ -1,10 +1,11 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", "../src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/resolve-map/tsconfig.json b/packages/resolve-map/tsconfig.json index bd6481a5a6..bcf03f18b4 100644 --- a/packages/resolve-map/tsconfig.json +++ b/packages/resolve-map/tsconfig.json @@ -1,9 +1,11 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/rle-pack/.npmignore b/packages/rle-pack/.npmignore index d703bda97a..67d0c55714 100644 --- a/packages/rle-pack/.npmignore +++ b/packages/rle-pack/.npmignore @@ -1,10 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/rle-pack/CHANGELOG.md b/packages/rle-pack/CHANGELOG.md index 25d8f4a30c..05593166a0 100644 --- a/packages/rle-pack/CHANGELOG.md +++ b/packages/rle-pack/CHANGELOG.md @@ -3,6 +3,28 @@ 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/rle-pack@1.0.8...@thi.ng/rle-pack@2.0.0) (2019-01-21) + + +### Build System + +* update package build scripts & outputs, imports in ~50 packages ([b54b703](https://github.com/thi-ng/umbrella/commit/b54b703)) + + +### BREAKING CHANGES + +* enabled multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols. + + + + + ## [1.0.8](https://github.com/thi-ng/umbrella/compare/@thi.ng/rle-pack@1.0.7...@thi.ng/rle-pack@1.0.8) (2018-12-15) **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 c9c4695a08..5381489245 100644 --- a/packages/rle-pack/package.json +++ b/packages/rle-pack/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/rle-pack", - "version": "1.0.8", + "version": "2.0.0", "description": "Binary run-length encoding packer w/ flexible repeat bit widths", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,12 +14,14 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module rlePack bitstream errors", + "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", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", @@ -25,22 +29,27 @@ "benchmark": "^2.1.4", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/bitstream": "^0.4.21", - "@thi.ng/errors": "^0.1.12" + "@thi.ng/bitstream": "^1.0.0", + "@thi.ng/errors": "^1.0.0" }, "keywords": [ "binary", "bits", + "compression", "ES6", "packer", "RLE", - "typescript" + "run-length", + "typescript", + "variable width", + "wordsize" ], "publishConfig": { "access": "public" - } + }, + "sideEffects": false } diff --git a/packages/rle-pack/src/index.ts b/packages/rle-pack/src/index.ts index e6e5901bdd..e665c8c04f 100644 --- a/packages/rle-pack/src/index.ts +++ b/packages/rle-pack/src/index.ts @@ -1,5 +1,5 @@ import { BitInputStream, BitOutputStream } from "@thi.ng/bitstream"; -import { illegalArgs } from "@thi.ng/errors/illegal-arguments"; +import { illegalArgs } from "@thi.ng/errors"; export type RLESizes = [number, number, number, number]; @@ -12,7 +12,12 @@ export type RLESizes = [number, number, number, number]; * @param wordSize in bits, range 1 - 32 * @param rleSizes run-length group sizes (in bits, max. 16) */ -export function encode(src: Iterable, num: number, wordSize = 8, rleSizes: RLESizes = [3, 4, 8, 16]) { +export const encode = ( + src: Iterable, + num: number, + wordSize = 8, + rleSizes: RLESizes = [3, 4, 8, 16] +) => { (wordSize < 1 || wordSize > 32) && illegalArgs("word size (1-32 bits only)"); const out = new BitOutputStream(Math.ceil(num * wordSize / 8) + 4 + 2 + 1) .write(num, 32) @@ -80,34 +85,36 @@ export function encode(src: Iterable, num: number, wordSize = 8, rleSize writeRLE(); } return out.bytes(); -} +}; -export function decode(src: Uint8Array) { - const input = new BitInputStream(src); - const num = input.read(32); - const wordSize = input.read(5) + 1; - const rleSizes = [0, 0, 0, 0].map(() => input.read(4) + 1); - const out = arrayForWordSize(wordSize, num); - let x, j; - for (let i = 0; i < num;) { - x = input.readBit(); - j = i + 1 + input.read(rleSizes[input.read(2)]); - if (x) { - out.fill(input.read(wordSize), i, j); - i = j; - } else { - for (; i < j; i++) { - out[i] = input.read(wordSize); +export const decode = + (src: Uint8Array) => { + const input = new BitInputStream(src); + const num = input.read(32); + const wordSize = input.read(5) + 1; + const rleSizes = [0, 0, 0, 0].map(() => input.read(4) + 1); + const out = arrayForWordSize(wordSize, num); + let x, j; + for (let i = 0; i < num;) { + x = input.readBit(); + j = i + 1 + input.read(rleSizes[input.read(2)]); + if (x) { + out.fill(input.read(wordSize), i, j); + i = j; + } else { + for (; i < j; i++) { + out[i] = input.read(wordSize); + } } } - } - return out; -} + return out; + }; -const arrayForWordSize = (ws: number, n: number) => { - return new (ws < 9 ? - Uint8Array : - ws < 17 ? - Uint16Array : - Uint32Array)(n); -} \ No newline at end of file +const arrayForWordSize = + (ws: number, n: number) => { + return new (ws < 9 ? + Uint8Array : + ws < 17 ? + Uint16Array : + Uint32Array)(n); + }; \ No newline at end of file diff --git a/packages/rle-pack/test/tsconfig.json b/packages/rle-pack/test/tsconfig.json index 13d45669e5..2c9c12a650 100644 --- a/packages/rle-pack/test/tsconfig.json +++ b/packages/rle-pack/test/tsconfig.json @@ -1,7 +1,8 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", diff --git a/packages/rle-pack/tsconfig.json b/packages/rle-pack/tsconfig.json index f6c291a0a0..bcf03f18b4 100644 --- a/packages/rle-pack/tsconfig.json +++ b/packages/rle-pack/tsconfig.json @@ -1,7 +1,9 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" diff --git a/packages/router/.npmignore b/packages/router/.npmignore index d703bda97a..67d0c55714 100644 --- a/packages/router/.npmignore +++ b/packages/router/.npmignore @@ -1,10 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/router/CHANGELOG.md b/packages/router/CHANGELOG.md index 1c2fc004a3..8d7d8be8b7 100644 --- a/packages/router/CHANGELOG.md +++ b/packages/router/CHANGELOG.md @@ -3,6 +3,28 @@ 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/router@0.1.30...@thi.ng/router@1.0.0) (2019-01-21) + + +### Build System + +* update package build scripts & outputs, imports in ~50 packages ([b54b703](https://github.com/thi-ng/umbrella/commit/b54b703)) + + +### BREAKING CHANGES + +* enabled multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols. + + + + + ## [0.1.30](https://github.com/thi-ng/umbrella/compare/@thi.ng/router@0.1.29...@thi.ng/router@0.1.30) (2018-12-15) **Note:** Version bump only for package @thi.ng/router diff --git a/packages/router/README.md b/packages/router/README.md index 7b35f79fe6..9827a64cd7 100644 --- a/packages/router/README.md +++ b/packages/router/README.md @@ -56,7 +56,7 @@ A complete, full commented demo app is here: [Live demo](https://demo.thi.ng/umbrella/router-basics/) ```ts -import * as r from "@thi.ng/router"; +import { HTMLRouter, EV_ROUTE_CHANGED } from "@thi.ng/router"; // router configuration const config = { @@ -139,8 +139,8 @@ const config = { // `HTMLRouter` ONLY works in browser environments // for non-browser use cases use `BasicRouter` -const router = new r.HTMLRouter(config); -router.addListener(r.EV_ROUTE_CHANGED, console.log); +const router = new HTMLRouter(config); +router.addListener(EV_ROUTE_CHANGED, console.log); router.start(); ``` diff --git a/packages/router/package.json b/packages/router/package.json index 52ca63dd08..f0440281fe 100644 --- a/packages/router/package.json +++ b/packages/router/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/router", - "version": "0.1.30", + "version": "1.0.0", "description": "Generic router for browser & non-browser based applications", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,37 +14,44 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn run clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module router api checks equiv errors", + "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 run build && yarn publish --access public", - "test": "rm -rf build && tsc -p test && mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/api": "^4.2.4", - "@thi.ng/checks": "^1.5.14", - "@thi.ng/equiv": "^0.1.15", - "@thi.ng/errors": "^0.1.12" + "@thi.ng/api": "^5.0.0", + "@thi.ng/checks": "^2.0.0", + "@thi.ng/equiv": "^1.0.0", + "@thi.ng/errors": "^1.0.0" }, "keywords": [ + "browser", "declarative", "ES6", "html", "history", "parametric", "router", + "SPA", "typescript", - "validation" + "validation", + "UI" ], "publishConfig": { "access": "public" - } + }, + "sideEffects": false } diff --git a/packages/router/src/api.ts b/packages/router/src/api.ts index 05077031cc..40269510ff 100644 --- a/packages/router/src/api.ts +++ b/packages/router/src/api.ts @@ -1,4 +1,4 @@ -import { IID, IObjectOf } from "@thi.ng/api/api"; +import { IID, IObjectOf } from "@thi.ng/api"; /** * A validation function to for authenticated routes. If this function diff --git a/packages/router/src/basic.ts b/packages/router/src/basic.ts index 6a0082ebd3..a03e628fa7 100644 --- a/packages/router/src/basic.ts +++ b/packages/router/src/basic.ts @@ -1,15 +1,13 @@ import { Event, INotify, + INotifyMixin, IObjectOf, Listener -} from "@thi.ng/api/api"; -import * as mixin from "@thi.ng/api/mixins/inotify"; -import { isString } from "@thi.ng/checks/is-string"; +} from "@thi.ng/api"; +import { isString } from "@thi.ng/checks"; import { equiv } from "@thi.ng/equiv"; -import { illegalArgs } from "@thi.ng/errors/illegal-arguments"; -import { illegalArity } from "@thi.ng/errors/illegal-arity"; - +import { illegalArgs, illegalArity } from "@thi.ng/errors"; import { EVENT_ROUTE_CHANGED, Route, @@ -18,7 +16,7 @@ import { RouterConfig } from "./api"; -@mixin.INotify +@INotifyMixin export class BasicRouter implements INotify { diff --git a/packages/router/src/history.ts b/packages/router/src/history.ts index 0a9b650adf..b6dfdb8245 100644 --- a/packages/router/src/history.ts +++ b/packages/router/src/history.ts @@ -1,7 +1,6 @@ +import { isString } from "@thi.ng/checks"; import { equiv } from "@thi.ng/equiv"; import { illegalArity } from "@thi.ng/errors"; -import { isString } from "@thi.ng/checks/is-string"; - import { HTMLRouterConfig, RouteMatch, RouterConfig } from "./api"; import { BasicRouter } from "./basic"; diff --git a/packages/router/test/tsconfig.json b/packages/router/test/tsconfig.json index bcf29ace54..2c9c12a650 100644 --- a/packages/router/test/tsconfig.json +++ b/packages/router/test/tsconfig.json @@ -1,10 +1,11 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", "../src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/router/tsconfig.json b/packages/router/tsconfig.json index bd6481a5a6..bcf03f18b4 100644 --- a/packages/router/tsconfig.json +++ b/packages/router/tsconfig.json @@ -1,9 +1,11 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/rstream-csp/.npmignore b/packages/rstream-csp/.npmignore index d703bda97a..67d0c55714 100644 --- a/packages/rstream-csp/.npmignore +++ b/packages/rstream-csp/.npmignore @@ -1,10 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/rstream-csp/CHANGELOG.md b/packages/rstream-csp/CHANGELOG.md index 14f10a5ea7..05bdacd7e2 100644 --- a/packages/rstream-csp/CHANGELOG.md +++ b/packages/rstream-csp/CHANGELOG.md @@ -3,6 +3,28 @@ 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/rstream-csp@0.1.125...@thi.ng/rstream-csp@1.0.0) (2019-01-21) + + +### Build System + +* update package scripts, outputs, imports in remaining packages ([f912a84](https://github.com/thi-ng/umbrella/commit/f912a84)) + + +### BREAKING CHANGES + +* enable multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols + + + + + ## [0.1.125](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-csp@0.1.124...@thi.ng/rstream-csp@0.1.125) (2019-01-02) **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 597657234c..d2f8c94792 100644 --- a/packages/rstream-csp/package.json +++ b/packages/rstream-csp/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/rstream-csp", - "version": "0.1.125", + "version": "1.0.0", "description": "@thi.ng/csp bridge module for @thi.ng/rstream", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,24 +14,26 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc from", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module rstreamCsp csp rstream", + "test": "rimraf build && tsc -p test/tsconfig.json && nyc mocha build/test/*.js", + "clean": "rimraf *.js *.d.ts .nyc_output build coverage doc lib from", "cover": "yarn test && nyc report --reporter=lcov", "doc": "node_modules/.bin/typedoc --mode modules --out doc src", - "pub": "yarn build && yarn publish --access public", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/csp": "^0.3.79", - "@thi.ng/rstream": "^1.14.9" + "@thi.ng/csp": "^1.0.0", + "@thi.ng/rstream": "^2.0.0" }, "keywords": [ "bridge", @@ -41,5 +45,6 @@ ], "publishConfig": { "access": "public" - } + }, + "sideEffects": false } diff --git a/packages/rstream-csp/src/from/channel.ts b/packages/rstream-csp/src/from/channel.ts index 5638f9fc05..790850eaf3 100644 --- a/packages/rstream-csp/src/from/channel.ts +++ b/packages/rstream-csp/src/from/channel.ts @@ -1,31 +1,33 @@ -import { Channel } from "@thi.ng/csp/channel"; -import { DEBUG } from "@thi.ng/rstream/api"; -import { Stream } from "@thi.ng/rstream/stream"; +import { Channel } from "@thi.ng/csp"; +import { DEBUG, Stream } from "@thi.ng/rstream"; /** * * @param src * @param closeWhenCancelled */ -export function fromChannel(src: Channel, closeWhenCancelled = true) { - return new Stream((stream) => { - let isActive = true; - (async () => { - let x; - while ((x = null, x = await src.read()) !== undefined) { - if (x === undefined || !isActive) { - break; - } - stream.next(x); - } - stream.done(); - })(); - return () => { - if (closeWhenCancelled) { - src.close(true); - DEBUG && console.log("closed channel", src.id); - } - isActive = false; - }; - }, `obs-${src.id}`); -} +export const fromChannel = + (src: Channel, closeWhenCancelled = true) => + new Stream( + (stream) => { + let isActive = true; + (async () => { + let x; + while ((x = null, x = await src.read()) !== undefined) { + if (x === undefined || !isActive) { + break; + } + stream.next(x); + } + stream.done(); + })(); + return () => { + if (closeWhenCancelled) { + src.close(true); + DEBUG && console.log("closed channel", src.id); + } + isActive = false; + }; + }, + `channel-${src.id}` + ); diff --git a/packages/rstream-csp/test/tsconfig.json b/packages/rstream-csp/test/tsconfig.json index 13d45669e5..2c9c12a650 100644 --- a/packages/rstream-csp/test/tsconfig.json +++ b/packages/rstream-csp/test/tsconfig.json @@ -1,7 +1,8 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", diff --git a/packages/rstream-csp/tsconfig.json b/packages/rstream-csp/tsconfig.json index f6c291a0a0..ad49a0c5d4 100644 --- a/packages/rstream-csp/tsconfig.json +++ b/packages/rstream-csp/tsconfig.json @@ -1,7 +1,9 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "esnext" }, "include": [ "./src/**/*.ts" diff --git a/packages/rstream-dot/.npmignore b/packages/rstream-dot/.npmignore index d703bda97a..67d0c55714 100644 --- a/packages/rstream-dot/.npmignore +++ b/packages/rstream-dot/.npmignore @@ -1,10 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/rstream-dot/CHANGELOG.md b/packages/rstream-dot/CHANGELOG.md index 618bc509fe..7ad2b3167c 100644 --- a/packages/rstream-dot/CHANGELOG.md +++ b/packages/rstream-dot/CHANGELOG.md @@ -3,6 +3,28 @@ 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/rstream-dot@0.2.64...@thi.ng/rstream-dot@1.0.0) (2019-01-21) + + +### Build System + +* update package scripts, outputs, imports in remaining packages ([f912a84](https://github.com/thi-ng/umbrella/commit/f912a84)) + + +### BREAKING CHANGES + +* enable multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols + + + + + ## [0.2.64](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-dot@0.2.63...@thi.ng/rstream-dot@0.2.64) (2019-01-02) **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 98fec00007..3309c2ec81 100644 --- a/packages/rstream-dot/package.json +++ b/packages/rstream-dot/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/rstream-dot", - "version": "0.2.64", + "version": "1.0.0", "description": "Graphviz DOT conversion of @thi.ng/rstream dataflow graph topologies", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,23 +14,25 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn run clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module rstreamDot rstream", + "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 run build && yarn publish --access public", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/rstream": "^1.14.9" + "@thi.ng/rstream": "^2.0.0" }, "keywords": [ "conversion", @@ -44,5 +48,6 @@ ], "publishConfig": { "access": "public" - } + }, + "sideEffects": false } diff --git a/packages/rstream-dot/src/index.ts b/packages/rstream-dot/src/index.ts index bb0d49496e..9745ad37fe 100644 --- a/packages/rstream-dot/src/index.ts +++ b/packages/rstream-dot/src/index.ts @@ -1,8 +1,10 @@ +import { + ISubscribable, + Stream, + StreamMerge, + StreamSync +} from "@thi.ng/rstream"; import { DotOpts, Node, WalkState } from "./api"; -import { ISubscribable } from "@thi.ng/rstream/api"; -import { Stream } from "@thi.ng/rstream/stream"; -import { StreamMerge } from "@thi.ng/rstream/stream-merge"; -import { StreamSync } from "@thi.ng/rstream/stream-sync"; export * from "./api"; diff --git a/packages/rstream-dot/test/tsconfig.json b/packages/rstream-dot/test/tsconfig.json index bcf29ace54..2c9c12a650 100644 --- a/packages/rstream-dot/test/tsconfig.json +++ b/packages/rstream-dot/test/tsconfig.json @@ -1,10 +1,11 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", "../src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/rstream-dot/tsconfig.json b/packages/rstream-dot/tsconfig.json index bd6481a5a6..bcf03f18b4 100644 --- a/packages/rstream-dot/tsconfig.json +++ b/packages/rstream-dot/tsconfig.json @@ -1,9 +1,11 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/rstream-gestures/.npmignore b/packages/rstream-gestures/.npmignore index d703bda97a..67d0c55714 100644 --- a/packages/rstream-gestures/.npmignore +++ b/packages/rstream-gestures/.npmignore @@ -1,10 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/rstream-gestures/CHANGELOG.md b/packages/rstream-gestures/CHANGELOG.md index 5557393977..70ce0b736f 100644 --- a/packages/rstream-gestures/CHANGELOG.md +++ b/packages/rstream-gestures/CHANGELOG.md @@ -3,6 +3,33 @@ 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/rstream-gestures@0.6.9...@thi.ng/rstream-gestures@1.0.0) (2019-01-21) + + +### Bug Fixes + +* **rstream-gestures:** disable __GestureType reverse enum export ([19449e8](https://github.com/thi-ng/umbrella/commit/19449e8)) + + +### Build System + +* update package scripts, outputs, imports in remaining packages ([f912a84](https://github.com/thi-ng/umbrella/commit/f912a84)) + + +### BREAKING CHANGES + +* enable multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols + + + + + ## [0.6.9](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-gestures@0.6.8...@thi.ng/rstream-gestures@0.6.9) (2019-01-02) **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 f33218615d..2351cc9a48 100644 --- a/packages/rstream-gestures/package.json +++ b/packages/rstream-gestures/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/rstream-gestures", - "version": "0.6.9", + "version": "1.0.0", "description": "Unified mouse, mouse wheel & single-touch event stream abstraction", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,25 +14,27 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn run clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module rstreamGestures api rstream transducers", + "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 run build && yarn publish --access public", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/api": "^4.2.4", - "@thi.ng/rstream": "^1.14.9", - "@thi.ng/transducers": "^2.3.2" + "@thi.ng/api": "^5.0.0", + "@thi.ng/rstream": "^2.0.0", + "@thi.ng/transducers": "^3.0.0" }, "keywords": [ "dataflow", @@ -40,11 +44,12 @@ "mouse", "mousewheel", "stream", + "rstream", "touch", "typescript" ], "publishConfig": { "access": "public" }, - "gitHead": "673bf50ff571fc65bd984d1f83929bcc69a8b394" + "sideEffects": false } diff --git a/packages/rstream-gestures/src/index.ts b/packages/rstream-gestures/src/index.ts index ab75860468..b2872ed99e 100644 --- a/packages/rstream-gestures/src/index.ts +++ b/packages/rstream-gestures/src/index.ts @@ -1,7 +1,6 @@ -import { IID } from "@thi.ng/api/api"; -import { fromEvent } from "@thi.ng/rstream/from/event"; -import { merge, StreamMerge } from "@thi.ng/rstream/stream-merge"; -import { map } from "@thi.ng/transducers/xform/map"; +import { IID } from "@thi.ng/api"; +import { fromEvent, merge, StreamMerge } from "@thi.ng/rstream"; +import { map } from "@thi.ng/transducers"; export const enum GestureType { START, @@ -14,7 +13,7 @@ export const enum GestureType { /** * Reverse lookup for `GestureType` enums */ -export const __GestureType = (exports).GestureType; +// export const __GestureType = (exports).GestureType; export interface GestureInfo { pos: number[]; @@ -105,9 +104,14 @@ export interface GestureStreamOpts extends IID { * @param el * @param opts */ -export function gestureStream(el: HTMLElement, opts?: Partial): StreamMerge { +export const gestureStream = ( + el: HTMLElement, + opts?: Partial +): StreamMerge => { + let isDown = false, clickPos: number[]; + opts = Object.assign({ id: "gestures", zoom: 1, @@ -120,8 +124,10 @@ export function gestureStream(el: HTMLElement, opts?: Partial local: true, scale: false, }, opts); + let zoom = Math.min(Math.max(opts.zoom, opts.minZoom), opts.maxZoom); const dpr = window.devicePixelRatio || 1; + return merge({ id: opts.id, src: [ @@ -183,4 +189,4 @@ export function gestureStream(el: HTMLElement, opts?: Partial return [type, body]; }) }); -} +}; diff --git a/packages/rstream-gestures/test/tsconfig.json b/packages/rstream-gestures/test/tsconfig.json index bcf29ace54..2c9c12a650 100644 --- a/packages/rstream-gestures/test/tsconfig.json +++ b/packages/rstream-gestures/test/tsconfig.json @@ -1,10 +1,11 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", "../src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/rstream-gestures/tsconfig.json b/packages/rstream-gestures/tsconfig.json index bd6481a5a6..bcf03f18b4 100644 --- a/packages/rstream-gestures/tsconfig.json +++ b/packages/rstream-gestures/tsconfig.json @@ -1,9 +1,11 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/rstream-graph/.npmignore b/packages/rstream-graph/.npmignore index d703bda97a..67d0c55714 100644 --- a/packages/rstream-graph/.npmignore +++ b/packages/rstream-graph/.npmignore @@ -1,10 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/rstream-graph/CHANGELOG.md b/packages/rstream-graph/CHANGELOG.md index 2390a3c8b8..551b351348 100644 --- a/packages/rstream-graph/CHANGELOG.md +++ b/packages/rstream-graph/CHANGELOG.md @@ -3,6 +3,28 @@ 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/rstream-graph@2.1.50...@thi.ng/rstream-graph@3.0.0) (2019-01-21) + + +### Build System + +* update package scripts, outputs, imports in remaining packages ([f912a84](https://github.com/thi-ng/umbrella/commit/f912a84)) + + +### BREAKING CHANGES + +* enable multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols + + + + + ## [2.1.50](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-graph@2.1.49...@thi.ng/rstream-graph@2.1.50) (2019-01-02) **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 194bffeb64..925b56d1eb 100644 --- a/packages/rstream-graph/package.json +++ b/packages/rstream-graph/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/rstream-graph", - "version": "2.1.50", + "version": "3.0.0", "description": "Declarative dataflow graph construction for @thi.ng/rstream", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,29 +14,31 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn run clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc nodes", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module rstreamGraph api checks errors paths resolve-map rstream transducers", + "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 run build && yarn publish --access public", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/api": "^4.2.4", - "@thi.ng/checks": "^1.5.14", - "@thi.ng/errors": "^0.1.12", - "@thi.ng/paths": "^1.6.6", - "@thi.ng/resolve-map": "^3.0.16", - "@thi.ng/rstream": "^1.14.9", - "@thi.ng/transducers": "^2.3.2" + "@thi.ng/api": "^5.0.0", + "@thi.ng/checks": "^2.0.0", + "@thi.ng/errors": "^1.0.0", + "@thi.ng/paths": "^2.0.0", + "@thi.ng/resolve-map": "^4.0.0", + "@thi.ng/rstream": "^2.0.0", + "@thi.ng/transducers": "^3.0.0" }, "keywords": [ "compute", @@ -42,10 +46,12 @@ "ES6", "graph", "reactive", + "stream", "rstream", "typescript" ], "publishConfig": { "access": "public" - } + }, + "sideEffects": false } diff --git a/packages/rstream-graph/src/api.ts b/packages/rstream-graph/src/api.ts index bda295f8ba..cffd521299 100644 --- a/packages/rstream-graph/src/api.ts +++ b/packages/rstream-graph/src/api.ts @@ -1,14 +1,17 @@ -import { IObjectOf } from "@thi.ng/api/api"; +import { Fn, IObjectOf } from "@thi.ng/api"; import { Path } from "@thi.ng/paths"; -import { ISubscribable } from "@thi.ng/rstream/api"; -import { Transducer } from "@thi.ng/transducers/api"; +import { ResolveFn } from "@thi.ng/resolve-map"; +import { ISubscribable } from "@thi.ng/rstream"; +import { Transducer } from "@thi.ng/transducers"; /** * A function which constructs and returns an `ISubscribable` using * given object of inputs and node ID. See `node()` and `node1()`. */ -export type NodeFactory = (src: NodeInputs, id: string) => ISubscribable; +export type NodeFactory = + (src: NodeInputs, id: string) => ISubscribable; +export type NodeResolver = Fn; export type NodeInputs = IObjectOf>; export type NodeOutputs = IObjectOf>; export type Graph = IObjectOf; @@ -25,10 +28,12 @@ export interface Node { * and the operation to be applied to produce one or more result * streams. */ -export type GraphSpec = IObjectOf< - NodeSpec | - Node | - ((resolve: (path: string) => any) => Node)>; +export type GraphSpec = + IObjectOf< + NodeSpec | + Node | + NodeResolver + >; /** * Specification for a single "node" in the dataflow graph. Nodes here @@ -108,6 +113,8 @@ export interface NodeInputSpec { xform?: Transducer; } -export type NodeOutputSpec = Path | NodeOutputFn; +export type NodeOutputSpec = + Path | NodeOutputFn; -export type NodeOutputFn = (node: ISubscribable, id: PropertyKey) => ISubscribable; +export type NodeOutputFn = + (node: ISubscribable, id: PropertyKey) => ISubscribable; diff --git a/packages/rstream-graph/src/graph.ts b/packages/rstream-graph/src/graph.ts index aee4550821..83bca12679 100644 --- a/packages/rstream-graph/src/graph.ts +++ b/packages/rstream-graph/src/graph.ts @@ -1,18 +1,17 @@ -import { IObjectOf } from "@thi.ng/api/api"; -import { IAtom } from "@thi.ng/atom/api"; -import { isFunction } from "@thi.ng/checks/is-function"; -import { isPlainObject } from "@thi.ng/checks/is-plain-object"; -import { isString } from "@thi.ng/checks/is-string"; -import { illegalArgs } from "@thi.ng/errors/illegal-arguments"; +import { IObjectOf } from "@thi.ng/api"; +import { IAtom } from "@thi.ng/atom"; +import { isFunction, isPlainObject, isString } from "@thi.ng/checks"; +import { illegalArgs } from "@thi.ng/errors"; import { getIn } from "@thi.ng/paths"; -import { absPath, resolve } from "@thi.ng/resolve-map"; -import { ISubscribable } from "@thi.ng/rstream/api"; -import { fromIterableSync } from "@thi.ng/rstream/from/iterable"; -import { fromView } from "@thi.ng/rstream/from/view"; -import { StreamSync, sync } from "@thi.ng/rstream/stream-sync"; -import { Transducer } from "@thi.ng/transducers/api"; -import { map } from "@thi.ng/transducers/xform/map"; - +import { absPath, resolve, ResolveFn } from "@thi.ng/resolve-map"; +import { + fromIterableSync, + fromView, + ISubscribable, + StreamSync, + sync +} from "@thi.ng/rstream"; +import { map, Transducer } from "@thi.ng/transducers"; import { Graph, GraphSpec, @@ -37,21 +36,22 @@ import { * @param state * @param spec */ -export const initGraph = (state: IAtom, spec: GraphSpec): Graph => { - const res: Graph = {} - for (let id in spec) { - const n = spec[id]; - if (isNodeSpec(n)) { - res[id] = nodeFromSpec(state, spec[id], id); - } else { - res[id] = n; +export const initGraph = + (state: IAtom, spec: GraphSpec): Graph => { + const res: Graph = {} + for (let id in spec) { + const n = spec[id]; + res[id] = isNodeSpec(n) ? + nodeFromSpec(state, spec[id], id) : + n; } - } - return resolve(res); -}; + return resolve(res); + }; -const isNodeSpec = (x: any): x is NodeSpec => - isPlainObject(x) && isFunction((x).fn); +const isNodeSpec = + (x: any): x is NodeSpec => + isPlainObject(x) && + isFunction((x).fn); /** * Transforms a single `NodeSpec` into a lookup function for `resolve` @@ -96,15 +96,20 @@ const isNodeSpec = (x: any): x is NodeSpec => * @param spec * @param id */ -const nodeFromSpec = (state: IAtom, spec: NodeSpec, id: string) => - (resolve) => { - const ins = prepareNodeInputs(spec.ins, state, resolve); - const node = spec.fn(ins, id); - const outs = prepareNodeOutputs(spec.outs, node, state, id); - return { ins, node, outs }; - }; +const nodeFromSpec = + (state: IAtom, spec: NodeSpec, id: string) => + (resolve: ResolveFn): Node => { + const ins = prepareNodeInputs(spec.ins, state, resolve); + const node = spec.fn(ins, id); + const outs = prepareNodeOutputs(spec.outs, node, state, id); + return { ins, node, outs }; + }; -const prepareNodeInputs = (ins: IObjectOf, state: IAtom, resolve: (x: string) => any) => { +const prepareNodeInputs = ( + ins: IObjectOf, + state: IAtom, + resolve: ResolveFn +) => { const res: NodeInputs = {}; if (!ins) return res; for (let id in ins) { @@ -128,9 +133,14 @@ const prepareNodeInputs = (ins: IObjectOf, state: IAtom, res res[id] = s; } return res; -} +}; -const prepareNodeOutputs = (outs: IObjectOf, node: ISubscribable, state: IAtom, nodeID: string) => { +const prepareNodeOutputs = ( + outs: IObjectOf, + node: ISubscribable, + state: IAtom, + nodeID: string +) => { const res: NodeOutputs = {}; if (!outs) return res; for (let id in outs) { @@ -164,10 +174,14 @@ const prepareNodeOutputs = (outs: IObjectOf, node: ISubscribable * @param id * @param spec */ -export const addNode = (graph: Graph, state: IAtom, id: string, spec: NodeSpec): Node => { - if (graph[id]) { +export const addNode = ( + graph: Graph, + state: IAtom, + id: string, + spec: NodeSpec +): Node => { + graph[id] && illegalArgs(`graph already contains a node with ID: ${id}`); - } return graph[id] = nodeFromSpec(state, spec, id)( (path) => getIn(graph, absPath([id], path)) ); @@ -181,18 +195,19 @@ export const addNode = (graph: Graph, state: IAtom, id: string, spec: NodeS * @param graph * @param id */ -export const removeNode = (graph: Graph, id: string) => { - const node = graph[id]; - if (node) { - node.node.unsubscribe(); - for (let id in node.outs) { - node.outs[id].unsubscribe(); +export const removeNode = + (graph: Graph, id: string) => { + const node = graph[id]; + if (node) { + node.node.unsubscribe(); + for (let id in node.outs) { + node.outs[id].unsubscribe(); + } + delete graph[id]; + return true; } - delete graph[id]; - return true; - } - return false; -}; + return false; + }; /** * Calls `.unsubscribe()` on all nodes in the graph, causing all related @@ -200,11 +215,12 @@ export const removeNode = (graph: Graph, id: string) => { * * @param graph */ -export const stop = (graph: Graph) => { - for (let id in graph) { - graph[id].node.unsubscribe(); - } -}; +export const stop = + (graph: Graph) => { + for (let id in graph) { + graph[id].node.unsubscribe(); + } + }; /** * Higher order node / stream creator. Takes a transducer and (optional) @@ -216,11 +232,14 @@ export const stop = (graph: Graph) => { * @param xform * @param inputIDs */ -export const node = (xform: Transducer, any>, inputIDs?: string[]): NodeFactory => - (src: IObjectOf>, id: string): StreamSync => { - ensureInputs(src, inputIDs, id); - return sync({ src, xform, id }); - }; +export const node = ( + xform: Transducer, any>, + inputIDs?: string[] +): NodeFactory => + (src: IObjectOf>, id: string): StreamSync => ( + ensureInputs(src, inputIDs, id), + sync({ src, xform, id }) + ); /** * Similar to `node()`, but optimized for nodes using only a single @@ -229,13 +248,16 @@ export const node = (xform: Transducer, any>, inputIDs?: string[] * @param xform * @param inputID */ -export const node1 = (xform?: Transducer, inputID = "src"): NodeFactory => - (src: IObjectOf>, id: string): ISubscribable => { - ensureInputs(src, [inputID], id); - return xform ? +export const node1 = ( + xform?: Transducer, + inputID = "src" +): NodeFactory => + (src: IObjectOf>, id: string): ISubscribable => ( + ensureInputs(src, [inputID], id), + xform ? src[inputID].subscribe(xform, id) : - src[inputID].subscribe(null, id); - }; + src[inputID].subscribe(null, id) + ); /** * Helper function to verify given object of inputs has required input IDs. @@ -245,14 +267,17 @@ export const node1 = (xform?: Transducer, inputID = "src"): NodeFactor * @param inputIDs * @param nodeID */ -export const ensureInputs = (src: IObjectOf>, inputIDs: string[], nodeID: string) => { +export const ensureInputs = ( + src: IObjectOf>, + inputIDs: string[], + nodeID: string +) => { if (inputIDs !== undefined) { const missing: string[] = []; for (let i of inputIDs) { !src[i] && missing.push(i); } - if (missing.length) { + missing.length && illegalArgs(`node "${nodeID}": missing input(s): ${missing.join(", ")}`); - } } }; diff --git a/packages/rstream-graph/src/nodes/extract.ts b/packages/rstream-graph/src/nodes/extract.ts index 1df94cfa92..6a4bbcd773 100644 --- a/packages/rstream-graph/src/nodes/extract.ts +++ b/packages/rstream-graph/src/nodes/extract.ts @@ -1,6 +1,5 @@ import { getIn, Path } from "@thi.ng/paths"; -import { map } from "@thi.ng/transducers/xform/map"; - +import { map } from "@thi.ng/transducers"; import { NodeFactory } from "../api"; import { node1 } from "../graph"; @@ -12,5 +11,6 @@ import { node1 } from "../graph"; * @param path value lookup path * @param inputID default: `src` */ -export const extract = (path: Path, inputID?: string): NodeFactory => - node1(map((x) => getIn(x, path)), inputID); +export const extract = + (path: Path, inputID?: string): NodeFactory => + node1(map((x) => getIn(x, path)), inputID); diff --git a/packages/rstream-graph/src/nodes/math.ts b/packages/rstream-graph/src/nodes/math.ts index ff7a1255fa..7e0b76b02b 100644 --- a/packages/rstream-graph/src/nodes/math.ts +++ b/packages/rstream-graph/src/nodes/math.ts @@ -1,6 +1,5 @@ -import { IObjectOf } from "@thi.ng/api/api"; -import { map } from "@thi.ng/transducers/xform/map"; - +import { IObjectOf } from "@thi.ng/api"; +import { map } from "@thi.ng/transducers"; import { NodeFactory } from "../api"; import { node } from "../graph"; @@ -9,32 +8,36 @@ import { node } from "../graph"; * * Inputs: any */ -export const add: NodeFactory = node( - map((ports: IObjectOf) => { - let acc = 0; - let v; - for (let p in ports) { - if ((v = ports[p]) == null) return; - acc += v; - } - return acc; - })); +export const add: NodeFactory = + node( + map((ports: IObjectOf) => { + let acc = 0; + let v; + for (let p in ports) { + if ((v = ports[p]) == null) return; + acc += v; + } + return acc; + }) + ); /** * Multiplication node. * * Inputs: any */ -export const mul: NodeFactory = node( - map((ports: IObjectOf) => { - let acc = 1; - let v; - for (let p in ports) { - if ((v = ports[p]) == null) return; - acc *= v; - } - return acc; - })); +export const mul: NodeFactory = + node( + map((ports: IObjectOf) => { + let acc = 1; + let v; + for (let p in ports) { + if ((v = ports[p]) == null) return; + acc *= v; + } + return acc; + }) + ); /** * Subtraction node. @@ -42,7 +45,10 @@ export const mul: NodeFactory = node( * Inputs: `a`, `b` */ export const sub: NodeFactory = - node(map((ports: IObjectOf) => ports.a - ports.b), ["a", "b"]); + node( + map((ports: IObjectOf) => ports.a - ports.b), + ["a", "b"] + ); /** * Division node. @@ -50,4 +56,7 @@ export const sub: NodeFactory = * Inputs: `a`, `b` */ export const div: NodeFactory = - node(map((ports: IObjectOf) => ports.a / ports.b), ["a", "b"]); + node( + map((ports: IObjectOf) => ports.a / ports.b), + ["a", "b"] + ); diff --git a/packages/rstream-graph/test/index.ts b/packages/rstream-graph/test/index.ts index ab6d50717f..1fa9786f8b 100644 --- a/packages/rstream-graph/test/index.ts +++ b/packages/rstream-graph/test/index.ts @@ -1,8 +1,7 @@ import { Atom } from "@thi.ng/atom"; import * as rs from "@thi.ng/rstream"; -import { map } from "@thi.ng/transducers/xform/map"; +import { map } from "@thi.ng/transducers"; import * as assert from "assert"; - import * as rsg from "../src"; describe("rstream-graph", () => { diff --git a/packages/rstream-graph/test/tsconfig.json b/packages/rstream-graph/test/tsconfig.json index bcf29ace54..2c9c12a650 100644 --- a/packages/rstream-graph/test/tsconfig.json +++ b/packages/rstream-graph/test/tsconfig.json @@ -1,10 +1,11 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", "../src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/rstream-graph/tsconfig.json b/packages/rstream-graph/tsconfig.json index bd6481a5a6..bcf03f18b4 100644 --- a/packages/rstream-graph/tsconfig.json +++ b/packages/rstream-graph/tsconfig.json @@ -1,9 +1,11 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/rstream-log/.npmignore b/packages/rstream-log/.npmignore index d703bda97a..67d0c55714 100644 --- a/packages/rstream-log/.npmignore +++ b/packages/rstream-log/.npmignore @@ -1,10 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/rstream-log/CHANGELOG.md b/packages/rstream-log/CHANGELOG.md index 4eb3af9058..17115dae94 100644 --- a/packages/rstream-log/CHANGELOG.md +++ b/packages/rstream-log/CHANGELOG.md @@ -3,6 +3,33 @@ 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/rstream-log@1.0.76...@thi.ng/rstream-log@2.0.0) (2019-01-21) + + +### Bug Fixes + +* **rstream-log:** remove __Level reverse enum lookup, update Level (non const) ([d89f28f](https://github.com/thi-ng/umbrella/commit/d89f28f)) + + +### Build System + +* update package scripts, outputs, imports in remaining packages ([f912a84](https://github.com/thi-ng/umbrella/commit/f912a84)) + + +### BREAKING CHANGES + +* enable multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols + + + + + ## [1.0.76](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-log@1.0.75...@thi.ng/rstream-log@1.0.76) (2019-01-02) **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 08b7de3944..876eb6901b 100644 --- a/packages/rstream-log/package.json +++ b/packages/rstream-log/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/rstream-log", - "version": "1.0.76", + "version": "2.0.0", "description": "Structured, multilevel & hierarchical loggers based on @thi.ng/rstream", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,27 +14,29 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc output xform", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module rstreamLog api checks errors rstream transducers", + "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", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/api": "^4.2.4", - "@thi.ng/checks": "^1.5.14", - "@thi.ng/errors": "^0.1.12", - "@thi.ng/rstream": "^1.14.9", - "@thi.ng/transducers": "^2.3.2" + "@thi.ng/api": "^5.0.0", + "@thi.ng/checks": "^2.0.0", + "@thi.ng/errors": "^1.0.0", + "@thi.ng/rstream": "^2.0.0", + "@thi.ng/transducers": "^3.0.0" }, "keywords": [ "ES6", @@ -47,5 +51,6 @@ ], "publishConfig": { "access": "public" - } + }, + "sideEffects": false } diff --git a/packages/rstream-log/src/api.ts b/packages/rstream-log/src/api.ts index 38942c1ca8..f9dcdbe55e 100644 --- a/packages/rstream-log/src/api.ts +++ b/packages/rstream-log/src/api.ts @@ -1,7 +1,7 @@ -import { IID } from "@thi.ng/api/api"; -import { ISubscribable } from "@thi.ng/rstream/api"; +import { IID } from "@thi.ng/api"; +import { ISubscribable } from "@thi.ng/rstream"; -export const enum Level { +export enum Level { FINE, DEBUG, INFO, @@ -13,7 +13,7 @@ export const enum Level { /** * Reverse lookup for `Level` enums */ -export const __Level = (exports).Level; +// export const __Level = (exports).Level; export interface LogEntry extends Array { [0]: Level; diff --git a/packages/rstream-log/src/logger.ts b/packages/rstream-log/src/logger.ts index 3c7b723aef..c662eb0c97 100644 --- a/packages/rstream-log/src/logger.ts +++ b/packages/rstream-log/src/logger.ts @@ -1,8 +1,5 @@ -import { illegalArity } from "@thi.ng/errors/illegal-arity"; -import { ISubscribable } from "@thi.ng/rstream/api"; -import { StreamMerge } from "@thi.ng/rstream/stream-merge"; -import { Subscription } from "@thi.ng/rstream/subscription"; - +import { illegalArity } from "@thi.ng/errors"; +import { ISubscribable, nextID, StreamMerge } from "@thi.ng/rstream"; import { ILogger, Level, LogEntry } from "./api"; export class Logger extends StreamMerge implements @@ -34,7 +31,7 @@ export class Logger extends StreamMerge implements default: illegalArity(args.length); } - id = id || `logger-${Subscription.NEXT_ID++}`; + id = id || `logger-${nextID()}`; super({ src, id, close: false }); this.level = level; } diff --git a/packages/rstream-log/src/output/console.ts b/packages/rstream-log/src/output/console.ts index 3c1da18296..8d93f3a145 100644 --- a/packages/rstream-log/src/output/console.ts +++ b/packages/rstream-log/src/output/console.ts @@ -1 +1 @@ -export { trace as writeConsole } from "@thi.ng/rstream/subs/trace"; +export { trace as writeConsole } from "@thi.ng/rstream"; diff --git a/packages/rstream-log/src/output/file.ts b/packages/rstream-log/src/output/file.ts index 51dbc51ede..3e0d153e2f 100644 --- a/packages/rstream-log/src/output/file.ts +++ b/packages/rstream-log/src/output/file.ts @@ -1,19 +1,20 @@ -import { isNode } from "@thi.ng/checks/is-node"; -import { unsupported } from "@thi.ng/errors/unsupported"; -import { ISubscriber } from "@thi.ng/rstream/api"; +import { isNode } from "@thi.ng/checks"; +import { unsupported } from "@thi.ng/errors"; +import { ISubscriber } from "@thi.ng/rstream"; -export function writeFile(path: string): ISubscriber { - if (isNode()) { - const fs = require("fs"); - return { - next(msg) { - fs.appendFile(path, msg + "\n", (e) => { - if (e) { - process.stderr.write(e.message); - } - }); - } - }; - } - unsupported("only available in NodeJS"); -} +export const writeFile = + (path: string): ISubscriber => { + if (isNode()) { + const fs = require("fs"); + return { + next(msg) { + fs.appendFile(path, msg + "\n", (e) => { + if (e) { + process.stderr.write(e.message); + } + }); + } + }; + } + unsupported("only available in NodeJS"); + }; diff --git a/packages/rstream-log/src/xform/filter.ts b/packages/rstream-log/src/xform/filter.ts index a4efe2bde3..fa3496e097 100644 --- a/packages/rstream-log/src/xform/filter.ts +++ b/packages/rstream-log/src/xform/filter.ts @@ -1,25 +1,24 @@ -import { isString } from "@thi.ng/checks/is-string"; -import { Transducer } from "@thi.ng/transducers/api"; -import { filter } from "@thi.ng/transducers/xform/filter"; - +import { isString } from "@thi.ng/checks"; +import { Transducer } from "@thi.ng/transducers"; +import { filter } from "@thi.ng/transducers"; import { Level, LogEntry } from "../api"; -export function onlyLevel(level: Level): Transducer { - return filter((l) => l[0] === level); -} +export const onlyLevel = + (level: Level): Transducer => + filter((l) => l[0] === level); -export function minLevel(level: Level): Transducer { - return filter((l) => l[0] >= level); -} +export const minLevel = + (level: Level): Transducer => + filter((l) => l[0] >= level); -export function maxLevel(level: Level): Transducer { - return filter((l) => l[0] <= level); -} +export const maxLevel = + (level: Level): Transducer => + filter((l) => l[0] <= level); -export function matchID(id: string | RegExp): Transducer { - return filter( - isString(id) ? - (l) => l[1] === id : - (l) => id.test(l[1]) - ); -} +export const matchID = + (id: string | RegExp): Transducer => + filter( + isString(id) ? + (l) => l[1] === id : + (l) => id.test(l[1]) + ); diff --git a/packages/rstream-log/src/xform/format.ts b/packages/rstream-log/src/xform/format.ts index e9de60c238..397b4e4980 100644 --- a/packages/rstream-log/src/xform/format.ts +++ b/packages/rstream-log/src/xform/format.ts @@ -1,38 +1,40 @@ -import { Transducer } from "@thi.ng/transducers/api"; -import { map } from "@thi.ng/transducers/xform/map"; - +import { map, Transducer } from "@thi.ng/transducers"; import { - __Level, + Level, BodyFormat, DateFormat, LogEntry, LogEntryObj } from "../api"; -export function formatString(dtFmt?: DateFormat, bodyFmt?: BodyFormat): Transducer { +export const formatString = ( + dtFmt?: DateFormat, + bodyFmt?: BodyFormat +): Transducer => { dtFmt = dtFmt || ((dt) => new Date(dt).toISOString()); bodyFmt = bodyFmt || ((x) => x.toString()); return map( ([level, id, time, ...body]) => - `[${__Level[level]}] [${id}] ${dtFmt(time)} ${bodyFmt(body)}` + `[${Level[level]}] [${id}] ${dtFmt(time)} ${bodyFmt(body)}` ); -} +}; -export function formatObject(): Transducer { - return map( - ([level, id, time, ...body]) => ({ level, id, time, body }) - ); -} +export const formatObject = + (): Transducer => + map( + ([level, id, time, ...body]) => ({ level, id, time, body }) + ); -export function formatJSON(dtfmt?: (dt: number) => string): Transducer { - dtfmt = dtfmt || ((dt) => new Date(dt).toISOString()); - return map( - ([level, id, time, ...body]) => - JSON.stringify({ - level: __Level[level], - id, - time: dtfmt(time), - body - }) - ); -} +export const formatJSON = + (dtfmt?: DateFormat): Transducer => { + dtfmt = dtfmt || ((dt) => new Date(dt).toISOString()); + return map( + ([level, id, time, ...body]) => + JSON.stringify({ + level: Level[level], + id, + time: dtfmt(time), + body + }) + ); + }; diff --git a/packages/rstream-log/test/tsconfig.json b/packages/rstream-log/test/tsconfig.json index 13d45669e5..2c9c12a650 100644 --- a/packages/rstream-log/test/tsconfig.json +++ b/packages/rstream-log/test/tsconfig.json @@ -1,7 +1,8 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", diff --git a/packages/rstream-log/tsconfig.json b/packages/rstream-log/tsconfig.json index f6c291a0a0..bcf03f18b4 100644 --- a/packages/rstream-log/tsconfig.json +++ b/packages/rstream-log/tsconfig.json @@ -1,7 +1,9 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" diff --git a/packages/rstream-query/.npmignore b/packages/rstream-query/.npmignore index d703bda97a..67d0c55714 100644 --- a/packages/rstream-query/.npmignore +++ b/packages/rstream-query/.npmignore @@ -1,10 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/rstream-query/CHANGELOG.md b/packages/rstream-query/CHANGELOG.md index e2fd70cf23..2a865e7ffa 100644 --- a/packages/rstream-query/CHANGELOG.md +++ b/packages/rstream-query/CHANGELOG.md @@ -3,6 +3,28 @@ 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/rstream-query@0.3.63...@thi.ng/rstream-query@1.0.0) (2019-01-21) + + +### Build System + +* update package scripts, outputs, imports in remaining packages ([f912a84](https://github.com/thi-ng/umbrella/commit/f912a84)) + + +### BREAKING CHANGES + +* enable multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols + + + + + ## [0.3.63](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream-query@0.3.62...@thi.ng/rstream-query@0.3.63) (2019-01-02) **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 82f7f3153f..6a3dde0402 100644 --- a/packages/rstream-query/package.json +++ b/packages/rstream-query/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/rstream-query", - "version": "0.3.63", + "version": "1.0.0", "description": "@thi.ng/rstream based triple store & reactive query engine", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,30 +14,32 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn run clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module rstreamQuery api associative checks equiv errors rstream rstream-dot transducers", + "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 run build && yarn publish --access public", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/api": "^4.2.4", - "@thi.ng/associative": "^0.6.23", - "@thi.ng/checks": "^1.5.14", - "@thi.ng/equiv": "^0.1.15", - "@thi.ng/errors": "^0.1.12", - "@thi.ng/rstream": "^1.14.9", - "@thi.ng/rstream-dot": "^0.2.64", - "@thi.ng/transducers": "^2.3.2" + "@thi.ng/api": "^5.0.0", + "@thi.ng/associative": "^1.0.0", + "@thi.ng/checks": "^2.0.0", + "@thi.ng/equiv": "^1.0.0", + "@thi.ng/errors": "^1.0.0", + "@thi.ng/rstream": "^2.0.0", + "@thi.ng/rstream-dot": "^1.0.0", + "@thi.ng/transducers": "^3.0.0" }, "keywords": [ "dataflow", @@ -53,5 +57,6 @@ ], "publishConfig": { "access": "public" - } + }, + "sideEffects": false } diff --git a/packages/rstream-query/src/api.ts b/packages/rstream-query/src/api.ts index 25c264b154..905ffb9ab9 100644 --- a/packages/rstream-query/src/api.ts +++ b/packages/rstream-query/src/api.ts @@ -1,5 +1,5 @@ -import { IObjectOf } from "@thi.ng/api/api"; -import { ISubscribable } from "@thi.ng/rstream/api"; +import { IObjectOf } from "@thi.ng/api"; +import { ISubscribable } from "@thi.ng/rstream"; export let DEBUG = false; @@ -47,4 +47,4 @@ export interface PathQuerySpec { export interface JoinOpts { limit: number; select: string[]; -} \ No newline at end of file +} diff --git a/packages/rstream-query/src/convert.ts b/packages/rstream-query/src/convert.ts index 0f1e2be710..4a4105a3ef 100644 --- a/packages/rstream-query/src/convert.ts +++ b/packages/rstream-query/src/convert.ts @@ -1,31 +1,30 @@ -import { isArray } from "@thi.ng/checks/is-array"; -import { isPlainObject } from "@thi.ng/checks/is-plain-object"; -import { concat } from "@thi.ng/transducers/iter/concat"; -import { pairs } from "@thi.ng/transducers/iter/pairs"; -import { mapcat } from "@thi.ng/transducers/xform/mapcat"; +import { isArray, isPlainObject } from "@thi.ng/checks"; +import { concat, pairs, mapcat } from "@thi.ng/transducers"; let NEXT_ID = 0; -const mapBNode = (s: any, p: any, o: any) => { - const id = `__b${NEXT_ID++}__`; - return concat([[s, p, id]], asTriples(o, id)); -}; - -const mapSubject = (subject: any) => - ([p, o]) => { - if (isArray(o)) { - return mapcat( - (o) => - isPlainObject(o) ? - mapBNode(subject, p, o) : - [[subject, p, o]], - o); - } else if (isPlainObject(o)) { - return mapBNode(subject, p, o); - } - return [[subject, p, o]]; +const mapBNode = + (s: any, p: any, o: any) => { + const id = `__b${NEXT_ID++}__`; + return concat([[s, p, id]], asTriples(o, id)); }; +const mapSubject = + (subject: any) => + ([p, o]) => { + if (isArray(o)) { + return mapcat( + (o) => + isPlainObject(o) ? + mapBNode(subject, p, o) : + [[subject, p, o]], + o); + } else if (isPlainObject(o)) { + return mapBNode(subject, p, o); + } + return [[subject, p, o]]; + }; + /** * Converts given object into an iterable of triples, with the following * conversion rules: @@ -75,10 +74,11 @@ const mapSubject = (subject: any) => * @param obj * @param subject internal use only, do not specify! */ -export const asTriples = (obj: any, subject?: any) => - mapcat( - subject === undefined ? - ([s, v]: any) => mapcat(mapSubject(s), pairs(v)) : - mapSubject(subject), - pairs(obj) - ); +export const asTriples = + (obj: any, subject?: any) => + mapcat( + subject === undefined ? + ([s, v]: any) => mapcat(mapSubject(s), pairs(v)) : + mapSubject(subject), + pairs(obj) + ); diff --git a/packages/rstream-query/src/pattern.ts b/packages/rstream-query/src/pattern.ts index e314c470e5..66282f7f51 100644 --- a/packages/rstream-query/src/pattern.ts +++ b/packages/rstream-query/src/pattern.ts @@ -1,23 +1,24 @@ -import { repeatedly } from "@thi.ng/transducers/iter/repeatedly"; - +import { repeatedly } from "@thi.ng/transducers"; import { PathPattern, Pattern } from "./api"; import { autoQVar, isQVar, qvarName } from "./qvar"; -export const patternVarCount = (p: Pattern) => { - let n = 0; - if (isQVar(p[0])) n++; - if (isQVar(p[1])) n++; - if (isQVar(p[2])) n++; - return n; -}; +export const patternVarCount = + (p: Pattern) => { + let n = 0; + if (isQVar(p[0])) n++; + if (isQVar(p[1])) n++; + if (isQVar(p[2])) n++; + return n; + }; -export const patternVars = ([s, p, o]: Pattern) => { - const vars = []; - isQVar(s) && vars.push(qvarName(s)); - isQVar(p) && vars.push(qvarName(p)); - isQVar(o) && vars.push(qvarName(o)); - return vars; -}; +export const patternVars = + ([s, p, o]: Pattern) => { + const vars = []; + isQVar(s) && vars.push(qvarName(s)); + isQVar(p) && vars.push(qvarName(p)); + isQVar(o) && vars.push(qvarName(o)); + return vars; + }; /** * Takes a path triple pattern and max depth. The pattern's predicate @@ -39,15 +40,17 @@ export const patternVars = ([s, p, o]: Pattern) => { * @param pattern * @param maxLen */ -export const resolvePathPattern = ([s, p, o]: PathPattern, maxLen = p.length): [Pattern[], string[]] => { - const res = []; - const avars = [...repeatedly(autoQVar, maxLen - 1)]; - for (let i = 0; i < maxLen; i++) { - res.push([s, p[i % p.length], s = avars[i]]); - } - res[res.length - 1][2] = o; - return [res, avars]; -}; +export const resolvePathPattern = + ([s, p, o]: PathPattern, maxLen = p.length): [Pattern[], string[]] => { + const res = []; + const avars = [...repeatedly(autoQVar, maxLen - 1)]; + for (let i = 0; i < maxLen; i++) { + res.push([s, p[i % p.length], s = avars[i]]); + } + res[res.length - 1][2] = o; + return [res, avars]; + }; -export const sortPatterns = (patterns: Pattern[]) => - patterns.sort((a, b) => patternVarCount(a) - patternVarCount(b)); +export const sortPatterns = + (patterns: Pattern[]) => + patterns.sort((a, b) => patternVarCount(a) - patternVarCount(b)); diff --git a/packages/rstream-query/src/qvar.ts b/packages/rstream-query/src/qvar.ts index 611ff2749b..a5a7b597cd 100644 --- a/packages/rstream-query/src/qvar.ts +++ b/packages/rstream-query/src/qvar.ts @@ -1,21 +1,20 @@ -import { isString } from "@thi.ng/checks/is-string"; - +import { isString } from "@thi.ng/checks"; import { Triple } from "./api"; const AUTO_QVAR_PREFIX = "?__q"; let AUTO_QVAR_ID = 0; -export const isQVar = (x: any) => - isString(x) && x.charAt(0) === "?"; +export const isQVar = + (x: any) => isString(x) && x.charAt(0) === "?"; -export const isAutoQVar = (x: any) => - isString(x) && x.indexOf(AUTO_QVAR_PREFIX) == 0; +export const isAutoQVar = + (x: any) => isString(x) && x.indexOf(AUTO_QVAR_PREFIX) == 0; -export const autoQVar = () => - AUTO_QVAR_PREFIX + (AUTO_QVAR_ID++).toString(36); +export const autoQVar = + () => AUTO_QVAR_PREFIX + (AUTO_QVAR_ID++).toString(36); -export const qvarName = (x: string) => - x.substr(1); +export const qvarName = + (x: string) => x.substr(1); /** * Returns an optimized query variable solution extractor function based @@ -31,28 +30,29 @@ export const qvarName = (x: string) => * @param p * @param o */ -export const qvarResolver = (vs: boolean, vp: boolean, vo: boolean, s, p, o) => { - const type = ((vs) << 2) | ((vp) << 1) | (vo); - let ss: any = vs && qvarName(s); - let pp: any = vp && qvarName(p); - let oo: any = vo && qvarName(o); - switch (type) { - case 0: - default: - return; - case 1: - return (f: Triple) => ({ [oo]: f[2] }); - case 2: - return (f: Triple) => ({ [pp]: f[1] }); - case 3: - return (f: Triple) => ({ [pp]: f[1], [oo]: f[2] }); - case 4: - return (f: Triple) => ({ [ss]: f[0] }); - case 5: - return (f: Triple) => ({ [ss]: f[0], [oo]: f[2] }); - case 6: - return (f: Triple) => ({ [ss]: f[0], [pp]: f[1] }); - case 7: - return (f: Triple) => ({ [ss]: f[0], [pp]: f[1], [oo]: f[2] }); - } -}; +export const qvarResolver = + (vs: boolean, vp: boolean, vo: boolean, s, p, o) => { + const type = ((vs) << 2) | ((vp) << 1) | (vo); + let ss: any = vs && qvarName(s); + let pp: any = vp && qvarName(p); + let oo: any = vo && qvarName(o); + switch (type) { + case 0: + default: + return; + case 1: + return (f: Triple) => ({ [oo]: f[2] }); + case 2: + return (f: Triple) => ({ [pp]: f[1] }); + case 3: + return (f: Triple) => ({ [pp]: f[1], [oo]: f[2] }); + case 4: + return (f: Triple) => ({ [ss]: f[0] }); + case 5: + return (f: Triple) => ({ [ss]: f[0], [oo]: f[2] }); + case 6: + return (f: Triple) => ({ [ss]: f[0], [pp]: f[1] }); + case 7: + return (f: Triple) => ({ [ss]: f[0], [pp]: f[1], [oo]: f[2] }); + } + }; diff --git a/packages/rstream-query/src/store.ts b/packages/rstream-query/src/store.ts index b4b7b9f070..af25261415 100644 --- a/packages/rstream-query/src/store.ts +++ b/packages/rstream-query/src/store.ts @@ -1,28 +1,32 @@ -import { IObjectOf } from "@thi.ng/api/api"; -import { intersection } from "@thi.ng/associative/intersection"; -import { join } from "@thi.ng/associative/join"; +import { IObjectOf } from "@thi.ng/api"; +import { intersection, join } from "@thi.ng/associative"; import { equiv } from "@thi.ng/equiv"; -import { illegalArgs } from "@thi.ng/errors/illegal-arguments"; +import { illegalArgs } from "@thi.ng/errors"; +import { + ISubscribable, + nextID, + Stream, + Subscription, + sync +} from "@thi.ng/rstream"; import { DotOpts, IToDot, toDot, walk } from "@thi.ng/rstream-dot"; -import { ISubscribable } from "@thi.ng/rstream/api"; -import { Stream } from "@thi.ng/rstream/stream"; -import { sync } from "@thi.ng/rstream/stream-sync"; -import { Subscription } from "@thi.ng/rstream/subscription"; -import { Reducer, Transducer } from "@thi.ng/transducers/api"; -import { comp } from "@thi.ng/transducers/func/comp"; -import { compR } from "@thi.ng/transducers/func/compr"; -import { keySelector } from "@thi.ng/transducers/func/key-selector"; -import { assocObj } from "@thi.ng/transducers/rfn/assoc-obj"; -import { transduce } from "@thi.ng/transducers/transduce"; -import { dedupe } from "@thi.ng/transducers/xform/dedupe"; -import { map } from "@thi.ng/transducers/xform/map"; -import { mapIndexed } from "@thi.ng/transducers/xform/map-indexed"; - +import { + assocObj, + comp, + compR, + dedupe, + keySelector, + map, + mapIndexed, + Reducer, + transduce, + Transducer +} from "@thi.ng/transducers"; import { BindFn, DEBUG, @@ -251,7 +255,7 @@ export class TripleStore implements if (!resolve) { illegalArgs("at least 1 query variable is required in pattern"); } - id || (id = `query-${Subscription.NEXT_ID++}`); + id || (id = `query-${nextID()}`); const query = >this.addPatternQuery( [vs ? null : s, vp ? null : p, vo ? null : o], id + "-raw" @@ -416,74 +420,83 @@ const intersect2: Transducer, TripleIds> = const intersect3: Transducer, TripleIds> = comp(map(({ s, p, o }) => intersection(intersection(s, p), o)), dedupe(equiv)); -const indexSel = (key: any): Transducer => - (rfn: Reducer) => { - const r = rfn[2]; - return compR(rfn, - (acc, e) => { - DEBUG && console.log("index sel", e.key, key); - if (equiv(e.key, key)) { - return r(acc, e.index); +const indexSel = + (key: any): Transducer => + (rfn: Reducer) => { + const r = rfn[2]; + return compR(rfn, + (acc, e) => { + DEBUG && console.log("index sel", e.key, key); + if (equiv(e.key, key)) { + return r(acc, e.index); + } + return acc; } - return acc; + ); + }; + +const resultTriples = + (graph: TripleStore) => + map>( + (ids) => { + const res = new Set(); + for (let id of ids) res.add(graph.triples[id]); + return res; + }); + +const joinSolutions = + (n: number) => + map, Solutions>((src) => { + let res: Solutions = src[0]; + for (let i = 1; i < n && res.size; i++) { + res = join(res, src[i]); } - ); - }; + return res; + }); -const resultTriples = (graph: TripleStore) => - map>( - (ids) => { - const res = new Set(); - for (let id of ids) res.add(graph.triples[id]); +const filterSolutions = + (qvars: Iterable) => { + const filterVars = keySelector([...qvars]); + return map((sol: Solutions) => { + const res: Solutions = new Set(); + for (let s of sol) { + res.add(filterVars(s)); + } return res; }); + }; -const joinSolutions = (n: number) => - map, Solutions>((src) => { - let res: Solutions = src[0]; - for (let i = 1; i < n && res.size; i++) { - res = join(res, src[i]); - } - return res; - }); - -const filterSolutions = (qvars: Iterable) => { - const filterVars = keySelector([...qvars]); - return map((sol: Solutions) => { - const res: Solutions = new Set(); - for (let s of sol) { - res.add(filterVars(s)); - } - return res; - }); -}; +const limitSolutions = + (n: number) => + map((sol: Solutions) => { + if (sol.size <= n) { + return sol; + } + const res: Solutions = new Set(); + let m = n; + for (let s of sol) { + res.add(s); + if (--m <= 0) break; + } + return res; + }); -const limitSolutions = (n: number) => - map((sol: Solutions) => { - if (sol.size <= n) { - return sol; - } - const res: Solutions = new Set(); - let m = n; - for (let s of sol) { - res.add(s); - if (--m <= 0) break; - } - return res; - }); - -const bindVars = (bindings: IObjectOf) => - map((sol: Solutions) => { - const res: Solutions = new Set(); - for (let s of sol) { - s = { ...s }; - res.add(s); - for (let b in bindings) { - s[b] = bindings[b](s); +const bindVars = + (bindings: IObjectOf) => + map((sol: Solutions) => { + const res: Solutions = new Set(); + for (let s of sol) { + s = { ...s }; + res.add(s); + for (let b in bindings) { + s[b] = bindings[b](s); + } } - } - return res; - }); + return res; + }); + +const isWhereQuery = + (q: SubQuerySpec): q is WhereQuerySpec => !!(q).where; -const isWhereQuery = (q: SubQuerySpec): q is WhereQuerySpec => !!(q).where; -const isPathQuery = (q: SubQuerySpec): q is PathQuerySpec => !!(q).path; +const isPathQuery = + (q: SubQuerySpec): q is PathQuerySpec => !!(q).path; diff --git a/packages/rstream-query/test/tsconfig.json b/packages/rstream-query/test/tsconfig.json index bcf29ace54..2c9c12a650 100644 --- a/packages/rstream-query/test/tsconfig.json +++ b/packages/rstream-query/test/tsconfig.json @@ -1,10 +1,11 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", "../src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/rstream-query/tsconfig.json b/packages/rstream-query/tsconfig.json index bd6481a5a6..bcf03f18b4 100644 --- a/packages/rstream-query/tsconfig.json +++ b/packages/rstream-query/tsconfig.json @@ -1,9 +1,11 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/rstream/.npmignore b/packages/rstream/.npmignore index d703bda97a..67d0c55714 100644 --- a/packages/rstream/.npmignore +++ b/packages/rstream/.npmignore @@ -1,10 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/rstream/CHANGELOG.md b/packages/rstream/CHANGELOG.md index c0e403426e..3b4934736d 100644 --- a/packages/rstream/CHANGELOG.md +++ b/packages/rstream/CHANGELOG.md @@ -3,6 +3,34 @@ 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/rstream@1.14.9...@thi.ng/rstream@2.0.0) (2019-01-21) + + +### Bug Fixes + +* **rstream:** avoid Subscription ctor to workaround parceljs build issue ([d1e275b](https://github.com/thi-ng/umbrella/commit/d1e275b)) +* **rstream:** disable __State reverse enum lookups ([b238a3a](https://github.com/thi-ng/umbrella/commit/b238a3a)) + + +### Build System + +* update package scripts, outputs, imports in remaining packages ([f912a84](https://github.com/thi-ng/umbrella/commit/f912a84)) + + +### BREAKING CHANGES + +* enable multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols + + + + + ## [1.14.9](https://github.com/thi-ng/umbrella/compare/@thi.ng/rstream@1.14.8...@thi.ng/rstream@1.14.9) (2019-01-02) **Note:** Version bump only for package @thi.ng/rstream diff --git a/packages/rstream/package.json b/packages/rstream/package.json index c0e39addc3..f10f1088fc 100644 --- a/packages/rstream/package.json +++ b/packages/rstream/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/rstream", - "version": "1.14.9", + "version": "2.0.0", "description": "Reactive multi-tap streams, dataflow & transformation pipeline constructs", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,29 +14,31 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc from subs utils", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module rstream api associative atom checks errors paths transducers", + "test": "rimraf build && tsc -p test/tsconfig.json && nyc mocha build/test/*.js", + "clean": "rimraf *.js *.d.ts .nyc_output build coverage doc lib from subs utils", "cover": "yarn test && nyc report --reporter=lcov", "doc": "node_modules/.bin/typedoc --mode modules --out doc src", - "pub": "yarn build && yarn publish --access public", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/api": "^4.2.4", - "@thi.ng/associative": "^0.6.23", - "@thi.ng/atom": "^1.5.8", - "@thi.ng/checks": "^1.5.14", - "@thi.ng/errors": "^0.1.12", - "@thi.ng/paths": "^1.6.6", - "@thi.ng/transducers": "^2.3.2" + "@thi.ng/api": "^5.0.0", + "@thi.ng/associative": "^1.0.0", + "@thi.ng/atom": "^2.0.0", + "@thi.ng/checks": "^2.0.0", + "@thi.ng/errors": "^1.0.0", + "@thi.ng/paths": "^2.0.0", + "@thi.ng/transducers": "^3.0.0" }, "keywords": [ "datastructure", @@ -50,5 +54,6 @@ ], "publishConfig": { "access": "public" - } + }, + "sideEffects": false } diff --git a/packages/rstream/src/api.ts b/packages/rstream/src/api.ts index 4de3d382a9..622a4f5479 100644 --- a/packages/rstream/src/api.ts +++ b/packages/rstream/src/api.ts @@ -1,6 +1,5 @@ -import { IDeref, IID } from "@thi.ng/api/api"; -import { Transducer } from "@thi.ng/transducers/api"; - +import { IDeref, IID } from "@thi.ng/api"; +import { Transducer } from "@thi.ng/transducers"; import { Stream } from "./stream"; import { Subscription } from "./subscription"; @@ -15,7 +14,7 @@ export const enum State { /** * Reverse lookup for `State` enums */ -export const __State = (exports).State; +// export const __State = (exports).State; export type Fn = (x: T) => void; diff --git a/packages/rstream/src/from/atom.ts b/packages/rstream/src/from/atom.ts index 901291e51f..a3bcded55b 100644 --- a/packages/rstream/src/from/atom.ts +++ b/packages/rstream/src/from/atom.ts @@ -1,7 +1,7 @@ -import { Predicate2 } from "@thi.ng/api/api"; -import { ReadonlyAtom } from "@thi.ng/atom/api"; - +import { Predicate2 } from "@thi.ng/api"; +import { ReadonlyAtom } from "@thi.ng/atom"; import { Stream } from "../stream"; +import { nextID } from "../utils/idgen"; /** * Yields stream of value changes in given atom / cursor. Attaches watch @@ -33,15 +33,22 @@ import { Stream } from "../stream"; * @param emitFirst * @param changed */ -export function fromAtom(atom: ReadonlyAtom, emitFirst = true, changed?: Predicate2): Stream { - return new Stream((stream) => { - changed = changed || ((a, b) => a !== b); - atom.addWatch(stream.id, (_, prev, curr) => { - if (changed(prev, curr)) { - stream.next(curr); - } - }); - emitFirst && stream.next(atom.deref()); - return () => atom.removeWatch(stream.id); - }); -} +export const fromAtom = ( + atom: ReadonlyAtom, + emitFirst = true, + changed?: Predicate2 +): Stream => + + new Stream( + (stream) => { + changed = changed || ((a, b) => a !== b); + atom.addWatch(stream.id, (_, prev, curr) => { + if (changed(prev, curr)) { + stream.next(curr); + } + }); + emitFirst && stream.next(atom.deref()); + return () => atom.removeWatch(stream.id); + }, + `atom-${nextID()}` + ); diff --git a/packages/rstream/src/from/event.ts b/packages/rstream/src/from/event.ts index 49d677b387..944649dab1 100644 --- a/packages/rstream/src/from/event.ts +++ b/packages/rstream/src/from/event.ts @@ -1,5 +1,5 @@ import { Stream } from "../stream"; -import { Subscription } from "../subscription"; +import { nextID } from "../utils/idgen"; /** * Creates a new stream of DOM events attached to given element / event @@ -10,10 +10,16 @@ import { Subscription } from "../subscription"; * @param name event name * @param opts listener opts */ -export function fromEvent(src: EventTarget, name: string, opts: boolean | AddEventListenerOptions = false) { - return new Stream((stream) => { - let listener = (e) => stream.next(e); - src.addEventListener(name, listener, opts); - return () => src.removeEventListener(name, listener, opts); - }, `event-${name}-${Subscription.NEXT_ID++}`); -} +export const fromEvent = ( + src: EventTarget, + name: string, + opts: boolean | AddEventListenerOptions = false +) => + new Stream( + (stream) => { + let listener = (e) => stream.next(e); + src.addEventListener(name, listener, opts); + return () => src.removeEventListener(name, listener, opts); + }, + `event-${name}-${nextID()}` + ); diff --git a/packages/rstream/src/from/interval.ts b/packages/rstream/src/from/interval.ts index b92c6b2f56..6336c1108f 100644 --- a/packages/rstream/src/from/interval.ts +++ b/packages/rstream/src/from/interval.ts @@ -1,5 +1,5 @@ import { Stream } from "../stream"; -import { Subscription } from "../subscription"; +import { nextID } from "../utils/idgen"; /** * Returns a new `Stream` which emits a monotonically increasing counter @@ -10,17 +10,20 @@ import { Subscription } from "../subscription"; * @param delay * @param count */ -export function fromInterval(delay: number, count = Infinity) { - return new Stream((stream) => { - let i = 0; - stream.next(i++); - let id = setInterval(() => { - stream.next(i++); - if (--count <= 0) { - clearInterval(id); - stream.done(); - } - }, delay); - return () => clearInterval(id); - }, `interval-${Subscription.NEXT_ID++}`); -} +export const fromInterval = + (delay: number, count = Infinity) => + new Stream( + (stream) => { + let i = 0; + stream.next(i++); + let id = setInterval(() => { + stream.next(i++); + if (--count <= 0) { + clearInterval(id); + stream.done(); + } + }, delay); + return () => clearInterval(id); + }, + `interval-${nextID()}` + ); diff --git a/packages/rstream/src/from/iterable.ts b/packages/rstream/src/from/iterable.ts index 57d74d73ce..401ae421d6 100644 --- a/packages/rstream/src/from/iterable.ts +++ b/packages/rstream/src/from/iterable.ts @@ -1,5 +1,5 @@ import { Stream } from "../stream"; -import { Subscription } from "../subscription"; +import { nextID } from "../utils/idgen"; /** * Creates a new `Stream` of given iterable which asynchronously calls @@ -13,24 +13,24 @@ import { Subscription } from "../subscription"; * @param delay * @param close */ -export function fromIterable(src: Iterable, delay = 0, close = true) { - return new Stream( - (stream) => { - const iter = src[Symbol.iterator](); - const id = setInterval(() => { - let val: IteratorResult; - if ((val = iter.next()).done) { - clearInterval(id); - close && stream.done(); - } else { - stream.next(val.value); - } - }, delay); - return () => clearInterval(id); - }, - `iterable-${Subscription.NEXT_ID++}` - ); -} +export const fromIterable = + (src: Iterable, delay = 0, close = true) => + new Stream( + (stream) => { + const iter = src[Symbol.iterator](); + const id = setInterval(() => { + let val: IteratorResult; + if ((val = iter.next()).done) { + clearInterval(id); + close && stream.done(); + } else { + stream.next(val.value); + } + }, delay); + return () => clearInterval(id); + }, + `iterable-${nextID()}` + ); /** * Creates a new `Stream` of given iterable which synchronously calls @@ -42,15 +42,15 @@ export function fromIterable(src: Iterable, delay = 0, close = true) { * @param src * @param close */ -export function fromIterableSync(src: Iterable, close = true) { - return new Stream( - (stream) => { - for (let s of src) { - stream.next(s); - } - close && stream.done(); - return null; - }, - `iterable-${Subscription.NEXT_ID++}` - ); -} +export const fromIterableSync = + (src: Iterable, close = true) => + new Stream( + (stream) => { + for (let s of src) { + stream.next(s); + } + close && stream.done(); + return null; + }, + `iterable-${nextID()}` + ); diff --git a/packages/rstream/src/from/promise.ts b/packages/rstream/src/from/promise.ts index 416a2962db..5f7052d738 100644 --- a/packages/rstream/src/from/promise.ts +++ b/packages/rstream/src/from/promise.ts @@ -1,6 +1,6 @@ import { State } from "../api"; import { Stream } from "../stream"; -import { Subscription } from "../subscription"; +import { nextID } from "../utils/idgen"; /** * Yields a single-value stream of the resolved promise and then @@ -9,31 +9,35 @@ import { Subscription } from "../subscription"; * * @param src */ -export function fromPromise(src: Promise) { - let canceled = false; - let isError = false; - let err: any = {}; - src.catch( - (e) => { - err = e; - isError = true; - } - ); - return new Stream((stream) => { - src.then( - (x) => { - if (!canceled && stream.getState() < State.DONE) { - if (isError) { - stream.error(err); - err = null; - } else { - stream.next(x); - stream.done(); - } - } +export const fromPromise = + (src: Promise) => { + let canceled = false; + let isError = false; + let err: any = {}; + src.catch( + (e) => { + err = e; + isError = true; + } + ); + return new Stream( + (stream) => { + src.then( + (x) => { + if (!canceled && stream.getState() < State.DONE) { + if (isError) { + stream.error(err); + err = null; + } else { + stream.next(x); + stream.done(); + } + } + }, + (e) => stream.error(e) + ); + return () => { canceled = true; }; }, - (e) => stream.error(e) + `promise-${nextID()}` ); - return () => { canceled = true; }; - }, `promise-${Subscription.NEXT_ID++}`); -} + }; diff --git a/packages/rstream/src/from/promises.ts b/packages/rstream/src/from/promises.ts index bd533037f2..13919b3681 100644 --- a/packages/rstream/src/from/promises.ts +++ b/packages/rstream/src/from/promises.ts @@ -1,5 +1,4 @@ -import { mapcat } from "@thi.ng/transducers/xform/mapcat"; - +import { mapcat } from "@thi.ng/transducers"; import { Subscription } from "../subscription"; import { fromPromise } from "./promise"; @@ -33,6 +32,6 @@ import { fromPromise } from "./promise"; * * @param promises */ -export function fromPromises(promises: Iterable>): Subscription { - return fromPromise(Promise.all(promises)).transform(mapcat((x: T[]) => x)); -} +export const fromPromises = + (promises: Iterable>): Subscription => + fromPromise(Promise.all(promises)).transform(mapcat((x: T[]) => x)); diff --git a/packages/rstream/src/from/raf.ts b/packages/rstream/src/from/raf.ts index f9de131334..edf0701c04 100644 --- a/packages/rstream/src/from/raf.ts +++ b/packages/rstream/src/from/raf.ts @@ -1,7 +1,6 @@ -import { isNode } from "@thi.ng/checks/is-node"; - +import { isNode } from "@thi.ng/checks"; import { Stream } from "../stream"; -import { Subscription } from "../subscription"; +import { nextID } from "../utils/idgen"; import { fromInterval } from "./interval"; /** @@ -13,17 +12,19 @@ import { fromInterval } from "./interval"; * Subscribers to this stream will be processed during that same loop * iteration. */ -export function fromRAF() { - return isNode() ? +export const fromRAF = () => + isNode() ? fromInterval(16) : - new Stream((stream) => { - let i = 0; - let isActive = true; - let loop = () => { - isActive && stream.next(i++); - isActive && (id = requestAnimationFrame(loop)); - }; - let id = requestAnimationFrame(loop); - return () => (isActive = false, cancelAnimationFrame(id)); - }, `raf-${Subscription.NEXT_ID++}`); -} + new Stream( + (stream) => { + let i = 0; + let isActive = true; + let loop = () => { + isActive && stream.next(i++); + isActive && (id = requestAnimationFrame(loop)); + }; + let id = requestAnimationFrame(loop); + return () => (isActive = false, cancelAnimationFrame(id)); + }, + `raf-${nextID()}` + ); diff --git a/packages/rstream/src/from/view.ts b/packages/rstream/src/from/view.ts index 35a9af2e13..62cf8f91ab 100644 --- a/packages/rstream/src/from/view.ts +++ b/packages/rstream/src/from/view.ts @@ -1,9 +1,9 @@ -import { Predicate2 } from "@thi.ng/api/api"; -import { ReadonlyAtom, ViewTransform } from "@thi.ng/atom/api"; -import { View } from "@thi.ng/atom/view"; +import { Predicate2 } from "@thi.ng/api"; +import { ReadonlyAtom, ViewTransform } from "@thi.ng/atom"; +import { View } from "@thi.ng/atom"; import { Path } from "@thi.ng/paths"; - import { Stream } from "../stream"; +import { nextID } from "../utils/idgen"; /** * Similar to `fromAtom()`, but creates an eager derived view for a @@ -43,18 +43,26 @@ import { Stream } from "../stream"; * @param equiv * @param id */ -export function fromView(atom: ReadonlyAtom, path: Path, tx?: ViewTransform, equiv?: Predicate2, id?: string): Stream { - return new Stream((stream) => { - let isActive = true; - const view = new View( - atom, - path, - tx ? - (x) => isActive && (x = tx(x), stream.next(x), x) : - (x) => isActive && (stream.next(x), x), - false, - equiv - ); - return () => (isActive = false, view.release()); - }, id); -} +export const fromView = ( + atom: ReadonlyAtom, + path: Path, + tx?: ViewTransform, + equiv?: Predicate2, + id?: string +): Stream => + new Stream( + (stream) => { + let isActive = true; + const view = new View( + atom, + path, + tx ? + (x) => isActive && (x = tx(x), stream.next(x), x) : + (x) => isActive && (stream.next(x), x), + false, + equiv + ); + return () => (isActive = false, view.release()); + }, + id || `view-${nextID()}` + ); diff --git a/packages/rstream/src/from/worker.ts b/packages/rstream/src/from/worker.ts index e045c5f3ce..83a7993908 100644 --- a/packages/rstream/src/from/worker.ts +++ b/packages/rstream/src/from/worker.ts @@ -1,5 +1,6 @@ import { DEBUG } from "../api"; import { Stream } from "../stream"; +import { nextID } from "../utils/idgen"; import { makeWorker } from "../utils/worker"; /** @@ -20,21 +21,26 @@ import { makeWorker } from "../utils/worker"; * * @param worker * @param terminate + * @param id */ -export function fromWorker(worker: Worker | Blob | string, terminate = true) { - const _worker = makeWorker(worker); - return new Stream((stream) => { - const ml = (e: MessageEvent) => { stream.next(e.data); }; - const el = (e: MessageEvent) => { stream.error(e.data); }; - _worker.addEventListener("message", ml); - _worker.addEventListener("error", el); - return () => { - _worker.removeEventListener("message", ml); - _worker.removeEventListener("error", el); - if (terminate) { - DEBUG && console.log("terminating worker", _worker); - _worker.terminate(); - } - }; - }); -} +export const fromWorker = + (worker: Worker | Blob | string, terminate = true, id?: string) => { + const _worker = makeWorker(worker); + return new Stream( + (stream) => { + const ml = (e: MessageEvent) => { stream.next(e.data); }; + const el = (e: MessageEvent) => { stream.error(e.data); }; + _worker.addEventListener("message", ml); + _worker.addEventListener("error", el); + return () => { + _worker.removeEventListener("message", ml); + _worker.removeEventListener("error", el); + if (terminate) { + DEBUG && console.log("terminating worker", _worker); + _worker.terminate(); + } + }; + }, + id || `worker-${nextID()}` + ); + }; diff --git a/packages/rstream/src/index.ts b/packages/rstream/src/index.ts index 007933fc25..3e76db7cf1 100644 --- a/packages/rstream/src/index.ts +++ b/packages/rstream/src/index.ts @@ -25,4 +25,5 @@ export * from "./subs/trace"; export * from "./subs/transduce"; export * from "./subs/tunnel"; +export * from "./utils/idgen"; export * from "./utils/worker"; diff --git a/packages/rstream/src/pubsub.ts b/packages/rstream/src/pubsub.ts index 8d97720d60..f357d53b9d 100644 --- a/packages/rstream/src/pubsub.ts +++ b/packages/rstream/src/pubsub.ts @@ -1,10 +1,10 @@ -import { Predicate2 } from "@thi.ng/api/api"; -import { EquivMap } from "@thi.ng/associative/equiv-map"; -import { unsupported } from "@thi.ng/errors/unsupported"; -import { Transducer } from "@thi.ng/transducers/api"; - +import { Predicate2 } from "@thi.ng/api"; +import { EquivMap } from "@thi.ng/associative"; +import { unsupported } from "@thi.ng/errors"; +import { Transducer } from "@thi.ng/transducers"; import { DEBUG, ISubscriber } from "./api"; -import { Subscription } from "./subscription"; +import { Subscription, subscription } from "./subscription"; +import { nextID } from "./utils/idgen"; export interface PubSubOpts { /** @@ -56,7 +56,7 @@ export class PubSub extends Subscription { constructor(opts?: PubSubOpts) { opts = opts || >{}; - super(null, opts.xform, null, opts.id || `pubsub-${Subscription.NEXT_ID++}`); + super(null, opts.xform, null, opts.id || `pubsub-${nextID()}`); this.topicfn = opts.topic; this.topics = new EquivMap>(null, { equiv: opts.equiv }); } @@ -84,7 +84,7 @@ export class PubSub extends Subscription { subscribeTopic(topicID: any, sub: any, id?: string): Subscription { let t = this.topics.get(topicID); if (!t) { - this.topics.set(topicID, t = new Subscription()); + this.topics.set(topicID, t = subscription()); } return t.subscribe(sub, id); } @@ -136,6 +136,6 @@ export class PubSub extends Subscription { * * @param opts */ -export function pubsub(opts: PubSubOpts) { - return new PubSub(opts); -} \ No newline at end of file +export const pubsub = + (opts: PubSubOpts) => + new PubSub(opts); diff --git a/packages/rstream/src/stream-merge.ts b/packages/rstream/src/stream-merge.ts index ff274bd5ed..6ba2696e3c 100644 --- a/packages/rstream/src/stream-merge.ts +++ b/packages/rstream/src/stream-merge.ts @@ -1,8 +1,8 @@ -import { IID } from "@thi.ng/api/api"; -import { Transducer } from "@thi.ng/transducers/api"; - +import { IID } from "@thi.ng/api"; +import { Transducer } from "@thi.ng/transducers"; import { ISubscribable, State } from "./api"; import { Subscription } from "./subscription"; +import { nextID } from "./utils/idgen"; export interface StreamMergeOpts extends IID { /** @@ -67,9 +67,9 @@ export interface StreamMergeOpts extends IID { * // ["b", 30] * ``` */ -export function merge(opts?: Partial>) { - return new StreamMerge(opts); -} +export const merge = + (opts?: Partial>) => + new StreamMerge(opts); export class StreamMerge extends Subscription { @@ -78,7 +78,7 @@ export class StreamMerge extends Subscription { constructor(opts?: Partial>) { opts = opts || {}; - super(null, opts.xform, null, opts.id || `streammerge-${Subscription.NEXT_ID++}`); + super(null, opts.xform, null, opts.id || `streammerge-${nextID()}`); this.sources = new Map(); this.autoClose = opts.close !== false; if (opts.src) { diff --git a/packages/rstream/src/stream-sync.ts b/packages/rstream/src/stream-sync.ts index 467758f7e9..dd3c46196d 100644 --- a/packages/rstream/src/stream-sync.ts +++ b/packages/rstream/src/stream-sync.ts @@ -1,13 +1,15 @@ -import { IID, IObjectOf } from "@thi.ng/api/api"; -import { isPlainObject } from "@thi.ng/checks/is-plain-object"; -import { Transducer } from "@thi.ng/transducers/api"; -import { comp } from "@thi.ng/transducers/func/comp"; -import { labeled } from "@thi.ng/transducers/xform/labeled"; -import { mapVals } from "@thi.ng/transducers/xform/map-vals"; -import { partitionSync } from "@thi.ng/transducers/xform/partition-sync"; - +import { IID, IObjectOf } from "@thi.ng/api"; +import { isPlainObject } from "@thi.ng/checks"; +import { + comp, + labeled, + mapVals, + partitionSync, + Transducer +} from "@thi.ng/transducers"; import { ISubscribable, State } from "./api"; import { Subscription } from "./subscription"; +import { nextID } from "./utils/idgen"; export interface StreamSyncOpts extends IID { /** @@ -91,9 +93,9 @@ export interface StreamSyncOpts extends IID { * the @thi.ng/transducers package. See this function's docs for further * details. */ -export function sync(opts: Partial>) { - return new StreamSync(opts); -} +export const sync = + (opts: Partial>) => + new StreamSync(opts); export class StreamSync extends Subscription { @@ -134,7 +136,7 @@ export class StreamSync extends Subscription { if (opts.xform) { xform = comp(xform, opts.xform); } - super(null, xform, null, opts.id || `streamsync-${Subscription.NEXT_ID++}`); + super(null, xform, null, opts.id || `streamsync-${nextID()}`); this.sources = new Map(); this.realSourceIDs = new Map(); this.invRealSourceIDs = new Map(); diff --git a/packages/rstream/src/stream.ts b/packages/rstream/src/stream.ts index b3f70a97e8..dc96d2902e 100644 --- a/packages/rstream/src/stream.ts +++ b/packages/rstream/src/stream.ts @@ -1,7 +1,6 @@ -import { isString } from "@thi.ng/checks/is-string"; -import { illegalArity } from "@thi.ng/errors/illegal-arity"; -import { Transducer } from "@thi.ng/transducers/api"; - +import { isString } from "@thi.ng/checks"; +import { illegalArity } from "@thi.ng/errors"; +import { Transducer } from "@thi.ng/transducers"; import { DEBUG, IStream, @@ -10,6 +9,7 @@ import { StreamSource } from "./api"; import { Subscription } from "./subscription"; +import { nextID } from "./utils/idgen"; /** * Creates a new `Stream` instance, optionally with given `StreamSource` @@ -97,7 +97,7 @@ export class Stream extends Subscription default: illegalArity(args.length); } - super(null, null, null, id || `stream-${Subscription.NEXT_ID++}`); + super(null, null, null, id || `stream-${nextID()}`); this.src = src; } diff --git a/packages/rstream/src/subs/bisect.ts b/packages/rstream/src/subs/bisect.ts index 2a05864e2c..a3e7068fdf 100644 --- a/packages/rstream/src/subs/bisect.ts +++ b/packages/rstream/src/subs/bisect.ts @@ -1,5 +1,4 @@ -import { Predicate } from "@thi.ng/api/api"; - +import { Predicate } from "@thi.ng/api"; import { ISubscriber } from "../api"; import { PubSub } from "../pubsub"; @@ -44,9 +43,13 @@ import { PubSub } from "../pubsub"; * @param a subscription for truthy branch * @param b subscription for falsy branch */ -export function bisect(pred: Predicate, a?: ISubscriber, b?: ISubscriber): PubSub { +export const bisect = ( + pred: Predicate, + a?: ISubscriber, + b?: ISubscriber +): PubSub => { const sub = new PubSub({ topic: pred }); sub.subscribeTopic(true, a); 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 c6520fdcff..f1fc5d2df2 100644 --- a/packages/rstream/src/subs/post-worker.ts +++ b/packages/rstream/src/subs/post-worker.ts @@ -1,6 +1,5 @@ -import { isTransferable } from "@thi.ng/checks/is-transferable"; -import { isTypedArray } from "@thi.ng/checks/is-typedarray"; - +import { isTransferable } from "@thi.ng/checks"; +import { isTypedArray } from "@thi.ng/checks"; import { DEBUG, ISubscriber } from "../api"; import { makeWorker } from "../utils/worker"; @@ -34,7 +33,12 @@ import { makeWorker } from "../utils/worker"; * @param transfer * @param terminate worker termination delay (ms) */ -export function postWorker(worker: Worker | Blob | string, transfer = false, terminate = 0): ISubscriber { +export const postWorker = ( + worker: Worker | Blob | string, + transfer = false, + terminate = 0 +): ISubscriber => { + const _worker = makeWorker(worker); return { next(x) { @@ -60,4 +64,4 @@ export function postWorker(worker: Worker | Blob | string, transfer = false, } } }; -} \ No newline at end of file +}; diff --git a/packages/rstream/src/subs/resolve.ts b/packages/rstream/src/subs/resolve.ts index 821067eb9b..1504af823e 100644 --- a/packages/rstream/src/subs/resolve.ts +++ b/packages/rstream/src/subs/resolve.ts @@ -1,7 +1,7 @@ -import { IID } from "@thi.ng/api/api"; - -import { __State, DEBUG, State } from "../api"; +import { IID } from "@thi.ng/api"; +import { DEBUG, State } from "../api"; import { Subscription } from "../subscription"; +import { nextID } from "../utils/idgen"; export interface ResolverOpts extends IID { /** @@ -30,9 +30,9 @@ export interface ResolverOpts extends IID { * * @param opts */ -export function resolve(opts?: Partial) { - return new Resolver(opts); -} +export const resolve = + (opts?: Partial) => + new Resolver(opts); export class Resolver extends Subscription, T> { @@ -40,7 +40,7 @@ export class Resolver extends Subscription, T> { protected fail: (e: any) => void; constructor(opts: Partial = {}) { - super(null, null, null, opts.id || `resolve-${Subscription.NEXT_ID++}`); + super(null, null, null, opts.id || `resolve-${nextID()}`); this.fail = opts.fail; } @@ -54,7 +54,7 @@ export class Resolver extends Subscription, T> { this.done(); } } else { - DEBUG && console.log(`resolved value in ${__State[this.state]} state (${x})`); + DEBUG && console.log(`resolved value in state ${this.state} (${x})`); } }, (e) => { diff --git a/packages/rstream/src/subs/sidechain-partition.ts b/packages/rstream/src/subs/sidechain-partition.ts index b0d7307876..b05d8efaab 100644 --- a/packages/rstream/src/subs/sidechain-partition.ts +++ b/packages/rstream/src/subs/sidechain-partition.ts @@ -1,7 +1,7 @@ -import { Predicate } from "@thi.ng/api/api"; - +import { Predicate } from "@thi.ng/api"; import { ISubscribable, State } from "../api"; import { Subscription } from "../subscription"; +import { nextID } from "../utils/idgen"; /** * Buffers values from `src` until side chain fires, then emits buffer @@ -27,9 +27,12 @@ import { Subscription } from "../subscription"; * @param pred * @param id */ -export function sidechainPartition(side: ISubscribable, pred?: Predicate, id?: string): Subscription { - return new SidechainPartition(side, pred, id); -} +export const sidechainPartition = ( + side: ISubscribable, + pred?: Predicate, + id?: string +): Subscription => + new SidechainPartition(side, pred, id); export class SidechainPartition extends Subscription { @@ -37,7 +40,7 @@ export class SidechainPartition extends Subscription { buf: A[]; constructor(side: ISubscribable, pred?: Predicate, id?: string) { - super(null, null, null, id || `sidepart-${Subscription.NEXT_ID++}`); + super(null, null, null, id || `sidepart-${nextID()}`); this.buf = []; const $this = this; pred = pred || (() => true); diff --git a/packages/rstream/src/subs/sidechain-toggle.ts b/packages/rstream/src/subs/sidechain-toggle.ts index 30595d9864..fe2983dad5 100644 --- a/packages/rstream/src/subs/sidechain-toggle.ts +++ b/packages/rstream/src/subs/sidechain-toggle.ts @@ -1,7 +1,7 @@ -import { Predicate } from "@thi.ng/api/api"; - +import { Predicate } from "@thi.ng/api"; import { ISubscribable } from "../api"; import { Subscription } from "../subscription"; +import { nextID } from "../utils/idgen"; /** * Filters values from input based on values received from side chain. @@ -29,9 +29,13 @@ import { Subscription } from "../subscription"; * @param initial initial switch state * @param id */ -export function sidechainToggle(side: ISubscribable, initial = true, pred?: Predicate, id?: string): Subscription { - return new SidechainToggle(side, initial, pred, id); -} +export const sidechainToggle = ( + side: ISubscribable, + initial = true, + pred?: Predicate, + id?: string +): Subscription => + new SidechainToggle(side, initial, pred, id); export class SidechainToggle extends Subscription { @@ -39,7 +43,7 @@ export class SidechainToggle extends Subscription { isActive: boolean; constructor(side: ISubscribable, initial = true, pred?: Predicate, id?: string) { - super(null, null, null, id || `sidetoggle-${Subscription.NEXT_ID++}`); + super(null, null, null, id || `sidetoggle-${nextID()}`); this.isActive = initial; const $this = this; pred = pred || (() => true); diff --git a/packages/rstream/src/subs/timeout.ts b/packages/rstream/src/subs/timeout.ts index 67e074cb2f..f656e82fbd 100644 --- a/packages/rstream/src/subs/timeout.ts +++ b/packages/rstream/src/subs/timeout.ts @@ -1,5 +1,6 @@ -import { State } from "../api" +import { State } from "../api"; import { Subscription } from "../subscription"; +import { nextID } from "../utils/idgen"; /** * A subscription that emits an arbitrary error object after a given @@ -14,9 +15,13 @@ import { Subscription } from "../subscription"; * @param resetTimeout timeout reset flag * @param id subscription id */ -export function timeout(timeoutMs: number, error?: any, resetTimeout = false, id?: string): Subscription { - return new Timeout(timeoutMs, error, resetTimeout, id); -} +export const timeout = ( + timeoutMs: number, + error?: any, + resetTimeout = false, + id?: string +): Subscription => + new Timeout(timeoutMs, error, resetTimeout, id); class Timeout extends Subscription { protected timeoutMs: number; @@ -25,7 +30,7 @@ class Timeout extends Subscription { protected resetTimeout: boolean; constructor(timeoutMs: number, error?: any, resetTimeout = false, id?: string) { - super(null, null, null, id || `timeout-${Subscription.NEXT_ID++}`); + super(null, null, null, id || `timeout-${nextID()}`); this.timeoutMs = timeoutMs; this.errorObj = error; this.resetTimeout = resetTimeout; diff --git a/packages/rstream/src/subs/trace.ts b/packages/rstream/src/subs/trace.ts index e9a403d8f4..ad5874e06f 100644 --- a/packages/rstream/src/subs/trace.ts +++ b/packages/rstream/src/subs/trace.ts @@ -6,16 +6,16 @@ import { ISubscriber } from "../api"; * * @param prefix */ -export function trace(prefix?: any): ISubscriber { - return { - next(x) { - prefix ? console.log(prefix, x) : console.log(x); - }, - done() { - prefix ? console.log(prefix, "done") : console.log("done"); - }, - error(e) { - prefix ? console.log(prefix, "error", e) : console.log("error", e); - } - } -} +export const trace = + (prefix?: any): ISubscriber => + ({ + next(x) { + prefix ? console.log(prefix, x) : console.log(x); + }, + done() { + prefix ? console.log(prefix, "done") : console.log("done"); + }, + error(e) { + prefix ? console.log(prefix, "error", e) : console.log("error", e); + } + }); diff --git a/packages/rstream/src/subs/transduce.ts b/packages/rstream/src/subs/transduce.ts index 123d904653..1be3645bd2 100644 --- a/packages/rstream/src/subs/transduce.ts +++ b/packages/rstream/src/subs/transduce.ts @@ -1,6 +1,5 @@ -import { Reducer, Transducer } from "@thi.ng/transducers/api"; -import { isReduced } from "@thi.ng/transducers/reduced"; - +import { Reducer, Transducer } from "@thi.ng/transducers"; +import { isReduced } from "@thi.ng/transducers"; import { Subscription } from "../subscription"; /** @@ -24,7 +23,13 @@ import { Subscription } from "../subscription"; * @param rfn * @param init */ -export function transduce(src: Subscription, xform: Transducer, rfn: Reducer, init?: C): Promise { +export const transduce = ( + src: Subscription, + xform: Transducer, + rfn: Reducer, + init?: C +): Promise => { + let acc = init !== undefined ? init : rfn[0](); let sub: Subscription; @@ -55,4 +60,4 @@ export function transduce(src: Subscription, xform: Transducer< throw rejected; } ); -} +}; diff --git a/packages/rstream/src/subs/tunnel.ts b/packages/rstream/src/subs/tunnel.ts index 8e135884a7..d5b0b2bac9 100644 --- a/packages/rstream/src/subs/tunnel.ts +++ b/packages/rstream/src/subs/tunnel.ts @@ -1,5 +1,6 @@ import { DEBUG, State } from "../api"; import { Subscription } from "../subscription"; +import { nextID } from "../utils/idgen"; import { makeWorker } from "../utils/worker"; export interface TunnelOpts { @@ -54,8 +55,9 @@ export interface TunnelOpts { * * @param opts */ -export const tunnel = (opts: TunnelOpts) => - new Tunnel(opts); +export const tunnel = + (opts: TunnelOpts) => + new Tunnel(opts); export class Tunnel extends Subscription { @@ -68,7 +70,7 @@ export class Tunnel extends Subscription { index: number; constructor(opts: TunnelOpts) { - super(null, null, null, opts.id || `tunnel-${Subscription.NEXT_ID++}`); + super(null, null, null, opts.id || `tunnel-${nextID()}`); this.src = opts.src; this.workers = new Array(opts.maxWorkers || 1); this.transferables = opts.transferables; diff --git a/packages/rstream/src/subscription.ts b/packages/rstream/src/subscription.ts index f6ac3a69ab..dbdd3d9804 100644 --- a/packages/rstream/src/subscription.ts +++ b/packages/rstream/src/subscription.ts @@ -1,21 +1,21 @@ -import { IDeref, SEMAPHORE } from "@thi.ng/api/api"; -import { implementsFunction } from "@thi.ng/checks/implements-function"; -import { isFunction } from "@thi.ng/checks/is-function"; -import { isString } from "@thi.ng/checks/is-string"; -import { illegalArity } from "@thi.ng/errors/illegal-arity"; -import { illegalState } from "@thi.ng/errors/illegal-state"; -import { Reducer, Transducer } from "@thi.ng/transducers/api"; -import { comp } from "@thi.ng/transducers/func/comp"; -import { isReduced, unreduced } from "@thi.ng/transducers/reduced"; -import { push } from "@thi.ng/transducers/rfn/push"; - +import { IDeref, SEMAPHORE } from "@thi.ng/api"; +import { implementsFunction, isFunction, isString } from "@thi.ng/checks"; +import { illegalArity, illegalState } from "@thi.ng/errors"; +import { + comp, + isReduced, + push, + Reducer, + Transducer, + unreduced +} from "@thi.ng/transducers"; import { - __State, DEBUG, ISubscribable, ISubscriber, State } from "./api"; +import { nextID } from "./utils/idgen"; /** * Creates a new `Subscription` instance, the fundamental datatype & @@ -51,17 +51,19 @@ import { * @param parent * @param id */ -export function subscription(sub?: ISubscriber, xform?: Transducer, parent?: ISubscribable, id?: string) { - return new Subscription(sub, xform, parent, id); -} +export const subscription = ( + sub?: ISubscriber, + xform?: Transducer, + parent?: ISubscribable, + id?: string +) => + new Subscription(sub, xform, parent, id); export class Subscription implements IDeref, ISubscriber, ISubscribable { - static NEXT_ID = 0; - id: string; protected parent: ISubscribable; @@ -73,7 +75,7 @@ export class Subscription implements constructor(sub?: ISubscriber, xform?: Transducer, parent?: ISubscribable, id?: string) { this.parent = parent; - this.id = id || `sub-${Subscription.NEXT_ID++}`; + this.id = id || `sub-${nextID()}`; this.last = SEMAPHORE; this.subs = []; if (sub) { @@ -109,7 +111,7 @@ export class Subscription implements case 2: if (isFunction(args[0])) { xform = args[0]; - id = args[1] || `xform-${Subscription.NEXT_ID++}`; + id = args[1] || `xform-${nextID()}`; } else { sub = args[0]; if (isFunction(args[1])) { @@ -128,7 +130,7 @@ export class Subscription implements if (implementsFunction(sub, "subscribe")) { sub.parent = this; } else { - sub = new Subscription(sub, xform, this, id); + sub = subscription(sub, xform, this, id); } if (this.last !== SEMAPHORE) { sub.next(this.last); @@ -296,7 +298,7 @@ export class Subscription implements protected ensureState() { if (this.state >= State.DONE) { - illegalState(`operation not allowed in ${__State[this.state]} state`); + illegalState(`operation not allowed in state ${this.state}`); } } diff --git a/packages/rstream/src/utils/idgen.ts b/packages/rstream/src/utils/idgen.ts new file mode 100644 index 0000000000..6a23983489 --- /dev/null +++ b/packages/rstream/src/utils/idgen.ts @@ -0,0 +1,3 @@ +let NEXT_ID = 0; + +export const nextID = () => NEXT_ID++; diff --git a/packages/rstream/src/utils/worker.ts b/packages/rstream/src/utils/worker.ts index 16221ab2c3..017d98a747 100644 --- a/packages/rstream/src/utils/worker.ts +++ b/packages/rstream/src/utils/worker.ts @@ -1,13 +1,13 @@ -export function inlineWorker(src: string) { - return makeWorker(new Blob([src], { type: "text/javascript" })); -} +export const inlineWorker = + (src: string) => + makeWorker(new Blob([src], { type: "text/javascript" })); -export function makeWorker(worker: Worker | string | Blob) { - return worker instanceof Worker ? - worker : - new Worker( - worker instanceof Blob ? - URL.createObjectURL(worker) : - worker - ); -} +export const makeWorker = + (worker: Worker | string | Blob) => + worker instanceof Worker ? + worker : + new Worker( + worker instanceof Blob ? + URL.createObjectURL(worker) : + worker + ); diff --git a/packages/rstream/test/tsconfig.json b/packages/rstream/test/tsconfig.json index 13d45669e5..2c9c12a650 100644 --- a/packages/rstream/test/tsconfig.json +++ b/packages/rstream/test/tsconfig.json @@ -1,7 +1,8 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", diff --git a/packages/rstream/tsconfig.json b/packages/rstream/tsconfig.json index f6c291a0a0..bcf03f18b4 100644 --- a/packages/rstream/tsconfig.json +++ b/packages/rstream/tsconfig.json @@ -1,7 +1,9 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" diff --git a/packages/sax/.npmignore b/packages/sax/.npmignore index d703bda97a..67d0c55714 100644 --- a/packages/sax/.npmignore +++ b/packages/sax/.npmignore @@ -1,10 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/sax/CHANGELOG.md b/packages/sax/CHANGELOG.md index 79a8d76398..0542f5a143 100644 --- a/packages/sax/CHANGELOG.md +++ b/packages/sax/CHANGELOG.md @@ -3,6 +3,28 @@ 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/sax@0.5.13...@thi.ng/sax@1.0.0) (2019-01-21) + + +### Build System + +* update package build scripts & outputs, imports in ~50 packages ([b54b703](https://github.com/thi-ng/umbrella/commit/b54b703)) + + +### BREAKING CHANGES + +* enabled multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols. + + + + + ## [0.5.13](https://github.com/thi-ng/umbrella/compare/@thi.ng/sax@0.5.12...@thi.ng/sax@0.5.13) (2019-01-02) **Note:** Version bump only for package @thi.ng/sax diff --git a/packages/sax/package.json b/packages/sax/package.json index 0b7cf05ac2..a9df3ddc8f 100644 --- a/packages/sax/package.json +++ b/packages/sax/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/sax", - "version": "0.5.13", + "version": "1.0.0", "description": "Transducer-based, SAX-like, non-validating, speedy & tiny XML parser", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,25 +14,27 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn run clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module sax api transducers transducers-fsm", + "test": "rimraf build && tsc -p test/tsconfig.json && nyc mocha build/test/*.js", + "clean": "rimraf *.js *.d.ts .nyc_output build coverage doc lib internal", "cover": "yarn test && nyc report --reporter=lcov", "doc": "node_modules/.bin/typedoc --mode modules --out doc src", - "pub": "yarn run build && yarn publish --access public", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/api": "^4.2.4", - "@thi.ng/transducers": "^2.3.2", - "@thi.ng/transducers-fsm": "^0.2.36" + "@thi.ng/api": "^5.0.0", + "@thi.ng/transducers": "^3.0.0", + "@thi.ng/transducers-fsm": "^1.0.0" }, "keywords": [ "ES6", @@ -43,5 +47,6 @@ ], "publishConfig": { "access": "public" - } + }, + "sideEffects": false } diff --git a/packages/sax/src/index.ts b/packages/sax/src/index.ts index 4765924d6b..4d04b26c61 100644 --- a/packages/sax/src/index.ts +++ b/packages/sax/src/index.ts @@ -1,7 +1,6 @@ import { IObjectOf } from "@thi.ng/api"; +import { $iter, iterator, Transducer } from "@thi.ng/transducers"; import { fsm, FSMState, FSMStateMap } from "@thi.ng/transducers-fsm"; -import { Transducer } from "@thi.ng/transducers/api"; -import { $iter, iterator } from "@thi.ng/transducers/iterator"; export interface ParseOpts { /** diff --git a/packages/sax/test/tsconfig.json b/packages/sax/test/tsconfig.json index bcf29ace54..2c9c12a650 100644 --- a/packages/sax/test/tsconfig.json +++ b/packages/sax/test/tsconfig.json @@ -1,10 +1,11 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", "../src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/sax/tsconfig.json b/packages/sax/tsconfig.json index bd6481a5a6..bcf03f18b4 100644 --- a/packages/sax/tsconfig.json +++ b/packages/sax/tsconfig.json @@ -1,9 +1,11 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/strings/.npmignore b/packages/strings/.npmignore index d703bda97a..67d0c55714 100644 --- a/packages/strings/.npmignore +++ b/packages/strings/.npmignore @@ -1,10 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/strings/CHANGELOG.md b/packages/strings/CHANGELOG.md index b69a89447a..679025e833 100644 --- a/packages/strings/CHANGELOG.md +++ b/packages/strings/CHANGELOG.md @@ -3,6 +3,33 @@ 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/strings@0.7.1...@thi.ng/strings@1.0.0) (2019-01-21) + + +### Build System + +* update package build scripts & outputs, imports in ~50 packages ([b54b703](https://github.com/thi-ng/umbrella/commit/b54b703)) + + +### Features + +* **strings:** add floatFixedWidth(), update float() ([816c9c0](https://github.com/thi-ng/umbrella/commit/816c9c0)) + + +### BREAKING CHANGES + +* enabled multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols. + + + + + ## [0.7.1](https://github.com/thi-ng/umbrella/compare/@thi.ng/strings@0.7.0...@thi.ng/strings@0.7.1) (2018-12-15) **Note:** Version bump only for package @thi.ng/strings diff --git a/packages/strings/README.md b/packages/strings/README.md index bf6def08b2..3cfbd5a5e7 100644 --- a/packages/strings/README.md +++ b/packages/strings/README.md @@ -20,8 +20,9 @@ This project is part of the ## About -Various higher-order, but low-level string formatting & utility -functions, some memoized. WIP / Alpha. Please sources for now. +Various higher-order, configurable string formatting & utility +functions, some memoized. WIP / Alpha. Please sources / docstrings for +now. ## Installation diff --git a/packages/strings/package.json b/packages/strings/package.json index 49aa43eedb..de96ca6b62 100644 --- a/packages/strings/package.json +++ b/packages/strings/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/strings", - "version": "0.7.1", + "version": "1.0.0", "description": "Various string formatting & utility functions", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,36 +14,50 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn run clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module strings errors memoize", + "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 run build && yarn publish --access public", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/errors": "^0.1.12", - "@thi.ng/memoize": "^0.2.6" + "@thi.ng/errors": "^1.0.0", + "@thi.ng/memoize": "^1.0.0" }, "keywords": [ + "composition", "ES6", + "camelcase", + "center", + "float", "format", "functional", + "hex", "higher order", - "padding", + "kebabcase", "number", + "padding", + "percent", + "radix", + "slugify", + "snakecase", "string", - "typescript" + "typescript", + "wordwrap" ], "publishConfig": { "access": "public" - } + }, + "sideEffects": false } diff --git a/packages/strings/src/center.ts b/packages/strings/src/center.ts index a2a6597b5c..261b2da014 100644 --- a/packages/strings/src/center.ts +++ b/packages/strings/src/center.ts @@ -1,4 +1,4 @@ -import { memoizeJ } from "@thi.ng/memoize/memoizej"; +import { memoizeJ } from "@thi.ng/memoize"; import { Stringer } from "./api"; import { repeat } from "./repeat"; diff --git a/packages/strings/src/float.ts b/packages/strings/src/float.ts index 5b8d2f71d6..251833a36e 100644 --- a/packages/strings/src/float.ts +++ b/packages/strings/src/float.ts @@ -1,12 +1,65 @@ -import { memoizeJ } from "@thi.ng/memoize/memoizej"; +import { memoizeJ } from "@thi.ng/memoize"; import { Stringer } from "./api"; +import { padLeft } from "./pad-left"; /** * Returns `Stringer` which formats numbers to given precision. + * Exceptions: + * + * - NaN => "NaN" + * - Infinity => "+/-∞" * * @param len number of fractional digits * @kind function */ export const float: (prec: number) => Stringer = - memoizeJ((prec) => (x: number) => x.toFixed(prec)); + memoizeJ((prec) => + (x: number) => + nanOrInf(x) || x.toFixed(prec) + ); + +/** + * Similar to `float`, returns `Stringer` which formats numbers to given + * character width & precision. Uses scientific notation if needed. + * + * Default precision: 3 fractional digits + */ +export const floatFixedWidth: (width: number, prec?: number) => Stringer = + memoizeJ((width, prec = 3) => { + const l = width - prec - 1; + const pl = Math.pow(10, l); + const pln = -Math.pow(10, l - 1); + const pr = Math.pow(10, -(prec - 1)); + const pad = padLeft(width); + return (x: number) => { + const ax = Math.abs(x); + return pad( + nanOrInf(x) || + (x === 0 ? + "0" : + ax < pr || ax >= pl ? + exp(x, width) : + x.toFixed(prec - (x < pln ? 1 : 0))) + ); + } + }); + +const exp = (x: number, w: number) => + x.toExponential( + Math.max( + w - 4 - + (Math.log(Math.abs(x)) / Math.LN10 >= 10 ? 2 : 1) + - (x < 0 ? 1 : 0), + 0 + ) + ); + +const nanOrInf = (x: number) => + isNaN(x) ? + "NaN" : + x === Infinity ? + "+∞" : + x === -Infinity ? + "-∞" : + undefined; diff --git a/packages/strings/src/format.ts b/packages/strings/src/format.ts index cb3f15c0c9..0b675165a6 100644 --- a/packages/strings/src/format.ts +++ b/packages/strings/src/format.ts @@ -1,15 +1,16 @@ -export const format = (fmt: any[], ...args: any[]) => { - const acc: any[] = []; - for (let i = 0, j = 0, n = fmt.length; i < n; i++) { - const f = fmt[i]; - const t = typeof f; - acc.push( - t === "function" ? - f(args[j++]) : - t === "object" ? - f[args[j++]] : - f - ); - } - return acc.join(""); -}; +export const format = + (fmt: any[], ...args: any[]) => { + const acc: any[] = []; + for (let i = 0, j = 0, n = fmt.length; i < n; i++) { + const f = fmt[i]; + const t = typeof f; + acc.push( + t === "function" ? + f(args[j++]) : + t === "object" ? + f[args[j++]] : + f + ); + } + return acc.join(""); + }; diff --git a/packages/strings/src/pad-left.ts b/packages/strings/src/pad-left.ts index 9f77c0153f..489a77ba46 100644 --- a/packages/strings/src/pad-left.ts +++ b/packages/strings/src/pad-left.ts @@ -1,4 +1,4 @@ -import { memoizeJ } from "@thi.ng/memoize/memoizej"; +import { memoizeJ } from "@thi.ng/memoize"; import { Stringer } from "./api"; import { repeat } from "./repeat"; diff --git a/packages/strings/src/pad-right.ts b/packages/strings/src/pad-right.ts index 2b2ff2e29f..73daa72358 100644 --- a/packages/strings/src/pad-right.ts +++ b/packages/strings/src/pad-right.ts @@ -1,4 +1,4 @@ -import { memoizeJ } from "@thi.ng/memoize/memoizej"; +import { memoizeJ } from "@thi.ng/memoize"; import { Stringer } from "./api"; import { repeat } from "./repeat"; diff --git a/packages/strings/src/parse.ts b/packages/strings/src/parse.ts index ada5e7bae6..86ada2b373 100644 --- a/packages/strings/src/parse.ts +++ b/packages/strings/src/parse.ts @@ -1,9 +1,11 @@ -export const maybeParseInt = (x: string, defaultVal: any = 0, radix = 10) => { - const n = parseInt(x, radix); - return isNaN(n) ? defaultVal : n; -}; +export const maybeParseInt = + (x: string, defaultVal: any = 0, radix = 10) => { + const n = parseInt(x, radix); + return isNaN(n) ? defaultVal : n; + }; -export const maybeParseFloat = (x: string, defaultVal: any = 0) => { - const n = parseFloat(x); - return isNaN(n) ? defaultVal : n; -}; +export const maybeParseFloat = + (x: string, defaultVal: any = 0) => { + const n = parseFloat(x); + return isNaN(n) ? defaultVal : n; + }; diff --git a/packages/strings/src/percent.ts b/packages/strings/src/percent.ts index cd6bd93645..fb1baf6e9d 100644 --- a/packages/strings/src/percent.ts +++ b/packages/strings/src/percent.ts @@ -6,5 +6,6 @@ import { Stringer } from "./api"; * * @param prec number of fractional digits (default: 0) */ -export const percent = (prec = 0): Stringer => - (x: number) => (x * 100).toFixed(prec) + "%"; +export const percent = + (prec = 0): Stringer => + (x: number) => (x * 100).toFixed(prec) + "%"; diff --git a/packages/strings/src/radix.ts b/packages/strings/src/radix.ts index fd3a84c46b..d404d748cc 100644 --- a/packages/strings/src/radix.ts +++ b/packages/strings/src/radix.ts @@ -1,5 +1,4 @@ -import { memoizeJ } from "@thi.ng/memoize/memoizej"; - +import { memoizeJ } from "@thi.ng/memoize"; import { Stringer } from "./api"; import { repeat } from "./repeat"; diff --git a/packages/strings/src/repeat.ts b/packages/strings/src/repeat.ts index 86738ee717..9813e2aa67 100644 --- a/packages/strings/src/repeat.ts +++ b/packages/strings/src/repeat.ts @@ -1,4 +1,4 @@ -import { memoizeJ } from "@thi.ng/memoize/memoizej"; +import { memoizeJ } from "@thi.ng/memoize"; /** * @param ch character diff --git a/packages/strings/src/splice.ts b/packages/strings/src/splice.ts index 7aa846314d..8b2f809fed 100644 --- a/packages/strings/src/splice.ts +++ b/packages/strings/src/splice.ts @@ -1,4 +1,4 @@ -import { illegalArgs } from "@thi.ng/errors/illegal-arguments"; +import { illegalArgs } from "@thi.ng/errors"; /** * Forms a new strings which inserts given `insert` string into `src` @@ -13,20 +13,21 @@ import { illegalArgs } from "@thi.ng/errors/illegal-arguments"; * @param from * @param to */ -export const splice = (src: string, insert: string, from: number, to = from) => { - if (from < 0) { - from += src.length; - } - if (to < 0) { - to += src.length; - } - if (from > to) { - illegalArgs("'from' index must be <= 'to'"); - } - to = Math.max(to, 0); - return from <= 0 ? - insert + src.substr(to) : - from >= src.length ? - src + insert : - src.substr(0, from) + insert + src.substr(to); -}; +export const splice = + (src: string, insert: string, from: number, to = from) => { + if (from < 0) { + from += src.length; + } + if (to < 0) { + to += src.length; + } + if (from > to) { + illegalArgs("'from' index must be <= 'to'"); + } + to = Math.max(to, 0); + return from <= 0 ? + insert + src.substr(to) : + from >= src.length ? + src + insert : + src.substr(0, from) + insert + src.substr(to); + }; diff --git a/packages/strings/src/truncate-left.ts b/packages/strings/src/truncate-left.ts index 27f0d44371..2534290364 100644 --- a/packages/strings/src/truncate-left.ts +++ b/packages/strings/src/truncate-left.ts @@ -1,5 +1,4 @@ -import { memoizeJ } from "@thi.ng/memoize/memoizej"; - +import { memoizeJ } from "@thi.ng/memoize"; import { Stringer } from "./api"; export const truncateLeft: (n: number, prefix?: string) => Stringer = diff --git a/packages/strings/src/truncate.ts b/packages/strings/src/truncate.ts index c470a25fd1..b4030b9461 100644 --- a/packages/strings/src/truncate.ts +++ b/packages/strings/src/truncate.ts @@ -1,5 +1,4 @@ -import { memoizeJ } from "@thi.ng/memoize/memoizej"; - +import { memoizeJ } from "@thi.ng/memoize"; import { Stringer } from "./api"; export const truncate: (n: number, suffix?: string) => Stringer = diff --git a/packages/strings/src/units.ts b/packages/strings/src/units.ts index efac24e8c9..3e6674f61f 100644 --- a/packages/strings/src/units.ts +++ b/packages/strings/src/units.ts @@ -1,5 +1,4 @@ -import { memoizeJ } from "@thi.ng/memoize/memoizej"; - +import { memoizeJ } from "@thi.ng/memoize"; import { Stringer } from "./api"; export const units: (exp: [number, string, number?][], base: string, prec?: number) => Stringer = diff --git a/packages/strings/src/wrap.ts b/packages/strings/src/wrap.ts index 95df096538..3fc08f4af4 100644 --- a/packages/strings/src/wrap.ts +++ b/packages/strings/src/wrap.ts @@ -1,5 +1,4 @@ -import { memoizeJ } from "@thi.ng/memoize/memoizej"; - +import { memoizeJ } from "@thi.ng/memoize"; import { Stringer } from "./api"; /** diff --git a/packages/strings/test/tsconfig.json b/packages/strings/test/tsconfig.json index bcf29ace54..2c9c12a650 100644 --- a/packages/strings/test/tsconfig.json +++ b/packages/strings/test/tsconfig.json @@ -1,10 +1,11 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", "../src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/strings/tsconfig.json b/packages/strings/tsconfig.json index bd6481a5a6..bcf03f18b4 100644 --- a/packages/strings/tsconfig.json +++ b/packages/strings/tsconfig.json @@ -1,9 +1,11 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/transducers-fsm/.npmignore b/packages/transducers-fsm/.npmignore index d703bda97a..67d0c55714 100644 --- a/packages/transducers-fsm/.npmignore +++ b/packages/transducers-fsm/.npmignore @@ -1,10 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/transducers-fsm/CHANGELOG.md b/packages/transducers-fsm/CHANGELOG.md index 883ac11343..f2580daaaf 100644 --- a/packages/transducers-fsm/CHANGELOG.md +++ b/packages/transducers-fsm/CHANGELOG.md @@ -3,6 +3,28 @@ 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/transducers-fsm@0.2.36...@thi.ng/transducers-fsm@1.0.0) (2019-01-21) + + +### Build System + +* update package build scripts & outputs, imports in ~50 packages ([b54b703](https://github.com/thi-ng/umbrella/commit/b54b703)) + + +### BREAKING CHANGES + +* enabled multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols. + + + + + ## [0.2.36](https://github.com/thi-ng/umbrella/compare/@thi.ng/transducers-fsm@0.2.35...@thi.ng/transducers-fsm@0.2.36) (2019-01-02) **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 0f5c1a3b47..20326b8274 100644 --- a/packages/transducers-fsm/package.json +++ b/packages/transducers-fsm/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/transducers-fsm", - "version": "0.2.36", + "version": "1.0.0", "description": "Transducer-based Finite State Machine transformer", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,24 +14,26 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn run clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module transducersFsm api transducers", + "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 run build && yarn publish --access public", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/api": "^4.2.4", - "@thi.ng/transducers": "^2.3.2" + "@thi.ng/api": "^5.0.0", + "@thi.ng/transducers": "^3.0.0" }, "keywords": [ "ES6", @@ -40,5 +44,6 @@ ], "publishConfig": { "access": "public" - } + }, + "sideEffects": false } diff --git a/packages/transducers-fsm/src/index.ts b/packages/transducers-fsm/src/index.ts index 08cef2db2d..32f024b832 100644 --- a/packages/transducers-fsm/src/index.ts +++ b/packages/transducers-fsm/src/index.ts @@ -1,8 +1,12 @@ -import { IObjectOf } from "@thi.ng/api/api"; -import { Reducer, Transducer } from "@thi.ng/transducers/api"; -import { comp } from "@thi.ng/transducers/func/comp"; -import { compR } from "@thi.ng/transducers/func/compr"; -import { ensureReduced, isReduced } from "@thi.ng/transducers/reduced"; +import { IObjectOf } from "@thi.ng/api"; +import { + comp, + compR, + ensureReduced, + isReduced, + Reducer, + Transducer +} from "@thi.ng/transducers"; export interface FSMState { state: PropertyKey; @@ -92,26 +96,26 @@ export interface FSMOpts { * * @param opts */ -export function fsm(opts: FSMOpts): Transducer { - return 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; +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; + } } } - } - 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/tsconfig.json b/packages/transducers-fsm/test/tsconfig.json index bcf29ace54..2c9c12a650 100644 --- a/packages/transducers-fsm/test/tsconfig.json +++ b/packages/transducers-fsm/test/tsconfig.json @@ -1,10 +1,11 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", "../src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/transducers-fsm/tsconfig.json b/packages/transducers-fsm/tsconfig.json index bd6481a5a6..bcf03f18b4 100644 --- a/packages/transducers-fsm/tsconfig.json +++ b/packages/transducers-fsm/tsconfig.json @@ -1,9 +1,11 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/transducers-hdom/.npmignore b/packages/transducers-hdom/.npmignore index d703bda97a..67d0c55714 100644 --- a/packages/transducers-hdom/.npmignore +++ b/packages/transducers-hdom/.npmignore @@ -1,10 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/transducers-hdom/CHANGELOG.md b/packages/transducers-hdom/CHANGELOG.md index 13d4c60f6f..9a8944f8a2 100644 --- a/packages/transducers-hdom/CHANGELOG.md +++ b/packages/transducers-hdom/CHANGELOG.md @@ -3,6 +3,36 @@ 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/transducers-hdom@1.2.16...@thi.ng/transducers-hdom@2.0.0) (2019-01-21) + + +### Build System + +* update package build scripts & outputs, imports in ~50 packages ([b54b703](https://github.com/thi-ng/umbrella/commit/b54b703)) +* update package scripts, outputs, imports in remaining packages ([f912a84](https://github.com/thi-ng/umbrella/commit/f912a84)) + + +### BREAKING CHANGES + +* enable multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols +* enabled multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols. + + + + + ## [1.2.16](https://github.com/thi-ng/umbrella/compare/@thi.ng/transducers-hdom@1.2.15...@thi.ng/transducers-hdom@1.2.16) (2019-01-02) **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 5ed805ae74..b54c177d7f 100644 --- a/packages/transducers-hdom/package.json +++ b/packages/transducers-hdom/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/transducers-hdom", - "version": "1.2.16", + "version": "2.0.0", "description": "Transducer based UI updater for @thi.ng/hdom", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,25 +14,27 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn run clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module transducersHdom hdom hiccup transducers", + "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 run build && yarn publish --access public", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/checks": "^1.5.14", - "@thi.ng/hdom": "^6.1.0", - "@thi.ng/transducers": "^2.3.2" + "@thi.ng/hdom": "^7.0.0", + "@thi.ng/hiccup": "^3.0.0", + "@thi.ng/transducers": "^3.0.0" }, "keywords": [ "diff", @@ -44,5 +48,6 @@ ], "publishConfig": { "access": "public" - } + }, + "sideEffects": false } diff --git a/packages/transducers-hdom/src/index.ts b/packages/transducers-hdom/src/index.ts index a7fcbb037d..2174571045 100644 --- a/packages/transducers-hdom/src/index.ts +++ b/packages/transducers-hdom/src/index.ts @@ -1,10 +1,11 @@ -import { HDOMImplementation, HDOMOpts } from "@thi.ng/hdom/api"; -import { DEFAULT_IMPL } from "@thi.ng/hdom/default"; -import { resolveRoot } from "@thi.ng/hdom/utils"; -import { derefContext } from "@thi.ng/hiccup/deref"; -import { Transducer } from "@thi.ng/transducers/api"; -import { reducer } from "@thi.ng/transducers/reduce"; -import { scan } from "@thi.ng/transducers/xform/scan"; +import { + DEFAULT_IMPL, + HDOMImplementation, + HDOMOpts, + resolveRoot +} from "@thi.ng/hdom"; +import { derefContext } from "@thi.ng/hiccup"; +import { scan, Transducer } from "@thi.ng/transducers"; /** * Side-effecting & stateful transducer which receives @thi.ng/hdom @@ -40,27 +41,31 @@ import { scan } from "@thi.ng/transducers/xform/scan"; * * @param opts hdom options */ -export const updateDOM = - (opts: Partial = {}, impl: HDOMImplementation = DEFAULT_IMPL): Transducer => { - const _opts = { root: "app", ...opts }; - const root = resolveRoot(_opts.root, impl); - return scan( - reducer( - () => [], - (prev, curr) => { - _opts.ctx = derefContext(opts.ctx, _opts.autoDerefKeys); - curr = impl.normalizeTree(_opts, curr); - if (curr != null) { - if (_opts.hydrate) { - impl.hydrateTree(_opts, root, curr); - _opts.hydrate = false; - } else { - impl.diffTree(_opts, root, prev, curr, 0); - } - return curr; +export const updateDOM = ( + opts: Partial = {}, + impl: HDOMImplementation = DEFAULT_IMPL +): Transducer => { + + const _opts = { root: "app", ...opts }; + const root = resolveRoot(_opts.root, impl); + return scan( + [ + () => [], + (acc) => acc, + (prev, curr) => { + _opts.ctx = derefContext(opts.ctx, _opts.autoDerefKeys); + curr = impl.normalizeTree(_opts, curr); + if (curr != null) { + if (_opts.hydrate) { + impl.hydrateTree(_opts, root, curr); + _opts.hydrate = false; + } else { + impl.diffTree(_opts, root, prev, curr, 0); } - return prev; + return curr; } - ) - ); - }; + return prev; + } + ] + ); +}; diff --git a/packages/transducers-hdom/test/tsconfig.json b/packages/transducers-hdom/test/tsconfig.json index bcf29ace54..2c9c12a650 100644 --- a/packages/transducers-hdom/test/tsconfig.json +++ b/packages/transducers-hdom/test/tsconfig.json @@ -1,10 +1,11 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", "../src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/transducers-hdom/tsconfig.json b/packages/transducers-hdom/tsconfig.json index bd6481a5a6..bcf03f18b4 100644 --- a/packages/transducers-hdom/tsconfig.json +++ b/packages/transducers-hdom/tsconfig.json @@ -1,9 +1,11 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/transducers-stats/.npmignore b/packages/transducers-stats/.npmignore index d703bda97a..67d0c55714 100644 --- a/packages/transducers-stats/.npmignore +++ b/packages/transducers-stats/.npmignore @@ -1,10 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/transducers-stats/CHANGELOG.md b/packages/transducers-stats/CHANGELOG.md index f0f70418fb..e01918bd68 100644 --- a/packages/transducers-stats/CHANGELOG.md +++ b/packages/transducers-stats/CHANGELOG.md @@ -3,6 +3,28 @@ 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/transducers-stats@0.4.23...@thi.ng/transducers-stats@1.0.0) (2019-01-21) + + +### Build System + +* update package build scripts & outputs, imports in ~50 packages ([b54b703](https://github.com/thi-ng/umbrella/commit/b54b703)) + + +### BREAKING CHANGES + +* enabled multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols. + + + + + ## [0.4.23](https://github.com/thi-ng/umbrella/compare/@thi.ng/transducers-stats@0.4.22...@thi.ng/transducers-stats@0.4.23) (2019-01-02) **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 537de88475..71af756db3 100644 --- a/packages/transducers-stats/package.json +++ b/packages/transducers-stats/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/transducers-stats", - "version": "0.4.23", + "version": "1.0.0", "description": "Transducers for statistical / technical analysis", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,25 +14,28 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn run clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module transducersStats checks dcons errors transducers", + "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 run build && yarn publish --access public", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/dcons": "^1.1.23", - "@thi.ng/errors": "^0.1.12", - "@thi.ng/transducers": "^2.3.2" + "@thi.ng/checks": "^2.0.0", + "@thi.ng/dcons": "^2.0.0", + "@thi.ng/errors": "^1.0.0", + "@thi.ng/transducers": "^3.0.0" }, "keywords": [ "ES6", @@ -38,5 +43,6 @@ ], "publishConfig": { "access": "public" - } + }, + "sideEffects": false } diff --git a/packages/transducers-stats/src/bollinger.ts b/packages/transducers-stats/src/bollinger.ts index 944547f04e..830362fe96 100644 --- a/packages/transducers-stats/src/bollinger.ts +++ b/packages/transducers-stats/src/bollinger.ts @@ -1,11 +1,12 @@ -import { Transducer } from "@thi.ng/transducers/api"; -import { $iter } from "@thi.ng/transducers/iterator"; -import { comp } from "@thi.ng/transducers/func/comp"; -import { drop } from "@thi.ng/transducers/xform/drop"; -import { map } from "@thi.ng/transducers/xform/map"; -import { multiplex } from "@thi.ng/transducers/xform/multiplex"; -import { partition } from "@thi.ng/transducers/xform/partition"; - +import { + $iter, + comp, + drop, + map, + multiplex, + partition, + Transducer +} from "@thi.ng/transducers"; import { mse } from "./mse"; import { sma } from "./sma"; diff --git a/packages/transducers-stats/src/donchian.ts b/packages/transducers-stats/src/donchian.ts index 10dc29094c..460e16494e 100644 --- a/packages/transducers-stats/src/donchian.ts +++ b/packages/transducers-stats/src/donchian.ts @@ -1,9 +1,10 @@ -import { Transducer } from "@thi.ng/transducers/api"; -import { comp } from "@thi.ng/transducers/func/comp"; -import { iterator } from "@thi.ng/transducers/iterator"; -import { map } from "@thi.ng/transducers/xform/map"; -import { partition } from "@thi.ng/transducers/xform/partition"; - +import { + comp, + iterator, + map, + partition, + Transducer +} from "@thi.ng/transducers"; import { bounds } from "./bounds"; /** diff --git a/packages/transducers-stats/src/ema.ts b/packages/transducers-stats/src/ema.ts index 005e5f62fa..406e1507a3 100644 --- a/packages/transducers-stats/src/ema.ts +++ b/packages/transducers-stats/src/ema.ts @@ -1,7 +1,10 @@ -import { illegalArgs } from "@thi.ng/errors/illegal-arguments"; -import { Reducer, Transducer } from "@thi.ng/transducers/api"; -import { compR } from "@thi.ng/transducers/func/compr"; -import { iterator1 } from "@thi.ng/transducers/iterator"; +import { illegalArgs } from "@thi.ng/errors"; +import { + compR, + iterator1, + Reducer, + Transducer +} from "@thi.ng/transducers"; /** * https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average diff --git a/packages/transducers-stats/src/hma.ts b/packages/transducers-stats/src/hma.ts index ab70bd4282..4c80ab79a7 100644 --- a/packages/transducers-stats/src/hma.ts +++ b/packages/transducers-stats/src/hma.ts @@ -1,10 +1,11 @@ -import { Transducer } from "@thi.ng/transducers/api"; -import { comp } from "@thi.ng/transducers/func/comp"; -import { iterator1 } from "@thi.ng/transducers/iterator"; -import { drop } from "@thi.ng/transducers/xform/drop"; -import { map } from "@thi.ng/transducers/xform/map"; -import { multiplex } from "@thi.ng/transducers/xform/multiplex"; - +import { + comp, + drop, + iterator1, + map, + multiplex, + Transducer +} from "@thi.ng/transducers"; import { wma } from "./wma"; /** diff --git a/packages/transducers-stats/src/macd.ts b/packages/transducers-stats/src/macd.ts index c6206d4eb7..f98989d7da 100644 --- a/packages/transducers-stats/src/macd.ts +++ b/packages/transducers-stats/src/macd.ts @@ -1,8 +1,10 @@ -import { Reducer, Transducer } from "@thi.ng/transducers/api"; -import { compR } from "@thi.ng/transducers/func/compr"; -import { $iter } from "@thi.ng/transducers/iterator"; -import { step } from "@thi.ng/transducers/step"; - +import { + $iter, + compR, + Reducer, + step, + Transducer +} from "@thi.ng/transducers"; import { ema } from "./ema"; export interface MACD { diff --git a/packages/transducers-stats/src/momentum.ts b/packages/transducers-stats/src/momentum.ts index 5273474dad..492fc7146e 100644 --- a/packages/transducers-stats/src/momentum.ts +++ b/packages/transducers-stats/src/momentum.ts @@ -1,8 +1,11 @@ import { DCons } from "@thi.ng/dcons"; -import { illegalArgs } from "@thi.ng/errors/illegal-arguments"; -import { Reducer, Transducer } from "@thi.ng/transducers/api"; -import { compR } from "@thi.ng/transducers/func/compr"; -import { iterator1 } from "@thi.ng/transducers/iterator"; +import { illegalArgs } from "@thi.ng/errors"; +import { + compR, + iterator1, + Reducer, + Transducer +} from "@thi.ng/transducers"; /** * https://en.wikipedia.org/wiki/Momentum_(technical_analysis) diff --git a/packages/transducers-stats/src/roc.ts b/packages/transducers-stats/src/roc.ts index b20dbf464a..18ae1fea0a 100644 --- a/packages/transducers-stats/src/roc.ts +++ b/packages/transducers-stats/src/roc.ts @@ -1,8 +1,11 @@ import { DCons } from "@thi.ng/dcons"; -import { illegalArgs } from "@thi.ng/errors/illegal-arguments"; -import { Reducer, Transducer } from "@thi.ng/transducers/api"; -import { compR } from "@thi.ng/transducers/func/compr"; -import { iterator1 } from "@thi.ng/transducers/iterator"; +import { illegalArgs } from "@thi.ng/errors"; +import { + compR, + iterator1, + Reducer, + Transducer +} from "@thi.ng/transducers"; /** * Rate of change. diff --git a/packages/transducers-stats/src/rsi.ts b/packages/transducers-stats/src/rsi.ts index 0f6fb8e38d..3b1c9427b6 100644 --- a/packages/transducers-stats/src/rsi.ts +++ b/packages/transducers-stats/src/rsi.ts @@ -1,10 +1,11 @@ -import { Transducer } from "@thi.ng/transducers/api"; -import { comp } from "@thi.ng/transducers/func/comp"; -import { iterator1 } from "@thi.ng/transducers/iterator"; -import { drop } from "@thi.ng/transducers/xform/drop"; -import { map } from "@thi.ng/transducers/xform/map"; -import { multiplex } from "@thi.ng/transducers/xform/multiplex"; - +import { + comp, + drop, + iterator1, + map, + multiplex, + Transducer +} from "@thi.ng/transducers"; import { momentum } from "./momentum"; import { sma } from "./sma"; diff --git a/packages/transducers-stats/src/sd.ts b/packages/transducers-stats/src/sd.ts index 7c3ae0df08..99decec5ef 100644 --- a/packages/transducers-stats/src/sd.ts +++ b/packages/transducers-stats/src/sd.ts @@ -1,13 +1,14 @@ -import { Transducer } from "@thi.ng/transducers/api"; -import { comp } from "@thi.ng/transducers/func/comp"; -import { drop } from "@thi.ng/transducers/xform/drop"; -import { map } from "@thi.ng/transducers/xform/map"; -import { multiplex } from "@thi.ng/transducers/xform/multiplex"; -import { partition } from "@thi.ng/transducers/xform/partition"; - +import { + $iter, + comp, + drop, + map, + multiplex, + partition, + Transducer +} from "@thi.ng/transducers"; import { mse } from "./mse"; import { sma } from "./sma"; -import { $iter } from "@thi.ng/transducers/iterator"; /** * Moving standard deviation, calculates mean square error to SMA and diff --git a/packages/transducers-stats/src/sma.ts b/packages/transducers-stats/src/sma.ts index b76353accd..d824082acf 100644 --- a/packages/transducers-stats/src/sma.ts +++ b/packages/transducers-stats/src/sma.ts @@ -1,8 +1,11 @@ import { DCons } from "@thi.ng/dcons"; -import { illegalArgs } from "@thi.ng/errors/illegal-arguments"; -import { Reducer, Transducer } from "@thi.ng/transducers/api"; -import { compR } from "@thi.ng/transducers/func/compr"; -import { iterator1 } from "@thi.ng/transducers/iterator"; +import { illegalArgs } from "@thi.ng/errors"; +import { + compR, + iterator1, + Reducer, + Transducer +} from "@thi.ng/transducers"; /** * Like @thi.ng/transducers `movingAverage`, but using more efficient diff --git a/packages/transducers-stats/src/stochastic.ts b/packages/transducers-stats/src/stochastic.ts index e3c326de89..27d7edcf0e 100644 --- a/packages/transducers-stats/src/stochastic.ts +++ b/packages/transducers-stats/src/stochastic.ts @@ -1,8 +1,10 @@ -import { Reducer, Transducer } from "@thi.ng/transducers/api"; -import { compR } from "@thi.ng/transducers/func/compr"; -import { $iter } from "@thi.ng/transducers/iterator"; -import { step } from "@thi.ng/transducers/step"; - +import { + $iter, + compR, + Reducer, + step, + Transducer +} from "@thi.ng/transducers"; import { donchian } from "./donchian"; import { sma } from "./sma"; diff --git a/packages/transducers-stats/src/trix.ts b/packages/transducers-stats/src/trix.ts index 15222027c8..a66ea94467 100644 --- a/packages/transducers-stats/src/trix.ts +++ b/packages/transducers-stats/src/trix.ts @@ -1,7 +1,4 @@ -import { Transducer } from "@thi.ng/transducers/api"; -import { comp } from "@thi.ng/transducers/func/comp"; -import { iterator1 } from "@thi.ng/transducers/iterator"; - +import { comp, iterator1, Transducer } from "@thi.ng/transducers"; import { ema } from "./ema"; import { roc } from "./roc"; diff --git a/packages/transducers-stats/src/wma.ts b/packages/transducers-stats/src/wma.ts index 8b5c5dea53..93bef142de 100644 --- a/packages/transducers-stats/src/wma.ts +++ b/packages/transducers-stats/src/wma.ts @@ -1,11 +1,12 @@ -import { isNumber } from "@thi.ng/checks/is-number"; -import { Transducer } from "@thi.ng/transducers/api"; -import { comp } from "@thi.ng/transducers/func/comp"; -import { range } from "@thi.ng/transducers/iter/range"; -import { iterator1 } from "@thi.ng/transducers/iterator"; -import { map } from "@thi.ng/transducers/xform/map"; -import { partition } from "@thi.ng/transducers/xform/partition"; - +import { isNumber } from "@thi.ng/checks"; +import { + comp, + iterator1, + map, + partition, + range, + Transducer +} from "@thi.ng/transducers"; import { dot } from "./dot"; /** diff --git a/packages/transducers-stats/test/tsconfig.json b/packages/transducers-stats/test/tsconfig.json index bcf29ace54..2c9c12a650 100644 --- a/packages/transducers-stats/test/tsconfig.json +++ b/packages/transducers-stats/test/tsconfig.json @@ -1,10 +1,11 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", "../src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/transducers-stats/tsconfig.json b/packages/transducers-stats/tsconfig.json index bd6481a5a6..bcf03f18b4 100644 --- a/packages/transducers-stats/tsconfig.json +++ b/packages/transducers-stats/tsconfig.json @@ -1,9 +1,11 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/transducers/.npmignore b/packages/transducers/.npmignore index d703bda97a..67d0c55714 100644 --- a/packages/transducers/.npmignore +++ b/packages/transducers/.npmignore @@ -1,10 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/transducers/CHANGELOG.md b/packages/transducers/CHANGELOG.md index 2b7203f00c..af434166ff 100644 --- a/packages/transducers/CHANGELOG.md +++ b/packages/transducers/CHANGELOG.md @@ -3,6 +3,33 @@ 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/transducers@2.3.2...@thi.ng/transducers@3.0.0) (2019-01-21) + + +### Bug Fixes + +* **transducers:** update juxt re-export ([a894a24](https://github.com/thi-ng/umbrella/commit/a894a24)) + + +### Build System + +* update package build scripts & outputs, imports in ~50 packages ([b54b703](https://github.com/thi-ng/umbrella/commit/b54b703)) + + +### BREAKING CHANGES + +* enabled multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols. + + + + + ## [2.3.2](https://github.com/thi-ng/umbrella/compare/@thi.ng/transducers@2.3.1...@thi.ng/transducers@2.3.2) (2019-01-02) diff --git a/packages/transducers/README.md b/packages/transducers/README.md index 98958bbda3..87a4da4462 100644 --- a/packages/transducers/README.md +++ b/packages/transducers/README.md @@ -110,16 +110,7 @@ purposes full module re-exports are defined. import * as tx from "@thi.ng/transducers"; // selective / single function imports -import { transduce } from "@thi.ng/transducers/transduce"; - -// all transducers are under the /xform import path -import { map } from "@thi.ng/transducers/xform/map"; - -// all reducers are under the /rfn import path -import { push } from "@thi.ng/transducers/rfn/push"; - -// all iterators are under the /iter import path -import { range } from "@thi.ng/transducers/iter/range"; +import { transduce } from "@thi.ng/transducers"; ``` ### Basic usage patterns diff --git a/packages/transducers/package.json b/packages/transducers/package.json index 610db1a276..3f641ce017 100644 --- a/packages/transducers/package.json +++ b/packages/transducers/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/transducers", - "version": "2.3.2", + "version": "3.0.0", "description": "Lightweight transducer implementations for ES6 / TypeScript", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,31 +14,36 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc func iter rfn xform", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module transducers api checks compare compose equiv errors strings", + "test": "rimraf build && tsc -p test/tsconfig.json && nyc mocha build/test/*.js", + "clean": "rimraf *.js *.d.ts .nyc_output build coverage doc lib func iter rfn xform", "cover": "yarn test && nyc report --reporter=lcov", "doc": "node_modules/.bin/typedoc --mode modules --out doc src", - "pub": "yarn build && yarn publish --access public", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/api": "^4.2.4", - "@thi.ng/checks": "^1.5.14", - "@thi.ng/compare": "^0.1.12", - "@thi.ng/compose": "^0.3.0", - "@thi.ng/equiv": "^0.1.15", - "@thi.ng/errors": "^0.1.12", - "@thi.ng/strings": "^0.7.1" + "@thi.ng/api": "^5.0.0", + "@thi.ng/checks": "^2.0.0", + "@thi.ng/compare": "^1.0.0", + "@thi.ng/compose": "^1.0.0", + "@thi.ng/equiv": "^1.0.0", + "@thi.ng/errors": "^1.0.0", + "@thi.ng/strings": "^1.0.0" }, "keywords": [ + "array", + "composition", + "data", "ES6", "functional", "generators", @@ -49,5 +56,6 @@ ], "publishConfig": { "access": "public" - } + }, + "sideEffects": false } diff --git a/packages/transducers/src/api.ts b/packages/transducers/src/api.ts index b6265e275a..22eed2828c 100644 --- a/packages/transducers/src/api.ts +++ b/packages/transducers/src/api.ts @@ -1,4 +1,4 @@ -import { Comparator, Fn, IObjectOf } from "@thi.ng/api/api"; +import { Comparator, Fn, IObjectOf } from "@thi.ng/api"; import { Reduced } from "./reduced"; diff --git a/packages/transducers/src/func/binary-search.ts b/packages/transducers/src/func/binary-search.ts index 577514154d..1e0086b713 100644 --- a/packages/transducers/src/func/binary-search.ts +++ b/packages/transducers/src/func/binary-search.ts @@ -1,4 +1,4 @@ -import { Comparator } from "@thi.ng/api/api"; +import { Comparator, Fn } from "@thi.ng/api"; /** * Returns the supposed index of `x` in pre-sorted array-like collection @@ -12,7 +12,12 @@ import { Comparator } from "@thi.ng/api/api"; * @param x * @returns index of `x`, else `-index` if item could not be found */ -export function binarySearch(arr: ArrayLike, key: (x: A) => B, cmp: Comparator, x: A) { +export const binarySearch = ( + arr: ArrayLike, + key: Fn, + cmp: Comparator, + x: A +) => { const kx = key(x); let low = 0; let high = arr.length - 1; @@ -28,4 +33,4 @@ export function binarySearch(arr: ArrayLike, key: (x: A) => B, cmp: Com } } return -low; -} +}; diff --git a/packages/transducers/src/func/comp.ts b/packages/transducers/src/func/comp.ts index 8e17710c1c..5f14212095 100644 --- a/packages/transducers/src/func/comp.ts +++ b/packages/transducers/src/func/comp.ts @@ -1,5 +1,4 @@ -import { comp as _comp } from "@thi.ng/compose/comp"; - +import { comp as _comp } from "@thi.ng/compose"; import { Transducer } from "../api"; export function comp(a: Transducer): Transducer; diff --git a/packages/transducers/src/func/compr.ts b/packages/transducers/src/func/compr.ts index aa77db09e4..6fb54a53b6 100644 --- a/packages/transducers/src/func/compr.ts +++ b/packages/transducers/src/func/compr.ts @@ -22,6 +22,6 @@ import { Reduced } from "../reduced"; * @param rfn * @param fn */ -export function compR(rfn: Reducer, fn: (acc: A, x: C) => A | Reduced) { - return >[rfn[0], rfn[1], fn]; -} +export const compR = + (rfn: Reducer, fn: (acc: A, x: C) => A | Reduced): Reducer => + [rfn[0], rfn[1], fn]; diff --git a/packages/transducers/src/func/constantly.ts b/packages/transducers/src/func/constantly.ts index dfd4499078..514541cc8d 100644 --- a/packages/transducers/src/func/constantly.ts +++ b/packages/transducers/src/func/constantly.ts @@ -1,3 +1,2 @@ -export function constantly(x: T): (...args: any[]) => T { - return () => x; -} +export const constantly = + (x: T): (...args: any[]) => T => () => x; diff --git a/packages/transducers/src/func/deep-transform.ts b/packages/transducers/src/func/deep-transform.ts index 12771c0450..b2fa9e69a6 100644 --- a/packages/transducers/src/func/deep-transform.ts +++ b/packages/transducers/src/func/deep-transform.ts @@ -1,5 +1,4 @@ -import { isFunction } from "@thi.ng/checks/is-function"; - +import { isFunction } from "@thi.ng/checks"; import { TransformSpec } from "../api"; /** @@ -63,19 +62,20 @@ import { TransformSpec } from "../api"; * * @param spec transformation spec */ -export function deepTransform(spec: TransformSpec): (x: any) => any { - if (isFunction(spec)) { - return spec; - } - const mapfns = Object.keys(spec[1] || {}).reduce( - (acc, k) => (acc[k] = deepTransform((spec)[1][k]), acc), - {} - ); - return (x) => { - const res = { ...x }; - for (let k in mapfns) { - res[k] = mapfns[k](res[k]); +export const deepTransform = + (spec: TransformSpec): (x: any) => any => { + if (isFunction(spec)) { + return spec; } - return spec[0](res); + const mapfns = Object.keys(spec[1] || {}).reduce( + (acc, k) => (acc[k] = deepTransform((spec)[1][k]), acc), + {} + ); + return (x) => { + const res = { ...x }; + for (let k in mapfns) { + res[k] = mapfns[k](res[k]); + } + return spec[0](res); + }; }; -} diff --git a/packages/transducers/src/func/delay.ts b/packages/transducers/src/func/delay.ts index 274d61cb04..c276804747 100644 --- a/packages/transducers/src/func/delay.ts +++ b/packages/transducers/src/func/delay.ts @@ -1,3 +1,3 @@ -export function delay(x: T, t: number) { - return new Promise((resolve) => setTimeout(() => resolve(x), t)); -} +export const delay = + (x: T, t: number) => + new Promise((resolve) => setTimeout(() => resolve(x), t)); diff --git a/packages/transducers/src/func/ensure-array.ts b/packages/transducers/src/func/ensure-array.ts index 5928b40a58..0de070f414 100644 --- a/packages/transducers/src/func/ensure-array.ts +++ b/packages/transducers/src/func/ensure-array.ts @@ -1,5 +1,4 @@ -import { isArray } from "@thi.ng/checks/is-array"; -import { isArrayLike } from "@thi.ng/checks/is-arraylike"; +import { isArray, isArrayLike } from "@thi.ng/checks"; import { ensureIterable } from "./ensure-iterable"; /** @@ -10,10 +9,10 @@ import { ensureIterable } from "./ensure-iterable"; * * @param x */ -export function ensureArray(x: any): any[] { - return isArray(x) ? x : [...ensureIterable(x)]; -} +export const ensureArray = + (x: any): any[] => + isArray(x) ? x : [...ensureIterable(x)]; -export function ensureArrayLike(x: any): ArrayLike { - return isArrayLike(x) ? x : [...ensureIterable(x)]; -} +export const ensureArrayLike = + (x: any): ArrayLike => + isArrayLike(x) ? x : [...ensureIterable(x)]; diff --git a/packages/transducers/src/func/ensure-iterable.ts b/packages/transducers/src/func/ensure-iterable.ts index f481c96398..dd9acf06c5 100644 --- a/packages/transducers/src/func/ensure-iterable.ts +++ b/packages/transducers/src/func/ensure-iterable.ts @@ -1,8 +1,9 @@ -import { illegalArgs } from "@thi.ng/errors/illegal-arguments"; +import { illegalArgs } from "@thi.ng/errors"; -export function ensureIterable(x: any): IterableIterator { - if (!(x != null && x[Symbol.iterator])) { - illegalArgs(`value is not iterable: ${x}`); - } - return x; -} +export const ensureIterable = + (x: any): IterableIterator => { + if (!(x != null && x[Symbol.iterator])) { + illegalArgs(`value is not iterable: ${x}`); + } + return x; + }; diff --git a/packages/transducers/src/func/even.ts b/packages/transducers/src/func/even.ts index 9d30160522..4fecc9bc95 100644 --- a/packages/transducers/src/func/even.ts +++ b/packages/transducers/src/func/even.ts @@ -1 +1 @@ -export { isEven as even } from "@thi.ng/checks/is-even"; +export { isEven as even } from "@thi.ng/checks"; diff --git a/packages/transducers/src/func/fuzzy-match.ts b/packages/transducers/src/func/fuzzy-match.ts index aa9f557cca..d9476ff966 100644 --- a/packages/transducers/src/func/fuzzy-match.ts +++ b/packages/transducers/src/func/fuzzy-match.ts @@ -1,4 +1,4 @@ -import { Predicate2 } from "@thi.ng/api/api"; +import { Predicate2 } from "@thi.ng/api"; import { equiv } from "@thi.ng/equiv"; /** @@ -15,7 +15,11 @@ import { equiv } from "@thi.ng/equiv"; * @param query * @param eq */ -export function fuzzyMatch(domain: ArrayLike, query: ArrayLike, eq: Predicate2 = equiv) { +export const fuzzyMatch = ( + domain: ArrayLike, + query: ArrayLike, + eq: Predicate2 = equiv +) => { const nd = domain.length; const nq = query.length; if (nq > nd) { @@ -35,4 +39,4 @@ export function fuzzyMatch(domain: ArrayLike, query: ArrayLike, eq: Pre return false; } return true; -} +}; diff --git a/packages/transducers/src/func/hex.ts b/packages/transducers/src/func/hex.ts index f0c60ec00d..c2d5d6eb94 100644 --- a/packages/transducers/src/func/hex.ts +++ b/packages/transducers/src/func/hex.ts @@ -1,5 +1,4 @@ -import { Stringer } from "@thi.ng/strings/api"; -import { radix } from "@thi.ng/strings/radix"; +import { radix, Stringer } from "@thi.ng/strings"; /** * @deprecated use thi.ng/strings `radix()` instead diff --git a/packages/transducers/src/func/identity.ts b/packages/transducers/src/func/identity.ts index 2eae1585ce..74efbc8cf1 100644 --- a/packages/transducers/src/func/identity.ts +++ b/packages/transducers/src/func/identity.ts @@ -1 +1 @@ -export function identity(x: T) { return x; } +export const identity = (x: T) => x; diff --git a/packages/transducers/src/func/juxt.ts b/packages/transducers/src/func/juxt.ts index 6c9a09f973..00b819d738 100644 --- a/packages/transducers/src/func/juxt.ts +++ b/packages/transducers/src/func/juxt.ts @@ -1 +1,3 @@ -export * from "@thi.ng/compose/juxt"; +import { juxt as _juxt } from "@thi.ng/compose"; + +export const juxt = _juxt; diff --git a/packages/transducers/src/func/key-selector.ts b/packages/transducers/src/func/key-selector.ts index e7720fa7ff..f9f99792d5 100644 --- a/packages/transducers/src/func/key-selector.ts +++ b/packages/transducers/src/func/key-selector.ts @@ -1,5 +1,5 @@ import { renamer } from "./renamer"; -export function keySelector(keys: PropertyKey[]) { - return renamer(keys.reduce((acc, x) => (acc[x] = x, acc), {})); -} +export const keySelector = + (keys: PropertyKey[]) => + renamer(keys.reduce((acc, x) => (acc[x] = x, acc), {})); diff --git a/packages/transducers/src/func/lookup.ts b/packages/transducers/src/func/lookup.ts index 9adbd24da2..dd6dec1eda 100644 --- a/packages/transducers/src/func/lookup.ts +++ b/packages/transducers/src/func/lookup.ts @@ -9,9 +9,8 @@ * * @param src source data */ -export function lookup1d(src: T[]) { - return (i: number) => src[i]; -} +export const lookup1d = + (src: T[]) => (i: number) => src[i]; /** * Returns function accepting a single `[x, y]` index tuple, @@ -28,9 +27,9 @@ export function lookup1d(src: T[]) { * @param src source data * @param width number of items along X (columns) */ -export function lookup2d(src: T[], width: number) { - return (i: number[]) => src[i[0] + i[1] * width]; -} +export const lookup2d = + (src: T[], width: number) => + (i: number[]) => src[i[0] + i[1] * width]; /** * Same as `lookup2d()`, but for 3D data. The index ordering of the @@ -41,7 +40,8 @@ export function lookup2d(src: T[], width: number) { * @param width number of items along X (columns) * @param height number of items along Y (rows) */ -export function lookup3d(src: T[], width: number, height: number) { - const stridez = width * height; - return (i: number[]) => src[i[0] + i[1] * width + i[2] * stridez]; -} +export const lookup3d = + (src: T[], width: number, height: number) => { + const stridez = width * height; + return (i: number[]) => src[i[0] + i[1] * width + i[2] * stridez]; + }; diff --git a/packages/transducers/src/func/odd.ts b/packages/transducers/src/func/odd.ts index f2914aff55..ab3065656e 100644 --- a/packages/transducers/src/func/odd.ts +++ b/packages/transducers/src/func/odd.ts @@ -1 +1 @@ -export { isOdd as odd } from "@thi.ng/checks/is-odd"; +export { isOdd as odd } from "@thi.ng/checks"; diff --git a/packages/transducers/src/func/peek.ts b/packages/transducers/src/func/peek.ts index bfae789cbb..f0c29728fe 100644 --- a/packages/transducers/src/func/peek.ts +++ b/packages/transducers/src/func/peek.ts @@ -3,6 +3,5 @@ * * @param x */ -export function peek(x: ArrayLike) { - return x[x.length - 1]; -} +export const peek = + (x: ArrayLike) => x[x.length - 1]; diff --git a/packages/transducers/src/func/random-id.ts b/packages/transducers/src/func/random-id.ts index 3aff55d031..f4901cbb38 100644 --- a/packages/transducers/src/func/random-id.ts +++ b/packages/transducers/src/func/random-id.ts @@ -18,5 +18,6 @@ import { take } from "../xform/take"; * @param prefix * @param syms */ -export const randomID = (len = 4, prefix = "", syms = "abcdefghijklmnopqrstuvwxyz") => - [prefix, ...take(len, choices(syms))].join(""); +export const randomID = + (len = 4, prefix = "", syms = "abcdefghijklmnopqrstuvwxyz") => + [prefix, ...take(len, choices(syms))].join(""); diff --git a/packages/transducers/src/func/renamer.ts b/packages/transducers/src/func/renamer.ts index ed30ac4126..1aefe1fd82 100644 --- a/packages/transducers/src/func/renamer.ts +++ b/packages/transducers/src/func/renamer.ts @@ -1,42 +1,43 @@ -import { IObjectOf } from "@thi.ng/api/api"; +import { IObjectOf } from "@thi.ng/api"; -export function renamer(kmap: IObjectOf) { - const ks = Object.keys(kmap); - const [a2, b2, c2] = ks; - const [a1, b1, c1] = ks.map((k) => kmap[k]); - switch (ks.length) { - case 3: - return (x) => { - const res: any = {}; - let v; - v = x[c1], v !== undefined && (res[c2] = v); - v = x[b1], v !== undefined && (res[b2] = v); - v = x[a1], v !== undefined && (res[a2] = v); - return res; - }; - case 2: - return (x) => { - const res: any = {}; - let v; - v = x[b1], v !== undefined && (res[b2] = v); - v = x[a1], v !== undefined && (res[a2] = v); - return res; - }; - case 1: - return (x) => { - const res: any = {}; - let v = x[a1]; - v !== undefined && (res[a2] = v); - return res; - }; - default: - return (x) => { - let k, v; - const res: any = {}; - for (let i = ks.length - 1; i >= 0; i--) { - k = ks[i], v = x[kmap[k]], v !== undefined && (res[k] = v); - } - return res; - }; - } -} +export const renamer = + (kmap: IObjectOf) => { + const ks = Object.keys(kmap); + const [a2, b2, c2] = ks; + const [a1, b1, c1] = ks.map((k) => kmap[k]); + switch (ks.length) { + case 3: + return (x) => { + const res: any = {}; + let v; + v = x[c1], v !== undefined && (res[c2] = v); + v = x[b1], v !== undefined && (res[b2] = v); + v = x[a1], v !== undefined && (res[a2] = v); + return res; + }; + case 2: + return (x) => { + const res: any = {}; + let v; + v = x[b1], v !== undefined && (res[b2] = v); + v = x[a1], v !== undefined && (res[a2] = v); + return res; + }; + case 1: + return (x) => { + const res: any = {}; + let v = x[a1]; + v !== undefined && (res[a2] = v); + return res; + }; + default: + return (x) => { + let k, v; + const res: any = {}; + for (let i = ks.length - 1; i >= 0; i--) { + k = ks[i], v = x[kmap[k]], v !== undefined && (res[k] = v); + } + return res; + }; + } + }; diff --git a/packages/transducers/src/func/shuffle.ts b/packages/transducers/src/func/shuffle.ts index 0d99287d35..9a3b355215 100644 --- a/packages/transducers/src/func/shuffle.ts +++ b/packages/transducers/src/func/shuffle.ts @@ -1,11 +1,12 @@ -export function shuffleN(buf: any[], n: number) { - const l = buf.length; - n = n < l ? n : l; - while (--n >= 0) { - const a = (Math.random() * l) | 0; - const b = (Math.random() * l) | 0; - const t = buf[a]; - buf[a] = buf[b]; - buf[b] = t; - } -} +export const shuffleN = + (buf: any[], n: number) => { + const l = buf.length; + n = n < l ? n : l; + while (--n >= 0) { + const a = (Math.random() * l) | 0; + const b = (Math.random() * l) | 0; + const t = buf[a]; + buf[a] = buf[b]; + buf[b] = t; + } + }; diff --git a/packages/transducers/src/func/swizzler.ts b/packages/transducers/src/func/swizzler.ts index 95ca29ebc2..5c368006eb 100644 --- a/packages/transducers/src/func/swizzler.ts +++ b/packages/transducers/src/func/swizzler.ts @@ -20,34 +20,35 @@ * * @param order indices */ -export function swizzler(order: string | PropertyKey[]): (x: T) => any[] { - const [a, b, c, d, e, f, g, h] = order; - switch (order.length) { - case 0: - return () => []; - case 1: - return (x) => [x[a]]; - case 2: - return (x) => [x[a], x[b]]; - case 3: - return (x) => [x[a], x[b], x[c]]; - case 4: - return (x) => [x[a], x[b], x[c], x[d]]; - case 5: - return (x) => [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]]; - case 7: - return (x) => [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]]; - default: - return (x) => { - const res = []; - for (let i = order.length - 1; i >= 0; i--) { - res[i] = x[order[i]]; - } - return res; - }; - } -} \ No newline at end of file +export const swizzler = + (order: string | PropertyKey[]): (x: T) => any[] => { + const [a, b, c, d, e, f, g, h] = order; + switch (order.length) { + case 0: + return () => []; + case 1: + return (x) => [x[a]]; + case 2: + return (x) => [x[a], x[b]]; + case 3: + return (x) => [x[a], x[b], x[c]]; + case 4: + return (x) => [x[a], x[b], x[c], x[d]]; + case 5: + return (x) => [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]]; + case 7: + return (x) => [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]]; + default: + return (x) => { + const res = []; + for (let i = order.length - 1; i >= 0; i--) { + res[i] = x[order[i]]; + } + return res; + }; + } + }; diff --git a/packages/transducers/src/func/weighted-random.ts b/packages/transducers/src/func/weighted-random.ts index 9f2dfab42a..22cc7dcc26 100644 --- a/packages/transducers/src/func/weighted-random.ts +++ b/packages/transducers/src/func/weighted-random.ts @@ -10,7 +10,10 @@ import { tuples } from "../iter/tuples"; * @param choices * @param weights */ -export function weightedRandom(choices: ArrayLike & Iterable, weights?: ArrayLike & Iterable) { +export const weightedRandom = ( + choices: ArrayLike & Iterable, + weights?: ArrayLike & Iterable +) => { const n = choices.length; const opts = [...tuples(choices, weights || repeat(1))].sort((a, b) => b[1] - a[1]); let total = 0, i, r, sum; @@ -27,4 +30,4 @@ export function weightedRandom(choices: ArrayLike & Iterable, weights?: } } }; -} \ No newline at end of file +}; diff --git a/packages/transducers/src/iter/choices.ts b/packages/transducers/src/iter/choices.ts index 9c3b9e316d..8abd5b830a 100644 --- a/packages/transducers/src/iter/choices.ts +++ b/packages/transducers/src/iter/choices.ts @@ -16,10 +16,12 @@ import { repeatedly } from "./repeatedly"; * @param choices * @param weights */ -export function choices(choices: ArrayLike & Iterable, weights?: ArrayLike & Iterable) { - return repeatedly( +export const choices = ( + choices: ArrayLike & Iterable, + weights?: ArrayLike & Iterable +) => + repeatedly( weights ? weightedRandom(choices, weights) : () => choices[(Math.random() * choices.length) | 0] ); -} diff --git a/packages/transducers/src/iter/pairs.ts b/packages/transducers/src/iter/pairs.ts index 66a44b9a25..d8cc39c265 100644 --- a/packages/transducers/src/iter/pairs.ts +++ b/packages/transducers/src/iter/pairs.ts @@ -1,4 +1,4 @@ -import { IObjectOf } from "@thi.ng/api/api"; +import { IObjectOf } from "@thi.ng/api"; export function* pairs(x: IObjectOf): IterableIterator<[string, T]> { for (let k in x) { diff --git a/packages/transducers/src/iter/permutations.ts b/packages/transducers/src/iter/permutations.ts index c0375cae68..67c7fd2c50 100644 --- a/packages/transducers/src/iter/permutations.ts +++ b/packages/transducers/src/iter/permutations.ts @@ -1,4 +1,4 @@ -import { illegalArgs } from "@thi.ng/errors/illegal-arguments"; +import { illegalArgs } from "@thi.ng/errors"; import { ensureArrayLike } from "../func/ensure-array"; import { range } from "./range"; @@ -73,14 +73,15 @@ export function* permutations(...src: any[]) { * @param m * @param offsets */ -export function permutationsN(n: number, m = n, offsets?: number[]): IterableIterator { - if (offsets && offsets.length < n) { - illegalArgs(`insufficient offsets, got ${offsets.length}, needed ${n}`); - } - const seqs = []; - while (--n >= 0) { - const o = offsets ? offsets[n] : 0; - seqs[n] = range(o, o + m); - } - return permutations.apply(null, seqs); -} +export const permutationsN = + (n: number, m = n, offsets?: number[]): IterableIterator => { + if (offsets && offsets.length < n) { + illegalArgs(`insufficient offsets, got ${offsets.length}, needed ${n}`); + } + const seqs = []; + while (--n >= 0) { + const o = offsets ? offsets[n] : 0; + seqs[n] = range(o, o + m); + } + return permutations.apply(null, seqs); + }; diff --git a/packages/transducers/src/iter/range2d.ts b/packages/transducers/src/iter/range2d.ts index c20ce2cbf2..e1ef9e799d 100644 --- a/packages/transducers/src/iter/range2d.ts +++ b/packages/transducers/src/iter/range2d.ts @@ -1,5 +1,4 @@ -import { illegalArity } from "@thi.ng/errors/illegal-arity"; - +import { illegalArity } from "@thi.ng/errors"; import { range } from "./range"; export function range2d(toX: number, toY: number): IterableIterator<[number, number]>; diff --git a/packages/transducers/src/iter/range3d.ts b/packages/transducers/src/iter/range3d.ts index 3325ed43e5..cb68fc54f2 100644 --- a/packages/transducers/src/iter/range3d.ts +++ b/packages/transducers/src/iter/range3d.ts @@ -1,5 +1,4 @@ -import { illegalArity } from "@thi.ng/errors/illegal-arity"; - +import { illegalArity } from "@thi.ng/errors"; import { range } from "./range"; export function range3d(toX: number, toY: number, toZ: number): IterableIterator<[number, number, number]>; diff --git a/packages/transducers/src/iter/vals.ts b/packages/transducers/src/iter/vals.ts index 36c2acb2c5..679f9e862f 100644 --- a/packages/transducers/src/iter/vals.ts +++ b/packages/transducers/src/iter/vals.ts @@ -1,4 +1,4 @@ -import { IObjectOf } from "@thi.ng/api/api"; +import { IObjectOf } from "@thi.ng/api"; export function* vals(x: IObjectOf): IterableIterator { for (let k in x) { diff --git a/packages/transducers/src/iter/wrap-both.ts b/packages/transducers/src/iter/wrap-both.ts index 791922d08b..84b9068c05 100644 --- a/packages/transducers/src/iter/wrap-both.ts +++ b/packages/transducers/src/iter/wrap-both.ts @@ -7,6 +7,5 @@ import { wrap } from "./wrap"; * @param src * @param n */ -export function wrapBoth(src: Iterable, n = 1) { - return wrap(src, n); -} +export const wrapBoth = + (src: Iterable, n = 1) => wrap(src, n); diff --git a/packages/transducers/src/iter/wrap-left.ts b/packages/transducers/src/iter/wrap-left.ts index 17c3f027b9..fbb738b427 100644 --- a/packages/transducers/src/iter/wrap-left.ts +++ b/packages/transducers/src/iter/wrap-left.ts @@ -7,6 +7,5 @@ import { wrap } from "./wrap"; * @param src * @param n */ -export function wrapLeft(src: Iterable, n = 1) { - return wrap(src, n, true, false); -} +export const wrapLeft = + (src: Iterable, n = 1) => wrap(src, n, true, false); diff --git a/packages/transducers/src/iter/wrap-right.ts b/packages/transducers/src/iter/wrap-right.ts index d7a0ba8cdb..6e63a5f8fc 100644 --- a/packages/transducers/src/iter/wrap-right.ts +++ b/packages/transducers/src/iter/wrap-right.ts @@ -7,6 +7,5 @@ import { wrap } from "./wrap"; * @param src * @param n */ -export function wrapRight(src: Iterable, n = 1) { - return wrap(src, n, false, true); -} +export const wrapRight = + (src: Iterable, n = 1) => wrap(src, n, false, true); diff --git a/packages/transducers/src/iter/wrap.ts b/packages/transducers/src/iter/wrap.ts index b67d78c3e0..100e857528 100644 --- a/packages/transducers/src/iter/wrap.ts +++ b/packages/transducers/src/iter/wrap.ts @@ -1,4 +1,4 @@ -import { illegalArgs } from "@thi.ng/errors/illegal-arguments"; +import { illegalArgs } from "@thi.ng/errors"; import { ensureArray } from "../func/ensure-array"; /** diff --git a/packages/transducers/src/iterator.ts b/packages/transducers/src/iterator.ts index ef8c6f6775..59bb3e21bd 100644 --- a/packages/transducers/src/iterator.ts +++ b/packages/transducers/src/iterator.ts @@ -1,5 +1,5 @@ -import { SEMAPHORE } from "@thi.ng/api/api"; -import { isIterable } from "@thi.ng/checks/is-iterable"; +import { SEMAPHORE } from "@thi.ng/api"; +import { isIterable } from "@thi.ng/checks"; import { Reducer, Transducer } from "./api"; import { isReduced, unreduced } from "./reduced"; @@ -64,7 +64,11 @@ export function* iterator1(xform: Transducer, xs: Iterable): Iter * @param args * @param impl */ -export const $iter = (xform: (...xs: any[]) => Transducer, args: any[], impl = iterator1) => { +export const $iter = ( + xform: (...xs: any[]) => Transducer, + args: any[], + impl = iterator1 +) => { const n = args.length - 1; return isIterable(args[n]) ? args.length > 1 ? diff --git a/packages/transducers/src/reduce.ts b/packages/transducers/src/reduce.ts index fc17cfb426..7d1bb84562 100644 --- a/packages/transducers/src/reduce.ts +++ b/packages/transducers/src/reduce.ts @@ -1,8 +1,5 @@ -import { implementsFunction } from "@thi.ng/checks/implements-function"; -import { isArrayLike } from "@thi.ng/checks/is-arraylike"; -import { isIterable } from "@thi.ng/checks/is-iterable"; -import { illegalArity } from "@thi.ng/errors/illegal-arity"; - +import { implementsFunction, isArrayLike, isIterable } from "@thi.ng/checks"; +import { illegalArity } from "@thi.ng/errors"; import { IReducible, Reducer } from "./api"; import { isReduced, Reduced, unreduced } from "./reduced"; @@ -58,15 +55,16 @@ export function reduce(...args: any[]): A { * @param init init step of reducer * @param rfn reduction step of reducer */ -export function reducer(init: () => A, rfn: (acc: A, x: B) => A | Reduced) { - return >[init, (acc) => acc, rfn]; -} +export const reducer = + (init: () => A, rfn: (acc: A, x: B) => A | Reduced) => + >[init, (acc) => acc, rfn]; -export const $$reduce = (rfn: (...args: any[]) => Reducer, args: any[]) => { - const n = args.length - 1; - return isIterable(args[n]) ? - args.length > 1 ? - reduce(rfn.apply(null, args.slice(0, n)), args[n]) : - reduce(rfn(), args[0]) : - undefined; -}; +export const $$reduce = + (rfn: (...args: any[]) => Reducer, args: any[]) => { + const n = args.length - 1; + return isIterable(args[n]) ? + args.length > 1 ? + reduce(rfn.apply(null, args.slice(0, n)), args[n]) : + reduce(rfn(), args[0]) : + undefined; + }; diff --git a/packages/transducers/src/reduced.ts b/packages/transducers/src/reduced.ts index 5e48322ba3..e0e944c1bb 100644 --- a/packages/transducers/src/reduced.ts +++ b/packages/transducers/src/reduced.ts @@ -1,4 +1,4 @@ -import { IDeref } from "@thi.ng/api/api"; +import { IDeref } from "@thi.ng/api"; export class Reduced implements IDeref { @@ -14,18 +14,14 @@ export class Reduced implements } } -export function reduced(x: any): any { - return new Reduced(x); -} +export const reduced = + (x: any): any => new Reduced(x); -export function isReduced(x: any): x is Reduced { - return x instanceof Reduced; -} +export const isReduced = + (x: any): x is Reduced => x instanceof Reduced; -export function ensureReduced(x: any) { - return x instanceof Reduced ? x : new Reduced(x); -} +export const ensureReduced = + (x: any) => x instanceof Reduced ? x : new Reduced(x); -export function unreduced(x: any) { - return x instanceof Reduced ? x.deref() : x; -} +export const unreduced = + (x: any) => x instanceof Reduced ? x.deref() : x; diff --git a/packages/transducers/src/rfn/assoc-map.ts b/packages/transducers/src/rfn/assoc-map.ts index 24acf2f757..7f7ecefebd 100644 --- a/packages/transducers/src/rfn/assoc-map.ts +++ b/packages/transducers/src/rfn/assoc-map.ts @@ -1,7 +1,6 @@ -import { Pair } from "@thi.ng/api/api"; - +import { Pair } from "@thi.ng/api"; import { Reducer } from "../api"; -import { reducer, reduce } from "../reduce"; +import { reduce, reducer } from "../reduce"; /** * Reducer accepting key-value pairs / tuples and transforming / adding diff --git a/packages/transducers/src/rfn/assoc-obj.ts b/packages/transducers/src/rfn/assoc-obj.ts index 410f78eeaa..f29e0aa7c5 100644 --- a/packages/transducers/src/rfn/assoc-obj.ts +++ b/packages/transducers/src/rfn/assoc-obj.ts @@ -1,5 +1,4 @@ -import { IObjectOf, Pair } from "@thi.ng/api/api"; - +import { IObjectOf, Pair } from "@thi.ng/api"; import { Reducer } from "../api"; import { reduce, reducer } from "../reduce"; diff --git a/packages/transducers/src/rfn/every.ts b/packages/transducers/src/rfn/every.ts index e18a366709..3f882b3e05 100644 --- a/packages/transducers/src/rfn/every.ts +++ b/packages/transducers/src/rfn/every.ts @@ -1,5 +1,4 @@ -import { Predicate } from "@thi.ng/api/api"; - +import { Predicate } from "@thi.ng/api"; import { Reducer } from "../api"; import { $$reduce, reducer } from "../reduce"; import { reduced } from "../reduced"; diff --git a/packages/transducers/src/rfn/fill.ts b/packages/transducers/src/rfn/fill.ts index c68a89370a..742de3667c 100644 --- a/packages/transducers/src/rfn/fill.ts +++ b/packages/transducers/src/rfn/fill.ts @@ -1,7 +1,6 @@ -import { NumericArray } from "@thi.ng/api/api"; - +import { NumericArray } from "@thi.ng/api"; import { Reducer } from "../api"; -import { reducer, $$reduce } from "../reduce"; +import { $$reduce, reducer } from "../reduce"; /** * Reducer which starts filling array with results from given `start` diff --git a/packages/transducers/src/rfn/frequencies.ts b/packages/transducers/src/rfn/frequencies.ts index 3554709c87..1fa9467aa0 100644 --- a/packages/transducers/src/rfn/frequencies.ts +++ b/packages/transducers/src/rfn/frequencies.ts @@ -1,5 +1,4 @@ -import { Fn } from "@thi.ng/api/api"; - +import { Fn } from "@thi.ng/api"; import { Reducer } from "../api"; import { identity } from "../func/identity"; import { $$reduce } from "../reduce"; diff --git a/packages/transducers/src/rfn/group-binary.ts b/packages/transducers/src/rfn/group-binary.ts index 4d033577b6..a0539edac3 100644 --- a/packages/transducers/src/rfn/group-binary.ts +++ b/packages/transducers/src/rfn/group-binary.ts @@ -1,12 +1,15 @@ -import { IObjectOf } from "@thi.ng/api/api"; - +import { IObjectOf } from "@thi.ng/api"; import { Reducer } from "../api"; import { groupByObj } from "./group-by-obj"; import { push } from "./push"; -function branchPred(key: (x: T) => number, b: number, l: PropertyKey, r: PropertyKey) { - return (x: T) => key(x) & b ? r : l; -} +const branchPred = ( + key: (x: T) => number, + b: number, + l: PropertyKey, + r: PropertyKey +) => + (x: T) => key(x) & b ? r : l; /** * Creates a bottom-up, unbalanced binary tree of desired depth and @@ -79,13 +82,14 @@ function branchPred(key: (x: T) => number, b: number, l: PropertyKey, r: Prop * @param left key for storing left branches (e.g. `0` for arrays) * @param right key for storing right branches (e.g. `1` for arrays) */ -export function groupBinary( +export const groupBinary = ( bits: number, key: (x: T) => number, branch?: () => IObjectOf, leaf?: Reducer, left: PropertyKey = "l", - right: PropertyKey = "r"): Reducer { + right: PropertyKey = "r" +): Reducer => { const init = branch || (() => ({})); let rfn: Reducer = groupByObj({ @@ -96,4 +100,4 @@ export function groupBinary( rfn = groupByObj({ key: branchPred(key, i, left, right), group: [init, rfn[1], rfn[2]] }); } return [init, rfn[1], rfn[2]]; -} +}; diff --git a/packages/transducers/src/rfn/group-by-obj.ts b/packages/transducers/src/rfn/group-by-obj.ts index 4f706a67bd..0e075ed96c 100644 --- a/packages/transducers/src/rfn/group-by-obj.ts +++ b/packages/transducers/src/rfn/group-by-obj.ts @@ -1,8 +1,7 @@ -import { IObjectOf } from "@thi.ng/api/api"; - +import { IObjectOf } from "@thi.ng/api"; import { GroupByOpts, Reducer } from "../api"; import { identity } from "../func/identity"; -import { reducer, $$reduce } from "../reduce"; +import { $$reduce, reducer } from "../reduce"; import { push } from "./push"; export function groupByObj(opts?: Partial>): Reducer, SRC>; diff --git a/packages/transducers/src/rfn/max-compare.ts b/packages/transducers/src/rfn/max-compare.ts index f49a78648f..6cca468f6a 100644 --- a/packages/transducers/src/rfn/max-compare.ts +++ b/packages/transducers/src/rfn/max-compare.ts @@ -1,6 +1,5 @@ -import { Comparator } from "@thi.ng/api/api"; +import { Comparator } from "@thi.ng/api"; import { compare } from "@thi.ng/compare"; - import { Reducer } from "../api"; import { $$reduce, reducer } from "../reduce"; diff --git a/packages/transducers/src/rfn/min-compare.ts b/packages/transducers/src/rfn/min-compare.ts index 381fe86420..f97ba5a3ce 100644 --- a/packages/transducers/src/rfn/min-compare.ts +++ b/packages/transducers/src/rfn/min-compare.ts @@ -1,6 +1,5 @@ -import { Comparator } from "@thi.ng/api/api"; +import { Comparator } from "@thi.ng/api"; import { compare } from "@thi.ng/compare"; - import { Reducer } from "../api"; import { $$reduce, reducer } from "../reduce"; diff --git a/packages/transducers/src/rfn/push-copy.ts b/packages/transducers/src/rfn/push-copy.ts index d3aece8533..ecf15165cb 100644 --- a/packages/transducers/src/rfn/push-copy.ts +++ b/packages/transducers/src/rfn/push-copy.ts @@ -1,6 +1,6 @@ import { Reducer } from "../api"; import { reducer } from "../reduce"; -export function pushCopy(): Reducer { - return reducer(() => [], (acc, x) => ((acc = acc.slice()).push(x), acc)); -} +export const pushCopy = + (): Reducer => + reducer(() => [], (acc, x) => ((acc = acc.slice()).push(x), acc)); diff --git a/packages/transducers/src/rfn/some.ts b/packages/transducers/src/rfn/some.ts index 266727ceab..90e67242b5 100644 --- a/packages/transducers/src/rfn/some.ts +++ b/packages/transducers/src/rfn/some.ts @@ -1,5 +1,4 @@ -import { Predicate } from "@thi.ng/api/api"; - +import { Predicate } from "@thi.ng/api"; import { Reducer } from "../api"; import { $$reduce, reducer } from "../reduce"; import { reduced } from "../reduced"; diff --git a/packages/transducers/src/step.ts b/packages/transducers/src/step.ts index c431a73007..eda33f1227 100644 --- a/packages/transducers/src/step.ts +++ b/packages/transducers/src/step.ts @@ -36,21 +36,22 @@ import { push } from "./rfn/push"; * * @param tx */ -export function step(tx: Transducer): (x: A) => B | B[] { - const [_, complete, reduce] = tx(push()); _; - let done = false; - return (x: A) => { - if (!done) { - let acc = reduce([], x); - done = isReduced(acc); - if (done) { - acc = complete(acc.deref()); +export const step = + (tx: Transducer): (x: A) => B | B[] => { + const [_, complete, reduce] = tx(push()); _; + let done = false; + return (x: A) => { + if (!done) { + let acc = reduce([], x); + done = isReduced(acc); + if (done) { + acc = complete(acc.deref()); + } + return acc.length === 1 ? + acc[0] : + acc.length > 0 ? + acc : + undefined; } - return acc.length === 1 ? - acc[0] : - acc.length > 0 ? - acc : - undefined; - } + }; }; -} diff --git a/packages/transducers/src/transduce.ts b/packages/transducers/src/transduce.ts index 028bbf1bf8..91212f5ce0 100644 --- a/packages/transducers/src/transduce.ts +++ b/packages/transducers/src/transduce.ts @@ -1,5 +1,4 @@ -import { illegalArity } from "@thi.ng/errors/illegal-arity"; - +import { illegalArity } from "@thi.ng/errors"; import { IReducible, Reducer, Transducer } from "./api"; import { reduce } from "./reduce"; import { map } from "./xform/map"; diff --git a/packages/transducers/src/xform/cat.ts b/packages/transducers/src/xform/cat.ts index 60c2303619..4c58d6f0bc 100644 --- a/packages/transducers/src/xform/cat.ts +++ b/packages/transducers/src/xform/cat.ts @@ -3,35 +3,51 @@ import { compR } from "../func/compr"; import { isReduced, unreduced, ensureReduced } from "../reduced"; /** - * Transducer to concatenate iterable values. If, during processing, the - * transducer is given a wrapped `reduced()` input iterable, it will - * still be processed as normal, but then immediately triggers early - * termination by wrapping its own result in `reduced()`. This behavior - * allows a `mapcat()` user functions to benefit from `reduced` results. + * Transducer to concatenate iterable values. Iterates over each input + * and emits individual values down stream, therefore removing one level + * of nesting from the input. If, during processing, the transducer is + * given a wrapped `reduced()` input iterable, it will still be + * processed as normal, but then immediately triggers early termination + * by wrapping its own result in `reduced()`. E.g. this behavior allows + * a `mapcat()` user functions to benefit from `reduced` results. * * ``` + * [...iterator(comp(map((x) => [x, x]), cat()), [1, 2, 3, 4])] + * // [ 1, 1, 2, 2, 3, 3, 4, 4 ] + * + * [...iterator( + * comp( + * mapIndexed((i, x) => [[i], [x, x]]), + * cat(), + * cat() + * ), + * "abc" + * )] + * // [ 0, 'a', 'a', 1, 'b', 'b', 2, 'c', 'c' ] + * * [...mapcat((x)=>(x > 1 ? reduced([x, x]) : [x, x]), [1, 2, 3, 4])] * // [ 1, 1, 2, 2 ] * ``` * + * @see thi.ng/transducers/iter/concat * @see thi.ng/transducers/xform/mapcat */ -export function cat(): Transducer, T> { - return (rfn: Reducer) => { - const r = rfn[2]; - return compR(rfn, - (acc, x: Iterable) => { - if (x) { - for (let y of unreduced(x)) { - acc = r(acc, y); - if (isReduced(acc)) { - break; +export const cat = + (): Transducer, T> => + (rfn: Reducer) => { + const r = rfn[2]; + return compR(rfn, + (acc, x: Iterable) => { + if (x) { + for (let y of unreduced(x)) { + acc = r(acc, y); + if (isReduced(acc)) { + break; + } } } - } - return isReduced(x) ? - ensureReduced(acc) : - acc; - }); - }; -} + return isReduced(x) ? + ensureReduced(acc) : + acc; + }); + }; diff --git a/packages/transducers/src/xform/convolve.ts b/packages/transducers/src/xform/convolve.ts index 6953b56044..b4dcbd15ab 100644 --- a/packages/transducers/src/xform/convolve.ts +++ b/packages/transducers/src/xform/convolve.ts @@ -1,5 +1,4 @@ -import { illegalArgs } from "@thi.ng/errors/illegal-arguments"; - +import { illegalArgs } from "@thi.ng/errors"; import { Transducer } from "../api"; import { range2d } from "../iter/range2d"; import { tuples } from "../iter/tuples"; diff --git a/packages/transducers/src/xform/dedupe.ts b/packages/transducers/src/xform/dedupe.ts index 9834e7bb89..dacf24a2ba 100644 --- a/packages/transducers/src/xform/dedupe.ts +++ b/packages/transducers/src/xform/dedupe.ts @@ -1,5 +1,4 @@ -import { Predicate2, SEMAPHORE } from "@thi.ng/api/api"; - +import { Predicate2, SEMAPHORE } from "@thi.ng/api"; import { Reducer, Transducer } from "../api"; import { compR } from "../func/compr"; import { $iter } from "../iterator"; diff --git a/packages/transducers/src/xform/delayed.ts b/packages/transducers/src/xform/delayed.ts index b9c3c44967..5cadd02718 100644 --- a/packages/transducers/src/xform/delayed.ts +++ b/packages/transducers/src/xform/delayed.ts @@ -11,6 +11,6 @@ import { map } from "./map"; * * @param t */ -export function delayed(t: number): Transducer> { - return map((x) => delay(x, t)); -} +export const delayed = + (t: number): Transducer> => + map((x) => delay(x, t)); diff --git a/packages/transducers/src/xform/drop-while.ts b/packages/transducers/src/xform/drop-while.ts index a950d72180..abaa872067 100644 --- a/packages/transducers/src/xform/drop-while.ts +++ b/packages/transducers/src/xform/drop-while.ts @@ -1,5 +1,4 @@ -import { Predicate } from "@thi.ng/api/api"; - +import { Predicate } from "@thi.ng/api"; import { Reducer, Transducer } from "../api"; import { compR } from "../func/compr"; import { $iter } from "../iterator"; diff --git a/packages/transducers/src/xform/filter-fuzzy.ts b/packages/transducers/src/xform/filter-fuzzy.ts index 13d91830c3..9679fdc655 100644 --- a/packages/transducers/src/xform/filter-fuzzy.ts +++ b/packages/transducers/src/xform/filter-fuzzy.ts @@ -1,5 +1,4 @@ -import { Fn, Predicate2 } from "@thi.ng/api/api"; - +import { Fn, Predicate2 } from "@thi.ng/api"; import { Transducer } from "../api"; import { fuzzyMatch } from "../func/fuzzy-match"; import { $iter } from "../iterator"; diff --git a/packages/transducers/src/xform/hex-dump.ts b/packages/transducers/src/xform/hex-dump.ts index a25491038d..9c6cbbbcff 100644 --- a/packages/transducers/src/xform/hex-dump.ts +++ b/packages/transducers/src/xform/hex-dump.ts @@ -1,5 +1,4 @@ -import { U32, U8 } from "@thi.ng/strings/radix"; - +import { U32, U8 } from "@thi.ng/strings"; import { Transducer } from "../api"; import { comp } from "../func/comp"; import { juxt } from "../func/juxt"; diff --git a/packages/transducers/src/xform/labeled.ts b/packages/transducers/src/xform/labeled.ts index 73341868ae..611a5bbc19 100644 --- a/packages/transducers/src/xform/labeled.ts +++ b/packages/transducers/src/xform/labeled.ts @@ -1,5 +1,4 @@ -import { isFunction } from "@thi.ng/checks/is-function"; - +import { isFunction } from "@thi.ng/checks"; import { Transducer } from "../api"; import { iterator1 } from "../iterator"; import { map } from "./map"; diff --git a/packages/transducers/src/xform/map-keys.ts b/packages/transducers/src/xform/map-keys.ts index ff646a9b03..35ea24b9eb 100644 --- a/packages/transducers/src/xform/map-keys.ts +++ b/packages/transducers/src/xform/map-keys.ts @@ -1,5 +1,4 @@ -import { Fn, IObjectOf } from "@thi.ng/api/api"; - +import { Fn, IObjectOf } from "@thi.ng/api"; import { Transducer } from "../api"; import { $iter } from "../iterator"; import { map } from "./map"; diff --git a/packages/transducers/src/xform/map-nth.ts b/packages/transducers/src/xform/map-nth.ts index cc2750b894..95ab9e8bd1 100644 --- a/packages/transducers/src/xform/map-nth.ts +++ b/packages/transducers/src/xform/map-nth.ts @@ -1,5 +1,4 @@ -import { Fn } from "@thi.ng/api/api"; - +import { Fn } from "@thi.ng/api"; import { Reducer, Transducer } from "../api"; import { compR } from "../func/compr"; import { $iter } from "../iterator"; diff --git a/packages/transducers/src/xform/map-vals.ts b/packages/transducers/src/xform/map-vals.ts index 90eb39f13d..1a4f60cc7b 100644 --- a/packages/transducers/src/xform/map-vals.ts +++ b/packages/transducers/src/xform/map-vals.ts @@ -1,5 +1,4 @@ -import { Fn, IObjectOf } from "@thi.ng/api/api"; - +import { Fn, IObjectOf } from "@thi.ng/api"; import { Transducer } from "../api"; import { $iter } from "../iterator"; import { map } from "./map"; diff --git a/packages/transducers/src/xform/map.ts b/packages/transducers/src/xform/map.ts index 3a409a5247..ddbf92550c 100644 --- a/packages/transducers/src/xform/map.ts +++ b/packages/transducers/src/xform/map.ts @@ -1,5 +1,4 @@ -import { Fn } from "@thi.ng/api/api"; - +import { Fn } from "@thi.ng/api"; import { Reducer, Transducer } from "../api"; import { compR } from "../func/compr"; import { iterator1 } from "../iterator"; diff --git a/packages/transducers/src/xform/mapcat.ts b/packages/transducers/src/xform/mapcat.ts index 5038dac1a6..552afd5e0e 100644 --- a/packages/transducers/src/xform/mapcat.ts +++ b/packages/transducers/src/xform/mapcat.ts @@ -1,5 +1,4 @@ -import { Fn } from "@thi.ng/api/api"; - +import { Fn } from "@thi.ng/api"; import { Transducer } from "../api"; import { comp } from "../func/comp"; import { iterator } from "../iterator"; diff --git a/packages/transducers/src/xform/moving-average.ts b/packages/transducers/src/xform/moving-average.ts index 3100013a3a..178bdfa64c 100644 --- a/packages/transducers/src/xform/moving-average.ts +++ b/packages/transducers/src/xform/moving-average.ts @@ -1,5 +1,4 @@ -import { illegalArgs } from "@thi.ng/errors/illegal-arguments"; - +import { illegalArgs } from "@thi.ng/errors"; import { Reducer, Transducer } from "../api"; import { compR } from "../func/compr"; import { iterator1 } from "../iterator"; diff --git a/packages/transducers/src/xform/multiplex-obj.ts b/packages/transducers/src/xform/multiplex-obj.ts index d0b9680df8..f9aa5f79cd 100644 --- a/packages/transducers/src/xform/multiplex-obj.ts +++ b/packages/transducers/src/xform/multiplex-obj.ts @@ -1,5 +1,4 @@ -import { IObjectOf } from "@thi.ng/api/api"; - +import { IObjectOf } from "@thi.ng/api"; import { Reducer, Transducer } from "../api"; import { comp } from "../func/comp"; import { $iter } from "../iterator"; diff --git a/packages/transducers/src/xform/noop.ts b/packages/transducers/src/xform/noop.ts index a825f0a88c..188a85c7f8 100644 --- a/packages/transducers/src/xform/noop.ts +++ b/packages/transducers/src/xform/noop.ts @@ -5,6 +5,6 @@ import { Transducer } from "../api"; * `map(identity)`, but faster. Useful for testing and / or to keep * existing values in a `multiplex()` tuple lane. */ -export function noop(): Transducer { - return (rfn) => rfn; -} +export const noop = + (): Transducer => + (rfn) => rfn; diff --git a/packages/transducers/src/xform/partition-by.ts b/packages/transducers/src/xform/partition-by.ts index d40fd7b025..4966cb002c 100644 --- a/packages/transducers/src/xform/partition-by.ts +++ b/packages/transducers/src/xform/partition-by.ts @@ -1,5 +1,4 @@ -import { Fn, SEMAPHORE } from "@thi.ng/api/api"; - +import { Fn, SEMAPHORE } from "@thi.ng/api"; import { Transducer } from "../api"; import { $iter, iterator } from "../iterator"; import { isReduced } from "../reduced"; diff --git a/packages/transducers/src/xform/partition-sync.ts b/packages/transducers/src/xform/partition-sync.ts index f81291b21a..c02e180bde 100644 --- a/packages/transducers/src/xform/partition-sync.ts +++ b/packages/transducers/src/xform/partition-sync.ts @@ -1,6 +1,5 @@ -import { IObjectOf } from "@thi.ng/api/api"; -import { isArray } from "@thi.ng/checks/is-array"; - +import { IObjectOf } from "@thi.ng/api"; +import { isArray } from "@thi.ng/checks"; import { Reducer, Transducer } from "../api"; import { identity } from "../func/identity"; import { $iter, iterator } from "../iterator"; diff --git a/packages/transducers/src/xform/rename.ts b/packages/transducers/src/xform/rename.ts index af52156a98..2e55ddbbef 100644 --- a/packages/transducers/src/xform/rename.ts +++ b/packages/transducers/src/xform/rename.ts @@ -1,6 +1,5 @@ -import { IObjectOf } from "@thi.ng/api/api"; -import { isArray } from "@thi.ng/checks/is-array"; - +import { IObjectOf } from "@thi.ng/api"; +import { isArray } from "@thi.ng/checks"; import { Reducer, Transducer } from "../api"; import { comp } from "../func/comp"; import { renamer } from "../func/renamer"; diff --git a/packages/transducers/src/xform/side-effect.ts b/packages/transducers/src/xform/side-effect.ts index 8434117d0a..eafefbcbf5 100644 --- a/packages/transducers/src/xform/side-effect.ts +++ b/packages/transducers/src/xform/side-effect.ts @@ -8,6 +8,6 @@ import { map } from "./map"; * * @param fn side effect */ -export function sideEffect(fn: (x: T) => void): Transducer { - return map((x) => (fn(x), x)); -} +export const sideEffect = + (fn: (x: T) => void): Transducer => + map((x) => (fn(x), x)); diff --git a/packages/transducers/src/xform/struct.ts b/packages/transducers/src/xform/struct.ts index 577f0078c6..76a2c9e632 100644 --- a/packages/transducers/src/xform/struct.ts +++ b/packages/transducers/src/xform/struct.ts @@ -1,5 +1,4 @@ -import { Fn } from "@thi.ng/api/api"; - +import { Fn } from "@thi.ng/api"; import { Transducer } from "../api"; import { comp } from "../func/comp"; import { iterator } from "../iterator"; diff --git a/packages/transducers/src/xform/take-while.ts b/packages/transducers/src/xform/take-while.ts index 5a6e3798ba..a1a25b2d84 100644 --- a/packages/transducers/src/xform/take-while.ts +++ b/packages/transducers/src/xform/take-while.ts @@ -1,5 +1,4 @@ -import { Predicate } from "@thi.ng/api/api"; - +import { Predicate } from "@thi.ng/api"; import { Reducer, Transducer } from "../api"; import { compR } from "../func/compr"; import { $iter } from "../iterator"; diff --git a/packages/transducers/src/xform/throttle.ts b/packages/transducers/src/xform/throttle.ts index e8564cc139..a86fb2bb51 100644 --- a/packages/transducers/src/xform/throttle.ts +++ b/packages/transducers/src/xform/throttle.ts @@ -1,5 +1,4 @@ -import { StatefulPredicate } from "@thi.ng/api/api"; - +import { StatefulPredicate } from "@thi.ng/api"; import { Reducer, Transducer } from "../api"; import { compR } from "../func/compr"; import { iterator1 } from "../iterator"; diff --git a/packages/transducers/src/xform/trace.ts b/packages/transducers/src/xform/trace.ts index 7f6abe084f..fa118f750a 100644 --- a/packages/transducers/src/xform/trace.ts +++ b/packages/transducers/src/xform/trace.ts @@ -1,6 +1,6 @@ import { Transducer } from "../api"; import { sideEffect } from "./side-effect"; -export function trace(prefix = ""): Transducer { - return sideEffect((x) => console.log(prefix, x)); -} +export const trace = + (prefix = ""): Transducer => + sideEffect((x) => console.log(prefix, x)); diff --git a/packages/transducers/test/partition-bits.ts b/packages/transducers/test/partition-bits.ts index 9e6d09809e..deceb1fbe6 100644 --- a/packages/transducers/test/partition-bits.ts +++ b/packages/transducers/test/partition-bits.ts @@ -1,5 +1,5 @@ import * as assert from "assert"; -import { radix } from "@thi.ng/strings/radix"; +import { radix } from "@thi.ng/strings"; import { comp } from "../src/func/comp"; import { range } from "../src/iter/range"; diff --git a/packages/transducers/test/tsconfig.json b/packages/transducers/test/tsconfig.json index 13d45669e5..2c9c12a650 100644 --- a/packages/transducers/test/tsconfig.json +++ b/packages/transducers/test/tsconfig.json @@ -1,7 +1,8 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", diff --git a/packages/transducers/tsconfig.json b/packages/transducers/tsconfig.json index f6c291a0a0..bcf03f18b4 100644 --- a/packages/transducers/tsconfig.json +++ b/packages/transducers/tsconfig.json @@ -1,7 +1,9 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" diff --git a/packages/unionstruct/.npmignore b/packages/unionstruct/.npmignore index d703bda97a..67d0c55714 100644 --- a/packages/unionstruct/.npmignore +++ b/packages/unionstruct/.npmignore @@ -1,10 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/unionstruct/CHANGELOG.md b/packages/unionstruct/CHANGELOG.md index 1f20a14953..cb8cf93eff 100644 --- a/packages/unionstruct/CHANGELOG.md +++ b/packages/unionstruct/CHANGELOG.md @@ -3,6 +3,28 @@ 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/unionstruct@0.1.19...@thi.ng/unionstruct@1.0.0) (2019-01-21) + + +### Build System + +* update package build scripts & outputs, imports in ~50 packages ([b54b703](https://github.com/thi-ng/umbrella/commit/b54b703)) + + +### BREAKING CHANGES + +* enabled multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols. + + + + + ## [0.1.19](https://github.com/thi-ng/umbrella/compare/@thi.ng/unionstruct@0.1.18...@thi.ng/unionstruct@0.1.19) (2018-12-15) **Note:** Version bump only for package @thi.ng/unionstruct diff --git a/packages/unionstruct/package.json b/packages/unionstruct/package.json index dab98fb9bf..0c79c08c05 100644 --- a/packages/unionstruct/package.json +++ b/packages/unionstruct/package.json @@ -1,8 +1,10 @@ { "name": "@thi.ng/unionstruct", - "version": "0.1.19", + "version": "1.0.0", "description": "C-style struct, union and bitfield views of ArrayBuffers", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -12,19 +14,21 @@ "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module unionstruct", + "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", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "keywords": [ @@ -34,11 +38,13 @@ "c", "cpp", "ES6", + "interop", "struct", "typescript", "union" ], "publishConfig": { "access": "public" - } + }, + "sideEffects": false } diff --git a/packages/unionstruct/src/index.ts b/packages/unionstruct/src/index.ts index 88cfd8d40b..e735d0947b 100644 --- a/packages/unionstruct/src/index.ts +++ b/packages/unionstruct/src/index.ts @@ -24,35 +24,45 @@ const TYPES = { const UNION = "union"; const STRUCT = "struct"; -let isBitField = (f: Field) => typeof f[2] === "number" && /^(u|i)\d+$/.test(f[1]); +const isBitField = + (f: Field) => + typeof f[2] === "number" && /^(u|i)\d+$/.test(f[1]); -let align = (bitOffset: number, type: string, spec: any) => { - if (type === UNION) { - spec = (spec.__spec || spec); - let a = 0, f; - for (let i = 0; i < spec.length; i++) { - f = spec[i]; - a = Math.max(align(bitOffset, f[1], f[2]), a); +const align = + (bitOffset: number, type: string, spec: any) => { + if (type === UNION) { + spec = (spec.__spec || spec); + let a = 0, f; + for (let i = 0; i < spec.length; i++) { + f = spec[i]; + a = Math.max(align(bitOffset, f[1], f[2]), a); + } + return a; + } else if (type === STRUCT) { + spec = (spec.__spec || spec)[0]; + return align(bitOffset, spec[1], spec[2]); } - return a; - } else if (type === STRUCT) { - spec = (spec.__spec || spec)[0]; - return align(bitOffset, spec[1], spec[2]); - } - let block = TYPES[type][0]; - return block > 8 ? (bitOffset + block - 1) & -block : bitOffset; -}; + let block = TYPES[type][0]; + return block > 8 ? (bitOffset + block - 1) & -block : bitOffset; + }; -let maybePad = (offset: number, spec: any[], i: number) => { - let f = spec[i], width; - if (i === spec.length - 1 || !isBitField(spec[i + 1])) { - width = TYPES[f[1]][0]; - offset += ((offset + width - 1) & ~(width - 1)) - offset; - } - return offset; -}; +const maybePad = + (offset: number, spec: any[], i: number) => { + let f = spec[i], width; + if (i === spec.length - 1 || !isBitField(spec[i + 1])) { + width = TYPES[f[1]][0]; + offset += ((offset + width - 1) & ~(width - 1)) - offset; + } + return offset; + }; -let _sizeOf = (spec: Field[], union: boolean, doAlign: boolean, bitOffset: number, total: number) => { +const _sizeOf = ( + spec: Field[], + union: boolean, + doAlign: boolean, + bitOffset: number, + total: number +) => { for (let i = 0; i < spec.length; i++) { let f = spec[i], type = f[1], size = f[2], isBF = isBitField(f); bitOffset = doAlign && !isBF ? align(bitOffset, type, size) : bitOffset; @@ -71,36 +81,46 @@ let _sizeOf = (spec: Field[], union: boolean, doAlign: boolean, bitOffset: numbe return [total, bitOffset]; }; -export let sizeOf = (spec: Field[], union = false, doAlign = true) => - _sizeOf(spec, union, doAlign, 0, 0)[0]; +export const sizeOf = + (spec: Field[], union = false, doAlign = true) => + _sizeOf(spec, union, doAlign, 0, 0)[0]; -let bitReader = (dv: DataView, byteOffset: number, bit: number, size: number) => { - const b = bit - size; - if (b >= 0) { - return () => dv.getUint32(byteOffset, false) >>> b & (1 << size) - 1; - } - return () => ((dv.getUint32(byteOffset, false) & (1 << bit) - 1) << -b) | - (dv.getUint32(byteOffset + 4, false) >>> (32 + b)); -}; +const bitReader = + (dv: DataView, byteOffset: number, bit: number, size: number) => { + const b = bit - size; + if (b >= 0) { + return () => dv.getUint32(byteOffset, false) >>> b & (1 << size) - 1; + } + return () => ((dv.getUint32(byteOffset, false) & (1 << bit) - 1) << -b) | + (dv.getUint32(byteOffset + 4, false) >>> (32 + b)); + }; -let bitWriter = (dv: DataView, byteOffset: number, bit: number, size: number) => { - const b = bit - size; - let m = bit < 32 ? ~((1 << bit) - 1) : 0; - if (b >= 0) { - m |= (1 << b) - 1; - return (x) => { - dv.setUint32(byteOffset, (dv.getUint32(byteOffset, false) & m) | (x << b & ~m), false); - }; - } else { - let bb = 32 + b; - return (x) => { - dv.setUint32(byteOffset, (dv.getUint32(byteOffset, false) & m) | (x >>> -b & ~m), false); - dv.setUint32(byteOffset + 4, (dv.getUint32(byteOffset + 4, false) & (1 << bb) - 1) | x << bb, false); +const bitWriter = + (dv: DataView, byteOffset: number, bit: number, size: number) => { + const b = bit - size; + let m = bit < 32 ? ~((1 << bit) - 1) : 0; + if (b >= 0) { + m |= (1 << b) - 1; + return (x) => { + dv.setUint32(byteOffset, (dv.getUint32(byteOffset, false) & m) | (x << b & ~m), false); + }; + } else { + let bb = 32 + b; + return (x) => { + dv.setUint32(byteOffset, (dv.getUint32(byteOffset, false) & m) | (x >>> -b & ~m), false); + dv.setUint32(byteOffset + 4, (dv.getUint32(byteOffset + 4, false) & (1 << bb) - 1) | x << bb, false); + } } - } -}; + }; -let makeField = (field: Field, obj: any, dv: DataView, bitOffset: number, doAlign: boolean, le: boolean) => { +const makeField = ( + field: Field, + obj: any, + dv: DataView, + bitOffset: number, + doAlign: boolean, + le: boolean +) => { let [id, type, size] = field; const isBF = isBitField(field); bitOffset = doAlign && !isBF ? align(bitOffset, type, size) : bitOffset; @@ -146,7 +166,14 @@ let makeField = (field: Field, obj: any, dv: DataView, bitOffset: number, doAlig return bitOffset; }; -export let typedef = (spec: Field[], struct: boolean, buf?: ArrayBuffer, offset = 0, doAlign = true, le = false) => { +export const typedef = ( + spec: Field[], + struct: boolean, + buf?: ArrayBuffer, + offset = 0, + doAlign = true, + le = false +) => { let size = sizeOf(spec, !struct, doAlign); let dv = new DataView(buf || new ArrayBuffer(((size + 7) & -8) >>> 3)); let off = offset << 3; @@ -169,10 +196,12 @@ export let typedef = (spec: Field[], struct: boolean, buf?: ArrayBuffer, offset return obj; }; -export let union = (spec: Field[], buf?: ArrayBuffer, offset?: number, doAlign?: boolean, le?: boolean) => { - return typedef(spec, false, buf, offset, doAlign, le); -} +export const union = + (spec: Field[], buf?: ArrayBuffer, offset?: number, doAlign?: boolean, le?: boolean) => { + return typedef(spec, false, buf, offset, doAlign, le); + } -export let struct = (spec: Field[], buf?: ArrayBuffer, offset?: number, doAlign?: boolean, le?: boolean) => { - return typedef(spec, true, buf, offset, doAlign, le); -} +export const struct = + (spec: Field[], buf?: ArrayBuffer, offset?: number, doAlign?: boolean, le?: boolean) => { + return typedef(spec, true, buf, offset, doAlign, le); + } diff --git a/packages/unionstruct/test/tsconfig.json b/packages/unionstruct/test/tsconfig.json index 13d45669e5..2c9c12a650 100644 --- a/packages/unionstruct/test/tsconfig.json +++ b/packages/unionstruct/test/tsconfig.json @@ -1,7 +1,8 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", diff --git a/packages/unionstruct/tsconfig.json b/packages/unionstruct/tsconfig.json index f6c291a0a0..bcf03f18b4 100644 --- a/packages/unionstruct/tsconfig.json +++ b/packages/unionstruct/tsconfig.json @@ -1,7 +1,9 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" diff --git a/packages/vector-pools/.npmignore b/packages/vector-pools/.npmignore new file mode 100644 index 0000000000..67d0c55714 --- /dev/null +++ b/packages/vector-pools/.npmignore @@ -0,0 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz +build +coverage +dev +doc +src* +test +tsconfig.json diff --git a/packages/vector-pools/CHANGELOG.md b/packages/vector-pools/CHANGELOG.md new file mode 100644 index 0000000000..974160cdd1 --- /dev/null +++ b/packages/vector-pools/CHANGELOG.md @@ -0,0 +1,14 @@ +# 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-01-21) + + +### Features + +* **vector-pools:** add AttribPool, refactor lists ([019c0af](https://github.com/thi-ng/umbrella/commit/019c0af)) +* **vector-pools:** add GLType alias, AttribPoolOpts, update pool impls ([4fe2047](https://github.com/thi-ng/umbrella/commit/4fe2047)) +* **vector-pools:** add VecPool, VecArrayList & VecLinkedList ([48d5d57](https://github.com/thi-ng/umbrella/commit/48d5d57)) +* **vector-pools:** update readme, add examples ([fd54d32](https://github.com/thi-ng/umbrella/commit/fd54d32)) diff --git a/packages/vector-pools/LICENSE b/packages/vector-pools/LICENSE new file mode 100644 index 0000000000..8dada3edaf --- /dev/null +++ b/packages/vector-pools/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/vector-pools/README.md b/packages/vector-pools/README.md new file mode 100644 index 0000000000..d58fcfa567 --- /dev/null +++ b/packages/vector-pools/README.md @@ -0,0 +1,223 @@ +# @thi.ng/vector-pools + +[![npm (scoped)](https://img.shields.io/npm/v/@thi.ng/vector-pools.svg)](https://www.npmjs.com/package/@thi.ng/vector-pools) +![npm downloads](https://img.shields.io/npm/dm/@thi.ng/vector-pools.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) + - [WebGL geometry definition / manipulation](#webgl-geometry-definition--manipulation) + - [WASM interop](#wasm-interop) +- [Authors](#authors) +- [License](#license) + + + +## About + +This still unreleased package provides various data structures for +managing & working with memory mapped vectors. Together with +[@thi.ng/vectors](https://github.com/thi-ng/umbrella/tree/master/packages/vectors) +(also still unreleased) these structures enable high-level, +zero-copy* manipulation of the underlying memory region and +are largely intended for WebGL & WASM use cases, e.g. to provide JS +friendly views of a structured data region of a WebGL or WASM memory +buffer. + +* The only copying taking place is to GPU memory + +## Installation + +```bash +yarn add @thi.ng/vector-pools +``` + +## Dependencies + +- [@thi.ng/api](https://github.com/thi-ng/umbrella/tree/master/packages/api) +- [@thi.ng/malloc](https://github.com/thi-ng/umbrella/tree/master/packages/malloc) +- [@thi.ng/vectors](https://github.com/thi-ng/umbrella/tree/master/packages/vectors) + +## Usage examples + +### WebGL geometry definition / manipulation + +```ts +import { AttribPool, GLType } from "@thi.ng/vector-pools"; +import * as v from "@thi.ng/vectors"; +import * as tx from "@thi.ng/transducers"; + +// ...Webgl boilerplate omitted +const gl = ... + +// create an interleaved (AOS layout) attribute buffer w/ default values +const geo = new AttribPool( + // initial size in bytes (or provide ArrayBuffer or @thi.ng/malloc/MemPool) + 0x200, + // num elements + 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 }, + col: { type: GLType.F32, size: 3, default: [1, 1, 1], byteOffset: 20 }, + id: { type: GLType.U16, size: 1, default: 0, 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.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 +v.mulN(null, geo.attribValue("pos", 3), 2); +// Float32Array [ -10, 10, 0 ] + +// get iterator of mapped attrib vals (e.g. for batch processing) +[...geo.attribValues("pos")] +// [ Float32Array [ -5, 0, 0 ], +// Float32Array [ 5, 0, 0 ], +// Float32Array [ 5, 5, 0 ], +// Float32Array [ -10, 10, 0 ] ] + +// 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")) +); + +// updated colors +[...geo.attribValues("col")] +// [ Float32Array [ 0, 0.5, 0.5 ], +// Float32Array [ 1, 0.5, 0.5 ], +// Float32Array [ 0.8535534143447876, 0.8535534143447876, 0.5 ], +// Float32Array [ 0.1464466154575348, 0.8535534143447876, 0.5 ] ] + +// dynamically add another attrib +// this will change the overall stride length and re-align all existing attribs +geo.addAttribs({ + normal: { type: GLType.F32, size: 3, default: [0, 0, 1], byteOffset: 36 } +}); + +// updated overall stride length +geo.byteStride +// 48 + +// only need to use & bind single (interleaved) buffer +// containing all attribs +buf = gl.createBuffer(); +gl.bindBuffer(gl.ARRAY_BUFFER, buf); +gl.bufferData(gl.ARRAY_BUFFER, geo.bytes(), gl.STATIC_DRAW); + +// helper fn to bind a single shader attrib +const initAttrib = (gl, loc, attrib) => { + gl.enableVertexAttribArray(loc); + gl.vertexAttribPointer( + loc, + attrib.size, + attrib.type, + false, + attrib.byteStride, // computed by pool + attrib.byteOffset + ); +}; + +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 + +```c +// main.c + +#include +#include + +typedef struct { + float pos[3]; + float uv[2]; + float col[3]; + uint16_t id; +} Vertex; + +Vertex vertices[] = { + {.pos = {-5, 0, 0}, .uv = {0, 0}, .col = {1, 0, 0}, .id = 0}, + {.pos = {5, 0, 0}, .uv = {1, 0}, .col = {0, 1, 0}, .id = 1}, + {.pos = {5, 5, 0}, .uv = {1, 1}, .col = {0, 0, 1}, .id = 2}, + {.pos = {-5, 5, 0}, .uv = {0, 1}, .col = {1, 0, 1}, .id = 3}, +}; + +int main() { return 0; } + +EMSCRIPTEN_KEEPALIVE Vertex* getVertices() { + return vertices; +} + +EMSCRIPTEN_KEEPALIVE int getNumVertices() { + return sizeof(vertices) / sizeof(Vertex); +} +``` + +```ts +// ... WASM / Emscripten boilerplate omitted +const Module = ... + +// +const geo = new vp.AttribPool( + // map WASM memory + Module.buffer, + // num elements (obtained from C function) + Module._getNumVertices(), + // attrib specs (data mapping layout) + // don't specify attrib defaults to avoid overriding + // values already initialized by WASM code + { + pos: { type: vp.GLType.F32, size: 3, byteOffset: 0 }, + uv: { type: vp.GLType.F32, size: 2, byteOffset: 12 }, + col: { type: vp.GLType.F32, size: 3, byteOffset: 20 }, + id: { type: vp.GLType.U16, size: 1, byteOffset: 32 } + }, + // pool options + { + // don't allow resizing (since we're mapping a fixed sized C array) + resizable: false, + // initialize mem pool to start @ C `vertices` array + mempool: { + start: Module._getVertices(), + } + } +); + +[...geo.attribValues("pos")] +// [ Float32Array [ -5, 0, 0 ], +// Float32Array [ 5, 0, 0 ], +// Float32Array [ 5, 5, 0 ], +// Float32Array [ -5, 5, 0 ] ] +``` + +## Authors + +- Karsten Schmidt + +## License + +© 2018 Karsten Schmidt // Apache Software License 2.0 diff --git a/packages/vector-pools/package.json b/packages/vector-pools/package.json new file mode 100644 index 0000000000..1d0131c72f --- /dev/null +++ b/packages/vector-pools/package.json @@ -0,0 +1,60 @@ +{ + "name": "@thi.ng/vector-pools", + "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/vector-pool", + "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 vectorPools api malloc vectors", + "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": "typedoc --mode modules --out doc src", + "pub": "yarn build && yarn publish --access public" + }, + "devDependencies": { + "@types/mocha": "^5.2.5", + "@types/node": "^10.12.15", + "mocha": "^5.2.0", + "nyc": "^13.1.0", + "typedoc": "^0.14.0", + "typescript": "^3.2.2" + }, + "dependencies": { + "@thi.ng/api": "^5.0.0", + "@thi.ng/malloc": "^1.0.0", + "@thi.ng/vectors": "^2.0.0" + }, + "keywords": [ + "ES6", + "memory", + "memory mapped", + "pool", + "typedarray", + "typescript", + "webgl", + "wasm" + ], + "publishConfig": { + "access": "public" + }, + "browserslist": [ + "since 2018-07" + ], + "browser": { + "process": false, + "setTimeout": false + }, + "sideEffects": false +} diff --git a/packages/vector-pools/src/alist.ts b/packages/vector-pools/src/alist.ts new file mode 100644 index 0000000000..251fb77304 --- /dev/null +++ b/packages/vector-pools/src/alist.ts @@ -0,0 +1,89 @@ +import { StridedVec, Vec } from "@thi.ng/vectors"; +import { VecFactory } from "./api"; +import { wrap } from "./wrap"; + +export abstract class AVecList { + + buffer: Vec; + factory: VecFactory; + + start: number; + capacity: number; + curr: number; + size: number; + estride: number; + cstride: number; + + freeIDs: number[]; + + /** + * + * @param buffer + * @param capacity + * @param size + * @param start + * @param cstride + * @param estride + * @param factory + */ + constructor( + buffer: Vec, + capacity: number, + size: number, + start = 0, + cstride = 1, + estride = size, + factory: VecFactory = wrap, + ) { + this.buffer = buffer || new Float32Array(size * capacity); + this.size = size; + this.factory = factory; + this.cstride = cstride; + this.estride = estride; + this.start = this.curr = start; + this.capacity = capacity; + this.freeIDs = []; + } + + abstract [Symbol.iterator](): IterableIterator; + + abstract get length(): number; + + abstract add(): T; + + abstract insert(i: number): T; + + abstract remove(v: T): boolean; + + abstract has(v: T): boolean; + + abstract nth(n: number): T; + + indices(res: Vec = [], i = 0, local = true) { + const start = this.start; + const estride = this.estride; + if (local) { + for (let v of this) { + res[i++] = (v.offset - start) / estride; + } + } else { + for (let v of this) { + res[i++] = v.offset; + } + } + return res; + } + + protected alloc() { + let idx: number; + if (this.freeIDs.length > 0) { + idx = this.freeIDs.pop(); + } else if (this.length >= this.capacity) { + return; + } else { + idx = this.curr; + this.curr += this.estride; + } + return this.factory(this.buffer, this.size, idx, this.cstride); + } +} diff --git a/packages/vector-pools/src/api.ts b/packages/vector-pools/src/api.ts new file mode 100644 index 0000000000..ca0025c537 --- /dev/null +++ b/packages/vector-pools/src/api.ts @@ -0,0 +1,78 @@ +import { IRelease, TypedArray } from "@thi.ng/api"; +import { Type, MemPoolOpts } from "@thi.ng/malloc"; +import { StridedVec, Vec, ReadonlyVec } from "@thi.ng/vectors"; + +export interface AttribSpec { + type: GLType | Type; + size: number; + default?: number | ReadonlyVec; + byteOffset: number; + stride?: number; +} + +export interface AttribPoolOpts { + resizable: boolean; + mempool: MemPoolOpts; +} + +export interface IVecPool extends IRelease { + + malloc(size: number, type?: GLType | Type): TypedArray; + + mallocWrapped(size: number, stride?: number, type?: GLType | Type): StridedVec; + + mallocArray(num: number, size: number, cstride?: number, estride?: number, type?: GLType | Type): StridedVec[]; + + free(vec: StridedVec | TypedArray): boolean; + + freeAll(); +} + +export type VecFactory = + (buf: Vec, size: number, index: number, stride: number) => StridedVec; + +/** + * WebGL numeric type constants. These can be used by classes in this + * package as aliases for thi.ng/malloc's `Type` enum (see `GL2TYPE` LUT + * below), but also then used directly when initializing WebGL buffers + * from given attribute buffer specs. + * + * See `AttribPool` & readme examples for more details. + */ +export const enum GLType { + I8 = 0x1400, + U8 = 0x1401, + I16 = 0x1402, + U16 = 0x1403, + I32 = 0x1404, + U32 = 0x1405, + F32 = 0x1406, +}; + +/** + * Conversion from `GLType` to `Type`. + */ +export const GL2TYPE = { + [GLType.I8]: Type.I8, + [GLType.U8]: Type.U8, + [GLType.I16]: Type.I16, + [GLType.U16]: Type.U16, + [GLType.I32]: Type.I32, + [GLType.I32]: Type.I32, + [GLType.U32]: Type.U32, + [GLType.F32]: Type.F32, +}; + +/** + * Conversion from `Type` to `GLType`. + */ +export const TYPE2GL = { + [Type.I8]: GLType.I8, + [Type.U8]: GLType.U8, + [Type.I16]: GLType.I16, + [Type.U16]: GLType.U16, + [Type.I32]: GLType.I32, + [Type.I32]: GLType.I32, + [Type.U32]: GLType.U32, + [Type.F32]: GLType.F32, +}; diff --git a/packages/vector-pools/src/array-list.ts b/packages/vector-pools/src/array-list.ts new file mode 100644 index 0000000000..237080fe3d --- /dev/null +++ b/packages/vector-pools/src/array-list.ts @@ -0,0 +1,72 @@ +import { StridedVec, Vec } from "@thi.ng/vectors"; +import { AVecList } from "./alist"; +import { VecFactory } from "./api"; + +export class VecArrayList extends AVecList { + + items: T[]; + + /** + * + * @param buffer + * @param capacity + * @param size + * @param cstride + * @param estride + * @param start + */ + constructor( + buffer: Vec, + capacity: number, + size: number, + start = 0, + cstride = 1, + estride = size, + factory?: VecFactory, + ) { + super(buffer, capacity, size, cstride, estride, start, factory); + this.items = []; + } + + *[Symbol.iterator]() { + yield* this.items; + } + + get length() { + return this.items.length; + } + + add() { + const v: T = this.alloc(); + if (v) { + this.items.push(v); + } + return v; + } + + insert(i: number) { + if (!this.length && i !== 0) return; + const v: T = this.alloc(); + if (v) { + this.items.splice(i, 0, v); + } + return v; + } + + remove(v: T) { + const idx = this.items.indexOf(v); + if (idx >= 0) { + this.freeIDs.push(v.offset); + this.items.splice(idx, 1); + return true; + } + } + + has(v: T) { + return this.items.indexOf(v) >= 0; + } + + nth(n: number) { + return this.items[n]; + } +} diff --git a/packages/vector-pools/src/attrib-pool.ts b/packages/vector-pools/src/attrib-pool.ts new file mode 100644 index 0000000000..0b47bccb79 --- /dev/null +++ b/packages/vector-pools/src/attrib-pool.ts @@ -0,0 +1,339 @@ +import { + assert, + IObjectOf, + IRelease, + TypedArray +} from "@thi.ng/api"; +import { align, Pow2 } from "@thi.ng/binary"; +import { MemPool, SIZEOF, wrap } from "@thi.ng/malloc"; +import { range } from "@thi.ng/transducers"; +import { ReadonlyVec, Vec } from "@thi.ng/vectors"; +import { asNativeType } from "./convert"; +import { + AttribPoolOpts, + AttribSpec, +} from "./api"; + +/* + * 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 + */ +export class AttribPool implements + IRelease { + + attribs: IObjectOf; + order: string[]; + specs: IObjectOf; + opts: AttribPoolOpts; + pool: MemPool; + addr: number; + capacity: number; + + byteStride: number; + maxAttribSize: number; + + constructor( + pool: number | ArrayBuffer | MemPool, + capacity: number, + specs: IObjectOf, + opts?: AttribPoolOpts + ) { + this.opts = { + resizable: true, + ...opts + }; + this.pool = !(pool instanceof MemPool) ? + new MemPool(pool, this.opts.mempool) : + pool; + this.opts = opts; + this.capacity = capacity; + this.specs = {}; + this.attribs = {}; + this.order = []; + this.byteStride = 1; + this.maxAttribSize = 1; + this.addAttribs(specs, true); + } + + bytes() { + return new Uint8Array(this.pool.buf, this.addr, this.capacity * this.byteStride); + } + + release(releasePool = true) { + if (releasePool && this.pool) { + this.pool.release(); + } + delete this.pool; + delete this.attribs; + delete this.specs; + return true; + } + + addAttribs(specs: IObjectOf, alloc = false) { + const [newStride, maxSize] = this.computeStride(specs); + this.maxAttribSize = maxSize; + if (newStride != this.byteStride) { + this.realign(newStride); + } + this.validateSpecs(specs, newStride); + this.byteStride = newStride; + if (alloc) { + const addr = this.pool.malloc(this.capacity * this.byteStride); + assert(addr > 0, `out of memory`); + this.addr = addr; + } + this.initDefaults(specs); + } + + attribValue(id: string, i: number): number | Vec { + const spec = this.specs[id]; + assert(!!spec, `invalid attrib: ${id}`); + if (i >= this.capacity) return; + 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; + const size = spec.size; + if (size > 1) { + for (let i = 0, j = 0, n = this.capacity; i < n; i++ , j += stride) { + yield buf.subarray(j, j + size); + } + } else { + for (let i = 0, n = this.capacity; i < n; i++) { + yield buf[i * stride]; + } + } + } + + setAttribValue(id: string, index: number, v: number | ReadonlyVec) { + const spec = this.specs[id]; + assert(!!spec, `invalid attrib: ${id}`); + this.ensure(index); + const buf = this.attribs[id]; + index *= spec.stride; + const isNum = typeof v === "number"; + assert( + () => (!isNum && spec.size > 1) || (isNum && spec.size === 1), + `incompatible value for attrib: ${id}` + ); + if (!isNum) { + assert( + (v).length <= spec.size, + `wrong attrib val size, expected ${spec.size}, got ${(v).length}` + ); + buf.set(v, index); + } else { + buf[index] = v; + } + return this; + } + + setAttribValues(id: string, vals: (number | ReadonlyVec)[]) { + 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); + const buf = this.attribs[id]; + const isNum = typeof v === "number"; + assert( + () => (!isNum && spec.size > 1) || (isNum && spec.size === 1), + `incompatible value(s) for attrib: ${id}` + ); + if (!isNum) { + assert( + (v).length <= spec.size, + `wrong attrib val size, expected ${spec.size}, got ${(v).length}` + ); + for (let i = 0; i < n; i++) { + buf.set(vals[i], i * stride); + } + } else { + for (let i = 0; i < n; i++) { + buf[i * stride] = vals[i]; + } + } + } + + removeAttrib(id: string) { + if (!this.attribs[id]) return false; + delete this.attribs[id]; + delete this.specs[id]; + this.updateOrder(); + const [stride, size] = this.computeStride(this.specs, false); + this.maxAttribSize = size; + this.realign(stride); + } + + ensure(newCapacity: number, fill = false) { + if (newCapacity <= this.capacity) return; + assert(this.opts.resizable, `pool resizing disabled`); + // TODO add realloc() + const newAddr = this.pool.malloc(newCapacity * this.byteStride); + assert(newAddr > 0, `out of memory`); + for (let id in this.specs) { + const a = this.specs[id]; + const buf = wrap( + asNativeType(a.type), + this.pool.buf, + newAddr + (a.byteOffset || 0), + (newCapacity - 1) * a.stride + a.size + ); + buf.set(this.attribs[id]); + this.attribs[id] = buf; + } + if (fill) { + this.setDefaults(this.specs, this.capacity, newCapacity); + } + this.pool.free(this.addr); + this.addr = newAddr; + this.capacity = newCapacity; + } + + protected computeStride(specs: IObjectOf, inclExisting = true) { + let maxStride = inclExisting ? this.byteStride : 1; + let maxSize = inclExisting ? this.maxAttribSize : 1; + for (let id in specs) { + const a = specs[id]; + const size = SIZEOF[asNativeType(a.type)]; + maxSize = Math.max(maxSize, size); + maxStride = Math.max(maxStride, a.byteOffset + a.size * size); + } + return [align(maxStride, maxSize), maxSize]; + } + + protected validateSpecs(specs: IObjectOf, stride = this.byteStride) { + for (let id in specs) { + assert(!this.attribs[id], `attrib: ${id} already exists`); + const a = specs[id]; + const size = SIZEOF[asNativeType(a.type)]; + const isNum = typeof a.default === "number"; + assert( + () => (!isNum && a.size === (a.default).length) || (isNum && a.size === 1), + `incompatible default value for attrib: ${id}, expected size ${a.size}` + ); + assert( + a.byteOffset % size === 0, + `invalid offset for attrib: ${id}, expected multiple of ${size}` + ); + a.stride = stride / size; + this.specs[id] = a; + } + this.updateOrder(); + } + + protected updateOrder() { + this.order = Object.keys(this.specs).sort( + (a, b) => this.specs[a].byteOffset - this.specs[b].byteOffset + ); + } + + protected initDefaults(specs: IObjectOf, start = 0, end = this.capacity) { + for (let id in specs) { + const a = specs[id]; + this.attribs[id] = wrap( + asNativeType(a.type), + this.pool.buf, + this.addr + (a.byteOffset || 0), + (this.capacity - 1) * a.stride + a.size + ); + } + this.setDefaults(specs, start, end); + } + + protected setDefaults(specs: IObjectOf, start = 0, end = this.capacity) { + for (let id in specs) { + const a = specs[id]; + if (a.default == null) continue; + const buf = this.attribs[id]; + const s = a.stride; + const v = a.default; + if (typeof v === "number") { + for (let i = start; i < end; i++) { + buf[i * s] = v; + } + } else { + for (let i = start; i < end; i++) { + buf.set(v, i * s); + } + } + } + } + + protected realign(newByteStride: number) { + if (this.order.length === 0 || newByteStride === this.byteStride) return; + console.warn(`realigning ${this.byteStride} -> ${newByteStride}...`); + const grow = newByteStride > this.byteStride; + let newAddr = this.addr; + if (grow) { + assert(this.opts.resizable, `pool resizing disabled`); + // TODO realloc + newAddr = this.pool.malloc(this.capacity * newByteStride); + assert(newAddr > 0, `out of memory`); + } else if (!this.opts.resizable) { + return; + } + const sameBlock = newAddr === this.addr; + const num = this.capacity - 1; + const attribs = this.attribs; + const newAttribs: IObjectOf<[TypedArray, number]> = {}; + const specs = this.specs; + const order = grow ? [...this.order].reverse() : this.order; + // create resized attrib views (in old or new address space) + for (let id in specs) { + const a = specs[id]; + const type = asNativeType(a.type); + const dStride = newByteStride / SIZEOF[type]; + newAttribs[id] = [ + wrap( + type, + this.pool.buf, + newAddr + a.byteOffset, + num * dStride + a.size + ), + dStride + ]; + } + // process in opposite directions based on new stride size + for (let i of newByteStride < this.byteStride ? range(num + 1) : range(num, -1, -1)) { + // ...in offset order to avoid successor attrib vals + for (let id of order) { + const a = specs[id]; + const sStride = a.stride; + const src = attribs[id]; + const [dest, dStride] = newAttribs[id]; + if (typeof a.default === "number") { + dest[i * dStride] = src[i * sStride]; + } else { + const j = i * sStride; + sameBlock ? + (grow ? dest : src).copyWithin(i * dStride, j, j + a.size) : + dest.set(src.subarray(j, j + a.size), i * dStride); + } + } + } + if (this.addr != newAddr) { + this.pool.free(this.addr); + this.addr = newAddr; + } + this.byteStride = newByteStride; + for (let id in newAttribs) { + const a = newAttribs[id]; + attribs[id] = a[0]; + specs[id].stride = a[1]; + } + } +} diff --git a/packages/vector-pools/src/convert.ts b/packages/vector-pools/src/convert.ts new file mode 100644 index 0000000000..65e497132c --- /dev/null +++ b/packages/vector-pools/src/convert.ts @@ -0,0 +1,23 @@ +import { Type } from "@thi.ng/malloc"; +import { GL2TYPE, GLType, TYPE2GL } from "./api"; + +/** + * Returns canonical `Type` value of `type` by first attempting to + * resolve it as `GLType` enum. + * + * ``` + * nativeType(GLType.F32) => Type.F32 + * nativeType(Type.F32) => Type.F32 + * ``` + * + * @param type + */ +export const asNativeType = (type: GLType | Type): Type => { + const t = GL2TYPE[type]; + return t !== undefined ? t : type; +}; + +export const asGLType = (type: GLType | Type): GLType => { + const t = TYPE2GL[type]; + return t !== undefined ? t : type; +}; diff --git a/packages/vector-pools/src/index.ts b/packages/vector-pools/src/index.ts new file mode 100644 index 0000000000..2a262e8c89 --- /dev/null +++ b/packages/vector-pools/src/index.ts @@ -0,0 +1,7 @@ +export * from "./api"; +export * from "./alist"; +export * from "./array-list"; +export * from "./attrib-pool"; +export * from "./linked-list"; +export * from "./vec-pool"; +export * from "./wrap"; diff --git a/packages/vector-pools/src/linked-list.ts b/packages/vector-pools/src/linked-list.ts new file mode 100644 index 0000000000..7155d7a0f4 --- /dev/null +++ b/packages/vector-pools/src/linked-list.ts @@ -0,0 +1,156 @@ +import { StridedVec, Vec } from "@thi.ng/vectors"; +import { AVecList } from "./alist"; +import { VecFactory } from "./api"; + +export class VecLinkedList extends AVecList { + + head: T; + tail: T; + readonly closed: boolean; + + protected _length: number; + + /** + * + * @param closed + * @param buffer + * @param capacity + * @param size + * @param factory + * @param cstride + * @param estride + * @param start + */ + constructor( + closed: boolean, + buffer: Vec, + capacity: number, + size: number, + start = 0, + cstride = 1, + estride = size, + factory?: VecFactory + ) { + super(buffer, capacity, size, cstride, estride, start, factory); + this.closed = closed; + this.head = null; + this.tail = null; + this._length = 0; + } + + *[Symbol.iterator]() { + if (this._length) { + let v: any = this.head; + const first = v; + do { + yield v; + v = v.next; + } while (v && v !== first); + } + } + + get length() { + return this._length; + } + + add(): T { + const v: any = this.alloc(); + if (v) { + if (this.tail) { + v.prev = this.tail; + (this.tail).next = v; + this.tail = v; + if (this.closed) { + v.next = this.head; + (this.head).prev = v; + } + this._length++; + } else { + this.tail = this.head = v; + v.next = v.prev = this.closed ? v : null; + this._length++; + } + } + return v; + } + + insert(i: number): T { + if (!this._length) { + return i === 0 ? this.add() : undefined; + } + const q: any = this.nth(i); + if (!q) return; + const v: any = this.alloc(); + if (v) { + if (this.head === q) { + this.head = v; + } + v.next = q; + v.prev = q.prev; + if (q.prev) { + q.prev.next = v; + } + q.prev = v; + this._length++; + } + return v; + } + + remove(vec: T): boolean { + if (this.has(vec)) { + this._length--; + this.freeIDs.push(vec.offset); + const v: any = vec; + if (v.prev) { + v.prev.next = v.next; + } + if (this.head === v) { + this.head = this._length ? v.next : null; + } + if (v.next) { + v.next.prev = v.prev; + } + if (this.tail === v) { + this.tail = this._length ? v.prev : null; + } + delete v.prev; + delete v.next; + return true; + } + } + + has(value: T) { + let v: any = this.head; + const first = v; + do { + if (v === value) { + return true; + } + v = v.next; + } while (v && v !== first); + return false; + } + + nth(n: number): T { + if (n < 0) { + n += this._length; + } + if (n < 0 || n >= this._length) { + return; + } + let v; + if (n <= this._length >> 1) { + v = this.head; + while (n-- > 0 && v) { + v = v.next; + } + } else { + v = this.tail; + n = this._length - n - 1; + while (n-- > 0 && v) { + v = v.prev; + } + } + return v; + } +} diff --git a/packages/vector-pools/src/vec-pool.ts b/packages/vector-pools/src/vec-pool.ts new file mode 100644 index 0000000000..1351e6d61f --- /dev/null +++ b/packages/vector-pools/src/vec-pool.ts @@ -0,0 +1,106 @@ +import { TypedArray } from "@thi.ng/api"; +import { isTypedArray } from "@thi.ng/checks"; +import { + MemPool, + MemPoolOpts, + MemPoolStats, + Type +} from "@thi.ng/malloc"; +import { IVector } from "@thi.ng/vectors"; +import { GLType, IVecPool } from "./api"; +import { asNativeType } from "./convert"; +import { wrap } from "./wrap"; + +export class VecPool implements + IVecPool { + + pool: MemPool; + + constructor(pool: MemPool); + constructor(buf: number | ArrayBuffer, opts?: Partial); + constructor(pool: any, opts?: Partial) { + this.pool = !(pool instanceof MemPool) ? + new MemPool(pool, opts) : + pool; + } + + stats(): MemPoolStats { + return this.pool.stats(); + } + + malloc(size: number, type: GLType | Type = Type.F32): TypedArray { + return this.pool.callocAs(asNativeType(type), size); + } + + mallocWrapped( + size: number, + stride = 1, + type: GLType | Type = Type.F32 + ): IVector { + const buf = this.pool.callocAs(asNativeType(type), size * stride); + return wrap(buf, size, 0, stride); + + } + + /** + * Intended to provide individual vector views of a larger + * underlying buffer. Attempts to allocate a single block of + * sufficient memory to hold `num` vectors of `size` elements and if + * successful returns array of vectors mapping the buffer with given + * stride lengths (both component and element strides can be + * provided). + * + * *Note:* Since all result vectors share the same continuous memory + * block, freeing any of them from the pool will invalidate all of + * them. + * + * Also see: + * - `Vec2.mapBuffer()` + * - `Vec3.mapBuffer()` + * - `Vec4.mapBuffer()` + * - `NDArray1.mapBuffer()` + * + * @param num + * @param size + * @param cstride + * @param estride + * @param type + */ + mallocArray( + num: number, + size: number, + cstride = 1, + estride = size, + type: GLType | Type = Type.F32 + ): IVector[] { + const buf = this.malloc( + Math.max(cstride, estride, size) * num, + asNativeType(type) + ); + if (!buf) return; + const res: IVector[] = []; + for (let i = 0; i < num; i += estride) { + res.push(wrap(buf, size, i, cstride)); + } + return res; + } + + free(vec: IVector | TypedArray) { + const buf = (vec).buf; + return buf ? + isTypedArray(buf) ? + this.pool.free(buf) : + false : + this.pool.free(vec); + } + + freeAll() { + this.pool.freeAll(); + } + + release() { + const res = this.pool.release(); + res && delete this.pool; + return res; + } +} diff --git a/packages/vector-pools/src/wrap.ts b/packages/vector-pools/src/wrap.ts new file mode 100644 index 0000000000..5c8f62e366 --- /dev/null +++ b/packages/vector-pools/src/wrap.ts @@ -0,0 +1,22 @@ +import { + gvec, + IVector, + Vec, + Vec2, + Vec3, + Vec4 +} from "@thi.ng/vectors"; + +export const wrap = + (buf: Vec, size: number, idx: number, stride: number): IVector => { + switch (size) { + case 2: + return new Vec2(buf, idx, stride); + case 3: + return new Vec3(buf, idx, stride); + case 4: + return new Vec4(buf, idx, stride); + default: + return gvec(buf, size, idx, stride); + } + }; diff --git a/packages/vector-pools/test/attribs.ts b/packages/vector-pools/test/attribs.ts new file mode 100644 index 0000000000..7a1d4ef7d9 --- /dev/null +++ b/packages/vector-pools/test/attribs.ts @@ -0,0 +1,26 @@ +import { AttribPool } from "../src/attrib-pool"; +import { Type } from "@thi.ng/malloc"; +// import * as assert from "assert"; + +describe("vector-pools", () => { + it("attribs", () => { + const pool = new AttribPool( + 0x100, + 8, + { + pos: { type: Type.F32, default: [0, 0], size: 2, byteOffset: 0 }, + 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 }, + } + ); + 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]); + }); +}); diff --git a/packages/vector-pools/test/index.ts b/packages/vector-pools/test/index.ts new file mode 100644 index 0000000000..b8c58a8837 --- /dev/null +++ b/packages/vector-pools/test/index.ts @@ -0,0 +1,6 @@ +// import * as assert from "assert"; +// import * as vp from "../src/index"; + +describe("vector-pools", () => { + it("tests pending"); +}); diff --git a/packages/vector-pools/test/tsconfig.json b/packages/vector-pools/test/tsconfig.json new file mode 100644 index 0000000000..2c9c12a650 --- /dev/null +++ b/packages/vector-pools/test/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../../tsconfig.json", + "compilerOptions": { + "outDir": "../build", + "module": "commonjs", + }, + "include": [ + "./**/*.ts", + "../src/**/*.ts" + ] +} \ No newline at end of file diff --git a/packages/vector-pools/tsconfig.json b/packages/vector-pools/tsconfig.json new file mode 100644 index 0000000000..bcf03f18b4 --- /dev/null +++ b/packages/vector-pools/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": ".", + "module": "es6", + "target": "es6" + }, + "include": [ + "./src/**/*.ts" + ] +} \ No newline at end of file diff --git a/packages/vectors/.npmignore b/packages/vectors/.npmignore index d703bda97a..67d0c55714 100644 --- a/packages/vectors/.npmignore +++ b/packages/vectors/.npmignore @@ -1,10 +1,13 @@ +.cache +.meta +.nyc_output +*.gz +*.html +*.tgz build coverage dev doc src* test -.nyc_output tsconfig.json -*.tgz -*.html diff --git a/packages/vectors/CHANGELOG.md b/packages/vectors/CHANGELOG.md index b4a0581c72..9bdfcb3e20 100644 --- a/packages/vectors/CHANGELOG.md +++ b/packages/vectors/CHANGELOG.md @@ -3,6 +3,33 @@ 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/vectors@1.4.12...@thi.ng/vectors@2.0.0) (2019-01-21) + + +### Bug Fixes + +* **vectors:** fix NaNs in Mat23.scaleWithCenter ([92bce73](https://github.com/thi-ng/umbrella/commit/92bce73)) + + +### Build System + +* update package build scripts & outputs, imports in ~50 packages ([b54b703](https://github.com/thi-ng/umbrella/commit/b54b703)) + + +### BREAKING CHANGES + +* enabled multi-outputs (ES6 modules, CJS, UMD) + +- build scripts now first build ES6 modules in package root, then call + `scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` +- all imports MUST be updated to only refer to package level + (not individual files anymore). tree shaking in user land will get rid of + all unused imported symbols. + + + + + ## [1.4.12](https://github.com/thi-ng/umbrella/compare/@thi.ng/vectors@1.4.11...@thi.ng/vectors@1.4.12) (2019-01-02) **Note:** Version bump only for package @thi.ng/vectors diff --git a/packages/vectors/README.md b/packages/vectors/README.md index cc8b5bc054..faeb318420 100644 --- a/packages/vectors/README.md +++ b/packages/vectors/README.md @@ -1,6 +1,6 @@ # @thi.ng/vectors -[![npm version](https://img.shields.io/npm/v/@thi.ng/vectors.svg)](https://www.npmjs.com/package/@thi.ng/vectors) +[![npm (scoped)](https://img.shields.io/npm/v/@thi.ng/vectors.svg)](https://www.npmjs.com/package/@thi.ng/vectors) ![npm downloads](https://img.shields.io/npm/dm/@thi.ng/vectors.svg) [![Twitter Follow](https://img.shields.io/twitter/follow/thing_umbrella.svg?style=flat-square&label=twitter)](https://twitter.com/thing_umbrella) @@ -10,14 +10,32 @@ This project is part of the - [About](#about) - - [Vectors](#vectors) - - [Matrices](#matrices) + - [Features](#features) + - [Related packages](#related-packages) - [Installation](#installation) - [Dependencies](#dependencies) - [Usage examples](#usage-examples) - - [Basics](#basics) - - [Vector classes & interleaved vectors in large buffer](#vector-classes--interleaved-vectors-in-large-buffer) - - [Image RGB grayscale conversion](#image-rgb-grayscale-conversion) +- [API](#api) + - [Constants](#constants) + - [Component setters & copying](#component-setters--copying) + - [Component swizzling](#component-swizzling) + - [Vector creation](#vector-creation) + - [Basic vector math](#basic-vector-math) + - [Multiply-add](#multiply-add) + - [Constraints](#constraints) + - [Cross product](#cross-product) + - [Dot product](#dot-product) + - [Interpolation](#interpolation) + - [Normalization / magnitude](#normalization--magnitude) + - [Distances](#distances) + - [Orientation](#orientation) + - [Rotations](#rotations) + - [Polar / cartesian conversion](#polar--cartesian-conversion) + - [Randomness](#randomness) + - [Unary vector math ops](#unary-vector-math-ops) + - [Vector array batch processing](#vector-array-batch-processing) + - [Comparison / equality](#comparison--equality) + - [Code generator](#code-generator) - [Authors](#authors) - [License](#license) @@ -25,330 +43,350 @@ This project is part of the ## About -This package provides vector and matrix operations as plain functions -and class wrappers with fluid interface. All functions support any array -/ typed array storage, incl. mapped views of larger buffers (e.g. for -WebGL / WASM interop, pixel buffers). Additionally, vectors support -flexible data layouts, incl. [AOS / -SOA](https://en.wikipedia.org/wiki/AOS_and_SOA), striped, interleaved, -aligned etc. +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). + +### 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. +- 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 + versions based on given vector arguments. +- Highly modular: Each function is defined in its own submodule / file. + In addition to each generic multi-method base function, all + fixed-length optimized versions are exported too. E.g. If + [`add`](https://github.com/thi-ng/umbrella/tree/master/packages/vectors/src/add.ts) + performs vector addition on arbitrary-length vectors, `add2`, `add3`, + `add4` are the optimized version for fixed-length vectors... +- Extensible: Custom vector ops can be defined in a similar manner using + the provided code generation helpers (see + [vop.ts](https://github.com/thi-ng/umbrella/tree/master/packages/vectors/src/internal/vop.ts) + and + [codegen.ts](https://github.com/thi-ng/umbrella/tree/master/packages/vectors/src/internal/codegen.ts) + for details). +- Immutable by default: Each operation producing a vector result takes + an output vector as first argument. If `null`, the vector given as 2nd + argument will be used as output (i.e. for mutation). +- Strided vector support is handled via the lightweight + [`Vec2/3/4`](https://github.com/thi-ng/umbrella/tree/master/packages/vectors/src/vec2.ts) + class wrappers and the + [`gvec()`](https://github.com/thi-ng/umbrella/tree/master/packages/vectors/src/gvec.ts) + proxy (for generic, arbitrary-length vectors). These types behave like + normal arrays (for read/write operations) and are also iterable. A + subset of functions (suffixed with `S`, e.g. + [`addS`](https://github.com/thi-ng/umbrella/tree/master/packages/vectors/src/adds.ts) + vs. `add`) also support striding without the need for extra class + wrappers. This is handled via additional index and stride arguments + for each input/output vector. These functions are only available for + sizes 2 / 3 / 4, though. +- Random vector functions support the `IRandom` interface defined by + [@thi.ng/random](https://github.com/thi-ng/umbrella/tree/master/packages/random) + to work with custom (P)RNGs. If omitted, the built-in `Math.random()` + will be used. + +### Related packages + +- [@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/vector-pools](https://github.com/thi-ng/umbrella/tree/master/packages/vector-pools) - operations on memory mapped data -**This package will soon be replaced by the currently still unreleased -[@thi.ng/vectors3](https://github.com/thi-ng/umbrella/tree/feature/vec-refactor/packages/vectors3) -and -[@thi.ng/matrices](https://github.com/thi-ng/umbrella/tree/feature/vec-refactor/packages/matrices) -packages** - -### Vectors +## Installation -In addition to [arbitrary sized -vectors](https://github.com/thi-ng/umbrella/tree/master/packages/vectors/src/gvec.ts), -the library provides these optimized fixed-sized versions: +```bash +yarn add @thi.ng/vectors +``` -- [Vec2](https://github.com/thi-ng/umbrella/tree/master/packages/vectors/src/vec2.ts) -- [Vec3](https://github.com/thi-ng/umbrella/tree/master/packages/vectors/src/vec3.ts) -- [Vec4](https://github.com/thi-ng/umbrella/tree/master/packages/vectors/src/vec4.ts) +## Dependencies -#### Vector classes +- [@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/equiv](https://github.com/thi-ng/umbrella/tree/master/packages/equiv) +- [@thi.ng/errors](https://github.com/thi-ng/umbrella/tree/master/packages/errors) +- [@thi.ng/math](https://github.com/thi-ng/umbrella/tree/master/packages/math) +- [@thi.ng/random](https://github.com/thi-ng/umbrella/tree/master/packages/random) +- [@thi.ng/transducers](https://github.com/thi-ng/umbrella/tree/master/packages/transducers) -All of the vector operations listed below are also available via class -wrappers of strided buffer views. These vector classes (`Vec2/3/4`) are -array-like themselves and provide array index and `.x`, `.y`, `.z`, `.w` -property accessors (including `.length`). The `GVec` class wrapper only -provides `.length` read access and element access via `getAt()` and -`setAt()`. All classes are iterable and provide `toString()` and -`toJSON()` implementations. +## Usage examples ```ts -buf = [0, 1, 0, 2, 0, 3]; +import * as v from "@thi.ng/vectors"; -// create Vec3 view from index 1, w/ stride 2 -a = new v.Vec3(buf, 1, 2); +// immutable vector addition (1st arg is result) +v.add([], [1, 2, 3, 4], [10, 20, 30, 40]) +// [11, 22, 33, 44] -a[0] *= 10; -a[1] *= 100; -a[2] *= 1000; +// mutable addition (if first arg is null) +a = [1, 2, 3]; +v.add(null, a, a); +// [2, 4, 6] -a.x // 10 -a.y // 200 -a.z // 3000 -a.length // 3 +// multiply-add (o = a + b * c) +v.madd([], [1, 2], [10, 20], [0.5, 0.25]); +// [6, 7] -// iterable -[...a] -// [ 10, 200, 3000 ] +// multiply-add w/ scalar (o = a + b * n) +v.maddN([], [1, 2], [10, 20], 0.5); +// [6, 12] -buf -// [ 0, 10, 0, 200, 0, 3000 ] -``` +// scalar addition w/ arbitrary length & strided vector +v.addN([], gvec([0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0], 3, 1, 4), 10); +// [11, 12, 13] -#### Supported operations - -Note: Most functions are provided in different (optimized) versions, -depending on vector size. E.g. `add` performs vector addition for -arbitrary sizes, `add2` for 2D vectors, `add3` for 3D, `add4` for 4D... -**Class wrapper methods use the non-suffixed naming.** - -All vector operations (regardless of size) operate on any array-like -buffer and accept optional start indices and component strides (number -of elements (+1) between individual vector components). This allows for -zero-copy vector operations on sections of larger buffers. The default -start index is 0, default stride 1. See examples below and -[tests](https://github.com/thi-ng/umbrella/tree/master/packages/vectors/test/). - -Naming conventions (suffixes): - -- `N` = uniform: 2nd or 3rd arg is a scalar which will be used for all - vector components, e.g. `setN3([], 0) => [0, 0, 0]` -- `S` = scalar: args are individual scalar values, - e.g. `setS3([], 10, 20, 30) => [10, 20, 30]` -- `o` = output: operation writes to separate output vector (1st arg), e.g. - `add2o([], [1,2], [10, 20])` - -| Operation | Generic | 2D | 3D | 4D | -|---------------------------------|--------------|-----------------------|---------------------|------------------| -| Get vector (dense copy) | `get` | `get2` | `get3` | `get4` | -| Set vector components (vector) | `set` | `set2` | `set3` | `set4` | -| Set vector components (uniform) | `setN` | `setN2` | `setN3` | `setN4` | -| Set vector components (scalars) | | `setS2` | `setS3` | `setS4` | -| Swizzle vector components | | `swizzle2` | `swizzle3` | `swizzle4` | -| Swap vectors | | `swap2` | `swap3` | `swap4` | -| Equality (w/ epsilon) | `eqDelta` | `eqDelta2` | `eqDelta3` | `eqDelta4` | -| Vector addition | `add` | `add2` | `add3` | `add4` | -| | | `add2o` | `add3o` | `add4o` | -| Vector subtraction | `sub` | `sub2` | `sub3` | `sub4` | -| | | `sub2o` | `sub3o` | `sub4o` | -| Vector multiplication | `mul` | `mul2` | `mul3` | `mul4` | -| | | `mul2o` | `mul3o` | `mul4o` | -| Vector division | `div` | `div2` | `div3` | `div4` | -| | | `div2o` | `div3o` | `div4o` | -| Uniform scalar addition | `addN` | `addN2` | `addN3` | `addN4` | -| | | `addN2o` | `addN3o` | `addN4o` | -| Uniform scalar subtraction | `subN` | `subN2` | `subN3` | `subN4` | -| | | `subN2o` | `subN3o` | `subN4o` | -| Uniform scalar multiply | `mulN` | `mulN2` | `mulN3` | `mulN4` | -| | | `mulN2o` | `mulN3o` | `mulN4o` | -| Uniform scalar multiply | `divN` | `divN2` | `divN3` | `divN4` | -| | | `divN2o` | `divN3o` | `divN4o` | -| Vector negation | `neg` | `neg2` | `neg3` | `neg4` | -| Multiply-add vectors | `madd` | `madd2` | `madd3` | `madd4` | -| Multiply-add scalar | `maddN` | `maddN2` | `maddN3` | `maddN4` | -| Linear interpolation (vector) | `mix` | `mix2` | `mix3` | `mix4` | -| | | `mix2o` | `mix3o` | `mix4o` | -| Linear interpolation (uniform) | `mixN` | `mixN2` | `mixN3` | `mixN4` | -| | | `mixN2o` | `mixN3o` | `mixN4o` | -| Bilinear interpolation* | | `mixBilinear2` | `mixBilinear3` | `mixBilinear4` | -| Dot product | `dot` | `dot2` | `dot3` | `dot4` | -| Cross product | | `cross2` | `cross3` | | -| Magnitude | `mag` | `mag2` | `mag3` | `mag4` | -| Magnitude (squared) | `magSq` | `magSq2` | `magSq3` | `magSq4` | -| Normalize (w/ opt length) | `normalize` | `normalize2` | `normalize3` | `normalize4` | -| Limit to length | | `limit2` | `limit3` | `limit4` | -| Distance | `dist` | `dist2` | `dist3` | `dist4` | -| Distance (squared) | `distSq` | `distSq2` | `distSq3` | `distSq4` | -| Manhattan distance | | `distManhattan2` | `distManhattan3` | `distManhattan4` | -| Chebyshev distance | | `distChebyshev2` | `distChebyshev3` | `distChebyshev4` | -| Reflection | | `reflect2` | `reflect3` | `reflect4` | -| Refraction | | `refract2` | `refract3` | `refract4` | -| Perpendicular | | `perpendicularLeft2` | | | -| | | `perpendicularRight2` | | | -| RotationX | | | `rotateX3` | | -| RotationY | | | `rotateY3` | | -| RotationZ | | `rotate2` | `rotateZ3` | | -| Rotation around point | | `rotateAroundPoint2` | | | -| Rotation around axis | | | `rotateAroundAxis3` | | -| Heading XY | | `heading2` | `headingXY3` | | -| Heading XZ | | | `headingXZ3` | | -| Heading YZ | | | `headingYZ3` | | -| Angle between vectors | | `angleBetween2` | `angleBetween3` | | -| Bisector angle | | `bisect2` | | | -| Cartesian -> Polar | | `toPolar2` | `toSpherical3` | | -| Polar -> Cartesian | | `toCartesian2` | `toCartesian3` | | -| Cartesian -> Cylindrical | | | `toCylindrical3` | | -| Cylindrical -> Cartesian | | | `fromCylindrical3` | | -| Minor axis | | `minorAxis2` | `minorAxis3` | `minorAxis4` | -| Major axis | | `majorAxis2` | `majorAxis3` | `majorAxis4` | -| Minimum | `min` | `min2` | `min3` | `min4` | -| Maximum | `max` | `max2` | `max3` | `max4` | -| Range clamping | `clamp` | `clamp2` | `clamp3` | `clamp4` | -| Step (like GLSL) | `step` | `step2` | `step3` | `step4` | -| SmoothStep (like GLSL) | `smoothStep` | `smoothStep2` | `smoothStep3` | `smoothStep4` | -| Absolute value | `abs` | `abs2` | `abs3` | `abs4` | -| Sign (w/ opt epsilon) | `sign` | `sign2` | `sign3` | `sign4` | -| Round down | `floor` | `floor2` | `floor3` | `floor4` | -| Round up | `ceil` | `ceil2` | `ceil3` | `ceil4` | -| Square root | `sqrt` | `sqrt2` | `sqrt3` | `sqrt4` | -| Power (vector) | `pow` | `pow2` | `pow3` | `pow4` | -| Power (uniform) | `powN` | `powN2` | `powN3` | `powN4` | - -(*) Static method in class wrapper - -### Matrices - -All matrix types are in WebGL layout (column major) and densely packed -(stride always 1). **As with vectors, class wrapper methods use the -non-suffixed naming.** - -- [Mat23](https://github.com/thi-ng/umbrella/tree/master/packages/vectors/src/mat23.ts) -- [Mat33](https://github.com/thi-ng/umbrella/tree/master/packages/vectors/src/mat33.ts) -- [Mat44](https://github.com/thi-ng/umbrella/tree/master/packages/vectors/src/mat44.ts) - -| Operation | 2x3 | 3x3 | 4x4 | -|--------------------------------------|-------------------------|---------------|---------------------| -| Set identity* | `identity23` | `identity33` | `identity44` | -| Get matrix components (dense copy) | `get23` | `get33` | `get44` | -| Set matrix components (matrix) | `set23` | `set33` | `set44` | -| Set matrix components (scalars) | `setS23` | `setS33` | `setS44` | -| Create rotation matrix* | | `rotationX33` | `rotationX44` | -| | | `rotationY33` | `rotationY44` | -| | `rotation23` | `rotationZ33` | `rotationZ44` | -| | `rotationAroundPoint23` | | | -| Create scale matrix* (vector) | `scaleV23` | `scaleV33` | `scaleV44` | -| Create scale matrix* (uniform) | `scaleN23` | `scaleN33` | `scaleN44` | -| Create scale matrix* (scalars) | `scaleS23` | `scaleS33` | `scaleS44` | -| | `scaleWithCenter23` | | `scaleWithCenter44` | -| Create translation matrix* (vector) | `translationV23` | | `translationV44` | -| Create translation matrix* (scalars) | `translationS23` | | `translationS44` | -| Create skew matrix* | `skewX23` / `shearX23` | | | -| | `skewY23` / `shearY23` | | | -| Create projection matrix* | | | `projection` | -| | | | `ortho` | -| | | | `frustum` | -| Create camera matrix* | | | `lookAt` | -| Matrix multiply | `mul23` | `mul33` | `mul44` | -| Matrix concatenation* (multiple) | `concat23` | `concat33` | `concat44` | -| Matrix vector multiply | `mulV23` | `mulV33` | `mulV44` (Vec4) | -| | | | `mulV344` (Vec3) | -| Determinant | `det23` | `det33` | `det44` | -| Matrix inversion | `invert23` | `invert33` | `invert44` | -| Matrix transpose | | `transpose33` | `transpose44` | - -(*) Static method in class wrapper +v.dist([1, 2], [100, 200]); +// 221.37072977247917 -## Installation +v.distManhattan([1, 2], [100, 200]); +// 297 -```bash -yarn add @thi.ng/vectors +v.distChebyshev([1, 2], [100, 200]); +// 198 + +v.mixN([], [1, 2], [10, 20], 0.5); +// [5.5, 11] + +v.fromHomogeneous([], [100, 200, 0.5]); +// [200, 400] + +v.swizzle4([], [1, 2], 1, 1, 0, 0); +// [ 2, 2, 1, 1 ] ``` -## Dependencies +## API -- [@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) +### Constants -## Usage examples +- `MAX2` / `MAX3` / `MAX4` - each component `+Infinity` +- `MIN2` / `MIN3` / `MIN4` - each component `-Infinity` +- `ONE2` / `ONE3` / `ONE4` - each component `1` +- `ZERO2` / `ZERO3` / `ZERO4` - each component `0` +- `X2` / `X3` / `X4` - positive X axis +- `Y2` / `Y3` / `Y4` - positive Y axis +- `Z3` / `Z4` - positive Z axis +- `W4` - positive W axis -### Basics +### Component setters & copying -```ts -import * as v from "@thi.ng/vectors"; +- `set` / `set2` / `set3` / `set4` +- `setC` / `setC2` / `setC3` / `setC4` / `setC6` +- `setN` / `setN2` / `setN3` / `setN4` +- `setS` / `setS2` / `setS3` / `setS4` +- `setSN2` / `setSN3` / `setSN4` +- `copy` +- `empty` +- `one` +- `zero` -// raw vector addition -v.add4([1, 2, 3, 4], [10, 20, 30, 40]); -// [ 11, 22, 33, 44 ] +### Component swizzling -// with custom layout -// here 3x 3D vectors in SOA layout: -// [x, x, x, y, y, y, z, z, z] -points = [1, 4, 7, 2, 5, 8, 3, 6, 9]; +- `swizzle2` / `swizzle3` / `swizzle4` +- `swapXY` / `swapXZ` / `swapYZ` -// specify start indices and stride lengths -// update 1st vector -v.add3(points, [100, 200, 300], 0, 0, 3, 1); -// [ 101, 4, 7, 202, 5, 8, 303, 6, 9 ] +### Vector creation -// update 2nd vector -v.add3(points, [100, 200, 300], 1, 0, 3, 1); -// [ 101, 104, 7, 202, 205, 8, 303, 306, 9 ] +Functions to create wrapped vector instances: -// update 3rd vector -v.add3(points, [100, 200, 300], 2, 0, 3, 1); -// [ 101, 104, 107, 202, 205, 208, 303, 306, 309 ] +- `vec2` / `vec2n` +- `vec3` / `vec3n` +- `vec4` / `vec4n` +- `gvec` -// add 1st and 3rd vector and extract result -v.get3(v.add3(points, points, 0, 2, 3, 3), 0, 3); -// [ 208, 410, 612 ] +Wrap existing vanilla vectors: -// re-arrange vector components into new vector -// the last 4 args define component order: +- `asVec2` / `asVec3` / `asVec4` -// YXWZ -v.swizzle4([], [10, 20, 30, 40], 1, 0, 3, 2); -// [ 20, 10, 40, 30 ] +Vanilla vector (array) factories: -// XXZZ -v.swizzle4([], [10, 20, 30, 40], 0, 0, 2, 2); -// [ 10, 10, 30, 30 ] +- `ones` +- `zeroes` -// arbitrary length vectors -norm = v.normalize([1, 2, 3, 4, 5, 6, 7, 8, 6, 4]); -// [ 0.0625, 0.125, 0.1875, 0.25, 0.3125, 0.375, 0.4375, 0.5, 0.375, 0.25 ] +### Basic vector math -v.mag(norm); -// 1 -``` +#### Vector / vector -### Vector classes & interleaved vectors in large buffer +Component wise op with 2 input vectors: -```ts -// element stride 3 + 2 + 4 = 9 -buf = [ - // pos uv color (rgba) - 0,0,0, 0,0, 1,0,0,1, - 100,0,0, 1,0, 1,1,0,1, - 100,100,0, 1,1, 1,0,1,1, - 0,100,0, 0,1, 0,1,1,1, -]; - -// create memory mapped vector instances (using classes) -pos = v.Vec3.mapBuffer(buf, 4, 0, 1, 9); // offset = 0 -uv = v.Vec2.mapBuffer(buf, 4, 3, 1, 9); // offset = 3 -col = v.Vec4.mapBuffer(buf, 4, 5, 1, 9); // offset = 5 - -console.log(`pos: ${pos[1]}, uv: ${uv[1]}, color: ${col[1]}`); -// pos: [100, 0, 0], uv: [1, 0], color: [1, 1, 0, 1] - -// compute centroid -centroid = pos.reduce((c, p) => c.add(p), v.vec3()).divN(pos.length); -// Vec3 { buf: [ 50, 50, 0 ], i: 0, s: 1 } - -// build matrix to transform geometry -tx = v.Mat44.concat( - v.Mat44.scale(0.01), - v.Mat44.translation(centroid.copy().neg()), - v.Mat44.rotationZ(v.rad(90)), -); - -// apply transform to all positions -pos.forEach((p) => tx.mulV3(p)); -``` +- `add` / `add2` / `add3` / `add4` +- `div` / `div2` / `div3` / `div4` +- `mul` / `mul2` / `mul3` / `mul4` +- `sub` / `sub2` / `sub3` / `sub4` +- `mod` / `mod2` / `mod3` / `mod4` +- `pow` / `pow2` / `pow3` / `pow4` -### Image RGB grayscale conversion +#### Vector / scalar -```ts -canvas = document.getElementById("main"); -img = canvas.getContext("2d").getImageData(0,0, canvas.width, canvas.height); - -v.transformVectors1( - // multiply each RGB vector w/ weights - // then use result for all 3 color channels - (a, b, ia, ib, sa, sb) => - v.setN3(a, v.dot3(a, b, ia, ib, sa, sb), ia, sa), - // pixel buffer - img, - // RGB weight coefficients - [0.29, 0.6, 0.11], - // num pixels (RGBA vectors) - canvas.width * canvas.height, - // start indices - 0, 0, - // component strides - 1, 1, - // pixel stride - 4 -); -``` +Component wise op with one input vector and single scalar: + +- `addN` / `addN2` / `addN3` / `addN4` +- `divN` / `divN2` / `divN3` / `divN4` +- `mulN` / `mulN2` / `mulN3` / `mulN4` +- `subN` / `subN2` / `subN3` / `subN4` +- `neg` - same as `mulN(out, v, -1)` +- `modN` / `modN2` / `modN3` / `modN4` +- `powN` / `powN2` / `powN3` / `powN4` + +#### Strided vectors + +Functions for memory mapped, strided vectors (without requiring wrappers): + +- `addS2` / `addS3` / `addS4` +- `divS2` / `divS3` / `divS4` +- `mulS2` / `mulS3` / `mulS4` +- `subS2` / `subS3` / `subS4` + +### Multiply-add + +- `addm` / `addm2` / `addm3` / `addm4` +- `addmN` / `addmN2` / `addmN3` / `addmN4` +- `addW2` / `addW3` / `addW4` / `addW5` +- `madd` / `madd2` / `madd3` / `madd4` +- `maddN` / `maddN2` / `maddN3` / `maddN4` +- `subm` / `subm2` / `subm3` / `subm4` +- `submN` / `submN2` / `submN3` / `submN4` + +### Constraints + +- `clamp` +- `clamp2` / `clamp3` / `clamp4` +- `clampN` / `clampN2` / `clampN3` / `clampN4` +- `clamp01` / `clamp01_2` / `clamp01_3` / `clamp01_4` +- `clamp11` / `clamp11_2` / `clamp11_3` / `clamp11_4` +- `max` / `max2` / `max3` / `max4` +- `min` / `min2` / `min3` / `min4` + +### Cross product + +- `cross2` +- `cross3` +- `orthoNormal3` +- `signedArea2` + +### Dot product + +- `dot` +- `dot2` / `dot3` / `dot4` +- `dotC4` / `dotC6` / `dotC8` +- `dotS2` / `dotS3` / `dotS4` + +### Interpolation + +- `mix` / `mix2` / `mix3` / `mix4` +- `mixN` / `mixN2` / `mixN3` / `mixN4` +- `mixBilinear` / `mixBilinear2` / `mixBilinear3` / `mixBilinear4` +- `mixCubic` +- `mixQuadratic` +- `smoothStep` / `smoothStep2` / `smoothStep3` / `smoothStep4` +- `step` / `step2` / `step3` / `step4` + +### Normalization / magnitude + +- `limit` +- `mag` +- `magSq` / `magSq2` / `magSq3` / `magSq4` +- `normalize` + +### Distances + +- `dist` +- `distSq` / `distSq2` / `distSq3` / `distSq4` +- `distChebyshev` / `distChebyshev2` / `distChebyshev3` / `distChebyshev4` +- `distManhattan` / `distManhattan2` / `distManhattan3` / `distManhattan4` + +### Orientation + +- `angleBetween` +- `angleRatio` +- `bisect2` +- `faceForward` +- `heading` / `headingXY` / `headingXZ` / `headingYZ` +- `perpendicularLeft2` / `perpendicularRight2` +- `project` +- `reflect` +- `refract` + +### Rotations + +(Also see rotation matrices provided by +[@thi.ng/matrices](https://github.com/thi-ng/umbrella/tree/master/packages/matrices)) + +- `rotateAroundAxis3` +- `rotateAroundPoint2` +- `rotateX` \ `rotateY` \ `rotateZ` + +### Polar / cartesian conversion + +- `cartesian` / `cartesian2` / `cartesian3` +- `polar` / `polar2` / `polar3` + +### Randomness + +All ops support custom PRNG impls based on the +[@thi.ng/random](https://github.com/thi-ng/umbrella/tree/master/packages/random) +`IRandom` interface and use `Math.random` by default: + +- `jitter` +- `randNorm` +- `random` / `random2` / `random3` / `random4` + +### Unary vector math ops + +- `abs` / `abs2` / `abs3` / `abs4` +- `acos` / `acos2` / `acos3` / `acos4` +- `asin` / `asin2` / `asin3` / `asin4` +- `ceil` / `ceil2` / `ceil3` / `ceil4` +- `cos` / `cos2` / `cos3` / `cos4` +- `cosh` / `cosh2` / `cosh3` / `cosh4` +- `exp` / `exp2` / `exp3` / `exp4` +- `floor` / `floor2` / `floor3` / `floor4` +- `fract` / `fract2` / `fract3` / `fract4` +- `fromHomogeneous` / `fromHomogeneous3` / `fromHomogeneous4` +- `invert` / `invert2` / `invert3` / `invert4` +- `invSqrt` / `invSqrt2` / `invSqrt3` / `invSqrt4` +- `log` / `log2` / `log3` / `log4` +- `major` / `major2` / `major3` / `major4` +- `minor` / `minor2` / `minor3` / `minor4` +- `round` / `round2` / `round3` / `round4` +- `sign` / `sign2` / `sign3` / `sign4` +- `sin` / `sin2` / `sin3` / `sin4` +- `sinh` / `sinh2` / `sinh3` / `sinh4` +- `sqrt` / `sqrt2` / `sqrt3` / `sqrt4` +- `sum` / `sum2` / `sum3` / `sum4` +- `tan` / `tan2` / `tan3` / `tan4` +- `tanh` / `tanh2` / `tanh3` / `tanh4` +- `trunc` / `trunc2` / `trunc3` / `trunc4` +- `wrap` / `wrap2` / `wrap3` / `wrap4` + +### Vector array batch processing + +Functions to transform flat / strided buffers w/ vector operations: + +- `mapV` / `mapVN` / `mapVV` / `mapVVN` / `mapVVV` + +### Comparison / equality + +- `comparator2` / `comparator3` / `comparator4` +- `eqDelta` / `eqDelta2` / `eqDelta3` / `eqDelta4` +- `eqDeltaS` +- `eqDeltaArray` + +### Code generator + +- `compile` / `compileG` / `compileGHOF` / `compileHOF` +- `defOp` / `defOpS` / `defFnOp` / `defHofOp` +- `defMathNOp` / `defMathOp` +- `vop` + +For more information about the code generator see: + +- [codegen.ts](https://github.com/thi-ng/umbrella/tree/master/packages/vectors/src/internal/codegen.ts) +- [templates.ts](https://github.com/thi-ng/umbrella/tree/master/packages/vectors/src/internal/templates.ts) +- [vop.ts](https://github.com/thi-ng/umbrella/tree/master/packages/vectors/src/internal/vop.ts) ## Authors @@ -356,4 +394,4 @@ v.transformVectors1( ## License -© 2016 - 2018 Karsten Schmidt // Apache Software License 2.0 +© 2018 Karsten Schmidt // Apache Software License 2.0 diff --git a/packages/vectors/bench/index.js b/packages/vectors/bench/index.js deleted file mode 100644 index 94fafa9a84..0000000000 --- a/packages/vectors/bench/index.js +++ /dev/null @@ -1,56 +0,0 @@ -const Benchmark = require("benchmark"); -const vec = require("../index"); - -const setS2Lib = (buf, n) => { - n *= 2; - for (let i = 0; i < n; i += 2) { - vec.setS2(buf, i, i + 1, i); - } - return buf; -}; - -const setS2Plain = (n) => { - const res = new Array(n); - for (let i = 0; i < n; i++) { - res[i] = [i, i + 1]; - } - return res; -}; - -const op2Lib = (buf, n, op, v) => - vec.transformVectors1(op, setS2Lib(buf, n), v, n, 0, 0, 1, 1, 2); - -const op2Plain = (n, op, v) => { - const res = setS2Plain(n); - for (let i = 0; i < n; i++) { - op(res[i], v); - } - return res; -}; - -const add2 = (a, b) => ( - a[0] += b[0], - a[1] += b[1], - a -); - -new Benchmark.Suite() - .add({ name: "set2 1k (lib, array)", fn: () => setS2Lib(new Array(2 * 1024), 1024) }) - .add({ name: "set2 1k (vanilla)", fn: () => setS2Plain(1024) }) - .add({ name: "set2 4k (lib, array)", fn: () => setS2Lib(new Array(2 * 4 * 1024), 4 * 1024) }) - .add({ name: "set2 4k (vanilla)", fn: () => setS2Plain(4 * 1024) }) - .add({ name: "add2 1k (lib, array)", fn: () => op2Lib(new Array(2 * 1024), 1024, vec.add2, [10, 20]) }) - .add({ name: "add2 1k (lib, f32)", fn: () => op2Lib(new Float32Array(2 * 1024), 1024, vec.add2, [10, 20]) }) - .add({ name: "add2 1k (lib, f64)", fn: () => op2Lib(new Float64Array(2 * 1024), 1024, vec.add2, [10, 20]) }) - .add({ name: "add2 1k (vanilla)", fn: () => op2Plain(1024, add2, [10, 20]) }) - .add({ name: "add2 4k (lib, array)", fn: () => op2Lib(new Array(2 * 4 * 1024), 4 * 1024, vec.add2, [10, 20]) }) - .add({ name: "add2 4k (lib, f32)", fn: () => op2Lib(new Float32Array(2 * 4 * 1024), 4 * 1024, vec.add2, [10, 20]) }) - .add({ name: "add2 4k (lib, f64)", fn: () => op2Lib(new Float64Array(2 * 4 * 1024), 4 * 1024, vec.add2, [10, 20]) }) - .add({ name: "add2 4k (vanilla)", fn: () => op2Plain(4 * 1024, add2, [10, 20]) }) - .on("cycle", (event) => - console.log( - event.target.toString(), - `mean: ${(event.target.stats.mean * 1e3).toFixed(5)}sec` - ) - ) - .run({ "async": false }); \ No newline at end of file diff --git a/packages/vectors/package.json b/packages/vectors/package.json index a62ea777f4..7eb66d60e2 100644 --- a/packages/vectors/package.json +++ b/packages/vectors/package.json @@ -1,50 +1,101 @@ { "name": "@thi.ng/vectors", - "version": "1.4.12", - "description": "Vector algebra for fixed & variable sizes, memory mapped, flexible layouts", - "main": "./index.js", + "version": "2.0.0", + "description": "Optimized 2d/3d/4d and arbitrary length vector operations", + "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/vectors", + "homepage": "https://github.com/thi-ng/umbrella/tree/master/packages/", "author": "Karsten Schmidt ", "license": "Apache-2.0", "scripts": { - "build": "yarn run clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module vectors api checks equiv errors math memoize random transducers", + "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 run build && yarn publish --access public", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "doc": "typedoc --mode modules --out doc src", + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", - "benchmark": "^2.1.4", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/api": "^4.2.4", - "@thi.ng/checks": "^1.5.14", - "@thi.ng/errors": "^0.1.12", - "@thi.ng/math": "^0.2.2", - "@thi.ng/transducers": "^2.3.2" + "@thi.ng/api": "^5.0.0", + "@thi.ng/checks": "^2.0.0", + "@thi.ng/equiv": "^1.0.0", + "@thi.ng/errors": "^1.0.0", + "@thi.ng/math": "^1.0.0", + "@thi.ng/memoize": "^1.0.0", + "@thi.ng/random": "^1.0.0", + "@thi.ng/transducers": "^3.0.0" }, "keywords": [ + "2D", + "3D", + "4D", + "abitrary length", + "bilinear", + "cartesian", + "chebyshev", + "clamp", + "code generator", + "cubic", + "data structures", + "distance", + "dot product", + "equality", "ES6", - "matrix", + "faceforward", + "geometry", + "gvec", + "heading", + "homogeneous", + "interpolation", + "manhattan", + "magnitude", + "math", "memory mapped", + "normal", + "normalize", + "polar", + "projection", + "quadratic", + "random", + "reflect", + "refract", + "rotation", + "setter", + "smoothstep", + "step", + "strided", "typescript", "webgl", - "wasm", - "vector algebra" + "vector", + "vec2", + "vec3", + "vec4" ], "publishConfig": { "access": "public" - } + }, + "browserslist": [ + "since 2018-07" + ], + "browser": { + "process": false, + "setTimeout": false + }, + "sideEffects": false } diff --git a/packages/vectors/src/abs.ts b/packages/vectors/src/abs.ts new file mode 100644 index 0000000000..b16e80d60a --- /dev/null +++ b/packages/vectors/src/abs.ts @@ -0,0 +1,5 @@ +import { MultiVecOpV, VecOpV } from "./api"; +import { defFnOp } from "./internal/codegen"; + +export const [abs, abs2, abs3, abs4] = + defFnOp("Math.abs"); diff --git a/packages/vectors/src/acos.ts b/packages/vectors/src/acos.ts new file mode 100644 index 0000000000..8618663a8d --- /dev/null +++ b/packages/vectors/src/acos.ts @@ -0,0 +1,5 @@ +import { MultiVecOpV, VecOpV } from "./api"; +import { defFnOp } from "./internal/codegen"; + +export const [acos, acos2, acos3, acos4] = + defFnOp("Math.acos"); diff --git a/packages/vectors/src/add.ts b/packages/vectors/src/add.ts new file mode 100644 index 0000000000..68bdc2d755 --- /dev/null +++ b/packages/vectors/src/add.ts @@ -0,0 +1,3 @@ +import { defMathOp } from "./internal/codegen"; + +export const [add, add2, add3, add4] = defMathOp("+"); diff --git a/packages/vectors/src/addm.ts b/packages/vectors/src/addm.ts new file mode 100644 index 0000000000..620d94594c --- /dev/null +++ b/packages/vectors/src/addm.ts @@ -0,0 +1,11 @@ +import { MultiVecOpVVV, VecOpVVV } from "./api"; +import { ARGS_VVV, defOp } from "./internal/codegen"; +import { ADDM } from "./internal/templates"; + +/** + * Returns `out = (a + b) * c`. + * + * @see madd + */ +export const [addm, addm2, addm3, addm4] = + defOp(ADDM, ARGS_VVV); diff --git a/packages/vectors/src/addmn.ts b/packages/vectors/src/addmn.ts new file mode 100644 index 0000000000..ebfefbbadc --- /dev/null +++ b/packages/vectors/src/addmn.ts @@ -0,0 +1,9 @@ +import { MultiVecOpVVN, VecOpVVN } from "./api"; +import { ARGS_VVN, defOp } from "./internal/codegen"; +import { ADDM_N } from "./internal/templates"; + +/** + * Returns `out = (a + b) * n`. + */ +export const [addmN, addmN2, addmN3, addmN4] = + defOp(ADDM_N, ARGS_VVN); diff --git a/packages/vectors/src/addn.ts b/packages/vectors/src/addn.ts new file mode 100644 index 0000000000..9c4c98b0fa --- /dev/null +++ b/packages/vectors/src/addn.ts @@ -0,0 +1,3 @@ +import { defMathNOp } from "./internal/codegen"; + +export const [addN, addN2, addN3, addN4] = defMathNOp("+"); diff --git a/packages/vectors/src/adds.ts b/packages/vectors/src/adds.ts new file mode 100644 index 0000000000..13908e35f3 --- /dev/null +++ b/packages/vectors/src/adds.ts @@ -0,0 +1,6 @@ +import { VecOpSVV } from "./api"; +import { defOpS } from "./internal/codegen"; +import { MATH } from "./internal/templates"; + +export const [addS2, addS3, addS4] = + defOpS(MATH("+")); diff --git a/packages/vectors/src/addw.ts b/packages/vectors/src/addw.ts new file mode 100644 index 0000000000..3634cb1515 --- /dev/null +++ b/packages/vectors/src/addw.ts @@ -0,0 +1,39 @@ +import { ReadonlyVec, Vec } from "./api"; +import { maddN } from "./maddn"; +import { mulN } from "./muln"; + +export const addW2 = + (out: Vec, a: ReadonlyVec, b: ReadonlyVec, wa: number, wb: number) => + maddN(out, + mulN(out, a, wa), + b, wb); + +export const addW3 = + (out: Vec, a: ReadonlyVec, b: ReadonlyVec, c: ReadonlyVec, wa: number, wb: number, wc: number) => + maddN(out, + maddN(out, + mulN(out, a, wa), + b, wb), + c, wc); + +export const addW4 = + (out: Vec, a: ReadonlyVec, b: ReadonlyVec, c: ReadonlyVec, d: ReadonlyVec, + wa: number, wb: number, wc: number, wd: number) => + maddN(out, + maddN(out, + maddN(out, + mulN(out, a, wa), b, wb), + c, wc), + d, wd); + +export const addW5 = + (out: Vec, a: ReadonlyVec, b: ReadonlyVec, c: ReadonlyVec, d: ReadonlyVec, e: ReadonlyVec, + wa: number, wb: number, wc: number, wd: number, we: number) => + maddN(out, + maddN(out, + maddN(out, + maddN(out, + mulN(out, a, wa), b, wb), + c, wc), + d, wd), + e, we); diff --git a/packages/vectors/src/angle-between.ts b/packages/vectors/src/angle-between.ts new file mode 100644 index 0000000000..50e8558291 --- /dev/null +++ b/packages/vectors/src/angle-between.ts @@ -0,0 +1,23 @@ +import { absInnerAngle } from "@thi.ng/math"; +import { ReadonlyVec } from "./api"; +import { cross2 } from "./cross"; +import { dot } from "./dot"; +import { mag } from "./mag"; + +export const angleRatio = + (a: ReadonlyVec, b: ReadonlyVec) => + dot(a, b) / (mag(a) * mag(b)); + +export const angleBetween2 = + (a: ReadonlyVec, b: ReadonlyVec, absInner = false) => { + const t = Math.atan2(cross2(a, b), dot(a, b)); + return absInner ? absInnerAngle(t) : t; + }; + +export const angleBetween3 = + (a: ReadonlyVec, b: ReadonlyVec, normalize = true, absInner = false) => { + const t = normalize ? + Math.acos(angleRatio(a, b)) : + Math.acos(dot(a, b)); + return absInner ? absInnerAngle(t) : t; + }; diff --git a/packages/vectors/src/api.ts b/packages/vectors/src/api.ts index c3ece347d7..3f7f631d9a 100644 --- a/packages/vectors/src/api.ts +++ b/packages/vectors/src/api.ts @@ -1,207 +1,114 @@ import { ICopy, - IEqualsDelta, - IEquiv, - NumericArray, IEmpty, + IEqualsDelta, ILength, - ICompare -} from "@thi.ng/api/api"; - -export type Vec = NumericArray; -export type ReadonlyVec = ArrayLike & Iterable; - -export type Mat = NumericArray; -export type ReadonlyMat = ArrayLike & Iterable; - -/** - * A vector operation involving only a single vector. The vector might - * be modified. - */ -export type VecOp1 = (v: Vec, i?: number, s?: number) => T; - -/** - * A vector operation involving 2 vectors. The first vector might be - * modified. - */ -export type VecOp2 = (a: Vec, b: ReadonlyVec, ia?: number, ib?: number, sa?: number, sb?: number) => T; - -/** - * A vector operation involving a vector and a scalar. The vector might - * be modified. - */ -export type VecOpN2 = (a: Vec, n: number, ia?: number, sa?: number) => T; - -/** - * A vector operation involving 2 readonly vectors and storing result - * in output vector `out`. - */ -export type VecOp2o = (out: Vec, a: ReadonlyVec, b: ReadonlyVec, io?: number, ia?: number, ib?: number, so?: number, sa?: number, sb?: number) => T; - -/** - * A vector operation involving a readonly vector and a scalar, - * storing result in output vector `out`. - */ -export type VecOpN2o = (out: Vec, a: ReadonlyVec, n: number, io?: number, ia?: number, so?: number, sa?: number) => T; - -/** - * A vector operation involving 3 vectors. The first vector might be - * modified. - */ -export type VecOp3 = (a: Vec, b: ReadonlyVec, c: ReadonlyVec, ia?: number, ib?: number, ic?: number, sa?: number, sb?: number, sc?: number) => T; - -/** - * A vector operation involving 2 vectors and a scalar. The first - * vector might be modified. - */ -export type VecOpN3 = (a: Vec, b: ReadonlyVec, n: number, ia?: number, ib?: number, sa?: number, sb?: number) => T; - -/** - * A vector operation involving 3 readonly vectors and storing result in - * output vector `out`. - */ -export type VecOp3o = (out: Vec, a: ReadonlyVec, b: ReadonlyVec, c: ReadonlyVec, io?: number, ia?: number, ib?: number, ic?: number, so?: number, sa?: number, sb?: number, sc?: number) => T; - -/** - * A vector operation involving 3 operands: 2 readonly vectors and a - * scalar, storing result in output vector `out`. - */ -export type VecOpN3o = (out: Vec, a: ReadonlyVec, b: ReadonlyVec, n: number, io?: number, ia?: number, ib?: number, so?: number, sa?: number, sb?: number) => T; - -/** - * A readonly vector operation involving only a single vector. - */ -export type ReadonlyVecOp1 = (v: ReadonlyVec, i?: number, s?: number) => T; - -/** - * A readonly vector operation involving two vectors. - */ -export type ReadonlyVecOp2 = (a: ReadonlyVec, b: ReadonlyVec, ia?: number, ib?: number, sa?: number, sb?: number) => T; - -export type Vec2Coord = 0 | 1; -export type Vec3Coord = 0 | 1 | 2; -export type Vec4Coord = 0 | 1 | 2 | 3; - -export interface IVec extends ILength { - buf: Vec; - i: number; - s: number; -} +} from "@thi.ng/api"; -export interface IVector extends +export interface Vec extends Iterable, - IVec, - ICopy, - ICompare, - IEmpty, - IEquiv, - IEqualsDelta, - IDistance, - IDotProduct, - IMagnitude, - IMath, - IMinMax, - IMix, - INormalize { - - set(v: T): T; - setN(n: number): T; -} + ILength { -export interface IAngleBetween { - angleBetween(v: Readonly, normalize?: boolean): number; + [id: number]: number; } -export interface IDistance { - dist(v: Readonly): number; - distSq(v: Readonly): number; -} -export interface IDotProduct { - dot(v: Readonly): number; -} - -export interface ICrossProduct { - cross(v: Readonly): R; -} - -export interface IMagnitude<> { - mag(): number; - magSq(): number; +export interface ReadonlyVec extends + Iterable, + ILength { + readonly [id: number]: number; } -export interface IMath { - add(v: Readonly): T; - sub(v: Readonly): T; - mul(v: Readonly): T; - div(v: Readonly): T; - addN(n: number): T; - subN(n: number): T; - mulN(n: number): T; - divN(n: number): T; - madd(v: Readonly, w: Readonly): T; - maddN(v: Readonly, n: number): T; - msub(v: Readonly, w: Readonly): T; - msubN(v: Readonly, n: number): T; - addNew(v: Readonly, out?: T): T; - subNew(v: Readonly, out?: T): T; - mulNew(v: Readonly, out?: T): T; - divNew(v: Readonly, out?: T): T; - addNewN(n: number, out?: T): T; - subNewN(n: number, out?: T): T; - mulNewN(n: number, out?: T): T; - divNewN(n: number, out?: T): T; - maddNew(v: Readonly, w: Readonly, out?: T): T; - maddNewN(v: Readonly, n: number, out?: T): T; - msubNew(v: Readonly, w: Readonly, out?: T): T; - msubNewN(v: Readonly, n: number, out?: T): T; +export interface StridedVec { + buf: Vec; + offset: number; + stride: number; } -export interface IMinMax { - min(v: Readonly): T; - max(v: Readonly): T; - clamp(min: Readonly, max: Readonly): T; +export interface IVector extends + Vec, + ICopy, + ICopyView, + IEmpty, + IEqualsDelta, + StridedVec { } -export interface IMix { - mix(v: Readonly, t: Readonly): T; - mixN(v: Readonly, t: number): T; - mixNew(v: Readonly, t: Readonly, out?: T): T; - mixNewN(v: Readonly, t: number, out?: T): T; +export interface ICopyView { + copyView(): T; } -export interface INormalize { - /** - * Normalizes vector to given `length`. If omitted, target length - * will be 1.0. - * - * @param length - */ - normalize(length?: number): T; +export interface VectorConstructor { + new(buf: Vec, offset?: number, stride?: number): T; } -export interface IPolar { - /** - * Converts vector into polar coordinates. For the 3D case, these - * will be spherical coordinates. - */ - toPolar(): T; - /** - * Converts vector with polar coordinates into cartesian form. The - * optional `offset` will be added to the result. - * - * @param offset - */ - toCartesian(offset?: Readonly): T; +export interface MultiVecOp { + add(dim: number, op: VOP): VOP; + default(op: VOP): VOP; } -const min = -Infinity; -const max = Infinity; -export const MIN4 = Object.freeze([min, min, min, min]); -export const MAX4 = Object.freeze([max, max, max, max]); +export type VecOpV = (out: Vec, a: ReadonlyVec) => Vec; +export type VecOpN = (out: Vec, n: number) => Vec; +export type VecOpVV = (out: Vec, a: ReadonlyVec, b: ReadonlyVec) => Vec; +export type VecOpVN = (out: Vec, a: ReadonlyVec, n: number) => Vec; +export type VecOpVVV = (out: Vec, a: ReadonlyVec, b: ReadonlyVec, c: ReadonlyVec) => Vec; +export type VecOpVVN = (out: Vec, a: ReadonlyVec, b: ReadonlyVec, n: number) => Vec; +export type VecOpVNN = (out: Vec, a: ReadonlyVec, u: number, v: number) => Vec; +export type VecOpVVVVNN = (out: Vec, a: ReadonlyVec, b: ReadonlyVec, c: ReadonlyVec, d: ReadonlyVec, u: number, v: number) => 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 VecOpRoV = (a: ReadonlyVec) => T; +export type VecOpRoVV = (a: ReadonlyVec, b: ReadonlyVec) => T; +export type VecOpRoVVO = (a: ReadonlyVec, b: ReadonlyVec, c?: O) => T; + +export type VecOpSV = (out: Vec, a: ReadonlyVec, io?: number, ia?: number, so?: number, sa?: number) => Vec; +export type VecOpSVV = (out: Vec, a: ReadonlyVec, b: ReadonlyVec, io?: number, ia?: number, ib?: number, so?: number, sa?: number, sb?: number) => Vec; +export type VecOpSRoVV = (a: ReadonlyVec, b: ReadonlyVec, ia?: number, ib?: number, sa?: number, sb?: number) => T; + +export interface MultiVecOpV extends VecOpV, MultiVecOp { } +export interface MultiVecOpN extends VecOpN, MultiVecOp { } +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 MultiVecOpVNN extends VecOpVNN, MultiVecOp { } +export interface MultiVecOpVVVVNN extends VecOpVVVVNN, MultiVecOp { } + +export interface MultiVecOpVO extends VecOpVO, MultiVecOp> { } +export interface MultiVecOpOO extends VecOpOO, MultiVecOp> { } +export interface MultiVecOpOOO extends VecOpOOO, MultiVecOp> { } +export interface MultiVecOpNNO extends VecOpNNO, MultiVecOp> { } + +export interface MultiVecOpRoV extends VecOpRoV, MultiVecOp> { } +export interface MultiVecOpRoVV extends VecOpRoVV, MultiVecOp> { } +export interface MultiVecOpRoVVO extends VecOpRoVVO, 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]); - diff --git a/packages/vectors/src/asin.ts b/packages/vectors/src/asin.ts new file mode 100644 index 0000000000..1138ce5a55 --- /dev/null +++ b/packages/vectors/src/asin.ts @@ -0,0 +1,5 @@ +import { MultiVecOpV, VecOpV } from "./api"; +import { defFnOp } from "./internal/codegen"; + +export const [asin, asin2, asin3, asin4] = + defFnOp("Math.asin"); diff --git a/packages/vectors/src/bisect.ts b/packages/vectors/src/bisect.ts new file mode 100644 index 0000000000..667b7714d7 --- /dev/null +++ b/packages/vectors/src/bisect.ts @@ -0,0 +1,9 @@ +import { HALF_PI, PI } from "@thi.ng/math"; +import { VecOpRoVV } from "./api"; +import { headingXY } from "./heading"; + +export const bisect2: VecOpRoVV = + (a, b) => { + const theta = (headingXY(a) + headingXY(b)) / 2; + return theta <= HALF_PI ? theta : PI - theta; + }; diff --git a/packages/vectors/src/cartesian.ts b/packages/vectors/src/cartesian.ts new file mode 100644 index 0000000000..1f9787449d --- /dev/null +++ b/packages/vectors/src/cartesian.ts @@ -0,0 +1,62 @@ +import { cossin } from "@thi.ng/math"; +import { + MultiVecOpVO, + ReadonlyVec, + ZERO2, + ZERO3 +} from "./api"; +import { vop } from "./internal/vop"; +import { maddN2 } from "./maddn"; +import { setC3 } from "./setc"; + +const cos = Math.cos; +const sin = Math.sin; + +/** + * Converts polar vector `v` to cartesian coordinates and adds optional + * `offset`. See `polar()` for reverse operation. If `out` is null, + * modifies `v` in place. + * + * @param out + * @param v + * @param offset + */ +export const cartesian: MultiVecOpVO = vop(1); + +/** + * Converts 2D polar vector `v` to cartesian coordinates and adds + * optional `offset`. See `polar()` for reverse operation. If `out` is + * null, modifies `v` in place. + * + * @param out + * @param v + * @param offset + */ +export const cartesian2 = + cartesian.add(2, + (out, a, b = ZERO2) => maddN2(out || a, b, cossin(a[1]), a[0]) + ); + +/** + * Converts 3D polar vector `v` to cartesian coordinates and adds + * optional `offset`. See `polar()` for reverse operation. If `out` is + * null, modifies `v` in place. + * + * @param out + * @param v + * @param offset + */ +export const cartesian3 = + cartesian.add(3, + (out, a, b = ZERO3) => { + const r = a[0]; + const theta = a[1]; + const phi = a[2]; + const ct = cos(theta); + return setC3( + out || a, + r * ct * cos(phi) + b[0], + r * ct * sin(phi) + b[1], + r * sin(theta) + b[2] + ); + }); diff --git a/packages/vectors/src/ceil.ts b/packages/vectors/src/ceil.ts new file mode 100644 index 0000000000..42df323bcf --- /dev/null +++ b/packages/vectors/src/ceil.ts @@ -0,0 +1,5 @@ +import { MultiVecOpV, VecOpV } from "./api"; +import { defFnOp } from "./internal/codegen"; + +export const [ceil, ceil2, ceil3, ceil4] = + defFnOp("Math.ceil"); diff --git a/packages/vectors/src/clamp.ts b/packages/vectors/src/clamp.ts new file mode 100644 index 0000000000..e580d4358d --- /dev/null +++ b/packages/vectors/src/clamp.ts @@ -0,0 +1,13 @@ +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"; + +export const [clamp, clamp2, clamp3, clamp4] = + defHofOp(_clamp, HOF_VVV, ARGS_VVV); + +export const [clamp01, clamp01_2, clamp01_3, clamp01_4] = + defHofOp(_clamp01, HOF_VVV, ARGS_VVV); + +export const [clamp11, clamp11_2, clamp11_3, clamp11_4] = + defHofOp(_clamp11, HOF_VVV, ARGS_VVV); diff --git a/packages/vectors/src/clampn.ts b/packages/vectors/src/clampn.ts new file mode 100644 index 0000000000..468453ea6c --- /dev/null +++ b/packages/vectors/src/clampn.ts @@ -0,0 +1,11 @@ +import { clamp as _clamp } from "@thi.ng/math"; +import { MultiVecOpVNN, VecOpVNN } from "./api"; +import { defHofOp } from "./internal/codegen"; + +export const [clampN, clampN2, clampN3, clampN4] = + defHofOp( + _clamp, + ([o, a]) => `${o}=op(${a},n,m);`, + "o,a,n,m", + "o,a" + ); diff --git a/packages/vectors/src/codegen.ts b/packages/vectors/src/codegen.ts deleted file mode 100644 index 089d4ce6cc..0000000000 --- a/packages/vectors/src/codegen.ts +++ /dev/null @@ -1,247 +0,0 @@ -import { comp } from "@thi.ng/transducers/func/comp"; -import { range } from "@thi.ng/transducers/iter/range"; -import { tuples } from "@thi.ng/transducers/iter/tuples"; -import { push } from "@thi.ng/transducers/rfn/push"; -import { transduce } from "@thi.ng/transducers/transduce"; -import { map } from "@thi.ng/transducers/xform/map"; -import { mapcat } from "@thi.ng/transducers/xform/mapcat"; -import { take } from "@thi.ng/transducers/xform/take"; -import { - Vec, - VecOp1, - VecOp2, - VecOp2o, - VecOp3, - VecOp3o, - VecOpN2, - VecOpN2o, - VecOpN3, - VecOpN3o -} from "./api"; - -type CommonOps = [ - - // set, setN - VecOp2, - VecOpN2, - - // add, sub, mul, div - VecOp2, - VecOp2, - VecOp2, - VecOp2, - - VecOp2o, - VecOp2o, - VecOp2o, - VecOp2o, - - VecOpN2, - VecOpN2, - VecOpN2, - VecOpN2, - - VecOpN2o, - VecOpN2o, - VecOpN2o, - VecOpN2o, - - // madd / msub - VecOp3, - VecOpN3, - VecOp3, - VecOpN3, - - // Math.* - VecOp1, - VecOp1, - VecOp1, - VecOp1, - VecOp1, - VecOp1, - VecOp1, - - // pow, min,max - VecOp2, - VecOp2, - VecOp2, - - // mix, mixN, mixo, mixNo - VecOp3, - VecOpN3, - VecOp3o, - VecOpN3o -]; - -/** - * HOF array index lookup gen to provide optimized versions of: - * - * ``` - * lookup("a")(0) // a[ia] - * lookup("a")(1) // a[ia * sa] - * lookup("a")(2) // a[ia + 2 * sa] - * ``` - * - * @param sym - */ -const lookup = (sym) => - (i) => i > 1 ? - `${sym}[i${sym}+${i}*s${sym}]` : - i == 1 ? `${sym}[i${sym}+s${sym}]` : - `${sym}[i${sym}]`; - -/** - * Infinite iterator of index lookups for `sym`. - * - * @param sym - */ -const indices = (sym) => map(lookup(sym), range()); - -/** - * Takes a vector size `dim`, a code template function and an array of - * symbol names participating in the template. For each symbol, creates - * iterator of index lookups, forms them into tuples and passes them to - * template to generate code. If the optional `ret` arg is not `null` - * (default `"a"`), appends a `return` statement to the result array, - * using `ret` as return value. Returns array - * - * @param dim - * @param tpl - * @param syms - * @param ret - */ -const assemble = (dim: number, tpl: (syms: string[]) => string, syms: string[], ret = "a") => { - const src = transduce( - comp(take(dim), map(tpl)), - push(), - tuples.apply(null, [...map(indices, syms)]) - ); - ret !== null && src.push(`return ${ret};`); - return src; -}; - -const compile = (args: string, src: string[]) => - new Function(args, src.join("")); - -export const defop1 = (dim: number, op: string): VecOp1 => - compile( - "a,ia=0,sa=1", - assemble(dim, ([a]) => `${a}=${op}(${a});`, ["a"]) - ); - -export const defop2 = (dim: number, op: string): VecOp2 => - compile( - "a,b,ia=0,ib=0,sa=1,sb=1", - assemble(dim, ([a, b]) => `${a}${op}=${b};`, ["a", "b"]) - ); - -export const defopfn2 = (dim: number, fn: string): VecOp2 => - compile( - "a,b,ia=0,ib=0,sa=1,sb=1", - assemble(dim, ([a, b]) => `${a}=${fn}(${a},${b});`, ["a", "b"]) - ); - -export const defopN = (dim: number, op: string): VecOpN2 => - compile( - "a,n,ia=0,sa=1", - assemble(dim, ([a]) => `${a}${op}=n;`, ["a"]) - ); - -export const defop2o = (dim: number, op: string): VecOp2o => - compile( - "o,a,b,io=0,ia=0,ib=0,so=1,sa=1,sb=1", - assemble(dim, ([o, a, b]) => `${o}=${a}${op}${b};`, ["o", "a", "b"], "o") - ); - -export const defopNo = (dim: number, op: string): VecOpN2o => - compile( - "o,a,n,io=0,ia=0,so=1,sa=1", - assemble(dim, ([o, a]) => `${o}=${a}${op}n;`, ["o", "a"], "o") - ); - -export const defop3 = (dim: number, op1: string, op2: string): VecOp3 => - compile( - "a,b,c,ia=0,ib=0,ic=0,sa=1,sb=1,sc=1", - assemble(dim, ([a, b, c]) => `${a}${op1}=${b}${op2}${c};`, ["a", "b", "c"]) - ); - -export const defopN3 = (dim: number, op1: string, op2: string): VecOpN3 => - compile( - "a,b,n,ia=0,ib=0,sa=1,sb=1", - assemble(dim, ([a, b]) => `${a}${op1}=${b}${op2}n;`, ["a", "b"]) - ); - -export const defmix = (dim: number): VecOp3 => - compile( - "a,b,c,ia=0,ib=0,ic=0,sa=1,sb=1,sc=1", - assemble(dim, ([a, b, c]) => `${a}+=(${b}-${a})*${c};`, ["a", "b", "c"]) - ); - -export const defmixN = (dim: number): VecOpN3 => - compile( - "a,b,n,ia=0,ib=0,sa=1,sb=1", - assemble(dim, ([a, b]) => `${a}+=(${b}-${a})*n;`, ["a", "b"]) - ); - -export const defmixo = (dim: number): VecOp3o => - compile( - "o,a,b,c,io=0,ia=0,ib=0,ic=0,so=1,sa=1,sb=1,sc=1", - assemble(dim, ([o, a, b, c]) => `${o}=${a}+(${b}-${a})*${c};`, ["o", "a", "b", "c"], "o") - ); - -export const defmixNo = (dim: number): VecOpN3o => - compile( - "o,a,b,n,io=0,ia=0,ib=0,so=1,sa=1,sb=1", - assemble(dim, ([o, a, b]) => `${o}=${a}+(${b}-${a})*n;`, ["o", "a", "b"], "o") - ); - -export const defcommon = (dim: number): CommonOps => - [ - defop2(dim, ""), - defopN(dim, ""), - - ...mapcat( - (f) => map((op) => f(dim, op), "+-*/"), - [defop2, defop2o, defopN, defopNo] - ), - ...mapcat( - ([op1, op2]) => [defop3(dim, op1, op2), defopN3(dim, op1, op2)], - [["+", "*"], ["-", "*"]] - ), - ...map( - (op) => defop1(dim, `Math.${op}`), - ["abs", "sign", "floor", "ceil", "sin", "cos", "sqrt"] - ), - ...map( - (op) => defopfn2(dim, `Math.${op}`), - ["pow", "min", "max"] - ), - defmix(dim), - defmixN(dim), - defmixo(dim), - defmixNo(dim), - ]; - -/** - * Helper function to create vector/matrix index & property accessors. - * - * @param proto - * @param indices - * @param props - */ -export const declareIndices = (proto: any, props: string[]) => { - const get = (i: number) => function () { return this.buf[this.i + i * (this.s || 1)]; }; - const set = (i: number) => function (n: number) { this.buf[this.i + i * (this.s || 1)] = n; }; - props.forEach((id, i) => { - Object.defineProperty(proto, i, { - get: get(i), - set: set(i), - enumerable: true, - }); - Object.defineProperty(proto, id, { - get: get(i), - set: set(i), - enumerable: true, - }); - }); -}; diff --git a/packages/vectors/src/common.ts b/packages/vectors/src/common.ts deleted file mode 100644 index 1d6dd58ec9..0000000000 --- a/packages/vectors/src/common.ts +++ /dev/null @@ -1,187 +0,0 @@ -import { EPS } from "@thi.ng/math/api"; -import { eqDelta as _eqDelta } from "@thi.ng/math/eqdelta"; -import { - ReadonlyVec, - ReadonlyVecOp1, - Vec, - VecOp2, - VecOp2o -} from "./api"; - -export const x: ReadonlyVecOp1 = (v: ReadonlyVec, i = 0) => v[i]; -export const y: ReadonlyVecOp1 = (v: ReadonlyVec, i = 0, s = 1) => v[i + s]; -export const z: ReadonlyVecOp1 = (v: ReadonlyVec, i = 0, s = 1) => v[i + 2 * s]; -export const w: ReadonlyVecOp1 = (v: ReadonlyVec, i = 0, s = 1) => v[i + 3 * s]; - -export function* $iter(buf: Vec, n: number, i = 0, s = 1) { - for (; n > 0; n-- , i += s) { - yield buf[i]; - } -} - -/** - * Applies vector op `fn` to all raw vectors in array `a`, using the - * same raw vector `b` as 2nd argument for each iteration. Assumes `fn` - * writes results back into `a` and no other copying is performed. - * - * ``` - * transformVectors1( - * v.add3, - * [1, 2, 3, 0, 4, 5, 6, 0], - * [10, 20, 30], - * 2, 0, 0, 1, 1, 4 - * ) - * // [ 11, 22, 33, 0, 14, 25, 36, 0 ] - * ``` - * - * @param fn op - * @param a vector array to process - * @param b vector operand - * @param num num elements - * @param esa element stride `a` - * @param ia start index `a` - * @param ib start index `b` - * @param csa component stride `a` - * @param csb component stride `b` - */ -export const transformVectors1 = ( - fn: VecOp2, a: Vec, b: ReadonlyVec, num: number, - esa: number, - ia = 0, ib = 0, - csa = 1, csb = 1) => { - for (; num > 0; num-- , ia += esa) { - fn(a, b, ia, ib, csa, csb); - } - return a; -}; - -/** - * Similar to `transformVectors1`, but for ops which don't modify `a` or - * `b` and instead write result into given `out` vector, which is then - * also returned. - * - * @param fn - * @param out - * @param a - * @param b - * @param num - * @param eso - * @param esa - * @param io - * @param ia - * @param ib - * @param cso - * @param csa - * @param csb - */ -export const transformVectors1o = ( - fn: VecOp2o, out: Vec, a: ReadonlyVec, b: ReadonlyVec, num: number, - eso: number, esa: number, - io = 0, ia = 0, ib = 0, - cso = 1, csa = 1, csb = 1) => { - for (; num > 0; num-- , io += eso, ia += esa) { - fn(out, a, b, io, ia, ib, cso, csa, csb); - } - return out; -}; - -/** - * Similar to `transformVectors1` but also traverses vector `b` array, - * i.e. applies `fn` to 1st vector of `a` and `b`, then to 2nd `a` and - * `b` etc. - * - * @param fn - * @param a - * @param b - * @param n - * @param esa - * @param esb - * @param ia - * @param ib - * @param csa - * @param csb - */ -export const transformVectors2 = ( - fn: VecOp2, a: Vec, b: ReadonlyVec, n: number, - esa: number, esb: number, - ia = 0, ib = 0, - csa = 1, csb = 1) => { - for (; n > 0; n-- , ia += esa, ib += esb) { - fn(a, b, ia, ib, csa, csb); - } - return a; -}; - -/** - * Similar to `transformVectors2`, but for ops which don't modify `a` or - * `b` and instead write result into given `out` vector, which is then - * also returned. - * - * @param fn - * @param out - * @param a - * @param b - * @param n - * @param eso - * @param esa - * @param esb - * @param io - * @param ia - * @param ib - * @param cso - * @param csa - * @param csb - */ -export const transformVectors2o = ( - fn: VecOp2o, out: Vec, a: ReadonlyVec, b: ReadonlyVec, n: number, - eso: number, esa: number, esb: number, - io = 0, ia = 0, ib = 0, - cso = 1, csa = 1, csb = 1) => { - for (; n > 0; n-- , io += eso, ia += esa, ib += esb) { - fn(out, a, b, io, ia, ib, cso, csa, csb); - } - return out; -}; - -/** - * Takes 2 vectors `a` and `b`, their offsets and strides, returns true - * if the first `n` elements are equal. - * - * @param a - * @param b - * @param n - * @param ia - * @param ib - * @param sa - * @param sb - */ -export const equiv = (a: ReadonlyVec, b: ReadonlyVec, n: number, ia = 0, ib = 0, sa = 1, sb = 1) => { - for (; n > 0; n-- , ia += sa, ib += sb) { - if (a[ia] !== b[ib]) { - return false; - } - } - return true; -}; - -/** - * Similar to `equiv()`, but takes tolerance `eps` into account for - * equality checks. - * - * @param a first vector - * @param b second vector - * @param n number of elements - * @param eps tolerance - * @param ia start index a - * @param ib start index b - * @param sa stride a - * @param sb stride b - */ -export const eqDelta = (a: ReadonlyVec, b: ReadonlyVec, n: number, eps = EPS, ia = 0, ib = 0, sa = 1, sb = 1) => { - for (; n > 0; n-- , ia += sa, ib += sb) { - if (!_eqDelta(a[ia], b[ib], eps)) { - return false; - } - } - return true; -}; diff --git a/packages/vectors/src/compare.ts b/packages/vectors/src/compare.ts new file mode 100644 index 0000000000..9019864e42 --- /dev/null +++ b/packages/vectors/src/compare.ts @@ -0,0 +1,87 @@ +import { Comparator } from "@thi.ng/api"; +import { ReadonlyVec } from "./api"; + +/** + * Returns a new 2D vector comparator using given component order. The + * comparator returns the signed index+1 of the first differing + * component, e.g. if order is `0,1`, a return value of -2 means that + * `a.y < b.y`. + * + * @param o1 + * @param o2 + */ +export const comparator2 = + (o1: number, o2: number): Comparator => + (a, b): number => { + const ax = a[o1]; + const ay = a[o2]; + const bx = b[o1]; + const by = b[o2]; + return ax === bx ? + ay === by ? + 0 : + ay < by ? -2 : 2 : + ax < bx ? -1 : 1; + }; + +/** + * Returns a new 3D vector comparator using given component order. The + * comparator returns the signed index+1 of the first differing + * component, e.g. if order is `0,1,2`, a return value of -3 means that + * `a.z < b.z`. + * + * @param o1 + * @param o2 + * @param o3 + */ +export const comparator3 = + (o1: number, o2: number, o3: number): Comparator => + (a, b): number => { + const ax = a[o1]; + const ay = a[o2]; + const az = a[o3]; + const bx = b[o1]; + const by = b[o2]; + const bz = b[o3]; + return ax === bx ? + ay === by ? + az === bz ? + 0 : + az < bz ? -3 : 3 : + ay < by ? -2 : 2 : + ax < bx ? -1 : 1; + }; + +/** + * Returns a new 4D vector comparator using given component order. The + * comparator returns the signed index+1 of the first differing + * component, e.g. if order is `0,1,2,3`, a return value of -4 means + * that `a.w < b.w`. + * + * @param o1 + * @param o2 + * @param o3 + * @param o4 + */ +export const comparator4 = + (o1: number, o2: number, o3: number, o4: number): Comparator => + (a, b): number => { + + const ax = a[o1]; + const ay = a[o2]; + const az = a[o3]; + const aw = b[o4]; + const bx = b[o1]; + const by = b[o2]; + const bz = b[o3]; + const bw = b[o4]; + return ax === bx ? + ay === by ? + az === bz ? + aw === bw ? + 0 : + aw < bw ? -4 : 4 : + az < bz ? -3 : 3 : + ay < by ? -2 : 2 : + ax < bx ? -1 : 1; + }; diff --git a/packages/vectors/src/copy.ts b/packages/vectors/src/copy.ts new file mode 100644 index 0000000000..08a6ef21c2 --- /dev/null +++ b/packages/vectors/src/copy.ts @@ -0,0 +1,9 @@ +import { implementsFunction } from "@thi.ng/checks"; +import { ReadonlyVec, Vec } from "./api"; +import { set } from "./set"; + +export const copy = + (v: ReadonlyVec): Vec => + implementsFunction(v, "copy") ? + (v).copy() : + set([], v); diff --git a/packages/vectors/src/cos.ts b/packages/vectors/src/cos.ts new file mode 100644 index 0000000000..786614add8 --- /dev/null +++ b/packages/vectors/src/cos.ts @@ -0,0 +1,5 @@ +import { MultiVecOpV, VecOpV } from "./api"; +import { defFnOp } from "./internal/codegen"; + +export const [cos, cos2, cos3, cos4] = + defFnOp("Math.cos"); diff --git a/packages/vectors/src/cosh.ts b/packages/vectors/src/cosh.ts new file mode 100644 index 0000000000..417b3bd067 --- /dev/null +++ b/packages/vectors/src/cosh.ts @@ -0,0 +1,5 @@ +import { MultiVecOpV, VecOpV } from "./api"; +import { defFnOp } from "./internal/codegen"; + +export const [cosh, cosh2, cosh3, cosh4] = + defFnOp("Math.cosh"); diff --git a/packages/vectors/src/cross.ts b/packages/vectors/src/cross.ts new file mode 100644 index 0000000000..1491edd0e0 --- /dev/null +++ b/packages/vectors/src/cross.ts @@ -0,0 +1,15 @@ +import { ReadonlyVec, Vec } from "./api"; +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) => + setC3( + out || a, + a[1] * b[2] - a[2] * b[1], + a[2] * b[0] - a[0] * b[2], + a[0] * b[1] - a[1] * b[0] + ); diff --git a/packages/vectors/src/dist-chebyshev.ts b/packages/vectors/src/dist-chebyshev.ts new file mode 100644 index 0000000000..0d9930dbbb --- /dev/null +++ b/packages/vectors/src/dist-chebyshev.ts @@ -0,0 +1,33 @@ +import { MultiVecOpRoVV } from "./api"; +import { compile } from "./internal/codegen"; +import { vop } from "./internal/vop"; + +const $ = (dim: number) => + distChebyshev.add( + dim, + compile( + dim, + ([a, b]) => `Math.abs(${a}-${b})`, + "a,b", + undefined, + null, + ",", + "return Math.max(", ");" + ) + ); + +export const distChebyshev: MultiVecOpRoVV = vop(); + +distChebyshev.default( + (a, b) => { + let max = 0; + for (let i = a.length; --i >= 0;) { + max = Math.max(max, Math.abs(a[i] - b[i])); + } + return max; + } +); + +export const distChebyshev2 = $(2); +export const distChebyshev3 = $(3); +export const distChebyshev4 = $(4); diff --git a/packages/vectors/src/dist-manhattan.ts b/packages/vectors/src/dist-manhattan.ts new file mode 100644 index 0000000000..62ee55eb89 --- /dev/null +++ b/packages/vectors/src/dist-manhattan.ts @@ -0,0 +1,34 @@ +import { MultiVecOpRoVV } from "./api"; +import { compile, compileG } from "./internal/codegen"; +import { vop } from "./internal/vop"; + +const $ = (dim: number) => + distManhattan.add( + dim, + compile( + dim, + ([a, b]) => `Math.abs(${a}-${b})`, + "a,b", + undefined, + null, + "+", + "return ", + ";" + ) + ); + +export const distManhattan: MultiVecOpRoVV = vop(); + +distManhattan.default( + compileG( + ([a, b]) => `sum+=Math.abs(${a}-${b});`, + "a,b", + undefined, + "sum", + "let sum=0;" + ) +); + +export const distManhattan2 = $(2); +export const distManhattan3 = $(3); +export const distManhattan4 = $(4); diff --git a/packages/vectors/src/dist.ts b/packages/vectors/src/dist.ts new file mode 100644 index 0000000000..e9de6b2143 --- /dev/null +++ b/packages/vectors/src/dist.ts @@ -0,0 +1,6 @@ +import { ReadonlyVec } from "./api"; +import { distSq } from "./distsq"; + +export const dist = + (a: ReadonlyVec, b: ReadonlyVec) => + Math.sqrt(distSq(a, b)); diff --git a/packages/vectors/src/distsq.ts b/packages/vectors/src/distsq.ts new file mode 100644 index 0000000000..d358c664b0 --- /dev/null +++ b/packages/vectors/src/distsq.ts @@ -0,0 +1,20 @@ +import { MultiVecOpRoVV } from "./api"; +import { compile, compileG } from "./internal/codegen"; +import { vop } from "./internal/vop"; + +const tpl = ([a, b]) => `t=${a}-${b};s+=t*t;`; +const pre = "let t,s=0;"; + +const $ = (dim: number) => + distSq.add( + dim, + compile(dim, tpl, "a,b", undefined, "s", "", pre) + ); + +export const distSq: MultiVecOpRoVV = vop(); + +distSq.default(compileG(tpl, "a,b", undefined, "s", pre)); + +export const distSq2 = $(2); +export const distSq3 = $(3); +export const distSq4 = $(4); diff --git a/packages/vectors/src/div.ts b/packages/vectors/src/div.ts new file mode 100644 index 0000000000..034bdfd8e3 --- /dev/null +++ b/packages/vectors/src/div.ts @@ -0,0 +1,3 @@ +import { defMathOp } from "./internal/codegen"; + +export const [div, div2, div3, div4] = defMathOp("/"); diff --git a/packages/vectors/src/divn.ts b/packages/vectors/src/divn.ts new file mode 100644 index 0000000000..4ba8f37dbb --- /dev/null +++ b/packages/vectors/src/divn.ts @@ -0,0 +1,3 @@ +import { defMathNOp } from "./internal/codegen"; + +export const [divN, divN2, divN3, divN4] = defMathNOp("/"); diff --git a/packages/vectors/src/divs.ts b/packages/vectors/src/divs.ts new file mode 100644 index 0000000000..5960a124ec --- /dev/null +++ b/packages/vectors/src/divs.ts @@ -0,0 +1,6 @@ +import { VecOpSVV } from "./api"; +import { defOpS } from "./internal/codegen"; +import { MATH } from "./internal/templates"; + +export const [divS2, divS3, divS4] = + defOpS(MATH("/")); diff --git a/packages/vectors/src/dot.ts b/packages/vectors/src/dot.ts new file mode 100644 index 0000000000..187b8913b1 --- /dev/null +++ b/packages/vectors/src/dot.ts @@ -0,0 +1,29 @@ +import { MultiVecOpRoVV } from "./api"; +import { compile, compileG } from "./internal/codegen"; +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 ", + ";" + ) + ); + +export const dot: MultiVecOpRoVV = vop(); + +dot.default( + compileG(DOT_G, "a,b", undefined, "s", "let s=0;") +); + +export const dot2 = $(2); +export const dot3 = $(3); +export const dot4 = $(4); diff --git a/packages/vectors/src/dotc.ts b/packages/vectors/src/dotc.ts new file mode 100644 index 0000000000..5225c97099 --- /dev/null +++ b/packages/vectors/src/dotc.ts @@ -0,0 +1,41 @@ +/** + * Returns pairwise product sum of given components. + * + * @param a + * @param b + * @param c + * @param d + */ +export const dotC4 = + (a: number, b: number, c: number, d: number) => + a * b + c * d; + +/** + * Returns pairwise product sum of given components. + * + * @param a + * @param b + * @param c + * @param d + * @param e + * @param f + */ +export const dotC6 = + (a: number, b: number, c: number, d: number, e: number, f: number) => + a * b + c * d + e * f; + +/** + * Returns pairwise product sum of given components. + * + * @param a + * @param b + * @param c + * @param d + * @param e + * @param f + * @param g + * @param h + */ +export const dotC8 = + (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number) => + a * b + c * d + e * f + g * h; diff --git a/packages/vectors/src/dots.ts b/packages/vectors/src/dots.ts new file mode 100644 index 0000000000..786ff0eaef --- /dev/null +++ b/packages/vectors/src/dots.ts @@ -0,0 +1,21 @@ +import { VecOpSRoVV } from "./api"; +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 + ); + +export const dotS2 = $(2); +export const dotS3 = $(3); +export const dotS4 = $(4); diff --git a/packages/vectors/src/empty.ts b/packages/vectors/src/empty.ts new file mode 100644 index 0000000000..1084914f82 --- /dev/null +++ b/packages/vectors/src/empty.ts @@ -0,0 +1,9 @@ +import { implementsFunction } from "@thi.ng/checks"; +import { ReadonlyVec, Vec } from "./api"; +import { zeroes } from "./setn"; + +export const empty = + (v: ReadonlyVec): Vec => + implementsFunction(v, "empty") ? + (v).empty() : + zeroes(v.length); diff --git a/packages/vectors/src/eqdelta.ts b/packages/vectors/src/eqdelta.ts new file mode 100644 index 0000000000..8387f8604e --- /dev/null +++ b/packages/vectors/src/eqdelta.ts @@ -0,0 +1,82 @@ +import { implementsFunction } from "@thi.ng/checks"; +import { EPS, eqDelta as _eq } from "@thi.ng/math"; +import { MultiVecOpRoVVO, ReadonlyVec } from "./api"; +import { compileHOF } from "./internal/codegen"; +import { vop } from "./internal/vop"; + +const $ = (dim) => + eqDelta.add( + dim, + compileHOF( + dim, + [_eq, EPS], + ([a, b]) => `eq(${a},${b},eps)`, + "eq,_eps", + "a,b,eps=_eps", + "a,b", + null, + "&&", + "return a.length === b.length && ", + ";" + ) + ); + +export const eqDelta: MultiVecOpRoVVO = vop(); + +eqDelta.default( + (v1, v2, eps = EPS) => { + if (implementsFunction(v1, "eqDelta")) { + return (v1).eqDelta(v2, eps); + } + if (implementsFunction(v2, "eqDelta")) { + return (v2).eqDelta(v1, eps); + } + return eqDeltaS(v1, v2, v1.length, eps); + } +); + +export const eqDelta2 = $(2); +export const eqDelta3 = $(3); +export const eqDelta4 = $(4); + +/** + * Similar to `equiv()`, but takes tolerance `eps` into account for + * equality checks. + * + * @param a first vector + * @param b second vector + * @param n number of elements + * @param eps tolerance + * @param ia start index a + * @param ib start index b + * @param sa stride a + * @param sb stride b + */ +export const eqDeltaS = ( + a: ReadonlyVec, + b: ReadonlyVec, + n: number, + eps = EPS, + ia = 0, + ib = 0, + sa = 1, + sb = 1) => { + + for (; n > 0; n-- , ia += sa, ib += sb) { + if (!_eq(a[ia], b[ib], eps)) { + return false; + } + } + return true; +}; + +export const eqDeltaArray = (a: ReadonlyVec[], b: ReadonlyVec[], eps = EPS) => { + if (a === b) return true; + if (a.length !== b.length) return false; + for (let i = a.length; --i >= 0;) { + if (!eqDelta(a[i], b[i], eps)) { + return false; + } + } + return true; +}; diff --git a/packages/vectors/src/exp.ts b/packages/vectors/src/exp.ts new file mode 100644 index 0000000000..5c5c0c0e07 --- /dev/null +++ b/packages/vectors/src/exp.ts @@ -0,0 +1,5 @@ +import { MultiVecOpV, VecOpV } from "./api"; +import { defFnOp } from "./internal/codegen"; + +export const [exp, exp2, exp3, exp4] = + defFnOp("Math.exp"); diff --git a/packages/vectors/src/face-forward.ts b/packages/vectors/src/face-forward.ts new file mode 100644 index 0000000000..e317a4283a --- /dev/null +++ b/packages/vectors/src/face-forward.ts @@ -0,0 +1,14 @@ +import { VecOpVVV } from "./api"; +import { dot } from "./dot"; +import { mulN } from "./muln"; +import { set } from "./set"; + +export const faceForward: VecOpVVV = + (out, n, i, nref) => { + !out && (out = n); + return dot(nref, i) < 0 ? + out !== n ? + set(out, n) : + out : + mulN(out, n, -1); + }; diff --git a/packages/vectors/src/floor.ts b/packages/vectors/src/floor.ts new file mode 100644 index 0000000000..ea1bd54171 --- /dev/null +++ b/packages/vectors/src/floor.ts @@ -0,0 +1,5 @@ +import { MultiVecOpV, VecOpV } from "./api"; +import { defFnOp } from "./internal/codegen"; + +export const [floor, floor2, floor3, floor4] = + defFnOp("Math.floor"); diff --git a/packages/vectors/src/fract.ts b/packages/vectors/src/fract.ts new file mode 100644 index 0000000000..fe7c8604a4 --- /dev/null +++ b/packages/vectors/src/fract.ts @@ -0,0 +1,6 @@ +import { fract as _fract } from "@thi.ng/math"; +import { MultiVecOpV, VecOpV } from "./api"; +import { defHofOp } from "./internal/codegen"; + +export const [fract, fract2, fract3, fract4] = + defHofOp(_fract); diff --git a/packages/vectors/src/gvec.ts b/packages/vectors/src/gvec.ts index c0a65e9cea..99da073a48 100644 --- a/packages/vectors/src/gvec.ts +++ b/packages/vectors/src/gvec.ts @@ -1,578 +1,167 @@ -import { - ICopy, - IEqualsDelta, - IEquiv, - ILength -} from "@thi.ng/api/api"; -import { isArrayLike } from "@thi.ng/checks/is-arraylike"; -import { illegalArgs } from "@thi.ng/errors/illegal-arguments"; -import { sign as _sign } from "@thi.ng/math/abs"; -import { EPS } from "@thi.ng/math/api"; -import { clamp as _clamp } from "@thi.ng/math/interval"; -import { fract as _fract } from "@thi.ng/math/prec"; -import { smoothStep as _smoothStep, step as _step } from "@thi.ng/math/step"; -import { - IDotProduct, - IMagnitude, - IMath, - IMinMax, - IMix, - INormalize, - IVec, - ReadonlyVec, - Vec -} from "./api"; -import { $iter, eqDelta, equiv } from "./common"; - - -export const opg0 = (fn: () => number, a: Vec, num = a.length, i = 0, s = 1) => { - i += num * s; - while (i -= s, --num >= 0) { - a[i] = fn(); - } - return a; -}; - -export const opg1 = (fn: (x: number) => number, a: Vec, num = a.length, i = 0, s = 1) => { - i += num * s; - while (i -= s, --num >= 0) { - a[i] = fn(a[i]); - } - return a; -}; - -export const opg2 = (fn: (x: number, y: number) => number, a: Vec, b: ReadonlyVec, num = a.length, ia = 0, ib = 0, sa = 1, sb = 1) => { - ia += num * sa; - ib += num * sb; - while (ia -= sa, ib -= sb, --num >= 0) { - a[ia] = fn(a[ia], b[ib]); - } - return a; -}; - -export const opg3 = (fn: (x: number, y: number, z: number) => number, a: Vec, b: ReadonlyVec, c: ReadonlyVec, num = a.length, ia = 0, ib = 0, ic = 0, sa = 1, sb = 1, sc = 1) => { - ia += num * sa; - ib += num * sb; - ic += num * sc; - while (ia -= sa, ib -= sb, ic -= sc, --num >= 0) { - a[ia] = fn(a[ia], b[ib], c[ic]); - } - return a; -}; - -export const get = (a: ReadonlyVec, num = a.length, i = 0, s = 1) => - set(new ((a.constructor))(num), a, num, 0, i, 1, s); - -export const set = (a: Vec, b: ReadonlyVec, num = a.length, ia = 0, ib = 0, sa = 1, sb = 1) => { - ia += num * sa; - ib += num * sb; - while (ia -= sa, ib -= sb, --num >= 0) { - a[ia] = b[ib]; - } - return a; -}; - -export const setN = (a: Vec, n: number, num = a.length, ia = 0, sa = 1) => { - ia += num * sa; - while (ia -= sa, --num >= 0) { - a[ia] = n; - } - return a; -}; - -export const randNorm = (a: Vec, n = 1, num = a.length, ia = 0, sa = 1) => - randMinMax(a, -n, n, num, ia, sa); - -export const randMinMax = (a: Vec, min: number, max: number, num = a.length, ia = 0, sa = 1) => { - const d = max - min; - return opg0(() => min + d * Math.random(), a, num, ia, sa); -}; - -export const jitter = (a: Vec, n: number, num = a.length, ia = 0, sa = 1) => - opg1((x) => x + Math.random() * 2 * n - n, a, num, ia, sa); - -export const add = (a: Vec, b: ReadonlyVec, num = a.length, ia = 0, ib = 0, sa = 1, sb = 1) => - opg2((x, y) => x + y, a, b, num, ia, ib, sa, sb); - -export const sub = (a: Vec, b: ReadonlyVec, num = a.length, ia = 0, ib = 0, sa = 1, sb = 1) => - opg2((x, y) => x - y, a, b, num, ia, ib, sa, sb); - -export const mul = (a: Vec, b: ReadonlyVec, num = a.length, ia = 0, ib = 0, sa = 1, sb = 1) => - opg2((x, y) => x * y, a, b, num, ia, ib, sa, sb); - -export const div = (a: Vec, b: ReadonlyVec, num = a.length, ia = 0, ib = 0, sa = 1, sb = 1) => - opg2((x, y) => x / y, a, b, num, ia, ib, sa, sb); - -export const addN = (a: Vec, n: number, num = a.length, i = 0, s = 1) => - opg1((x) => x + n, a, num, i, s); - -export const subN = (a: Vec, n: number, num = a.length, i = 0, s = 1) => - opg1((x) => x - n, a, num, i, s); - -export const mulN = (a: Vec, n: number, num = a.length, i = 0, s = 1) => - opg1((x) => x * n, a, num, i, s); - -export const divN = (a: Vec, n: number, num = a.length, i = 0, s = 1) => - opg1((x) => x / n, a, num, i, s); - -export const dot = (a: ReadonlyVec, b: ReadonlyVec, num = a.length, ia = 0, ib = 0, sa = 1, sb = 1) => { - let res = 0; - while (--num >= 0) { - res += a[ia + num * sa] * b[ib + num * sb]; - } - return res; -}; - -export const madd = (a: Vec, b: ReadonlyVec, c: ReadonlyVec, num = a.length, ia = 0, ib = 0, ic = 0, sa = 1, sb = 1, sc = 1) => - opg3((x, y, z) => x + y * z, a, b, c, num, ia, ib, ic, sa, sb, sc); - -export const maddN = (a: Vec, b: ReadonlyVec, n: number, num = a.length, ia = 0, ib = 0, sa = 1, sb = 1) => - opg2((x, y) => x + y * n, a, b, num, ia, ib, sa, sb); - -export const msub = (a: Vec, b: ReadonlyVec, c: ReadonlyVec, num = a.length, ia = 0, ib = 0, ic = 0, sa = 1, sb = 1, sc = 1) => - opg3((x, y, z) => x - y * z, a, b, c, num, ia, ib, ic, sa, sb, sc); - -export const msubN = (a: Vec, b: ReadonlyVec, n: number, num = a.length, ia = 0, ib = 0, sa = 1, sb = 1) => - opg2((x, y) => x + y * n, a, b, num, ia, ib, sa, sb); - -export const mix = (a: Vec, b: ReadonlyVec, c: ReadonlyVec, num = a.length, ia = 0, ib = 0, ic = 0, sa = 1, sb = 1, sc = 1) => - opg3((x, y, z) => x + (y - x) * z, a, b, c, num, ia, ib, ic, sa, sb, sc); - -export const mixN = (a: Vec, b: ReadonlyVec, n: number, num = a.length, ia = 0, ib = 0, sa = 1, sb = 1) => - opg2((x, y) => x + (y - x) * n, a, b, num, ia, ib, sa, sb); - -export const magSq = (a: ReadonlyVec, num = a.length, i = 0, s = 1) => - dot(a, a, num, i, i, s, s); - -export const mag = (a: ReadonlyVec, num = a.length, i = 0, s = 1) => - Math.sqrt(magSq(a, num, i, s)); - -export const distSq = (a: ReadonlyVec, b: ReadonlyVec, num = a.length, ia = 0, ib = 0, sa = 1, sb = 1) => { - let res = 0; - while (--num >= 0) { - res += Math.pow(a[ia + num * sa] - b[ib + num * sb], 2); - } - return res; -}; - -export const dist = (a: ReadonlyVec, b: ReadonlyVec, num = a.length, ia = 0, ib = 0, sa = 1, sb = 1) => - Math.sqrt(distSq(a, b, num, ia, ib, sa, sb)); - -export const normalize = (a: Vec, num = a.length, len = 1, i = 0, s = 1) => { - const m = mag(a, num, i, s); - m >= EPS && mulN(a, len / m, num, i, s); - return a; -}; - -export const neg = (a: Vec, num = a.length, i = 0, s = 1) => - mulN(a, -1, num, i, s); - -export const abs = (a: Vec, num = a.length, i = 0, s = 1) => - opg1(Math.abs, a, num, i, s); - -export const sign = (a: Vec, num = a.length, eps = EPS, i = 0, s = 1) => - opg1((x) => _sign(x, eps), a, num, i, s); - -export const floor = (a: Vec, num = a.length, i = 0, s = 1) => - opg1(Math.floor, a, num, i, s); - -export const ceil = (a: Vec, num = a.length, i = 0, s = 1) => - opg1(Math.ceil, a, num, i, s); - -export const fract = (a: Vec, num = a.length, i = 0, s = 1) => - opg1(_fract, a, num, i, s); - -export const sin = (a: Vec, num = a.length, i = 0, s = 1) => - opg1(Math.sin, a, num, i, s); - -export const cos = (a: Vec, num = a.length, i = 0, s = 1) => - opg1(Math.cos, a, num, i, s); - -export const sqrt = (a: Vec, num = a.length, i = 0, s = 1) => - opg1(Math.sqrt, a, num, i, s); - -export const pow = (a: Vec, b: ReadonlyVec, num = a.length, ia = 0, ib = 0, sa = 1, sb = 1) => - opg2(Math.pow, a, b, num, ia, ib, sa, sb); - -export const powN = (a: Vec, n: number, num = a.length, i = 0, s = 1) => - opg1((x) => Math.pow(x, n), a, num, i, s); - -export const min = (a: Vec, b: ReadonlyVec, num = a.length, ia = 0, ib = 0, sa = 1, sb = 1) => - opg2(Math.min, a, b, num, ia, ib, sa, sb); - -export const max = (a: Vec, b: ReadonlyVec, num = a.length, ia = 0, ib = 0, sa = 1, sb = 1) => - opg2(Math.max, a, b, num, ia, ib, sa, sb); - -export const clamp = (a: Vec, b: ReadonlyVec, c: ReadonlyVec, num = a.length, ia = 0, ib = 0, ic = 0, sa = 1, sb = 1, sc = 1) => - opg3(_clamp, a, b, c, num, ia, ib, ic, sa, sb, sc); - -export const step = (a: Vec, b: ReadonlyVec, num = a.length, ia = 0, ib = 0, sa = 1, sb = 1) => - opg2((x, e) => _step(e, x), a, b, num, ia, ib, sa, sb); - -export const smoothStep = (a: Vec, b: ReadonlyVec, c: ReadonlyVec, num = a.length, ia = 0, ib = 0, ic = 0, sa = 1, sb = 1, sc = 1) => - opg3((x, e1, e2) => _smoothStep(e1, e2, x), a, b, c, num, ia, ib, ic, sa, sb, sc); - -export const gvec = (...coords: number[]) => - new GVec(coords, coords.length); - -export class GVec implements - ICopy, - IDotProduct, - IEqualsDelta, - IEquiv, - ILength, - IMagnitude, - IMath, - IMinMax, - IMix, - INormalize, - Iterable, - IVec { - - static mapBuffer(buf: Vec, numV: number, length: number, start = 0, cstride = 1, estride = length) { - const res: GVec[] = []; - while (--numV >= 0) { - res.push(new GVec(buf, length, start, cstride)); - start += estride; - } - return res; - } - - static intoBuffer(buf: Vec, src: Iterable>, start = 0, cstride: number, estride: number) { - for (let v of src) { - set(buf, v.buf, v.n, start, v.i, cstride, v.s); - start += estride; - } - return buf; - } - - static of(size: number, n = 0) { - return new GVec(setN([], n, size)); - } - - static randNorm(size: number, n = 1) { - return new GVec(randNorm([], n, size)); - } - - static random(size: number, min: number, max: number) { - return new GVec(randMinMax([], min, max, size)); - } - - buf: Vec; - n: number; - i: number; - s: number; - - constructor(buf: Vec, n = buf.length, i = 0, s = 1) { - this.buf = buf; - this.n = n; - this.i = i; - this.s = s; - } - - [Symbol.iterator]() { - return $iter(this.buf, this.n, this.i, this.s); - } - - get length() { - return this.n; - } - - getAt(i: number, safe = true) { - safe && this.ensureIndex(i); - return this.buf[this.i + i * this.s]; - } - - setAt(i: number, x: number, safe = true) { - safe && this.ensureIndex(i); - this.buf[this.i + i * this.s] = x; - } - - copy() { - return new GVec(get(this.buf, this.n, this.i, this.s)); - } - - equiv(v: any) { - return v instanceof GVec && v.n === this.n ? - equiv(this.buf, v.buf, this.n, this.i, v.i, this.s, v.s) : - isArrayLike(v) && v.length === this.n ? - equiv(this.buf, v, this.n, this.i, 0, this.s, 1) : - false; - } - - eqDelta(v: Readonly, eps = EPS) { - return this.n === v.n && eqDelta(this.buf, v.buf, this.n, eps, this.i, v.i, this.s, v.s); - } - - set(v: Readonly) { - this.ensureSize(v); - set(this.buf, v.buf, this.n, this.i, v.i, this.s, v.s); - return this; - } - - setN(n: number) { - setN(this.buf, n, this.n, this.i, this.s); - return this; - } - - jitter(n = 1) { - jitter(this.buf, n, this.n, this.i, this.s); - return this; - } - - add(v: Readonly) { - this.ensureSize(v); - add(this.buf, v.buf, this.n, this.i, v.i, this.s, v.s); - return this; - } - - sub(v: Readonly) { - this.ensureSize(v); - sub(this.buf, v.buf, this.n, this.i, v.i, this.s, v.s); - return this; - } - - mul(v: Readonly) { - this.ensureSize(v); - mul(this.buf, v.buf, this.n, this.i, v.i, this.s, v.s); - return this; - } - - div(v: Readonly) { - this.ensureSize(v); - div(this.buf, v.buf, this.n, this.i, v.i, this.s, v.s); - return this; - } - - addN(n: number) { - addN(this.buf, n, this.n, this.i, this.s); - return this; - } - - subN(n: number) { - subN(this.buf, n, this.n, this.i, this.s); - return this; - } - - mulN(n: number) { - mulN(this.buf, n, this.n, this.i, this.s); - return this; - } - - divN(n: number) { - divN(this.buf, n, this.n, this.i, this.s); - return this; - } - - madd(b: Readonly, c: Readonly) { - this.ensureSize(b); - this.ensureSize(c); - madd(this.buf, b.buf, c.buf, this.n, this.i, b.i, c.i, this.s, b.s, c.s); - return this; - } - - maddN(v: Readonly, n: number) { - this.ensureSize(v); - maddN(this.buf, v.buf, n, this.n, this.i, v.i, this.s, v.s); - return this; - } - - msub(b: Readonly, c: Readonly) { - this.ensureSize(b); - this.ensureSize(c); - msub(this.buf, b.buf, c.buf, this.n, this.i, b.i, c.i, this.s, b.s, c.s); - return this; - } - - msubN(v: Readonly, n: number) { - this.ensureSize(v); - msubN(this.buf, v.buf, n, this.n, this.i, v.i, this.s, v.s); - return this; - } - - mix(b: Readonly, c: Readonly) { - this.ensureSize(b); - this.ensureSize(c); - mix(this.buf, b.buf, c.buf, this.n, this.i, b.i, c.i, this.s, b.s, c.s); - return this; - } - - mixN(v: Readonly, n = 0.5) { - this.ensureSize(v); - mixN(this.buf, v.buf, n, this.n, this.i, v.i, this.s, v.s); - return this; - } - - mixNew(b: Readonly, c: Readonly, out?: GVec) { - return (out || this.copy()).mix(b, c); - } - - mixNewN(v: Readonly, n = 0.5, out?: GVec) { - return (out || this.copy()).mixN(v, n); - } - - addNew(v: Readonly, out?: GVec) { - return (out || this.copy()).add(v); - } - - subNew(v: Readonly, out?: GVec) { - return (out || this.copy()).sub(v); - } - - mulNew(v: Readonly, out?: GVec) { - return (out || this.copy()).mul(v); - } - - divNew(v: Readonly, out?: GVec) { - return (out || this.copy()).div(v); - } - - addNewN(n: number, out?: GVec) { - return (out || this.copy()).addN(n); - } - - subNewN(n: number, out?: GVec) { - return (out || this.copy()).subN(n); - } - - mulNewN(n: number, out?: GVec) { - return (out || this.copy()).mulN(n); - } - - divNewN(n: number, out?: GVec) { - return (out || this.copy()).divN(n); - } - - maddNew(v: Readonly, w: Readonly, out?: GVec) { - return (out || this.copy()).madd(v, w); - } - - maddNewN(v: Readonly, n: number, out?: GVec) { - return (out || this.copy()).maddN(v, n); - } - - msubNew(v: Readonly, w: Readonly, out?: GVec) { - return (out || this.copy()).msub(v, w); - } - - msubNewN(v: Readonly, n: number, out?: GVec) { - return (out || this.copy()).msubN(v, n); - } - - magSq() { - return magSq(this.buf, this.n, this.i, this.s); - } - - mag() { - return mag(this.buf, this.n, this.i, this.s); - } - - normalize(len = 1) { - normalize(this.buf, this.n, len, this.i, this.s); - return this; - } - - dot(v: Readonly) { - this.ensureSize(v); - return dot(this.buf, v.buf, this.n, this.i, v.i, this.s, v.s); - } - - abs() { - abs(this.buf, this.n, this.i, this.s); - return this; - } - - sign() { - sign(this.buf, this.n, this.i, this.s); - return this; - } - - ceil() { - ceil(this.buf, this.n, this.i, this.s); - return this; - } - - fract() { - fract(this.buf, this.n, this.i, this.s); - return this; - } - - floor() { - floor(this.buf, this.n, this.i, this.s); - return this; - } - - sin() { - sin(this.buf, this.n, this.i, this.s); - return this; - } - - cos() { - cos(this.buf, this.n, this.i, this.s); - return this; - } - - sqrt() { - sqrt(this.buf, this.n, this.i, this.s); - return this; - } - - pow(v: Readonly) { - this.ensureSize(v); - pow(this.buf, v.buf, this.n, this.i, v.i, this.s, v.s); - return this; - } - - powN(n: number) { - powN(this.buf, n, this.n, this.i, this.s); - return this; - } - - min(v: Readonly) { - this.ensureSize(v); - min(this.buf, v.buf, this.n, this.i, v.i, this.s, v.s); - return this; - } - - max(v: Readonly) { - this.ensureSize(v); - max(this.buf, v.buf, this.n, this.i, v.i, this.s, v.s); - return this; - } - - clamp(min: Readonly, max: Readonly) { - this.ensureSize(min); - this.ensureSize(max); - clamp(this.buf, min.buf, max.buf, this.n, this.i, min.i, max.i, this.s, min.s, max.s); - return this; - } - - step(e: Readonly) { - this.ensureSize(e); - step(this.buf, e.buf, this.n, this.i, e.i, this.s, e.s); - return this; - } - - smoothStep(e1: Readonly, e2: Readonly) { - this.ensureSize(e1); - this.ensureSize(e2); - smoothStep(this.buf, e1.buf, e2.buf, this.n, this.i, e1.i, e2.i, this.s, e1.s, e2.s); - return this; - } - - toString() { - return `[${get(this.buf, this.n, this.i, this.s).join(", ")}]`; - } - - toJSON() { - return get(this.buf, this.n, this.i, this.s); - } - - protected ensureSize(v: Readonly) { - this.n !== v.n && illegalArgs(`vector size: ${v.n} (needed ${this.n})`); - } - - protected ensureIndex(i: number) { - (i < 0 && i >= this.n) && illegalArgs(`index out of bounds: ${i}`); - } -} +import { EPS } from "@thi.ng/math"; +import { memoize1 } from "@thi.ng/memoize"; +import { map, range } from "@thi.ng/transducers"; +import { IVector, Vec } from "./api"; +import { eqDeltaS } from "./eqdelta"; +import { values } from "./internal/vec-utils"; +import { zeroes } from "./setn"; +import { setS } from "./sets"; + +const SYM_B = "buf"; +const SYM_L = "length"; +const SYM_O = "offset"; +const SYM_S = "stride"; +const SYM_C = "copy"; +const SYM_CV = "copyView"; +const SYM_EMPTY = "empty"; +const SYM_EQD = "eqDelta"; +const SYM_STR = "toString"; + +const PROPS = new Set([ + SYM_B, + SYM_C, + SYM_CV, + SYM_EMPTY, + SYM_EQD, + SYM_L, + SYM_O, + SYM_S, + SYM_STR, + Symbol.iterator +]); + +const keys = memoize1( + (size: number) => [ + ...map(String, range(size)), + ...PROPS + ] +); + +/** + * Wrapper for strided, arbitrary length vectors. Wraps given buffer in + * ES6 `Proxy` with custom property getters/setters and implements the + * following interfaces: + * + * - `Iterable` (ES6) + * - `ICopy` + * - `IEmpty` + * - `IEqualsDelta` + * - `IVector` + * - `Object.toString()` + * + * Read/write access for the following properties: + * + * - array indices in the [0 .. `size`) interval + * - `offset` - start index + * - `stride` - component stride + * - `buf` - backing buffer (readonly) + * - `length` - vector size + * + * Array index access uses bounds checking against the [0 .. `size`) + * interval, but, for performance reasons, **not** against the actual + * wrapped buffer. + * + * Note: ES6 proxies are ~10x slower than standard array accesses. If + * several computations are to be performed on such vectors it will be + * much more efficient to first copy them to compact arrays and then + * copy result back if needed. + * + * ``` + * // 3D vector w/ stride length of 4 + * a = gvec([1,0,0,0,2,0,0,0,3,0,0,0], 3, 0, 4); + * a[0] // 1 + * a[1] // 2 + * a[2] // 3 + * + * a.stride + * // 4 + * + * [...a] + * // [1, 2, 3] + * + * a.toString() + * // "[1,2,3]" + * + * add([], a, a) + * // [2, 4, 6] + * + * copy(a) + * // [1, 2, 3] + * + * a.copyView() + * // Proxy [ [ 1, 0, 2, 0, 3, 0 ], ... } + * + * eqDelta(a, [1, 2, 3]) + * // true + * ``` + * + * @param buf + * @param size + * @param offset + * @param stride + */ +export const gvec = + (buf: Vec, size: number, offset = 0, stride = 1): IVector => + new Proxy(buf, { + get(obj, id) { + switch (id) { + case Symbol.iterator: + return () => values(obj, size, offset, stride); + case SYM_L: + return size; + case SYM_B: + return buf; + case SYM_O: + return offset; + case SYM_S: + return stride; + case SYM_C: + return () => + setS([], obj, size, 0, offset, 1, stride); + case SYM_CV: + return () => + gvec(obj, size, offset, stride); + case SYM_EMPTY: + return () => zeroes(size); + case SYM_EQD: + return (o, eps = EPS) => + eqDeltaS(buf, o, size, eps, offset, 0, stride, 1); + case SYM_STR: + return () => + JSON.stringify([...values(obj, size, offset, stride)]); + default: + const j = parseInt(id); + return !isNaN(j) && j >= 0 && j < size ? + obj[offset + j * stride] : + undefined; + } + }, + set(obj, id, value) { + const j = parseInt(id); + if (!isNaN(j) && j >= 0 && j < size) { + obj[offset + (id | 0) * stride] = value; + } else { + switch (id) { + case SYM_O: + offset = value; + break; + case SYM_S: + stride = value; + break; + case SYM_L: + size = value; + break; + default: + return false; + } + } + return true + }, + has(_, id) { + return (id >= 0 && id < size) || + PROPS.has(id); + }, + ownKeys() { + return keys(size); + } + }); diff --git a/packages/vectors/src/heading.ts b/packages/vectors/src/heading.ts new file mode 100644 index 0000000000..f4f7d8bb45 --- /dev/null +++ b/packages/vectors/src/heading.ts @@ -0,0 +1,8 @@ +import { atan2Abs } from "@thi.ng/math"; +import { ReadonlyVec } from "./api"; + +export const headingXY = (a: ReadonlyVec) => atan2Abs(a[1], a[0]); +export const headingXZ = (a: ReadonlyVec) => atan2Abs(a[2], a[0]); +export const headingYZ = (a: ReadonlyVec) => atan2Abs(a[2], a[1]); + +export const heading = headingXY; diff --git a/packages/vectors/src/homogeneous.ts b/packages/vectors/src/homogeneous.ts new file mode 100644 index 0000000000..1d98208bdd --- /dev/null +++ b/packages/vectors/src/homogeneous.ts @@ -0,0 +1,17 @@ +import { MultiVecOpV } from "./api"; +import { vop } from "./internal/vop"; +import { setC2, setC3 } from "./setc"; + +export const fromHomogeneous: MultiVecOpV = vop(1); + +export const fromHomogeneous3 = + fromHomogeneous.add(3, + (out, [x, y, w]) => + setC2(out || [], x / w, y / w) + ); + +export const fromHomogeneous4 = + fromHomogeneous.add(4, + (out, [x, y, z, w]) => + setC3(out || [], x / w, y / w, z / w) + ); diff --git a/packages/vectors/src/index.ts b/packages/vectors/src/index.ts index 921f2cba05..b7bcb04093 100644 --- a/packages/vectors/src/index.ts +++ b/packages/vectors/src/index.ts @@ -1,11 +1,113 @@ export * from "./api"; -export * from "./common"; -export * from "./mat23"; -export * from "./mat33"; -export * from "./mat44"; -export * from "./gvec"; +export * from "./internal/accessors"; +export * from "./internal/avec"; +export * from "./internal/codegen"; +export * from "./internal/templates"; +export * from "./internal/vec-utils"; +export * from "./internal/vop"; + export * from "./vec2"; export * from "./vec3"; export * from "./vec4"; -// export * from "./codegen"; +export * from "./abs"; +export * from "./acos"; +export * from "./addw"; +export * from "./add"; +export * from "./addm"; +export * from "./addmn"; +export * from "./addn"; +export * from "./adds"; +export * from "./angle-between"; +export * from "./asin"; +export * from "./bisect"; +export * from "./cartesian"; +export * from "./ceil"; +export * from "./clamp"; +export * from "./clampn"; +export * from "./compare"; +export * from "./copy"; +export * from "./cos"; +export * from "./cosh"; +export * from "./cross"; +export * from "./dist"; +export * from "./dist-chebyshev"; +export * from "./dist-manhattan"; +export * from "./distsq"; +export * from "./div"; +export * from "./divn"; +export * from "./divs"; +export * from "./dot"; +export * from "./dotc"; +export * from "./dots"; +export * from "./empty"; +export * from "./eqdelta"; +export * from "./exp"; +export * from "./face-forward"; +export * from "./floor"; +export * from "./fract"; +export * from "./gvec"; +export * from "./heading"; +export * from "./homogeneous"; +export * from "./invert"; +export * from "./invsqrt"; +export * from "./jitter"; +export * from "./limit"; +export * from "./log"; +export * from "./madd"; +export * from "./maddn"; +export * from "./mag"; +export * from "./magsq"; +export * from "./major"; +export * from "./map"; +export * from "./max"; +export * from "./min"; +export * from "./minor"; +export * from "./mix-bilinear"; +export * from "./mix-cubic"; +export * from "./mix-quadratic"; +export * from "./mix"; +export * from "./mixn"; +export * from "./mod"; +export * from "./modn"; +export * from "./mul"; +export * from "./muln"; +export * from "./muls"; +export * from "./neg"; +export * from "./normalize"; +export * from "./ortho-normal"; +export * from "./perpendicular"; +export * from "./polar"; +export * from "./pow"; +export * from "./pown"; +export * from "./project"; +export * from "./random"; +export * from "./reflect"; +export * from "./refract"; +export * from "./rotate-around-axis"; +export * from "./rotate-around-point"; +export * from "./rotate"; +export * from "./round"; +export * from "./set"; +export * from "./setc"; +export * from "./setn"; +export * from "./sets"; +export * from "./setsn"; +export * from "./sign"; +export * from "./signed-area"; +export * from "./sin"; +export * from "./sinh"; +export * from "./sqrt"; +export * from "./step"; +export * from "./smoothstep"; +export * from "./sub"; +export * from "./subm"; +export * from "./submn"; +export * from "./subn"; +export * from "./subs"; +export * from "./sum"; +export * from "./swizzle"; +export * from "./tan"; +export * from "./tanh"; +export * from "./trunc"; +export * from "./wrap"; diff --git a/packages/vectors/src/internal/accessors.ts b/packages/vectors/src/internal/accessors.ts new file mode 100644 index 0000000000..44f5dec4dd --- /dev/null +++ b/packages/vectors/src/internal/accessors.ts @@ -0,0 +1,32 @@ +export const declareIndex = ( + proto: any, + id: string, + idx: number, + strided = true, + defNumeric = true +) => { + const get = strided ? + function () { return this.buf[this.offset + idx * this.stride]; } : + function () { return this.buf[this.offset + idx]; }; + const set = strided ? + function (n: number) { this.buf[this.offset + idx * this.stride] = n; } : + function (n: number) { this.buf[this.offset + idx] = n; }; + + defNumeric && Object.defineProperty(proto, idx, { + get, + set, + enumerable: true, + }); + Object.defineProperty(proto, id, { + get, + set, + enumerable: true, + }); +}; + +export const declareIndices = ( + proto: any, + props: string[], + strided?: boolean, + defNumeric?: boolean +) => props.forEach((id, i) => declareIndex(proto, id, i, strided, defNumeric)); diff --git a/packages/vectors/src/internal/avec.ts b/packages/vectors/src/internal/avec.ts new file mode 100644 index 0000000000..335b95efa9 --- /dev/null +++ b/packages/vectors/src/internal/avec.ts @@ -0,0 +1,18 @@ +import { StridedVec, Vec } from "../api"; + +export abstract class AVec implements StridedVec { + + buf: Vec; + offset: number; + stride: number; + + constructor(buf: Vec, offset = 0, stride = 1) { + this.buf = buf; + this.offset = offset; + this.stride = stride; + } + + abstract get length(): number; + + abstract [Symbol.iterator](): IterableIterator; +} diff --git a/packages/vectors/src/internal/codegen.ts b/packages/vectors/src/internal/codegen.ts new file mode 100644 index 0000000000..56d5f84e80 --- /dev/null +++ b/packages/vectors/src/internal/codegen.ts @@ -0,0 +1,272 @@ +import { + comp, + map, + mapIndexed, + range, + str, + take, + transduce, + tuples +} from "@thi.ng/transducers"; +import { + MultiVecOpVN, + MultiVecOpVV, + VecOpVN, + VecOpVV +} from "../api"; +import { FN, MATH, MATH_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_VVN = "o,a,b,n"; + +export const SARGS_V = "io=0,ia=0,so=1,sa=1"; +export const SARGS_VV = "io=0,ia=0,ib=0,so=1,sa=1,sb=1"; +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: + * + * ``` + * lookup("a")(0) // a[ia] + * lookup("a")(1) // a[ia * sa] + * lookup("a")(2) // a[ia + 2 * sa] + * ``` + * + * @param sym + */ +const lookup = + (sym: string) => + (i) => i > 1 ? + `${sym}[i${sym}+${i}*s${sym}]` : + i == 1 ? `${sym}[i${sym}+s${sym}]` : + `${sym}[i${sym}]`; + +/** + * Infinite iterator of strided index lookups for `sym`. + * + * @param sym + */ +const indicesStrided = + (sym: string) => map(lookup(sym), range()); + +/** + * Infinite iterator of simple (non-strided) index lookups for `sym`. + * + * @param sym + */ +const indices = + (sym: string) => map((i) => `${sym}[${i}]`, range()); + +/** + * Code generator for loop-unrolled vector operations. Takes a vector + * size `dim`, a code template function `tpl` and an array of symbol + * names participating in the template. For each symbol, creates + * iterator of index lookups (e.g. `a[0]` or `a[ia+k*sa]`), forms them + * into tuples and passes them to template to generate code and joins + * generated result with `opJoin` separator (default: + * `""`). + * + * If the optional `ret` arg is not `null` (default `"a"`), appends a + * `return` statement to the result array, using `ret` as return value. + * Returns array of source code lines. + * + * The optional `pre` and `post` strings can be used to wrap the + * generated code. `post` will be injected **before** the generated + * return statement (if not suppressed). + * + * @param dim + * @param tpl + * @param syms + * @param ret + * @param opJoin + * @param pre + * @param post + * @param strided + */ +const assemble = ( + dim: number, + tpl: Template, + syms: string, + ret = "a", + opJoin = "", + pre = "", + post = "", + strided = false) => + + [ + pre, + transduce( + comp( + take(dim), + mapIndexed((i, x: string[]) => tpl(x, i)) + ), + str(opJoin), + tuples.apply( + null, + syms.split(",").map( + strided ? + indicesStrided : + indices, + ) + ) + ), + post, + ret !== null ? `return ${ret};` : "" + ]; + +const assembleG = ( + tpl: Template, + syms: string, + ret = "a", + pre?: string, + post?: string, + strided = false) => [ + pre, + "for(let i=a.length;--i>=0;) {", + tpl( + syms.split(",").map( + strided ? + (x) => `${x}[i${x}+i*s${x}]` : + (x) => `${x}[i]` + ) + ), + "}", + post, + ret !== null ? `return ${ret};` : "" + ]; + +export const defaultOut = + (o: string, args: string) => `!${o} && (${o}=${args.split(",")[1]});` + +export const compile = ( + dim: number, + tpl: Template, + args: string, + syms = args, + ret = "a", + opJoin?: string, + pre?: string, + post?: string, + strided = false) => + + new Function( + args, + assemble(dim, tpl, syms, ret, opJoin, pre, post, strided).join("") + ); + +export const compileHOF = ( + dim: number, + fns: any[], + tpl: Template, + hofArgs: string, + args: string, + syms = args, + ret = "a", + opJoin = "", + pre?: string, + post?: string, + strided = false) => { + + return new Function( + hofArgs, + `return (${args})=>{${ + assemble(dim, tpl, syms, ret, opJoin, pre, post, strided).join("") + }}` + )(...fns); +}; + +export const compileG = ( + tpl: Template, + args: string, + syms = args, + ret = "a", + pre?: string, + post?: string, + strided = false) => + + new Function( + args, + assembleG(tpl, syms, ret, pre, post, strided).join("") + ); + +export const compileGHOF = ( + fns: any[], + tpl: Template, + hofArgs: string, + args: string, + syms = args, + ret = "a", + pre?: string, + post?: string, + strided = false) => + + new Function( + hofArgs, + `return (${args})=>{${ + assembleG(tpl, syms, ret, pre, post, strided).join("") + }}` + )(...fns); + +export const defOp = ( + tpl: Template, + args = ARGS_VV, + syms?: string, + ret = "o", + dispatch = 1, + pre?: string): [M, V, V, V] => { + + 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)); + fn.default(compileG(tpl, args, syms, ret, pre)); + return [fn, $(2), $(3), $(4)]; +}; + +export const defFnOp = + (op: string) => defOp(FN(op), ARGS_V); + +export const defHofOp = ( + op, + tpl?: Template, + args = ARGS_V, + syms?: string, + ret = "o", + dispatch = 1, + pre?: string): [M, V, V, V] => { + + 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 fn: any = vop(dispatch); + fn.default(compileGHOF([op], tpl, "op", args, syms, ret, pre)); + return [fn, $(2), $(3), $(4)]; +}; + +export const defOpS = ( + tpl: Template, + args = `${ARGS_VV},${SARGS_VV}`, + syms = ARGS_VV, + ret = "o", + pre?: string, + sizes = [2, 3, 4]): V[] => + + sizes.map( + (dim) => compile(dim, tpl, args, syms, ret, "", pre != null ? pre : defaultOut(ret, args), "", true) + ); + +export const defMathOp = + (op: string) => defOp(MATH(op)); + +export const defMathNOp = + (op: string) => defOp(MATH_N(op), ARGS_VN); diff --git a/packages/vectors/src/internal/templates.ts b/packages/vectors/src/internal/templates.ts new file mode 100644 index 0000000000..a8acfdd1e3 --- /dev/null +++ b/packages/vectors/src/internal/templates.ts @@ -0,0 +1,21 @@ +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);` + +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;` + +export const HOF_VVV = ([o, a, b, c]) => `${o}=op(${a},${b},${c});`; + +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;`; diff --git a/packages/vectors/src/internal/vec-utils.ts b/packages/vectors/src/internal/vec-utils.ts new file mode 100644 index 0000000000..387d4d9174 --- /dev/null +++ b/packages/vectors/src/internal/vec-utils.ts @@ -0,0 +1,58 @@ +import { Vec, VecOpSV, VectorConstructor } from "../api"; + +export const mapBuffer = ( + ctor: VectorConstructor, + buf: Vec, + num: number, + start: number, + cstride: number, + estride: number +) => { + const res: T[] = []; + while (--num >= 0) { + res.push(new ctor(buf, start, cstride)); + start += estride; + } + return res; +}; + +export const intoBuffer = ( + set: VecOpSV, + buf: Vec, + src: Iterable, + start: number, + cstride: number, + estride: number +) => { + for (let v of src) { + set(buf, v, start, 0, cstride, 1); + start += estride; + } + return buf; +}; + +export function* vecIterator( + ctor: VectorConstructor, + buf: Vec, + num: number, + start: number, + cstride: number, + estride: number) { + + while (num-- > 0) { + yield new ctor(buf, start, cstride); + start += estride; + } +} + +export function* values( + buf: Vec, + num: number, + start: number, + stride: number +) { + while (num-- > 0) { + yield buf[start]; + start += stride; + } +} diff --git a/packages/vectors/src/internal/vop.ts b/packages/vectors/src/internal/vop.ts new file mode 100644 index 0000000000..71b4f26750 --- /dev/null +++ b/packages/vectors/src/internal/vop.ts @@ -0,0 +1,23 @@ +import { unsupported } from "@thi.ng/errors"; + +/** + * Specialized / optimized version of `@thi.ng/defmulti` for vector + * operations. Uses simplified logic to dispatch on length (vector size) + * of `dispatch` argument. + * + * @param dispatch arg index + */ +export const vop = (dispatch = 0) => { + const impls = new Array(5); + let fallback; + 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.impls = impls; + return fn; +}; diff --git a/packages/vectors/src/invert.ts b/packages/vectors/src/invert.ts new file mode 100644 index 0000000000..64bde8064b --- /dev/null +++ b/packages/vectors/src/invert.ts @@ -0,0 +1,5 @@ +import { MultiVecOpV, VecOpV } from "./api"; +import { defOp } from "./internal/codegen"; + +export const [invert, invert2, invert3, invert4] = + defOp(([o, a]) => `${o}=1/${a};`); diff --git a/packages/vectors/src/invsqrt.ts b/packages/vectors/src/invsqrt.ts new file mode 100644 index 0000000000..f948bd5480 --- /dev/null +++ b/packages/vectors/src/invsqrt.ts @@ -0,0 +1,5 @@ +import { MultiVecOpV, VecOpV } from "./api"; +import { defOp } from "./internal/codegen"; + +export const [invSqrt, invSqrt2, invSqrt3, invSqrt4] = + defOp(([o, a]) => `${o}=1/Math.sqrt(${a});`); diff --git a/packages/vectors/src/jitter.ts b/packages/vectors/src/jitter.ts new file mode 100644 index 0000000000..0b2ca7ce91 --- /dev/null +++ b/packages/vectors/src/jitter.ts @@ -0,0 +1,8 @@ +import { IRandom, SYSTEM } from "@thi.ng/random"; +import { add } from "./add"; +import { ReadonlyVec, Vec } from "./api"; +import { randNorm } from "./random"; + +export const jitter = + (out: Vec, a: ReadonlyVec, n = 1, rnd: IRandom = SYSTEM) => + add(out, a, randNorm(new Array(a.length), n, rnd)); diff --git a/packages/vectors/src/limit.ts b/packages/vectors/src/limit.ts new file mode 100644 index 0000000000..40dd78d14d --- /dev/null +++ b/packages/vectors/src/limit.ts @@ -0,0 +1,15 @@ +import { ReadonlyVec, Vec } from "./api"; +import { mag } from "./mag"; +import { mulN } from "./muln"; +import { set } from "./set"; + +export const limit = + (out: Vec, v: ReadonlyVec, n: number) => { + !out && (out = v); + const m = mag(v); + return m > n ? + mulN(out, v, n / m) : + out !== v ? + set(out, v) : + out; + }; diff --git a/packages/vectors/src/log.ts b/packages/vectors/src/log.ts new file mode 100644 index 0000000000..138a22a29d --- /dev/null +++ b/packages/vectors/src/log.ts @@ -0,0 +1,5 @@ +import { MultiVecOpV, VecOpV } from "./api"; +import { defFnOp } from "./internal/codegen"; + +export const [log, log2, log3, log4] = + defFnOp("Math.log"); diff --git a/packages/vectors/src/madd.ts b/packages/vectors/src/madd.ts new file mode 100644 index 0000000000..5c577ca5f4 --- /dev/null +++ b/packages/vectors/src/madd.ts @@ -0,0 +1,11 @@ +import { MultiVecOpVVV, VecOpVVV } from "./api"; +import { ARGS_VVV, defOp } from "./internal/codegen"; +import { MADD } from "./internal/templates"; + +/** + * Returns `out = a + b * c`. + * + * @see addm + */ +export const [madd, madd2, madd3, madd4] = + defOp(MADD, ARGS_VVV); diff --git a/packages/vectors/src/maddn.ts b/packages/vectors/src/maddn.ts new file mode 100644 index 0000000000..1e067a5835 --- /dev/null +++ b/packages/vectors/src/maddn.ts @@ -0,0 +1,9 @@ +import { MultiVecOpVVN, VecOpVVN } from "./api"; +import { ARGS_VVN, defOp } from "./internal/codegen"; +import { MADD_N } from "./internal/templates"; + +/** + * Returns `out = a + b * n`. + */ +export const [maddN, maddN2, maddN3, maddN4] = + defOp(MADD_N, ARGS_VVN); diff --git a/packages/vectors/src/mag.ts b/packages/vectors/src/mag.ts new file mode 100644 index 0000000000..0ac55ab8f7 --- /dev/null +++ b/packages/vectors/src/mag.ts @@ -0,0 +1,5 @@ +import { ReadonlyVec } from "./api"; +import { magSq } from "./magsq"; + +export const mag = + (v: ReadonlyVec) => Math.sqrt(magSq(v)); diff --git a/packages/vectors/src/magsq.ts b/packages/vectors/src/magsq.ts new file mode 100644 index 0000000000..f2533c874b --- /dev/null +++ b/packages/vectors/src/magsq.ts @@ -0,0 +1,28 @@ +import { MultiVecOpRoV } from "./api"; +import { compile, compileG } from "./internal/codegen"; +import { vop } from "./internal/vop"; + +const $ = (dim: number) => + magSq.add( + dim, + compile( + dim, + ([a]) => `${a}*${a}`, + "a", + "a", + null, + "+", + "return ", + ";" + ) + ); + +export const magSq: MultiVecOpRoV = vop(); + +magSq.default( + compileG(([a]) => `sum+=${a}*${a};`, "a", undefined, "sum", "let sum=0;") +); + +export const magSq2 = $(2); +export const magSq3 = $(3); +export const magSq4 = $(4); diff --git a/packages/vectors/src/major.ts b/packages/vectors/src/major.ts new file mode 100644 index 0000000000..e3d3325add --- /dev/null +++ b/packages/vectors/src/major.ts @@ -0,0 +1,29 @@ +import { max2id, max3id, max4id } from "@thi.ng/math"; +import { MultiVecOpRoV } from "./api"; +import { vop } from "./internal/vop"; + +const abs = Math.abs; + +/** + * Returns index of major component/axis in `v`, i.e. where `|v[i]|` is + * the largest. + * + * @param v + */ +export const major: MultiVecOpRoV = vop(); + +major.default((a) => { + let id, max = -Infinity; + for (let i = a.length; --i >= 0;) { + const x = abs(a[i]); + if (x > max) { + max = x; + id = i; + } + } + return id; +}); + +export const major2 = major.add(2, (a) => max2id(abs(a[0]), abs(a[1]))); +export const major3 = major.add(3, (a) => max3id(abs(a[0]), abs(a[1]), abs(a[2]))); +export const major4 = major.add(4, (a) => max4id(abs(a[0]), abs(a[1]), abs(a[2]), abs(a[3]))); diff --git a/packages/vectors/src/map.ts b/packages/vectors/src/map.ts new file mode 100644 index 0000000000..495ff8d463 --- /dev/null +++ b/packages/vectors/src/map.ts @@ -0,0 +1,229 @@ +import { IVector, VecOpV, VecOpVV, VecOpVN, VecOpVVV, VecOpVVN } from "./api"; + +/** + * Vec2/3/4 view based buffer transformation for `VecOpVV` type ops and + * supporting arbitrary component and element layouts of all input and + * output buffers. The given pre-initialized vectors MUST be separate + * instances, are used as sliding cursors / views of their respective + * backing buffers and will be modified as part of the transformation + * process (though the input buffers themselves are treated as + * immutable, unless `out` is configured to use one of the input + * buffers). + * + * In each iteration `op` is called via `op(out, a, b)`, followed by + * cursor updates to process the next vector view. No bounds checking is + * performed. + * + * This function returns `out`'s backing buffer. + * + * ``` + * // each input buffer contains 2 2D vectors, but using + * // different strided data layouts + * mapVV( + * // transformation function + * add, + * // init output buffer view + * new Vec2(), + * // wrap 1st input buffer & configure offset & component stride + * new Vec2([1,0,2,0,0,0,0,0,3,0,4,0,0,0,0,0], 0, 2), + * // wrap 2nd input buffer + * new Vec2([0,10,0,0,20,0,0,30,0,0,40], 1, 3), + * 2, // num vectors + * 2, // output element stride + * 8, // input #1 element stride + * 6 // input #2 element stride + * ); + * // [ 11, 22, 33, 44 ] + * ``` + * + * Alternatively, `Vec2/3/4.iterator()` combined with transducers can be + * used to achieve the same (and more flexible) transformations, but + * will incur more intermediate object allocations. `mapV*()` + * functions only use (and mutate) the provided vector instances and do + * not allocate any further objects. + * + * ``` + * // output buffer + * const out = new Array(4); + * + * tx.run( + * tx.map(([o, a, b]) => add(o, a, b)), + * tx.tuples( + * Vec2.iterator(out, 2), + * Vec2.iterator([1,0,2,0,0,0,0,0,3,0,4,0,0,0,0,0], 2, 0, 2, 8), + * Vec2.iterator([0,10,0,0,20,0,0,30,0,0,40], 2, 1, 3, 6), + * ) + * ); + * + * out + * // [ 11, 22, 33, 44 ] + * ``` + * + * @param op + * @param out + * @param a + * @param b + * @param num + * @param so + * @param sa + * @param sb + */ +export const mapVV = ( + op: VecOpVV, + out: IVector, + a: IVector, + b: IVector, + num: number, + so = out.length * out.stride, + sa = a.length * a.stride, + sb = b.length * b.stride) => { + + while (num-- > 0) { + op(out, a, b); + out.offset += so; + a.offset += sa; + b.offset += sb; + } + return out.buf; +}; + +/** + * Like `mapVV`, but for `VecOpV` type ops and hence only using + * single input. + * + * ``` + * // 4x 2D vectors in SOA layout + * // i.e. [x1, x2, x3, x4, y1, y2, y3, y4] + * buf = [1, 3, 5, 7, 2, 4, 6, 8]; + * + * // use `swapXY` to swizzle each vector and use AOS for output + * res = mapV(swapXY, new Vec2(), new Vec2(buf, 0, 4), 4, 2, 1); + * // [ 2, 1, 4, 3, 6, 5, 8, 7 ] + * + * // unpack result for demonstration purposes + * [...Vec2.iterator(res, 4)].map(v => [...v]); + * // [ [ 2, 1 ], [ 4, 3 ], [ 6, 5 ], [ 8, 7 ] ] + * ``` + * + * @param op + * @param out + * @param a + * @param num + * @param so + * @param sa + */ +export const mapV = ( + op: VecOpV, + out: IVector, + a: IVector, + num: number, + so = out.length * out.stride, + sa = a.length * a.stride) => { + + while (num-- > 0) { + op(out, a); + out.offset += so; + a.offset += sa; + } + return out.buf; +}; + +/** + * Like `mapVV`, but for `VecOpVN` type ops and hence using a single + * vector input buffer `a` and a scalar `n`. + * + * @param op + * @param out + * @param a + * @param n + * @param num + * @param so + * @param sa + */ +export const mapVN = ( + op: VecOpVN, + out: IVector, + a: IVector, + n: number, + num: number, + so = out.length * out.stride, + sa = a.length * a.stride) => { + + while (num-- > 0) { + op(out, a, n); + out.offset += so; + a.offset += sa; + } + return out.buf; +}; + +/** + * Like `mapVV`, but for `VecOpVVV` type ops and hence using three + * vector input buffers `a`, `b`, `c`. + * + * @param op + * @param out + * @param a + * @param b + * @param c + * @param num + * @param so + * @param sa + * @param sb + * @param sc + */ +export const mapVVV = ( + op: VecOpVVV, + out: IVector, + a: IVector, + b: IVector, + c: IVector, + num: number, + so = out.length * out.stride, + sa = a.length * a.stride, + sb = b.length * b.stride, + sc = c.length * c.stride) => { + + while (num-- > 0) { + op(out, a, b, c); + out.offset += so; + a.offset += sa; + b.offset += sb; + c.offset += sc; + } + return out.buf; +}; + +/** + * Like `mapVV`, but for `VecOpVVN` type ops and hence using two + * vector input buffers `a`, `b` and a scalar `n`. + * + * @param op + * @param out + * @param a + * @param b + * @param n + * @param num + * @param so + * @param sa + * @param sb + */ +export const mapVVN = ( + op: VecOpVVN, + out: IVector, + a: IVector, + b: IVector, + n: number, + num: number, + so = out.length * out.stride, + sa = a.length * a.stride, + sb = b.length * b.stride) => { + + while (num-- > 0) { + op(out, a, b, n); + out.offset += so; + a.offset += sa; + b.offset += sb; + } + return out.buf; +}; diff --git a/packages/vectors/src/mat23.ts b/packages/vectors/src/mat23.ts deleted file mode 100644 index f7e3683be9..0000000000 --- a/packages/vectors/src/mat23.ts +++ /dev/null @@ -1,309 +0,0 @@ -import { ICopy, IEqualsDelta } from "@thi.ng/api/api"; -import { isArrayLike } from "@thi.ng/checks/is-arraylike"; -import { EPS } from "@thi.ng/math/api"; -import { - Mat, - ReadonlyMat, - ReadonlyVec, - Vec -} from "./api"; -import { declareIndices } from "./codegen"; -import { $iter, eqDelta } from "./common"; -import { - cross2, - dot2, - setS2, - Vec2 -} from "./vec2"; - -export const get23 = (a: Mat, i = 0) => - a.slice(i, i + 6); - -export const set23 = (a: Mat, b: ReadonlyMat, ia = 0, ib = 0) => ( - a[ia] = b[ib], - a[ia + 1] = b[ib + 1], - a[ia + 2] = b[ib + 2], - a[ia + 3] = b[ib + 3], - a[ia + 4] = b[ib + 4], - a[ia + 5] = b[ib + 5], - a -); - -/** - * ``` - * m00 m10 m20 - * m01 m11 m21 - * ``` - * - * @param m - * @param m00 - * @param m01 - * @param m10 - * @param m11 - * @param m20 - * @param m21 - * @param i - */ -export const setS23 = ( - m: Mat, - m00: number, m01: number, - m10: number, m11: number, - m20: number, m21: number, - i = 0) => ( - m[i] = m00, - m[i + 1] = m01, - m[i + 2] = m10, - m[i + 3] = m11, - m[i + 4] = m20, - m[i + 5] = m21, - m - ); - -export const identity23 = (m?: Mat, i = 0) => - setS23(m || [], 1, 0, 0, 1, 0, 0, i); - -export const rotation23 = (m: Mat, theta: number, i = 0) => { - const s = Math.sin(theta); - const c = Math.cos(theta); - return setS23(m || [], c, s, -s, c, 0, 0, i); -}; - -export const rotationAroundPoint23 = (m: Mat, p: ReadonlyVec, theta: number, im = 0, iv = 0, sv = 1) => - concat23( - translationV23(m || [], p, im, iv, sv), im, - rotation23([], theta), - translationS23([], -p[iv], -p[iv + sv]) - ); - -export const scaleV23 = (m: Mat, v: Vec, i = 0, iv = 0, sv = 1) => - scaleS23(m, v[iv], v[iv + sv], i); - -export const scaleN23 = (m: Mat, n: number, i = 0) => - scaleS23(m, n, n, i); - -export const scaleS23 = (m: Mat, sx: number, sy: number, i = 0) => - setS23(m || [], sx, 0, 0, sy, 0, 0, i); - -export const scaleWithCenter23 = (m: Mat, p: ReadonlyVec, sx: number, sy: number, im = 0, iv = 0, sv = 1) => - concat23( - translationV23(m || [], p, im, iv, sv), im, - scaleS23([], sx, sy), - translationS23([], -p[iv], -p[iv + sv]) - ); - -export const translationV23 = (m: Mat, v: ReadonlyVec, i = 0, iv = 0, sv = 1) => - translationS23(m, v[iv], v[iv + sv], i); - -export const translationS23 = (m: Mat, x: number, y: number, i = 0) => - setS23(m || [], 1, 0, 0, 1, x, y, i); - -export const shearX23 = (m: Mat, x: number, i = 0) => - setS23(m || [], 1, 0, x, 1, 0, 0, i); - -export const shearY23 = (m: Mat, y: number, i = 0) => - setS23(m || [], 1, y, 0, 1, 0, 0, i); - -export const skewX23 = (m: Mat, theta: number, i = 0) => - shearX23(m, Math.tan(theta), i); - -export const skewY23 = (m: Mat, theta: number, i = 0) => - shearY23(m, Math.tan(theta), i); - -export const mul23 = (a: Mat, b: ReadonlyMat, ia = 0, ib = 0) => - setS23( - a, - dot2(a, b, ia, ib, 2), - dot2(a, b, ia + 1, ib, 2), - dot2(a, b, ia, ib + 2, 2), - dot2(a, b, ia + 1, ib + 2, 2), - dot2(a, b, ia, ib + 4, 2) + a[ia + 4], - dot2(a, b, ia + 1, ib + 4, 2) + a[ia + 5], - ia - ); - -export const concat23 = (a: Mat, ia: number, ...xs: (ReadonlyMat | [ReadonlyMat, number])[]) => - xs.reduce( - (acc: Mat, x) => isArrayLike(x[0]) ? - mul23(acc, x[0], ia, x[1]) : - mul23(acc, x, ia), - a - ); - -export const mulV23 = (v: Vec, m: ReadonlyMat, iv = 0, im = 0, sv = 1) => - setS2( - v, - dot2(m, v, im, iv, 2, sv) + m[im + 4], - dot2(m, v, im + 1, iv, 2, sv) + m[im + 5], - iv, sv - ); - -export const det23 = (m: ReadonlyMat, i = 0) => - cross2(m, m, i, i + 1, 2, 2); - -export const invert23 = (m: Mat, i = 0) => { - const m00 = m[i]; - const m01 = m[i + 1]; - const m10 = m[i + 2]; - const m11 = m[i + 3]; - const m20 = m[i + 4]; - const m21 = m[i + 5]; - let det = m00 * m11 - m01 * m10; - if (!det) { - return; - } - det = 1.0 / det; - return setS23( - m, - m11 * det, - -m01 * det, - -m10 * det, - m00 * det, - (m10 * m21 - m11 * m20) * det, - (m01 * m20 - m00 * m21) * det, - i - ); -} - -export class Mat23 implements - ICopy, - IEqualsDelta { - - static identity() { - return new Mat23(identity23()); - } - - static rotation(theta: number) { - return new Mat23(rotation23([], theta)); - } - - static rotationAroundPoint(p: Readonly, theta: number) { - return new Mat23(rotationAroundPoint23([], p.buf, theta, 0, p.i, p.s)); - } - - static scale(v: Vec2): Mat23; - static scale(n: number): Mat23; - static scale(x: number, y: number): Mat23; - static scale(x: any, y = x) { - return new Mat23( - x instanceof Vec2 ? - scaleV23([], x.buf, 0, x.i, x.s) : - scaleS23([], x, y) - ); - } - - static scaleWithCenter(p: Readonly, sx: number, sy = sx) { - return new Mat23(scaleWithCenter23([], p.buf, sx, sy, p.i, p.s)); - } - - static translation(v: Readonly): Mat23; - static translation(x: number, y: number): Mat23; - static translation(x: any, y?: any) { - return new Mat23( - x instanceof Vec2 ? - translationV23([], x.buf, 0, x.i) : - translationS23([], x, y) - ); - } - - static skewX(x: number) { - return new Mat23(skewX23([], x)); - } - - static skewY(y: number) { - return new Mat23(skewY23([], y)); - } - - static shearX(theta: number) { - return new Mat23(shearX23([], theta)); - } - - static shearY(theta: number) { - return new Mat23(shearY23([], theta)); - } - - static concat(m: Readonly, ...xs: Readonly[]) { - return new Mat23(concat23.apply(null, [ - get23(m.buf, m.i), 0, - ...<[ReadonlyMat, number][]>xs.map((x) => [x.buf, x.i])]) - ); - } - - buf: Mat; - i: number; - m00: number; - m01: number; - m10: number; - m11: number; - m20: number; - m21: number; - [id: number]: number; - - constructor(buf?: Mat, i = 0) { - this.buf = buf || [0, 0, 0, 0, 0, 0]; - this.i = i; - } - - [Symbol.iterator]() { - return $iter(this.buf, 6, this.i); - } - - get length() { - return 6; - } - - copy() { - return new Mat23(get23(this.buf, this.i)); - } - - eqDelta(m: Mat23, eps = EPS) { - return eqDelta(this.buf, m.buf, 6, eps, this.i, m.i); - } - - identity() { - identity23(this.buf, this.i); - return this; - } - - set(m: Readonly) { - set23(this.buf, m.buf, this.i, m.i); - return this; - } - - setS(m00: number, m01: number, m10: number, m11: number, m20: number, m21: number) { - setS23(this.buf, m00, m01, m10, m11, m20, m21, this.i); - return this; - } - - mul(m: Readonly) { - mul23(this.buf, m.buf, this.i, m.i); - return this; - } - - mulV(v: Vec2) { - mulV23(v.buf, this.buf, v.i, this.i, v.s); - return v; - } - - determinant() { - return det23(this.buf, this.i); - } - - invert() { - invert23(this.buf, this.i); - return this; - } - - toString() { - const b = (get23(this.buf, this.i)).map((x) => x.toFixed(4)); - return `${b[0]} ${b[2]} ${b[4]}\n${b[1]} ${b[3]} ${b[5]}`; - } - - toJSON() { - return get23(this.buf, this.i); - } -} - -declareIndices( - Mat23.prototype, - ["m00", "m01", "m10", "m11", "m20", "m21"] -); diff --git a/packages/vectors/src/mat33.ts b/packages/vectors/src/mat33.ts deleted file mode 100644 index b4235482ef..0000000000 --- a/packages/vectors/src/mat33.ts +++ /dev/null @@ -1,355 +0,0 @@ -import { ICopy, IEqualsDelta } from "@thi.ng/api/api"; -import { isArrayLike } from "@thi.ng/checks/is-arraylike"; -import { EPS } from "@thi.ng/math/api"; -import { - Mat, - ReadonlyMat, - ReadonlyVec, - Vec -} from "./api"; -import { declareIndices } from "./codegen"; -import { $iter, eqDelta } from "./common"; -import { - dot3, - set3, - setS3, - Vec3 -} from "./vec3"; -import { setS4 } from "./vec4"; - -export const get33 = (a: Mat, i = 0) => - a.slice(i, i + 9); - -export const set33 = (a: Mat, b: ReadonlyMat, ia = 0, ib = 0) => ( - a[ia] = b[ib], - a[ia + 1] = b[ib + 1], - a[ia + 2] = b[ib + 2], - a[ia + 3] = b[ib + 3], - a[ia + 4] = b[ib + 4], - a[ia + 5] = b[ib + 5], - a[ia + 6] = b[ib + 6], - a[ia + 7] = b[ib + 7], - a[ia + 8] = b[ib + 8], - a -); - -/** - * ``` - * m00 m10 m20 - * m01 m11 m21 - * m02 m12 m22 - * ``` - * - * @param m - * @param m00 - * @param m01 - * @param m02 - * @param m10 - * @param m11 - * @param m12 - * @param m20 - * @param m21 - * @param m22 - * @param i - */ -export const setS33 = ( - m: Mat, - m00: number, m01: number, m02: number, - m10: number, m11: number, m12: number, - m20: number, m21: number, m22: number, - i = 0) => ( - m[i] = m00, - m[i + 1] = m01, - m[i + 2] = m02, - m[i + 3] = m10, - m[i + 4] = m11, - m[i + 5] = m12, - m[i + 6] = m20, - m[i + 7] = m21, - m[i + 8] = m22, - m - ); - -export const identity33 = (m?: Mat, i = 0) => - setS33(m || [], - 1, 0, 0, - 0, 1, 0, - 0, 0, 1, - i - ); - -export const rotationX33 = (m: Mat, theta: number, i = 0) => { - const s = Math.sin(theta); - const c = Math.cos(theta); - return setS33(m || [], - 1, 0, 0, - 0, c, s, - 0, -s, c, - i - ); -}; - -export const rotationY33 = (m: Mat, theta: number, i = 0) => { - const s = Math.sin(theta); - const c = Math.cos(theta); - return setS33(m || [], - c, 0, -s, - 0, 1, 0, - s, 0, c, - i - ); -}; - -export const rotationZ33 = (m: Mat, theta: number, i = 0) => { - const s = Math.sin(theta); - const c = Math.cos(theta); - return setS33(m || [], - c, s, 0, - -s, c, 0, - 0, 0, 1, - i - ); -}; - -export const scaleV33 = (m: Mat, v: ReadonlyVec, i = 0, iv = 0, sv = 1) => - scaleS33(m, v[iv], v[iv + sv], v[iv + 2 * sv], i); - -export const scaleN33 = (m: Mat, n: number, i = 0) => - scaleS33(m, n, n, n, i); - -export const scaleS33 = (m: Mat, sx: number, sy: number, sz: number, i = 0) => - setS33(m || [], - sx, 0, 0, - 0, sy, 0, - 0, 0, sz, - i - ); - -export const mul33 = (a: Mat, b: ReadonlyMat, ia = 0, ib = 0) => - setS33( - a, - dot3(a, b, ia, ib, 3), - dot3(a, b, ia + 1, ib, 3), - dot3(a, b, ia + 2, ib, 3), - dot3(a, b, ia, ib + 3, 3), - dot3(a, b, ia + 1, ib + 3, 3), - dot3(a, b, ia + 2, ib + 3, 3), - dot3(a, b, ia, ib + 6, 3), - dot3(a, b, ia + 1, ib + 6, 3), - dot3(a, b, ia + 2, ib + 6, 3), - ia - ); - -export const concat33 = (a: Mat, ia: number, ...xs: (ReadonlyMat | [ReadonlyMat, number])[]) => - xs.reduce( - (acc: Mat, x) => isArrayLike(x[0]) ? - mul33(acc, x[0], ia, x[1]) : - mul33(acc, x, ia), - a - ); - -export const mulV33 = (v: Vec, m: ReadonlyMat, iv = 0, im = 0, sv = 1) => - setS3( - v, - dot3(m, v, im, iv, 3, sv), - dot3(m, v, im + 1, iv, 3, sv), - dot3(m, v, im + 2, iv, 3, sv), - iv, sv - ); - -export const det33 = (m: ReadonlyMat, i = 0) => { - const m00 = m[i]; - const m01 = m[i + 1]; - const m02 = m[i + 2]; - const m10 = m[i + 3]; - const m11 = m[i + 4]; - const m12 = m[i + 5]; - const m20 = m[i + 6]; - const m21 = m[i + 7]; - const m22 = m[i + 8]; - const d01 = m22 * m11 - m12 * m21; - const d11 = -m22 * m10 + m12 * m20; - const d21 = m21 * m10 - m11 * m20; - return m00 * d01 + m01 * d11 + m02 * d21; -}; - -export const invert33 = (m: Mat, i = 0) => { - const m00 = m[i]; - const m01 = m[i + 1]; - const m02 = m[i + 2]; - const m10 = m[i + 3]; - const m11 = m[i + 4]; - const m12 = m[i + 5]; - const m20 = m[i + 6]; - const m21 = m[i + 7]; - const m22 = m[i + 8]; - const d01 = m22 * m11 - m12 * m21; - const d11 = -m22 * m10 + m12 * m20; - const d21 = m21 * m10 - m11 * m20; - let det = m00 * d01 + m01 * d11 + m02 * d21; - if (!det) { - return; - } - det = 1.0 / det; - return setS33( - m, - d01 * det, - (-m22 * m01 + m02 * m21) * det, - (m12 * m01 - m02 * m11) * det, - d11 * det, - (m22 * m00 - m02 * m20) * det, - (-m12 * m00 + m02 * m10) * det, - d21 * det, - (-m21 * m00 + m01 * m20) * det, - (m11 * m00 - m01 * m10) * det, - i - ); -} - -export const transpose33 = (m: Mat, i = 0) => - setS33( - m, - m[i], m[i + 3], m[i + 6], - m[i + 1], m[i + 4], m[i + 7], - m[i + 2], m[i + 5], m[i + 8], - i - ); - -export const mat33to44 = (m44: Mat, m33: ReadonlyMat, ia = 0, ib = 0) => ( - set3(m44, m33, ia, ib), - set3(m44, m33, ia + 4, ib + 3), - set3(m44, m33, ia + 8, ib + 6), - setS3(m44, 0, 0, 0, ia + 12), - setS4(m44, 0, 0, 0, 1, ia + 3, 4), - m44 -); - -export class Mat33 implements - ICopy, - IEqualsDelta { - - static identity() { - return new Mat33(identity33()); - } - - static rotationX(theta: number) { - return new Mat33(rotationX33([], theta)); - } - - static rotationY(theta: number) { - return new Mat33(rotationY33([], theta)); - } - - static rotationZ(theta: number) { - return new Mat33(rotationZ33([], theta)); - } - - static scale(v: Readonly): Mat33; - static scale(n: number): Mat33; - static scale(x: number, y: number, z: number): Mat33; - static scale(x: any, y = x, z = x) { - return new Mat33( - x instanceof Vec3 ? - scaleV33([], x.buf, 0, x.i) : - scaleS33([], x, y, z) - ); - } - - static concat(m: Readonly, ...xs: Readonly[]) { - return new Mat33(concat33.apply(null, [ - get33(m.buf, m.i), 0, - ...<[ReadonlyMat, number][]>xs.map((x) => [x.buf, x.i])]) - ); - } - - buf: Mat; - i: number; - m00: number; - m01: number; - m02: number; - m10: number; - m11: number; - m12: number; - m20: number; - m21: number; - m22: number; - [id: number]: number; - - constructor(buf?: Mat, i = 0) { - this.buf = buf || [0, 0, 0, 0, 0, 0, 0, 0, 0]; - this.i = i; - } - - [Symbol.iterator]() { - return $iter(this.buf, 9, this.i); - } - - get length() { - return 9; - } - - copy() { - return new Mat33(get33(this.buf, this.i)); - } - - eqDelta(m: Mat33, eps = EPS) { - return eqDelta(this.buf, m.buf, 9, eps, this.i, m.i); - } - - identity() { - identity33(this.buf, this.i); - return this; - } - - set(m: Readonly) { - set33(this.buf, m.buf, this.i, m.i); - return this; - } - - setS(m00: number, m01: number, m02: number, - m10: number, m11: number, m12: number, - m20: number, m21: number, m22: number) { - setS33(this.buf, m00, m01, m02, m10, m11, m12, m20, m21, m22, this.i); - return this; - } - - mul(m: Readonly) { - mul33(this.buf, m.buf, this.i, m.i); - return this; - } - - mulV(v: Vec3) { - mulV33(v.buf, this.buf, v.i, this.i, v.s); - return v; - } - - determinant() { - return det33(this.buf, this.i); - } - - invert() { - invert33(this.buf, this.i); - return this; - } - - transpose() { - transpose33(this.buf, this.i); - return this; - } - - toString() { - const b = (get33(this.buf, this.i)).map((x) => x.toFixed(4)); - return `${b[0]} ${b[3]} ${b[6]} -${b[1]} ${b[4]} ${b[7]} -${b[2]} ${b[5]} ${b[8]}`; - } - - toJSON() { - return get33(this.buf, this.i); - } -} - -declareIndices( - Mat33.prototype, - ["m00", "m01", "m02", "m10", "m11", "m12", "m20", "m21", "m22"] -); diff --git a/packages/vectors/src/mat44.ts b/packages/vectors/src/mat44.ts deleted file mode 100644 index fdb447d5a1..0000000000 --- a/packages/vectors/src/mat44.ts +++ /dev/null @@ -1,598 +0,0 @@ -import { ICopy, IEqualsDelta } from "@thi.ng/api/api"; -import { isArrayLike } from "@thi.ng/checks/is-arraylike"; -import { - Mat, - ReadonlyMat, - ReadonlyVec, - Vec -} from "./api"; -import { declareIndices } from "./codegen"; -import { $iter, eqDelta } from "./common"; -import { Mat33 } from "./mat33"; -import { - cross3, - dot3, - get3, - normalize3, - set3, - setS3, - sub3, - Vec3 -} from "./vec3"; -import { dot4, setS4, Vec4 } from "./vec4"; -import { EPS, DEG2RAD } from "@thi.ng/math/api"; - -export const get44 = (a: Mat, i = 0) => - a.slice(i, i + 16); - -export const set44 = (a: Mat, b: ReadonlyMat, ia = 0, ib = 0) => { - for (let i = 0; i < 16; i++) { - a[ia + i] = b[ib + i]; - } - return a; -}; - -/** - * ``` - * m00 m10 m20 m30 - * m01 m11 m21 m31 - * m02 m12 m22 m32 - * m03 m13 m23 m33 - * ``` - */ -export const setS44 = ( - m: Mat, - m00: number, m01: number, m02: number, m03: number, - m10: number, m11: number, m12: number, m13: number, - m20: number, m21: number, m22: number, m23: number, - m30: number, m31: number, m32: number, m33: number, - i = 0) => ( - m[i] = m00, - m[i + 1] = m01, - m[i + 2] = m02, - m[i + 3] = m03, - m[i + 4] = m10, - m[i + 5] = m11, - m[i + 6] = m12, - m[i + 7] = m13, - m[i + 8] = m20, - m[i + 9] = m21, - m[i + 10] = m22, - m[i + 11] = m23, - m[i + 12] = m30, - m[i + 13] = m31, - m[i + 14] = m32, - m[i + 15] = m33, - m - ); - -export const identity44 = (m?: Mat, i = 0) => - setS44(m || [], - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1, - i - ); - -export const rotationX44 = (m: Mat, theta: number, i = 0) => { - const s = Math.sin(theta); - const c = Math.cos(theta); - return setS44(m || [], - 1, 0, 0, 0, - 0, c, s, 0, - 0, -s, c, 0, - 0, 0, 0, 1, - i - ); -}; - -export const rotationY44 = (m: Mat, theta: number, i = 0) => { - const s = Math.sin(theta); - const c = Math.cos(theta); - return setS44(m || [], - c, 0, -s, 0, - 0, 1, 0, 0, - s, 0, c, 0, - 0, 0, 0, 1, - i - ); -}; - -export const rotationZ44 = (m: Mat, theta: number, i = 0) => { - const s = Math.sin(theta); - const c = Math.cos(theta); - return setS44(m || [], - c, s, 0, 0, - -s, c, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1, - i - ); -}; - -export const scaleV44 = (m: Mat, v: ReadonlyVec, i = 0, iv = 0, sv = 1) => - scaleS44(m, v[iv], v[iv + sv], v[iv + 2 * sv], i); - -export const scaleN44 = (m: Mat, n: number, i = 0) => - scaleS44(m, n, n, n, i); - -export const scaleS44 = (m: Mat, sx: number, sy: number, sz: number, i = 0) => - setS44(m || [], - sx, 0, 0, 0, - 0, sy, 0, 0, - 0, 0, sz, 0, - 0, 0, 0, 1, - i - ); - -export const scaleWithCenter44 = (m: Mat, p: ReadonlyVec, sx: number, sy: number, sz: number, im = 0, iv = 0, sv = 1) => - concat44( - translationV44(m || [], p, im, iv, sv), im, - scaleS44([], sx, sy, sz), - translationS44([], -p[iv], -p[iv + sv], -p[iv + 2 * sv]) - ); - -export const translationV44 = (m: Mat, v: ReadonlyVec, i = 0, iv = 0, sv = 1) => - translationS44(m, v[iv], v[iv + sv], v[iv + 2 * sv], i); - -export const translationS44 = (m: Mat, x: number, y: number, z: number, i = 0) => - setS44(m || [], - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - x, y, z, 1, - i - ); - -export const frustum = (m: Mat, left: number, right: number, bottom: number, top: number, near: number, far: number, i = 0) => { - const dx = 1 / (right - left); - const dy = 1 / (top - bottom); - const dz = 1 / (far - near); - return setS44(m || [], - near * 2 * dx, 0, 0, 0, - 0, near * 2 * dy, 0, 0, - (right + left) * dx, (top + bottom) * dy, -(far + near) * dz, -1, - 0, 0, -(far * near * 2) * dz, 0, - i - ); -}; - -export const frustumBounds = (fovy: number, aspect: number, near: number, far: number) => { - const top = near * Math.tan(fovy * DEG2RAD / 2); - const right = top * aspect; - return { - left: -right, - right, - bottom: -top, - top, - near, - far - }; -}; - -export const perspective = (m: Mat, fov: number, aspect: number, near: number, far: number, i = 0) => { - const f = frustumBounds(fov, aspect, near, far); - return frustum(m || [], f.left, f.right, f.bottom, f.top, f.near, f.far, i); -}; - -export const ortho = (m: Mat, left: number, right: number, bottom: number, top: number, near: number, far: number, i = 0) => { - const dx = 1 / (right - left); - const dy = 1 / (top - bottom); - const dz = 1 / (far - near); - return setS44(m || [], - 2 * dx, 0, 0, 0, - 0, 2 * dy, 0, 0, - 0, 0, -2 * dz, 0, - -(left + right) * dx, -(top + bottom) * dy, -(far + near) * dz, 1, - i - ); -}; - -export const lookAt = (m: Mat, eye: ReadonlyVec, target: ReadonlyVec, up: ReadonlyVec, im = 0, ie = 0, it = 0, iu = 0, se = 1, st = 1, su = 1) => { - const z = normalize3(sub3(get3(eye, ie, se), get3(target, it, st))); - const x = normalize3(cross3(get3(up, iu, su), z)); - const y = normalize3(cross3([...z], x)); - return setS44(m || [], - x[0], y[0], z[0], 0, - x[1], y[1], z[1], 0, - x[2], y[2], z[2], 0, - -dot3(eye, x, ie, 0, se), -dot3(eye, y, ie, 0, se), -dot3(eye, z, ie, 0, se), 1, - im - ); -} - -export const mul44 = (a: Mat, b: ReadonlyMat, ia = 0, ib = 0) => - setS44( - a, - dot4(a, b, ia, ib, 4), - dot4(a, b, ia + 1, ib, 4), - dot4(a, b, ia + 2, ib, 4), - dot4(a, b, ia + 3, ib, 4), - dot4(a, b, ia, ib + 4, 4), - dot4(a, b, ia + 1, ib + 4, 4), - dot4(a, b, ia + 2, ib + 4, 4), - dot4(a, b, ia + 3, ib + 4, 4), - dot4(a, b, ia, ib + 8, 4), - dot4(a, b, ia + 1, ib + 8, 4), - dot4(a, b, ia + 2, ib + 8, 4), - dot4(a, b, ia + 3, ib + 8, 4), - dot4(a, b, ia, ib + 12, 4), - dot4(a, b, ia + 1, ib + 12, 4), - dot4(a, b, ia + 2, ib + 12, 4), - dot4(a, b, ia + 3, ib + 12, 4), - ia - ); - -export const concat44 = (a: Mat, ia: number, ...xs: (ReadonlyMat | [ReadonlyMat, number])[]) => - xs.reduce( - (acc: Mat, x) => isArrayLike(x[0]) ? - mul44(acc, x[0], ia, x[1]) : - mul44(acc, x, ia), - a - ); - -export const mulV344 = (v: Vec, m: ReadonlyMat, iv = 0, im = 0, sv = 1) => - setS3( - v, - dot3(m, v, im, iv, 4, sv) + m[12], - dot3(m, v, im + 1, iv, 4, sv) + m[13], - dot3(m, v, im + 2, iv, 4, sv) + m[14], - iv, sv - ); - -export const mulV44 = (v: Vec, m: ReadonlyMat, iv = 0, im = 0, sv = 1) => - setS4( - v, - dot4(m, v, im, iv, 4, sv), - dot4(m, v, im + 1, iv, 4, sv), - dot4(m, v, im + 2, iv, 4, sv), - dot4(m, v, im + 3, iv, 4, sv), - iv, sv - ); - -const detCoeffs44 = (m: ReadonlyMat, i = 0) => { - const m00 = m[i]; - const m01 = m[i + 1]; - const m02 = m[i + 2]; - const m03 = m[i + 3]; - const m10 = m[i + 4]; - const m11 = m[i + 5]; - const m12 = m[i + 6]; - const m13 = m[i + 7]; - const m20 = m[i + 8]; - const m21 = m[i + 9]; - const m22 = m[i + 10]; - const m23 = m[i + 11]; - const m30 = m[i + 12]; - const m31 = m[i + 13]; - const m32 = m[i + 14]; - const m33 = m[i + 15]; - return [ - m00 * m11 - m01 * m10, - m00 * m12 - m02 * m10, - m00 * m13 - m03 * m10, - m01 * m12 - m02 * m11, - m01 * m13 - m03 * m11, - m02 * m13 - m03 * m12, - m20 * m31 - m21 * m30, - m20 * m32 - m22 * m30, - m20 * m33 - m23 * m30, - m21 * m32 - m22 * m31, - m21 * m33 - m23 * m31, - m22 * m33 - m23 * m32, - ]; -}; - -export const det44 = (m: ReadonlyMat, i = 0) => { - const d = detCoeffs44(m, i); - return d[0] * d[11] - d[1] * d[10] + d[2] * d[9] + - d[3] * d[8] - d[4] * d[7] + d[5] * d[6]; -}; - -export const invert44 = (m: Mat, i = 0) => { - const m00 = m[i]; - const m01 = m[i + 1]; - const m02 = m[i + 2]; - const m03 = m[i + 3]; - const m10 = m[i + 4]; - const m11 = m[i + 5]; - const m12 = m[i + 6]; - const m13 = m[i + 7]; - const m20 = m[i + 8]; - const m21 = m[i + 9]; - const m22 = m[i + 10]; - const m23 = m[i + 11]; - const m30 = m[i + 12]; - const m31 = m[i + 13]; - const m32 = m[i + 14]; - const m33 = m[i + 15]; - const d = detCoeffs44(m, i); - const d00 = d[0]; - const d01 = d[1]; - const d02 = d[2]; - const d03 = d[3]; - const d04 = d[4]; - const d05 = d[5]; - const d06 = d[6]; - const d07 = d[7]; - const d08 = d[8]; - const d09 = d[9]; - const d10 = d[10]; - const d11 = d[11]; - let det = (d00 * d11 - d01 * d10 + d02 * d09 + d03 * d08 - d04 * d07 + d05 * d06); - if (!det) { - return; - } - det = 1.0 / det; - return setS44( - m, - (m11 * d11 - m12 * d10 + m13 * d09) * det, - (-m01 * d11 + m02 * d10 - m03 * d09) * det, - (m31 * d05 - m32 * d04 + m33 * d03) * det, - (-m21 * d05 + m22 * d04 - m23 * d03) * det, - (-m10 * d11 + m12 * d08 - m13 * d07) * det, - (m00 * d11 - m02 * d08 + m03 * d07) * det, - (-m30 * d05 + m32 * d02 - m33 * d01) * det, - (m20 * d05 - m22 * d02 + m23 * d01) * det, - (m10 * d10 - m11 * d08 + m13 * d06) * det, - (-m00 * d10 + m01 * d08 - m03 * d06) * det, - (m30 * d04 - m31 * d02 + m33 * d00) * det, - (-m20 * d04 + m21 * d02 - m23 * d00) * det, - (-m10 * d09 + m11 * d07 - m12 * d06) * det, - (m00 * d09 - m01 * d07 + m02 * d06) * det, - (-m30 * d03 + m31 * d01 - m32 * d00) * det, - (m20 * d03 - m21 * d01 + m22 * d00) * det, - i - ); -} - -export const transpose44 = (m: Mat, i = 0) => - setS44( - m, - m[i], m[i + 4], m[i + 8], m[i + 12], - m[i + 1], m[i + 5], m[i + 9], m[i + 13], - m[i + 2], m[i + 6], m[i + 10], m[i + 14], - m[i + 3], m[i + 7], m[i + 11], m[i + 15], - i - ); - -export const normal44 = (a: Mat, b: ReadonlyMat, ia = 0, ib = 0) => { - const m00 = b[ib]; - const m01 = b[ib + 1]; - const m02 = b[ib + 2]; - const m10 = b[ib + 4]; - const m11 = b[ib + 5]; - const m12 = b[ib + 6]; - const m20 = b[ib + 8]; - const m21 = b[ib + 9]; - const m22 = b[ib + 10]; - const d01 = m22 * m11 - m12 * m21; - const d11 = -m22 * m10 + m12 * m20; - const d21 = m21 * m10 - m11 * m20; - let det = m00 * d01 + m01 * d11 + m02 * d21; - if (!det) { - return; - } - det = 1.0 / det; - a[ia] = d01 * det; - a[ia + 1] = d11 * det; - a[ia + 2] = d21 * det; - a[ia + 3] = (-m22 * m01 + m02 * m21) * det; - a[ia + 4] = (m22 * m00 - m02 * m20) * det; - a[ia + 5] = (-m21 * m00 + m01 * m20) * det; - a[ia + 6] = (m12 * m01 - m02 * m11) * det; - a[ia + 7] = (-m12 * m00 + m02 * m10) * det; - a[ia + 8] = (m11 * m00 - m01 * m10) * det; - return a; -}; - -export const mat44to33 = (m33: Mat, m44: ReadonlyMat, ia = 0, ib = 0) => ( - set3(m33, m44, ia, ib), - set3(m33, m44, ia + 3, ib + 4), - set3(m33, m44, ia + 6, ib + 8), - m33 -); - -export class Mat44 implements - ICopy, - IEqualsDelta { - - static identity() { - return new Mat44(identity44()); - } - - static rotationX(theta: number) { - return new Mat44(rotationX44([], theta)); - } - - static rotationY(theta: number) { - return new Mat44(rotationY44([], theta)); - } - - static rotationZ(theta: number) { - return new Mat44(rotationZ44([], theta)); - } - - static scale(v: Readonly): Mat44; - static scale(n: number): Mat44; - static scale(x: number, y: number, z: number): Mat44; - static scale(x: any, y = x, z = x) { - return new Mat44( - x instanceof Vec3 ? - scaleV44([], x.buf, 0, x.i) : - scaleS44([], x, y, z) - ); - } - - static scaleWithCenter(p: Readonly, sx: number, sy = sx, sz = sy) { - return new Mat44(scaleWithCenter44([], p.buf, sx, sy, sz, p.i, p.s)); - } - - static translation(v: Readonly): Mat44; - static translation(x: number, y: number, z: number): Mat44; - static translation(x: any, y?: any, z?: any) { - return new Mat44( - x instanceof Vec3 ? - translationV44([], x.buf, 0, x.i) : - translationS44([], x, y, z) - ); - } - - static perspective(fov: number, aspect: number, near: number, far: number) { - return new Mat44(perspective([], fov, aspect, near, far)); - } - - static ortho(left: number, right: number, bottom: number, top: number, near: number, far: number) { - return new Mat44(ortho([], left, right, bottom, top, near, far)); - } - - static frustum(left: number, right: number, bottom: number, top: number, near: number, far: number) { - return new Mat44(frustum([], left, right, bottom, top, near, far)); - } - - static lookAt(eye: Readonly, target: Readonly, up: Readonly) { - return new Mat44(lookAt( - [], - eye.buf, target.buf, up.buf, - 0, eye.i, target.i, up.i, - eye.s, target.s, up.s - )); - } - - static concat(m: Readonly, ...xs: Readonly[]) { - return new Mat44(concat44.apply(null, [ - get44(m.buf, m.i), 0, - ...<[ReadonlyMat, number][]>xs.map((x) => [x.buf, x.i])]) - ); - } - - buf: Mat; - i: number; - m00: number; - m01: number; - m02: number; - m03: number; - m10: number; - m11: number; - m12: number; - m13: number; - m20: number; - m21: number; - m22: number; - m23: number; - m30: number; - m31: number; - m32: number; - m33: number; - [id: number]: number; - - constructor(buf?: Mat, i = 0) { - this.buf = buf || (new Array(16).fill(0)); - this.i = i; - } - - [Symbol.iterator]() { - return $iter(this.buf, 16, this.i); - } - - get length() { - return 16; - } - - copy() { - return new Mat44(get44(this.buf, this.i)); - } - - eqDelta(m: Mat44, eps = EPS) { - return eqDelta(this.buf, m.buf, 16, eps, this.i, m.i); - } - - identity() { - identity44(this.buf, this.i); - return this; - } - - set(m: Readonly) { - set44(this.buf, m.buf, this.i, m.i); - return this; - } - - setS(m00: number, m01: number, m02: number, m03: number, - m10: number, m11: number, m12: number, m13: number, - m20: number, m21: number, m22: number, m23: number, - m30: number, m31: number, m32: number, m33: number) { - setS44( - this.buf, - m00, m01, m02, m03, - m10, m11, m12, m13, - m20, m21, m22, m23, - m30, m31, m32, m33, - this.i - ); - return this; - } - - mul(m: Readonly) { - mul44(this.buf, m.buf, this.i, m.i); - return this; - } - - mulV3(v: Vec3) { - mulV344(v.buf, this.buf, v.i, this.i, v.s); - return v; - } - - mulV(v: Vec4) { - mulV44(v.buf, this.buf, v.i, this.i, v.s); - return v; - } - - determinant() { - return det44(this.buf, this.i); - } - - invert() { - invert44(this.buf, this.i); - return this; - } - - transpose() { - transpose44(this.buf, this.i); - return this; - } - - normalMat(m?: Mat33) { - !m && (m = new Mat33([])); - normal44(m.buf, this.buf, m.i, this.i); - return m; - } - - toMat33(m?: Mat33) { - !m && (m = new Mat33([])); - mat44to33(m.buf, this.buf, m.i, this.i); - return m; - } - - toString() { - const b = (get44(this.buf, this.i)).map((x) => x.toFixed(4)); - return `${b[0]} ${b[4]} ${b[8]} ${b[12]} -${b[1]} ${b[5]} ${b[9]} ${b[13]} -${b[2]} ${b[6]} ${b[10]} ${b[14]} -${b[3]} ${b[7]} ${b[11]} ${b[15]}`; - } - - toJSON() { - return get44(this.buf, this.i); - } -} - -declareIndices( - Mat44.prototype, - [ - "m00", "m01", "m02", "m03", - "m10", "m11", "m12", "m13", - "m20", "m21", "m22", "m23", - "m30", "m31", "m32", "m33" - ] -); diff --git a/packages/vectors/src/max.ts b/packages/vectors/src/max.ts new file mode 100644 index 0000000000..020df3486b --- /dev/null +++ b/packages/vectors/src/max.ts @@ -0,0 +1,5 @@ +import { MultiVecOpVV, VecOpVV } from "./api"; +import { defOp } from "./internal/codegen"; + +export const [max, max2, max3, max4] = + defOp(([o, a, b]) => `${o}=Math.max(${a},${b});`); diff --git a/packages/vectors/src/min.ts b/packages/vectors/src/min.ts new file mode 100644 index 0000000000..b118587dcf --- /dev/null +++ b/packages/vectors/src/min.ts @@ -0,0 +1,5 @@ +import { MultiVecOpVV, VecOpVV } from "./api"; +import { defOp } from "./internal/codegen"; + +export const [min, min2, min3, min4] = + defOp(([o, a, b]) => `${o}=Math.min(${a},${b});`); diff --git a/packages/vectors/src/minor.ts b/packages/vectors/src/minor.ts new file mode 100644 index 0000000000..381843c710 --- /dev/null +++ b/packages/vectors/src/minor.ts @@ -0,0 +1,29 @@ +import { min2id, min3id, min4id } from "@thi.ng/math"; +import { MultiVecOpRoV } from "./api"; +import { vop } from "./internal/vop"; + +const abs = Math.abs; + +/** + * Returns index of minor component/axis in `v`, i.e. where `|v[i]|` is + * the smallest. + * + * @param v + */ +export const minor: MultiVecOpRoV = vop(); + +minor.default((a) => { + let id, min = Infinity; + for (let i = a.length; --i >= 0;) { + const x = abs(a[i]); + if (x < min) { + min = x; + id = i; + } + } + return id; +}); + +export const minor2 = minor.add(2, (a) => min2id(abs(a[0]), abs(a[1]))); +export const minor3 = minor.add(3, (a) => min3id(abs(a[0]), abs(a[1]), abs(a[2]))); +export const minor4 = minor.add(4, (a) => min4id(abs(a[0]), abs(a[1]), abs(a[2]), abs(a[3]))); diff --git a/packages/vectors/src/mix-bilinear.ts b/packages/vectors/src/mix-bilinear.ts new file mode 100644 index 0000000000..72b8eb9707 --- /dev/null +++ b/packages/vectors/src/mix-bilinear.ts @@ -0,0 +1,10 @@ +import { mixBilinear as _mix } from "@thi.ng/math"; +import { MultiVecOpVVVVNN, VecOpVVVVNN } from "./api"; +import { defHofOp } from "./internal/codegen"; + +export const [mixBilinear, mixBilinear2, mixBilinear3, mixBilinear4] = + defHofOp( + _mix, + ([o, a, b, c, d]) => `${o}=op(${a},${b},${c},${d},u,v);`, + "o,a,b,c,d,u,v" + ); diff --git a/packages/vectors/src/mix-cubic.ts b/packages/vectors/src/mix-cubic.ts new file mode 100644 index 0000000000..51aa4053fc --- /dev/null +++ b/packages/vectors/src/mix-cubic.ts @@ -0,0 +1,10 @@ +import { ReadonlyVec, Vec } from "./api"; +import { addW4 } from "./addw"; + +export const mixCubic = + (out: Vec, a: ReadonlyVec, b: ReadonlyVec, c: ReadonlyVec, d: ReadonlyVec, t: number) => { + const s = 1 - t; + const s2 = s * s; + const t2 = t * t; + return addW4(out, a, b, c, d, s2 * s, 3 * s2 * t, 3 * t2 * s, t2 * t); + }; diff --git a/packages/vectors/src/mix-quadratic.ts b/packages/vectors/src/mix-quadratic.ts new file mode 100644 index 0000000000..fbbdb2646f --- /dev/null +++ b/packages/vectors/src/mix-quadratic.ts @@ -0,0 +1,8 @@ +import { addW3 } from "./addw"; +import { ReadonlyVec, Vec } from "./api"; + +export const mixQuadratic = + (out: Vec, a: ReadonlyVec, b: ReadonlyVec, c: ReadonlyVec, t: number) => { + const s = 1 - t; + return addW3(out, a, b, c, s * s, 2 * s * t, t * t); + }; diff --git a/packages/vectors/src/mix.ts b/packages/vectors/src/mix.ts new file mode 100644 index 0000000000..fcbee18af0 --- /dev/null +++ b/packages/vectors/src/mix.ts @@ -0,0 +1,6 @@ +import { MultiVecOpVVV, VecOpVVV } from "./api"; +import { ARGS_VVV, defOp } from "./internal/codegen"; +import { MIX } from "./internal/templates"; + +export const [mix, mix2, mix3, mix4] = + defOp(MIX, ARGS_VVV); diff --git a/packages/vectors/src/mixn.ts b/packages/vectors/src/mixn.ts new file mode 100644 index 0000000000..79b355f13d --- /dev/null +++ b/packages/vectors/src/mixn.ts @@ -0,0 +1,6 @@ +import { MultiVecOpVVN, VecOpVVN } from "./api"; +import { ARGS_VVN, defOp } from "./internal/codegen"; +import { MIX_N } from "./internal/templates"; + +export const [mixN, mixN2, mixN3, mixN4] = + defOp(MIX_N, ARGS_VVN); diff --git a/packages/vectors/src/mod.ts b/packages/vectors/src/mod.ts new file mode 100644 index 0000000000..c5bb5091cc --- /dev/null +++ b/packages/vectors/src/mod.ts @@ -0,0 +1,5 @@ +import { MultiVecOpVV, VecOpVV } from "./api"; +import { defOp } from "./internal/codegen"; + +export const [mod, mod2, mod3, mod4] = + defOp(([o, a, b]) => `${o}=${a}%${b};`); diff --git a/packages/vectors/src/modn.ts b/packages/vectors/src/modn.ts new file mode 100644 index 0000000000..4f570a719e --- /dev/null +++ b/packages/vectors/src/modn.ts @@ -0,0 +1,5 @@ +import { MultiVecOpVN, VecOpVN } from "./api"; +import { ARGS_VN, defOp } from "./internal/codegen"; + +export const [modN, modN2, modN3, modN4] = + defOp(([o, a]) => `${o}=${a}%n;`, ARGS_VN); diff --git a/packages/vectors/src/mul.ts b/packages/vectors/src/mul.ts new file mode 100644 index 0000000000..6dc31c562e --- /dev/null +++ b/packages/vectors/src/mul.ts @@ -0,0 +1,3 @@ +import { defMathOp } from "./internal/codegen"; + +export const [mul, mul2, mul3, mul4] = defMathOp("*"); diff --git a/packages/vectors/src/muln.ts b/packages/vectors/src/muln.ts new file mode 100644 index 0000000000..f7019a269a --- /dev/null +++ b/packages/vectors/src/muln.ts @@ -0,0 +1,3 @@ +import { defMathNOp } from "./internal/codegen"; + +export const [mulN, mulN2, mulN3, mulN4] = defMathNOp("*"); diff --git a/packages/vectors/src/muls.ts b/packages/vectors/src/muls.ts new file mode 100644 index 0000000000..f07d896cd6 --- /dev/null +++ b/packages/vectors/src/muls.ts @@ -0,0 +1,6 @@ +import { VecOpSVV } from "./api"; +import { defOpS } from "./internal/codegen"; +import { MATH } from "./internal/templates"; + +export const [mulS2, mulS3, mulS4] = + defOpS(MATH("*")); diff --git a/packages/vectors/src/neg.ts b/packages/vectors/src/neg.ts new file mode 100644 index 0000000000..6611bd7edf --- /dev/null +++ b/packages/vectors/src/neg.ts @@ -0,0 +1,5 @@ +import { ReadonlyVec, Vec, VecOpV } from "./api"; +import { mulN } from "./muln"; + +export const neg: VecOpV = + (out: Vec, v: ReadonlyVec) => mulN(out, v, -1); diff --git a/packages/vectors/src/normalize.ts b/packages/vectors/src/normalize.ts new file mode 100644 index 0000000000..b29fc9ade7 --- /dev/null +++ b/packages/vectors/src/normalize.ts @@ -0,0 +1,24 @@ +import { EPS } from "@thi.ng/math"; +import { VecOpVO } from "./api"; +import { mag } from "./mag"; +import { mulN } from "./muln"; +import { set } from "./set"; + +/** + * Normalizes vector to given (optional) length (default: 1). If `out` + * is null, modifies `v` in place. + * + * @param out + * @param v + * @param n + */ +export const normalize: VecOpVO = + (out, v, n = 1) => { + !out && (out = v); + const m = mag(v); + return m >= EPS ? + mulN(out, v, n / m) : + out !== v ? + set(out, v) : + out; + }; diff --git a/packages/vectors/src/ortho-normal.ts b/packages/vectors/src/ortho-normal.ts new file mode 100644 index 0000000000..45403346db --- /dev/null +++ b/packages/vectors/src/ortho-normal.ts @@ -0,0 +1,26 @@ +import { cross3 } from "./cross"; +import { sub3 } from "./sub"; +import { normalize } from "./normalize"; +import { Vec, ReadonlyVec } from "./api"; + +/** + * Produces a vector which is perpendicular/normal to the plane spanned + * by given 3 input vectors. If `normalize` is true (default), the + * result vector will be normalized. + * + * ``` + * orthoNormal3([], [0,0,0], [1,0,0], [0,1,0]) + * // [0,0,1] + * ``` + * + * @param out + * @param a + * @param b + * @param c + * @param normalize + */ +export const orthoNormal3 = + (out: Vec, a: ReadonlyVec, b: ReadonlyVec, c: ReadonlyVec, doNormalize = true) => { + out = cross3(null, sub3(out || a, b, a), sub3([], c, a)); + return doNormalize ? normalize(out, out) : out; + }; diff --git a/packages/vectors/src/perpendicular.ts b/packages/vectors/src/perpendicular.ts new file mode 100644 index 0000000000..b478e4ac56 --- /dev/null +++ b/packages/vectors/src/perpendicular.ts @@ -0,0 +1,20 @@ +import { VecOpV } from "./api"; +import { setC2 } from "./setc"; + +/** + * Produces a perpendicular vector to `v`, i.e. `[-y,x]`. + * + * @param out + * @param v + */ +export const perpendicularLeft2: VecOpV = + (out, a) => setC2(out || a, -a[1], a[0]); + +/** + * Produces a perpendicular vector to `v`, i.e. `[y,-x]`. + * + * @param out + * @param v + */ +export const perpendicularRight2: VecOpV = + (out, a) => setC2(out || a, a[1], -a[0]); diff --git a/packages/vectors/src/polar.ts b/packages/vectors/src/polar.ts new file mode 100644 index 0000000000..7fafdba5ce --- /dev/null +++ b/packages/vectors/src/polar.ts @@ -0,0 +1,45 @@ +import { MultiVecOpV } from "./api"; +import { vop } from "./internal/vop"; +import { mag } from "./mag"; +import { setC2, setC3 } from "./setc"; + +const sqrt = Math.sqrt; +const asin = Math.asin; +const atan2 = Math.atan2; + +/** + * Converts cartesian vector `v` to polar coordinates. See `cartesian()` + * for reverse operation. If `out` is null, modifies `v` in place. + * + * @param out + * @param v + */ +export const polar: MultiVecOpV = vop(1); + +/** + * Converts 2D cartesian vector `v` to polar coordinates, i.e. `[r,θ]` + * (angle in radians). See `cartesian()` for reverse operation. If `out` + * is null, modifies `v` in place. + * + * @param out + * @param v + */ +export const polar2 = polar.add(2, (out, a) => + setC2(out || a, mag(a), atan2(a[1], a[0])) +); + +/** + * Converts 3D cartesian vector `v` to spherical coordinates, i.e. + * `[r,θ,Ï•]` (angles in radians). See `cartesian()` for reverse + * operation. If `out` is null, modifies `v` in place. + * + * @param out + * @param v + */ +export const polar3 = polar.add(3, (out, a) => { + const x = a[0]; + const y = a[1]; + const z = a[2]; + const r = sqrt(x * x + y * y + z * z); + return setC3(out || a, r, asin(z / r), atan2(y, x)); +}); diff --git a/packages/vectors/src/pow.ts b/packages/vectors/src/pow.ts new file mode 100644 index 0000000000..40cbdb9ad0 --- /dev/null +++ b/packages/vectors/src/pow.ts @@ -0,0 +1,6 @@ +import { MultiVecOpVV, VecOpVV } from "./api"; +import { defOp } from "./internal/codegen"; +import { FN2 } from "./internal/templates"; + +export const [pow, pow2, pow3, pow4] = + defOp(FN2("Math.pow")); diff --git a/packages/vectors/src/pown.ts b/packages/vectors/src/pown.ts new file mode 100644 index 0000000000..8097f72810 --- /dev/null +++ b/packages/vectors/src/pown.ts @@ -0,0 +1,6 @@ +import { MultiVecOpVN, VecOpVN } from "./api"; +import { ARGS_VN, defOp } from "./internal/codegen"; +import { FN_N } from "./internal/templates"; + +export const [powN, powN2, powN3, powN4] = + defOp(FN_N("Math.pow"), ARGS_VN); diff --git a/packages/vectors/src/project.ts b/packages/vectors/src/project.ts new file mode 100644 index 0000000000..358c08b218 --- /dev/null +++ b/packages/vectors/src/project.ts @@ -0,0 +1,16 @@ +import { ReadonlyVec, Vec } from "./api"; +import { dot } from "./dot"; +import { magSq } from "./magsq"; +import { mulN } from "./muln"; + +/** + * Returns vector projection of `v` onto `dir`. + * + * https://en.wikipedia.org/wiki/Vector_projection + * + * @param v + * @param dir + */ +export const project = + (out: Vec, v: ReadonlyVec, dir: ReadonlyVec) => + mulN(out || v, dir, dot(v, dir) / magSq(dir)); diff --git a/packages/vectors/src/random.ts b/packages/vectors/src/random.ts new file mode 100644 index 0000000000..dac711b784 --- /dev/null +++ b/packages/vectors/src/random.ts @@ -0,0 +1,60 @@ +import { IRandom, SYSTEM } from "@thi.ng/random"; +import { + MultiVecOpOOO, + ReadonlyVec, + Vec, + VecOpOOO +} from "./api"; +import { defHofOp } from "./internal/codegen"; +import { normalize } from "./normalize"; + +/** + * Sets `v` to random vector, with each component in interval `[n..m)`. + * If no `rnd` instance is given, uses `SYSTEM`, i.e. `Math.random`. + * + * @param v + * @param n default -1 + * @param m default 1 + * @param rnd + */ +export const [random, random2, random3, random4] = + defHofOp, VecOpOOO>( + SYSTEM, + ([a]) => `${a}=rnd.minmax(n,m);`, + "a,n=-1,m=1,rnd=op", + "a", + "a", + 0, + "" + ); + +/** + * Sets `v` to random vector, normalized to length `n` (default: 1). If no + * `rnd` instance is given, uses `SYSTEM`, i.e. `Math.random`. + * + * @param v + * @param n + * @param rnd + */ +export const randNorm = + (v: Vec, n = 1, rnd: IRandom = SYSTEM) => { + v = random(v, -1, 1, rnd); + return normalize(v, v, n); + }; + +/** + * Sets `out` to random vector with each component in the semi-open + * interval defined by [min,max). + * + * @param out + * @param min + * @param max + * @param rnd + */ +export const [randMinMax, randMinMax2, randMinMax3, randMinMax4] = + defHofOp, VecOpOOO>( + SYSTEM, + ([o, a, b]) => `${o}=rnd.minmax(${a},${b});`, + "o,a,b,rnd=op", + "o,a,b" + ); \ No newline at end of file diff --git a/packages/vectors/src/reflect.ts b/packages/vectors/src/reflect.ts new file mode 100644 index 0000000000..4a26cff6bc --- /dev/null +++ b/packages/vectors/src/reflect.ts @@ -0,0 +1,6 @@ +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)); diff --git a/packages/vectors/src/refract.ts b/packages/vectors/src/refract.ts new file mode 100644 index 0000000000..7d439a5850 --- /dev/null +++ b/packages/vectors/src/refract.ts @@ -0,0 +1,15 @@ +import { VecOpVVN } from "./api"; +import { dot } from "./dot"; +import { maddN } from "./maddn"; +import { mulN } from "./muln"; +import { zero } from "./setn"; + +export const refract: VecOpVVN = + (out, a, n, eta) => { + !out && (out = a); + const d = dot(a, n); + 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))); + }; diff --git a/packages/vectors/src/rotate-around-axis.ts b/packages/vectors/src/rotate-around-axis.ts new file mode 100644 index 0000000000..e77f28178f --- /dev/null +++ b/packages/vectors/src/rotate-around-axis.ts @@ -0,0 +1,30 @@ +import { ReadonlyVec, Vec } from "./api"; +import { setC3 } from "./setc"; + +export const rotateAroundAxis3 = + (out: Vec, v: ReadonlyVec, axis: ReadonlyVec, theta: number) => { + const x = v[0]; + const y = v[1]; + const z = v[2]; + const ax = axis[0]; + const ay = axis[1]; + const az = axis[2]; + const ux = ax * x; + const uy = ax * y; + const uz = ax * z; + const vx = ay * x; + const vy = ay * y; + const vz = ay * z; + const wx = az * x; + const wy = az * y; + const wz = az * z; + const uvw = ux + vy + wz; + const s = Math.sin(theta); + const c = Math.cos(theta); + return setC3( + out || v, + ax * uvw + (x * (ay * ay + az * az) - ax * (vy + wz)) * c + (-wy + vz) * s, + ay * uvw + (y * (ax * ax + az * az) - ay * (ux + wz)) * c + (wx - uz) * s, + az * uvw + (z * (ax * ax + ay * ay) - az * (ux + vy)) * c + (-vx + uy) * s + ); + }; diff --git a/packages/vectors/src/rotate-around-point.ts b/packages/vectors/src/rotate-around-point.ts new file mode 100644 index 0000000000..e1bcd294e9 --- /dev/null +++ b/packages/vectors/src/rotate-around-point.ts @@ -0,0 +1,15 @@ +import { VecOpVVN } from "./api"; +import { setC2 } from "./setc"; + +export const rotateAroundPoint2: VecOpVVN = + (out, v, p, theta) => { + const x = v[0] - p[0]; + const y = v[1] - p[1]; + const s = Math.sin(theta); + const c = Math.cos(theta); + return setC2( + out || v, + x * c - y * s + p[0], + x * s + y * c + p[1] + ); + }; diff --git a/packages/vectors/src/rotate.ts b/packages/vectors/src/rotate.ts new file mode 100644 index 0000000000..df891e68fb --- /dev/null +++ b/packages/vectors/src/rotate.ts @@ -0,0 +1,21 @@ +import { VecOpVN } from "./api"; +import { set } from "./set"; + +const _rotate = + (u: number, v: number): VecOpVN => + (out, a, theta) => { + out ? + (out !== a && set(out, a)) : + (out = a); + const s = Math.sin(theta); + const c = Math.cos(theta); + const x = a[u]; + const y = a[v]; + out[u] = x * c - y * s; + out[v] = x * s + y * c; + return out; + }; + +export const rotateX = _rotate(1, 2); +export const rotateY = _rotate(2, 0); +export const rotateZ = _rotate(0, 1); diff --git a/packages/vectors/src/round.ts b/packages/vectors/src/round.ts new file mode 100644 index 0000000000..6fe0e04a29 --- /dev/null +++ b/packages/vectors/src/round.ts @@ -0,0 +1,12 @@ +import { roundTo as _round } from "@thi.ng/math"; +import { MultiVecOpVO, VecOpVO } from "./api"; +import { defHofOp } from "./internal/codegen"; +import { FN_N } from "./internal/templates"; + +export const [round, round2, round3, round4] = + defHofOp, VecOpVO>( + _round, + FN_N("op"), + "o,a,n=1", + "o,a" + ); diff --git a/packages/vectors/src/set.ts b/packages/vectors/src/set.ts new file mode 100644 index 0000000000..c7ad526776 --- /dev/null +++ b/packages/vectors/src/set.ts @@ -0,0 +1,6 @@ +import { MultiVecOpV, VecOpV } from "./api"; +import { defOp, NEW_OUT } from "./internal/codegen"; +import { SET } from "./internal/templates"; + +export const [set, set2, set3, set4] = + defOp(SET, "o,a", undefined, "o", 1, NEW_OUT); diff --git a/packages/vectors/src/setc.ts b/packages/vectors/src/setc.ts new file mode 100644 index 0000000000..99e87d9c68 --- /dev/null +++ b/packages/vectors/src/setc.ts @@ -0,0 +1,49 @@ +import { Vec } from "./api"; + +export const setC2 = + (out: Vec, x: number, y: number) => ( + !out && (out = []), + out[0] = x, + out[1] = y, + out + ); + +export const setC3 = + (out: Vec, 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) => ( + !out && (out = []), + out[0] = x, + out[1] = y, + out[2] = z, + out[3] = w, + out + ); + +export const setC6 = + (out: Vec, a: number, b: number, c: number, d: number, e: number, f: number) => ( + !out && (out = []), + out[0] = a, + out[1] = b, + out[2] = c, + out[3] = d, + out[4] = e, + out[5] = f, + out + ); + +export const setC = + (out: Vec, ...xs: number[]) => { + !out && (out = []); + for (let i = 0, n = xs.length; i < n; i++) { + out[i] = xs[i]; + } + return out; + }; diff --git a/packages/vectors/src/setn.ts b/packages/vectors/src/setn.ts new file mode 100644 index 0000000000..8b7a09de78 --- /dev/null +++ b/packages/vectors/src/setn.ts @@ -0,0 +1,12 @@ +import { MultiVecOpN, Vec, VecOpN } from "./api"; +import { defOp } from "./internal/codegen"; +import { SET_N } from "./internal/templates"; + +export const [setN, setN2, setN3, setN4] = + defOp(SET_N, "a,n", "a", "a", 0, ""); + +export const zero = (a: Vec) => setN(a, 0); +export const one = (a: Vec) => setN(a, 1); + +export const zeroes = (n: number) => new Array(n).fill(0); +export const ones = (n: number) => new Array(n).fill(1); diff --git a/packages/vectors/src/sets.ts b/packages/vectors/src/sets.ts new file mode 100644 index 0000000000..dbb663a09b --- /dev/null +++ b/packages/vectors/src/sets.ts @@ -0,0 +1,14 @@ +import { ReadonlyVec, Vec, VecOpSV } from "./api"; +import { defOpS, NEW_OUT, SARGS_V } from "./internal/codegen"; +import { SET } from "./internal/templates"; + +export const [setS2, setS3, setS4] = + defOpS(SET, `o,a,${SARGS_V}`, "o,a", "o", NEW_OUT); + +export const setS = + (out: Vec, a: ReadonlyVec, n: number, io = 0, ia = 0, so = 1, sa = 1) => { + for (let i = 0; i < n; i++) { + out[io + i * so] = a[ia + i * sa]; + } + return out; + }; diff --git a/packages/vectors/src/setsn.ts b/packages/vectors/src/setsn.ts new file mode 100644 index 0000000000..30501cd5b3 --- /dev/null +++ b/packages/vectors/src/setsn.ts @@ -0,0 +1,6 @@ +import { VecOpSV } from "./api"; +import { defOpS } from "./internal/codegen"; +import { SET_N } from "./internal/templates"; + +export const [setSN2, setSN3, setSN4] = + defOpS(SET_N, "o,n,io=0,so=1", "o", "o", ""); diff --git a/packages/vectors/src/sign.ts b/packages/vectors/src/sign.ts new file mode 100644 index 0000000000..7f05994fc8 --- /dev/null +++ b/packages/vectors/src/sign.ts @@ -0,0 +1,5 @@ +import { MultiVecOpV, VecOpV } from "./api"; +import { defFnOp } from "./internal/codegen"; + +export const [sign, sign2, sign3, sign4] = + defFnOp("Math.sign"); diff --git a/packages/vectors/src/signed-area.ts b/packages/vectors/src/signed-area.ts new file mode 100644 index 0000000000..4ea96d7d94 --- /dev/null +++ b/packages/vectors/src/signed-area.ts @@ -0,0 +1,22 @@ +import { ReadonlyVec } from "./api"; + +/** + * Returns area*2 of the 2D triangle defined by the input vectors. This + * is a useful classifier for many geometry processing tasks. In + * addition to the triangle area, the result can also be interpreted as + * follows: + * + * - > 0: points are ordered anti-clockwise + * - < 0: points are ordered clockwise + * - 0: points are co-linear + * + * @param a + * @param b + * @param c + */ +export const signedArea2 = + (a: ReadonlyVec, b: ReadonlyVec, c: ReadonlyVec) => { + const ax = a[0]; + const ay = a[1]; + return (b[0] - ax) * (c[1] - ay) - (c[0] - ax) * (b[1] - ay); + }; diff --git a/packages/vectors/src/sin.ts b/packages/vectors/src/sin.ts new file mode 100644 index 0000000000..913976c0b1 --- /dev/null +++ b/packages/vectors/src/sin.ts @@ -0,0 +1,5 @@ +import { MultiVecOpV, VecOpV } from "./api"; +import { defFnOp } from "./internal/codegen"; + +export const [sin, sin2, sin3, sin4] = + defFnOp("Math.sin"); diff --git a/packages/vectors/src/sinh.ts b/packages/vectors/src/sinh.ts new file mode 100644 index 0000000000..3925ba0ece --- /dev/null +++ b/packages/vectors/src/sinh.ts @@ -0,0 +1,5 @@ +import { MultiVecOpV, VecOpV } from "./api"; +import { defFnOp } from "./internal/codegen"; + +export const [sinh, sinh2, sinh3, sinh4] = + defFnOp("Math.sinh"); diff --git a/packages/vectors/src/smoothstep.ts b/packages/vectors/src/smoothstep.ts new file mode 100644 index 0000000000..c42e71970e --- /dev/null +++ b/packages/vectors/src/smoothstep.ts @@ -0,0 +1,23 @@ +import { smoothStep as _step } from "@thi.ng/math"; +import { MultiVecOpV, VecOpV } from "./api"; +import { DEFAULT_OUT, defHofOp } from "./internal/codegen"; +import { HOF_VVV } from "./internal/templates"; + +/** + * Like GLSL `smoothstep()` + * + * @param out + * @param e1 + * @param e2 + * @param v + */ +export const [smoothStep, smoothStep2, smoothStep3, smoothStep4] = + defHofOp( + _step, + HOF_VVV, + "o,e1,e2,a", + undefined, + "o", + 3, + DEFAULT_OUT + ); diff --git a/packages/vectors/src/sqrt.ts b/packages/vectors/src/sqrt.ts new file mode 100644 index 0000000000..84d98828a7 --- /dev/null +++ b/packages/vectors/src/sqrt.ts @@ -0,0 +1,5 @@ +import { MultiVecOpV, VecOpV } from "./api"; +import { defFnOp } from "./internal/codegen"; + +export const [sqrt, sqrt2, sqrt3, sqrt4] = + defFnOp("Math.sqrt"); diff --git a/packages/vectors/src/step.ts b/packages/vectors/src/step.ts new file mode 100644 index 0000000000..84d05d127a --- /dev/null +++ b/packages/vectors/src/step.ts @@ -0,0 +1,22 @@ +import { step as _step } from "@thi.ng/math"; +import { MultiVecOpV, VecOpV } from "./api"; +import { DEFAULT_OUT, defHofOp } from "./internal/codegen"; +import { FN2 } from "./internal/templates"; + +/** + * Like GLSL `step()` + * + * @param out + * @param e + * @param v + */ +export const [step, step2, step3, step4] = + defHofOp( + _step, + FN2("op"), + "o,e,a", + undefined, + "o", + 2, + DEFAULT_OUT + ); diff --git a/packages/vectors/src/sub.ts b/packages/vectors/src/sub.ts new file mode 100644 index 0000000000..4dfbf570ec --- /dev/null +++ b/packages/vectors/src/sub.ts @@ -0,0 +1,3 @@ +import { defMathOp } from "./internal/codegen"; + +export const [sub, sub2, sub3, sub4] = defMathOp("-"); diff --git a/packages/vectors/src/subm.ts b/packages/vectors/src/subm.ts new file mode 100644 index 0000000000..01938e147c --- /dev/null +++ b/packages/vectors/src/subm.ts @@ -0,0 +1,11 @@ +import { MultiVecOpVVV, VecOpVVV } from "./api"; +import { ARGS_VVV, defOp } from "./internal/codegen"; +import { SUBM } from "./internal/templates"; + +/** + * Returns `out = (a + b) * c`. + * + * @see madd + */ +export const [subm, subm2, subm3, subm4] = + defOp(SUBM, ARGS_VVV); diff --git a/packages/vectors/src/submn.ts b/packages/vectors/src/submn.ts new file mode 100644 index 0000000000..3863046a6f --- /dev/null +++ b/packages/vectors/src/submn.ts @@ -0,0 +1,9 @@ +import { MultiVecOpVVN, VecOpVVN } from "./api"; +import { ARGS_VVN, defOp } from "./internal/codegen"; +import { SUBM_N } from "./internal/templates"; + +/** + * Returns `out = (a - b) * n`. + */ +export const [submN, submN2, submN3, submN4] = + defOp(SUBM_N, ARGS_VVN); diff --git a/packages/vectors/src/subn.ts b/packages/vectors/src/subn.ts new file mode 100644 index 0000000000..e8f49e9235 --- /dev/null +++ b/packages/vectors/src/subn.ts @@ -0,0 +1,3 @@ +import { defMathNOp } from "./internal/codegen"; + +export const [subN, subN2, subN3, subN4] = defMathNOp("-"); diff --git a/packages/vectors/src/subs.ts b/packages/vectors/src/subs.ts new file mode 100644 index 0000000000..455bcff401 --- /dev/null +++ b/packages/vectors/src/subs.ts @@ -0,0 +1,6 @@ +import { VecOpSVV } from "./api"; +import { defOpS } from "./internal/codegen"; +import { MATH } from "./internal/templates"; + +export const [subS2, subS3, subS4] = + defOpS(MATH("-")); diff --git a/packages/vectors/src/sum.ts b/packages/vectors/src/sum.ts new file mode 100644 index 0000000000..33ebd10d7f --- /dev/null +++ b/packages/vectors/src/sum.ts @@ -0,0 +1,16 @@ +import { add, reduce } from "@thi.ng/transducers"; +import { MultiVecOpRoV } from "./api"; +import { vop } from "./internal/vop"; + +/** + * Returns component sum of vector `v`. + * + * @param v + */ +export const sum: MultiVecOpRoV = vop(0); + +sum.default((v) => reduce(add(), v)); + +export const sum2 = sum.add(2, (a) => a[0] + a[1]); +export const sum3 = sum.add(3, (a) => a[0] + a[1] + a[2]); +export const sum4 = sum.add(4, (a) => a[0] + a[1] + a[2] + a[3]); diff --git a/packages/vectors/src/swizzle.ts b/packages/vectors/src/swizzle.ts new file mode 100644 index 0000000000..4cd0f49e23 --- /dev/null +++ b/packages/vectors/src/swizzle.ts @@ -0,0 +1,53 @@ +import { ReadonlyVec, Vec, VecOpV } from "./api"; +import { setC2, setC3, setC4 } from "./setc"; + +/** + * Places a re-ordered 2D version of vector `a` into `out`. The given + * coord indices must be valid for `a`. No bounds checking. + * + * @param out + * @param a + * @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); + +/** + * Places a re-ordered 3D version of vector `a` into `out`. The given + * coord indices must be valid for `a`. No bounds checking. + * + * @param out + * @param a + * @param x new x coord index + * @param y new y coord index + * @param z new z coord index + */ +export const swizzle3 = + (out: Vec, a: ReadonlyVec, x: number, y: number, z: number) => + setC3(out || a, a[x] || 0, a[y] || 0, a[z] || 0); + +/** + * Places a re-ordered 4D version of vector `a` into `out`. The given + * coord indices must be valid for `a`. No bounds checking. + * + * @param out + * @param a + * @param x new x coord index + * @param y new y coord index + * @param z new z coord index + * @param w new w coord index + */ +export const swizzle4 = + (out: Vec, a: ReadonlyVec, x: number, y: number, z: number, w: number) => + setC4(out || a, a[x] || 0, a[y] || 0, a[z] || 0, a[w] || 0); + +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); diff --git a/packages/vectors/src/tan.ts b/packages/vectors/src/tan.ts new file mode 100644 index 0000000000..07558363ff --- /dev/null +++ b/packages/vectors/src/tan.ts @@ -0,0 +1,5 @@ +import { MultiVecOpV, VecOpV } from "./api"; +import { defFnOp } from "./internal/codegen"; + +export const [tan, tan2, tan3, tan4] = + defFnOp("Math.tan"); diff --git a/packages/vectors/src/tanh.ts b/packages/vectors/src/tanh.ts new file mode 100644 index 0000000000..18e849fe32 --- /dev/null +++ b/packages/vectors/src/tanh.ts @@ -0,0 +1,5 @@ +import { MultiVecOpV, VecOpV } from "./api"; +import { defFnOp } from "./internal/codegen"; + +export const [tanh, tanh2, tanh3, tanh4] = + defFnOp("Math.tanh"); diff --git a/packages/vectors/src/trunc.ts b/packages/vectors/src/trunc.ts new file mode 100644 index 0000000000..abb8161ed8 --- /dev/null +++ b/packages/vectors/src/trunc.ts @@ -0,0 +1,5 @@ +import { MultiVecOpV, VecOpV } from "./api"; +import { defFnOp } from "./internal/codegen"; + +export const [trunc, trunc2, trunc3, trunc4] = + defFnOp("Math.trunc"); diff --git a/packages/vectors/src/vec2.ts b/packages/vectors/src/vec2.ts index d13aa63d09..c4273a4615 100644 --- a/packages/vectors/src/vec2.ts +++ b/packages/vectors/src/vec2.ts @@ -1,307 +1,28 @@ -import { isArrayLike } from "@thi.ng/checks/is-arraylike"; -import { atan2Abs } from "@thi.ng/math/angle"; -import { EPS, HALF_PI, PI } from "@thi.ng/math/api"; -import { eqDelta } from "@thi.ng/math/eqdelta"; -import { max2id, min2id } from "@thi.ng/math/interval"; -import { mixBilinear } from "@thi.ng/math/mix"; -import { fract } from "@thi.ng/math/prec"; -import { smoothStep, step } from "@thi.ng/math/step"; +import { EPS } from "@thi.ng/math"; import { - IAngleBetween, - ICrossProduct, - IPolar, - IVec, IVector, - MAX4, - MIN4, - ONE4, + MAX2, + MIN2, + ONE2, ReadonlyVec, Vec, - Vec2Coord, - X4, - Y4, - ZERO4 + X2, + Y2, + ZERO2 } from "./api"; -import { declareIndices, defcommon } from "./codegen"; -import { $iter } from "./common"; - -export const op2 = (fn: (x: number) => number, a: Vec, ia = 0, sa = 1) => - (a[ia] = fn(a[ia]), a[ia + sa] = fn(a[ia + sa]), a); - -export const op20 = (fn: () => number, a: Vec, ia = 0, sa = 1) => ( - a[ia] = fn(), - a[ia + sa] = fn(), - a -); - -export const op21 = (fn: (a: number, n: number) => number, a: Vec, n: number, ia = 0, sa = 1) => ( - a[ia] = fn(a[ia], n), - a[ia + sa] = fn(a[ia + sa], n), - a -); - -export const get2 = (a: ReadonlyVec, ia = 0, sa = 1) => - set2(new ((a.constructor))(2), a, 0, ia, 1, sa); - -export const setS2 = (a: Vec, x: number, y: number, ia = 0, sa = 1) => - (a[ia] = x, a[ia + sa] = y, a); - -export const randNorm2 = (a: Vec, n = 1, ia = 0, sa = 1) => - randMinMax2(a, -n, n, ia, sa); - -export const randMinMax2 = (a: Vec, min: number, max: number, ia = 0, sa = 1) => { - const d = max - min; - return op20(() => min + d * Math.random(), a, ia, sa); -}; - -export const jitter2 = (a: Vec, n: number, ia = 0, sa = 1) => - op2((x) => x + Math.random() * 2 * n - n, a, ia, sa); - -export const swizzle2 = (a: Vec, b: ReadonlyVec, x: number, y: number, ia = 0, ib = 0, sa = 1, sb = 1) => - setS2(a, b[ib + x * sb], b[ib + y * sb], ia, sa); - -export const swap2 = (a: Vec, b: Vec, ia = 0, ib = 0, sa = 1, sb = 1) => { - let t = a[ia]; a[ia] = b[ib]; b[ib] = t; - ia += sa; ib += sb; - t = a[ia]; a[ia] = b[ib]; b[ib] = t; - return a; -}; - -export const equiv2 = (a: ReadonlyVec, b: ReadonlyVec, ia = 0, ib = 0, sa = 1, sb = 1) => - a[ia] === b[ib] && - a[ia + sa] === b[ib + sb]; - -export const eqDelta2 = (a: ReadonlyVec, b: ReadonlyVec, eps = EPS, ia = 0, ib = 0, sa = 1, sb = 1) => - eqDelta(a[ia], b[ib], eps) && - eqDelta(a[ia + sa], b[ib + sb], eps); - -export const eqDelta2buf = (a: ReadonlyVec, b: ReadonlyVec, num: number, eps = EPS, ia = 0, ib = 0, sca = 1, scb = 1, sea = 2, seb = 2) => { - while (--num >= 0) { - if (!eqDelta2(a, b, eps, ia + num * sea, ib + num * seb, sca, scb)) { - return false; - } - } - return true; -}; - -export const eqDelta2array = (a: ReadonlyVec[], b: ReadonlyVec[], eps = EPS) => { - const na = a.length; - if (b.length !== na) { - return false; - } - for (let i = 0; i < na; i++) { - if (!eqDelta2(a[i], b[i], eps)) { - return false; - } - } - return true; -}; - -export const compare2 = ( - a: ReadonlyVec, - b: ReadonlyVec, - o1: Vec2Coord, o2: Vec2Coord, - ia = 0, ib = 0, sa = 1, sb = 1): number => { - - const ax = a[ia + o1 * sa]; - const ay = a[ia + o2 * sa]; - const bx = b[ib + o1 * sb]; - const by = b[ib + o2 * sb]; - return ax === bx ? - ay === by ? - 0 : - ay < by ? -2 : 2 : - ax < bx ? -1 : 1; -}; - -export const collate2 = (buf: Vec, src: Iterable, start = 0, cstride = 1, estride = 2) => { - for (let v of src) { - set2(buf, v, start, 0, cstride, 1); - start += estride; - } - return buf; -}; - -export const [ - set2, setN2, - add2, sub2, mul2, div2, - add2o, sub2o, mul2o, div2o, - addN2, subN2, mulN2, divN2, - addN2o, subN2o, mulN2o, divN2o, - madd2, maddN2, msub2, msubN2, - abs2, sign2, floor2, ceil2, sin2, cos2, sqrt2, - pow2, min2, max2, - mix2, mixN2, mix2o, mixN2o -] = defcommon(2); - -export const neg2 = (a: Vec, ia = 0, sa = 1) => - mulN2(a, -1, ia, sa); - -export const fract2 = (a: Vec, ia = 0, sa = 1) => - op2(fract, a, ia, sa); - -export const powN2 = (a: Vec, n: number, ia = 0, sa = 1) => - op21(Math.pow, a, n, ia, sa); - -export const dot2 = (a: ReadonlyVec, b: ReadonlyVec, ia = 0, ib = 0, sa = 1, sb = 1) => - a[ia] * b[ib] + a[ia + sa] * b[ib + sb]; - -export const cross2 = (a: ReadonlyVec, b: ReadonlyVec, ia = 0, ib = 0, sa = 1, sb = 1) => - a[ia] * b[ib + sb] - a[ia + sa] * b[ib]; - -export const mixBilinear2 = ( - a: Vec, b: ReadonlyVec, c: ReadonlyVec, d: ReadonlyVec, u: number, v: number, - ia = 0, ib = 0, ic = 0, id = 0, - sa = 1, sb = 1, sc = 1, sd = 1) => ( - a[ia] = mixBilinear(a[ia], b[ib], c[ic], d[id], u, v), - a[ia + sa] = mixBilinear(a[ia + sa], b[ib + sb], c[ic + sc], d[id + sd], u, v), - a - ); - -export const clamp2 = (a: Vec, min: ReadonlyVec, max: ReadonlyVec, ia = 0, imin = 0, imax = 0, sa = 1, smin = 1, smax = 1) => - max2(min2(a, max, ia, imax, sa, smax), min, ia, imin, sa, smin); - -export const step2 = (a: Vec, e: ReadonlyVec, ia = 0, ie = 0, sa = 1, stridee = 1) => - (a[ia] = step(e[ie], a[ia]), a[ia + sa] = step(e[ie + stridee], a[ia + sa]), a); - -export const smoothStep2 = (a: Vec, e1: ReadonlyVec, e2: ReadonlyVec, ia = 0, ie1 = 0, ie2 = 0, sa = 1, se1 = 1, se2 = 1) => ( - a[ia] = smoothStep(e1[ie1], e2[ie2], a[ia]), - a[ia + sa] = smoothStep(e1[ie1 + se1], e2[ie2 + se2], a[ia + sa]), - a -); - -export const magSq2 = (a: ReadonlyVec, ia = 0, sa = 1) => { - const x = a[ia], y = a[ia + sa]; - return x * x + y * y; -}; - -export const mag2 = (a: ReadonlyVec, ia = 0, sa = 1) => - Math.sqrt(magSq2(a, ia, sa)); - -export const distSq2 = (a: ReadonlyVec, b: ReadonlyVec, ia = 0, ib = 0, sa = 1, sb = 1) => { - const x = a[ia] - b[ib]; - const y = a[ia + sa] - b[ib + sb]; - return x * x + y * y; -}; - -export const dist2 = (a: ReadonlyVec, b: ReadonlyVec, ia = 0, ib = 0, sa = 1, sb = 1) => - Math.sqrt(distSq2(a, b, ia, ib, sa, sb)); - -export const distManhattan2 = (a: ReadonlyVec, b: ReadonlyVec, ia = 0, ib = 0, sa = 1, sb = 1) => { - return Math.abs(a[ia] - b[ib]) + Math.abs(a[ia + sa] - b[ib + sb]) -}; - -export const distChebyshev2 = (a: ReadonlyVec, b: ReadonlyVec, ia = 0, ib = 0, sa = 1, sb = 1) => { - return Math.max(Math.abs(a[ia] - b[ib]), Math.abs(a[ia + sa] - b[ib + sb])) -}; - -export const normalize2 = (a: Vec, n = 1, ia = 0, sa = 1) => { - const m = mag2(a, ia, sa); - m >= EPS && mulN2(a, n / m, ia, sa); - return a; -}; - -export const limit2 = (a: Vec, n: number, ia = 0, sa = 1) => { - const m = mag2(a, ia, sa); - m >= n && mulN2(a, n / m, ia, sa); - return a; -}; - -export const reflect2 = (a: Vec, b: ReadonlyVec, ia = 0, ib = 0, sa = 1, sb = 1) => - maddN2(a, b, -2 * dot2(a, b, ia, ib, sa, sb), ia, ib, sa, sb); - -export const refract2 = (a: Vec, b: ReadonlyVec, eta: number, ia = 0, ib = 0, sa = 1, sb = 1) => { - const d = dot2(a, b, ia, ib, sa, sb); - const k = 1 - eta * eta * (1 - d * d); - return k < 0 ? - setN2(a, 0, ia, sa) : - msubN2(mulN2(a, eta, ia, sa), b, eta * d + Math.sqrt(k), ia, ib, sa, sb); -}; - -export const perpendicularLeft2 = (a: Vec, ia = 0, sa = 1) => { - const x = a[ia]; - a[ia] = -a[ia + sa]; - a[ia + sa] = x; - return a; -}; - -export const perpendicularRight2 = (a: Vec, ia = 0, sa = 1) => { - const x = -a[ia]; - a[ia] = a[ia + sa]; - a[ia + sa] = x; - return a; -}; - -export const rotate2 = (a: Vec, theta: number, ia = 0, sa = 1) => { - const s = Math.sin(theta); - const c = Math.cos(theta); - const x = a[ia]; - const y = a[ia + sa]; - return setS2(a, x * c - y * s, x * s + y * c, ia, sa); -}; - -export const rotateAroundPoint2 = (a: Vec, b: Vec, theta: number, ia = 0, ib = 0, sa = 1, sb = 1) => { - const x = a[ia] - b[ib]; - const y = a[ia + sa] - b[ib + sb]; - const s = Math.sin(theta); - const c = Math.cos(theta); - return setS2( - a, - x * c - y * s + b[ib], - x * s + y * c + b[ib + sb], - ia, sa - ); -}; - -export const heading2 = (a: ReadonlyVec, ia = 0, sa = 1) => - atan2Abs(a[ia + sa], a[ia]); - -export const angleRatio2 = (a: ReadonlyVec, b: ReadonlyVec, ia = 0, ib = 0, sa = 1, sb = 1) => - dot2(a, b, ia, ib, sa, sb) / (mag2(a, ia, sa) * mag2(b, ib, sb)); - -export const angleBetween2 = (a: ReadonlyVec, b: ReadonlyVec, normalize = false, ia = 0, ib = 0, sa = 1, sb = 1): number => - normalize ? - (a[ia] * b[ib + sb] < a[ia + sa] * b[ib] ? -1 : 1) * - Math.acos(angleRatio2(a, b, ia, ib, sa, sb)) : - Math.acos(dot2(a, b, ia, ib, sa, sb)); - -export const bisect2 = (a: ReadonlyVec, b: ReadonlyVec, ia = 0, ib = 0, sa = 1, sb = 1) => { - const theta = (heading2(a, ia, sa) + heading2(b, ib, sb)) / 2; - return theta <= HALF_PI ? theta : PI - theta; -} - -export const toPolar2 = (a: Vec, ia = 0, sa = 1) => { - const x = a[ia], y = a[ia + sa]; - return setS2(a, Math.sqrt(x * x + y * y), Math.atan2(y, x), ia, sa); -}; - -export const toCartesian2 = (a: Vec, b: ReadonlyVec = ZERO4, ia = 0, ib = 0, sa = 1, sb = 1) => { - const r = a[ia], theta = a[ia + sa]; - return setS2( - a, - r * Math.cos(theta) + b[ib], - r * Math.sin(theta) + b[ib + sb], - ia, sa - ); -}; - -export const minorAxis2 = (a: Vec, ia = 0, sa = 1) => - min2id(Math.abs(a[ia]), Math.abs(a[ia + sa])); - -export const majorAxis2 = (a: Vec, ia = 0, sa = 1) => - max2id(Math.abs(a[ia]), Math.abs(a[ia + sa])); - -export const vec2 = (x = 0, y = 0) => - new Vec2([x, y]); - -export const asVec2 = (x: ReadonlyVec) => - x instanceof Vec2 ? x : new Vec2([x[0] || 0, x[1] || 0]); +import { eqDelta2 } from "./eqdelta"; +import { declareIndices } from "./internal/accessors"; +import { AVec } from "./internal/avec"; +import { + intoBuffer, + mapBuffer, + values, + vecIterator +} from "./internal/vec-utils"; +import { setS2 } from "./sets"; -export class Vec2 implements - IVector, - IAngleBetween, - ICrossProduct, - IPolar { +export class Vec2 extends AVec implements + IVector { /** * Returns array of memory mapped `Vec2` instances using given @@ -312,18 +33,13 @@ export class Vec2 implements * interleaved etc. * * @param buf backing array - * @param n num vectors + * @param num num vectors * @param start start index * @param cstride component stride * @param estride element stride */ - static mapBuffer(buf: Vec, n: number = buf.length >> 1, start = 0, cstride = 1, estride = 2) { - const res: Vec2[] = []; - while (--n >= 0) { - res.push(new Vec2(buf, start, cstride)); - start += estride; - } - return res; + static mapBuffer(buf: Vec, num: number = buf.length >> 1, start = 0, cstride = 1, estride = 2) { + return mapBuffer(Vec2, buf, num, start, cstride, estride); } /** @@ -332,7 +48,7 @@ export class Vec2 implements * strides, starting at `start` index. It's the user's * responsibility to ensure the target buffer has sufficient * capacity to hold the input vectors. See `Vec2.mapBuffer` for the - * reverse operation. Returns buffer. + * inverse operation. Returns `buf`. * * @param buf * @param src @@ -340,66 +56,31 @@ export class Vec2 implements * @param cstride * @param estride */ - static intoBuffer(buf: Vec, src: Iterable>, start = 0, cstride = 1, estride = 2) { - for (let v of src) { - set2(buf, v.buf, start, v.i, cstride, v.s); - start += estride; - } - return buf; - } - - static swizzle(v: IVec, x: number, y: number) { - return new Vec2([]).swizzle(v, x, y); - } - - static mixBilinear(a: Readonly, b: Readonly, c: Readonly, d: Readonly, u: number, v: number) { - return new Vec2( - mixBilinear2( - get2(a.buf, a.i, a.s), b.buf, c.buf, d.buf, u, v, - 0, b.i, c.i, d.i, - 1, b.s, c.s, d.s, - ) - ); - } - - static randNorm(n = 1) { - return new Vec2(randNorm2([], n)); + static intoBuffer(buf: Vec, src: Iterable, start = 0, cstride = 1, estride = 2) { + return intoBuffer(setS2, buf, src, start, cstride, estride); } - static random(min: number, max: number) { - return new Vec2(randMinMax2([], min, max)); + static iterator(buf: Vec, num: number, start = 0, cstride = 1, estride = 2) { + return vecIterator(Vec2, buf, num, start, cstride, estride); } - static comparator(o1: Vec2Coord, o2: Vec2Coord) { - return (a: Readonly, b: Readonly) => a.compare(b, o1, o2); - } - - static readonly ZERO = Object.freeze(new Vec2(ZERO4)); - static readonly ONE = Object.freeze(new Vec2(ONE4)); - static readonly MIN = Object.freeze(new Vec2(MIN4)); - static readonly MAX = Object.freeze(new Vec2(MAX4)); - static readonly X_AXIS = Object.freeze(new Vec2(X4)); - static readonly Y_AXIS = Object.freeze(new Vec2(Y4)); + static readonly X_AXIS = new Vec2(X2); + static readonly Y_AXIS = new Vec2(Y2); + static readonly MIN = new Vec2(MIN2); + static readonly MAX = new Vec2(MAX2); + static readonly ZERO = new Vec2(ZERO2); + static readonly ONE = new Vec2(ONE2); - buf: Vec; - i: number; - s: number; x: number; y: number; [id: number]: number; - constructor(buf?: Vec, index = 0, stride = 1) { - this.buf = buf || [0, 0]; - this.i = index; - this.s = stride; + constructor(buf?: Vec, offset = 0, stride = 1) { + super(buf || [0, 0], offset, stride); } [Symbol.iterator]() { - return $iter(this.buf, 2, this.i, this.s); - } - - array() { - return get2(this.buf, this.i, this.s); + return values(this.buf, 2, this.offset, this.stride); } get length() { @@ -407,402 +88,40 @@ export class Vec2 implements } copy() { - return new Vec2(get2(this.buf, this.i, this.s)); - } - - empty() { - return new Vec2(); - } - - equiv(v: any) { - return v instanceof Vec2 ? - equiv2(this.buf, v.buf, this.i, v.i, this.s, v.s) : - isArrayLike(v) && v.length === 2 ? - equiv2(this.buf, v, this.i, 0, this.s, 1) : - false; - } - - eqDelta(v: Readonly, eps = EPS) { - return eqDelta2(this.buf, v.buf, eps, this.i, v.i, this.s, v.s); - } - - compare(v: Readonly, o1: Vec2Coord = 0, o2: Vec2Coord = 1) { - return compare2(this.buf, v.buf, o1, o2, this.i, v.i, this.s, v.s); - } - - set(v: Readonly) { - set2(this.buf, v.buf, this.i, v.i, this.s, v.s); - return this; - } - - setN(n: number) { - setN2(this.buf, n, this.i, this.s); - return this; - } - - setS(x: number, y: number) { - setS2(this.buf, x, y, this.i, this.s); - return this; - } - - jitter(n = 1) { - jitter2(this.buf, n, this.i, this.s); - return this; - } - - swizzle(v: IVec, x: number, y: number) { - swizzle2(this.buf, v.buf, x, y, this.i, v.i, this.s, v.s); - return this; - } - - swap(v: Vec2) { - swap2(this.buf, v.buf, this.i, v.i, this.s, v.s); - return this; - } - - add(v: Readonly) { - add2(this.buf, v.buf, this.i, v.i, this.s, v.s); - return this; - } - - sub(v: Readonly) { - sub2(this.buf, v.buf, this.i, v.i, this.s, v.s); - return this; - } - - mul(v: Readonly) { - mul2(this.buf, v.buf, this.i, v.i, this.s, v.s); - return this; - } - - div(v: Readonly) { - div2(this.buf, v.buf, this.i, v.i, this.s, v.s); - return this; - } - - addN(n: number) { - addN2(this.buf, n, this.i, this.s); - return this; - } - - subN(n: number) { - subN2(this.buf, n, this.i, this.s); - return this; - } - - mulN(n: number) { - mulN2(this.buf, n, this.i, this.s); - return this; - } - - divN(n: number) { - divN2(this.buf, n, this.i, this.s); - return this; - } - - addNew(b: Readonly, out?: Vec2) { - !out && (out = new Vec2([])); - add2o(out.buf, this.buf, b.buf, out.i, this.i, b.i, out.s, this.s, b.s); - return out; - } - - subNew(b: Readonly, out?: Vec2) { - !out && (out = new Vec2([])); - sub2o(out.buf, this.buf, b.buf, out.i, this.i, b.i, out.s, this.s, b.s); - return out; - } - - mulNew(b: Readonly, out?: Vec2) { - !out && (out = new Vec2([])); - mul2o(out.buf, this.buf, b.buf, out.i, this.i, b.i, out.s, this.s, b.s); - return out; - } - - divNew(b: Readonly, out?: Vec2) { - !out && (out = new Vec2([])); - div2o(out.buf, this.buf, b.buf, out.i, this.i, b.i, out.s, this.s, b.s); - return out; - } - - addNewN(n: number, out?: Vec2) { - !out && (out = new Vec2([])); - addN2o(out.buf, this.buf, n, out.i, this.i, out.s, this.s); - return out; - } - - subNewN(n: number, out?: Vec2) { - !out && (out = new Vec2([])); - subN2o(out.buf, this.buf, n, out.i, this.i, out.s, this.s); - return out; - } - - mulNewN(n: number, out?: Vec2) { - !out && (out = new Vec2([])); - mulN2o(out.buf, this.buf, n, out.i, this.i, out.s, this.s); - return out; - } - - divNewN(n: number, out?: Vec2) { - !out && (out = new Vec2([])); - divN2o(out.buf, this.buf, n, out.i, this.i, out.s, this.s); - return out; - } - - maddNew(b: Readonly, c: Readonly, out?: Vec2) { - out = out ? out.set(this) : this.copy(); - madd2(out.buf, b.buf, c.buf, out.i, b.i, c.i, out.s, b.s, c.s); - return out; - } - - maddNewN(b: Readonly, n: number, out?: Vec2) { - out = out ? out.set(this) : this.copy(); - maddN2(out.buf, b.buf, n, out.i, b.i, out.s, b.s); - return out; - } - - msubNew(b: Readonly, c: Readonly, out?: Vec2) { - out = out ? out.set(this) : this.copy(); - msub2(out.buf, b.buf, c.buf, out.i, b.i, c.i, out.s, b.s, c.s); - return out; - } - - msubNewN(b: Readonly, n: number, out?: Vec2) { - out = out ? out.set(this) : this.copy(); - msubN2(out.buf, b.buf, n, out.i, b.i, out.s, b.s); - return out; - } - - mixNew(b: Readonly, t: Readonly, out?: Vec2) { - !out && (out = new Vec2([])); - mix2o(out.buf, this.buf, b.buf, t.buf, out.i, this.i, b.i, t.i, out.s, this.s, b.s, t.s); - return out; - } - - mixNewN(b: Readonly, n = 0.5, out?: Vec2) { - !out && (out = new Vec2([])); - mixN2o(out.buf, this.buf, b.buf, n, out.i, this.i, b.i, out.s, this.s, b.s); - return out; - } - - neg() { - mulN2(this.buf, -1, this.i, this.s); - return this; - } - - abs() { - abs2(this.buf, this.i, this.s); - return this; - } - - sign() { - sign2(this.buf, this.i, this.s); - return this; - } - - floor() { - floor2(this.buf, this.i, this.s); - return this; - } - - ceil() { - ceil2(this.buf, this.i, this.s); - return this; - } - - fract() { - fract2(this.buf, this.i, this.s); - return this; - } - - sqrt() { - sqrt2(this.buf, this.i, this.s); - return this; - } - - pow(v: Readonly) { - pow2(this.buf, v.buf, this.i, v.i, this.s, v.s); - return this; - } - - powN(n: number) { - powN2(this.buf, n, this.i, this.s); - return this; - } - - sin() { - sin2(this.buf, this.i, this.s); - return this; - } - - cos() { - cos2(this.buf, this.i, this.s); - return this; - } - - madd(b: Readonly, c: Readonly) { - madd2(this.buf, b.buf, c.buf, this.i, b.i, c.i, this.s, b.s, c.s); - return this; - } - - maddN(b: Readonly, n: number) { - maddN2(this.buf, b.buf, n, this.i, b.i, this.s, b.s); - return this; - } - - msub(b: Readonly, c: Readonly) { - msub2(this.buf, b.buf, c.buf, this.i, b.i, c.i, this.s, b.s, c.s); - return this; - } - - msubN(b: Readonly, n: number) { - msubN2(this.buf, b.buf, n, this.i, b.i, this.s, b.s); - return this; - } - - mix(b: Readonly, c: Readonly) { - mix2(this.buf, b.buf, c.buf, this.i, b.i, c.i, this.s, b.s, c.s); - return this; - } - - mixN(b: Readonly, n = 0.5) { - mixN2(this.buf, b.buf, n, this.i, b.i, this.s, b.s); - return this; - } - - min(v: Readonly) { - min2(this.buf, v.buf, this.i, v.i, this.s, v.s); - return this; - } - - max(v: Readonly) { - max2(this.buf, v.buf, this.i, v.i, this.s, v.s); - return this; - } - - clamp(min: Readonly, max: Readonly) { - clamp2(this.buf, min.buf, max.buf, this.i, min.i, max.i, this.s, min.s, max.s); - return this; - } - - minorAxis() { - return minorAxis2(this.buf, this.i, this.s); - } - - majorAxis() { - return majorAxis2(this.buf, this.i, this.s); - } - - step(e: Readonly) { - step2(this.buf, e.buf, this.i, e.i, this.s, e.s); - return this; - } - - smoothStep(e1: Readonly, e2: Readonly) { - smoothStep2(this.buf, e1.buf, e2.buf, this.i, e1.i, e2.i, this.s, e1.s, e2.s); - return this; - } - - dot(v: Readonly) { - return dot2(this.buf, v.buf, this.i, v.i, this.s, v.s); - } - - cross(v: Readonly) { - return cross2(this.buf, v.buf, this.i, v.i, this.s, v.s); - } - - mag() { - return mag2(this.buf, this.i, this.s); - } - - magSq() { - return magSq2(this.buf, this.i, this.s); - } - - dist(v: Readonly) { - return dist2(this.buf, v.buf, this.i, v.i, this.s, v.s); - } - - distSq(v: Readonly) { - return distSq2(this.buf, v.buf, this.i, v.i, this.s, v.s); - } - - distManhattan(v: Readonly) { - return distManhattan2(this.buf, v.buf, this.i, v.i, this.s, v.s); - } - - distChebyshev(v: Readonly) { - return distChebyshev2(this.buf, v.buf, this.i, v.i, this.s, v.s); - } - - normalize(len = 1) { - normalize2(this.buf, len, this.i, this.s); - return this; - } - - limit(len: number) { - limit2(this.buf, len, this.i, this.s); - return this; - } - - reflect(n: Readonly) { - reflect2(this.buf, n.buf, this.i, n.i, this.s, n.s); - return this; - } - - refract(n: Readonly, eta: number) { - refract2(this.buf, n.buf, eta, this.i, n.i, this.s, n.s); - return this; - } - - rotate(theta: number) { - rotate2(this.buf, theta, this.i, this.s); - return this; - } - - rotateAroundPoint(v: Readonly, theta: number) { - rotateAroundPoint2(this.buf, v.buf, theta, this.i, v.i, this.s, v.s); - return this; - } - - heading() { - return heading2(this.buf, this.i, this.s); - } - - angleBetween(v: Readonly, normalize = false) { - return angleBetween2(this.buf, v.buf, normalize, this.i, v.i, this.s, v.s); + return new Vec2([this.x, this.y]); } - bisect(v: Readonly) { - return bisect2(this.buf, v.buf, this.i, v.i, this.s, v.s); + copyView() { + return new Vec2(this.buf, this.offset, this.stride); } - perpendicularLeft() { - perpendicularLeft2(this.buf, this.i, this.s); - return this; - } - - perpendicularRight() { - perpendicularRight2(this.buf, this.i, this.s); - return this; + empty() { + return new Vec2(); } - toPolar() { - toPolar2(this.buf, this.i, this.s); - return this; + eqDelta(v: ReadonlyVec, eps = EPS) { + return eqDelta2(this, v, eps); } - toCartesian(o: Readonly = Vec2.ZERO) { - toCartesian2(this.buf, o.buf, this.i, o.i, this.s, o.s); - return this; + toJSON() { + return [this.x, this.y]; } toString() { - return `[${this.buf[this.i]}, ${this.buf[this.i + this.s]}]`; - } - - toJSON() { - return this.array(); + return `[${this.x}, ${this.y}]`; } } declareIndices(Vec2.prototype, ["x", "y"]); + +export const vec2 = + (x = 0, y = 0) => new Vec2([x, y]); + +export const vec2n = + (n: number) => new Vec2([n, n]); + +export const asVec2 = + (x: Vec) => + x instanceof Vec2 ? + x : + new Vec2(x.length >= 2 ? x : [x[0] || 0, x[1] || 0]); diff --git a/packages/vectors/src/vec3.ts b/packages/vectors/src/vec3.ts index 1ce2dfd6c4..b800a053c3 100644 --- a/packages/vectors/src/vec3.ts +++ b/packages/vectors/src/vec3.ts @@ -1,373 +1,29 @@ -import { isArrayLike } from "@thi.ng/checks/is-arraylike"; -import { atan2Abs } from "@thi.ng/math/angle"; -import { EPS } from "@thi.ng/math/api"; -import { eqDelta } from "@thi.ng/math/eqdelta"; -import { max3id, min3id } from "@thi.ng/math/interval"; -import { mixBilinear } from "@thi.ng/math/mix"; -import { fract } from "@thi.ng/math/prec"; -import { smoothStep, step } from "@thi.ng/math/step"; +import { EPS } from "@thi.ng/math"; import { - IAngleBetween, - ICrossProduct, - IPolar, - IVec, IVector, - MAX4, - MIN4, - ONE4, + MAX3, + MIN3, + ONE3, ReadonlyVec, Vec, - Vec3Coord, - X4, - Y4, - Z4, - ZERO4 + X3, + Y3, + Z3, + ZERO3 } from "./api"; -import { declareIndices, defcommon } from "./codegen"; -import { $iter } from "./common"; +import { eqDelta3 } from "./eqdelta"; +import { declareIndices } from "./internal/accessors"; +import { AVec } from "./internal/avec"; import { - heading2, - rotate2, - toCartesian2, - toPolar2 -} from "./vec2"; + intoBuffer, + mapBuffer, + values, + vecIterator +} from "./internal/vec-utils"; +import { setS3 } from "./sets"; -export const op3 = (fn: (x: number) => number, a: Vec, ia = 0, sa = 1) => ( - a[ia] = fn(a[ia]), - a[ia + sa] = fn(a[ia + sa]), - a[ia + 2 * sa] = fn(a[ia + 2 * sa]), - a -); - -export const op30 = (fn: () => number, a: Vec, ia = 0, sa = 1) => ( - a[ia] = fn(), - a[ia + sa] = fn(), - a[ia + 2 * sa] = fn(), - a -); - -export const op31 = (fn: (a: number, n: number) => number, a: Vec, n: number, ia = 0, sa = 1) => ( - a[ia] = fn(a[ia], n), - a[ia + sa] = fn(a[ia + sa], n), - a[ia + 2 * sa] = fn(a[ia + 2 * sa], n), - a -); - -export const get3 = (a: ReadonlyVec, ia = 0, sa = 1) => - set3(new ((a.constructor))(3), a, 0, ia, 1, sa); - -export const setS3 = (a: Vec, x: number, y: number, z: number, ia = 0, sa = 1) => - (a[ia] = x, a[ia + sa] = y, a[ia + 2 * sa] = z, a); - -export const randNorm3 = (a: Vec, n = 1, ia = 0, sa = 1) => - randMinMax3(a, -n, n, ia, sa); - -export const randMinMax3 = (a: Vec, min: number, max: number, ia = 0, sa = 1) => { - const d = max - min; - return op30(() => min + d * Math.random(), a, ia, sa); -}; - -export const jitter3 = (a: Vec, n: number, ia = 0, sa = 1) => - op3((x) => x + Math.random() * 2 * n - n, a, ia, sa); - -export const swizzle3 = (a: Vec, b: ReadonlyVec, x: number, y: number, z: number, ia = 0, ib = 0, sa = 1, sb = 1) => - setS3(a, b[ib + x * sb], b[ib + y * sb], b[ib + z * sb], ia, sa); - -export const swap3 = (a: Vec, b: Vec, ia = 0, ib = 0, sa = 1, sb = 1) => { - let t = a[ia]; a[ia] = b[ib]; b[ib] = t; - ia += sa; ib += sb; - t = a[ia]; a[ia] = b[ib]; b[ib] = t; - ia += sa; ib += sb; - t = a[ia]; a[ia] = b[ib]; b[ib] = t; - return a; -}; - -export const equiv3 = (a: ReadonlyVec, b: ReadonlyVec, ia = 0, ib = 0, sa = 1, sb = 1) => - a[ia] === b[ib] && - a[ia + sa] === b[ib + sb] && - a[ia + 2 * sa] === b[ib + 2 * sb]; - -export const eqDelta3 = (a: ReadonlyVec, b: ReadonlyVec, eps = EPS, ia = 0, ib = 0, sa = 1, sb = 1) => - eqDelta(a[ia], b[ib], eps) && - eqDelta(a[ia + sa], b[ib + sb], eps) && - eqDelta(a[ia + 2 * sa], b[ib + 2 * sb], eps); - -export const eqDelta3buf = (a: ReadonlyVec, b: ReadonlyVec, num: number, eps = EPS, ia = 0, ib = 0, sca = 1, scb = 1, sea = 3, seb = 3) => { - while (--num >= 0) { - if (!eqDelta3(a, b, eps, ia + num * sea, ib + num * seb, sca, scb)) { - return false; - } - } - return true; -}; - -export const eqDelta3array = (a: ReadonlyVec[], b: ReadonlyVec[], eps = EPS) => { - const na = a.length; - if (b.length !== na) { - return false; - } - for (let i = 0; i < na; i++) { - if (!eqDelta3(a[i], b[i], eps)) { - return false; - } - } - return true; -}; - -export const compare3 = ( - a: ReadonlyVec, - b: ReadonlyVec, - o1: Vec3Coord, o2: Vec3Coord, o3: Vec3Coord, - ia = 0, ib = 0, sa = 1, sb = 1): number => { - - const ax = a[ia + o1 * sa]; - const ay = a[ia + o2 * sa]; - const az = a[ia + o3 * sa]; - const bx = b[ib + o1 * sb]; - const by = b[ib + o2 * sb]; - const bz = b[ib + o3 * sb]; - return ax === bx ? - ay === by ? - az === bz ? - 0 : - az < bz ? -3 : 3 : - ay < by ? -2 : 2 : - ax < bx ? -1 : 1; -}; - -export const collate3 = (buf: Vec, src: Iterable, start = 0, cstride = 1, estride = 3) => { - for (let v of src) { - set3(buf, v, start, 0, cstride, 1); - start += estride; - } - return buf; -}; - -export const [ - set3, setN3, - add3, sub3, mul3, div3, - add3o, sub3o, mul3o, div3o, - addN3, subN3, mulN3, divN3, - addN3o, subN3o, mulN3o, divN3o, - madd3, maddN3, msub3, msubN3, - abs3, sign3, floor3, ceil3, sin3, cos3, sqrt3, - pow3, min3, max3, - mix3, mixN3, mix3o, mixN3o -] = defcommon(3); - -export const neg3 = (a: Vec, ia = 0, sa = 1) => - mulN3(a, -1, ia, sa); - -export const fract3 = (a: Vec, ia = 0, sa = 1) => - op3(fract, a, ia, sa); - -export const powN3 = (a: Vec, n: number, ia = 0, sa = 1) => - op31(Math.pow, a, n, ia, sa); - -export const dot3 = (a: ReadonlyVec, b: ReadonlyVec, ia = 0, ib = 0, sa = 1, sb = 1) => - a[ia] * b[ib] + - a[ia + sa] * b[ib + sb] + - a[ia + 2 * sa] * b[ib + 2 * sb]; - -export const cross3 = (a: Vec, b: ReadonlyVec, ia = 0, ib = 0, sa = 1, sb = 1) => { - const iay = ia + sa; - const iaz = ia + 2 * sa; - const iby = ib + sb; - const ibz = ib + 2 * sb; - const x = a[iay] * b[ibz] - a[iaz] * b[iby]; - const y = a[iaz] * b[ib] - a[ia] * b[ibz]; - a[iaz] = a[ia] * b[iby] - a[iay] * b[ib]; - a[iay] = y; - a[ia] = x; - return a; -}; - -export const orthoNormal3 = (a: Vec, b: Vec, c: Vec, ia = 0, ib = 0, ic = 0, sa = 1, sb = 1, sc = 1) => - cross3( - sub3(get3(c, ic, sc), a, 0, ia, 1, sa), - sub3(get3(b, ib, sb), a, 0, ia, 1, sa) - ); - -export const mixBilinear3 = ( - a: Vec, b: ReadonlyVec, c: ReadonlyVec, d: ReadonlyVec, u: number, v: number, - ia = 0, ib = 0, ic = 0, id = 0, - sa = 1, sb = 1, sc = 1, sd = 1) => ( - a[ia] = mixBilinear(a[ia], b[ib], c[ic], d[id], u, v), - a[ia + sa] = mixBilinear(a[ia + sa], b[ib + sb], c[ic + sc], d[id + sd], u, v), - a[ia + 2 * sa] = mixBilinear(a[ia + 2 * sa], b[ib + 2 * sb], c[ic + 2 * sc], d[id + 2 * sd], u, v), - a - ); - -export const clamp3 = (a: Vec, min: ReadonlyVec, max: ReadonlyVec, ia = 0, imin = 0, imax = 0, sa = 1, smin = 1, smax = 1) => - max3(min3(a, max, ia, imax, sa, smax), min, ia, imin, sa, smin); - -export const step3 = (a: Vec, e: ReadonlyVec, ia = 0, ie = 0, sa = 1, se = 1) => ( - a[ia] = step(e[ie], a[ia]), - a[ia + sa] = step(e[ie + se], a[ia + sa]), - a[ia + 2 * sa] = step(e[ie + 2 * se], a[ia + 2 * sa]), - a -); - -export const smoothStep3 = (a: Vec, e1: ReadonlyVec, e2: ReadonlyVec, ia = 0, ie1 = 0, ie2 = 0, sa = 1, se1 = 1, se2 = 1) => ( - a[ia] = smoothStep(e1[ie1], e2[ie2], a[ia]), - a[ia + sa] = smoothStep(e1[ie1 + se1], e2[ie2 + se2], a[ia + sa]), - a[ia + 2 * sa] = smoothStep(e1[ie1 + 2 * se1], e2[ie2 + 2 * se2], a[ia + 2 * sa]), - a -); - -export const magSq3 = (a: ReadonlyVec, ia = 0, sa = 1) => { - const x = a[ia]; - const y = a[ia + sa]; - const z = a[ia + 2 * sa]; - return x * x + y * y + z * z; -}; - -export const mag3 = (a: ReadonlyVec, ia = 0, sa = 1) => - Math.sqrt(magSq3(a, ia, sa)); - -export const distSq3 = (a: ReadonlyVec, b: ReadonlyVec, ia = 0, ib = 0, sa = 1, sb = 1) => { - const x = a[ia] - b[ib]; - const y = a[ia + sa] - b[ib + sb]; - const z = a[ia + 2 * sa] - b[ib + 2 * sb]; - return x * x + y * y + z * z; -}; - -export const dist3 = (a: ReadonlyVec, b: ReadonlyVec, ia = 0, ib = 0, sa = 1, sb = 1) => - Math.sqrt(distSq3(a, b, ia, ib, sa, sb)); - -export const distManhattan3 = (a: ReadonlyVec, b: ReadonlyVec, ia = 0, ib = 0, sa = 1, sb = 1) => - Math.abs(a[ia] - b[ib]) + - Math.abs(a[ia + sa] - b[ib + sb]) + - Math.abs(a[ia + 2 * sa] - b[ib + 2 * sb]); - -export const distChebyshev3 = (a: ReadonlyVec, b: ReadonlyVec, ia = 0, ib = 0, sa = 1, sb = 1) => - Math.max( - Math.abs(a[ia] - b[ib]), - Math.abs(a[ia + sa] - b[ib + sb]), - Math.abs(a[ia + 2 * sa] - b[ib + 2 * sb]) - ); - -export const normalize3 = (a: Vec, n = 1, ia = 0, sa = 1) => { - const m = mag3(a, ia, sa); - m >= EPS && mulN3(a, n / m, ia, sa); - return a; -}; - -export const limit3 = (a: Vec, n: number, ia = 0, sa = 1) => { - const m = mag3(a, ia, sa); - m >= n && mulN3(a, n / m, ia, sa); - return a; -}; - -export const reflect3 = (a: Vec, b: ReadonlyVec, ia = 0, ib = 0, sa = 1, sb = 1) => - maddN3(a, b, -2 * dot3(a, b, ia, ib, sa, sb), ia, ib, sa, sb); - -export const refract3 = (a: Vec, b: ReadonlyVec, eta: number, ia = 0, ib = 0, sa = 1, sb = 1) => { - const d = dot3(a, b, ia, ib, sa, sb); - const k = 1 - eta * eta * (1 - d * d); - return k < 0 ? - setN3(a, 0, ia, sa) : - msubN3(mulN3(a, eta, ia, sa), b, eta * d + Math.sqrt(k), ia, ib, sa, sb); -}; - -export const rotateX3 = (a: Vec, theta: number, ia = 0, sa = 1) => - rotate2(a, theta, ia + sa, sa); - -export const rotateY3 = (a: Vec, theta: number, ia = 0, sa = 1) => - rotate2(a, theta, ia + 2 * sa, -2 * sa); - -export const rotateZ3 = rotate2; - -export const rotateAroundAxis3 = (v: Vec, axis: Vec, theta: number, ia = 0, ib = 0, sa = 1, sb = 1) => { - const x = v[ia]; - const y = v[ia + sa]; - const z = v[ia + 2 * sa]; - const ax = axis[ib]; - const ay = axis[ib + sb]; - const az = axis[ib + 2 * sb]; - const ux = ax * x; - const uy = ax * y; - const uz = ax * z; - const vx = ay * x; - const vy = ay * y; - const vz = ay * z; - const wx = az * x; - const wy = az * y; - const wz = az * z; - const uvw = ux + vy + wz; - const s = Math.sin(theta); - const c = Math.cos(theta); - return setS3(v, - (ax * uvw + (x * (ay * ay + az * az) - ax * (vy + wz)) * c + (-wy + vz) * s), - (ay * uvw + (y * (ax * ax + az * az) - ay * (ux + wz)) * c + (wx - uz) * s), - (az * uvw + (z * (ax * ax + ay * ay) - az * (ux + vy)) * c + (-vx + uy) * s), - ia, sa - ); -} - -export const headingXY3 = heading2; - -export const headingXZ3 = (a: ReadonlyVec, ia = 0, sa = 1) => - atan2Abs(a[ia + 2 * sa], a[ia]); - -export const headingYZ3 = (a: ReadonlyVec, ia = 0, sa = 1) => - atan2Abs(a[ia + 2 * sa], a[ia + sa]); - -export const angleRatio3 = (a: ReadonlyVec, b: ReadonlyVec, ia = 0, ib = 0, sa = 1, sb = 1) => - dot3(a, b, ia, ib, sa, sb) / (mag3(a, ia, sa) * mag3(b, ib, sb)); - -export const angleBetween3 = (a: ReadonlyVec, b: ReadonlyVec, normalize = false, ia = 0, ib = 0, sa = 1, sb = 1): number => - normalize ? - (a[ia] * b[ib + sb] < a[ia + sa] * b[ib] ? -1 : 1) * - Math.acos(angleRatio3(a, b, ia, ib, sa, sb)) : - Math.acos(dot3(a, b, ia, ib, sa, sb)); - -export const toPolar3 = (a: Vec, ia = 0, sa = 1) => { - const x = a[ia]; - const y = a[ia + sa]; - const z = a[ia + 2 * sa]; - const r = Math.sqrt(x * x + y * y + z * z); - return setS3(a, r, Math.asin(z / r), Math.atan2(y, x), ia, sa); -}; - -export const toCartesian3 = (a: Vec, b: ReadonlyVec = ZERO4, ia = 0, ib = 0, sa = 1, sb = 1) => { - const r = a[ia]; - const theta = a[ia + sa]; - const phi = a[ia + 2 * sa]; - const ct = Math.cos(theta); - return setS3(a, - r * ct * Math.cos(phi) + b[ib], - r * ct * Math.sin(phi) + b[ib + sb], - r * Math.sin(theta) + b[ib + 2 * sb], - ia, sa - ); -}; - -export const toCylindrical3 = toPolar2; - -export const fromCylindrical3 = (a: Vec, b: ReadonlyVec = ZERO4, ia = 0, ib = 0, sa = 1, sb = 1) => { - toCartesian2(a, b, ia, ib, sa, sb); - a[ia + 2 * sa] += b[ib + 2 * sb]; - return a; -}; - -export const minorAxis3 = (a: Vec, ia = 0, sa = 1) => - min3id(Math.abs(a[ia]), Math.abs(a[ia + sa]), Math.abs(a[ia + 2 * sa])); - -export const majorAxis3 = (a: Vec, ia = 0, sa = 1) => - max3id(Math.abs(a[ia]), Math.abs(a[ia + sa]), Math.abs(a[ia + 2 * sa])); - -export const vec3 = (x = 0, y = 0, z = 0) => - new Vec3([x, y, z]); - -export const asVec3 = (x: ReadonlyVec) => - x instanceof Vec3 ? x : new Vec3([x[0] || 0, x[1] || 0, x[2] || 0]); - -export class Vec3 implements - IVector, - IAngleBetween, - ICrossProduct, - IPolar { +export class Vec3 extends AVec implements + IVector { /** * Returns array of memory mapped `Vec3` instances using given @@ -378,18 +34,13 @@ export class Vec3 implements * interleaved etc. * * @param buf backing array - * @param n num vectors + * @param num num vectors * @param start start index * @param cstride component stride * @param estride element stride */ - static mapBuffer(buf: Vec, n = (buf.length / 3) | 0, start = 0, cstride = 1, estride = 3) { - const res: Vec3[] = []; - while (--n >= 0) { - res.push(new Vec3(buf, start, cstride)); - start += estride; - } - return res; + static mapBuffer(buf: Vec, num: number = (buf.length / 3) | 0, start = 0, cstride = 1, estride = 3) { + return mapBuffer(Vec3, buf, num, start, cstride, estride); } /** @@ -398,7 +49,7 @@ export class Vec3 implements * strides, starting at `start` index. It's the user's * responsibility to ensure the target buffer has sufficient * capacity to hold the input vectors. See `Vec3.mapBuffer` for the - * reverse operation. Returns buffer. + * inverse operation. Returns `buf`. * * @param buf * @param src @@ -406,72 +57,33 @@ export class Vec3 implements * @param cstride * @param estride */ - static intoBuffer(buf: Vec, src: Iterable>, start = 0, cstride = 1, estride = 3) { - for (let v of src) { - set3(buf, v.buf, start, v.i, cstride, v.s); - start += estride; - } - return buf; + static intoBuffer(buf: Vec, src: Iterable, start = 0, cstride = 1, estride = 3) { + return intoBuffer(setS3, buf, src, start, cstride, estride); } - static swizzle(v: IVec, x: number, y: number, z: number) { - return new Vec3([]).swizzle(v, x, y, z); + static iterator(buf: Vec, num: number, start = 0, cstride = 1, estride = 3) { + return vecIterator(Vec3, buf, num, start, cstride, estride); } - static mixBilinear(a: Readonly, b: Readonly, c: Readonly, d: Readonly, u: number, v: number) { - return new Vec3( - mixBilinear3( - get3(a.buf, a.i, a.s), b.buf, c.buf, d.buf, u, v, - 0, b.i, c.i, d.i, - 1, b.s, c.s, d.s - ) - ); - } - - static orthoNormal3(a: Readonly, b: Readonly, c: Readonly) { - return new Vec3(orthoNormal3(a.buf, b.buf, c.buf, a.i, b.i, c.i, a.s, b.s, c.s)); - } - - static randNorm(n = 1) { - return new Vec3(randNorm3([], n)); - } - - static random(min: number, max: number) { - return new Vec3(randMinMax3([], min, max)); - } + static readonly X_AXIS = new Vec3(X3); + static readonly Y_AXIS = new Vec3(Y3); + static readonly Z_AXIS = new Vec3(Z3); + static readonly MIN = new Vec3(MIN3); + static readonly MAX = new Vec3(MAX3); + static readonly ZERO = new Vec3(ZERO3); + static readonly ONE = new Vec3(ONE3); - static comparator(o1: Vec3Coord, o2: Vec3Coord, o3: Vec3Coord) { - return (a: Readonly, b: Readonly) => a.compare(b, o1, o2, o3); - } - - static readonly ZERO = Object.freeze(new Vec3(ZERO4)); - static readonly ONE = Object.freeze(new Vec3(ONE4)); - static readonly MIN = Object.freeze(new Vec3(MIN4)); - static readonly MAX = Object.freeze(new Vec3(MAX4)); - static readonly X_AXIS = Object.freeze(new Vec3(X4)); - static readonly Y_AXIS = Object.freeze(new Vec3(Y4)); - static readonly Z_AXIS = Object.freeze(new Vec3(Z4)); - - buf: Vec; - i: number; - s: number; x: number; y: number; z: number; [id: number]: number; - constructor(buf?: Vec, index = 0, stride = 1) { - this.buf = buf || [0, 0, 0]; - this.i = index; - this.s = stride; + constructor(buf?: Vec, offset = 0, stride = 1) { + super(buf || [0, 0, 0], offset, stride); } [Symbol.iterator]() { - return $iter(this.buf, 3, this.i, this.s); - } - - array() { - return get3(this.buf, this.i, this.s); + return values(this.buf, 3, this.offset, this.stride); } get length() { @@ -479,423 +91,40 @@ export class Vec3 implements } copy() { - return new Vec3(get3(this.buf, this.i, this.s)); - } - - empty() { - return new Vec3(); - } - - equiv(v: any) { - return v instanceof Vec3 ? - equiv3(this.buf, v.buf, this.i, v.i, this.s, v.s) : - isArrayLike(v) && v.length === 3 ? - equiv3(this.buf, v, this.i, 0, this.s, 1) : - false; - } - - eqDelta(v: Readonly, eps = EPS) { - return eqDelta3(this.buf, v.buf, eps, this.i, v.i, this.s, v.s); - } - - compare(v: Readonly, o1: Vec3Coord = 0, o2: Vec3Coord = 1, o3: Vec3Coord = 2) { - return compare3(this.buf, v.buf, o1, o2, o3, this.i, v.i, this.s, v.s); - } - - set(v: Readonly) { - set3(this.buf, v.buf, this.i, v.i, this.s, v.s); - return this; - } - - setN(n: number) { - setN3(this.buf, n, this.i, this.s); - return this; - } - - setS(x: number, y: number, z: number) { - setS3(this.buf, x, y, z, this.i, this.s); - return this; - } - - jitter(n = 1) { - jitter3(this.buf, n, this.i, this.s); - return this; + return new Vec3([this.x, this.y, this.z]); } - swizzle(v: IVec, x: number, y: number, z: number) { - swizzle3(this.buf, v.buf, x, y, z, this.i, v.i, this.s, v.s); - return this; + copyView() { + return new Vec3(this.buf, this.offset, this.stride); } - swap(v: Vec3) { - swap3(this.buf, v.buf, this.i, v.i, this.s, v.s); - return this; - } - - add(v: Readonly) { - add3(this.buf, v.buf, this.i, v.i, this.s, v.s); - return this; - } - - sub(v: Readonly) { - sub3(this.buf, v.buf, this.i, v.i, this.s, v.s); - return this; - } - - mul(v: Readonly) { - mul3(this.buf, v.buf, this.i, v.i, this.s, v.s); - return this; - } - - div(v: Readonly) { - div3(this.buf, v.buf, this.i, v.i, this.s, v.s); - return this; - } - - addN(n: number) { - addN3(this.buf, n, this.i, this.s); - return this; - } - - subN(n: number) { - subN3(this.buf, n, this.i, this.s); - return this; - } - - mulN(n: number) { - mulN3(this.buf, n, this.i, this.s); - return this; - } - - divN(n: number) { - divN3(this.buf, n, this.i, this.s); - return this; - } - - addNew(b: Readonly, out?: Vec3) { - !out && (out = new Vec3([])); - add3o(out.buf, this.buf, b.buf, out.i, this.i, b.i, out.s, this.s, b.s); - return out; - } - - subNew(b: Readonly, out?: Vec3) { - !out && (out = new Vec3([])); - sub3o(out.buf, this.buf, b.buf, out.i, this.i, b.i, out.s, this.s, b.s); - return out; - } - - mulNew(b: Readonly, out?: Vec3) { - !out && (out = new Vec3([])); - mul3o(out.buf, this.buf, b.buf, out.i, this.i, b.i, out.s, this.s, b.s); - return out; - } - - divNew(b: Readonly, out?: Vec3) { - !out && (out = new Vec3([])); - div3o(out.buf, this.buf, b.buf, out.i, this.i, b.i, out.s, this.s, b.s); - return out; - } - - addNewN(n: number, out?: Vec3) { - !out && (out = new Vec3([])); - addN3o(out.buf, this.buf, n, out.i, this.i, out.s, this.s); - return out; - } - - subNewN(n: number, out?: Vec3) { - !out && (out = new Vec3([])); - subN3o(out.buf, this.buf, n, out.i, this.i, out.s, this.s); - return out; - } - - mulNewN(n: number, out?: Vec3) { - !out && (out = new Vec3([])); - mulN3o(out.buf, this.buf, n, out.i, this.i, out.s, this.s); - return out; - } - - divNewN(n: number, out?: Vec3) { - !out && (out = new Vec3([])); - divN3o(out.buf, this.buf, n, out.i, this.i, out.s, this.s); - return out; - } - - maddNew(b: Readonly, c: Readonly, out?: Vec3) { - out = out ? out.set(this) : this.copy(); - madd3(out.buf, b.buf, c.buf, out.i, b.i, c.i, out.s, b.s, c.s); - return out; - } - - maddNewN(b: Readonly, n: number, out?: Vec3) { - out = out ? out.set(this) : this.copy(); - maddN3(out.buf, b.buf, n, out.i, b.i, out.s, b.s); - return out; - } - - msubNew(b: Readonly, c: Readonly, out?: Vec3) { - out = out ? out.set(this) : this.copy(); - msub3(out.buf, b.buf, c.buf, out.i, b.i, c.i, out.s, b.s, c.s); - return out; - } - - msubNewN(b: Readonly, n: number, out?: Vec3) { - out = out ? out.set(this) : this.copy(); - msubN3(out.buf, b.buf, n, out.i, b.i, out.s, b.s); - return out; - } - - mixNew(b: Readonly, t: Readonly, out?: Vec3) { - !out && (out = new Vec3([])); - mix3o(out.buf, this.buf, b.buf, t.buf, out.i, this.i, b.i, t.i, out.s, this.s, b.s, t.s); - return out; - } - - mixNewN(b: Readonly, n = 0.5, out?: Vec3) { - !out && (out = new Vec3([])); - mixN3o(out.buf, this.buf, b.buf, n, out.i, this.i, b.i, out.s, this.s, b.s); - return out; - } - - neg() { - mulN3(this.buf, -1, this.i, this.s); - return this; - } - - abs() { - abs3(this.buf, this.i, this.s); - return this; - } - - sign() { - sign3(this.buf, this.i, this.s); - return this; - } - - floor() { - floor3(this.buf, this.i, this.s); - return this; - } - - ceil() { - ceil3(this.buf, this.i, this.s); - return this; - } - - fract() { - fract3(this.buf, this.i, this.s); - return this; - } - - sqrt() { - sqrt3(this.buf, this.i, this.s); - return this; - } - - pow(v: Readonly) { - pow3(this.buf, v.buf, this.i, v.i, this.s, v.s); - return this; - } - - powN(n: number) { - powN3(this.buf, n, this.i, this.s); - return this; - } - - sin() { - sin3(this.buf, this.i, this.s); - return this; - } - - cos() { - cos3(this.buf, this.i, this.s); - return this; - } - - madd(b: Readonly, c: Readonly) { - madd3(this.buf, b.buf, c.buf, this.i, b.i, c.i, this.s, b.s, c.s); - return this; - } - - maddN(b: Readonly, n: number) { - maddN3(this.buf, b.buf, n, this.i, b.i, this.s, b.s); - return this; - } - - msub(b: Readonly, c: Readonly) { - msub3(this.buf, b.buf, c.buf, this.i, b.i, c.i, this.s, b.s, c.s); - return this; - } - - msubN(b: Readonly, n: number) { - msubN3(this.buf, b.buf, n, this.i, b.i, this.s, b.s); - return this; - } - - mix(b: Readonly, c: Readonly) { - mix3(this.buf, b.buf, c.buf, this.i, b.i, c.i, this.s, b.s, c.s); - return this; - } - - mixN(b: Readonly, n = 0.5) { - mixN3(this.buf, b.buf, n, this.i, b.i, this.s, b.s); - return this; - } - - min(v: Readonly) { - min3(this.buf, v.buf, this.i, v.i, this.s, v.s); - return this; - } - - max(v: Readonly) { - max3(this.buf, v.buf, this.i, v.i, this.s, v.s); - return this; - } - - clamp(min: Readonly, max: Readonly) { - clamp3(this.buf, min.buf, max.buf, this.i, min.i, max.i, this.s, min.s, max.s); - return this; - } - - minorAxis() { - return minorAxis3(this.buf, this.i, this.s); - } - - majorAxis() { - return majorAxis3(this.buf, this.i, this.s); - } - - step(e: Readonly) { - step3(this.buf, e.buf, this.i, e.i, this.s, e.s); - return this; - } - - smoothStep(e1: Readonly, e2: Readonly) { - smoothStep3(this.buf, e1.buf, e2.buf, this.i, e1.i, e2.i, this.s, e1.s, e2.s); - return this; - } - - dot(v: Readonly) { - return dot3(this.buf, v.buf, this.i, v.i, this.s, v.s); - } - - cross(v: Readonly) { - cross3(this.buf, v.buf, this.i, v.i, this.s, v.s); - return this; - } - - orthoNormal(v: Readonly) { - return this.cross(v).normalize(); - } - - mag() { - return mag3(this.buf, this.i, this.s); - } - - magSq() { - return magSq3(this.buf, this.i, this.s); - } - - dist(v: Readonly) { - return dist3(this.buf, v.buf, this.i, v.i, this.s, v.s); - } - - distSq(v: Readonly) { - return distSq3(this.buf, v.buf, this.i, v.i, this.s, v.s); - } - - distManhattan(v: Readonly) { - return distManhattan3(this.buf, v.buf, this.i, v.i, this.s, v.s); - } - - distChebyshev(v: Readonly) { - return distChebyshev3(this.buf, v.buf, this.i, v.i, this.s, v.s); - } - - normalize(len = 1) { - normalize3(this.buf, len, this.i, this.s); - return this; - } - - limit(len: number) { - limit3(this.buf, len, this.i, this.s); - return this; - } - - reflect(n: Readonly) { - reflect3(this.buf, n.buf, this.i, n.i, this.s, n.s); - return this; - } - - refract(n: Readonly, eta: number) { - refract3(this.buf, n.buf, eta, this.i, n.i, this.s, n.s); - return this; - } - - rotateX(theta: number) { - rotateX3(this.buf, theta, this.i, this.s); - return this; - } - - rotateY(theta: number) { - rotateY3(this.buf, theta, this.i, this.s); - return this; - } - - rotateZ(theta: number) { - rotateZ3(this.buf, theta, this.i, this.s); - return this; - } - - rotateAroundAxis(axis: Vec3, theta: number) { - rotateAroundAxis3(this.buf, axis.buf, theta, this.i, axis.i, this.s, axis.s); - return this; - } - - headingXY() { - return headingXY3(this.buf, this.i, this.s); - } - - headingXZ() { - return headingXZ3(this.buf, this.i, this.s); - } - - headingYZ() { - return headingYZ3(this.buf, this.i, this.s); - } - - angleBetween(v: Readonly, normalize = false) { - return angleBetween3(this.buf, v.buf, normalize, this.i, v.i, this.s, v.s); - } - - toPolar() { - toPolar3(this.buf, this.i, this.s); - return this; - } - - toCartesian(o: Readonly = Vec3.ZERO) { - toCartesian3(this.buf, o.buf, this.i, o.i, this.s, o.s); - return this; + empty() { + return new Vec3(); } - toCylindrical() { - toCylindrical3(this.buf, this.i, this.s); - return this; + eqDelta(v: ReadonlyVec, eps = EPS) { + return eqDelta3(this, v, eps); } - fromCylindrical(o: Readonly = Vec3.ZERO) { - fromCylindrical3(this.buf, o.buf, this.i, o.i, this.s, o.s); - return this; + toJSON() { + return [this.x, this.y, this.z]; } toString() { - const i = this.i; - const s = this.s; - return `[${this.buf[i]}, ${this.buf[i + s]}, ${this.buf[i + 2 * s]}]`; - } - - toJSON() { - return this.array(); + return `[${this.x}, ${this.y}, ${this.z}]`; } } declareIndices(Vec3.prototype, ["x", "y", "z"]); + +export const vec3 = + (x = 0, y = 0, z = 0) => new Vec3([x, y, z]); + +export const vec3n = + (n: number) => new Vec3([n, n, n]); + +export const asVec3 = + (x: Vec) => + x instanceof Vec3 ? + x : + new Vec3(x.length >= 3 ? x : [x[0] || 0, x[1] || 0, x[2] || 0]); diff --git a/packages/vectors/src/vec4.ts b/packages/vectors/src/vec4.ts index 310f1ca4a8..dc5e27059f 100644 --- a/packages/vectors/src/vec4.ts +++ b/packages/vectors/src/vec4.ts @@ -1,307 +1,46 @@ -import { isArrayLike } from "@thi.ng/checks/is-arraylike"; -import { EPS } from "@thi.ng/math/api"; -import { eqDelta } from "@thi.ng/math/eqdelta"; -import { max4id, min4id } from "@thi.ng/math/interval"; -import { mixBilinear } from "@thi.ng/math/mix"; -import { fract } from "@thi.ng/math/prec"; -import { smoothStep, step } from "@thi.ng/math/step"; +import { EPS } from "@thi.ng/math"; import { - IVec, IVector, MAX4, MIN4, ONE4, ReadonlyVec, Vec, - Vec4Coord, - W4, X4, Y4, Z4, ZERO4 } from "./api"; -import { declareIndices, defcommon } from "./codegen"; -import { $iter } from "./common"; - -export const op4 = (fn: (x: number) => number, a: Vec, ia = 0, sa = 1) => ( - a[ia] = fn(a[ia]), - a[ia + sa] = fn(a[ia + sa]), - a[ia + 2 * sa] = fn(a[ia + 2 * sa]), - a[ia + 3 * sa] = fn(a[ia + 3 * sa]), - a -); - -export const op40 = (fn: () => number, a: Vec, ia = 0, sa = 1) => ( - a[ia] = fn(), - a[ia + sa] = fn(), - a[ia + 2 * sa] = fn(), - a[ia + 3 * sa] = fn(), - a -); - -export const op41 = (fn: (a: number, n: number) => number, a: Vec, n: number, ia = 0, sa = 1) => ( - a[ia] = fn(a[ia], n), - a[ia + sa] = fn(a[ia + sa], n), - a[ia + 2 * sa] = fn(a[ia + 2 * sa], n), - a[ia + 3 * sa] = fn(a[ia + 3 * sa], n), - a -); - -export const get4 = (a: ReadonlyVec, ia = 0, sa = 1) => - set4(new ((a.constructor))(4), a, 0, ia, 1, sa); - -export const setS4 = (a: Vec, x: number, y: number, z: number, w: number, ia = 0, sa = 1) => ( - a[ia] = x, - a[ia + sa] = y, - a[ia + 2 * sa] = z, - a[ia + 3 * sa] = w, - a -); - -export const randNorm4 = (a: Vec, n = 1, ia = 0, sa = 1) => - randMinMax4(a, -n, n, ia, sa); - -export const randMinMax4 = (a: Vec, min: number, max: number, ia = 0, sa = 1) => { - const d = max - min; - return op40(() => min + d * Math.random(), a, ia, sa); -}; - -export const jitter4 = (a: Vec, n: number, ia = 0, sa = 1) => - op4((x) => x + Math.random() * 2 * n - n, a, ia, sa); - -export const swizzle4 = (a: Vec, b: ReadonlyVec, x: number, y: number, z: number, w: number, ia = 0, ib = 0, sa = 1, sb = 1) => - setS4(a, b[ib + x * sb], b[ib + y * sb], b[ib + z * sb], b[ib + w * sb], ia, sa); - -export const swap4 = (a: Vec, b: Vec, ia = 0, ib = 0, sa = 1, sb = 1) => { - let t = a[ia]; a[ia] = b[ib]; b[ib] = t; - ia += sa; ib += sb; - t = a[ia]; a[ia] = b[ib]; b[ib] = t; - ia += sa; ib += sb; - t = a[ia]; a[ia] = b[ib]; b[ib] = t; - ia += sa; ib += sb; - t = a[ia]; a[ia] = b[ib]; b[ib] = t; - return a; -}; - -export const equiv4 = (a: ReadonlyVec, b: ReadonlyVec, ia = 0, ib = 0, sa = 1, sb = 1) => - a[ia] === b[ib] && - a[ia + sa] === b[ib + sb] && - a[ia + 2 * sa] === b[ib + 2 * sb] && - a[ia + 3 * sa] === b[ib + 3 * sb]; - -export const eqDelta4 = (a: ReadonlyVec, b: ReadonlyVec, eps = EPS, ia = 0, ib = 0, sa = 1, sb = 1) => - eqDelta(a[ia], b[ib], eps) && - eqDelta(a[ia + sa], b[ib + sb], eps) && - eqDelta(a[ia + 2 * sa], b[ib + 2 * sb], eps) && - eqDelta(a[ia + 3 * sa], b[ib + 3 * sb], eps); - -export const eqDelta4buf = (a: ReadonlyVec, b: ReadonlyVec, num: number, eps = EPS, ia = 0, ib = 0, sca = 1, scb = 1, sea = 4, seb = 4) => { - while (--num >= 0) { - if (!eqDelta4(a, b, eps, ia + num * sea, ib + num * seb, sca, scb)) { - return false; - } - } - return true; -}; - -export const eqDelta4array = (a: ReadonlyVec[], b: ReadonlyVec[], eps = EPS) => { - const na = a.length; - if (b.length !== na) { - return false; - } - for (let i = 0; i < na; i++) { - if (!eqDelta4(a[i], b[i], eps)) { - return false; - } - } - return true; -}; - -export const compare4 = ( - a: ReadonlyVec, - b: ReadonlyVec, - o1: Vec4Coord, o2: Vec4Coord, o3: Vec4Coord, o4: Vec4Coord, - ia = 0, ib = 0, sa = 1, sb = 1): number => { - - const ax = a[ia + o1 * sa]; - const ay = a[ia + o2 * sa]; - const az = a[ia + o3 * sa]; - const aw = b[ia + o4 * sa]; - const bx = b[ib + o1 * sb]; - const by = b[ib + o2 * sb]; - const bz = b[ib + o3 * sb]; - const bw = b[ib + o4 * sb]; - return ax === bx ? - ay === by ? - az === bz ? - aw === bw ? - 0 : - aw < bw ? -4 : 4 : - az < bz ? -3 : 3 : - ay < by ? -2 : 2 : - ax < bx ? -1 : 1; -}; - -export const collate4 = (buf: Vec, src: Iterable, start = 0, cstride = 1, estride = 4) => { - for (let v of src) { - set4(buf, v, start, 0, cstride, 1); - start += estride; - } - return buf; -}; - -export const [ - set4, setN4, - add4, sub4, mul4, div4, - add4o, sub4o, mul4o, div4o, - addN4, subN4, mulN4, divN4, - addN4o, subN4o, mulN4o, divN4o, - madd4, maddN4, msub4, msubN4, - abs4, sign4, floor4, ceil4, sin4, cos4, sqrt4, - pow4, min4, max4, - mix4, mixN4, mix4o, mixN4o -] = defcommon(4); - -export const neg4 = (a: Vec, ia = 0, sa = 1) => - mulN4(a, -1, ia, sa); - -export const fract4 = (a: Vec, ia = 0, sa = 1) => - op4(fract, a, ia, sa); - -export const powN4 = (a: Vec, n: number, ia = 0, sa = 1) => - op41(Math.pow, a, n, ia, sa); - -export const dot4 = (a: ReadonlyVec, b: ReadonlyVec, ia = 0, ib = 0, sa = 1, sb = 1) => - a[ia] * b[ib] + - a[ia + sa] * b[ib + sb] + - a[ia + 2 * sa] * b[ib + 2 * sb] + - a[ia + 3 * sa] * b[ib + 3 * sb]; - -export const mixBilinear4 = ( - a: Vec, b: ReadonlyVec, c: ReadonlyVec, d: ReadonlyVec, u: number, v: number, - ia = 0, ib = 0, ic = 0, id = 0, - sa = 1, sb = 1, sc = 1, sd = 1) => ( - a[ia] = mixBilinear(a[ia], b[ib], c[ic], d[id], u, v), - a[ia + sa] = mixBilinear(a[ia + sa], b[ib + sb], c[ic + sc], d[id + sd], u, v), - a[ia + 2 * sa] = mixBilinear(a[ia + 2 * sa], b[ib + 2 * sb], c[ic + 2 * sc], d[id + 2 * sd], u, v), - a[ia + 3 * sa] = mixBilinear(a[ia + 3 * sa], b[ib + 3 * sb], c[ic + 3 * sc], d[id + 3 * sd], u, v), - a - ); - -export const clamp4 = (a: Vec, min: ReadonlyVec, max: ReadonlyVec, ia = 0, imin = 0, imax = 0, sa = 1, smin = 1, smax = 1) => - max4(min4(a, max, ia, imax, sa, smax), min, ia, imin, sa, smin); - -export const step4 = (a: Vec, e: ReadonlyVec, ia = 0, ie = 0, sa = 1, se = 1) => ( - a[ia] = step(e[ie], a[ia]), - a[ia + sa] = step(e[ie + se], a[ia + sa]), - a[ia + 2 * sa] = step(e[ie + 2 * se], a[ia + 2 * sa]), - a[ia + 3 * sa] = step(e[ie + 3 * se], a[ia + 3 * sa]), - a -); - -export const smoothStep4 = (a: Vec, e1: ReadonlyVec, e2: ReadonlyVec, ia = 0, ie1 = 0, ie2 = 0, sa = 1, se1 = 1, se2 = 1) => ( - a[ia] = smoothStep(e1[ie1], e2[ie2], a[ia]), - a[ia + sa] = smoothStep(e1[ie1 + se1], e2[ie2 + se2], a[ia + sa]), - a[ia + 2 * sa] = smoothStep(e1[ie1 + 2 * se1], e2[ie2 + 2 * se2], a[ia + 2 * sa]), - a[ia + 3 * sa] = smoothStep(e1[ie1 + 3 * se1], e2[ie2 + 2 * se2], a[ia + 3 * sa]), - a -); - -export const magSq4 = (a: ReadonlyVec, ia = 0, sa = 1) => { - const x = a[ia]; - const y = a[ia + sa]; - const z = a[ia + 2 * sa]; - const w = a[ia + 3 * sa]; - return x * x + y * y + z * z + w * w; -}; - -export const mag4 = (a: ReadonlyVec, ia = 0, sa = 1) => - Math.sqrt(magSq4(a, ia, sa)); - -export const distSq4 = (a: ReadonlyVec, b: ReadonlyVec, ia = 0, ib = 0, sa = 1, sb = 1) => { - const x = a[ia] - b[ib]; - const y = a[ia + sa] - b[ib + sb]; - const z = a[ia + 2 * sa] - b[ib + 2 * sb]; - const w = a[ia + 3 * sa] - b[ib + 3 * sb]; - return x * x + y * y + z * z + w * w; -}; - -export const dist4 = (a: ReadonlyVec, b: ReadonlyVec, ia = 0, ib = 0, sa = 1, sb = 1) => - Math.sqrt(distSq4(a, b, ia, ib, sa, sb)); - -export const distManhattan4 = (a: ReadonlyVec, b: ReadonlyVec, ia = 0, ib = 0, sa = 1, sb = 1) => - Math.abs(a[ia] - b[ib]) + - Math.abs(a[ia + sa] - b[ib + sb]) + - Math.abs(a[ia + 2 * sa] - b[ib + 2 * sb]) + - Math.abs(a[ia + 3 * sa] - b[ib + 3 * sb]); - -export const distChebyshev4 = (a: ReadonlyVec, b: ReadonlyVec, ia = 0, ib = 0, sa = 1, sb = 1) => - Math.max( - Math.abs(a[ia] - b[ib]), - Math.abs(a[ia + sa] - b[ib + sb]), - Math.abs(a[ia + 2 * sa] - b[ib + 2 * sb]), - Math.abs(a[ia + 3 * sa] - b[ib + 3 * sb]) - ); - -export const normalize4 = (a: Vec, n = 1, ia = 0, sa = 1) => { - const m = mag4(a, ia, sa); - m >= EPS && mulN4(a, n / m, ia, sa); - return a; -}; - -export const limit4 = (a: Vec, n: number, ia = 0, sa = 1) => { - const m = mag4(a, ia, sa); - m >= n && mulN4(a, n / m, ia, sa); - return a; -}; - -export const reflect4 = (a: Vec, b: ReadonlyVec, ia = 0, ib = 0, sa = 1, sb = 1) => - maddN4(a, b, -2 * dot4(a, b, ia, ib, sa, sb), ia, ib, sa, sb); - -export const refract4 = (a: Vec, b: ReadonlyVec, eta: number, ia = 0, ib = 0, sa = 1, sb = 1) => { - const d = dot4(a, b, ia, ib, sa, sb); - const k = 1 - eta * eta * (1 - d * d); - return k < 0 ? - setN4(a, 0, ia, sa) : - msubN4(mulN4(a, eta, ia, sa), b, eta * d + Math.sqrt(k), ia, ib, sa, sb); -}; - -export const minorAxis4 = (a: Vec, ia = 0, sa = 1) => - min4id(Math.abs(a[ia]), Math.abs(a[ia + sa]), Math.abs(a[ia + 2 * sa]), Math.abs(a[ia + 3 * sa])); - -export const majorAxis4 = (a: Vec, ia = 0, sa = 1) => - max4id(Math.abs(a[ia]), Math.abs(a[ia + sa]), Math.abs(a[ia + 2 * sa]), Math.abs(a[ia + 3 * sa])); - -export const vec4 = (x = 0, y = 0, z = 0, w = 0) => - new Vec4([x, y, z, w]); - -export const asVec4 = (x: ReadonlyVec) => - x instanceof Vec4 ? x : new Vec4([x[0] || 0, x[1] || 0, x[2] || 0, x[3] || 0]); - -export class Vec4 implements +import { eqDelta4 } from "./eqdelta"; +import { declareIndices } from "./internal/accessors"; +import { AVec } from "./internal/avec"; +import { + intoBuffer, + mapBuffer, + values, + vecIterator +} from "./internal/vec-utils"; +import { setS4 } from "./sets"; + +export class Vec4 extends AVec implements IVector { /** * Returns array of memory mapped `Vec4` instances using given * backing array and stride settings: The `cstride` is the step size - * between individual XYZW vector components. `estride` is the step + * between individual XYZ vector components. `estride` is the step * size between successive vectors. This arrangement allows for * different storage approaches, incl. SOA, AOS, striped / * interleaved etc. * * @param buf backing array - * @param n num vectors + * @param num num vectors * @param start start index * @param cstride component stride * @param estride element stride */ - static mapBuffer(buf: Vec, n = buf.length >> 2, start = 0, cstride = 1, estride = 4) { - const res: Vec4[] = []; - while (--n >= 0) { - res.push(new Vec4(buf, start, cstride)); - start += estride; - } - return res; + static mapBuffer(buf: Vec, num: number = buf.length >> 2, start = 0, cstride = 1, estride = 4) { + return mapBuffer(Vec4, buf, num, start, cstride, estride); } /** @@ -310,7 +49,7 @@ export class Vec4 implements * strides, starting at `start` index. It's the user's * responsibility to ensure the target buffer has sufficient * capacity to hold the input vectors. See `Vec4.mapBuffer` for the - * reverse operation. Returns buffer. + * inverse operation. Returns `buf`. * * @param buf * @param src @@ -318,69 +57,34 @@ export class Vec4 implements * @param cstride * @param estride */ - static intoBuffer(buf: Vec, src: Iterable>, start = 0, cstride = 1, estride = 4) { - for (let v of src) { - set4(buf, v.buf, start, v.i, cstride, v.s); - start += estride; - } - return buf; + static intoBuffer(buf: Vec, src: Iterable, start = 0, cstride = 1, estride = 4) { + return intoBuffer(setS4, buf, src, start, cstride, estride); } - static swizzle(v: IVec, x: number, y: number, z: number, w: number) { - return new Vec4([]).swizzle(v, x, y, z, w); + static *iterator(buf: Vec, num: number, start = 0, cstride = 1, estride = 4) { + return vecIterator(Vec4, buf, num, start, cstride, estride); } - static mixBilinear(a: Readonly, b: Readonly, c: Readonly, d: Readonly, u: number, v: number) { - return new Vec4( - mixBilinear4( - get4(a.buf, a.i, a.s), b.buf, c.buf, d.buf, u, v, - 0, b.i, c.i, d.i, - 1, b.s, c.s, d.s - ) - ); - } + static readonly X_AXIS = new Vec4(X4); + static readonly Y_AXIS = new Vec4(Y4); + static readonly Z_AXIS = new Vec4(Z4); + static readonly MIN = new Vec4(MIN4); + static readonly MAX = new Vec4(MAX4); + static readonly ZERO = new Vec4(ZERO4); + static readonly ONE = new Vec4(ONE4); - static randNorm(n = 1) { - return new Vec4(randNorm4([], n)); - } - - static random(min: number, max: number) { - return new Vec4(randMinMax4([], min, max)); - } - - static comparator(o1: Vec4Coord, o2: Vec4Coord, o3: Vec4Coord, o4: Vec4Coord) { - return (a: Readonly, b: Readonly) => a.compare(b, o1, o2, o3, o4); - } - - static readonly ZERO = Object.freeze(new Vec4(ZERO4)); - static readonly ONE = Object.freeze(new Vec4(ONE4)); - static readonly MIN = Object.freeze(new Vec4(MIN4)); - static readonly MAX = Object.freeze(new Vec4(MAX4)); - static readonly X_AXIS = Object.freeze(new Vec4(X4)); - static readonly Y_AXIS = Object.freeze(new Vec4(Y4)); - static readonly Z_AXIS = Object.freeze(new Vec4(Z4)); - static readonly W_AXIS = Object.freeze(new Vec4(W4)); - buf: Vec; - i: number; - s: number; x: number; y: number; z: number; w: number; [id: number]: number; - constructor(buf?: Vec, index = 0, stride = 1) { - this.buf = buf || [0, 0, 0, 0]; - this.i = index; - this.s = stride; + constructor(buf?: Vec, offset = 0, stride = 1) { + super(buf || [0, 0, 0, 0], offset, stride); } [Symbol.iterator]() { - return $iter(this.buf, 4, this.i, this.s); - } - - array() { - return get4(this.buf, this.i, this.s); + return values(this.buf, 4, this.offset, this.stride); } get length() { @@ -388,358 +92,44 @@ export class Vec4 implements } copy() { - return new Vec4(get4(this.buf, this.i, this.s)); - } - - empty() { - return new Vec4(); - } - - equiv(v: any) { - return v instanceof Vec4 ? - equiv4(this.buf, v.buf, this.i, v.i, this.s, v.s) : - isArrayLike(v) && v.length === 4 ? - equiv4(this.buf, v, this.i, 0, this.s, 1) : - false; - } - - eqDelta(v: Readonly, eps = EPS) { - return eqDelta4(this.buf, v.buf, eps, this.i, v.i, this.s, v.s); - } - - compare(v: Readonly, o1: Vec4Coord = 0, o2: Vec4Coord = 1, o3: Vec4Coord = 2, o4: Vec4Coord = 3) { - return compare4(this.buf, v.buf, o1, o2, o3, o4, this.i, v.i, this.s, v.s); - } - - set(v: Readonly) { - set4(this.buf, v.buf, this.i, v.i, this.s, v.s); - return this; - } - - setN(n: number) { - setN4(this.buf, n, this.i, this.s); - return this; - } - - setS(x: number, y: number, z: number, w: number) { - setS4(this.buf, x, y, z, w, this.i, this.s); - return this; - } - - jitter(n = 1) { - jitter4(this.buf, n, this.i, this.s); - return this; - } - - swizzle(v: IVec, x: number, y: number, z: number, w: number) { - swizzle4(this.buf, v.buf, x, y, z, w, this.i, v.i, this.s, v.s); - return this; - } - - swap(v: Vec4) { - swap4(this.buf, v.buf, this.i, v.i, this.s, v.s); - return this; - } - - add(v: Readonly) { - add4(this.buf, v.buf, this.i, v.i, this.s, v.s); - return this; - } - - sub(v: Readonly) { - sub4(this.buf, v.buf, this.i, v.i, this.s, v.s); - return this; - } - - mul(v: Readonly) { - mul4(this.buf, v.buf, this.i, v.i, this.s, v.s); - return this; - } - - div(v: Readonly) { - div4(this.buf, v.buf, this.i, v.i, this.s, v.s); - return this; - } - - addN(n: number) { - addN4(this.buf, n, this.i, this.s); - return this; - } - - subN(n: number) { - subN4(this.buf, n, this.i, this.s); - return this; - } - - mulN(n: number) { - mulN4(this.buf, n, this.i, this.s); - return this; - } - - divN(n: number) { - divN4(this.buf, n, this.i, this.s); - return this; - } - - addNew(b: Readonly, out?: Vec4) { - !out && (out = new Vec4([])); - add4o(out.buf, this.buf, b.buf, out.i, this.i, b.i, out.s, this.s, b.s); - return out; + return new Vec4([this.x, this.y, this.z, this.w]); } - subNew(b: Readonly, out?: Vec4) { - !out && (out = new Vec4([])); - sub4o(out.buf, this.buf, b.buf, out.i, this.i, b.i, out.s, this.s, b.s); - return out; + copyView() { + return new Vec4(this.buf, this.offset, this.stride); } - mulNew(b: Readonly, out?: Vec4) { - !out && (out = new Vec4([])); - mul4o(out.buf, this.buf, b.buf, out.i, this.i, b.i, out.s, this.s, b.s); - return out; - } - - divNew(b: Readonly, out?: Vec4) { - !out && (out = new Vec4([])); - div4o(out.buf, this.buf, b.buf, out.i, this.i, b.i, out.s, this.s, b.s); - return out; - } - - addNewN(n: number, out?: Vec4) { - !out && (out = new Vec4([])); - addN4o(out.buf, this.buf, n, out.i, this.i, out.s, this.s); - return out; - } - - subNewN(n: number, out?: Vec4) { - !out && (out = new Vec4([])); - subN4o(out.buf, this.buf, n, out.i, this.i, out.s, this.s); - return out; - } - - mulNewN(n: number, out?: Vec4) { - !out && (out = new Vec4([])); - mulN4o(out.buf, this.buf, n, out.i, this.i, out.s, this.s); - return out; - } - - divNewN(n: number, out?: Vec4) { - !out && (out = new Vec4([])); - divN4o(out.buf, this.buf, n, out.i, this.i, out.s, this.s); - return out; - } - - maddNew(b: Readonly, c: Readonly, out?: Vec4) { - out = out ? out.set(this) : this.copy(); - madd4(out.buf, b.buf, c.buf, out.i, b.i, c.i, out.s, b.s, c.s); - return out; - } - - maddNewN(b: Readonly, n: number, out?: Vec4) { - out = out ? out.set(this) : this.copy(); - maddN4(out.buf, b.buf, n, out.i, b.i, out.s, b.s); - return out; - } - - msubNew(b: Readonly, c: Readonly, out?: Vec4) { - out = out ? out.set(this) : this.copy(); - msub4(out.buf, b.buf, c.buf, out.i, b.i, c.i, out.s, b.s, c.s); - return out; - } - - msubNewN(b: Readonly, n: number, out?: Vec4) { - out = out ? out.set(this) : this.copy(); - msubN4(out.buf, b.buf, n, out.i, b.i, out.s, b.s); - return out; - } - - mixNew(b: Readonly, t: Readonly, out?: Vec4) { - !out && (out = new Vec4([])); - mix4o(out.buf, this.buf, b.buf, t.buf, out.i, this.i, b.i, t.i, out.s, this.s, b.s, t.s); - return out; - } - - mixNewN(b: Readonly, n = 0.5, out?: Vec4) { - !out && (out = new Vec4([])); - mixN4o(out.buf, this.buf, b.buf, n, out.i, this.i, b.i, out.s, this.s, b.s); - return out; - } - - neg() { - mulN4(this.buf, -1, this.i, this.s); - return this; - } - - abs() { - abs4(this.buf, this.i, this.s); - return this; - } - - sign() { - sign4(this.buf, this.i, this.s); - return this; - } - - floor() { - floor4(this.buf, this.i, this.s); - return this; - } - - ceil() { - ceil4(this.buf, this.i, this.s); - return this; - } - - fract() { - fract4(this.buf, this.i, this.s); - return this; - } - - sqrt() { - sqrt4(this.buf, this.i, this.s); - return this; - } - - pow(v: Readonly) { - pow4(this.buf, v.buf, this.i, v.i, this.s, v.s); - return this; - } - - powN(n: number) { - powN4(this.buf, n, this.i, this.s); - return this; - } - - sin() { - sin4(this.buf, this.i, this.s); - return this; - } - - cos() { - cos4(this.buf, this.i, this.s); - return this; - } - - madd(b: Readonly, c: Readonly) { - madd4(this.buf, b.buf, c.buf, this.i, b.i, c.i, this.s, b.s, c.s); - return this; - } - - maddN(b: Readonly, n: number) { - maddN4(this.buf, b.buf, n, this.i, b.i, this.s, b.s); - return this; - } - - msub(b: Readonly, c: Readonly) { - msub4(this.buf, b.buf, c.buf, this.i, b.i, c.i, this.s, b.s, c.s); - return this; - } - - msubN(b: Readonly, n: number) { - msubN4(this.buf, b.buf, n, this.i, b.i, this.s, b.s); - return this; - } - - mix(b: Readonly, c: Readonly) { - mix4(this.buf, b.buf, c.buf, this.i, b.i, c.i, this.s, b.s, c.s); - return this; - } - - mixN(b: Readonly, n = 0.5) { - mixN4(this.buf, b.buf, n, this.i, b.i, this.s, b.s); - return this; - } - - min(v: Readonly) { - min4(this.buf, v.buf, this.i, v.i, this.s, v.s); - return this; - } - - max(v: Readonly) { - max4(this.buf, v.buf, this.i, v.i, this.s, v.s); - return this; - } - - clamp(min: Readonly, max: Readonly) { - clamp4(this.buf, min.buf, max.buf, this.i, min.i, max.i, this.s, min.s, max.s); - return this; - } - - minorAxis() { - return minorAxis4(this.buf, this.i, this.s); - } - - majorAxis() { - return majorAxis4(this.buf, this.i, this.s); - } - - step(e: Readonly) { - step4(this.buf, e.buf, this.i, e.i, this.s, e.s); - return this; - } - - smoothStep(e1: Readonly, e2: Readonly) { - smoothStep4(this.buf, e1.buf, e2.buf, this.i, e1.i, e2.i, this.s, e1.s, e2.s); - return this; - } - - dot(v: Readonly) { - return dot4(this.buf, v.buf, this.i, v.i, this.s, v.s); - } - - mag() { - return mag4(this.buf, this.i, this.s); - } - - magSq() { - return magSq4(this.buf, this.i, this.s); - } - - dist(v: Readonly) { - return dist4(this.buf, v.buf, this.i, v.i, this.s, v.s); - } - - distSq(v: Readonly) { - return distSq4(this.buf, v.buf, this.i, v.i, this.s, v.s); - } - - distManhattan(v: Readonly) { - return distManhattan4(this.buf, v.buf, this.i, v.i, this.s, v.s); - } - - distChebyshev(v: Readonly) { - return distChebyshev4(this.buf, v.buf, this.i, v.i, this.s, v.s); - } - - normalize(len = 1) { - normalize4(this.buf, len, this.i, this.s); - return this; - } - - limit(len: number) { - limit4(this.buf, len, this.i, this.s); - return this; + empty() { + return new Vec4(); } - reflect(n: Readonly) { - reflect4(this.buf, n.buf, this.i, n.i, this.s, n.s); - return this; + eqDelta(v: ReadonlyVec, eps = EPS) { + return eqDelta4(this, v, eps); } - refract(n: Readonly, eta: number) { - refract4(this.buf, n.buf, eta, this.i, n.i, this.s, n.s); - return this; + toJSON() { + return [this.x, this.y, this.z, this.w]; } toString() { - const i = this.i; - const s = this.s; - return `[${this.buf[i]}, ${this.buf[i + s]}, ${this.buf[i + 2 * s]}, ${this.buf[i + 3 * s]}]`; - } - - toJSON() { - return this.array(); + return `[${this.x}, ${this.y}, ${this.z}, ${this.w}]`; } } declareIndices(Vec4.prototype, ["x", "y", "z", "w"]); + +export const vec4 = + (x = 0, y = 0, z = 0, w = 0) => new Vec4([x, y, z, w]); + +export const vec4n = + (n: number) => new Vec4([n, n, n, n]); + +export const asVec4 = + (x: Vec) => + x instanceof Vec4 ? + x : + new Vec4( + x.length >= 4 ? + x : + [x[0] || 0, x[1] || 0, x[2] || 0, x[3] || 0] + ); diff --git a/packages/vectors/src/wrap.ts b/packages/vectors/src/wrap.ts new file mode 100644 index 0000000000..50cf460522 --- /dev/null +++ b/packages/vectors/src/wrap.ts @@ -0,0 +1,7 @@ +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"; + +export const [wrap, wrap2, wrap3, wrap4] = + defHofOp(_wrap, HOF_VVV, ARGS_VVV); diff --git a/packages/vectors/test/gvec.ts b/packages/vectors/test/gvec.ts deleted file mode 100644 index 6fb251cc3d..0000000000 --- a/packages/vectors/test/gvec.ts +++ /dev/null @@ -1,82 +0,0 @@ -import * as assert from "assert"; -import * as v from "../src/index"; - -describe("gvec", () => { - - const op2 = (fn, x, y, z, w) => { - assert.deepEqual( - fn([1, 2, 3, 4], [10, 20, 30, 40], 4), - [x, y, z, w] - ); - assert.deepEqual( - fn([0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0], [0, 10, 0, 20, 0, 30, 0, 40, 0], 4, 1, 1, 4, 2), - [0, x, 0, 0, 0, y, 0, 0, 0, z, 0, 0, 0, w, 0, 0] - ); - }; - - const opn = (fn, x, y, z, w) => { - assert.deepEqual( - fn([1, 2, 3, 4], 10, 4), - [x, y, z, w] - ); - assert.deepEqual( - fn([0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0], 10, 4, 1, 4), - [0, x, 0, 0, 0, y, 0, 0, 0, z, 0, 0, 0, w, 0, 0] - ); - }; - - it("add", () => op2(v.add, 11, 22, 33, 44)); - it("sub", () => op2(v.sub, -9, -18, -27, -36)); - it("mul", () => op2(v.mul, 10, 40, 90, 160)); - it("div", () => op2(v.div, 0.1, 0.1, 0.1, 0.1)); - - it("addn", () => opn(v.addN, 11, 12, 13, 14)); - it("subn", () => opn(v.subN, -9, -8, -7, -6)); - it("muln", () => opn(v.mulN, 10, 20, 30, 40)); - it("divn", () => opn(v.divN, 0.1, 0.2, 0.3, 0.4)); - - it("madd", () => { - assert.deepEqual( - v.madd([1, 2, 3, 4], [10, 20, 30, 40], [0.5, 0.25, 0.75, 0.125], 4), - [1 + 10 * 0.5, 2 + 20 * 0.25, 3 + 30 * 0.75, 4 + 40 * 0.125] - ); - assert.deepEqual( - v.madd([1, 2, 3, 4], [10, 0, 20, 0, 30, 0, 40], [0.5, 0, 0, 0.25, 0, 0, 0.75, 0, 0, 0.125], 4, 0, 0, 0, 1, 2, 3), - [1 + 10 * 0.5, 2 + 20 * 0.25, 3 + 30 * 0.75, 4 + 40 * 0.125] - ); - }); - - it("maddn", () => { - assert.deepEqual( - v.maddN([1, 2, 3, 4], [10, 20, 30, 40], 0.5, 4), - [1 + 10 * 0.5, 2 + 20 * 0.5, 3 + 30 * 0.5, 4 + 40 * 0.5] - ); - assert.deepEqual( - v.maddN([1, 2, 3, 4], [10, 0, 20, 0, 30, 0, 40], 0.5, 4, 0, 0, 1, 2), - [1 + 10 * 0.5, 2 + 20 * 0.5, 3 + 30 * 0.5, 4 + 40 * 0.5] - ); - }); - - it("equiv", () => { - const buf = [1, 2, 3, 4, 1, 0, 2, 0, 3, 0, 4]; - assert(v.equiv(buf, buf, 4, 0, 4, 1, 2)); - assert(!v.equiv(buf, buf, 4, 0, 4)); - assert(new v.GVec(buf, 4).equiv(buf.slice(0, 4))); - assert(new v.GVec(buf, 4).equiv(new v.GVec(buf, 4, 4, 2))); - assert(!new v.GVec(buf, 4).equiv(new v.GVec(buf, 4, 4, 1))); - }); - - it("eqdelta", () => { - assert(v.eqDelta([0, 1.001, 0, 1.999, 0, 3.0099, 0, 3.991], [1, 2, 3, 4], 4, 0.01, 1, 0, 2, 1)); - assert(!v.eqDelta([0, 1.001, 0, 1.999, 0, 3.02, 0, 4], [1, 2, 3, 4], 4, 0.01, 1, 0, 2, 1)); - }); - - it("iterator", () => { - assert.deepEqual([...v.gvec(1, 2, 3)], [1, 2, 3]); - assert.deepEqual([...new v.GVec([0, 1, 0, 2, 0, 3], 3, 1, 2)], [1, 2, 3]); - }); - - it("length", () => { - assert.deepEqual(v.gvec(1, 2, 3).length, 3); - }); -}); diff --git a/packages/vectors/test/index.ts b/packages/vectors/test/index.ts new file mode 100644 index 0000000000..d099875f10 --- /dev/null +++ b/packages/vectors/test/index.ts @@ -0,0 +1,6 @@ +// import * as assert from "assert"; +// import * as v from "../src/index"; + +describe("vectors", () => { + it("tests pending"); +}); diff --git a/packages/vectors/test/swizzle.ts b/packages/vectors/test/swizzle.ts deleted file mode 100644 index dbf85f9df9..0000000000 --- a/packages/vectors/test/swizzle.ts +++ /dev/null @@ -1,88 +0,0 @@ -import * as assert from "assert"; -import { Vec2, swizzle2 } from "../src/vec2"; -import { Vec3, swizzle3 } from "../src/vec3"; -import { Vec4, swizzle4 } from "../src/vec4"; - -describe("swizzle", () => { - - it("vec2", () => { - assert.deepEqual( - swizzle2([], [10, 20], 1, 0), - [20, 10] - ); - assert.deepEqual( - swizzle2([], [10, 20], 1, 1), - [20, 20] - ); - assert.deepEqual( - swizzle2([0, 0, 0, 0], [10, 20], 1, 0, 1, 0, 2, 1), - [0, 20, 0, 10] - ); - assert.deepEqual( - swizzle2([], [0, 10, 0, 0, 0, 20], 1, 0, 0, 1, 1, 4), - [20, 10] - ); - assert.deepEqual( - new Vec2([]).swizzle(new Vec2([10, 0, 20, 0], 0, 2), 1, 0).buf, - [20, 10] - ); - assert.deepEqual( - new Vec2([0, 0, 0, 0, 0], 1, 2).swizzle(new Vec2([10, 0, 0, 0, 20, 0, 0, 0], 0, 4), 1, 0).buf, - [0, 20, 0, 10, 0] - ); - }); - - it("vec3", () => { - assert.deepEqual( - swizzle3([], [10, 20, 30], 2, 1, 0), - [30, 20, 10] - ); - assert.deepEqual( - swizzle3([], [10, 20, 30], 1, 1, 1), - [20, 20, 20] - ); - assert.deepEqual( - swizzle3([0, 0, 0, 0, 0, 0], [10, 20, 30], 2, 1, 0, 1, 0, 2, 1), - [0, 30, 0, 20, 0, 10] - ); - assert.deepEqual( - swizzle3([], [0, 10, 0, 0, 0, 20, 0, 0, 0, 30], 2, 1, 0, 0, 1, 1, 4), - [30, 20, 10] - ); - assert.deepEqual( - new Vec3([]).swizzle(new Vec3([10, 0, 20, 0, 30, 0], 0, 2), 2, 1, 0).buf, - [30, 20, 10] - ); - assert.deepEqual( - new Vec3([0, 0, 0, 0, 0, 0, 0], 1, 2).swizzle(new Vec2([10, 0, 0, 0, 20, 0, 0, 0], 0, 4), 1, 1, 0).buf, - [0, 20, 0, 20, 0, 10, 0] - ); - }); - - it("vec4", () => { - assert.deepEqual( - swizzle4([], [10, 20, 30, 40], 3, 2, 1, 0), - [40, 30, 20, 10] - ); - assert.deepEqual( - swizzle4([], [10, 20, 30, 40], 1, 1, 1, 1), - [20, 20, 20, 20] - ); - assert.deepEqual( - swizzle4([0, 0, 0, 0, 0, 0, 0, 0], [10, 20, 30, 40], 3, 2, 1, 0, 1, 0, 2, 1), - [0, 40, 0, 30, 0, 20, 0, 10] - ); - assert.deepEqual( - swizzle4([], [0, 10, 0, 0, 0, 20, 0, 0, 0, 30, 0, 0, 0, 40], 3, 2, 1, 0, 0, 1, 1, 4), - [40, 30, 20, 10] - ); - assert.deepEqual( - new Vec4([]).swizzle(new Vec4([10, 0, 20, 0, 30, 0, 40, 0], 0, 2), 3, 2, 1, 0).buf, - [40, 30, 20, 10] - ); - assert.deepEqual( - new Vec4([0, 0, 0, 0, 0, 0, 0, 0, 0], 1, 2).swizzle(new Vec2([10, 0, 0, 0, 20, 0, 0, 0], 0, 4), 1, 1, 0, 0).buf, - [0, 20, 0, 20, 0, 10, 0, 10, 0] - ); - }); -}); diff --git a/packages/vectors/test/tsconfig.json b/packages/vectors/test/tsconfig.json index bcf29ace54..2c9c12a650 100644 --- a/packages/vectors/test/tsconfig.json +++ b/packages/vectors/test/tsconfig.json @@ -1,10 +1,11 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs", }, "include": [ "./**/*.ts", "../src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/packages/vectors/test/vec2.ts b/packages/vectors/test/vec2.ts deleted file mode 100644 index 79839c71ea..0000000000 --- a/packages/vectors/test/vec2.ts +++ /dev/null @@ -1,103 +0,0 @@ -import * as assert from "assert"; -import * as v from "../src/index"; - -describe("vec2", () => { - - const op2 = (fn, x, y) => { - assert.deepEqual( - fn([1, 2], [10, 20]), - [x, y] - ); - assert.deepEqual( - fn([0, 1, 0, 0, 0, 2, 0, 0], [0, 10, 0, 20, 0], 1, 1, 4, 2), - [0, x, 0, 0, 0, y, 0, 0] - ); - }; - - const opn = (fn, x, y) => { - assert.deepEqual( - fn([1, 2], 10), - [x, y] - ); - assert.deepEqual( - fn([0, 1, 0, 0, 0, 2, 0, 0], 10, 1, 4), - [0, x, 0, 0, 0, y, 0, 0] - ); - }; - - it("add", () => op2(v.add2, 11, 22)); - it("sub", () => op2(v.sub2, -9, -18)); - it("mul", () => op2(v.mul2, 10, 40)); - it("div", () => op2(v.div2, 0.1, 0.1)); - - it("addn", () => opn(v.addN2, 11, 12)); - it("subn", () => opn(v.subN2, -9, -8)); - it("muln", () => opn(v.mulN2, 10, 20)); - it("divn", () => opn(v.divN2, 0.1, 0.2)); - - it("madd", () => { - assert.deepEqual( - v.madd2([1, 2], [10, 20], [0.5, 0.25]), - [1 + 10 * 0.5, 2 + 20 * 0.25] - ); - assert.deepEqual( - v.madd2([1, 2], [10, 0, 20, 0], [0.5, 0, 0, 0.25], 0, 0, 0, 1, 2, 3), - [1 + 10 * 0.5, 2 + 20 * 0.25] - ); - }); - - it("maddn", () => { - assert.deepEqual( - v.maddN2([1, 2], [10, 20], 0.5), - [1 + 10 * 0.5, 2 + 20 * 0.5] - ); - assert.deepEqual( - v.maddN2([1, 2], [10, 0, 20, 0], 0.5, 0, 0, 1, 2), - [1 + 10 * 0.5, 2 + 20 * 0.5] - ); - }); - - it("equiv", () => { - const buf = [1, 2, 1, 0, 2, 0] - assert(v.equiv2(buf, buf, 0, 2, 1, 2)); - assert(!v.equiv2(buf, buf, 0, 2)); - assert(new v.Vec2(buf).equiv(buf.slice(0, 2))); - assert(new v.Vec2(buf).equiv(new v.Vec2(buf, 2, 2))); - assert(!new v.Vec2(buf).equiv(new v.Vec2(buf, 2, 1))); - }); - - it("eqdelta", () => { - assert(v.eqDelta2([0, 1.001, 0, 1.999, 0], [1, 2], 0.01, 1, 0, 2, 1)); - assert(!v.eqDelta2([0, 1.001, 0, 1.989, 0], [1, 2], 0.01, 1, 0, 2, 1)); - }); - - it("iterator", () => { - assert.deepEqual([...new v.Vec2([1, 2])], [1, 2]); - assert.deepEqual([...new v.Vec2([0, 1, 0, 2], 1, 2)], [1, 2]); - }); - - it("arraylike", () => { - const buf = [0, 1, 0, 2]; - const a = new v.Vec2(buf, 1, 2); - assert.equal(a.length, 2); - assert.equal(a[0], 1); - assert.equal(a[1], 2); - a[0] = 10; - a[1] = 20; - assert.equal(a[0], 10); - assert.equal(a[1], 20); - assert.deepEqual(a.buf, [0, 10, 0, 20]); - }); - - it("prop access", () => { - const buf = [0, 1, 0, 2]; - const a = new v.Vec2(buf, 1, 2); - assert.equal(a.x, 1); - assert.equal(a.y, 2); - a.x = 10; - a.y = 20; - assert.equal(a.x, 10); - assert.equal(a.y, 20); - assert.deepEqual(a.buf, [0, 10, 0, 20]); - }); -}); diff --git a/packages/vectors/test/vec3.ts b/packages/vectors/test/vec3.ts deleted file mode 100644 index 7e5f3df709..0000000000 --- a/packages/vectors/test/vec3.ts +++ /dev/null @@ -1,111 +0,0 @@ -import * as assert from "assert"; -import * as v from "../src/index"; - -describe("vec3", () => { - - const op2 = (fn, x, y, z) => { - assert.deepEqual( - fn([1, 2, 3], [10, 20, 30]), - [x, y, z] - ); - assert.deepEqual( - fn([0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0], [0, 10, 0, 20, 0, 30, 0], 1, 1, 4, 2), - [0, x, 0, 0, 0, y, 0, 0, 0, z, 0, 0] - ); - }; - - const opn = (fn, x, y, z) => { - assert.deepEqual( - fn([1, 2, 3], 10), - [x, y, z] - ); - assert.deepEqual( - fn([0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0], 10, 1, 4), - [0, x, 0, 0, 0, y, 0, 0, 0, z, 0, 0] - ); - }; - - it("add", () => op2(v.add3, 11, 22, 33)); - it("sub", () => op2(v.sub3, -9, -18, -27)); - it("mul", () => op2(v.mul3, 10, 40, 90)); - it("div", () => op2(v.div3, 0.1, 0.1, 0.1)); - - it("addn", () => opn(v.addN3, 11, 12, 13)); - it("subn", () => opn(v.subN3, -9, -8, -7)); - it("muln", () => opn(v.mulN3, 10, 20, 30)); - it("divn", () => opn(v.divN3, 0.1, 0.2, 0.3)); - - it("madd", () => { - assert.deepEqual( - v.madd3([1, 2, 3], [10, 20, 30], [0.5, 0.25, 0.75]), - [1 + 10 * 0.5, 2 + 20 * 0.25, 3 + 30 * 0.75] - ); - assert.deepEqual( - v.madd3([1, 2, 3], [10, 0, 20, 0, 30], [0.5, 0, 0, 0.25, 0, 0, 0.75], 0, 0, 0, 1, 2, 3), - [1 + 10 * 0.5, 2 + 20 * 0.25, 3 + 30 * 0.75] - ); - }); - - it("maddn", () => { - assert.deepEqual( - v.maddN3([1, 2, 3], [10, 20, 30], 0.5), - [1 + 10 * 0.5, 2 + 20 * 0.5, 3 + 30 * 0.5] - ); - assert.deepEqual( - v.maddN3([1, 2, 3], [10, 0, 20, 0, 30], 0.5, 0, 0, 1, 2), - [1 + 10 * 0.5, 2 + 20 * 0.5, 3 + 30 * 0.5] - ); - }); - - it("equiv", () => { - const buf = [1, 2, 3, 0, 1, 0, 2, 0, 3] - assert(v.equiv3(buf, buf, 0, 4, 1, 2)); - assert(!v.equiv3(buf, buf, 0, 4)); - assert(new v.Vec3(buf).equiv(buf.slice(0, 3))); - assert(new v.Vec3(buf).equiv(new v.Vec3(buf, 4, 2))); - assert(!new v.Vec3(buf).equiv(new v.Vec3(buf, 4, 1))); - }); - - it("eqdelta", () => { - assert(v.eqDelta3([0, 1.001, 0, 1.999, 0, 3.0099], [1, 2, 3], 0.01, 1, 0, 2, 1)); - assert(!v.eqDelta3([0, 1.001, 0, 1.999, 0, 3.02], [1, 2, 3], 0.01, 1, 0, 2, 1)); - assert(new v.Vec3([0, 1.001, 0, 1.999, 0, 3.0099], 1, 2).eqDelta(v.vec3(1, 2, 3), 0.01)); - assert(!new v.Vec3([0, 1.001, 0, 1.999, 0, 3.02], 1, 2).eqDelta(v.vec3(1, 2, 3), 0.01)); - }); - - it("iterator", () => { - assert.deepEqual([...new v.Vec3([1, 2, 3])], [1, 2, 3]); - assert.deepEqual([...new v.Vec3([0, 1, 0, 2, 0, 3], 1, 2)], [1, 2, 3]); - }); - - it("arraylike", () => { - const buf = [0, 1, 0, 2, 0, 3]; - const a = new v.Vec3(buf, 1, 2); - assert.equal(a.length, 3); - assert.equal(a[0], 1); - assert.equal(a[1], 2); - assert.equal(a[2], 3); - a[0] = 10; - a[1] = 20; - a[2] = 30; - assert.equal(a[0], 10); - assert.equal(a[1], 20); - assert.equal(a[2], 30); - assert.deepEqual(a.buf, [0, 10, 0, 20, 0, 30]); - }); - - it("prop access", () => { - const buf = [0, 1, 0, 2, 0, 3]; - const a = new v.Vec3(buf, 1, 2); - assert.equal(a.x, 1); - assert.equal(a.y, 2); - assert.equal(a.z, 3); - a.x = 10; - a.y = 20; - a.z = 30; - assert.equal(a.x, 10); - assert.equal(a.y, 20); - assert.equal(a.z, 30); - assert.deepEqual(a.buf, [0, 10, 0, 20, 0, 30]); - }); -}); diff --git a/packages/vectors/test/vec4.ts b/packages/vectors/test/vec4.ts deleted file mode 100644 index c2b8931ab3..0000000000 --- a/packages/vectors/test/vec4.ts +++ /dev/null @@ -1,115 +0,0 @@ -import * as assert from "assert"; -import * as v from "../src/index"; - -describe("vec4", () => { - - const op2 = (fn, x, y, z, w) => { - assert.deepEqual( - fn([1, 2, 3, 4], [10, 20, 30, 40]), - [x, y, z, w] - ); - assert.deepEqual( - fn([0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0], [0, 10, 0, 20, 0, 30, 0, 40, 0], 1, 1, 4, 2), - [0, x, 0, 0, 0, y, 0, 0, 0, z, 0, 0, 0, w, 0, 0] - ); - }; - - const opn = (fn, x, y, z, w) => { - assert.deepEqual( - fn([1, 2, 3, 4], 10), - [x, y, z, w] - ); - assert.deepEqual( - fn([0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0], 10, 1, 4), - [0, x, 0, 0, 0, y, 0, 0, 0, z, 0, 0, 0, w, 0, 0] - ); - }; - - it("add", () => op2(v.add4, 11, 22, 33, 44)); - it("sub", () => op2(v.sub4, -9, -18, -27, -36)); - it("mul", () => op2(v.mul4, 10, 40, 90, 160)); - it("div", () => op2(v.div4, 0.1, 0.1, 0.1, 0.1)); - - it("addn", () => opn(v.addN4, 11, 12, 13, 14)); - it("subn", () => opn(v.subN4, -9, -8, -7, -6)); - it("muln", () => opn(v.mulN4, 10, 20, 30, 40)); - it("divn", () => opn(v.divN4, 0.1, 0.2, 0.3, 0.4)); - - it("madd", () => { - assert.deepEqual( - v.madd4([1, 2, 3, 4], [10, 20, 30, 40], [0.5, 0.25, 0.75, 0.125]), - [1 + 10 * 0.5, 2 + 20 * 0.25, 3 + 30 * 0.75, 4 + 40 * 0.125] - ); - assert.deepEqual( - v.madd4([1, 2, 3, 4], [10, 0, 20, 0, 30, 0, 40], [0.5, 0, 0, 0.25, 0, 0, 0.75, 0, 0, 0.125], 0, 0, 0, 1, 2, 3), - [1 + 10 * 0.5, 2 + 20 * 0.25, 3 + 30 * 0.75, 4 + 40 * 0.125] - ); - }); - - it("maddn", () => { - assert.deepEqual( - v.maddN4([1, 2, 3, 4], [10, 20, 30, 40], 0.5), - [1 + 10 * 0.5, 2 + 20 * 0.5, 3 + 30 * 0.5, 4 + 40 * 0.5] - ); - assert.deepEqual( - v.maddN4([1, 2, 3, 4], [10, 0, 20, 0, 30, 0, 40], 0.5, 0, 0, 1, 2), - [1 + 10 * 0.5, 2 + 20 * 0.5, 3 + 30 * 0.5, 4 + 40 * 0.5] - ); - }); - - it("equiv", () => { - const buf = [1, 2, 3, 4, 1, 0, 2, 0, 3, 0, 4] - assert(v.equiv4(buf, buf, 0, 4, 1, 2)); - assert(!v.equiv4(buf, buf, 0, 4)); - assert(new v.Vec4(buf).equiv(buf.slice(0, 4))); - assert(new v.Vec4(buf).equiv(new v.Vec4(buf, 4, 2))); - assert(!new v.Vec4(buf).equiv(new v.Vec4(buf, 4, 1))); - }); - - it("eqdelta", () => { - assert(v.eqDelta4([0, 1.001, 0, 1.999, 0, 3.0099, 0, 3.991], [1, 2, 3, 4], 0.01, 1, 0, 2, 1)); - assert(!v.eqDelta4([0, 1.001, 0, 1.999, 0, 3.02, 0, 4], [1, 2, 3, 4], 0.01, 1, 0, 2, 1)); - }); - - it("iterator", () => { - assert.deepEqual([...new v.Vec4([1, 2, 3, 4])], [1, 2, 3, 4]); - assert.deepEqual([...new v.Vec4([0, 1, 0, 2, 0, 3, 0, 4], 1, 2)], [1, 2, 3, 4]); - }); - - it("arraylike", () => { - const buf = [0, 1, 0, 2, 0, 3, 0, 4]; - const a = new v.Vec4(buf, 1, 2); - assert.equal(a.length, 4); - assert.equal(a[0], 1); - assert.equal(a[1], 2); - assert.equal(a[2], 3); - assert.equal(a[3], 4); - a[0] = 10; - a[1] = 20; - a[2] = 30; - a[3] = 40; - assert.equal(a[0], 10); - assert.equal(a[1], 20); - assert.equal(a[2], 30); - assert.equal(a[3], 40); - assert.deepEqual(a.buf, [0, 10, 0, 20, 0, 30, 0, 40]); - }); - - it("prop access", () => { - const buf = [0, 1, 0, 2, 0, 3, 0, 4]; - const a = new v.Vec4(buf, 1, 2); - assert.equal(a.x, 1); - assert.equal(a.y, 2); - assert.equal(a.z, 3); - assert.equal(a.w, 4); - a.x = 10; - a.y = 20; - a.z = 30; - a.w = 40; - assert.equal(a.x, 10); - assert.equal(a.y, 20); - assert.equal(a.z, 30); - assert.equal(a.w, 40); - assert.deepEqual(a.buf, [0, 10, 0, 20, 0, 30, 0, 40]); - }); -}); diff --git a/packages/vectors/tsconfig.json b/packages/vectors/tsconfig.json index bd6481a5a6..bcf03f18b4 100644 --- a/packages/vectors/tsconfig.json +++ b/packages/vectors/tsconfig.json @@ -1,9 +1,11 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" ] -} +} \ No newline at end of file diff --git a/scripts/bundle-module b/scripts/bundle-module new file mode 100755 index 0000000000..0f8ed33b64 --- /dev/null +++ b/scripts/bundle-module @@ -0,0 +1,98 @@ +#!/usr/bin/env node +const fs = require("fs"); +const rollup = require("rollup"); +const cleanup = require("rollup-plugin-cleanup"); +const terser = require("terser"); +const gz = require("gzip-size"); + +const camelCase = + (x) => x.replace(/\-+(\w)/g, (_, c) => c.toUpperCase()); + +const size = + (x) => (x / 1024).toFixed(2) + "KB"; + +const name = process.argv[2]; + +const deps = process.argv + .slice(3) + .reduce( + (acc, x) => (acc[`@thi.ng/${x}`] = `thi.ng.${camelCase(x)}`, acc), + {} + ); + +const INPUT_OPTS = { + external: Object.keys(deps), + input: "./index.js", + plugins: [ + cleanup({ comments: "some" }) + ] +}; + +const TERSER_OPTS = { + compress: true, + mangle: true, + ecma: 6 +}; + +const buildVersion = + async (opts, write = true, compressed = false) => { + + console.log(`bundling (${opts.format}): ${opts.file}`); + + const bundle = await rollup.rollup(INPUT_OPTS); + const bundleOut = (await bundle.generate(opts)).output[0]; + const bundleCode = bundleOut.code; + const terserOut = terser.minify(bundleCode, TERSER_OPTS).code; + const gzSize = gz.sync(terserOut); + + write && fs.writeFileSync(opts.file, compressed ? terserOut : bundleCode); + opts.sourcemap && fs.writeFileSync(opts.file + ".map", bundleOut.map); + + console.log(`\tsize: ${size(terserOut.length)} / gzipped: ${size(gzSize)}`); + return { raw: bundleCode.length, min: terserOut.length, gzip: gzSize }; + }; + +const build = + async () => { + + !fs.existsSync("lib") && fs.mkdirSync("lib"); + !fs.existsSync(".meta") && fs.mkdirSync(".meta"); + + const cjs = await buildVersion( + { + file: "lib/index.js", + format: "cjs", + // we don't use default exports, so safe to remove interop blocks + interop: false, + sourcemap: true, + sourcemapExcludeSources: true, + } + ); + + // output disabled, just collect meta data + const esm = await buildVersion( + { + file: "lib/index.es6.js", + format: "esm", + interop: false, + }, + false + ); + + // write minified version + const umd = await buildVersion( + { + file: "lib/index.umd.js", + format: "umd", + globals: deps, + name: `thi.ng.${name}`, + interop: false, + sourcemap: true, + sourcemapExcludeSources: true, + } + ); + + fs.writeFileSync(".meta/size.json", JSON.stringify({ esm, cjs, umd })); + }; + +build(); diff --git a/scripts/depgraph b/scripts/depgraph index 350c789485..ad39db192e 100755 --- a/scripts/depgraph +++ b/scripts/depgraph @@ -53,5 +53,14 @@ tx.run( ([p, d]) => g.addDependency(p, d), packages); -console.log("topo order:", g.sort().map((x) => x.replace("@thi.ng/", "")).join(" ")); -console.log("done"); \ No newline at end of file + +const sorted = g.sort(); +console.log("topo order:", sorted.map((x) => x.substr(8)).join(" "), "\n\n"); + +const noprefix = (ids) => [...ids].sort().map((x) => x.substr(8)); + +sorted.forEach((x) => { + console.log(`${x}:`); + console.log(`\t<-- ${noprefix(g.transitiveDependencies(x))}`); + console.log(`\t--> ${noprefix(g.transitiveDependents(x))}\n\n`); +}); diff --git a/scripts/make-example b/scripts/make-example index 234cb5ac44..d1707237d2 100755 --- a/scripts/make-example +++ b/scripts/make-example @@ -27,18 +27,18 @@ cat << EOF > $MODULE/package.json "author": "$AUTHOR <$EMAIL>", "license": "Apache-2.0", "scripts": { - "clean": "rm -rf .cache build out", + "clean": "rimraf .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.10.3", - "terser": "^3.11.0", + "parcel-bundler": "^1.11.0", + "rimraf": "^2.6.3", + "terser": "^3.14.1", "typescript": "^3.2.2" }, "dependencies": { "@thi.ng/api": "latest", - "@thi.ng/atom": "latest", "@thi.ng/rstream": "latest", "@thi.ng/transducers-hdom": "latest" }, @@ -101,12 +101,7 @@ cat << EOF > $MODULE/README.md [Live demo](http://demo.thi.ng/umbrella/$1/) -\`\`\`bash -git clone https://github.com/thi-ng/umbrella.git -cd umbrella/examples/$1 -yarn install -yarn start -\`\`\` +Please refer to the [example build instructions](https://github.com/thi-ng/umbrella/wiki/Example-build-instructions) on the wiki. ## Authors diff --git a/scripts/make-module b/scripts/make-module index bf87bba7cf..97073dd76c 100755 --- a/scripts/make-module +++ b/scripts/make-module @@ -35,7 +35,9 @@ cat << EOF > $MODULE/package.json "name": "@thi.ng/$1", "version": "0.0.1", "description": "TODO", - "main": "./index.js", + "module": "./index.js", + "main": "./lib/index.js", + "umd:main": "./lib/index.umd.js", "typings": "./index.d.ts", "repository": { "type": "git", @@ -45,23 +47,25 @@ cat << EOF > $MODULE/package.json "author": "$AUTHOR <$EMAIL>", "license": "Apache-2.0", "scripts": { - "build": "yarn run clean && tsc --declaration", - "clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", + "build": "yarn clean && yarn build:es6 && yarn build:bundle", + "build:es6": "tsc --declaration", + "build:bundle": "../../scripts/bundle-module $1", + "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 run build && yarn publish --access public", - "test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" + "pub": "yarn build && yarn publish --access public" }, "devDependencies": { "@types/mocha": "^5.2.5", "@types/node": "^10.12.15", "mocha": "^5.2.0", "nyc": "^13.1.0", - "typedoc": "^0.13.0", + "typedoc": "^0.14.0", "typescript": "^3.2.2" }, "dependencies": { - "@thi.ng/api": "^4.2.3" + "@thi.ng/api": "^4.2.4" }, "keywords": [ "ES6", @@ -69,7 +73,8 @@ cat << EOF > $MODULE/package.json ], "publishConfig": { "access": "public" - } + }, + "sideEffects": false } EOF @@ -78,7 +83,9 @@ cat << EOF > $MODULE/tsconfig.json { "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "." + "outDir": ".", + "module": "es6", + "target": "es6" }, "include": [ "./src/**/*.ts" @@ -91,7 +98,8 @@ cat << EOF > $MODULE/test/tsconfig.json { "extends": "../../../tsconfig.json", "compilerOptions": { - "outDir": "../build" + "outDir": "../build", + "module": "commonjs" }, "include": [ "./**/*.ts", @@ -102,6 +110,10 @@ EOF echo "writing .npmignore..." cat << EOF > $MODULE/.npmignore +.meta +.nyc_output +*.html +*.tgz build coverage dev @@ -109,10 +121,7 @@ doc export src* test -.nyc_output tsconfig.json -*.tgz -*.html EOF echo "writing README.md..." diff --git a/tsconfig.json b/tsconfig.json index 4777c2b7bd..67f0c1e296 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,11 +1,12 @@ { "compilerOptions": { - "module": "commonjs", + "module": "es6", "target": "es6", "experimentalDecorators": true, "noUnusedParameters": true, "noUnusedLocals": true, - "preserveConstEnums": true + "preserveConstEnums": true, + "moduleResolution": "node" }, "exclude": [ "./**/node_modules" diff --git a/yarn.lock b/yarn.lock index 57aa3a86df..c2c91e123c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10,31 +10,31 @@ "@babel/highlight" "^7.0.0" "@babel/core@^7.0.0": - version "7.1.2" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.1.2.tgz#f8d2a9ceb6832887329a7b60f9d035791400ba4e" - integrity sha512-IFeSSnjXdhDaoysIlev//UzHZbdEmm7D0EIH2qtse9xK7mXEZQpYjs2P00XlP1qYsYvid79p+Zgg6tz1mp6iVw== + version "7.2.2" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.2.2.tgz#07adba6dde27bb5ad8d8672f15fde3e08184a687" + integrity sha512-59vB0RWt09cAct5EIe58+NzGP4TFSD3Bz//2/ELy3ZeTeKF6VTD1AXlH8BGGbCX0PuobZBsIzO7IAI9PH67eKw== dependencies: "@babel/code-frame" "^7.0.0" - "@babel/generator" "^7.1.2" - "@babel/helpers" "^7.1.2" - "@babel/parser" "^7.1.2" - "@babel/template" "^7.1.2" - "@babel/traverse" "^7.1.0" - "@babel/types" "^7.1.2" + "@babel/generator" "^7.2.2" + "@babel/helpers" "^7.2.0" + "@babel/parser" "^7.2.2" + "@babel/template" "^7.2.2" + "@babel/traverse" "^7.2.2" + "@babel/types" "^7.2.2" convert-source-map "^1.1.0" - debug "^3.1.0" - json5 "^0.5.0" + debug "^4.1.0" + json5 "^2.1.0" lodash "^4.17.10" resolve "^1.3.2" semver "^5.4.1" source-map "^0.5.0" -"@babel/generator@^7.0.0", "@babel/generator@^7.1.2", "@babel/generator@^7.1.3": - version "7.1.3" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.1.3.tgz#2103ec9c42d9bdad9190a6ad5ff2d456fd7b8673" - integrity sha512-ZoCZGcfIJFJuZBqxcY9OjC1KW2lWK64qrX1o4UYL3yshVhwKFYgzpWZ0vvtGMNJdTlvkw0W+HR1VnYN8q3QPFQ== +"@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.1.3" + "@babel/types" "^7.2.2" jsesc "^2.5.1" lodash "^4.17.10" source-map "^0.5.0" @@ -127,15 +127,15 @@ "@babel/types" "^7.0.0" "@babel/helper-module-transforms@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.1.0.tgz#470d4f9676d9fad50b324cdcce5fbabbc3da5787" - integrity sha512-0JZRd2yhawo79Rcm4w0LwSMILFmFXjugG3yqf+P/UsKsRS1mJCmMwwlHDlMg7Avr9LrvSpp4ZSULO9r8jpCzcw== + 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== 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.1.0" - "@babel/types" "^7.0.0" + "@babel/template" "^7.2.2" + "@babel/types" "^7.2.2" lodash "^4.17.10" "@babel/helper-optimise-call-expression@^7.0.0": @@ -169,13 +169,13 @@ "@babel/types" "^7.0.0" "@babel/helper-replace-supers@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.1.0.tgz#5fc31de522ec0ef0899dc9b3e7cf6a5dd655f362" - integrity sha512-BvcDWYZRWVuDeXTYZWxekQNO5D4kO55aArwZOTFXw6rlLQA8ZaDicJR1sO47h+HrnCiDFiww0fSPV0d713KBGQ== + 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.1.0" + "@babel/traverse" "^7.2.3" "@babel/types" "^7.0.0" "@babel/helper-simple-access@^7.1.0": @@ -194,23 +194,23 @@ "@babel/types" "^7.0.0" "@babel/helper-wrap-function@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.1.0.tgz#8cf54e9190706067f016af8f75cb3df829cc8c66" - integrity sha512-R6HU3dete+rwsdAfrOzTlE9Mcpk4RjU3aX3gi9grtmugQY0u79X7eogUvfXA5sI81Mfq1cn6AgxihfN33STjJA== + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.2.0.tgz#c4e0012445769e2815b55296ead43a958549f6fa" + integrity sha512-o9fP1BZLLSrYlxYEYyl2aS+Flun5gtjTIG8iln+XuEzQTs0PLagAGSXUcqruJwD5fM48jzIEggCKpIfWTcR7pQ== dependencies: "@babel/helper-function-name" "^7.1.0" "@babel/template" "^7.1.0" "@babel/traverse" "^7.1.0" - "@babel/types" "^7.0.0" + "@babel/types" "^7.2.0" -"@babel/helpers@^7.1.2": - version "7.1.2" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.1.2.tgz#ab752e8c35ef7d39987df4e8586c63b8846234b5" - integrity sha512-Myc3pUE8eswD73aWcartxB16K6CGmHDv9KxOmD2CeOs/FaEAQodr3VYGmlvOmog60vNQ2w8QbatuahepZwrHiA== +"@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== dependencies: "@babel/template" "^7.1.2" - "@babel/traverse" "^7.1.0" - "@babel/types" "^7.1.2" + "@babel/traverse" "^7.1.5" + "@babel/types" "^7.2.0" "@babel/highlight@^7.0.0": version "7.0.0" @@ -221,130 +221,130 @@ esutils "^2.0.2" js-tokens "^4.0.0" -"@babel/parser@^7.0.0", "@babel/parser@^7.1.2", "@babel/parser@^7.1.3": - version "7.1.3" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.1.3.tgz#2c92469bac2b7fbff810b67fca07bd138b48af77" - integrity sha512-gqmspPZOMW3MIRb9HlrnbZHXI1/KHTOroBwN1NcLL6pWxzqzEKGvRTq0W/PxS45OtQGbaFikSQpkS5zbnsQm2w== +"@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/plugin-proposal-async-generator-functions@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.1.0.tgz#41c1a702e10081456e23a7b74d891922dd1bb6ce" - integrity sha512-Fq803F3Jcxo20MXUSDdmZZXrPe6BWyGcWBPPNB/M7WaUYESKDeKMOGIxEzQOjGSmW/NWb6UaPZrtTB2ekhB/ew== +"@babel/plugin-proposal-async-generator-functions@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz#b289b306669dce4ad20b0252889a15768c9d417e" + integrity sha512-+Dfo/SCQqrwx48ptLVGLdE39YtWRuKc/Y9I5Fy0P1DDBB9lsAHpjcEJQt+4IifuSOSTLBKJObJqMvaO1pIE8LQ== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/helper-remap-async-to-generator" "^7.1.0" - "@babel/plugin-syntax-async-generators" "^7.0.0" + "@babel/plugin-syntax-async-generators" "^7.2.0" -"@babel/plugin-proposal-json-strings@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.0.0.tgz#3b4d7b5cf51e1f2e70f52351d28d44fc2970d01e" - integrity sha512-kfVdUkIAGJIVmHmtS/40i/fg/AGnw/rsZBCaapY5yjeO5RA9m165Xbw9KMOu2nqXP5dTFjEjHdfNdoVcHv133Q== +"@babel/plugin-proposal-json-strings@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.2.0.tgz#568ecc446c6148ae6b267f02551130891e29f317" + integrity sha512-MAFV1CA/YVmYwZG0fBQyXhmj0BHCB5egZHCKWIFVv/XCxAeVGIHfos3SwDck4LvCllENIAg7xMKOG5kH0dzyUg== dependencies: "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-json-strings" "^7.0.0" + "@babel/plugin-syntax-json-strings" "^7.2.0" -"@babel/plugin-proposal-object-rest-spread@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.0.0.tgz#9a17b547f64d0676b6c9cecd4edf74a82ab85e7e" - integrity sha512-14fhfoPcNu7itSen7Py1iGN0gEm87hX/B+8nZPqkdmANyyYWYMY2pjA3r8WXbWVKMzfnSNS0xY8GVS0IjXi/iw== +"@babel/plugin-proposal-object-rest-spread@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.2.0.tgz#88f5fec3e7ad019014c97f7ee3c992f0adbf7fb8" + integrity sha512-1L5mWLSvR76XYUQJXkd/EEQgjq8HHRP6lQuZTTg0VA4tTGPpGemmCdAfQIz1rzEuWAm+ecP8PyyEm30jC1eQCg== dependencies: "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-object-rest-spread" "^7.0.0" + "@babel/plugin-syntax-object-rest-spread" "^7.2.0" -"@babel/plugin-proposal-optional-catch-binding@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.0.0.tgz#b610d928fe551ff7117d42c8bb410eec312a6425" - integrity sha512-JPqAvLG1s13B/AuoBjdBYvn38RqW6n1TzrQO839/sIpqLpbnXKacsAgpZHzLD83Sm8SDXMkkrAvEnJ25+0yIpw== +"@babel/plugin-proposal-optional-catch-binding@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.2.0.tgz#135d81edb68a081e55e56ec48541ece8065c38f5" + integrity sha512-mgYj3jCcxug6KUcX4OBoOJz3CMrwRfQELPQ5560F70YQUBZB7uac9fqaWamKR1iWUzGiK2t0ygzjTScZnVz75g== dependencies: "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-optional-catch-binding" "^7.0.0" + "@babel/plugin-syntax-optional-catch-binding" "^7.2.0" -"@babel/plugin-proposal-unicode-property-regex@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.0.0.tgz#498b39cd72536cd7c4b26177d030226eba08cd33" - integrity sha512-tM3icA6GhC3ch2SkmSxv7J/hCWKISzwycub6eGsDrFDgukD4dZ/I+x81XgW0YslS6mzNuQ1Cbzh5osjIMgepPQ== +"@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== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/helper-regex" "^7.0.0" regexpu-core "^4.2.0" -"@babel/plugin-syntax-async-generators@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.0.0.tgz#bf0891dcdbf59558359d0c626fdc9490e20bc13c" - integrity sha512-im7ged00ddGKAjcZgewXmp1vxSZQQywuQXe2B1A7kajjZmDeY/ekMPmWr9zJgveSaQH0k7BcGrojQhcK06l0zA== +"@babel/plugin-syntax-async-generators@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.2.0.tgz#69e1f0db34c6f5a0cf7e2b3323bf159a76c8cb7f" + integrity sha512-1ZrIRBv2t0GSlcwVoQ6VgSLpLgiN/FVQUzt9znxo7v2Ov4jJrs8RY8tv0wvDmFN3qIdMKWrmMMW6yZ0G19MfGg== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-syntax-flow@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.0.0.tgz#70638aeaad9ee426bc532e51523cff8ff02f6f17" - integrity sha512-zGcuZWiWWDa5qTZ6iAnpG0fnX/GOu49pGR5PFvkQ9GmKNaSphXQnlNXh/LG20sqWtNrx/eB6krzfEzcwvUyeFA== +"@babel/plugin-syntax-flow@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.2.0.tgz#a765f061f803bc48f240c26f8747faf97c26bf7c" + integrity sha512-r6YMuZDWLtLlu0kqIim5o/3TNRAlWb073HwT3e2nKf9I8IIvOggPrnILYPsrrKilmn/mYEMCf/Z07w3yQJF6dg== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-syntax-json-strings@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.0.0.tgz#0d259a68090e15b383ce3710e01d5b23f3770cbd" - integrity sha512-UlSfNydC+XLj4bw7ijpldc1uZ/HB84vw+U6BTuqMdIEmz/LDe63w/GHtpQMdXWdqQZFeAI9PjnHe/vDhwirhKA== +"@babel/plugin-syntax-json-strings@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.2.0.tgz#72bd13f6ffe1d25938129d2a186b11fd62951470" + integrity sha512-5UGYnMSLRE1dqqZwug+1LISpA403HzlSfsg6P9VXU6TBjcSHeNlw4DxDx7LgpF+iKZoOG/+uzqoRHTdcUpiZNg== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-syntax-jsx@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.0.0.tgz#034d5e2b4e14ccaea2e4c137af7e4afb39375ffd" - integrity sha512-PdmL2AoPsCLWxhIr3kG2+F9v4WH06Q3z+NoGVpQgnUNGcagXHq5sB3OXxkSahKq9TLdNMN/AJzFYSOo8UKDMHg== +"@babel/plugin-syntax-jsx@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.2.0.tgz#0b85a3b4bc7cdf4cc4b8bf236335b907ca22e7c7" + integrity sha512-VyN4QANJkRW6lDBmENzRszvZf3/4AXaj9YR7GwrWeeN9tEBPuXbmDYVU9bYBN0D70zCWVwUy0HWq2553VCb6Hw== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-syntax-object-rest-spread@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.0.0.tgz#37d8fbcaf216bd658ea1aebbeb8b75e88ebc549b" - integrity sha512-5A0n4p6bIiVe5OvQPxBnesezsgFJdHhSs3uFSvaPdMqtsovajLZ+G2vZyvNe10EzJBWWo3AcHGKhAFUxqwp2dw== +"@babel/plugin-syntax-object-rest-spread@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz#3b7a3e733510c57e820b9142a6579ac8b0dfad2e" + integrity sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-syntax-optional-catch-binding@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.0.0.tgz#886f72008b3a8b185977f7cb70713b45e51ee475" - integrity sha512-Wc+HVvwjcq5qBg1w5RG9o9RVzmCaAg/Vp0erHCKpAYV8La6I94o4GQAmFYNmkzoMO6gzoOSulpKeSSz6mPEoZw== +"@babel/plugin-syntax-optional-catch-binding@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.2.0.tgz#a94013d6eda8908dfe6a477e7f9eda85656ecf5c" + integrity sha512-bDe4xKNhb0LI7IvZHiA13kff0KEfaGX/Hv4lMA9+7TEc63hMNvfKo6ZFpXhKuEp+II/q35Gc4NoMeDZyaUbj9w== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-arrow-functions@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.0.0.tgz#a6c14875848c68a3b4b3163a486535ef25c7e749" - integrity sha512-2EZDBl1WIO/q4DIkIp4s86sdp4ZifL51MoIviLY/gG/mLSuOIEg7J8o6mhbxOTvUJkaN50n+8u41FVsr5KLy/w== +"@babel/plugin-transform-arrow-functions@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz#9aeafbe4d6ffc6563bf8f8372091628f00779550" + integrity sha512-ER77Cax1+8/8jCB9fo4Ud161OZzWN5qawi4GusDuRLcDbDG+bIGYY20zb2dfAFdTRGzrfq2xZPvF0R64EHnimg== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-async-to-generator@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.1.0.tgz#109e036496c51dd65857e16acab3bafdf3c57811" - integrity sha512-rNmcmoQ78IrvNCIt/R9U+cixUHeYAzgusTFgIAv+wQb9HJU4szhpDD6e5GCACmj/JP5KxuCwM96bX3L9v4ZN/g== +"@babel/plugin-transform-async-to-generator@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.2.0.tgz#68b8a438663e88519e65b776f8938f3445b1a2ff" + integrity sha512-CEHzg4g5UraReozI9D4fblBYABs7IM6UerAVG7EJVrTLC5keh00aEuLUT+O40+mJCEzaXkYfTCUKIyeDfMOFFQ== dependencies: "@babel/helper-module-imports" "^7.0.0" "@babel/helper-plugin-utils" "^7.0.0" "@babel/helper-remap-async-to-generator" "^7.1.0" -"@babel/plugin-transform-block-scoped-functions@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.0.0.tgz#482b3f75103927e37288b3b67b65f848e2aa0d07" - integrity sha512-AOBiyUp7vYTqz2Jibe1UaAWL0Hl9JUXEgjFvvvcSc9MVDItv46ViXFw2F7SVt1B5k+KWjl44eeXOAk3UDEaJjQ== +"@babel/plugin-transform-block-scoped-functions@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.2.0.tgz#5d3cc11e8d5ddd752aa64c9148d0db6cb79fd190" + integrity sha512-ntQPR6q1/NKuphly49+QiQiTN0O63uOwjdD6dhIjSWBI5xlrbUFh720TIpzBhpnrLfv2tNH/BXvLIab1+BAI0w== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-block-scoping@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.0.0.tgz#1745075edffd7cdaf69fab2fb6f9694424b7e9bc" - integrity sha512-GWEMCrmHQcYWISilUrk9GDqH4enf3UmhOEbNbNrlNAX1ssH3MsS1xLOS6rdjRVPgA7XXVPn87tRkdTEoA/dxEg== +"@babel/plugin-transform-block-scoping@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.2.0.tgz#f17c49d91eedbcdf5dd50597d16f5f2f770132d4" + integrity sha512-vDTgf19ZEV6mx35yiPJe4fS02mPQUUcBNwWQSZFXSzTSbsJFQvHt7DqyS3LK8oOWALFOsJ+8bbqBgkirZteD5Q== dependencies: "@babel/helper-plugin-utils" "^7.0.0" lodash "^4.17.10" -"@babel/plugin-transform-classes@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.1.0.tgz#ab3f8a564361800cbc8ab1ca6f21108038432249" - integrity sha512-rNaqoD+4OCBZjM7VaskladgqnZ1LO6o2UxuWSDzljzW21pN1KXkB7BstAVweZdxQkHAujps5QMNOTWesBciKFg== +"@babel/plugin-transform-classes@^7.2.0": + version "7.2.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.2.2.tgz#6c90542f210ee975aa2aa8c8b5af7fa73a126953" + integrity sha512-gEZvgTy1VtcDOaQty1l10T3jQmJKlNVxLDCs+3rCVPr6nMkODLELxViq5X9l+rfxbie3XrfrMCYYY6eX3aOcOQ== dependencies: "@babel/helper-annotate-as-pure" "^7.0.0" "@babel/helper-define-map" "^7.1.0" @@ -355,103 +355,103 @@ "@babel/helper-split-export-declaration" "^7.0.0" globals "^11.1.0" -"@babel/plugin-transform-computed-properties@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.0.0.tgz#2fbb8900cd3e8258f2a2ede909b90e7556185e31" - integrity sha512-ubouZdChNAv4AAWAgU7QKbB93NU5sHwInEWfp+/OzJKA02E6Woh9RVoX4sZrbRwtybky/d7baTUqwFx+HgbvMA== +"@babel/plugin-transform-computed-properties@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.2.0.tgz#83a7df6a658865b1c8f641d510c6f3af220216da" + integrity sha512-kP/drqTxY6Xt3NNpKiMomfgkNn4o7+vKxK2DDKcBG9sHj51vHqMBGy8wbDS/J4lMxnqs153/T3+DmCEAkC5cpA== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-destructuring@^7.0.0": - version "7.1.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.1.3.tgz#e69ff50ca01fac6cb72863c544e516c2b193012f" - integrity sha512-Mb9M4DGIOspH1ExHOUnn2UUXFOyVTiX84fXCd+6B5iWrQg/QMeeRmSwpZ9lnjYLSXtZwiw80ytVMr3zue0ucYw== +"@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== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-dotall-regex@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.0.0.tgz#73a24da69bc3c370251f43a3d048198546115e58" - integrity sha512-00THs8eJxOJUFVx1w8i1MBF4XH4PsAjKjQ1eqN/uCH3YKwP21GCKfrn6YZFZswbOk9+0cw1zGQPHVc1KBlSxig== +"@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== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/helper-regex" "^7.0.0" regexpu-core "^4.1.3" -"@babel/plugin-transform-duplicate-keys@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.0.0.tgz#a0601e580991e7cace080e4cf919cfd58da74e86" - integrity sha512-w2vfPkMqRkdxx+C71ATLJG30PpwtTpW7DDdLqYt2acXU7YjztzeWW2Jk1T6hKqCLYCcEA5UQM/+xTAm+QCSnuQ== +"@babel/plugin-transform-duplicate-keys@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.2.0.tgz#d952c4930f312a4dbfff18f0b2914e60c35530b3" + integrity sha512-q+yuxW4DsTjNceUiTzK0L+AfQ0zD9rWaTLiUqHA8p0gxx7lu1EylenfzjeIWNkPy6e/0VG/Wjw9uf9LueQwLOw== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-exponentiation-operator@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.1.0.tgz#9c34c2ee7fd77e02779cfa37e403a2e1003ccc73" - integrity sha512-uZt9kD1Pp/JubkukOGQml9tqAeI8NkE98oZnHZ2qHRElmeKCodbTZgOEUtujSCSLhHSBWbzNiFSDIMC4/RBTLQ== +"@babel/plugin-transform-exponentiation-operator@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.2.0.tgz#a63868289e5b4007f7054d46491af51435766008" + integrity sha512-umh4hR6N7mu4Elq9GG8TOu9M0bakvlsREEC+ialrQN6ABS4oDQ69qJv1VtR3uxlKMCQMCvzk7vr17RHKcjx68A== dependencies: "@babel/helper-builder-binary-assignment-operator-visitor" "^7.1.0" "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-flow-strip-types@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.0.0.tgz#c40ced34c2783985d90d9f9ac77a13e6fb396a01" - integrity sha512-WhXUNb4It5a19RsgKKbQPrjmy4yWOY1KynpEbNw7bnd1QTcrT/EIl3MJvnGgpgvrKyKbqX7nUNOJfkpLOnoDKA== + version "7.2.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.2.3.tgz#e3ac2a594948454e7431c7db33e1d02d51b5cd69" + integrity sha512-xnt7UIk9GYZRitqCnsVMjQK1O2eKZwFB3CvvHjf5SGx6K6vr/MScCKQDnf1DxRaj501e3pXjti+inbSXX2ZUoQ== dependencies: "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-flow" "^7.0.0" + "@babel/plugin-syntax-flow" "^7.2.0" -"@babel/plugin-transform-for-of@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.0.0.tgz#f2ba4eadb83bd17dc3c7e9b30f4707365e1c3e39" - integrity sha512-TlxKecN20X2tt2UEr2LNE6aqA0oPeMT1Y3cgz8k4Dn1j5ObT8M3nl9aA37LLklx0PBZKETC9ZAf9n/6SujTuXA== +"@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== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-function-name@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.1.0.tgz#29c5550d5c46208e7f730516d41eeddd4affadbb" - integrity sha512-VxOa1TMlFMtqPW2IDYZQaHsFrq/dDoIjgN098NowhexhZcz3UGlvPgZXuE1jEvNygyWyxRacqDpCZt+par1FNg== +"@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== dependencies: "@babel/helper-function-name" "^7.1.0" "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-literals@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.0.0.tgz#2aec1d29cdd24c407359c930cdd89e914ee8ff86" - integrity sha512-1NTDBWkeNXgpUcyoVFxbr9hS57EpZYXpje92zv0SUzjdu3enaRwF/l3cmyRnXLtIdyJASyiS6PtybK+CgKf7jA== +"@babel/plugin-transform-literals@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.2.0.tgz#690353e81f9267dad4fd8cfd77eafa86aba53ea1" + integrity sha512-2ThDhm4lI4oV7fVQ6pNNK+sx+c/GM5/SaML0w/r4ZB7sAneD/piDJtwdKlNckXeyGK7wlwg2E2w33C/Hh+VFCg== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-modules-amd@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.1.0.tgz#f9e0a7072c12e296079b5a59f408ff5b97bf86a8" - integrity sha512-wt8P+xQ85rrnGNr2x1iV3DW32W8zrB6ctuBkYBbf5/ZzJY99Ob4MFgsZDFgczNU76iy9PWsy4EuxOliDjdKw6A== +"@babel/plugin-transform-modules-amd@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.2.0.tgz#82a9bce45b95441f617a24011dc89d12da7f4ee6" + integrity sha512-mK2A8ucqz1qhrdqjS9VMIDfIvvT2thrEsIQzbaTdc5QFzhDjQv2CkJJ5f6BXIkgbmaoax3zBr2RyvV/8zeoUZw== dependencies: "@babel/helper-module-transforms" "^7.1.0" "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-modules-commonjs@^7.0.0", "@babel/plugin-transform-modules-commonjs@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.1.0.tgz#0a9d86451cbbfb29bd15186306897c67f6f9a05c" - integrity sha512-wtNwtMjn1XGwM0AXPspQgvmE6msSJP15CX2RVfpTSTNPLhKhaOjaIfBaVfj4iUZ/VrFSodcFedwtPg/NxwQlPA== +"@babel/plugin-transform-modules-commonjs@^7.0.0", "@babel/plugin-transform-modules-commonjs@^7.2.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== dependencies: "@babel/helper-module-transforms" "^7.1.0" "@babel/helper-plugin-utils" "^7.0.0" "@babel/helper-simple-access" "^7.1.0" -"@babel/plugin-transform-modules-systemjs@^7.0.0": - version "7.1.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.1.3.tgz#2119a3e3db612fd74a19d88652efbfe9613a5db0" - integrity sha512-PvTxgjxQAq4pvVUZF3mD5gEtVDuId8NtWkJsZLEJZMZAW3TvgQl1pmydLLN1bM8huHFVVU43lf0uvjQj9FRkKw== +"@babel/plugin-transform-modules-systemjs@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.2.0.tgz#912bfe9e5ff982924c81d0937c92d24994bb9068" + integrity sha512-aYJwpAhoK9a+1+O625WIjvMY11wkB/ok0WClVwmeo3mCjcNRjt+/8gHWrB5i+00mUju0gWsBkQnPpdvQ7PImmQ== dependencies: "@babel/helper-hoist-variables" "^7.0.0" "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-modules-umd@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.1.0.tgz#a29a7d85d6f28c3561c33964442257cc6a21f2a8" - integrity sha512-enrRtn5TfRhMmbRwm7F8qOj0qEYByqUvTttPEGimcBH4CJHphjyK1Vg7sdU7JjeEmgSpM890IT/efS2nMHwYig== +"@babel/plugin-transform-modules-umd@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.2.0.tgz#7678ce75169f0877b8eb2235538c074268dd01ae" + integrity sha512-BV3bw6MyUH1iIsGhXlOK6sXhmSarZjtJ/vMiD9dNmpY8QXFFQTj+6v92pcfy1iqa8DeAfJFwoxcrS/TUZda6sw== dependencies: "@babel/helper-module-transforms" "^7.1.0" "@babel/helper-plugin-utils" "^7.0.0" @@ -463,31 +463,31 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-object-super@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.1.0.tgz#b1ae194a054b826d8d4ba7ca91486d4ada0f91bb" - integrity sha512-/O02Je1CRTSk2SSJaq0xjwQ8hG4zhZGNjE8psTsSNPXyLRCODv7/PBozqT5AmQMzp7MI3ndvMhGdqp9c96tTEw== +"@babel/plugin-transform-object-super@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.2.0.tgz#b35d4c10f56bab5d650047dad0f1d8e8814b6598" + integrity sha512-VMyhPYZISFZAqAPVkiYb7dUe2AsVi2/wCT5+wZdsNO31FojQJa9ns40hzZ6U9f50Jlq4w6qwzdBB2uwqZ00ebg== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/helper-replace-supers" "^7.1.0" -"@babel/plugin-transform-parameters@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.1.0.tgz#44f492f9d618c9124026e62301c296bf606a7aed" - integrity sha512-vHV7oxkEJ8IHxTfRr3hNGzV446GAb+0hgbA7o/0Jd76s+YzccdWuTU296FOCOl/xweU4t/Ya4g41yWz80RFCRw== +"@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== dependencies: "@babel/helper-call-delegate" "^7.1.0" "@babel/helper-get-function-arity" "^7.0.0" "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-react-jsx@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.0.0.tgz#524379e4eca5363cd10c4446ba163f093da75f3e" - integrity sha512-0TMP21hXsSUjIQJmu/r7RiVxeFrXRcMUigbKu0BLegJK9PkYodHstaszcig7zxXfaBji2LYUdtqIkHs+hgYkJQ== + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.2.0.tgz#ca36b6561c4d3b45524f8efb6f0fbc9a0d1d622f" + integrity sha512-h/fZRel5wAfCqcKgq3OhbmYaReo7KkoJBpt8XnvpS7wqaNMqtw5xhxutzcm35iMUWucfAdT/nvGTsWln0JTg2Q== dependencies: "@babel/helper-builder-react-jsx" "^7.0.0" "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-jsx" "^7.0.0" + "@babel/plugin-syntax-jsx" "^7.2.0" "@babel/plugin-transform-regenerator@^7.0.0": version "7.0.0" @@ -496,148 +496,153 @@ dependencies: regenerator-transform "^0.13.3" -"@babel/plugin-transform-shorthand-properties@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.0.0.tgz#85f8af592dcc07647541a0350e8c95c7bf419d15" - integrity sha512-g/99LI4vm5iOf5r1Gdxq5Xmu91zvjhEG5+yZDJW268AZELAu4J1EiFLnkSG3yuUsZyOipVOVUKoGPYwfsTymhw== +"@babel/plugin-transform-shorthand-properties@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.2.0.tgz#6333aee2f8d6ee7e28615457298934a3b46198f0" + integrity sha512-QP4eUM83ha9zmYtpbnyjTLAGKQritA5XW/iG9cjtuOI8s1RuL/3V6a3DeSHfKutJQ+ayUfeZJPcnCYEQzaPQqg== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-spread@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.0.0.tgz#93583ce48dd8c85e53f3a46056c856e4af30b49b" - integrity sha512-L702YFy2EvirrR4shTj0g2xQp7aNwZoWNCkNu2mcoU0uyzMl0XRwDSwzB/xp6DSUFiBmEXuyAyEN16LsgVqGGQ== +"@babel/plugin-transform-spread@^7.2.0": + version "7.2.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.2.2.tgz#3103a9abe22f742b6d406ecd3cd49b774919b406" + integrity sha512-KWfky/58vubwtS0hLqEnrWJjsMGaOeSBn90Ezn5Jeg9Z8KKHmELbP1yGylMlm5N6TPKeY9A2+UaSYLdxahg01w== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-sticky-regex@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.0.0.tgz#30a9d64ac2ab46eec087b8530535becd90e73366" - integrity sha512-LFUToxiyS/WD+XEWpkx/XJBrUXKewSZpzX68s+yEOtIbdnsRjpryDw9U06gYc6klYEij/+KQVRnD3nz3AoKmjw== +"@babel/plugin-transform-sticky-regex@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.2.0.tgz#a1e454b5995560a9c1e0d537dfc15061fd2687e1" + integrity sha512-KKYCoGaRAf+ckH8gEL3JHUaFVyNHKe3ASNsZ+AlktgHevvxGigoIttrEJb8iKN03Q7Eazlv1s6cx2B2cQ3Jabw== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/helper-regex" "^7.0.0" -"@babel/plugin-transform-template-literals@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.0.0.tgz#084f1952efe5b153ddae69eb8945f882c7a97c65" - integrity sha512-vA6rkTCabRZu7Nbl9DfLZE1imj4tzdWcg5vtdQGvj+OH9itNNB6hxuRMHuIY8SGnEt1T9g5foqs9LnrHzsqEFg== +"@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== dependencies: "@babel/helper-annotate-as-pure" "^7.0.0" "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-typeof-symbol@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.0.0.tgz#4dcf1e52e943e5267b7313bff347fdbe0f81cec9" - integrity sha512-1r1X5DO78WnaAIvs5uC48t41LLckxsYklJrZjNKcevyz83sF2l4RHbw29qrCPr/6ksFsdfRpT/ZgxNWHXRnffg== +"@babel/plugin-transform-typeof-symbol@^7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.2.0.tgz#117d2bcec2fbf64b4b59d1f9819894682d29f2b2" + integrity sha512-2LNhETWYxiYysBtrBTqL8+La0jIoQQnIScUJc74OYvUGRmkskNY4EzLCnjHBzdmb38wqtTaixpo1NctEcvMDZw== dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-transform-unicode-regex@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.0.0.tgz#c6780e5b1863a76fe792d90eded9fcd5b51d68fc" - integrity sha512-uJBrJhBOEa3D033P95nPHu3nbFwFE9ZgXsfEitzoIXIwqAZWk7uXcg06yFKXz9FSxBH5ucgU/cYdX0IV8ldHKw== +"@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== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/helper-regex" "^7.0.0" regexpu-core "^4.1.3" "@babel/preset-env@^7.0.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.1.0.tgz#e67ea5b0441cfeab1d6f41e9b5c79798800e8d11" - integrity sha512-ZLVSynfAoDHB/34A17/JCZbyrzbQj59QC1Anyueb4Bwjh373nVPq5/HMph0z+tCmcDjXDe+DlKQq9ywQuvWrQg== + version "7.2.3" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.2.3.tgz#948c8df4d4609c99c7e0130169f052ea6a7a8933" + integrity sha512-AuHzW7a9rbv5WXmvGaPX7wADxFkZIqKlbBh1dmZUQp4iwiPpkE/Qnrji6SC4UQCQzvWY/cpHET29eUhXS9cLPw== dependencies: "@babel/helper-module-imports" "^7.0.0" "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-proposal-async-generator-functions" "^7.1.0" - "@babel/plugin-proposal-json-strings" "^7.0.0" - "@babel/plugin-proposal-object-rest-spread" "^7.0.0" - "@babel/plugin-proposal-optional-catch-binding" "^7.0.0" - "@babel/plugin-proposal-unicode-property-regex" "^7.0.0" - "@babel/plugin-syntax-async-generators" "^7.0.0" - "@babel/plugin-syntax-object-rest-spread" "^7.0.0" - "@babel/plugin-syntax-optional-catch-binding" "^7.0.0" - "@babel/plugin-transform-arrow-functions" "^7.0.0" - "@babel/plugin-transform-async-to-generator" "^7.1.0" - "@babel/plugin-transform-block-scoped-functions" "^7.0.0" - "@babel/plugin-transform-block-scoping" "^7.0.0" - "@babel/plugin-transform-classes" "^7.1.0" - "@babel/plugin-transform-computed-properties" "^7.0.0" - "@babel/plugin-transform-destructuring" "^7.0.0" - "@babel/plugin-transform-dotall-regex" "^7.0.0" - "@babel/plugin-transform-duplicate-keys" "^7.0.0" - "@babel/plugin-transform-exponentiation-operator" "^7.1.0" - "@babel/plugin-transform-for-of" "^7.0.0" - "@babel/plugin-transform-function-name" "^7.1.0" - "@babel/plugin-transform-literals" "^7.0.0" - "@babel/plugin-transform-modules-amd" "^7.1.0" - "@babel/plugin-transform-modules-commonjs" "^7.1.0" - "@babel/plugin-transform-modules-systemjs" "^7.0.0" - "@babel/plugin-transform-modules-umd" "^7.1.0" + "@babel/plugin-proposal-async-generator-functions" "^7.2.0" + "@babel/plugin-proposal-json-strings" "^7.2.0" + "@babel/plugin-proposal-object-rest-spread" "^7.2.0" + "@babel/plugin-proposal-optional-catch-binding" "^7.2.0" + "@babel/plugin-proposal-unicode-property-regex" "^7.2.0" + "@babel/plugin-syntax-async-generators" "^7.2.0" + "@babel/plugin-syntax-object-rest-spread" "^7.2.0" + "@babel/plugin-syntax-optional-catch-binding" "^7.2.0" + "@babel/plugin-transform-arrow-functions" "^7.2.0" + "@babel/plugin-transform-async-to-generator" "^7.2.0" + "@babel/plugin-transform-block-scoped-functions" "^7.2.0" + "@babel/plugin-transform-block-scoping" "^7.2.0" + "@babel/plugin-transform-classes" "^7.2.0" + "@babel/plugin-transform-computed-properties" "^7.2.0" + "@babel/plugin-transform-destructuring" "^7.2.0" + "@babel/plugin-transform-dotall-regex" "^7.2.0" + "@babel/plugin-transform-duplicate-keys" "^7.2.0" + "@babel/plugin-transform-exponentiation-operator" "^7.2.0" + "@babel/plugin-transform-for-of" "^7.2.0" + "@babel/plugin-transform-function-name" "^7.2.0" + "@babel/plugin-transform-literals" "^7.2.0" + "@babel/plugin-transform-modules-amd" "^7.2.0" + "@babel/plugin-transform-modules-commonjs" "^7.2.0" + "@babel/plugin-transform-modules-systemjs" "^7.2.0" + "@babel/plugin-transform-modules-umd" "^7.2.0" "@babel/plugin-transform-new-target" "^7.0.0" - "@babel/plugin-transform-object-super" "^7.1.0" - "@babel/plugin-transform-parameters" "^7.1.0" + "@babel/plugin-transform-object-super" "^7.2.0" + "@babel/plugin-transform-parameters" "^7.2.0" "@babel/plugin-transform-regenerator" "^7.0.0" - "@babel/plugin-transform-shorthand-properties" "^7.0.0" - "@babel/plugin-transform-spread" "^7.0.0" - "@babel/plugin-transform-sticky-regex" "^7.0.0" - "@babel/plugin-transform-template-literals" "^7.0.0" - "@babel/plugin-transform-typeof-symbol" "^7.0.0" - "@babel/plugin-transform-unicode-regex" "^7.0.0" - browserslist "^4.1.0" + "@babel/plugin-transform-shorthand-properties" "^7.2.0" + "@babel/plugin-transform-spread" "^7.2.0" + "@babel/plugin-transform-sticky-regex" "^7.2.0" + "@babel/plugin-transform-template-literals" "^7.2.0" + "@babel/plugin-transform-typeof-symbol" "^7.2.0" + "@babel/plugin-transform-unicode-regex" "^7.2.0" + browserslist "^4.3.4" invariant "^2.2.2" js-levenshtein "^1.1.3" semver "^5.3.0" "@babel/runtime@^7.0.0": - version "7.1.2" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.1.2.tgz#81c89935f4647706fc54541145e6b4ecfef4b8e3" - integrity sha512-Y3SCjmhSupzFB6wcv1KmmFucH6gDVnI30WjOcicV10ju0cZjak3Jcs67YLIXBrmZYw1xCrVeJPbycFwrqNyxpg== + version "7.2.0" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.2.0.tgz#b03e42eeddf5898e00646e4c840fa07ba8dcad7f" + integrity sha512-oouEibCbHMVdZSDlJBO6bZmID/zA/G/Qx3H1d3rSNPTD+L8UNKvCat7aKWSJ74zYbm5zWGh0GQN0hKj8zYFTCg== dependencies: regenerator-runtime "^0.12.0" -"@babel/template@^7.0.0", "@babel/template@^7.1.0", "@babel/template@^7.1.2": - version "7.1.2" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.1.2.tgz#090484a574fef5a2d2d7726a674eceda5c5b5644" - integrity sha512-SY1MmplssORfFiLDcOETrW7fCLl+PavlwMh92rrGcikQaRq4iWPVH0MpwPpY3etVMx6RnDjXtr6VZYr/IbP/Ag== +"@babel/template@^7.0.0", "@babel/template@^7.1.0", "@babel/template@^7.1.2", "@babel/template@^7.2.2": + version "7.2.2" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.2.2.tgz#005b3fdf0ed96e88041330379e0da9a708eb2907" + integrity sha512-zRL0IMM02AUDwghf5LMSSDEz7sBCO2YnNmpg3uWTZj/v1rcG2BmQUvaGU8GhU8BvfMh1k2KIAYZ7Ji9KXPUg7g== dependencies: "@babel/code-frame" "^7.0.0" - "@babel/parser" "^7.1.2" - "@babel/types" "^7.1.2" + "@babel/parser" "^7.2.2" + "@babel/types" "^7.2.2" -"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0": - version "7.1.4" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.1.4.tgz#f4f83b93d649b4b2c91121a9087fa2fa949ec2b4" - integrity sha512-my9mdrAIGdDiSVBuMjpn/oXYpva0/EZwWL3sm3Wcy/AVWO2eXnsoZruOT9jOGNRXU8KbCIu5zsKnXcAJ6PcV6Q== +"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.1.5", "@babel/traverse@^7.2.2", "@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== dependencies: "@babel/code-frame" "^7.0.0" - "@babel/generator" "^7.1.3" + "@babel/generator" "^7.2.2" "@babel/helper-function-name" "^7.1.0" "@babel/helper-split-export-declaration" "^7.0.0" - "@babel/parser" "^7.1.3" - "@babel/types" "^7.1.3" - debug "^3.1.0" + "@babel/parser" "^7.2.3" + "@babel/types" "^7.2.2" + debug "^4.1.0" globals "^11.1.0" lodash "^4.17.10" -"@babel/types@^7.0.0", "@babel/types@^7.1.2", "@babel/types@^7.1.3": - version "7.1.3" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.1.3.tgz#3a767004567060c2f40fca49a304712c525ee37d" - integrity sha512-RpPOVfK+yatXyn8n4PB1NW6k9qjinrXrRR8ugBN8fD6hCy5RXI6PSbVqpOJBO9oSaY7Nom4ohj35feb0UR9hSA== +"@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== dependencies: esutils "^2.0.2" lodash "^4.17.10" to-fast-properties "^2.0.0" -"@lerna/add@^3.6.0": - version "3.6.0" - resolved "https://registry.yarnpkg.com/@lerna/add/-/add-3.6.0.tgz#eea53efff0b3237774ddac6eaa84957140e89238" - integrity sha512-aFVekkHMno3hj1Vg3EiIpAwrZ4g34i8z4KrCx7ATY6BRuxVT4Nt/Nk3l2k6gEOq3tWUDtUctLHxIAo14FI8sng== - dependencies: - "@lerna/bootstrap" "^3.6.0" - "@lerna/command" "^3.6.0" - "@lerna/filter-options" "^3.6.0" - "@lerna/npm-conf" "^3.4.1" +"@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== + +"@lerna/add@^3.8.5": + version "3.8.5" + resolved "https://registry.yarnpkg.com/@lerna/add/-/add-3.8.5.tgz#f7dec6b9ce20bc42d64bbb29381b62a918c8c7aa" + integrity sha512-jySRqLaROejfBriA4cFdc1AlSoeQ/0f6uocdIgkFFHwWyU65j48fdLlERRDE6t2iTwh4u+UVnK5eIglGBJUqEA== + dependencies: + "@lerna/bootstrap" "^3.8.5" + "@lerna/command" "^3.8.5" + "@lerna/filter-options" "^3.8.1" + "@lerna/npm-conf" "^3.7.0" "@lerna/validation-error" "^3.6.0" dedent "^0.7.0" libnpm "^2.0.1" @@ -653,23 +658,23 @@ "@lerna/validation-error" "^3.6.0" libnpm "^2.0.1" -"@lerna/bootstrap@^3.6.0": - version "3.6.0" - resolved "https://registry.yarnpkg.com/@lerna/bootstrap/-/bootstrap-3.6.0.tgz#a47cd484ad60638d518a606d627b9997d5f7c960" - integrity sha512-z6rZQw/aLEN+ragWRYqIIVwA9rDv3QtmRc5VyIRrlV/JiuGpq67FcSR6BrCMc/A7UJ9Kx95+bESm/HUwheKoiQ== +"@lerna/bootstrap@^3.8.5": + version "3.8.5" + resolved "https://registry.yarnpkg.com/@lerna/bootstrap/-/bootstrap-3.8.5.tgz#0063763aa2ad8f8dec96dd92f42a01e053fa7290" + integrity sha512-AF46juyExojRndbFU5K9xX+IkvqDlaGsGzYxVaDn2o4xQwC/TnvtCuIooEKgDcVkhyTHhBi+PNr5RWcRm/IhxA== dependencies: "@lerna/batch-packages" "^3.6.0" - "@lerna/command" "^3.6.0" - "@lerna/filter-options" "^3.6.0" + "@lerna/command" "^3.8.5" + "@lerna/filter-options" "^3.8.1" "@lerna/has-npm-version" "^3.3.0" - "@lerna/npm-conf" "^3.4.1" - "@lerna/npm-install" "^3.6.0" + "@lerna/npm-install" "^3.8.2" "@lerna/package-graph" "^3.6.0" + "@lerna/pulse-till-done" "^3.7.1" "@lerna/rimraf-dir" "^3.6.0" - "@lerna/run-lifecycle" "^3.6.0" + "@lerna/run-lifecycle" "^3.8.2" "@lerna/run-parallel-batches" "^3.0.0" - "@lerna/symlink-binary" "^3.6.0" - "@lerna/symlink-dependencies" "^3.6.0" + "@lerna/symlink-binary" "^3.7.2" + "@lerna/symlink-dependencies" "^3.8.1" "@lerna/validation-error" "^3.6.0" dedent "^0.7.0" get-port "^3.2.0" @@ -682,23 +687,23 @@ read-package-tree "^5.1.6" semver "^5.5.0" -"@lerna/changed@^3.6.0": - version "3.6.0" - resolved "https://registry.yarnpkg.com/@lerna/changed/-/changed-3.6.0.tgz#a6c97b9c4829d294a1d8e8a7140667bc89c996e2" - integrity sha512-L1SXTtQrsv+4F5Knw5sW/nGnMJq+bbOzhZX2srJ10WsuHuzk3cJWAi7dVEsS3RPKUw9DWOuHKy86o3v6byEiqA== +"@lerna/changed@^3.8.5": + version "3.8.5" + resolved "https://registry.yarnpkg.com/@lerna/changed/-/changed-3.8.5.tgz#fe2712c66caf768a31568b4b6b864c664d084298" + integrity sha512-VIRldHvs0niGVnrZjGw2oi7MWY50vh5AkZ2E6XQFP5guHjPWF18SdRa0p0oLf4Ci+I3KskFNjzJS0dMSnmP+BA== dependencies: - "@lerna/collect-updates" "^3.6.0" - "@lerna/command" "^3.6.0" + "@lerna/collect-updates" "^3.8.1" + "@lerna/command" "^3.8.5" "@lerna/listable" "^3.6.0" "@lerna/output" "^3.6.0" - "@lerna/version" "^3.6.0" + "@lerna/version" "^3.8.5" -"@lerna/check-working-tree@^3.6.0": - version "3.6.0" - resolved "https://registry.yarnpkg.com/@lerna/check-working-tree/-/check-working-tree-3.6.0.tgz#638ee7f5976fe607d544629b1ef4ae67887984b5" - integrity sha512-Ioy1t2aVasAwhY1Oi5kfpwbW9RDupxxVVu2t2c1EeBYYCu3jIt1A5ad34gidgsKyiG3HeBEVziI4Uaihnb96ZQ== +"@lerna/check-working-tree@^3.8.1": + version "3.8.1" + resolved "https://registry.yarnpkg.com/@lerna/check-working-tree/-/check-working-tree-3.8.1.tgz#bda0719f3a3ceaed976b08f57b054af6a0acf295" + integrity sha512-UJqyvFr3+MTDo31fVjJlV/eshmQg8u0vpQcY95Vs00B99QxzLoICSGpNdldhSBnOIpOlq6tm5H/2hflc5hANew== dependencies: - "@lerna/describe-ref" "^3.6.0" + "@lerna/describe-ref" "^3.8.1" "@lerna/validation-error" "^3.6.0" "@lerna/child-process@^3.3.0": @@ -710,14 +715,15 @@ execa "^1.0.0" strong-log-transformer "^2.0.0" -"@lerna/clean@^3.6.0": - version "3.6.0" - resolved "https://registry.yarnpkg.com/@lerna/clean/-/clean-3.6.0.tgz#9a9d73324389cba694b19a913229c19d58e62485" - integrity sha512-4LodI/jh8IEYtqnrY/OFSpWn5YfDWoDv+5QjiJpd91EjW9vjmkvyhzQ5fG9KtltwgYVn/NJ5zlI1WfmMEXvFFQ== +"@lerna/clean@^3.8.5": + version "3.8.5" + resolved "https://registry.yarnpkg.com/@lerna/clean/-/clean-3.8.5.tgz#42ec3b70a032b38bbdcac6ea804baf2df22432cf" + integrity sha512-fYym9Lj0szbW5Z+QQuXFgsdtoe3VQxfwgFOWDDpnDr4DpjKrKulwYkR15Cx+Lc6gpjYGlM8bmi/KOFtaLfKwcQ== dependencies: - "@lerna/command" "^3.6.0" - "@lerna/filter-options" "^3.6.0" + "@lerna/command" "^3.8.5" + "@lerna/filter-options" "^3.8.1" "@lerna/prompt" "^3.6.0" + "@lerna/pulse-till-done" "^3.7.1" "@lerna/rimraf-dir" "^3.6.0" p-map "^1.2.0" p-map-series "^1.0.0" @@ -733,25 +739,25 @@ libnpm "^2.0.1" yargs "^12.0.1" -"@lerna/collect-updates@^3.6.0": - version "3.6.0" - resolved "https://registry.yarnpkg.com/@lerna/collect-updates/-/collect-updates-3.6.0.tgz#8520d64852c5059b453db53afee22539853f2bde" - integrity sha512-knliEz3phY51SGnwDhhYqx6SJN6y9qh/gZrZgQ7ogqz1UgA/MyJb27gszjsyyG6jUQshimBpjsG7OMwjt8+n9A== +"@lerna/collect-updates@^3.8.1": + version "3.8.1" + resolved "https://registry.yarnpkg.com/@lerna/collect-updates/-/collect-updates-3.8.1.tgz#e227efe9955b56b258baf7e8f853f779d40556a7" + integrity sha512-1ULd1FBX8j8XGe166CUx+PkNeBJrbauI6Ux9+NiVrpeyE5rF6hzrowRyaptE9n5jzAl0WtTTIP1MsdrVG7BvAA== dependencies: "@lerna/child-process" "^3.3.0" - "@lerna/describe-ref" "^3.6.0" + "@lerna/describe-ref" "^3.8.1" libnpm "^2.0.1" minimatch "^3.0.4" slash "^1.0.0" -"@lerna/command@^3.6.0": - version "3.6.0" - resolved "https://registry.yarnpkg.com/@lerna/command/-/command-3.6.0.tgz#b3289d1f72d2bebb7375d424b1778121a3d4e82c" - integrity sha512-BGpXaY2WrxPcIiZX0aATO2HQBatvYT7Qy46lqMnV9RrTePYJ1PPbX1nMzLXSxgrnnlTcTwJNEkw/TL9Xzrph7Q== +"@lerna/command@^3.8.5": + version "3.8.5" + resolved "https://registry.yarnpkg.com/@lerna/command/-/command-3.8.5.tgz#b551f3a83c87258c8e9eb681dec95542df849119" + integrity sha512-NkLuA46RlL+LZ6lyXcuhJKbiS0LgnvRj0uwkxre2yHFDRnUdoCLXEXcslHO+fcM0ROOPYOa8rWEb2uGplfM1ug== dependencies: "@lerna/child-process" "^3.3.0" "@lerna/package-graph" "^3.6.0" - "@lerna/project" "^3.6.0" + "@lerna/project" "^3.8.5" "@lerna/validation-error" "^3.6.0" "@lerna/write-log-file" "^3.6.0" dedent "^0.7.0" @@ -783,14 +789,14 @@ fs-extra "^7.0.0" libnpm "^2.0.1" -"@lerna/create@^3.6.0": - version "3.6.0" - resolved "https://registry.yarnpkg.com/@lerna/create/-/create-3.6.0.tgz#4540c9ee69f63d11b3138eb5eac1942348643af1" - integrity sha512-21OunW25Y3Q/oynqWVk0znQFBvZ5tHyLPhzkJeomGmOj0il1RdOUiChu9G9AYsCaLDwBFR0ZFqvTgJ5iw/eaIg== +"@lerna/create@^3.8.5": + version "3.8.5" + resolved "https://registry.yarnpkg.com/@lerna/create/-/create-3.8.5.tgz#c4d41e879110f3cbc842d93d90f2f827413e8e8e" + integrity sha512-Kgkp4jttk1ElBT2A0WiCBC5E/KWU5dnt4iCmXRqcEe5ZaV+Jd669llkp26mDY2/wx9Tjdh+CaZO54PTrVZnAZQ== dependencies: "@lerna/child-process" "^3.3.0" - "@lerna/command" "^3.6.0" - "@lerna/npm-conf" "^3.4.1" + "@lerna/command" "^3.8.5" + "@lerna/npm-conf" "^3.7.0" "@lerna/validation-error" "^3.6.0" camelcase "^4.1.0" dedent "^0.7.0" @@ -806,42 +812,42 @@ validate-npm-package-name "^3.0.0" whatwg-url "^7.0.0" -"@lerna/describe-ref@^3.6.0": - version "3.6.0" - resolved "https://registry.yarnpkg.com/@lerna/describe-ref/-/describe-ref-3.6.0.tgz#29eda334c81cd4c0a2942f309936bcb69a4543a0" - integrity sha512-hVZJ2hYVbrrNiEG+dEg/Op4pYAbROkDZdiIUabAJffr0T/frcN+5es2HfmOC//4+78Cs1M9iTyQRoyC1RXS2BQ== +"@lerna/describe-ref@^3.8.1": + version "3.8.1" + resolved "https://registry.yarnpkg.com/@lerna/describe-ref/-/describe-ref-3.8.1.tgz#b99ef6f8aa58fa9389af1e03beaa716cc6cb506d" + integrity sha512-EPXFiZbWG0KiaDM+BT3RZahy5gwrTVyKDv8HmPkGhu2h4pr34tzsSMmYmJ8I0dLeu4IpP/G/OIBa6DkYWisiZw== dependencies: "@lerna/child-process" "^3.3.0" libnpm "^2.0.1" -"@lerna/diff@^3.6.0": - version "3.6.0" - resolved "https://registry.yarnpkg.com/@lerna/diff/-/diff-3.6.0.tgz#ea8a77e712daf951c05316c81fe4065bf6b5e22c" - integrity sha512-p5+VyYKuAnw6NFVrT4s9eBubFZEYlJmiR1mdVlwNtohqS86gERjrPtI0unUK/pxFKb1U2ZNo4fhSlPd+pLwfHg== +"@lerna/diff@^3.8.5": + version "3.8.5" + resolved "https://registry.yarnpkg.com/@lerna/diff/-/diff-3.8.5.tgz#4f68fc9833bf722d2d7bea2be33e5e09d3651d92" + integrity sha512-20aT02ryjHwWwrLMdBZat6Wz3SzMUy3eoJ0IcNnmdz1ju9TKms3ImeeuAwFIJ1q71jQFSYT9HGDR0d3Yq5WVhw== dependencies: "@lerna/child-process" "^3.3.0" - "@lerna/command" "^3.6.0" + "@lerna/command" "^3.8.5" "@lerna/validation-error" "^3.6.0" libnpm "^2.0.1" -"@lerna/exec@^3.6.0": - version "3.6.0" - resolved "https://registry.yarnpkg.com/@lerna/exec/-/exec-3.6.0.tgz#757e96e890e436a31efc59dc72c5a7c2944d1a44" - integrity sha512-lwLYASpS8FoQpVYLBpoZlS7bpzkO9pD3D9XeDDKZBodDhdZeCEx2Md2CxZU1RKYDSVIXA8oObvlUh1FEhRQv2w== +"@lerna/exec@^3.8.5": + version "3.8.5" + resolved "https://registry.yarnpkg.com/@lerna/exec/-/exec-3.8.5.tgz#ab95de1bec09789e4ff3b2f7683c7f565eaeed38" + integrity sha512-lcblv2lQpKTk2sRAzV+VrHcZhHoFO9GVyZDAY6uEeQHlY2NoydeSwXT7g+jUbmhAqypptjyIeM8V3wnCu9nnrw== dependencies: "@lerna/batch-packages" "^3.6.0" "@lerna/child-process" "^3.3.0" - "@lerna/command" "^3.6.0" - "@lerna/filter-options" "^3.6.0" + "@lerna/command" "^3.8.5" + "@lerna/filter-options" "^3.8.1" "@lerna/run-parallel-batches" "^3.0.0" "@lerna/validation-error" "^3.6.0" -"@lerna/filter-options@^3.6.0": - version "3.6.0" - resolved "https://registry.yarnpkg.com/@lerna/filter-options/-/filter-options-3.6.0.tgz#8100a3f2e18a9772a61138711e1fe1f14969f814" - integrity sha512-6iUMZuvvXPL5EAF7Zo9azaZ6FxOq6tGbiSX8fUXgCdN+jlRjorvkzR+E0HS4bEGTWmV446lnLwdQLZuySfLcbQ== +"@lerna/filter-options@^3.8.1": + version "3.8.1" + resolved "https://registry.yarnpkg.com/@lerna/filter-options/-/filter-options-3.8.1.tgz#8c9708d60681383051d90a06eaa292dddd1d16b4" + integrity sha512-ty4Pl+vZjPSc7jc4nhK/4YYGKpLOhcGHLw6Zu71D4V3DJW/ZDHm/veRIApmhddL7+6y9G+ZGnGYYh/8RFyT6hA== dependencies: - "@lerna/collect-updates" "^3.6.0" + "@lerna/collect-updates" "^3.8.1" "@lerna/filter-packages" "^3.6.0" dedent "^0.7.0" @@ -861,6 +867,15 @@ dependencies: libnpm "^2.0.1" +"@lerna/get-packed@^3.7.0": + version "3.7.0" + resolved "https://registry.yarnpkg.com/@lerna/get-packed/-/get-packed-3.7.0.tgz#549c7738f7be5e3b1433e82ed9cda9123bcd1ed5" + integrity sha512-yuFtjsUZIHjeIvIYQ/QuytC+FQcHwo3peB+yGBST2uWCLUCR5rx6knoQcPzbxdFDCuUb5IFccFGd3B1fHFg3RQ== + dependencies: + fs-extra "^7.0.0" + ssri "^6.0.1" + tar "^4.4.8" + "@lerna/global-options@^3.1.3": version "3.1.3" resolved "https://registry.yarnpkg.com/@lerna/global-options/-/global-options-3.1.3.tgz#cf85e24655a91d04d4efc9a80c1f83fc768d08ae" @@ -874,48 +889,49 @@ "@lerna/child-process" "^3.3.0" semver "^5.5.0" -"@lerna/import@^3.6.0": - version "3.6.0" - resolved "https://registry.yarnpkg.com/@lerna/import/-/import-3.6.0.tgz#84ef5eea61ab9a284054be32367906d092aadab5" - integrity sha512-8jxNRbAaa4mvMJr0u+sy75gMFPyWfxLHEp+pDs73x1oqMZhpS8O5901QMnpZyRyOvJRhoBJd5hBX2dpsLxC6Xw== +"@lerna/import@^3.8.5": + version "3.8.5" + resolved "https://registry.yarnpkg.com/@lerna/import/-/import-3.8.5.tgz#143e96b29c64ae060882e49ecf6b583ae87e10f9" + integrity sha512-6mT4rYafszXdUOCKDfOGi/oOD+mKeoH1nn8z97PPm9V8b79c/TOROJ0vrjtRa9bS/5BpXMRKTRwq2BV+z5UiIA== dependencies: "@lerna/child-process" "^3.3.0" - "@lerna/command" "^3.6.0" + "@lerna/command" "^3.8.5" "@lerna/prompt" "^3.6.0" + "@lerna/pulse-till-done" "^3.7.1" "@lerna/validation-error" "^3.6.0" dedent "^0.7.0" fs-extra "^7.0.0" p-map-series "^1.0.0" -"@lerna/init@^3.6.0": - version "3.6.0" - resolved "https://registry.yarnpkg.com/@lerna/init/-/init-3.6.0.tgz#6e23c3db632b713e23250d33519ed844a79a145e" - integrity sha512-MTLy3rmMdvpXRmDdoYiVPx7I8sXH4dquq/0MxntL5VxSVh/ZS1HsbrjyRqpdkUKWD9QguxR/w0pzOjVvCeM8CQ== +"@lerna/init@^3.8.5": + version "3.8.5" + resolved "https://registry.yarnpkg.com/@lerna/init/-/init-3.8.5.tgz#c5e11ba0bf4df258538c1718e74897a4d6d23c4a" + integrity sha512-yVQmEqPY0WkXXv9HgKSiEC845PK/zQ6ejQKQbh83fV59VTkLLaLXJoCcj7OsiMiNlKdN92LxiNHE/T25Zrwokg== dependencies: "@lerna/child-process" "^3.3.0" - "@lerna/command" "^3.6.0" + "@lerna/command" "^3.8.5" fs-extra "^7.0.0" p-map "^1.2.0" write-json-file "^2.3.0" -"@lerna/link@^3.6.0": - version "3.6.0" - resolved "https://registry.yarnpkg.com/@lerna/link/-/link-3.6.0.tgz#490f14216b489fd66d9d3d3d0765f75dbbf52178" - integrity sha512-Xk8TTAE4EWGyhxLuPxWdyS7i7vfsM5igb6tEyhZm94XUdlA4PmMOYe25BfO7SM/9LYroFknZeDyWAebye3r+PA== +"@lerna/link@^3.8.5": + version "3.8.5" + resolved "https://registry.yarnpkg.com/@lerna/link/-/link-3.8.5.tgz#6a7060e0e7f3d99f3f3b9ccdeab5b46f6f8c836a" + integrity sha512-Xd4A5rLP5780KJ6eVqbRhkHFGCw+lfBgHr8imXwaaou7IuZv7Sh69C8YcceyQHQLwJsjNT7LaX1VXbPe4Hs1rw== dependencies: - "@lerna/command" "^3.6.0" + "@lerna/command" "^3.8.5" "@lerna/package-graph" "^3.6.0" - "@lerna/symlink-dependencies" "^3.6.0" + "@lerna/symlink-dependencies" "^3.8.1" p-map "^1.2.0" slash "^1.0.0" -"@lerna/list@^3.6.0": - version "3.6.0" - resolved "https://registry.yarnpkg.com/@lerna/list/-/list-3.6.0.tgz#18ae4b1e375ef1329261c9d21be27098ca0edf63" - integrity sha512-hlQOJkg8K3XXUVXotofP71XsgkhXkkmU/EkqlNg15D78MjzhT+p1wCbG5m89K3tzvjcWVeZwU6L0elaOIXVyCw== +"@lerna/list@^3.8.5": + version "3.8.5" + resolved "https://registry.yarnpkg.com/@lerna/list/-/list-3.8.5.tgz#3b2a80ed8f3fc7ea8ab97ea45cbedcb0d3258f5e" + integrity sha512-YfPllSZkw29ZDHOGBut8ju5WOLvYopqlb2KOWgmhJOMO+7P9f5Hm1A+/cjVvPQlEmV8RDgc7t4lOuC9sAfXBSA== dependencies: - "@lerna/command" "^3.6.0" - "@lerna/filter-options" "^3.6.0" + "@lerna/command" "^3.8.5" + "@lerna/filter-options" "^3.8.1" "@lerna/listable" "^3.6.0" "@lerna/output" "^3.6.0" @@ -938,26 +954,26 @@ has-unicode "^2.0.1" libnpm "^2.0.1" -"@lerna/npm-conf@^3.4.1": - version "3.4.1" - resolved "https://registry.yarnpkg.com/@lerna/npm-conf/-/npm-conf-3.4.1.tgz#859e931b0bc9a5eed86309cc09508810c1e7d121" - integrity sha512-i9G6DnbCqiAqxKx2rSXej/n14qxlV/XOebL6QZonxJKzNTB+Q2wglnhTXmfZXTPJfoqimLaY4NfAEtbOXRWOXQ== +"@lerna/npm-conf@^3.7.0": + version "3.7.0" + resolved "https://registry.yarnpkg.com/@lerna/npm-conf/-/npm-conf-3.7.0.tgz#f101d4fdf07cefcf1161bcfaf3c0f105b420a450" + integrity sha512-+WSMDfPKcKzMfqq283ydz9RRpOU6p9wfx0wy4hVSUY/6YUpsyuk8SShjcRtY8zTM5AOrxvFBuuV90H4YpZ5+Ng== dependencies: config-chain "^1.1.11" pify "^3.0.0" -"@lerna/npm-dist-tag@^3.6.0": - version "3.6.0" - resolved "https://registry.yarnpkg.com/@lerna/npm-dist-tag/-/npm-dist-tag-3.6.0.tgz#8f8c8567810bd9ee1c1277a71b57cec1acc101f4" - integrity sha512-qX6IfQPX9Tum1LRjvjgj/yr2FYbc9dfHyeh7RI9zJ8pGncWbksBmnMcvoxF0Eu4+d7MjjIGfEnIp9LIl4MHSIA== +"@lerna/npm-dist-tag@^3.8.5": + version "3.8.5" + resolved "https://registry.yarnpkg.com/@lerna/npm-dist-tag/-/npm-dist-tag-3.8.5.tgz#5ce22a72576badc8cb6baf85550043d63e66ea44" + integrity sha512-VO57yKTB4NC2LZuTd4w0LmlRpoFm/gejQ1gqqLGzSJuSZaBXmieElFovzl21S07cqiy7FNVdz75x7/a6WCZ6XA== dependencies: + figgy-pudding "^3.5.1" libnpm "^2.0.1" - npm-registry-fetch "^3.8.0" -"@lerna/npm-install@^3.6.0": - version "3.6.0" - resolved "https://registry.yarnpkg.com/@lerna/npm-install/-/npm-install-3.6.0.tgz#314fc0d0c35429e2b5db1e7de87b3ddb1ab77606" - integrity sha512-RKV31VdrBZKjmKfq25JG4mIHJ8NAOsLKq/aYSaBs8zP+uwXH7RU39saVfv9ReKiAzhKE2ghOG2JeMdIHtYnPNA== +"@lerna/npm-install@^3.8.2": + version "3.8.2" + resolved "https://registry.yarnpkg.com/@lerna/npm-install/-/npm-install-3.8.2.tgz#24c7271a62bd3ec03275cf0a1c5fbafef4955f42" + integrity sha512-A22IrhPy70Gm30rBYSPp/PDWjByvj6QdxqQh41HlNGOCzM5WCCSDXpfeoxzS0ow0d3WGJMraE2k1GFpOP6Hyxg== dependencies: "@lerna/child-process" "^3.3.0" "@lerna/get-npm-exec-opts" "^3.6.0" @@ -966,18 +982,15 @@ signal-exit "^3.0.2" write-pkg "^3.1.0" -"@lerna/npm-publish@^3.6.0": - version "3.6.0" - resolved "https://registry.yarnpkg.com/@lerna/npm-publish/-/npm-publish-3.6.0.tgz#8981a9744779c55955a8c4249fe6b44a0485f9d3" - integrity sha512-k4yF8ursajoGRlJeRh7xdeGN0HV/ALt5qImUnpTliux0213jqxA0YigiD8WSaXpvSqxSFyvh38DbJhhy9q+NuQ== +"@lerna/npm-publish@^3.8.5": + version "3.8.5" + resolved "https://registry.yarnpkg.com/@lerna/npm-publish/-/npm-publish-3.8.5.tgz#c6718be54dff1e7b701aed7763b213d2002b988d" + integrity sha512-cXmgiOhOKP9Ew+SncmE5ZQpEWA3mTcG5ItG5EUWAd/h9WwYOTCr7SD67lOlrkge/xw8dUQd0iDNz2QxDrpQaUg== dependencies: - "@lerna/child-process" "^3.3.0" - "@lerna/get-npm-exec-opts" "^3.6.0" - "@lerna/has-npm-version" "^3.3.0" - "@lerna/log-packed" "^3.6.0" + "@lerna/run-lifecycle" "^3.8.2" + figgy-pudding "^3.5.1" fs-extra "^7.0.0" libnpm "^2.0.1" - p-map "^1.2.0" "@lerna/npm-run-script@^3.6.0": version "3.6.0" @@ -995,6 +1008,20 @@ dependencies: libnpm "^2.0.1" +"@lerna/pack-directory@^3.8.2": + version "3.8.2" + resolved "https://registry.yarnpkg.com/@lerna/pack-directory/-/pack-directory-3.8.2.tgz#5ffddce7781998195cffcbe51128c5a69dd3ca7a" + integrity sha512-sYXioixVw3L5r9O4bt+hnfPQ8jLn/PVOJVivQdpSlup+ZUiI5mmtjzAO3NOK/k8DZf8YrUx0Lm1+vzgnqu1tKw== + dependencies: + "@lerna/get-packed" "^3.7.0" + "@lerna/package" "^3.7.2" + "@lerna/run-lifecycle" "^3.8.2" + figgy-pudding "^3.5.1" + libnpm "^2.0.1" + npm-packlist "^1.1.12" + tar "^4.4.8" + temp-write "^3.4.0" + "@lerna/package-graph@^3.6.0": version "3.6.0" resolved "https://registry.yarnpkg.com/@lerna/package-graph/-/package-graph-3.6.0.tgz#d13e6e80d30e2e29226d335412997b9ddf646305" @@ -1004,20 +1031,21 @@ libnpm "^2.0.1" semver "^5.5.0" -"@lerna/package@^3.6.0": - version "3.6.0" - resolved "https://registry.yarnpkg.com/@lerna/package/-/package-3.6.0.tgz#1095b91d277820b7ae8a2cfeeb73d57c6cd9b17e" - integrity sha512-XbXcjwPKA1V640mqjEicpBriO6QcNtocdfLAtEUP4uCKkRx5r9h7DdznQMCoSJYJF6Gh/PpLokPUItfMhJP3Hg== +"@lerna/package@^3.7.2": + version "3.7.2" + resolved "https://registry.yarnpkg.com/@lerna/package/-/package-3.7.2.tgz#03c69fd7fb965c372c8c969165a2f7d6dfe2dfcb" + integrity sha512-8A5hN2CekM1a0Ix4VUO/g+REo+MsnXb8lnQ0bGjr1YGWzSL5NxYJ0Z9+0pwTfDpvRDYlFYO0rMVwBUW44b4dUw== dependencies: libnpm "^2.0.1" + load-json-file "^4.0.0" write-pkg "^3.1.0" -"@lerna/project@^3.6.0": - version "3.6.0" - resolved "https://registry.yarnpkg.com/@lerna/project/-/project-3.6.0.tgz#b5dd2b94fae6f58478be1c53962c2570498867ab" - integrity sha512-pEOZF1igGFqs+qWog6cJWqVyBUX21xSqrlcgeN0yzqzI36VMHozmf/u7dgclIb5MylWk5Yp87KCKswBF4hrcuQ== +"@lerna/project@^3.8.5": + version "3.8.5" + resolved "https://registry.yarnpkg.com/@lerna/project/-/project-3.8.5.tgz#7177d74ad4a9fa6b709ae4f29d64951165332565" + integrity sha512-D0no5qrfKGxFkUOypUFCsT1iZww0ioW2zbwyUqvWal5ut/lH9+T7RLFxSKVfo+tuJTT0zqCITHBtsA3G/wwNDg== dependencies: - "@lerna/package" "^3.6.0" + "@lerna/package" "^3.7.2" "@lerna/validation-error" "^3.6.0" cosmiconfig "^5.0.2" dedent "^0.7.0" @@ -1038,36 +1066,45 @@ inquirer "^6.2.0" libnpm "^2.0.1" -"@lerna/publish@^3.6.0": - version "3.6.0" - resolved "https://registry.yarnpkg.com/@lerna/publish/-/publish-3.6.0.tgz#7985b8c549c83114180e99a9e291e8b82db57aac" - integrity sha512-F2bT96ZS7NJfid6T4a6TSanpVUQ4VOuhjPBPX2hagt5gnocm7lluvAFR7dl/cbEgmKIg2zJQnfAPTYjrtxXMVg== +"@lerna/publish@^3.8.5": + version "3.8.5" + resolved "https://registry.yarnpkg.com/@lerna/publish/-/publish-3.8.5.tgz#27437c44e76c5f2f71af339275c5582f80bd769c" + integrity sha512-F+68eSYlI16INIpWLXjprArsh1tFvSeEqaJEMCCu5NUAWHlCvds/+L5RJZDXatWFppRsNR6dlYKdM9FbAZHuLw== dependencies: "@lerna/batch-packages" "^3.6.0" - "@lerna/check-working-tree" "^3.6.0" + "@lerna/check-working-tree" "^3.8.1" "@lerna/child-process" "^3.3.0" - "@lerna/collect-updates" "^3.6.0" - "@lerna/command" "^3.6.0" - "@lerna/describe-ref" "^3.6.0" - "@lerna/get-npm-exec-opts" "^3.6.0" - "@lerna/npm-conf" "^3.4.1" - "@lerna/npm-dist-tag" "^3.6.0" - "@lerna/npm-publish" "^3.6.0" + "@lerna/collect-updates" "^3.8.1" + "@lerna/command" "^3.8.5" + "@lerna/describe-ref" "^3.8.1" + "@lerna/log-packed" "^3.6.0" + "@lerna/npm-conf" "^3.7.0" + "@lerna/npm-dist-tag" "^3.8.5" + "@lerna/npm-publish" "^3.8.5" "@lerna/output" "^3.6.0" + "@lerna/pack-directory" "^3.8.2" "@lerna/prompt" "^3.6.0" - "@lerna/run-lifecycle" "^3.6.0" + "@lerna/pulse-till-done" "^3.7.1" + "@lerna/run-lifecycle" "^3.8.2" "@lerna/run-parallel-batches" "^3.0.0" "@lerna/validation-error" "^3.6.0" - "@lerna/version" "^3.6.0" + "@lerna/version" "^3.8.5" + figgy-pudding "^3.5.1" fs-extra "^7.0.0" libnpm "^2.0.1" - npm-registry-fetch "^3.8.0" p-finally "^1.0.0" p-map "^1.2.0" p-pipe "^1.2.0" p-reduce "^1.0.0" semver "^5.5.0" +"@lerna/pulse-till-done@^3.7.1": + version "3.7.1" + resolved "https://registry.yarnpkg.com/@lerna/pulse-till-done/-/pulse-till-done-3.7.1.tgz#a9e55380fa18f6896a3e5b23621a4227adfb8f85" + integrity sha512-MzpesZeW3Mc+CiAq4zUt9qTXI9uEBBKrubYHE36voQTSkHvu/Rox6YOvfUr+U7P6k8frFPeCgGpfMDTLhiqe6w== + dependencies: + libnpm "^2.0.1" + "@lerna/resolve-symlink@^3.6.0": version "3.6.0" resolved "https://registry.yarnpkg.com/@lerna/resolve-symlink/-/resolve-symlink-3.6.0.tgz#985344796b704ff32afa923901e795e80741b86e" @@ -1087,12 +1124,13 @@ path-exists "^3.0.0" rimraf "^2.6.2" -"@lerna/run-lifecycle@^3.6.0": - version "3.6.0" - resolved "https://registry.yarnpkg.com/@lerna/run-lifecycle/-/run-lifecycle-3.6.0.tgz#2381fd827b4a4135613e7d73d25ae76b7af5e6ef" - integrity sha512-/1+vAZnckgKwHVgWG0plVO24erNWUduz9htMOO9wuOfglTnHlMRqDc3s9B/OIKxGDkyzEvxqzfzq3c6JqEolRQ== +"@lerna/run-lifecycle@^3.8.2": + version "3.8.2" + resolved "https://registry.yarnpkg.com/@lerna/run-lifecycle/-/run-lifecycle-3.8.2.tgz#fe97f771506e2351aa170ec75ef8e6d7e9b94509" + integrity sha512-V80nIoHpp0IL9WEaK8wz47SeqLSlI8DyNqVqUoG1DCeCGr6rdvRGD0FgHSKgRnZxk/SgP1Az/YBBtc5qnA+CzA== dependencies: - "@lerna/npm-conf" "^3.4.1" + "@lerna/npm-conf" "^3.7.0" + figgy-pudding "^3.5.1" libnpm "^2.0.1" "@lerna/run-parallel-batches@^3.0.0": @@ -1103,14 +1141,14 @@ p-map "^1.2.0" p-map-series "^1.0.0" -"@lerna/run@^3.6.0": - version "3.6.0" - resolved "https://registry.yarnpkg.com/@lerna/run/-/run-3.6.0.tgz#f545fcde889d7a1433b3f2cc444eeec39713ea62" - integrity sha512-OYa5pQTOiES/h9rg8vwnt0nYU/wLKUQmFYhMUxdX3lXYpoIcQ28PR7qPG1CVhex4KAU2OW42a7vnm5MAOoScDg== +"@lerna/run@^3.8.5": + version "3.8.5" + resolved "https://registry.yarnpkg.com/@lerna/run/-/run-3.8.5.tgz#5c22b4d15a29a3f98f5bd367fed754e2cf495e89" + integrity sha512-EthL+RhaS2RSXH+l1xtlekx/ZAo2ci/oK9hEESP6YS/VON4wqbMDzPlU6nBcYz/omqO2fFKfDW3pSdzDLMMUgA== dependencies: "@lerna/batch-packages" "^3.6.0" - "@lerna/command" "^3.6.0" - "@lerna/filter-options" "^3.6.0" + "@lerna/command" "^3.8.5" + "@lerna/filter-options" "^3.8.1" "@lerna/npm-run-script" "^3.6.0" "@lerna/output" "^3.6.0" "@lerna/run-parallel-batches" "^3.0.0" @@ -1118,25 +1156,24 @@ "@lerna/validation-error" "^3.6.0" p-map "^1.2.0" -"@lerna/symlink-binary@^3.6.0": - version "3.6.0" - resolved "https://registry.yarnpkg.com/@lerna/symlink-binary/-/symlink-binary-3.6.0.tgz#935a5b98908578da7f9eed20818899f728b9f3d9" - integrity sha512-h69AQBBWgZOEzQ1RJEYQ7Ou6llrJNhNNkpqT6k8qSWZ93iXyFmLE4hWoxMXXHFmxmQ0CqjEYKmeLV1Dr5DKT4g== +"@lerna/symlink-binary@^3.7.2": + version "3.7.2" + resolved "https://registry.yarnpkg.com/@lerna/symlink-binary/-/symlink-binary-3.7.2.tgz#fedce89711ecfeb3d85fd7035199fab0436a793a" + integrity sha512-xS7DdBXNQgfgrhBe2Jz27+S65yxBfnl+Xi+grvlqoEGVk7b8kt2VcBtui/XgL6AAaTg6f9szj4LUnwC/oX6S1Q== dependencies: "@lerna/create-symlink" "^3.6.0" - "@lerna/package" "^3.6.0" + "@lerna/package" "^3.7.2" fs-extra "^7.0.0" p-map "^1.2.0" - read-pkg "^3.0.0" -"@lerna/symlink-dependencies@^3.6.0": - version "3.6.0" - resolved "https://registry.yarnpkg.com/@lerna/symlink-dependencies/-/symlink-dependencies-3.6.0.tgz#76e9d54f6fd3af3e24221cce3ee546e5657ea2d8" - integrity sha512-mLpbWLidAU5Xi7bc9Fj8Yt/9XvDczzWocnS/yEe0E6RqWXh2KK+4VR9H24rLywBAWTv2s4GEXrb/ofbPb8gwBQ== +"@lerna/symlink-dependencies@^3.8.1": + version "3.8.1" + resolved "https://registry.yarnpkg.com/@lerna/symlink-dependencies/-/symlink-dependencies-3.8.1.tgz#890979f232beb9c4618a3b49d4ad11f567617642" + integrity sha512-MlXRTpB3Go/ubexxySngzg8PnItpPIxa0ydHMxvvw7s06g7ZsOOMOAx+F7AUPPr7bssdZ+gg5bfSq+J1HoINrg== dependencies: "@lerna/create-symlink" "^3.6.0" "@lerna/resolve-symlink" "^3.6.0" - "@lerna/symlink-binary" "^3.6.0" + "@lerna/symlink-binary" "^3.7.2" fs-extra "^7.0.0" p-finally "^1.0.0" p-map "^1.2.0" @@ -1154,20 +1191,20 @@ dependencies: libnpm "^2.0.1" -"@lerna/version@^3.6.0": - version "3.6.0" - resolved "https://registry.yarnpkg.com/@lerna/version/-/version-3.6.0.tgz#7360d8a93b1cc5fe6a7588d7266812b916a281f7" - integrity sha512-V1f3fNM5ELGHmF824Wc8ah505SMpfiBqOHAIiW+u9soH/3W/t256c1P9UeaDh5blWAk3HeZMzbpRZ9Nlpf6aQA== +"@lerna/version@^3.8.5": + version "3.8.5" + resolved "https://registry.yarnpkg.com/@lerna/version/-/version-3.8.5.tgz#dd4b95d1ed40211063bb546bba1581db4bab9b1a" + integrity sha512-CfWoef3M2CCA3dMqPYJCrshuSAs+xCAEfVpLmaHQyutKXXGG1LZD38iq2Xs3dxNF07Md5H9+Mt6pfEwsXqjhJA== dependencies: "@lerna/batch-packages" "^3.6.0" - "@lerna/check-working-tree" "^3.6.0" + "@lerna/check-working-tree" "^3.8.1" "@lerna/child-process" "^3.3.0" - "@lerna/collect-updates" "^3.6.0" - "@lerna/command" "^3.6.0" + "@lerna/collect-updates" "^3.8.1" + "@lerna/command" "^3.8.5" "@lerna/conventional-commits" "^3.6.0" "@lerna/output" "^3.6.0" "@lerna/prompt" "^3.6.0" - "@lerna/run-lifecycle" "^3.6.0" + "@lerna/run-lifecycle" "^3.8.2" "@lerna/validation-error" "^3.6.0" chalk "^2.3.1" dedent "^0.7.0" @@ -1197,10 +1234,56 @@ call-me-maybe "^1.0.1" glob-to-regexp "^0.3.0" -"@nodelib/fs.stat@^1.0.1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.2.tgz#54c5a964462be3d4d78af631363c18d6fa91ac26" - integrity sha512-yprFYuno9FtNsSHVlSWd+nRlmGoAbqbeCwOryP6sC/zoCjhpArcRMYp19EvpSUSizJAlsXEwJv+wcWS9XaXdMw== +"@nodelib/fs.stat@^1.1.2": + version "1.1.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b" + integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw== + +"@parcel/fs@^1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@parcel/fs/-/fs-1.11.0.tgz#fb8a2be038c454ad46a50dc0554c1805f13535cd" + integrity sha512-86RyEqULbbVoeo8OLcv+LQ1Vq2PKBAvWTU9fCgALxuCTbbs5Ppcvll4Vr+Ko1AnmMzja/k++SzNAwJfeQXVlpA== + dependencies: + "@parcel/utils" "^1.11.0" + mkdirp "^0.5.1" + rimraf "^2.6.2" + +"@parcel/logger@^1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@parcel/logger/-/logger-1.11.0.tgz#91f39da14ba08dd85db247145698c62102960abb" + integrity sha512-lIRfDg+junbFUUeU0QtHX00gKCgEsYHZydFKwrJ8dc0D+WE2SYT1FcVCgpPAfKYgtg0QQMns8E9vzT9UjH92PQ== + dependencies: + "@parcel/workers" "^1.11.0" + chalk "^2.1.0" + grapheme-breaker "^0.3.2" + ora "^2.1.0" + strip-ansi "^4.0.0" + +"@parcel/utils@^1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@parcel/utils/-/utils-1.11.0.tgz#539e08fff8af3b26eca11302be80b522674b51ea" + integrity sha512-cA3p4jTlaMeOtAKR/6AadanOPvKeg8VwgnHhOyfi0yClD0TZS/hi9xu12w4EzA/8NtHu0g6o4RDfcNjqN8l1AQ== + +"@parcel/watcher@^1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher/-/watcher-1.11.0.tgz#a05ee752d47bf3627b77a64a6089404683edc255" + integrity sha512-1ySF0sH06jyhpaErW1UWC7BNgkAl6PJyBjuu2cLTW1o71J2iQqgGt95cbuqmfmjI3l0xYN+nauDFqHERaj7Z8A== + dependencies: + "@parcel/utils" "^1.11.0" + chokidar "^2.0.3" + +"@parcel/workers@^1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@parcel/workers/-/workers-1.11.0.tgz#7b8dcf992806f4ad2b6cecf629839c41c2336c59" + integrity sha512-USSjRAAQYsZFlv43FUPdD+jEGML5/8oLF0rUzPQTtK4q9kvaXr49F5ZplyLz5lox78cLZ0TxN2bIDQ1xhOkulQ== + dependencies: + "@parcel/utils" "^1.11.0" + physical-cpu-count "^2.0.0" + +"@types/estree@0.0.39": + version "0.0.39" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" + integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== "@types/events@*": version "1.2.0" @@ -1224,9 +1307,9 @@ "@types/node" "*" "@types/handlebars@^4.0.38": - version "4.0.39" - resolved "https://registry.yarnpkg.com/@types/handlebars/-/handlebars-4.0.39.tgz#961fb54db68030890942e6aeffe9f93a957807bd" - integrity sha512-vjaS7Q0dVqFp85QhyPSZqDKnTTCemcSHNHFvDdalO1s0Ifz5KuE64jQD5xoUkfdWwF4WpqdJEl7LsWH8rzhKJA== + version "4.0.40" + resolved "https://registry.yarnpkg.com/@types/handlebars/-/handlebars-4.0.40.tgz#b714e13d296a75bff3f199316d1311933ca79ffd" + integrity sha512-sGWNtsjNrLOdKha2RV1UeF8+UbQnPSG7qbe5wwbni0mw4h2gHXyPFUMOC+xwGirIiiydM/HSqjDO4rk6NFB18w== "@types/highlight.js@^9.12.3": version "9.12.3" @@ -1234,9 +1317,9 @@ integrity sha512-pGF/zvYOACZ/gLGWdQH8zSwteQS1epp68yRcVLJMgUck/MjEn/FBYmPub9pXT8C1e4a8YZfHo1CKyV8q1vKUnQ== "@types/lodash@^4.14.110": - version "4.14.117" - resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.117.tgz#695a7f514182771a1e0f4345d189052ee33c8778" - integrity sha512-xyf2m6tRbz8qQKcxYZa7PA4SllYcay+eh25DN3jmNYY6gSTL7Htc/bttVdkqj2wfJGbeWlQiX8pIyJpKU+tubw== + version "4.14.119" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.119.tgz#be847e5f4bc3e35e46d041c394ead8b603ad8b39" + integrity sha512-Z3TNyBL8Vd/M9D9Ms2S3LmFq2sSMzahodD6rCS9V2N44HUMINb75jNkSuwAx7eo2ufqTdfOdtGQpNbieUjPQmw== "@types/marked@^0.4.0": version "0.4.2" @@ -1253,15 +1336,15 @@ resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-5.2.5.tgz#8a4accfc403c124a0bafe8a9fc61a05ec1032073" integrity sha512-lAVp+Kj54ui/vLUFxsJTMtWvZraZxum3w3Nwkble2dNuV5VnPA+Mi2oGX9XYJAaIvZi3tn3cbjS/qcJXRb6Bww== -"@types/node@*", "@types/node@^10.11.7": - version "10.12.0" - resolved "https://registry.yarnpkg.com/@types/node/-/node-10.12.0.tgz#ea6dcbddbc5b584c83f06c60e82736d8fbb0c235" - integrity sha512-3TUHC3jsBAB7qVRGxT6lWyYo2v96BMmD2PTcl47H25Lu7UXtFH/2qqmKiVrnel6Ne//0TFYf6uvNX+HW2FRkLQ== +"@types/node@*", "@types/node@^10.11.7", "@types/node@^10.12.15": + 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@^10.12.15": - version "10.12.15" - resolved "https://registry.yarnpkg.com/@types/node/-/node-10.12.15.tgz#20e85651b62fd86656e57c9c9bc771ab1570bc59" - integrity sha512-9kROxduaN98QghwwHmxXO2Xz3MaWf+I1sLVAA6KJDF5xix+IyXVhds0MAfdNwtcpSrzhaTsNB0/jnL86fgUhqA== +"@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" @@ -1269,9 +1352,9 @@ integrity sha512-41qEJgBH/TWgo5NFSvBCJ1qkoi3Q6ONSF2avrHq1LVEZfYpdHmj0y9SuTK+u9ZhG1sYQKBL1AWXKyLWP4RaUoQ== "@types/shelljs@^0.8.0": - version "0.8.0" - resolved "https://registry.yarnpkg.com/@types/shelljs/-/shelljs-0.8.0.tgz#0caa56b68baae4f68f44e0dd666ab30b098e3632" - integrity sha512-vs1hCC8RxLHRu2bwumNyYRNrU3o8BtZhLysH5A4I98iYmA2APl6R3uNQb5ihl+WiwH0xdC9LLO+vRrXLs/Kyxg== + version "0.8.1" + resolved "https://registry.yarnpkg.com/@types/shelljs/-/shelljs-0.8.1.tgz#133e874b5fb816a2e1c8647839c82d76760b1191" + integrity sha512-1lQw+48BuVgp6c1+z8EMipp18IdnV2dLh6KQGwOm+kJy9nPjEkaqRKmwbDNEYf//EKBvKcwOC6V2cDrNxVoQeQ== dependencies: "@types/glob" "*" "@types/node" "*" @@ -1281,6 +1364,159 @@ resolved "https://registry.yarnpkg.com/@types/webgl2/-/webgl2-0.0.4.tgz#c3b0f9d6b465c66138e84e64cb3bdf8373c2c279" integrity sha512-PACt1xdErJbMUOUweSrbVM7gSIYm1vTncW2hF6Os/EeWi6TXYAYMPp+8v6rzHmypE5gHrxaxZNXgMkJVIdZpHw== +"@webassemblyjs/ast@1.7.11": + version "1.7.11" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.7.11.tgz#b988582cafbb2b095e8b556526f30c90d057cace" + integrity sha512-ZEzy4vjvTzScC+SH8RBssQUawpaInUdMTYwYYLh54/s8TuT0gBLuyUnppKsVyZEi876VmmStKsUs28UxPgdvrA== + dependencies: + "@webassemblyjs/helper-module-context" "1.7.11" + "@webassemblyjs/helper-wasm-bytecode" "1.7.11" + "@webassemblyjs/wast-parser" "1.7.11" + +"@webassemblyjs/floating-point-hex-parser@1.7.11": + version "1.7.11" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.7.11.tgz#a69f0af6502eb9a3c045555b1a6129d3d3f2e313" + integrity sha512-zY8dSNyYcgzNRNT666/zOoAyImshm3ycKdoLsyDw/Bwo6+/uktb7p4xyApuef1dwEBo/U/SYQzbGBvV+nru2Xg== + +"@webassemblyjs/helper-api-error@1.7.11": + version "1.7.11" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.7.11.tgz#c7b6bb8105f84039511a2b39ce494f193818a32a" + integrity sha512-7r1qXLmiglC+wPNkGuXCvkmalyEstKVwcueZRP2GNC2PAvxbLYwLLPr14rcdJaE4UtHxQKfFkuDFuv91ipqvXg== + +"@webassemblyjs/helper-buffer@1.7.11": + version "1.7.11" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.7.11.tgz#3122d48dcc6c9456ed982debe16c8f37101df39b" + integrity sha512-MynuervdylPPh3ix+mKZloTcL06P8tenNH3sx6s0qE8SLR6DdwnfgA7Hc9NSYeob2jrW5Vql6GVlsQzKQCa13w== + +"@webassemblyjs/helper-code-frame@1.7.11": + version "1.7.11" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.7.11.tgz#cf8f106e746662a0da29bdef635fcd3d1248364b" + integrity sha512-T8ESC9KMXFTXA5urJcyor5cn6qWeZ4/zLPyWeEXZ03hj/x9weSokGNkVCdnhSabKGYWxElSdgJ+sFa9G/RdHNw== + dependencies: + "@webassemblyjs/wast-printer" "1.7.11" + +"@webassemblyjs/helper-fsm@1.7.11": + version "1.7.11" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-fsm/-/helper-fsm-1.7.11.tgz#df38882a624080d03f7503f93e3f17ac5ac01181" + integrity sha512-nsAQWNP1+8Z6tkzdYlXT0kxfa2Z1tRTARd8wYnc/e3Zv3VydVVnaeePgqUzFrpkGUyhUUxOl5ML7f1NuT+gC0A== + +"@webassemblyjs/helper-module-context@1.7.11": + version "1.7.11" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-module-context/-/helper-module-context-1.7.11.tgz#d874d722e51e62ac202476935d649c802fa0e209" + integrity sha512-JxfD5DX8Ygq4PvXDucq0M+sbUFA7BJAv/GGl9ITovqE+idGX+J3QSzJYz+LwQmL7fC3Rs+utvWoJxDb6pmC0qg== + +"@webassemblyjs/helper-wasm-bytecode@1.7.11": + version "1.7.11" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.7.11.tgz#dd9a1e817f1c2eb105b4cf1013093cb9f3c9cb06" + integrity sha512-cMXeVS9rhoXsI9LLL4tJxBgVD/KMOKXuFqYb5oCJ/opScWpkCMEz9EJtkonaNcnLv2R3K5jIeS4TRj/drde1JQ== + +"@webassemblyjs/helper-wasm-section@1.7.11": + version "1.7.11" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.7.11.tgz#9c9ac41ecf9fbcfffc96f6d2675e2de33811e68a" + integrity sha512-8ZRY5iZbZdtNFE5UFunB8mmBEAbSI3guwbrsCl4fWdfRiAcvqQpeqd5KHhSWLL5wuxo53zcaGZDBU64qgn4I4Q== + dependencies: + "@webassemblyjs/ast" "1.7.11" + "@webassemblyjs/helper-buffer" "1.7.11" + "@webassemblyjs/helper-wasm-bytecode" "1.7.11" + "@webassemblyjs/wasm-gen" "1.7.11" + +"@webassemblyjs/ieee754@1.7.11": + version "1.7.11" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.7.11.tgz#c95839eb63757a31880aaec7b6512d4191ac640b" + integrity sha512-Mmqx/cS68K1tSrvRLtaV/Lp3NZWzXtOHUW2IvDvl2sihAwJh4ACE0eL6A8FvMyDG9abes3saB6dMimLOs+HMoQ== + dependencies: + "@xtuc/ieee754" "^1.2.0" + +"@webassemblyjs/leb128@1.7.11": + version "1.7.11" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.7.11.tgz#d7267a1ee9c4594fd3f7e37298818ec65687db63" + integrity sha512-vuGmgZjjp3zjcerQg+JA+tGOncOnJLWVkt8Aze5eWQLwTQGNgVLcyOTqgSCxWTR4J42ijHbBxnuRaL1Rv7XMdw== + dependencies: + "@xtuc/long" "4.2.1" + +"@webassemblyjs/utf8@1.7.11": + version "1.7.11" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.7.11.tgz#06d7218ea9fdc94a6793aa92208160db3d26ee82" + integrity sha512-C6GFkc7aErQIAH+BMrIdVSmW+6HSe20wg57HEC1uqJP8E/xpMjXqQUxkQw07MhNDSDcGpxI9G5JSNOQCqJk4sA== + +"@webassemblyjs/wasm-edit@1.7.11": + version "1.7.11" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.7.11.tgz#8c74ca474d4f951d01dbae9bd70814ee22a82005" + integrity sha512-FUd97guNGsCZQgeTPKdgxJhBXkUbMTY6hFPf2Y4OedXd48H97J+sOY2Ltaq6WGVpIH8o/TGOVNiVz/SbpEMJGg== + dependencies: + "@webassemblyjs/ast" "1.7.11" + "@webassemblyjs/helper-buffer" "1.7.11" + "@webassemblyjs/helper-wasm-bytecode" "1.7.11" + "@webassemblyjs/helper-wasm-section" "1.7.11" + "@webassemblyjs/wasm-gen" "1.7.11" + "@webassemblyjs/wasm-opt" "1.7.11" + "@webassemblyjs/wasm-parser" "1.7.11" + "@webassemblyjs/wast-printer" "1.7.11" + +"@webassemblyjs/wasm-gen@1.7.11": + version "1.7.11" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.7.11.tgz#9bbba942f22375686a6fb759afcd7ac9c45da1a8" + integrity sha512-U/KDYp7fgAZX5KPfq4NOupK/BmhDc5Kjy2GIqstMhvvdJRcER/kUsMThpWeRP8BMn4LXaKhSTggIJPOeYHwISA== + dependencies: + "@webassemblyjs/ast" "1.7.11" + "@webassemblyjs/helper-wasm-bytecode" "1.7.11" + "@webassemblyjs/ieee754" "1.7.11" + "@webassemblyjs/leb128" "1.7.11" + "@webassemblyjs/utf8" "1.7.11" + +"@webassemblyjs/wasm-opt@1.7.11": + version "1.7.11" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.7.11.tgz#b331e8e7cef8f8e2f007d42c3a36a0580a7d6ca7" + integrity sha512-XynkOwQyiRidh0GLua7SkeHvAPXQV/RxsUeERILmAInZegApOUAIJfRuPYe2F7RcjOC9tW3Cb9juPvAC/sCqvg== + dependencies: + "@webassemblyjs/ast" "1.7.11" + "@webassemblyjs/helper-buffer" "1.7.11" + "@webassemblyjs/wasm-gen" "1.7.11" + "@webassemblyjs/wasm-parser" "1.7.11" + +"@webassemblyjs/wasm-parser@1.7.11": + version "1.7.11" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.7.11.tgz#6e3d20fa6a3519f6b084ef9391ad58211efb0a1a" + integrity sha512-6lmXRTrrZjYD8Ng8xRyvyXQJYUQKYSXhJqXOBLw24rdiXsHAOlvw5PhesjdcaMadU/pyPQOJ5dHreMjBxwnQKg== + dependencies: + "@webassemblyjs/ast" "1.7.11" + "@webassemblyjs/helper-api-error" "1.7.11" + "@webassemblyjs/helper-wasm-bytecode" "1.7.11" + "@webassemblyjs/ieee754" "1.7.11" + "@webassemblyjs/leb128" "1.7.11" + "@webassemblyjs/utf8" "1.7.11" + +"@webassemblyjs/wast-parser@1.7.11": + version "1.7.11" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-parser/-/wast-parser-1.7.11.tgz#25bd117562ca8c002720ff8116ef9072d9ca869c" + integrity sha512-lEyVCg2np15tS+dm7+JJTNhNWq9yTZvi3qEhAIIOaofcYlUp0UR5/tVqOwa/gXYr3gjwSZqw+/lS9dscyLelbQ== + dependencies: + "@webassemblyjs/ast" "1.7.11" + "@webassemblyjs/floating-point-hex-parser" "1.7.11" + "@webassemblyjs/helper-api-error" "1.7.11" + "@webassemblyjs/helper-code-frame" "1.7.11" + "@webassemblyjs/helper-fsm" "1.7.11" + "@xtuc/long" "4.2.1" + +"@webassemblyjs/wast-printer@1.7.11": + version "1.7.11" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.7.11.tgz#c4245b6de242cb50a2cc950174fdbf65c78d7813" + integrity sha512-m5vkAsuJ32QpkdkDOUPGSltrg8Cuk3KBx4YrmAGQwCZPRdUHXxG4phIOuuycLemHFr74sWL9Wthqss4fzdzSwg== + dependencies: + "@webassemblyjs/ast" "1.7.11" + "@webassemblyjs/wast-parser" "1.7.11" + "@xtuc/long" "4.2.1" + +"@xtuc/ieee754@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" + integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== + +"@xtuc/long@4.2.1": + version "4.2.1" + resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.1.tgz#5c85d662f76fa1d34575766c5dcd6615abcd30d8" + integrity sha512-FZdkNBDqBRHKQ2MEbSC17xnPFOhZxeJ2YGSfr2BKf3sujG49Qe3bB+rGCwQfIaA7WHnGeGkSijX4FuBCdrzW/g== + JSONStream@^1.0.4, JSONStream@^1.3.4: version "1.3.5" resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0" @@ -1294,11 +1530,23 @@ abbrev@1: resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== -acorn@^5.0.0: +acorn-dynamic-import@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-3.0.0.tgz#901ceee4c7faaef7e07ad2a47e890675da50a278" + integrity sha512-zVWV8Z8lislJoOKKqdNMOB+s6+XV5WERty8MnKBeFgwA+19XJjJHs2RP5dzM57FftIs+jQnRToLiWazKr6sSWg== + dependencies: + acorn "^5.0.0" + +acorn@^5.0.0, acorn@^5.6.2: version "5.7.3" resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279" integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw== +acorn@^6.0.5: + version "6.0.5" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.0.5.tgz#81730c0815f3f3b34d8efa95cb7430965f4d887a" + integrity sha512-i33Zgp3XWtmZBMNvCr4azvOFeWVw1Rk6p3hfi3LUDvIFraOMywb1kAtrbi+med14m4Xfpqm3zRZMT+c0FNE7kg== + agent-base@4, agent-base@^4.1.0, agent-base@~4.2.0: version "4.2.1" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.1.tgz#d89e5999f797875674c07d87f260fc41e83e8ca9" @@ -1307,21 +1555,31 @@ agent-base@4, agent-base@^4.1.0, agent-base@~4.2.0: es6-promisify "^5.0.0" agentkeepalive@^3.4.1: - version "3.5.1" - resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-3.5.1.tgz#4eba75cf2ad258fc09efd506cdb8d8c2971d35a4" - integrity sha512-Cte/sTY9/XcygXjJ0q58v//SnEQ7ViWExKyJpLJlLqomDbQyMLh6Is4KuWJ/wmxzhiwkGRple7Gqv1zf6Syz5w== + version "3.5.2" + resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-3.5.2.tgz#a113924dd3fa24a0bc3b78108c450c2abee00f67" + integrity sha512-e0L/HNe6qkQ7H19kTlRRqUibEAwDK5AFk6y3PtMsuut2VAH6+Q4xZml1tNDJD7kSAyqmbG/K08K5WEJYtUrSlQ== dependencies: humanize-ms "^1.2.1" -ajv@^5.3.0: - version "5.5.2" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" - integrity sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU= +ajv-errors@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d" + 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= + +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== dependencies: - co "^4.6.0" - fast-deep-equal "^1.0.0" + fast-deep-equal "^2.0.1" fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.3.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" alphanum-sort@^1.0.0, alphanum-sort@^1.0.1, alphanum-sort@^1.0.2: version "1.0.2" @@ -1343,6 +1601,11 @@ 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-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" @@ -1356,9 +1619,9 @@ ansi-styles@^3.2.1: color-convert "^1.9.0" ansi-to-html@^0.6.4: - version "0.6.6" - resolved "https://registry.yarnpkg.com/ansi-to-html/-/ansi-to-html-0.6.6.tgz#58a8d04b87ec9a85e3ad273c12a5fbc7147b9c42" - integrity sha512-90M/2sZna3OsoOEbSyXK46poFnlClBC53Rx6etNKQK7iShsX5fI5E/M9Ld6FurtLaxAWLuAPi0Jp8p3y5oAkxg== + 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== dependencies: entities "^1.1.1" @@ -1407,12 +1670,19 @@ argparse@^1.0.7: dependencies: sprintf-js "~1.0.2" +arr-diff@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" + integrity sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8= + dependencies: + arr-flatten "^1.0.1" + arr-diff@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= -arr-flatten@^1.1.0: +arr-flatten@^1.0.1, arr-flatten@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== @@ -1449,6 +1719,11 @@ array-uniq@^1.0.1: resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY= +array-unique@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" + integrity sha1-odl8yvy8JiXMcPrc6zalDFiwGlM= + array-unique@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" @@ -1625,6 +1900,11 @@ benchmark@^2.1.4: lodash "^4.17.4" platform "^1.3.3" +big.js@^5.2.2: + version "5.2.2" + resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" + integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== + bin-links@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/bin-links/-/bin-links-1.1.2.tgz#fb74bd54bae6b7befc6c6221f25322ac830d9757" @@ -1653,16 +1933,11 @@ block-stream@*: dependencies: inherits "~2.0.0" -bluebird@^3.5.0, bluebird@^3.5.2, bluebird@^3.5.3: +bluebird@^3.5.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== -bluebird@^3.5.1: - version "3.5.2" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.2.tgz#1be0908e054a751754549c270489c1505d4ab15a" - integrity sha512-dhHTWMI7kMx5whMQntl7Vr9C6BvV10lFXDAasnqnrMYhXVCzzk6IO9Fo2L75jXHT07WrOngL1WDXOp+yYS91Yg== - bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0: version "4.11.8" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" @@ -1681,6 +1956,15 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" +braces@^1.8.2: + version "1.8.5" + resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" + integrity sha1-uneWLhLf+WnWt2cR6RS3N4V79qc= + dependencies: + expand-range "^1.8.1" + preserve "^0.2.0" + repeat-element "^1.1.2" + braces@^2.3.0, braces@^2.3.1: version "2.3.2" resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" @@ -1784,14 +2068,14 @@ browserslist@^1.3.6, browserslist@^1.5.2, browserslist@^1.7.6: caniuse-db "^1.0.30000639" electron-to-chromium "^1.2.7" -browserslist@^4.0.0, browserslist@^4.1.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.2.1.tgz#257a24c879d1cd4016348eee5c25de683260b21d" - integrity sha512-1oO0c7Zhejwd+LXihS89WqtKionSbz298rJZKJgfrHIZhrV8AC15gw553VcB0lcEugja7IhWD7iAlrsamfYVPA== +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== dependencies: - caniuse-lite "^1.0.30000890" - electron-to-chromium "^1.3.79" - node-releases "^1.0.0-alpha.14" + caniuse-lite "^1.0.30000925" + electron-to-chromium "^1.3.96" + node-releases "^1.1.3" buffer-equal@0.0.1: version "0.0.1" @@ -1838,48 +2122,28 @@ byline@^5.0.0: integrity sha1-dBxSFkaOrcRXsDQQEYrXfejB3bE= byte-size@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/byte-size/-/byte-size-4.0.3.tgz#b7c095efc68eadf82985fccd9a2df43a74fa2ccd" - integrity sha512-JGC3EV2bCzJH/ENSh3afyJrH4vwxbHTuO5ljLoI5+2iJOcEpMgP8T782jH9b5qGxf2mSUIp1lfGnfKNrRHpvVg== - -cacache@^11.0.1: - version "11.2.0" - resolved "https://registry.yarnpkg.com/cacache/-/cacache-11.2.0.tgz#617bdc0b02844af56310e411c0878941d5739965" - integrity sha512-IFWl6lfK6wSeYCHUXh+N1lY72UDrpyrYQJNIVQf48paDuWbv5RbAtJYf/4gUQFObTCHZwdZ5sI8Iw7nqwP6nlQ== - dependencies: - bluebird "^3.5.1" - chownr "^1.0.1" - figgy-pudding "^3.1.0" - glob "^7.1.2" - graceful-fs "^4.1.11" - lru-cache "^4.1.3" - mississippi "^3.0.0" - mkdirp "^0.5.1" - move-concurrently "^1.0.1" - promise-inflight "^1.0.1" - rimraf "^2.6.2" - ssri "^6.0.0" - unique-filename "^1.1.0" - y18n "^4.0.0" + version "4.0.4" + resolved "https://registry.yarnpkg.com/byte-size/-/byte-size-4.0.4.tgz#29d381709f41aae0d89c631f1c81aec88cd40b23" + integrity sha512-82RPeneC6nqCdSwCX2hZUz3JPOvN5at/nTEw/CMf05Smu3Hrpo9Psb7LjN+k+XndNArG1EY8L4+BM3aTM4BCvw== -cacache@^11.2.0: - version "11.3.1" - resolved "https://registry.yarnpkg.com/cacache/-/cacache-11.3.1.tgz#d09d25f6c4aca7a6d305d141ae332613aa1d515f" - integrity sha512-2PEw4cRRDu+iQvBTTuttQifacYjLPhET+SYO/gEFMy8uhi+jlJREDAjSF5FWSdV/Aw5h18caHA7vMTw2c+wDzA== +cacache@^11.0.1, cacache@^11.0.2, 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== dependencies: - bluebird "^3.5.1" - chownr "^1.0.1" - figgy-pudding "^3.1.0" - glob "^7.1.2" - graceful-fs "^4.1.11" - lru-cache "^4.1.3" + bluebird "^3.5.3" + chownr "^1.1.1" + figgy-pudding "^3.5.1" + glob "^7.1.3" + graceful-fs "^4.1.15" + lru-cache "^5.1.1" mississippi "^3.0.0" mkdirp "^0.5.1" move-concurrently "^1.0.1" promise-inflight "^1.0.1" rimraf "^2.6.2" - ssri "^6.0.0" - unique-filename "^1.1.0" + ssri "^6.0.1" + unique-filename "^1.1.1" y18n "^4.0.0" cache-base@^1.0.1: @@ -1912,6 +2176,25 @@ call-me-maybe@^1.0.1: resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b" integrity sha1-JtII6onje1y95gJQoV8DHBak1ms= +caller-callsite@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" + integrity sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ= + dependencies: + callsites "^2.0.0" + +caller-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4" + integrity sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ= + dependencies: + caller-callsite "^2.0.0" + +callsites@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" + integrity sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA= + camelcase-keys@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7" @@ -1939,6 +2222,11 @@ camelcase@^4.1.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" 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== + caniuse-api@^1.5.2: version "1.6.1" resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-1.6.1.tgz#b534e7c734c4f81ec5fbe8aca2ad24354b962c6c" @@ -1960,14 +2248,14 @@ caniuse-api@^3.0.0: lodash.uniq "^4.5.0" caniuse-db@^1.0.30000529, caniuse-db@^1.0.30000634, caniuse-db@^1.0.30000639: - version "1.0.30000892" - resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000892.tgz#3a03ecec4283caa5dac49facf024d13113c4499f" - integrity sha512-as/DXjiFJg051+GSJLmkY0hckkVsmTB4nuDUPLwK1sMHk94XsYuocNJuU0wdOpobwI/3sqNeW5ETebvdPGvwBQ== + version "1.0.30000927" + resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000927.tgz#9906eecf59ae7ee5d1bb2c16cf06fc31b642bfda" + integrity sha512-CX/QvLA8oh7kQ9cHCCzFm0UZW4KwSyQSRJ5A1XtH42HaMJQ0yh+9fEVWagMqv9I1vSCtaqA5Mb8k0uKfv7jhDw== -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000890: - version "1.0.30000892" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000892.tgz#344d2b51ee3ff5977537da4aa449c90eec40b759" - integrity sha512-X9rxMaWZNbJB5qjkDqPtNv/yfViTeUL6ILk0QJNxLV3OhKC5Acn5vxsuUvllR6B48mog8lmS+whwHq/QIYSL9w== +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== caseless@~0.12.0: version "0.12.0" @@ -1986,9 +2274,9 @@ chalk@^1.1.3: supports-color "^2.0.0" chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3.1, chalk@^2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" - integrity sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ== + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== dependencies: ansi-styles "^3.2.1" escape-string-regexp "^1.0.5" @@ -1999,7 +2287,7 @@ chardet@^0.7.0: resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== -chokidar@^2.0.3: +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== @@ -2019,11 +2307,18 @@ chokidar@^2.0.3: optionalDependencies: fsevents "^1.2.2" -chownr@^1.0.1, chownr@^1.1.1: +chownr@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.1.tgz#54726b8b8fff4df053c42187e801fb4412df1494" 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== + dependencies: + tslib "^1.9.0" + ci-info@^1.5.0: version "1.6.0" resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.6.0.tgz#2ca20dbb9ceb32d4524a683303313f0304b1e497" @@ -2090,10 +2385,10 @@ clone@^2.1.1: resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18= -clones@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/clones/-/clones-1.1.0.tgz#87e904132d6140c5c0b72006c08c0d05bd7b63b3" - integrity sha1-h+kEEy1hQMXAtyAGwIwNBb17Y7M= +clones@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/clones/-/clones-1.2.0.tgz#b34c872045446a9f264ccceb7731bca05c529b71" + integrity sha512-FXDYw4TjR8wgPZYui2LeTqWh1BLpfQ8lB6upMtlpDF6WlOOxghmTTxWyngdKTgozqBgKnHbTVwTE+hOHqAykuQ== cmd-shim@^2.0.2: version "2.0.2" @@ -2103,11 +2398,6 @@ cmd-shim@^2.0.2: graceful-fs "^4.1.2" mkdirp "~0.5.0" -co@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" - integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= - coa@~1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/coa/-/coa-1.0.4.tgz#a9ef153660d6a86a8bdec0289a5c684d217432fd" @@ -2116,10 +2406,12 @@ coa@~1.0.1: q "^1.1.2" coa@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/coa/-/coa-2.0.1.tgz#f3f8b0b15073e35d70263fb1042cb2c023db38af" - integrity sha512-5wfTTO8E2/ja4jFSxePXlG5nRu5bBtL/r1HCIpJW/lzT6yDtKl0u0Z4o/Vpz32IpKmBn7HerheEZQgA9N2DarQ== + version "2.0.2" + resolved "https://registry.yarnpkg.com/coa/-/coa-2.0.2.tgz#43f6c21151b4ef2bf57187db0d73de229e3e7ec3" + integrity sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA== dependencies: + "@types/q" "^1.5.1" + chalk "^2.4.1" q "^1.1.2" code-point-at@^1.0.0: @@ -2266,7 +2558,7 @@ concat-stream@^1.5.0, concat-stream@^1.6.0, concat-stream@~1.6.0: readable-stream "^2.2.2" typedarray "^0.0.6" -config-chain@^1.1.11, config-chain@~1.1.5: +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" integrity sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA== @@ -2399,9 +2691,9 @@ copy-descriptor@^0.1.0: integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= core-js@^2.4.0: - version "2.5.7" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.7.tgz#f972608ff0cead68b841a16a932d0b183791814e" - integrity sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw== + version "2.6.1" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.1.tgz#87416ae817de957a3f249b3b5ca475d4aaed6042" + integrity sha512-L72mmmEayPJBejKIWe2pYtGis5r0tQ5NaJekdhyXgeMQTpJoBsH0NL4ElY2LfSoV15xeQWKQ+XTTOZdyero5Xg== core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" @@ -2409,10 +2701,11 @@ core-util-is@1.0.2, core-util-is@~1.0.0: integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= cosmiconfig@^5.0.0, cosmiconfig@^5.0.2: - version "5.0.6" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.0.6.tgz#dca6cf680a0bd03589aff684700858c81abeeb39" - integrity sha512-6DWfizHriCrFWURP1/qyhsiFvYdlJzbCzmtFWh744+KyWsJo5+kPzUZZaMRSSItoYc0pxFX7gEO7ZC1/gN/7AQ== + 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" @@ -2465,7 +2758,7 @@ cross-spawn@^5.0.1: shebang-command "^1.2.0" which "^1.2.9" -cross-spawn@^6.0.0, cross-spawn@^6.0.4: +cross-spawn@^6.0.0, cross-spawn@^6.0.4, cross-spawn@^6.0.5: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== @@ -2507,19 +2800,19 @@ css-declaration-sorter@^4.0.1: timsort "^0.3.0" css-select-base-adapter@~0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/css-select-base-adapter/-/css-select-base-adapter-0.1.0.tgz#0102b3d14630df86c3eb9fa9f5456270106cf990" - integrity sha1-AQKz0UYw34bD65+p9UVicBBs+ZA= + 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== css-select@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/css-select/-/css-select-2.0.0.tgz#7aa2921392114831f68db175c0b6a555df74bbd5" - integrity sha512-MGhoq1S9EyPgZIGnts8Yz5WwUOyHmPMdlqeifsYs/xFX7AAm3hY0RJe1dqVlXtYPI66Nsk39R/sa5/ree6L2qg== + version "2.0.2" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-2.0.2.tgz#ab4386cec9e1f668855564b17c3733b43b2a5ede" + integrity sha512-dSpYaDVoWaELjvZ3mS6IKZM/y2PMPa/XYoEfYNZePL4U/XgyxZNroHEHReDx/d+VgXh9VbCTtFqLkFbmeqeaRQ== dependencies: boolbase "^1.0.0" - css-what "2.1" + css-what "^2.1.2" domutils "^1.7.0" - nth-check "^1.0.1" + nth-check "^1.0.2" css-tree@1.0.0-alpha.28: version "1.0.0-alpha.28" @@ -2547,27 +2840,32 @@ css-url-regex@^1.1.0: resolved "https://registry.yarnpkg.com/css-url-regex/-/css-url-regex-1.1.0.tgz#83834230cc9f74c457de59eebd1543feeb83b7ec" integrity sha1-g4NCMMyfdMRX3lnuvRVD/uuDt+w= -css-what@2.1: - version "2.1.0" - resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.0.tgz#9467d032c38cfaefb9f2d79501253062f87fa1bd" - integrity sha1-lGfQMsOM+u+58teVASUwYvh/ob0= +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== -cssnano-preset-default@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-4.0.2.tgz#1de3f27e73b7f0fbf87c1d7fd7a63ae980ac3774" - integrity sha512-zO9PeP84l1E4kbrdyF7NSLtA/JrJY1paX5FHy5+w/ziIXO2kDqDMfJ/mosXkaHHSa3RPiIY3eB6aEgwx3IiGqA== +cssesc@^2.0.0: + version "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 "^6.0.2" + 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.6" + 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" @@ -2649,12 +2947,12 @@ cssnano@^3.4.0: postcss-zindex "^2.0.1" cssnano@^4.0.0: - version "4.1.4" - resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-4.1.4.tgz#55b71e3d8f5451dd3edc7955673415c98795788f" - integrity sha512-wP0wbOM9oqsek14CiNRYrK9N3w3jgadtGZKHXysgC/OMVpy0KZgWVPdNqODSZbz7txO9Gekr9taOfcCgL0pOOw== + 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.2" + cssnano-preset-default "^4.0.6" is-resolvable "^1.0.0" postcss "^7.0.0" @@ -2709,13 +3007,13 @@ dateformat@^3.0.0: resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q== -deasync@^0.1.13: - version "0.1.13" - resolved "https://registry.yarnpkg.com/deasync/-/deasync-0.1.13.tgz#815c2b69bbd1117cae570152cd895661c09f20ea" - integrity sha512-/6ngYM7AapueqLtvOzjv9+11N2fHDSrkxeMF1YPE20WIfaaawiBg+HZH1E5lHrcJxlKR42t6XPOEmMmqcAsU1g== +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== dependencies: bindings "~1.2.1" - nan "^2.0.7" + node-addon-api "^1.6.0" debug-log@^1.0.1: version "1.0.1" @@ -2743,6 +3041,13 @@ debug@^3.1.0: dependencies: ms "^2.1.1" +debug@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" + integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== + dependencies: + ms "^2.1.1" + debuglog@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492" @@ -2756,18 +3061,11 @@ decamelize-keys@^1.0.0: decamelize "^1.1.0" map-obj "^1.0.0" -decamelize@^1.1.0, decamelize@^1.1.1, decamelize@^1.1.2: +decamelize@^1.1.0, decamelize@^1.1.1, decamelize@^1.1.2, decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= -decamelize@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-2.0.0.tgz#656d7bbc8094c4c788ea53c5840908c9c7d063c7" - integrity sha512-Ikpp5scV3MSYxY39ymh45ZLEecsTdv/Xj2CaQfI8RLMuwi7XvjX9H/fhraiSuU+C5w5NTDu4ZU72xNiZnurBPg== - dependencies: - xregexp "4.0.0" - decode-uri-component@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" @@ -2802,7 +3100,7 @@ defaults@^1.0.3: dependencies: clone "^1.0.2" -define-properties@^1.1.2: +define-properties@^1.1.2, define-properties@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== @@ -2864,6 +3162,11 @@ destroy@~1.0.4: resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= +detect-file@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7" + integrity sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc= + detect-indent@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-5.0.0.tgz#3871cc0a6a002e8c3e5b3cf7f336264675f06b9d" @@ -2918,9 +3221,9 @@ domain-browser@^1.1.1: integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== domelementtype@1, domelementtype@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.0.tgz#b17aed82e8ab59e52dd9c19b1756e0fc187204c2" - integrity sha1-sXrtguirWeUt2cGbF1bg/BhyBMI= + 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" @@ -2996,7 +3299,7 @@ ecc-jsbn@~0.1.1: jsbn "~0.1.0" safer-buffer "^2.1.0" -editorconfig@^0.15.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== @@ -3013,10 +3316,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.2.7, electron-to-chromium@^1.3.79: - version "1.3.79" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.79.tgz#774718f06284a4bf8f578ac67e74508fe659f13a" - integrity sha512-LQdY3j4PxuUl6xfxiFruTSlCniTrTrzAd8/HfsLEMi0PUpaQ0Iy+Pr4N4VllDYjs0Hyu2lkTbvzqlG+PX9NsNw== +electron-to-chromium@^1.2.7, 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== elliptic@^6.0.0: version "6.4.1" @@ -3031,6 +3334,11 @@ elliptic@^6.0.0: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.0" +emojis-list@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" + integrity sha1-TapNnbAPmBmIDHn6RXrlsJof04k= + encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" @@ -3050,16 +3358,32 @@ end-of-stream@^1.0.0, end-of-stream@^1.1.0: dependencies: once "^1.4.0" +enhanced-resolve@^4.0.0, enhanced-resolve@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz#41c7e0bfdfe74ac1ffe1e57ad6a5c6c9f3742a7f" + integrity sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng== + dependencies: + graceful-fs "^4.1.2" + memory-fs "^0.4.0" + tapable "^1.0.0" + entities@^1.1.1, entities@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0" - integrity sha1-blwtClYhtdra7O+AuQ7ftc13cvA= + version "1.1.2" + resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" + integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== err-code@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/err-code/-/err-code-1.1.2.tgz#06e0116d3028f6aef4806849eb0ea6a748ae6960" integrity sha1-BuARbTAo9q70gGhJ6w6mp0iuaWA= +errno@^0.1.3, errno@~0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618" + integrity sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg== + dependencies: + prr "~1.0.1" + error-ex@^1.2.0, error-ex@^1.3.1: version "1.3.2" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" @@ -3067,18 +3391,19 @@ error-ex@^1.2.0, error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -es-abstract@^1.5.1, es-abstract@^1.6.1: - version "1.12.0" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.12.0.tgz#9dbbdd27c6856f0001421ca18782d786bf8a6165" - integrity sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA== +es-abstract@^1.12.0, es-abstract@^1.5.1: + version "1.13.0" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.13.0.tgz#ac86145fdd5099d8dd49558ccba2eaf9b88e24e9" + integrity sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg== dependencies: - es-to-primitive "^1.1.1" + es-to-primitive "^1.2.0" function-bind "^1.1.1" - has "^1.0.1" - is-callable "^1.1.3" + has "^1.0.3" + is-callable "^1.1.4" is-regex "^1.0.4" + object-keys "^1.0.12" -es-to-primitive@^1.1.1: +es-to-primitive@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377" integrity sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg== @@ -3138,6 +3463,14 @@ escodegen@~1.9.0: optionalDependencies: 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== + dependencies: + esrecurse "^4.1.0" + estraverse "^4.1.1" + esprima@^2.6.0: version "2.7.3" resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" @@ -3153,11 +3486,23 @@ esprima@^4.0.0: resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -estraverse@^4.2.0: +esrecurse@^4.1.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" + integrity sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ== + dependencies: + estraverse "^4.1.0" + +estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" integrity sha1-De4/7TH81GlhjOc0IJn8GvoL2xM= +estree-walker@^0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.5.2.tgz#d3850be7529c9580d815600b53126515e146dd39" + integrity sha512-XpCnW/AE10ws/kDAs37cngSkvgIR8aN3G0MS85m7dUpuK2EREo9VJ00uvw6Dg/hXEpfsE1I1TvJOJr+Z+TL+ig== + esutils@^2.0.0, esutils@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" @@ -3181,19 +3526,6 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: md5.js "^1.3.4" safe-buffer "^5.1.1" -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" - execa@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" @@ -3220,6 +3552,13 @@ execa@^1.0.0: signal-exit "^3.0.0" strip-eof "^1.0.0" +expand-brackets@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" + integrity sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s= + dependencies: + is-posix-bracket "^0.1.0" + expand-brackets@^2.1.4: version "2.1.4" resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" @@ -3233,6 +3572,20 @@ expand-brackets@^2.1.4: snapdragon "^0.8.1" to-regex "^3.0.1" +expand-range@^1.8.1: + version "1.8.2" + resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" + integrity sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc= + dependencies: + fill-range "^2.1.0" + +expand-tilde@^2.0.0, expand-tilde@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502" + integrity sha1-l+gBqgUt8CRU3kawK/YhZCzchQI= + dependencies: + homedir-polyfill "^1.0.1" + extend-shallow@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" @@ -3262,6 +3615,13 @@ external-editor@^3.0.0: iconv-lite "^0.4.24" tmp "^0.0.33" +extglob@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" + integrity sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE= + dependencies: + is-extglob "^1.0.0" + extglob@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" @@ -3296,21 +3656,21 @@ falafel@^2.1.0: isarray "0.0.1" object-keys "^1.0.6" -fast-deep-equal@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" - integrity sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ= +fast-deep-equal@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" + integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= fast-glob@^2.0.2, fast-glob@^2.2.2: - version "2.2.3" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.2.3.tgz#d09d378e9ef6b0076a0fa1ba7519d9d4d9699c28" - integrity sha512-NiX+JXjnx43RzvVFwRWfPKo4U+1BrK5pJPsHQdKMlLoFHrrGktXglQhHliSihWAq+m1z6fHk3uwGHrtRbS9vLA== + version "2.2.4" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.2.4.tgz#e54f4b66d378040e0e4d6a68ec36bbc5b04363c0" + integrity sha512-FjK2nCGI/McyzgNtTESqaWP3trPvHyRyoyY70hxjc3oKPNmDe8taohLZpoVKoUjW85tbU5txaYUZCNtVzygl1g== dependencies: "@mrmlnc/readdir-enhanced" "^2.2.1" - "@nodelib/fs.stat" "^1.0.1" + "@nodelib/fs.stat" "^1.1.2" glob-parent "^3.1.0" is-glob "^4.0.0" - merge2 "^1.2.1" + merge2 "^1.2.3" micromatch "^3.1.10" fast-json-stable-stringify@^2.0.0: @@ -3323,7 +3683,7 @@ fast-levenshtein@~2.0.4: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= -figgy-pudding@^3.1.0, figgy-pudding@^3.4.1, figgy-pudding@^3.5.1: +figgy-pudding@^3.4.1, figgy-pudding@^3.5.1: version "3.5.1" resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790" integrity sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w== @@ -3335,11 +3695,35 @@ 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== + dependencies: + loader-utils "^1.0.2" + schema-utils "^1.0.0" + +filename-regex@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" + integrity sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY= + filesize@^3.6.0: version "3.6.1" resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.6.1.tgz#090bb3ee01b6f801a8a8be99d31710b3422bb317" integrity sha512-7KjR1vv6qnicaPMi1iiTcI85CyYwRO/PSFCu6SvqL8jN2Wjt/NIYQTFtFs7fSDCYOstUkEWIQGFUg5YZQfjlcg== +fill-range@^2.1.0: + version "2.2.4" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.4.tgz#eb1e773abb056dcd8df2bfdf6af59b8b3a936565" + integrity sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q== + dependencies: + is-number "^2.1.0" + isobject "^2.0.0" + randomatic "^3.0.0" + repeat-element "^1.1.2" + repeat-string "^1.5.2" + fill-range@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" @@ -3386,6 +3770,16 @@ find-up@^3.0.0: dependencies: locate-path "^3.0.0" +findup-sync@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-2.0.0.tgz#9326b1488c22d1a6088650a86901b2d9a90a2cbc" + integrity sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw= + dependencies: + detect-file "^1.0.0" + is-glob "^3.1.0" + micromatch "^3.0.4" + resolve-dir "^1.0.1" + flatten@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782" @@ -3399,11 +3793,18 @@ flush-write-stream@^1.0.0: inherits "^2.0.1" readable-stream "^2.0.4" -for-in@^1.0.2: +for-in@^1.0.1, for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= +for-own@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" + integrity sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4= + dependencies: + for-in "^1.0.1" + foreach@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" @@ -3452,9 +3853,9 @@ from2@^2.1.0: readable-stream "^2.0.0" fs-extra@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.0.tgz#8cc3f47ce07ef7b3593a11b9fb245f7e34c041d6" - integrity sha512-EglNDLRpmaTWiD/qraZn6HREAEAHJcJOmxNEYwq6xeMKnVMAy3GUcFB+wXt2C6k4CNvB/mP1y/U3dzvKKj5OtQ== + version "7.0.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" + integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== dependencies: graceful-fs "^4.1.2" jsonfile "^4.0.0" @@ -3509,14 +3910,7 @@ fstream@^1.0.0, fstream@^1.0.2: mkdirp ">=0.5 0" rimraf "2" -fswatcher-child@^1.0.5: - version "1.1.1" - resolved "https://registry.yarnpkg.com/fswatcher-child/-/fswatcher-child-1.1.1.tgz#264dd95f9c4b5f8615327d7d7567884591846b9b" - integrity sha512-FVDjVhR71TkJ+ud6vnRwCHvCgK9drGRdimWcTLqw8iN88uL5tTX+/xrwigJdcuQGrWYo3TRw9gRzk9xqR0UPPQ== - dependencies: - chokidar "^2.0.3" - -function-bind@^1.1.0, function-bind@^1.1.1: +function-bind@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== @@ -3638,6 +4032,21 @@ gitconfiglocal@^1.0.0: dependencies: ini "^1.3.2" +glob-base@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" + integrity sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q= + dependencies: + glob-parent "^2.0.0" + is-glob "^2.0.0" + +glob-parent@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" + integrity sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg= + dependencies: + is-glob "^2.0.0" + glob-parent@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" @@ -3663,7 +4072,7 @@ glob@7.1.2: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3: +glob@^7.0.0, glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3: version "7.1.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== @@ -3675,10 +4084,35 @@ glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3: once "^1.3.0" path-is-absolute "^1.0.0" +global-modules-path@^2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/global-modules-path/-/global-modules-path-2.3.1.tgz#e541f4c800a1a8514a990477b267ac67525b9931" + integrity sha512-y+shkf4InI7mPRHSo2b/k6ix6+NLDtyccYv86whhxrSGX9wjPX1VMITmrDbE1eh7zkzhiWtW2sHklJYoQ62Cxg== + +global-modules@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea" + integrity sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg== + dependencies: + global-prefix "^1.0.1" + is-windows "^1.0.1" + resolve-dir "^1.0.0" + +global-prefix@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-1.0.2.tgz#dbf743c6c14992593c655568cb66ed32c0122ebe" + integrity sha1-2/dDxsFJklk8ZVVoy2btMsASLr4= + dependencies: + expand-tilde "^2.0.2" + homedir-polyfill "^1.0.1" + ini "^1.3.4" + is-windows "^1.0.1" + which "^1.2.14" + globals@^11.1.0: - version "11.8.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.8.0.tgz#c1ef45ee9bed6badf0663c5cb90e8d1adec1321d" - integrity sha512-io6LkyPVuzCHBSQV9fmOwxZkUk6nIaGmxheLDgmuFv89j0fm2aqDbIXKAGfzCMHqz3HLF2Zf8WSG6VqMh2qFmA== + version "11.9.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.9.0.tgz#bde236808e987f290768a93d065060d78e6ab249" + integrity sha512-5cJVtyXWH8PiJPVLZzzoIizXx944O4OmRro5MWKx5fT4MgcN7OfaMutPeaTdJCCURwbWdhhcCWcKIffPnmTzBg== globby@^8.0.1: version "8.0.1" @@ -3693,10 +4127,10 @@ globby@^8.0.1: pify "^3.0.0" slash "^1.0.0" -graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6: - version "4.1.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" - integrity sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg= +graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6: + version "4.1.15" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00" + integrity sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA== grapheme-breaker@^0.3.2: version "0.3.2" @@ -3711,6 +4145,14 @@ growl@1.10.5: resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== +gzip-size@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-5.0.0.tgz#a55ecd99222f4c48fd8c01c625ce3b349d0a0e80" + integrity sha512-5iI7omclyqrnWw4XbXAmGhPsABkSIDQonv2K0h61lybgofWa6iZyvrI3r2zsJH4P8Nb64fFVzlvfhs0g7BBxAA== + dependencies: + duplexer "^0.1.1" + pify "^3.0.0" + handlebars@^4.0.11, handlebars@^4.0.2, handlebars@^4.0.6: version "4.0.12" resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.12.tgz#2c15c8a96d46da5e266700518ba8cb8d919d5bc5" @@ -3728,11 +4170,11 @@ har-schema@^2.0.0: integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= har-validator@~5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.0.tgz#44657f5688a22cfd4b72486e81b3a3fb11742c29" - integrity sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA== + version "5.1.3" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080" + integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g== dependencies: - ajv "^5.3.0" + ajv "^6.5.5" har-schema "^2.0.0" has-ansi@^2.0.0: @@ -3793,7 +4235,7 @@ has-values@^1.0.0: is-number "^3.0.0" kind-of "^4.0.0" -has@^1.0.0, has@^1.0.1: +has@^1.0.0, has@^1.0.1, has@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== @@ -3809,9 +4251,9 @@ hash-base@^3.0.0: safe-buffer "^5.0.1" hash.js@^1.0.0, hash.js@^1.0.3: - version "1.1.5" - resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.5.tgz#e38ab4b85dfb1e0c40fe9265c0e9b54854c23812" - integrity sha512-eWI5HG9Np+eHV1KQhisXWwM+4EPPYe5dFX1UZZH7k/E3JzDEazVH+VGlZi6R94ZqImq+A3D1mCEtrFIfg/E7sA== + version "1.1.7" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" + integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== dependencies: inherits "^2.0.3" minimalistic-assert "^1.0.1" @@ -3826,10 +4268,10 @@ hex-color-regex@^1.1.0: resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e" integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ== -highlight.js@^9.0.0: - version "9.13.1" - resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.13.1.tgz#054586d53a6863311168488a0f58d6c505ce641e" - integrity sha512-Sc28JNQNDzaH6PORtRLMvif9RSn1mYuOoX3omVjnb0+HbpPygU2ALBI0R/wsiqCb4/fcp07Gdo8g+fhtFrQl6A== +highlight.js@9.12.0: + version "9.12.0" + resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.12.0.tgz#e6d9dbe57cbefe60751f02af336195870c90c01e" + integrity sha1-5tnb5Xy+/mB1HwKvM2GVhwyQwB4= hmac-drbg@^1.0.0: version "1.0.1" @@ -3840,6 +4282,13 @@ hmac-drbg@^1.0.0: minimalistic-assert "^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= + dependencies: + parse-passwd "^1.0.0" + hosted-git-info@^2.1.4, hosted-git-info@^2.6.0: version "2.7.1" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.7.1.tgz#97f236977bd6e125408930ff6de3eec6281ec047" @@ -3873,16 +4322,16 @@ htmlnano@^0.1.9: terser "^3.8.1" htmlparser2@^3.9.2: - version "3.9.2" - resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.9.2.tgz#1bdf87acca0f3f9e53fa4fcceb0f4b4cbb00b338" - integrity sha1-G9+HrMoPP55T+k/M6w9LTLsAszg= + version "3.10.0" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.0.tgz#5f5e422dcf6119c0d983ed36260ce9ded0bee464" + integrity sha512-J1nEUGv+MkXS0weHNWVKJJ+UrLfePxRWpN3C9bEi9fLxL2+ggW94DQvgYVXsaT30PGwYRIZKNZXuyMhp3Di4bQ== dependencies: domelementtype "^1.3.0" domhandler "^2.3.0" domutils "^1.5.1" entities "^1.1.1" inherits "^2.0.1" - readable-stream "^2.0.2" + readable-stream "^3.0.6" http-cache-semantics@^3.8.1: version "3.8.1" @@ -3965,12 +4414,28 @@ ignore@^3.3.5: resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043" integrity sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug== +import-fresh@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" + integrity sha1-2BNVwVYS04bGH53dOSLUMEgipUY= + dependencies: + caller-path "^2.0.0" + resolve-from "^3.0.0" + import-local@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/import-local/-/import-local-1.0.0.tgz#5e4ffdc03f4fe6c009c6729beb29631c2f8227bc" integrity sha512-vAaZHieK9qjGo58agRBg+bhHX3hoTZU/Oa3GESWLz7t1U62fk63aHuDJJEteXoDeTCcPmUT+z38gkHPZkkmpmQ== dependencies: - pkg-dir "^2.0.0" + pkg-dir "^2.0.0" + resolve-cwd "^2.0.0" + +import-local@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-2.0.0.tgz#55070be38a5993cf18ef6db7e961f5bee5c5a09d" + integrity sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ== + dependencies: + pkg-dir "^3.0.0" resolve-cwd "^2.0.0" imurmurhash@^0.1.4: @@ -4038,9 +4503,9 @@ init-package-json@^1.10.3: validate-npm-package-name "^3.0.0" inquirer@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.2.0.tgz#51adcd776f661369dc1e894859c2560a224abdd8" - integrity sha512-QIEQG4YyQ2UYZGDC4srMZ7BjHOmNk1lR2JQj5UknBapklm6WHA+VVH7N+sUdX3A7NeCfGF8o4X1S3Ao7nAcIeg== + version "6.2.1" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.2.1.tgz#9943fc4882161bdb0b0c9276769c75b32dbfcd52" + integrity sha512-088kl3DRT2dLU5riVMKKr1DlImd6X7smDhpXUCkJDCKvTEJeRiXh0G132HG9u5a+6Ylw9plFRY7RuTnwohYSpg== dependencies: ansi-escapes "^3.0.0" chalk "^2.0.0" @@ -4053,13 +4518,13 @@ inquirer@^6.2.0: run-async "^2.2.0" rxjs "^6.1.0" string-width "^2.1.0" - strip-ansi "^4.0.0" + strip-ansi "^5.0.0" through "^2.3.6" -interpret@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614" - integrity sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ= +interpret@^1.0.0, interpret@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.2.0.tgz#d5061a6224be58e8083985f5014d844359576296" + integrity sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw== invariant@^2.2.2: version "2.2.4" @@ -4131,7 +4596,7 @@ is-builtin-module@^1.0.0: dependencies: builtin-modules "^1.0.0" -is-callable@^1.1.3, is-callable@^1.1.4: +is-callable@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA== @@ -4197,6 +4662,18 @@ is-directory@^0.3.1: resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE= +is-dotfile@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" + integrity sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE= + +is-equal-shallow@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" + integrity sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ= + dependencies: + is-primitive "^2.0.0" + is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" @@ -4209,6 +4686,11 @@ is-extendable@^1.0.1: dependencies: is-plain-object "^2.0.4" +is-extglob@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" + integrity sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA= + is-extglob@^2.1.0, is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" @@ -4233,6 +4715,13 @@ is-fullwidth-code-point@^2.0.0: resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= +is-glob@^2.0.0, is-glob@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" + integrity sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM= + dependencies: + is-extglob "^1.0.0" + is-glob@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" @@ -4247,6 +4736,13 @@ is-glob@^4.0.0: dependencies: is-extglob "^2.1.1" +is-number@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" + integrity sha1-Afy7s5NGOlSPL0ZszhbezknbkI8= + dependencies: + kind-of "^3.0.2" + is-number@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" @@ -4254,6 +4750,11 @@ is-number@^3.0.0: dependencies: kind-of "^3.0.2" +is-number@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff" + integrity sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ== + is-obj@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" @@ -4271,6 +4772,16 @@ is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: dependencies: isobject "^3.0.1" +is-posix-bracket@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" + integrity sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q= + +is-primitive@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" + integrity sha1-IHurkWOEmcB7Kt8kCkGochADRXU= + is-promise@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" @@ -4341,7 +4852,7 @@ is-utf8@^0.2.0: resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= -is-windows@^1.0.2: +is-windows@^1.0.1, is-windows@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== @@ -4436,20 +4947,30 @@ istanbul-reports@^2.0.1: handlebars "^4.0.11" js-base64@^2.1.9: - version "2.4.9" - resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.4.9.tgz#748911fb04f48a60c4771b375cac45a80df11c03" - integrity sha512-xcinL3AuDJk7VSzsHgb9DvvIXayBbadtMZ4HFPx8rUszbW1MuNMlwYVC4zzCZ6e1sqZpnNS5ZFYOhXqA39T7LQ== + version "2.5.0" + resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.5.0.tgz#42255ba183ab67ce59a0dee640afdc00ab5ae93e" + integrity sha512-wlEBIZ5LP8usDylWbDNhKPEFVFdI5hCHpnVoT/Ysvoi/PRhJENm/Rlh9TvjYB38HFfKZN7OzEbRjmjvLkFw11g== -js-beautify@^1.7.5: - version "1.8.7" - resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.8.7.tgz#d87100f714aeb3c388bce9ef011442fc07bda93a" - integrity sha512-yhAMCTv0L9GNg6Gql7i+g4C1z9rQhfHXy4J0TGYFoBzzHR4reWYS573gkRrPuE58dYOH451LmBeAb8L1pLEfdA== +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== dependencies: - config-chain "~1.1.5" - editorconfig "^0.15.0" + config-chain "^1.1.12" + editorconfig "^0.15.2" + glob "^7.1.3" mkdirp "~0.5.0" nopt "~4.0.1" +js-cleanup@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/js-cleanup/-/js-cleanup-1.0.0.tgz#a3aad18a23a1752e9fa005f9128e65d601d2d634" + integrity sha512-gT33849UQki2Ek5NJM9eCH1ZEMjzMfyE881kmfv51hxO4K+TgH+qBIt9RZjczrV02wFqNDSVCk8pE9p78I3cIw== + dependencies: + magic-string "^0.25.1" + perf-regexes "^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" @@ -4466,9 +4987,9 @@ js-tokens@^3.0.2: integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls= js-yaml@^3.10.0, js-yaml@^3.12.0, js-yaml@^3.7.0, js-yaml@^3.9.0: - version "3.12.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.0.tgz#eaed656ec8344f10f527c6bfa1b6e2244de167d1" - integrity sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A== + 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" @@ -4487,24 +5008,24 @@ jsbn@~0.1.0: integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= jsesc@^2.5.1: - version "2.5.1" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.1.tgz#e421a2a8e20d6b0819df28908f782526b96dd1fe" - integrity sha1-5CGiqOINawgZ3yiQj3glJrlt0f4= + version "2.5.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== jsesc@~0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= -json-parse-better-errors@^1.0.0, json-parse-better-errors@^1.0.1: +json-parse-better-errors@^1.0.0, json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== -json-schema-traverse@^0.3.0: - version "0.3.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" - integrity sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A= +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== json-schema@0.2.3: version "0.2.3" @@ -4516,11 +5037,6 @@ json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= -json5@^0.5.0: - version "0.5.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" - integrity sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE= - json5@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" @@ -4528,6 +5044,13 @@ json5@^1.0.1: dependencies: minimist "^1.2.0" +json5@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.0.tgz#e7a0c62c48285c628d20a10b85c89bb807c32850" + integrity sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ== + dependencies: + minimist "^1.2.0" + jsonfile@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" @@ -4588,26 +5111,26 @@ lcid@^2.0.0: dependencies: invert-kv "^2.0.0" -lerna@^3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/lerna/-/lerna-3.6.0.tgz#b6616873fa038ee1dae514e04322c191ff71a369" - integrity sha512-iQFAgrgtv18SI5LtQBBca0WVeYvk2r8eYgiEQtcZBT63T5R9RVv+snsviIiOp0z6gD43tcyiWXiLvBdp1IY/Rg== +lerna@^3.8.5: + version "3.8.5" + resolved "https://registry.yarnpkg.com/lerna/-/lerna-3.8.5.tgz#30001989ccd44dca631c1a77eb4ec1238c4a6dfc" + integrity sha512-cPXU+4CHa0Hg9TBLQsLF7U9LssheakzD/zPQm7hXFjbqKrTx+p1QAgI/ehaY5CMqT4dPZUjOuR2zWI2hpBJaXQ== dependencies: - "@lerna/add" "^3.6.0" - "@lerna/bootstrap" "^3.6.0" - "@lerna/changed" "^3.6.0" - "@lerna/clean" "^3.6.0" + "@lerna/add" "^3.8.5" + "@lerna/bootstrap" "^3.8.5" + "@lerna/changed" "^3.8.5" + "@lerna/clean" "^3.8.5" "@lerna/cli" "^3.6.0" - "@lerna/create" "^3.6.0" - "@lerna/diff" "^3.6.0" - "@lerna/exec" "^3.6.0" - "@lerna/import" "^3.6.0" - "@lerna/init" "^3.6.0" - "@lerna/link" "^3.6.0" - "@lerna/list" "^3.6.0" - "@lerna/publish" "^3.6.0" - "@lerna/run" "^3.6.0" - "@lerna/version" "^3.6.0" + "@lerna/create" "^3.8.5" + "@lerna/diff" "^3.8.5" + "@lerna/exec" "^3.8.5" + "@lerna/import" "^3.8.5" + "@lerna/init" "^3.8.5" + "@lerna/link" "^3.8.5" + "@lerna/list" "^3.8.5" + "@lerna/publish" "^3.8.5" + "@lerna/run" "^3.8.5" + "@lerna/version" "^3.8.5" import-local "^1.0.0" libnpm "^2.0.1" @@ -4718,6 +5241,11 @@ libnpmteam@^1.0.1: get-stream "^4.0.0" npm-registry-fetch "^3.8.0" +lightercollective@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/lightercollective/-/lightercollective-0.1.0.tgz#70df102c530dcb8d0ccabfe6175a8d00d5f61300" + integrity sha512-J9tg5uraYoQKaWbmrzDDexbG6hHnMcWS1qLYgJSWE+mpA3U5OCSeMUhb+K55otgZJ34oFdR0ECvdIb3xuO5JOQ== + 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" @@ -4739,6 +5267,20 @@ load-json-file@^4.0.0: pify "^3.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== + +loader-utils@^1.0.2, loader-utils@^1.1.0: + version "1.2.3" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.2.3.tgz#1ff5dc6911c9f0a062531a4c04b609406108c2c7" + integrity sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA== + dependencies: + big.js "^5.2.2" + emojis-list "^2.0.0" + json5 "^1.0.1" + locate-path@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" @@ -4846,13 +5388,20 @@ loud-rejection@^1.0.0: signal-exit "^3.0.0" lru-cache@^4.0.1, lru-cache@^4.1.2, lru-cache@^4.1.3: - version "4.1.3" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.3.tgz#a1175cf3496dfc8436c156c334b4955992bce69c" - integrity sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA== + version "4.1.5" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" + integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== dependencies: pseudomap "^1.0.2" yallist "^2.1.2" +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" + magic-string@^0.22.4: version "0.22.5" resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.22.5.tgz#8e9cf5afddf44385c1da5bc2a6a0dbd10b03657e" @@ -4860,6 +5409,13 @@ magic-string@^0.22.4: dependencies: 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== + dependencies: + sourcemap-codec "^1.4.1" + make-dir@^1.0.0, make-dir@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" @@ -4885,9 +5441,9 @@ make-fetch-happen@^4.0.1: ssri "^6.0.0" map-age-cleaner@^0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.2.tgz#098fb15538fd3dbe461f12745b0ca8568d4e3f74" - integrity sha512-UN1dNocxQq44IhJyMI4TU8phc2m9BddacHRPRjKGLYaF0jqd3xLz0jS0skpAU9WgYyoR4gHtUpzytNBS385FWQ== + version "0.1.3" + resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a" + integrity sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w== dependencies: p-defer "^1.0.0" @@ -4923,6 +5479,11 @@ math-expression-evaluator@^1.2.14: resolved "https://registry.yarnpkg.com/math-expression-evaluator/-/math-expression-evaluator-1.2.17.tgz#de819fdbcd84dccd8fae59c6aeb79615b9d266ac" integrity sha1-3oGf282E3M2PrlnGrreWFbnSZqw= +math-random@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.1.tgz#8b3aac588b8a66e4975e3cdea67f7bb329601fac" + integrity sha1-izqsWIuKZuSXXjzepn97sylgH6w= + md5-hex@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/md5-hex/-/md5-hex-2.0.0.tgz#d0588e9f1c74954492ecd24ac0ac6ce997d92e33" @@ -4965,6 +5526,14 @@ mem@^4.0.0: mimic-fn "^1.0.0" p-is-promise "^1.1.0" +memory-fs@^0.4.0, memory-fs@~0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" + integrity sha1-OpoguEYlI+RHz7x+i7gO1me/xVI= + dependencies: + errno "^0.1.3" + readable-stream "^2.0.1" + meow@^3.3.0: version "3.7.0" resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb" @@ -5010,12 +5579,31 @@ merge-source-map@^1.1.0: dependencies: source-map "^0.6.1" -merge2@^1.2.1: +merge2@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.2.3.tgz#7ee99dbd69bb6481689253f018488a1b902b0ed5" integrity sha512-gdUU1Fwj5ep4kplwcmftruWofEFt6lfpkkr3h860CXbAB9c3hGb55EOL2ali0Td5oebvW0E1+3Sr+Ur7XfKpRA== -micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4: +micromatch@^2.3.11: + version "2.3.11" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" + integrity sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU= + dependencies: + arr-diff "^2.0.0" + array-unique "^0.2.1" + braces "^1.8.2" + expand-brackets "^0.1.4" + extglob "^0.3.1" + filename-regex "^2.0.0" + is-extglob "^1.0.0" + is-glob "^2.0.1" + kind-of "^3.0.2" + normalize-path "^2.0.1" + object.omit "^2.0.0" + parse-glob "^3.0.4" + regex-cache "^0.4.2" + +micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4, micromatch@^3.1.8: version "3.1.10" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== @@ -5042,17 +5630,17 @@ miller-rabin@^4.0.0: bn.js "^4.0.0" brorand "^1.0.1" -mime-db@~1.36.0: - version "1.36.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.36.0.tgz#5020478db3c7fe93aad7bbcc4dcf869c43363397" - integrity sha512-L+xvyD9MkoYMXb1jAmzI/lWYAxAMCPvIBSWur0PZ5nOf5euahRLVqH//FKW9mWp2lkqUgYiXPgkzfMUFi4zVDw== +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-types@^2.1.12, mime-types@~2.1.19: - version "2.1.20" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.20.tgz#930cb719d571e903738520f8470911548ca2cc19" - integrity sha512-HrkrPaP9vGuWbLK1B1FfgAkbqNjIuy4eHlIYnFi7kamZyLLrGlo2mpcx0bBmNpKqBtYtAfGbodDddIgddSJC2A== + 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== dependencies: - mime-db "~1.36.0" + mime-db "~1.37.0" mime@1.4.1: version "1.4.1" @@ -5104,15 +5692,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.3: - version "2.3.4" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.4.tgz#4768d7605ed6194d6d576169b9e12ef71e9d9957" - integrity sha512-mlouk1OHlaUE8Odt1drMtG1bAJA4ZA6B/ehysgV0LUIrDHdKgo1KorZq3pK0b/7Z7LJIQ12MNM6aC+Tn6lUZ5w== - dependencies: - safe-buffer "^5.1.2" - yallist "^3.0.0" - -minipass@^2.3.4, minipass@^2.3.5: +minipass@^2.2.1, minipass@^2.3.4, minipass@^2.3.5: version "2.3.5" resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.5.tgz#cacebe492022497f656b0f0f51e2682a9ed2d848" integrity sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA== @@ -5120,13 +5700,6 @@ minipass@^2.3.4, minipass@^2.3.5: safe-buffer "^5.1.2" yallist "^3.0.0" -minizlib@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.1.1.tgz#6734acc045a46e61d596a43bb9d9cd326e19cc42" - integrity sha512-TrfjCjk4jLhcJyGMYymBH6oTXcWjYbUAXTHDbtnWHjZC25h0cdajHuPE1zxb4DVmu8crfh+HwH/WMuyLG0nHBg== - dependencies: - minipass "^2.2.1" - minizlib@^1.1.1: version "1.2.1" resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.2.1.tgz#dd27ea6136243c7c880684e8672bb3a45fd9b614" @@ -5219,15 +5792,20 @@ multimatch@^2.1.0: arrify "^1.0.0" minimatch "^3.0.0" -mute-stream@0.0.7, mute-stream@~0.0.4: +mute-stream@0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= -nan@^2.0.7, nan@^2.9.2: - version "2.11.1" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.11.1.tgz#90e22bccb8ca57ea4cd37cc83d3819b52eea6766" - integrity sha512-iji6k87OSXa0CcrLl9z+ZiYSuR2o+c0bGuNmXdrhTQTakxytAFsC56SArGYoiHlJlFoHSnvmhpceZJaXkVuOtA== +mute-stream@~0.0.4: + version "0.0.8" + 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== nanomatch@^1.2.9: version "1.2.13" @@ -5255,11 +5833,21 @@ needle@^2.2.1: iconv-lite "^0.4.4" sax "^1.2.4" +neo-async@^2.5.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== + nice-try@^1.0.4: version "1.0.5" resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" 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== + node-fetch-npm@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/node-fetch-npm/-/node-fetch-npm-2.0.2.tgz#7258c9046182dca345b4208eda918daf33697ff7" @@ -5337,10 +5925,10 @@ node-pre-gyp@^0.10.0: semver "^5.3.0" tar "^4" -node-releases@^1.0.0-alpha.14: - version "1.0.0-alpha.14" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.0.0-alpha.14.tgz#da9e2780add4bbb59ad890af9e2018a1d9c0034b" - integrity sha512-G8nnF9cP9QPP/jUmYWw/uUUhumHmkm+X/EarCugYFjYm2uXRMFeOD6CVT3RLdoyCvDUNy51nirGfUItKWs/S1g== +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== dependencies: semver "^5.3.0" @@ -5369,7 +5957,7 @@ normalize-package-data@^2.0.0, normalize-package-data@^2.3.0, normalize-package- semver "2 || 3 || 4 || 5" validate-npm-package-license "^3.0.1" -normalize-path@^2.1.1: +normalize-path@^2.0.1, normalize-path@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= @@ -5431,9 +6019,9 @@ npm-logical-tree@^1.2.1: validate-npm-package-name "^3.0.0" npm-packlist@^1.1.12, npm-packlist@^1.1.6: - version "1.1.12" - resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.1.12.tgz#22bde2ebc12e72ca482abd67afc51eb49377243a" - integrity sha512-WJKFOVMeAlsU/pjXuqVdzU0WfgtIBCupkEVwn+1Y0ERAbUfWw8R4GjgVbaKnUjRoD2FoQbHOCbOyT5Mbs9Lw4g== + 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" @@ -5485,10 +6073,10 @@ npm-run-path@^2.0.0: gauge "~2.7.3" set-blocking "~2.0.0" -nth-check@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.1.tgz#9929acdf628fc2c41098deab82ac580cf149aae4" - integrity sha1-mSms32KPwsQQmN6rgqxYDPFJquQ= +nth-check@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c" + integrity sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg== dependencies: boolbase "~1.0.0" @@ -5577,6 +6165,14 @@ object.getownpropertydescriptors@^2.0.3: define-properties "^1.1.2" es-abstract "^1.5.1" +object.omit@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" + integrity sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo= + dependencies: + for-own "^0.1.4" + is-extendable "^0.1.1" + object.pick@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" @@ -5585,14 +6181,14 @@ object.pick@^1.3.0: isobject "^3.0.1" object.values@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.0.4.tgz#e524da09b4f66ff05df457546ec72ac99f13069a" - integrity sha1-5STaCbT2b/Bd9FdUbscqyZ8TBpo= + version "1.1.0" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.0.tgz#bf6810ef5da3e5325790eaaa2be213ea84624da9" + integrity sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg== dependencies: - define-properties "^1.1.2" - es-abstract "^1.6.1" - function-bind "^1.1.0" - has "^1.0.1" + define-properties "^1.1.3" + es-abstract "^1.12.0" + function-bind "^1.1.1" + has "^1.0.3" on-finished@~2.3.0: version "2.3.0" @@ -5674,11 +6270,11 @@ os-locale@^2.0.0: mem "^1.1.0" os-locale@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.0.1.tgz#3b014fbf01d87f60a1e5348d80fe870dc82c4620" - integrity sha512-7g5e7dmXPtzcP4bgsZ8ixDVqA7oWYuEz4lOSujeWyliPai4gfVDiFIcwBg3aGCPnmSGfzOKTK3ccPn0CKv3DBw== + version "3.1.0" + resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a" + integrity sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q== dependencies: - execa "^0.10.0" + execa "^1.0.0" lcid "^2.0.0" mem "^4.0.0" @@ -5718,9 +6314,9 @@ p-limit@^1.1.0: p-try "^1.0.0" p-limit@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.0.0.tgz#e624ed54ee8c460a778b3c9f3670496ff8a57aec" - integrity sha512-fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A== + version "2.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.1.0.tgz#1d5a0d20fb12707c758a655f6bbc4386b5930d68" + integrity sha512-NhURkNcrVB+8hNfLuysU8enY5xn2KXphsHBaC2YmRNTZRc7RWusw6apSpdEj3jo4CMb6W9nrF6tTnsJsJeyu6g== dependencies: p-try "^2.0.0" @@ -5788,16 +6384,16 @@ package-hash@^2.0.0: release-zalgo "^1.0.0" pacote@^9.2.3: - version "9.2.3" - resolved "https://registry.yarnpkg.com/pacote/-/pacote-9.2.3.tgz#48cfe87beb9177acd6594355a584a538835424b3" - integrity sha512-Y3+yY3nBRAxMlZWvr62XLJxOwCmG9UmkGZkFurWHoCjqF0cZL72cTOCRJTvWw8T4OhJS2RTg13x4oYYriauvEw== + version "9.3.0" + resolved "https://registry.yarnpkg.com/pacote/-/pacote-9.3.0.tgz#ec0d21b739a625d81a19ae546386fedee3300bc1" + integrity sha512-uy5xghB5wUtmFS+uNhQGhlsIF9rfsfxw6Zsu2VpmSz4/f+8D2+5V1HwjHdSn7W6aQTrxNNmmoUF5qNE10/EVdA== dependencies: - bluebird "^3.5.2" - cacache "^11.2.0" + bluebird "^3.5.3" + cacache "^11.3.2" figgy-pudding "^3.5.1" get-stream "^4.1.0" glob "^7.1.3" - lru-cache "^4.1.3" + lru-cache "^5.1.1" make-fetch-happen "^4.0.1" minimatch "^3.0.4" minipass "^2.3.5" @@ -5816,7 +6412,7 @@ pacote@^9.2.3: safe-buffer "^5.1.2" semver "^5.6.0" ssri "^6.0.1" - tar "^4.4.6" + tar "^4.4.8" unique-filename "^1.1.1" which "^1.3.1" @@ -5826,9 +6422,9 @@ pako@^0.2.5: integrity sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU= pako@~1.0.5: - version "1.0.6" - resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.6.tgz#0101211baa70c4bca4a0f63f2206e97b7dfaf258" - integrity sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg== + version "1.0.7" + resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.7.tgz#2473439021b57f1516c82f58be7275ad8ef1bb27" + integrity sha512-3HNK5tW4x8o5mO8RuHZp3Ydw9icZXx0RANAOMzlMzx7LVXhMJ4mo3MOBpzyd7r/+RUu8BmndP47LXT+vzjtWcQ== parallel-transform@^1.1.0: version "1.1.0" @@ -5839,10 +6435,10 @@ parallel-transform@^1.1.0: inherits "^2.0.3" readable-stream "^2.1.5" -parcel-bundler@^1.10.3: - version "1.10.3" - resolved "https://registry.yarnpkg.com/parcel-bundler/-/parcel-bundler-1.10.3.tgz#8502b40d3f23139093b25e82658f6060f025c024" - integrity sha512-Lj31fr5o2AZFbazghL/MrubzvJEXLwx24rd3MiR3lncmqCXbd5q0hgl1kpV6X+vRaN9/cSDR8G0lotmgl5OyZg== +parcel-bundler@^1.11.0: + version "1.11.0" + resolved "https://registry.yarnpkg.com/parcel-bundler/-/parcel-bundler-1.11.0.tgz#7e821a5246d7503aebf3c1bc279b59cbb8a3d4e3" + integrity sha512-H0w/Obx76vWiG+UtofznfcHZJBmd6JA5iCn7zrGBINyVAh+Nt/JLD6QDROghHLXfJkO4XyczsB+fO+nPbXlFfA== dependencies: "@babel/code-frame" "^7.0.0" "@babel/core" "^7.0.0" @@ -5856,6 +6452,12 @@ parcel-bundler@^1.10.3: "@babel/template" "^7.0.0" "@babel/traverse" "^7.0.0" "@babel/types" "^7.0.0" + "@iarna/toml" "^2.2.0" + "@parcel/fs" "^1.11.0" + "@parcel/logger" "^1.11.0" + "@parcel/utils" "^1.11.0" + "@parcel/watcher" "^1.11.0" + "@parcel/workers" "^1.11.0" ansi-to-html "^0.6.4" babylon-walk "^1.0.2" browserslist "^4.1.0" @@ -5865,14 +6467,12 @@ parcel-bundler@^1.10.3: commander "^2.11.0" cross-spawn "^6.0.4" cssnano "^4.0.0" - deasync "^0.1.13" + deasync "^0.1.14" dotenv "^5.0.0" dotenv-expand "^4.2.0" fast-glob "^2.2.2" filesize "^3.6.0" - fswatcher-child "^1.0.5" get-port "^3.2.0" - grapheme-breaker "^0.3.2" htmlnano "^0.1.9" is-glob "^4.0.0" is-url "^1.2.2" @@ -5883,10 +6483,8 @@ parcel-bundler@^1.10.3: node-forge "^0.7.1" node-libs-browser "^2.0.0" opn "^5.1.0" - ora "^2.1.0" - physical-cpu-count "^2.0.0" - postcss "^6.0.19" - postcss-value-parser "^3.3.0" + postcss "^7.0.5" + postcss-value-parser "^3.3.1" posthtml "^0.11.2" posthtml-parser "^0.4.0" posthtml-render "^1.1.3" @@ -5895,10 +6493,7 @@ parcel-bundler@^1.10.3: serialize-to-js "^1.1.1" serve-static "^1.12.4" source-map "0.6.1" - strip-ansi "^4.0.0" terser "^3.7.3" - toml "^2.3.3" - tomlify-j0.4 "^3.0.0" v8-compile-cache "^2.0.0" ws "^5.1.1" @@ -5918,6 +6513,16 @@ parse-github-repo-url@^1.3.0: resolved "https://registry.yarnpkg.com/parse-github-repo-url/-/parse-github-repo-url-1.4.1.tgz#9e7d8bb252a6cb6ba42595060b7bf6df3dbc1f50" integrity sha1-nn2LslKmy2ukJZUGC3v23z28H1A= +parse-glob@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" + integrity sha1-ssN2z7EfNVE7rdFz7wu246OIORw= + dependencies: + glob-base "^0.3.0" + is-dotfile "^1.0.0" + is-extglob "^1.0.0" + is-glob "^2.0.0" + parse-json@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" @@ -5933,6 +6538,11 @@ parse-json@^4.0.0: error-ex "^1.3.1" json-parse-better-errors "^1.0.1" +parse-passwd@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" + integrity sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY= + parseurl@~1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3" @@ -5980,7 +6590,7 @@ path-key@^2.0.0, path-key@^2.0.1: resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= -path-parse@^1.0.5: +path-parse@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== @@ -6012,10 +6622,15 @@ pbkdf2@^3.0.3: safe-buffer "^5.0.1" sha.js "^2.4.8" -pegjs@^0.10.0: - version "0.10.0" - resolved "https://registry.yarnpkg.com/pegjs/-/pegjs-0.10.0.tgz#cf8bafae6eddff4b5a7efb185269eaaf4610ddbd" - integrity sha1-z4uvrm7d/0tafvsYUmnqr0YQ3b0= +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== + +perf-regexes@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/perf-regexes/-/perf-regexes-1.0.1.tgz#6da1d62f5a94bf9353a0451bccacf69068b75d0b" + integrity sha512-L7MXxUDtqr4PUaLFCDCXBfGV/6KLIuSEccizDI7JxT+c9x1G1v04BQ4+4oag84SHaCdrBgQAIs/Cqn+flwFPng== performance-now@^2.1.0: version "2.1.0" @@ -6082,15 +6697,15 @@ postcss-calc@^5.2.0: postcss-message-helpers "^2.0.0" reduce-css-calc "^1.2.6" -postcss-calc@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-6.0.2.tgz#4d9a43e27dbbf27d095fecb021ac6896e2318337" - integrity sha512-fiznXjEN5T42Qm7qqMCVJXS3roaj9r4xsSi+meaBVe7CJBl8t/QLOXu02Z2E6oWAMWIvCuF6JrvzFekmVEbOKA== +postcss-calc@^7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-7.0.1.tgz#36d77bab023b0ecbb9789d84dcb23c4941145436" + integrity sha512-oXqx0m6tb4N3JGdmeMSc/i91KppbYsFZKdH0xMOqK8V1rJlzrKlTdokz8ozUXLVejydRN6u2IddxpcijRj2FqQ== dependencies: css-unit-converter "^1.1.1" - postcss "^7.0.2" - postcss-selector-parser "^2.2.2" - reduce-css-calc "^2.0.0" + postcss "^7.0.5" + postcss-selector-parser "^5.0.0-rc.4" + postcss-value-parser "^3.3.1" postcss-colormin@^2.1.8: version "2.2.2" @@ -6215,10 +6830,10 @@ postcss-merge-longhand@^2.0.1: dependencies: postcss "^5.0.4" -postcss-merge-longhand@^4.0.6: - version "4.0.6" - resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-4.0.6.tgz#2b938fa3529c3d1657e53dc7ff0fd604dbc85ff1" - integrity sha512-JavnI+V4IHWsaUAfOoKeMEiJQGXTraEy1nHM0ILlE6NIQPEZrJDAnPh3lNGZ5HAk2mSSrwp66JoGhvjp6SqShA== +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" @@ -6507,6 +7122,15 @@ postcss-selector-parser@^3.0.0: indexes-of "^1.0.1" uniq "^1.0.1" +postcss-selector-parser@^5.0.0-rc.4: + version "5.0.0" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz#249044356697b33b64f1a8f7c80922dddee7195c" + integrity sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ== + dependencies: + cssesc "^2.0.0" + indexes-of "^1.0.1" + uniq "^1.0.1" + postcss-svgo@^2.1.1: version "2.1.6" resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-2.1.6.tgz#b6df18aa613b666e133f08adb5219c2684ac108d" @@ -6545,7 +7169,7 @@ postcss-unique-selectors@^4.0.1: postcss "^7.0.0" uniqs "^2.0.0" -postcss-value-parser@^3.0.0, postcss-value-parser@^3.0.1, postcss-value-parser@^3.0.2, postcss-value-parser@^3.1.1, postcss-value-parser@^3.1.2, postcss-value-parser@^3.2.3, postcss-value-parser@^3.3.0: +postcss-value-parser@^3.0.0, postcss-value-parser@^3.0.1, postcss-value-parser@^3.0.2, postcss-value-parser@^3.1.1, postcss-value-parser@^3.1.2, postcss-value-parser@^3.2.3, postcss-value-parser@^3.3.0, postcss-value-parser@^3.3.1: version "3.3.1" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ== @@ -6569,19 +7193,10 @@ postcss@^5.0.10, postcss@^5.0.11, postcss@^5.0.12, postcss@^5.0.13, postcss@^5.0 source-map "^0.5.6" supports-color "^3.2.3" -postcss@^6.0.19: - version "6.0.23" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.23.tgz#61c82cc328ac60e677645f979054eb98bc0e3324" - integrity sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag== - dependencies: - chalk "^2.4.1" - source-map "^0.6.1" - supports-color "^5.4.0" - -postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.2: - version "7.0.5" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.5.tgz#70e6443e36a6d520b0fd4e7593fcca3635ee9f55" - integrity sha512-HBNpviAUFCKvEh7NZhw1e8MBPivRszIiUnhrJ+sBFVSYSqubrzwX3KG51mYgcRHX8j/cAgZJedONZcm5jTBdgQ== +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" @@ -6628,6 +7243,11 @@ prepend-http@^1.0.0: resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= +preserve@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" + integrity sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks= + private@^0.1.6: version "0.1.8" resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" @@ -6644,9 +7264,9 @@ process@^0.11.10: integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= progress@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.1.tgz#c9242169342b1c29d275889c95734621b1952e31" - integrity sha512-OE+a6vzqazc+K6LxJrX5UPyKFvGnL5CYmq2jFGNIBWHpc4QyE49/YOumcrpQFJpfejmvRtbJzgO1zPmMCqlbBg== + version "2.0.3" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" + integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== promise-inflight@^1.0.1: version "1.0.1" @@ -6680,15 +7300,20 @@ protoduck@^5.0.1: dependencies: genfun "^5.0.0" +prr@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" + integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY= + pseudomap@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= psl@^1.1.24: - version "1.1.29" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.29.tgz#60f580d360170bb722a797cc704411e6da850c67" - integrity sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ== + 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== public-encrypt@^4.0.0: version "4.0.3" @@ -6784,6 +7409,15 @@ quote-stream@^1.0.1, quote-stream@~1.0.2: minimist "^1.1.3" through2 "^2.0.0" +randomatic@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-3.1.1.tgz#b776efc59375984e36c537b2f51a1f0aff0da1ed" + integrity sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw== + dependencies: + is-number "^4.0.0" + kind-of "^6.0.0" + math-random "^1.0.1" + 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" @@ -6893,7 +7527,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.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@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: version "2.3.6" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== @@ -6906,6 +7540,15 @@ 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== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + readdir-scoped-modules@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/readdir-scoped-modules/-/readdir-scoped-modules-1.0.2.tgz#9fafa37d286be5d92cbaebdee030dc9b5f406747" @@ -6957,14 +7600,6 @@ reduce-css-calc@^1.2.6: math-expression-evaluator "^1.2.14" reduce-function-call "^1.0.1" -reduce-css-calc@^2.0.0: - version "2.1.5" - resolved "https://registry.yarnpkg.com/reduce-css-calc/-/reduce-css-calc-2.1.5.tgz#f283712f0c9708ef952d328f4b16112d57b03714" - integrity sha512-AybiBU03FKbjYzyvJvwkJZY6NLN+80Ufc2EqEs+41yQH+8wqBEslD6eGiS0oIeq5TNLA5PrhBeYHXWdn8gtW7A== - dependencies: - css-unit-converter "^1.1.1" - postcss-value-parser "^3.3.0" - reduce-function-call@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/reduce-function-call/-/reduce-function-call-1.0.2.tgz#5a200bf92e0e37751752fe45b0ab330fd4b6be99" @@ -7001,6 +7636,13 @@ regenerator-transform@^0.13.3: dependencies: private "^0.1.6" +regex-cache@^0.4.2: + version "0.4.4" + resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" + integrity sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ== + dependencies: + is-equal-shallow "^0.1.3" + regex-not@^1.0.0, regex-not@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" @@ -7010,26 +7652,26 @@ regex-not@^1.0.0, regex-not@^1.0.2: safe-regex "^1.1.0" regexpu-core@^4.1.3, regexpu-core@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.2.0.tgz#a3744fa03806cffe146dea4421a3e73bdcc47b1d" - integrity sha512-Z835VSnJJ46CNBttalHD/dB+Sj2ezmY6Xp38npwU87peK6mqOzOpV8eYktdkLTEkzzD+JsTcxd84ozd8I14+rw== + version "4.4.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.4.0.tgz#8d43e0d1266883969720345e70c275ee0aec0d32" + integrity sha512-eDDWElbwwI3K0Lo6CqbQbA6FwgtCz4kYTarrri1okfkRLZAqstU+B3voZBCjg8Fl6iq0gXrJG6MvRgLthfvgOA== dependencies: regenerate "^1.4.0" regenerate-unicode-properties "^7.0.0" - regjsgen "^0.4.0" - regjsparser "^0.3.0" + regjsgen "^0.5.0" + regjsparser "^0.6.0" unicode-match-property-ecmascript "^1.0.4" unicode-match-property-value-ecmascript "^1.0.2" -regjsgen@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.4.0.tgz#c1eb4c89a209263f8717c782591523913ede2561" - integrity sha512-X51Lte1gCYUdlwhF28+2YMO0U6WeN0GLpgpA7LK7mbdDnkQYiwvEpmpe0F/cv5L14EbxgrdayAG3JETBv0dbXA== +regjsgen@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.0.tgz#a7634dc08f89209c2049adda3525711fb97265dd" + integrity sha512-RnIrLhrXCX5ow/E5/Mh2O4e/oa1/jW0eaBKTSy3LaCj+M3Bqvm97GWDp2yUtzIs4LEn65zR2yiYGFqb2ApnzDA== -regjsparser@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.3.0.tgz#3c326da7fcfd69fa0d332575a41c8c0cdf588c96" - integrity sha512-zza72oZBBHzt64G7DxdqrOo/30bhHkwMUoT0WqfGu98XLd7N+1tsy5MJ96Bk4MD0y74n629RhmrGW6XlnLLwCA== +regjsparser@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.0.tgz#f1e6ae8b7da2bae96c99399b868cd6c933a2ba9c" + integrity sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ== dependencies: jsesc "~0.5.0" @@ -7050,7 +7692,7 @@ repeat-element@^1.1.2: resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== -repeat-string@^1.6.1: +repeat-string@^1.5.2, repeat-string@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= @@ -7105,6 +7747,14 @@ resolve-cwd@^2.0.0: dependencies: resolve-from "^3.0.0" +resolve-dir@^1.0.0, resolve-dir@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-1.0.1.tgz#79a40644c362be82f26effe739c9bb5382046f43" + integrity sha1-eaQGRMNivoLybv/nOcm7U4IEb0M= + dependencies: + expand-tilde "^2.0.0" + global-modules "^1.0.0" + resolve-from@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" @@ -7121,11 +7771,11 @@ resolve-url@^0.2.1: integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= resolve@^1.1.5, resolve@^1.1.6, resolve@^1.3.2, resolve@^1.4.0: - version "1.8.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.8.1.tgz#82f1ec19a423ac1fbd080b0bab06ba36e84a7a26" - integrity sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA== + version "1.9.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.9.0.tgz#a14c6fdfa8f92a7df1d996cb7105fa744658ea06" + integrity sha512-TZNye00tI67lwYvzxCxHGjwTNlUV70io54/Ed4j6PscB8xVfuBJpRenI/o6dVk0cY0PYTY27AgCoGGxRnYuItQ== dependencies: - path-parse "^1.0.5" + path-parse "^1.0.6" restore-cursor@^2.0.0: version "2.0.0" @@ -7155,12 +7805,12 @@ rgba-regex@^1.0.0: resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3" integrity sha1-QzdOLiyglosO8VI0YLfXMP8i7rM= -rimraf@2, rimraf@^2.5.2, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" - integrity sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w== +rimraf@2, rimraf@^2.5.2, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@^2.6.3: + version "2.6.3" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" + integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== dependencies: - glob "^7.0.5" + glob "^7.1.3" ripemd160@^2.0.0, ripemd160@^2.0.1: version "2.0.2" @@ -7170,6 +7820,31 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: hash-base "^3.0.0" inherits "^2.0.1" +rollup-plugin-cleanup@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/rollup-plugin-cleanup/-/rollup-plugin-cleanup-3.1.0.tgz#ba453828c9039fba76e276bb6c516e7dfd5d23d4" + integrity sha512-HA6PyX6tvN3rK6VgGemqPcDC62vYL9FawIng7IciaXbj/wJ4ydY13JmN+S+zIOtVaqpJhB3lTH24l2YVGJlC8A== + dependencies: + js-cleanup "^1.0.0" + rollup-pluginutils "^2.3.0" + +rollup-pluginutils@^2.3.0: + version "2.3.3" + resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-2.3.3.tgz#3aad9b1eb3e7fe8262820818840bf091e5ae6794" + integrity sha512-2XZwja7b6P5q4RZ5FhyX1+f46xi1Z3qBKigLRZ6VTZjwbN0K1IFGMlwm06Uu0Emcre2Z63l77nq/pzn+KxIEoA== + dependencies: + estree-walker "^0.5.2" + micromatch "^2.3.11" + +rollup@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-1.1.0.tgz#461a7534b55be48aa4a6e6810a1543a5769e75d1" + integrity sha512-NK03gkkOz0CchHBMGomcNqa6U3jLNzHuWK9SI0+1FV475JA6cQxVtjlDcQoKKDNIQ3IwYumIlgoKYDEWUyFBwQ== + dependencies: + "@types/estree" "0.0.39" + "@types/node" "*" + acorn "^6.0.5" + run-async@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" @@ -7208,19 +7883,36 @@ safe-regex@^1.1.0: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -safer-eval@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/safer-eval/-/safer-eval-1.2.3.tgz#73ba74a34bc8a07d6a44135c815fd18a8eebe7a0" - integrity sha512-nDwXOhiheoaBT6op02n8wzsshjLXHhh4YAeqsDEoVmy1k2+lGv/ENLsGaWqkaKArUkUx48VO12/ZPa3sI/OEqQ== +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== dependencies: - clones "^1.1.0" + clones "^1.2.0" sax@^1.2.4, sax@~1.2.1, sax@~1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== -"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: +schema-utils@^0.4.4: + version "0.4.7" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-0.4.7.tgz#ba74f597d2be2ea880131746ee17d0a093c68187" + integrity sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ== + dependencies: + ajv "^6.1.0" + ajv-keywords "^3.1.0" + +schema-utils@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770" + integrity sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g== + dependencies: + ajv "^6.1.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== @@ -7249,13 +7941,18 @@ send@0.16.2: range-parser "~1.2.0" statuses "~1.4.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-to-js@^1.1.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/serialize-to-js/-/serialize-to-js-1.2.1.tgz#2e87f61f938826d24c463a7cbd0dd2929ec38008" - integrity sha512-TK6d30GNkOLeFDPuP6Jfy1Q1V31GxzppYTt2lzr8KWmIUKomFj+260QP5o4AhHLu0pr6urgyS8i/Z1PqurjBoA== + version "1.2.2" + resolved "https://registry.yarnpkg.com/serialize-to-js/-/serialize-to-js-1.2.2.tgz#1a567b0c9bf557bc7d7b77b503dfae0a8218d15d" + integrity sha512-mUc8vA5iJghe+O+3s0YDGFLMJcqitVFk787YKiv8a4sf6RX5W0u81b+gcHrp15O0fFa010dRBVZvwcKXOWsL9Q== dependencies: - js-beautify "^1.7.5" - safer-eval "^1.2.3" + js-beautify "^1.8.9" + safer-eval "^1.3.0" serve-static@^1.12.4: version "1.13.2" @@ -7328,9 +8025,9 @@ shebang-regex@^1.0.0: integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= shelljs@^0.8.2: - version "0.8.2" - resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.2.tgz#345b7df7763f4c2340d584abb532c5f752ca9e35" - integrity sha512-pRXeNrCA2Wd9itwhvLp5LZQvPJ0wU6bcjaTMywHHGX5XWhVN2nzSu7WV0q+oUY7mGK3mgSkDDzP3MgjqdyIgbQ== + version "0.8.3" + resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.3.tgz#a7f3319520ebf09ee81275b2368adb286659b097" + integrity sha512-fc0BKlAWiLpwZljmOvAOTE/gXawtCoNrP5oaY7KIaQbbyHeQVg01pSEuEGvGh3HEdBU4baCD7wQBwADmM/7f7A== dependencies: glob "^7.0.0" interpret "^1.0.0" @@ -7353,6 +8050,11 @@ simple-swizzle@^0.2.2: dependencies: is-arrayish "^0.3.1" +skip-regex@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/skip-regex/-/skip-regex-1.0.2.tgz#ac655d77e7c771ac2b9f37585fea37bff56ad65b" + integrity sha512-pEjMUbwJ5Pl/6Vn6FsamXHXItJXSRftcibixDmNCWbWhic0hzHrwkMZo0IZ7fMRH9KxcWDFSkzhccB4285PutA== + slash@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" @@ -7407,9 +8109,9 @@ socks-proxy-agent@^4.0.0: socks "~2.2.0" socks@~2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/socks/-/socks-2.2.1.tgz#68ad678b3642fbc5d99c64c165bc561eab0215f9" - integrity sha512-0GabKw7n9mI46vcNrVfs0o6XzWzjVa3h6GaSo2UPxtWAROXUWavfJWh1M4PR5tnE0dcnQXZIDFP4yrAysLze/w== + version "2.2.2" + resolved "https://registry.yarnpkg.com/socks/-/socks-2.2.2.tgz#f061219fc2d4d332afb4af93e865c84d3fa26e2b" + integrity sha512-g6wjBnnMOZpE0ym6e0uHSddz9p3a+WsBaaYQaBaSCJYvrC4IXykQR9MNGjLQf38e9iIIhp3b1/Zk8YZI3KGJ0Q== dependencies: ip "^1.1.5" smart-buffer "^4.0.1" @@ -7428,6 +8130,11 @@ sort-keys@^2.0.0: dependencies: is-plain-obj "^1.0.0" +source-list-map@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" + integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== + source-map-resolve@^0.5.0: version "0.5.2" resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" @@ -7462,6 +8169,11 @@ 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: + version "1.4.4" + resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.4.tgz#c63ea927c029dd6bd9a2b7fa03b3fec02ad56e9f" + integrity sha512-CYAPYdBu34781kLHkaW3m6b/uUSyMOC2R61gcYMWooeuaGtjof86ZA/8T+qVPPt7np1085CR9hmMGrySwEc8Xg== + spawn-wrap@^1.4.2: version "1.4.2" resolved "https://registry.yarnpkg.com/spawn-wrap/-/spawn-wrap-1.4.2.tgz#cff58e73a8224617b6561abdc32586ea0c82248c" @@ -7475,9 +8187,9 @@ spawn-wrap@^1.4.2: which "^1.3.0" spdx-correct@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.0.2.tgz#19bb409e91b47b1ad54159243f7312a858db3c2e" - integrity sha512-q9hedtzyXHr5S0A1vEPoK/7l8NpfkFYTq6iCY+Pno2ZbdZR6WexZFtqeVGkGxW3TEJMN914Z55EnAGMmenlIQQ== + version "3.1.0" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4" + integrity sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q== dependencies: spdx-expression-parse "^3.0.0" spdx-license-ids "^3.0.0" @@ -7496,9 +8208,9 @@ spdx-expression-parse@^3.0.0: spdx-license-ids "^3.0.0" spdx-license-ids@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.1.tgz#e2a303236cac54b04031fa7a5a79c7e701df852f" - integrity sha512-TfOfPcYGBB5sDuPn3deByxPhmfegAhpDYKSOXZQN81Oyrrif8ZCodOLzK3AesELnCx03kikhyDwh0pfvvQvF8w== + version "3.0.3" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.3.tgz#81c0ce8f21474756148bbb5f3bfc0f36bf15d76e" + integrity sha512-uBIcIl3Ih6Phe3XHK1NqboJLdGfwr1UN3k6wSD1dZpmPsIkb8AGNbZYJ1fOBk834+Gxy8rpfDxrS6XLEMZMY2g== split-string@^3.0.1, split-string@^3.0.2: version "3.1.0" @@ -7527,9 +8239,9 @@ sprintf-js@~1.0.2: integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= sshpk@^1.7.0: - version "1.15.1" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.15.1.tgz#b79a089a732e346c6e0714830f36285cd38191a2" - integrity sha512-mSdgNUaidk+dRU5MhYtN9zebdzF2iG0cNPWy8HG+W8y+fT1JnSkh0fzzpjOa0L7P8i1Rscz38t0h4gPcKz43xA== + 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== dependencies: asn1 "~0.2.3" assert-plus "^1.0.0" @@ -7652,7 +8364,14 @@ string-width@^1.0.1: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" -string_decoder@^1.0.0, string_decoder@~1.1.1: +string_decoder@^1.0.0, string_decoder@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.2.0.tgz#fe86e738b19544afe70469243b2a1ee9240eae8d" + integrity sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w== + dependencies: + safe-buffer "~5.1.0" + +string_decoder@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== @@ -7678,6 +8397,13 @@ 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-bom@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" @@ -7713,11 +8439,10 @@ strip-json-comments@~2.0.1: integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= strong-log-transformer@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strong-log-transformer/-/strong-log-transformer-2.0.0.tgz#fa6d8e0a9e62b3c168c3cad5ae5d00dc97ba26cc" - integrity sha512-FQmNqAXJgOX8ygOcvPLlGWBNT41mvNJ9ALoYf0GTwVt9t30mGTqpmp/oJx5gLcu52DXK10kS7dVWhx8aPXDTlg== + version "2.1.0" + resolved "https://registry.yarnpkg.com/strong-log-transformer/-/strong-log-transformer-2.1.0.tgz#0f5ed78d325e0421ac6f90f7f10e691d6ae3ae10" + integrity sha512-B3Hgul+z0L9a236FAUC9iZsL+nVHgoCJnqCbN588DjYxvGXaXaaFbfmQ/JhvKjZwsOukuR72XbHv71Qkug0HxA== dependencies: - byline "^5.0.0" duplexer "^0.1.1" minimist "^1.2.0" through "^2.3.4" @@ -7790,6 +8515,11 @@ svgo@^1.0.0, svgo@^1.0.5: unquote "~1.1.1" util.promisify "~1.0.0" +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" @@ -7799,20 +8529,7 @@ tar@^2.0.0: fstream "^1.0.2" inherits "2" -tar@^4: - version "4.4.6" - resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.6.tgz#63110f09c00b4e60ac8bcfe1bf3c8660235fbc9b" - integrity sha512-tMkTnh9EdzxyfW+6GK6fCahagXsnYk6kE6S9Gr9pjVdys769+laCTbodXDhPAjzVtEBazRgP0gYqOjnk9dQzLg== - dependencies: - chownr "^1.0.1" - fs-minipass "^1.2.5" - minipass "^2.3.3" - minizlib "^1.1.0" - mkdirp "^0.5.0" - safe-buffer "^5.1.2" - yallist "^3.0.2" - -tar@^4.4.6: +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== @@ -7842,19 +8559,24 @@ temp-write@^3.4.0: temp-dir "^1.0.0" uuid "^3.0.1" -terser@^3.11.0: - version "3.11.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-3.11.0.tgz#60782893e1f4d6788acc696351f40636d0e37af0" - integrity sha512-5iLMdhEPIq3zFWskpmbzmKwMQixKmTYwY3Ox9pjtSklBLnHiuQ0GKJLhL1HSYtyffHM3/lDIFBnb82m9D7ewwQ== +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== dependencies: - commander "~2.17.1" - source-map "~0.6.1" - source-map-support "~0.5.6" + cacache "^11.0.2" + find-cache-dir "^2.0.0" + schema-utils "^1.0.0" + serialize-javascript "^1.4.0" + source-map "^0.6.1" + terser "^3.8.1" + webpack-sources "^1.1.0" + worker-farm "^1.5.2" -terser@^3.7.3, terser@^3.8.1: - version "3.10.1" - resolved "https://registry.yarnpkg.com/terser/-/terser-3.10.1.tgz#59c8cf87262d59e018ded4df30f834b602b1e232" - integrity sha512-GE0ShECt1/dZUZt9Kyr/IC6xXG46pTbm1C1WfzQbbnRB5LhdJlF8p5NBZ38RjspD7hEM9O5ud8aIcOFY6evl4A== +terser@^3.14.1, 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== dependencies: commander "~2.17.1" source-map "~0.6.1" @@ -7876,11 +8598,11 @@ text-extensions@^1.0.0: integrity sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ== through2@^2.0.0, through2@^2.0.2, through2@~2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be" - integrity sha1-AARWmzfHx0ujnEPzzteNGtlBQL4= + version "2.0.5" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" + integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== dependencies: - readable-stream "^2.1.5" + readable-stream "~2.3.6" xtend "~4.0.1" through@2, "through@>=2.2.7 <3", through@^2.3.4, through@^2.3.6: @@ -7952,16 +8674,6 @@ to-regex@^3.0.1, to-regex@^3.0.2: regex-not "^1.0.2" safe-regex "^1.1.0" -toml@^2.3.3: - version "2.3.3" - resolved "https://registry.yarnpkg.com/toml/-/toml-2.3.3.tgz#8d683d729577cb286231dfc7a8affe58d31728fb" - integrity sha512-O7L5hhSQHxuufWUdcTRPfuTh3phKfAZ/dqfxZFoxPCj2RYmpaSGLEIs016FCXItQwNr08yefUB5TSjzRYnajTA== - -tomlify-j0.4@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/tomlify-j0.4/-/tomlify-j0.4-3.0.0.tgz#99414d45268c3a3b8bf38be82145b7bba34b7473" - integrity sha512-2Ulkc8T7mXJ2l0W476YC/A209PR38Nw8PuaCNtk9uI3t1zzFdGQeWYGQvmj2PZkVvRC/Yoi4xQKMRnWc/N29tQ== - tough-cookie@~2.4.3: version "2.4.3" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781" @@ -7997,15 +8709,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.3.3: + version "5.3.3" + resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-5.3.3.tgz#8b4af042e773132d86b3c99ef0acf3b4d325f473" + integrity sha512-KwF1SplmOJepnoZ4eRIloH/zXL195F51skt7reEsS6jvDqzgc/YSbz9b8E07GxIUwLXdcD4ssrJu6v8CwaTafA== + dependencies: + chalk "^2.3.0" + enhanced-resolve "^4.0.0" + loader-utils "^1.0.2" + micromatch "^3.1.4" + semver "^5.0.1" + 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== -tslint@^5.11.0: - version "5.11.0" - resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.11.0.tgz#98f30c02eae3cde7006201e4c33cb08b48581eed" - integrity sha1-mPMMAurjzecAYgHkwzywi0hYHu0= +tslint@^5.12.0: + version "5.12.0" + resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.12.0.tgz#47f2dba291ed3d580752d109866fb640768fca36" + integrity sha512-CKEcH1MHUBhoV43SA/Jmy1l24HJJgI0eyLbBNSRyFlsQvb9v6Zdq+Nz2vEOH00nC5SUx4SneJ59PZUS/ARcokQ== dependencies: babel-code-frame "^6.22.0" builtin-modules "^1.1.1" @@ -8061,10 +8784,10 @@ typedoc-default-themes@^0.5.0: resolved "https://registry.yarnpkg.com/typedoc-default-themes/-/typedoc-default-themes-0.5.0.tgz#6dc2433e78ed8bea8e887a3acde2f31785bd6227" integrity sha1-bcJDPnjti+qOiHo6zeLzF4W9Yic= -typedoc@^0.13.0: - version "0.13.0" - resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.13.0.tgz#9efdf352bd54873955cd161bd4b75f24a8c59dde" - integrity sha512-jQWtvPcV+0fiLZAXFEe70v5gqjDO6pJYJz4mlTtmGJeW2KRoIU/BEfktma6Uj8Xii7UakuZjbxFewl3UYOkU/w== +typedoc@^0.14.0: + version "0.14.0" + resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.14.0.tgz#f7de2f3f1109b92eeafd6cbff269e28a86c8079e" + integrity sha512-9DOYWO6O02YGZfbNOrELtmpQF4Eba/6AfNQNt46iRuIokoEq1Axdz9Ae/XjgdoXsM2ShGlDZsAO36BwRVz/Nmw== dependencies: "@types/fs-extra" "^5.0.3" "@types/handlebars" "^4.0.38" @@ -8075,21 +8798,16 @@ typedoc@^0.13.0: "@types/shelljs" "^0.8.0" fs-extra "^7.0.0" handlebars "^4.0.6" - highlight.js "^9.0.0" + highlight.js "9.12.0" lodash "^4.17.10" marked "^0.4.0" minimatch "^3.0.0" progress "^2.0.0" shelljs "^0.8.2" typedoc-default-themes "^0.5.0" - typescript "3.1.x" - -typescript@3.1.x: - version "3.1.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.1.3.tgz#01b70247a6d3c2467f70c45795ef5ea18ce191d5" - integrity sha512-+81MUSyX+BaSo+u2RbozuQk/UWx6hfG0a5gHu4ANEM4sU96XbuIyAB+rWBW1u70c6a5QuZfuYICn3s2UjuHUpA== + typescript "3.2.x" -typescript@^3.2.2: +typescript@3.2.x, typescript@^3.2.2: version "3.2.2" resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.2.2.tgz#fe8101c46aa123f8353523ebdcf5730c2ae493e5" integrity sha512-VCj5UiSyHBjwfYacmDuc/NOk4QQixbE+Wn7MFJuS0nRuPQbof132Pw4u53dm264O8LPc2MVsc7RJNml5szurkg== @@ -8163,7 +8881,7 @@ uniqs@^2.0.0: resolved "https://registry.yarnpkg.com/uniqs/-/uniqs-2.0.0.tgz#ffede4b36b25290696e6e165d4a59edb998e6b02" integrity sha1-/+3ks2slKQaW5uFl1KWe25mOawI= -unique-filename@^1.1.0, unique-filename@^1.1.1: +unique-filename@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230" integrity sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ== @@ -8200,6 +8918,13 @@ upath@^1.0.5: resolved "https://registry.yarnpkg.com/upath/-/upath-1.1.0.tgz#35256597e46a581db4793d0ce47fa9aebfc9fabd" integrity sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw== +uri-js@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" + integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== + dependencies: + punycode "^2.1.0" + urix@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" @@ -8218,7 +8943,7 @@ use@^3.1.0: resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== -util-deprecate@~1.0.1: +util-deprecate@^1.0.1, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= @@ -8250,7 +8975,7 @@ uuid@^3.0.1, uuid@^3.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== -v8-compile-cache@^2.0.0: +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== @@ -8296,6 +9021,15 @@ vm-browserify@0.0.4: dependencies: indexof "0.0.1" +watchpack@^1.5.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.6.0.tgz#4bc12c2ebe8aa277a71f1d3f14d685c7b446cd00" + integrity sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA== + dependencies: + chokidar "^2.0.2" + graceful-fs "^4.1.2" + neo-async "^2.5.0" + wcwidth@^1.0.0, wcwidth@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" @@ -8308,6 +9042,63 @@ webidl-conversions@^4.0.2: resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg== +webpack-cli@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.2.1.tgz#779c696c82482491f0803907508db2e276ed3b61" + integrity sha512-jeJveHwz/vwpJ3B8bxEL5a/rVKIpRNJDsKggfKnxuYeohNDW4Y/wB9N/XHJA093qZyS0r6mYL+/crLsIol4WKA== + dependencies: + chalk "^2.4.1" + cross-spawn "^6.0.5" + enhanced-resolve "^4.1.0" + findup-sync "^2.0.0" + global-modules "^1.0.0" + global-modules-path "^2.3.0" + import-local "^2.0.0" + interpret "^1.1.0" + lightercollective "^0.1.0" + loader-utils "^1.1.0" + supports-color "^5.5.0" + v8-compile-cache "^2.0.2" + yargs "^12.0.4" + +webpack-sources@^1.1.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== + dependencies: + source-list-map "^2.0.0" + source-map "~0.6.1" + +webpack@^4.28.1: + version "4.28.1" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.28.1.tgz#d0e2856e75d1224b170bf16c30b6ca9b75f0d958" + integrity sha512-qAS7BFyS5iuOZzGJxyDXmEI289h7tVNtJ5XMxf6Tz55J2riOyH42uaEsWF0F32TRaI+54SmI6qRgHM3GzsZ+sQ== + dependencies: + "@webassemblyjs/ast" "1.7.11" + "@webassemblyjs/helper-module-context" "1.7.11" + "@webassemblyjs/wasm-edit" "1.7.11" + "@webassemblyjs/wasm-parser" "1.7.11" + acorn "^5.6.2" + acorn-dynamic-import "^3.0.0" + ajv "^6.1.0" + ajv-keywords "^3.1.0" + chrome-trace-event "^1.0.0" + enhanced-resolve "^4.1.0" + eslint-scope "^4.0.0" + json-parse-better-errors "^1.0.2" + loader-runner "^2.3.0" + loader-utils "^1.1.0" + memory-fs "~0.4.1" + micromatch "^3.1.8" + mkdirp "~0.5.0" + neo-async "^2.5.0" + node-libs-browser "^2.0.0" + schema-utils "^0.4.4" + tapable "^1.1.0" + terser-webpack-plugin "^1.1.0" + watchpack "^1.5.0" + webpack-sources "^1.3.0" + whatwg-url@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-7.0.0.tgz#fde926fa54a599f3adf82dff25a9f7be02dc6edd" @@ -8327,7 +9118,7 @@ which-module@^2.0.0: resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= -which@1, which@^1.2.9, which@^1.3.0, which@^1.3.1: +which@1, which@^1.2.14, which@^1.2.9, which@^1.3.0, which@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== @@ -8351,6 +9142,13 @@ 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== + dependencies: + errno "~0.1.7" + wrap-ansi@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" @@ -8400,11 +9198,6 @@ ws@^5.1.1: dependencies: async-limiter "~1.0.0" -xregexp@4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-4.0.0.tgz#e698189de49dd2a18cc5687b05e17c8e43943020" - integrity sha512-PHyM+sQouu7xspQQwELlGwwd05mXUFqwFYfqPO0cC7x4fxyHnnuetmQr6CjJiafIDoH4MogHb9dOoJzR/Y4rFg== - xtend@^4.0.0, xtend@~4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" @@ -8426,16 +9219,17 @@ yallist@^2.1.2: integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= yallist@^3.0.0, yallist@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.2.tgz#8452b4bb7e83c7c188d8041c1a837c773d6d8bb9" - integrity sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k= + 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@^10.1.0: - version "10.1.0" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8" - integrity sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ== +yargs-parser@^11.1.1: + version "11.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-11.1.1.tgz#879a0865973bca9f6bab5cbdf3b1c67ec7d3bcf4" + integrity sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ== dependencies: - camelcase "^4.1.0" + camelcase "^5.0.0" + decamelize "^1.2.0" yargs-parser@^9.0.2: version "9.0.2" @@ -8462,13 +9256,13 @@ yargs@11.1.0: y18n "^3.2.1" yargs-parser "^9.0.2" -yargs@^12.0.1: - version "12.0.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.2.tgz#fe58234369392af33ecbef53819171eff0f5aadc" - integrity sha512-e7SkEx6N6SIZ5c5H22RTZae61qtn3PYUE8JYbBFlK9sYmh3DMQ6E5ygtaG/2BW0JZi4WGgTR2IV5ChqlqrDGVQ== +yargs@^12.0.1, yargs@^12.0.4: + version "12.0.5" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.5.tgz#05f5997b609647b64f66b81e3b4b10a368e7ad13" + integrity sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw== dependencies: cliui "^4.0.0" - decamelize "^2.0.0" + decamelize "^1.2.0" find-up "^3.0.0" get-caller-file "^1.0.1" os-locale "^3.0.0" @@ -8478,4 +9272,4 @@ yargs@^12.0.1: string-width "^2.0.0" which-module "^2.0.0" y18n "^3.2.1 || ^4.0.0" - yargs-parser "^10.1.0" + yargs-parser "^11.1.1"

+// This is a test.