From 2348d056cbd91a0ef02f5c48a5608c21718b6b58 Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Sun, 1 May 2022 15:40:54 +0200 Subject: [PATCH 1/7] test jsdoc --- .gitignore | 1 + api.md | 140 +++++ jsdoc.config.json | 6 + package-lock.json | 1128 +++++++++++++++++++++++++++++++++++++ package.json | 6 +- packages/core/pattern.mjs | 76 ++- 6 files changed, 1343 insertions(+), 14 deletions(-) create mode 100644 api.md create mode 100644 jsdoc.config.json diff --git a/.gitignore b/.gitignore index 8631e12d..9a861675 100644 --- a/.gitignore +++ b/.gitignore @@ -27,4 +27,5 @@ node_modules/ repl-parcel mytunes.ts doc +out .parcel-cache \ No newline at end of file diff --git a/api.md b/api.md new file mode 100644 index 00000000..5bda9d74 --- /dev/null +++ b/api.md @@ -0,0 +1,140 @@ +## Classes + +
+
Pattern
+

Class representing a pattern.

+
+ +## Functions + +
+
pure(value)Pattern
+

A discrete value that repeats once per cycle:

+
stack(...items)Pattern
+

The given items are played at the same time at the same length:

+
slowcat(...items)Pattern
+

Concatenation: combines a list of patterns, switching between them successively, one per cycle:

+

synonyms: [cat](#cat)

+
slowcatPrime(...items)Pattern
+

Concatenation: combines a list of patterns, switching between them successively, one per cycle. Unlike slowcat, this version will skip cycles.

+
fastcat(...items)Pattern
+

Concatenation: as with [slowcat](#slowcat), but squashes a cycle from each pattern into one cycle

+

Synonyms: [seq](#seq), [sequence](#sequence)

+
cat()
+

See [slowcat](#slowcat)

+
timeCat(...items)Pattern
+

Like [fastcat](#fastcat), but where each step has a temporal weight:

+
sequence()
+

See [fastcat](#fastcat)

+
seq()
+

See [fastcat](#fastcat)

+
+ + + +## pure(value) ⇒ [Pattern](#Pattern) +

A discrete value that repeats once per cycle:

+ +**Kind**: global function + +| Param | Type | Description | +| --- | --- | --- | +| value | any |

The value to repeat

| + +**Example** +```js +pure('e4') +``` + + +## stack(...items) ⇒ [Pattern](#Pattern) +

The given items are played at the same time at the same length:

+ +**Kind**: global function + +| Param | Type | Description | +| --- | --- | --- | +| ...items | any |

The items to stack

| + +**Example** +```js +stack(g3, b3, [e4, d4]) +``` + + +## slowcat(...items) ⇒ [Pattern](#Pattern) +

Concatenation: combines a list of patterns, switching between them successively, one per cycle:

+

synonyms: [cat](#cat)

+ +**Kind**: global function + +| Param | Type | Description | +| --- | --- | --- | +| ...items | any |

The items to concatenate

| + +**Example** +```js +slowcat(e5, b4, [d5, c5]) +``` + + +## slowcatPrime(...items) ⇒ [Pattern](#Pattern) +

Concatenation: combines a list of patterns, switching between them successively, one per cycle. Unlike slowcat, this version will skip cycles.

+ +**Kind**: global function + +| Param | Type | Description | +| --- | --- | --- | +| ...items | any |

The items to concatenate

| + + + +## fastcat(...items) ⇒ [Pattern](#Pattern) +

Concatenation: as with [slowcat](#slowcat), but squashes a cycle from each pattern into one cycle

+

Synonyms: [seq](#seq), [sequence](#sequence)

+ +**Kind**: global function + +| Param | Type | Description | +| --- | --- | --- | +| ...items | any |

The items to concatenate

| + +**Example** +```js +fastcat(e5, b4, [d5, c5]) +sequence(e5, b4, [d5, c5]) +seq(e5, b4, [d5, c5]) +``` + + +## cat() +

See [slowcat](#slowcat)

+ +**Kind**: global function + + +## timeCat(...items) ⇒ [Pattern](#Pattern) +

Like [fastcat](#fastcat), but where each step has a temporal weight:

+ +**Kind**: global function + +| Param | Type | Description | +| --- | --- | --- | +| ...items | Array |

The items to concatenate

| + +**Example** +```js +timeCat([3,e3],[1, g3]) +``` + + +## sequence() +

See [fastcat](#fastcat)

+ +**Kind**: global function + + +## seq() +

See [fastcat](#fastcat)

+ +**Kind**: global function diff --git a/jsdoc.config.json b/jsdoc.config.json new file mode 100644 index 00000000..27be8275 --- /dev/null +++ b/jsdoc.config.json @@ -0,0 +1,6 @@ +{ + "source": { + "includePattern": ".+\\.(js(doc|x)?|mjs)$" + }, + "plugins": ["plugins/markdown"] +} diff --git a/package-lock.json b/package-lock.json index 718a01b0..678e7707 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,8 @@ ], "devDependencies": { "events": "^3.3.0", + "jsdoc": "^3.6.10", + "jsdoc-to-markdown": "^7.1.1", "lerna": "^4.0.0", "mocha": "^9.1.4" } @@ -2269,6 +2271,27 @@ "node": ">=6" } }, + "node_modules/ansi-escape-sequences": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-escape-sequences/-/ansi-escape-sequences-4.1.0.tgz", + "integrity": "sha512-dzW9kHxH011uBsidTXd14JXgzye/YLb2LzeKZ4bsgl/Knwx8AtbSFkkGxagdNOoh0DlqHCmfiEjWKBaqjOanVw==", + "dev": true, + "dependencies": { + "array-back": "^3.0.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/ansi-escape-sequences/node_modules/array-back": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", + "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/ansi-escapes": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", @@ -2342,6 +2365,15 @@ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, + "node_modules/array-back": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-6.2.2.tgz", + "integrity": "sha512-gUAZ7HPyb4SJczXAMUXMGAvI976JoK3qEx9v1FTmeYuJj0IBiaKttG1ydtGKdkfqWkIkouke7nG8ufGy77+Cvw==", + "dev": true, + "engines": { + "node": ">=12.17" + } + }, "node_modules/array-differ": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-3.0.0.tgz", @@ -2606,6 +2638,29 @@ "node": ">= 10" } }, + "node_modules/cache-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/cache-point/-/cache-point-2.0.0.tgz", + "integrity": "sha512-4gkeHlFpSKgm3vm2gJN5sPqfmijYRFYCQ6tv5cLw0xVmT6r1z1vd4FNnpuOREco3cBs1G709sZ72LdgddKvL5w==", + "dev": true, + "dependencies": { + "array-back": "^4.0.1", + "fs-then-native": "^2.0.0", + "mkdirp2": "^1.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cache-point/node_modules/array-back": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", + "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/call-bind": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", @@ -2912,6 +2967,19 @@ "node": ">=0.10.0" } }, + "node_modules/collect-all": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/collect-all/-/collect-all-1.0.4.tgz", + "integrity": "sha512-RKZhRwJtJEP5FWul+gkSMEnaK6H3AGPTTWOiRimCcs+rc/OmQE3Yhy1Q7A7KsdkG3ZXVdZq68Y6ONSdvkeEcKA==", + "dev": true, + "dependencies": { + "stream-connect": "^1.0.2", + "stream-via": "^1.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -2955,6 +3023,103 @@ "node": ">= 0.8" } }, + "node_modules/command-line-args": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.2.1.tgz", + "integrity": "sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg==", + "dev": true, + "dependencies": { + "array-back": "^3.1.0", + "find-replace": "^3.0.0", + "lodash.camelcase": "^4.3.0", + "typical": "^4.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/command-line-args/node_modules/array-back": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", + "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/command-line-args/node_modules/typical": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", + "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/command-line-tool": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/command-line-tool/-/command-line-tool-0.8.0.tgz", + "integrity": "sha512-Xw18HVx/QzQV3Sc5k1vy3kgtOeGmsKIqwtFFoyjI4bbcpSgnw2CWVULvtakyw4s6fhyAdI6soQQhXc2OzJy62g==", + "dev": true, + "dependencies": { + "ansi-escape-sequences": "^4.0.0", + "array-back": "^2.0.0", + "command-line-args": "^5.0.0", + "command-line-usage": "^4.1.0", + "typical": "^2.6.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/command-line-tool/node_modules/array-back": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", + "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", + "dev": true, + "dependencies": { + "typical": "^2.6.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/command-line-usage": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-4.1.0.tgz", + "integrity": "sha512-MxS8Ad995KpdAC0Jopo/ovGIroV/m0KHwzKfXxKag6FHOkGsH8/lv5yjgablcRxCJJC0oJeUMuO/gmaq+Wq46g==", + "dev": true, + "dependencies": { + "ansi-escape-sequences": "^4.0.0", + "array-back": "^2.0.0", + "table-layout": "^0.4.2", + "typical": "^2.6.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/command-line-usage/node_modules/array-back": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", + "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", + "dev": true, + "dependencies": { + "typical": "^2.6.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/common-sequence": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/common-sequence/-/common-sequence-2.0.2.tgz", + "integrity": "sha512-jAg09gkdkrDO9EWTdXfv80WWH3yeZl5oT69fGfedBNS9pXUKYInVJ1bJ+/ht2+Moeei48TmSbQDYMc8EOx9G0g==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/compare-func": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", @@ -3021,6 +3186,24 @@ "proto-list": "~1.2.1" } }, + "node_modules/config-master": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/config-master/-/config-master-3.1.0.tgz", + "integrity": "sha1-ZnZjWQUFooO/JqSE1oSJ10xUhdo=", + "dev": true, + "dependencies": { + "walk-back": "^2.0.1" + } + }, + "node_modules/config-master/node_modules/walk-back": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/walk-back/-/walk-back-2.0.1.tgz", + "integrity": "sha1-VU4qnYdPrEeoywBr9EwvDEmYoKQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", @@ -3330,6 +3513,15 @@ "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=", "dev": true }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, "node_modules/defaults": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", @@ -3430,6 +3622,29 @@ "gulp-jsdoc3": "^3.0.0" } }, + "node_modules/dmd": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/dmd/-/dmd-6.1.0.tgz", + "integrity": "sha512-0zQIJ873gay1scCTFZvHPWM9mVJBnaylB2NQDI8O9u8O32m00Jb6uxDKexZm8hjTRM7RiWe0FJ32pExHoXdwoQ==", + "dev": true, + "dependencies": { + "array-back": "^6.2.2", + "cache-point": "^2.0.0", + "common-sequence": "^2.0.2", + "file-set": "^4.0.2", + "handlebars": "^4.7.7", + "marked": "^4.0.12", + "object-get": "^2.1.1", + "reduce-flatten": "^3.0.1", + "reduce-unique": "^2.0.1", + "reduce-without": "^1.0.1", + "test-value": "^3.0.0", + "walk-back": "^5.1.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/dom-serializer": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", @@ -3823,6 +4038,28 @@ "node": ">=0.8.0" } }, + "node_modules/file-set": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/file-set/-/file-set-4.0.2.tgz", + "integrity": "sha512-fuxEgzk4L8waGXaAkd8cMr73Pm0FxOVkn8hztzUW7BAHhOGH90viQNXbiOsnecCWmfInqU6YmAMwxRMdKETceQ==", + "dev": true, + "dependencies": { + "array-back": "^5.0.0", + "glob": "^7.1.6" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/file-set/node_modules/array-back": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-5.0.0.tgz", + "integrity": "sha512-kgVWwJReZWmVuWOQKEOohXKJX+nD02JAZ54D1RRWlv8L0NebauKAaFxACKzB74RTclt1+WNz5KHaLRDAPZbDEw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -3844,6 +4081,27 @@ "node": ">=0.10.0" } }, + "node_modules/find-replace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", + "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==", + "dev": true, + "dependencies": { + "array-back": "^3.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/find-replace/node_modules/array-back": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", + "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -3931,6 +4189,15 @@ "node": ">= 8" } }, + "node_modules/fs-then-native": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fs-then-native/-/fs-then-native-2.0.0.tgz", + "integrity": "sha1-GaEk2U2QwiyOBF8ujdbr6jbUjGc=", + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -5161,6 +5428,64 @@ "node": ">=8.15.0" } }, + "node_modules/jsdoc-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/jsdoc-api/-/jsdoc-api-7.1.1.tgz", + "integrity": "sha512-0pkuPCzVXiqsDAsVrNFXCkHzlyNepBIDVtwwehry4RJAnZmXtlAz7rh8F9FRz53u3NeynGbex+bpYWwi8lE66A==", + "dev": true, + "dependencies": { + "array-back": "^6.2.2", + "cache-point": "^2.0.0", + "collect-all": "^1.0.4", + "file-set": "^4.0.2", + "fs-then-native": "^2.0.0", + "jsdoc": "^3.6.10", + "object-to-spawn-args": "^2.0.1", + "temp-path": "^1.0.0", + "walk-back": "^5.1.0" + }, + "engines": { + "node": ">=12.17" + } + }, + "node_modules/jsdoc-parse": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsdoc-parse/-/jsdoc-parse-6.1.0.tgz", + "integrity": "sha512-n/hDGQJa69IBun1yZAjqzV4gVR41+flZ3bIlm9fKvNe2Xjsd1/+zCo2+R9ls8LxtePgIWbpA1jU7xkB2lRdLLg==", + "dev": true, + "dependencies": { + "array-back": "^6.2.2", + "lodash.omit": "^4.5.0", + "lodash.pick": "^4.4.0", + "reduce-extract": "^1.0.0", + "sort-array": "^4.1.4", + "test-value": "^3.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/jsdoc-to-markdown": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/jsdoc-to-markdown/-/jsdoc-to-markdown-7.1.1.tgz", + "integrity": "sha512-CI86d63xAVNO+ENumWwmJ034lYe5iGU5GwjtTA11EuphP9tpnoi4hrKgR/J8uME0D+o4KUpVfwX1fjZhc8dEtg==", + "dev": true, + "dependencies": { + "array-back": "^6.2.2", + "command-line-tool": "^0.8.0", + "config-master": "^3.1.0", + "dmd": "^6.1.0", + "jsdoc-api": "^7.1.1", + "jsdoc-parse": "^6.1.0", + "walk-back": "^5.1.0" + }, + "bin": { + "jsdoc2md": "bin/cli.js" + }, + "engines": { + "node": ">=12.17" + } + }, "node_modules/jsdoc/node_modules/escape-string-regexp": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", @@ -5393,12 +5718,36 @@ "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", "dev": true }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=", + "dev": true + }, "node_modules/lodash.ismatch": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz", "integrity": "sha1-dWy1FQyjum8RCFp4hJZF8Yj4Xzc=", "dev": true }, + "node_modules/lodash.omit": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.omit/-/lodash.omit-4.5.0.tgz", + "integrity": "sha1-brGa5aHuHdnfC5aeZs4Lf6MLXmA=", + "dev": true + }, + "node_modules/lodash.padend": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.6.1.tgz", + "integrity": "sha1-U8y6BH0G4VjTEfRdpiX05J5vFm4=", + "dev": true + }, + "node_modules/lodash.pick": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", + "integrity": "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=", + "dev": true + }, "node_modules/lodash.template": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", @@ -5952,6 +6301,12 @@ "node": ">=10" } }, + "node_modules/mkdirp2": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/mkdirp2/-/mkdirp2-1.0.5.tgz", + "integrity": "sha512-xOE9xbICroUDmG1ye2h4bZ8WBie9EGmACaco8K8cx6RlkJJrxGIqjGqztAI+NMhexXBcdGbSEzI6N3EJPevxZw==", + "dev": true + }, "node_modules/mocha": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.2.2.tgz", @@ -6523,6 +6878,12 @@ "node": ">=0.10.0" } }, + "node_modules/object-get": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/object-get/-/object-get-2.1.1.tgz", + "integrity": "sha512-7n4IpLMzGGcLEMiQKsNR7vCe+N5E9LORFrtNUVy4sO3dj9a3HedZCxEL2T7QuLhcHN1NBuBsMOKaOsAYI9IIvg==", + "dev": true + }, "node_modules/object-inspect": { "version": "1.12.0", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", @@ -6541,6 +6902,15 @@ "node": ">= 0.4" } }, + "node_modules/object-to-spawn-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object-to-spawn-args/-/object-to-spawn-args-2.0.1.tgz", + "integrity": "sha512-6FuKFQ39cOID+BMZ3QaphcC8Y4cw6LXBLyIgPU+OhIYwviJamPAn+4mITapnSBQrejB+NNp+FMskhD8Cq+Ys3w==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/object.assign": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", @@ -7467,6 +7837,98 @@ "node": ">=8" } }, + "node_modules/reduce-extract": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/reduce-extract/-/reduce-extract-1.0.0.tgz", + "integrity": "sha1-Z/I4W+2mUGG19fQxJmLosIDKFSU=", + "dev": true, + "dependencies": { + "test-value": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/reduce-extract/node_modules/array-back": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", + "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", + "dev": true, + "dependencies": { + "typical": "^2.6.0" + }, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/reduce-extract/node_modules/test-value": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/test-value/-/test-value-1.1.0.tgz", + "integrity": "sha1-oJE29y7AQ9J8iTcHwrFZv6196T8=", + "dev": true, + "dependencies": { + "array-back": "^1.0.2", + "typical": "^2.4.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/reduce-flatten": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-3.0.1.tgz", + "integrity": "sha512-bYo+97BmUUOzg09XwfkwALt4PQH1M5L0wzKerBt6WLm3Fhdd43mMS89HiT1B9pJIqko/6lWx3OnV4J9f2Kqp5Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/reduce-unique": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/reduce-unique/-/reduce-unique-2.0.1.tgz", + "integrity": "sha512-x4jH/8L1eyZGR785WY+ePtyMNhycl1N2XOLxhCbzZFaqF4AXjLzqSxa2UHgJ2ZVR/HHyPOvl1L7xRnW8ye5MdA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/reduce-without": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/reduce-without/-/reduce-without-1.0.1.tgz", + "integrity": "sha1-aK0OrRGFXJo31OglbBW7+Hly/Iw=", + "dev": true, + "dependencies": { + "test-value": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/reduce-without/node_modules/array-back": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", + "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", + "dev": true, + "dependencies": { + "typical": "^2.6.0" + }, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/reduce-without/node_modules/test-value": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/test-value/-/test-value-2.1.0.tgz", + "integrity": "sha1-Edpv9nDzRxpztiXKTz/c97t0gpE=", + "dev": true, + "dependencies": { + "array-back": "^1.0.3", + "typical": "^2.6.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/regenerator-runtime": { "version": "0.13.9", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", @@ -7957,6 +8419,37 @@ "node": ">= 10" } }, + "node_modules/sort-array": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/sort-array/-/sort-array-4.1.5.tgz", + "integrity": "sha512-Ya4peoS1fgFN42RN1REk2FgdNOeLIEMKFGJvs7VTP3OklF8+kl2SkpVliZ4tk/PurWsrWRsdNdU+tgyOBkB9sA==", + "dev": true, + "dependencies": { + "array-back": "^5.0.0", + "typical": "^6.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/sort-array/node_modules/array-back": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-5.0.0.tgz", + "integrity": "sha512-kgVWwJReZWmVuWOQKEOohXKJX+nD02JAZ54D1RRWlv8L0NebauKAaFxACKzB74RTclt1+WNz5KHaLRDAPZbDEw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/sort-array/node_modules/typical": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/typical/-/typical-6.0.1.tgz", + "integrity": "sha512-+g3NEp7fJLe9DPa1TArHm9QAA7YciZmWnfAqEaFrBihQ7epOv9i99rjtgb6Iz0wh3WuQDjsCTDfgRoGnmHN81A==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/sort-keys": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-4.2.0.tgz", @@ -8104,6 +8597,39 @@ "tslib": "^2.3.1" } }, + "node_modules/stream-connect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stream-connect/-/stream-connect-1.0.2.tgz", + "integrity": "sha1-GLyB8u2zW4tdmoAJIAqYUxRCipc=", + "dev": true, + "dependencies": { + "array-back": "^1.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stream-connect/node_modules/array-back": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", + "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", + "dev": true, + "dependencies": { + "typical": "^2.6.0" + }, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/stream-via": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/stream-via/-/stream-via-1.0.4.tgz", + "integrity": "sha512-DBp0lSvX5G9KGRDTkR/R+a29H+Wk2xItOF+MpZLLNDWbEV9tGPnqLPxHEYjmiz8xGtJHRIqmI+hCjmNzqoA4nQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/strict-uri-encode": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", @@ -8286,6 +8812,34 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/table-layout": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-0.4.5.tgz", + "integrity": "sha512-zTvf0mcggrGeTe/2jJ6ECkJHAQPIYEwDoqsiqBjI24mvRmQbInK5jq33fyypaCBxX08hMkfmdOqj6haT33EqWw==", + "dev": true, + "dependencies": { + "array-back": "^2.0.0", + "deep-extend": "~0.6.0", + "lodash.padend": "^4.6.1", + "typical": "^2.6.1", + "wordwrapjs": "^3.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/table-layout/node_modules/array-back": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", + "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", + "dev": true, + "dependencies": { + "typical": "^2.6.1" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/taffydb": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz", @@ -8317,6 +8871,12 @@ "node": ">=4" } }, + "node_modules/temp-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/temp-path/-/temp-path-1.0.0.tgz", + "integrity": "sha1-JLFUOXOrRCiW2a02fdnL2/r+kYs=", + "dev": true + }, "node_modules/temp-write": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/temp-write/-/temp-write-4.0.0.tgz", @@ -8333,6 +8893,31 @@ "node": ">=8" } }, + "node_modules/test-value": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/test-value/-/test-value-3.0.0.tgz", + "integrity": "sha512-sVACdAWcZkSU9x7AOmJo5TqE+GyNJknHaHsMrR6ZnhjVlVN9Yx6FjHrsKZ3BjIpPCT68zYesPWkakrNupwfOTQ==", + "dev": true, + "dependencies": { + "array-back": "^2.0.0", + "typical": "^2.6.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/test-value/node_modules/array-back": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", + "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", + "dev": true, + "dependencies": { + "typical": "^2.6.1" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/text-extensions": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz", @@ -8496,6 +9081,12 @@ "is-typedarray": "^1.0.0" } }, + "node_modules/typical": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/typical/-/typical-2.6.1.tgz", + "integrity": "sha1-XAgOXWYcu+OCWdLnCjxyU+hziB0=", + "dev": true + }, "node_modules/uc.micro": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", @@ -8701,6 +9292,15 @@ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true }, + "node_modules/walk-back": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/walk-back/-/walk-back-5.1.0.tgz", + "integrity": "sha512-Uhxps5yZcVNbLEAnb+xaEEMdgTXl9qAQDzKYejG2AZ7qPwRQ81lozY9ECDbjLPNWm7YsO1IK5rsP1KoQzXAcGA==", + "dev": true, + "engines": { + "node": ">=12.17" + } + }, "node_modules/wcwidth": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", @@ -8787,6 +9387,28 @@ "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", "dev": true }, + "node_modules/wordwrapjs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-3.0.0.tgz", + "integrity": "sha512-mO8XtqyPvykVCsrwj5MlOVWvSnCdT+C+QVbm6blradR7JExAhbkZ7hZ9A+9NUtwzSqrlUo9a67ws0EiILrvRpw==", + "dev": true, + "dependencies": { + "reduce-flatten": "^1.0.1", + "typical": "^2.6.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/wordwrapjs/node_modules/reduce-flatten": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-1.0.1.tgz", + "integrity": "sha1-JYx479FT3fk8tWEjf2EYTzaW4yc=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/workerpool": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz", @@ -11176,6 +11798,23 @@ "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==" }, + "ansi-escape-sequences": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-escape-sequences/-/ansi-escape-sequences-4.1.0.tgz", + "integrity": "sha512-dzW9kHxH011uBsidTXd14JXgzye/YLb2LzeKZ4bsgl/Knwx8AtbSFkkGxagdNOoh0DlqHCmfiEjWKBaqjOanVw==", + "dev": true, + "requires": { + "array-back": "^3.0.1" + }, + "dependencies": { + "array-back": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", + "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", + "dev": true + } + } + }, "ansi-escapes": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", @@ -11231,6 +11870,12 @@ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, + "array-back": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-6.2.2.tgz", + "integrity": "sha512-gUAZ7HPyb4SJczXAMUXMGAvI976JoK3qEx9v1FTmeYuJj0IBiaKttG1ydtGKdkfqWkIkouke7nG8ufGy77+Cvw==", + "dev": true + }, "array-differ": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-3.0.0.tgz", @@ -11440,6 +12085,25 @@ "unique-filename": "^1.1.1" } }, + "cache-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/cache-point/-/cache-point-2.0.0.tgz", + "integrity": "sha512-4gkeHlFpSKgm3vm2gJN5sPqfmijYRFYCQ6tv5cLw0xVmT6r1z1vd4FNnpuOREco3cBs1G709sZ72LdgddKvL5w==", + "dev": true, + "requires": { + "array-back": "^4.0.1", + "fs-then-native": "^2.0.0", + "mkdirp2": "^1.0.4" + }, + "dependencies": { + "array-back": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", + "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", + "dev": true + } + } + }, "call-bind": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", @@ -11664,6 +12328,16 @@ "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", "dev": true }, + "collect-all": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/collect-all/-/collect-all-1.0.4.tgz", + "integrity": "sha512-RKZhRwJtJEP5FWul+gkSMEnaK6H3AGPTTWOiRimCcs+rc/OmQE3Yhy1Q7A7KsdkG3ZXVdZq68Y6ONSdvkeEcKA==", + "dev": true, + "requires": { + "stream-connect": "^1.0.2", + "stream-via": "^1.0.4" + } + }, "color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -11698,6 +12372,85 @@ "delayed-stream": "~1.0.0" } }, + "command-line-args": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.2.1.tgz", + "integrity": "sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg==", + "dev": true, + "requires": { + "array-back": "^3.1.0", + "find-replace": "^3.0.0", + "lodash.camelcase": "^4.3.0", + "typical": "^4.0.0" + }, + "dependencies": { + "array-back": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", + "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", + "dev": true + }, + "typical": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", + "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==", + "dev": true + } + } + }, + "command-line-tool": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/command-line-tool/-/command-line-tool-0.8.0.tgz", + "integrity": "sha512-Xw18HVx/QzQV3Sc5k1vy3kgtOeGmsKIqwtFFoyjI4bbcpSgnw2CWVULvtakyw4s6fhyAdI6soQQhXc2OzJy62g==", + "dev": true, + "requires": { + "ansi-escape-sequences": "^4.0.0", + "array-back": "^2.0.0", + "command-line-args": "^5.0.0", + "command-line-usage": "^4.1.0", + "typical": "^2.6.1" + }, + "dependencies": { + "array-back": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", + "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", + "dev": true, + "requires": { + "typical": "^2.6.1" + } + } + } + }, + "command-line-usage": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-4.1.0.tgz", + "integrity": "sha512-MxS8Ad995KpdAC0Jopo/ovGIroV/m0KHwzKfXxKag6FHOkGsH8/lv5yjgablcRxCJJC0oJeUMuO/gmaq+Wq46g==", + "dev": true, + "requires": { + "ansi-escape-sequences": "^4.0.0", + "array-back": "^2.0.0", + "table-layout": "^0.4.2", + "typical": "^2.6.1" + }, + "dependencies": { + "array-back": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", + "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", + "dev": true, + "requires": { + "typical": "^2.6.1" + } + } + } + }, + "common-sequence": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/common-sequence/-/common-sequence-2.0.2.tgz", + "integrity": "sha512-jAg09gkdkrDO9EWTdXfv80WWH3yeZl5oT69fGfedBNS9pXUKYInVJ1bJ+/ht2+Moeei48TmSbQDYMc8EOx9G0g==", + "dev": true + }, "compare-func": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", @@ -11759,6 +12512,23 @@ "proto-list": "~1.2.1" } }, + "config-master": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/config-master/-/config-master-3.1.0.tgz", + "integrity": "sha1-ZnZjWQUFooO/JqSE1oSJ10xUhdo=", + "dev": true, + "requires": { + "walk-back": "^2.0.1" + }, + "dependencies": { + "walk-back": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/walk-back/-/walk-back-2.0.1.tgz", + "integrity": "sha1-VU4qnYdPrEeoywBr9EwvDEmYoKQ=", + "dev": true + } + } + }, "console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", @@ -11999,6 +12769,12 @@ "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=", "dev": true }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true + }, "defaults": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", @@ -12081,6 +12857,26 @@ "gulp-jsdoc3": "^3.0.0" } }, + "dmd": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/dmd/-/dmd-6.1.0.tgz", + "integrity": "sha512-0zQIJ873gay1scCTFZvHPWM9mVJBnaylB2NQDI8O9u8O32m00Jb6uxDKexZm8hjTRM7RiWe0FJ32pExHoXdwoQ==", + "dev": true, + "requires": { + "array-back": "^6.2.2", + "cache-point": "^2.0.0", + "common-sequence": "^2.0.2", + "file-set": "^4.0.2", + "handlebars": "^4.7.7", + "marked": "^4.0.12", + "object-get": "^2.1.1", + "reduce-flatten": "^3.0.1", + "reduce-unique": "^2.0.1", + "reduce-without": "^1.0.1", + "test-value": "^3.0.0", + "walk-back": "^5.1.0" + } + }, "dom-serializer": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", @@ -12380,6 +13176,24 @@ } } }, + "file-set": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/file-set/-/file-set-4.0.2.tgz", + "integrity": "sha512-fuxEgzk4L8waGXaAkd8cMr73Pm0FxOVkn8hztzUW7BAHhOGH90viQNXbiOsnecCWmfInqU6YmAMwxRMdKETceQ==", + "dev": true, + "requires": { + "array-back": "^5.0.0", + "glob": "^7.1.6" + }, + "dependencies": { + "array-back": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-5.0.0.tgz", + "integrity": "sha512-kgVWwJReZWmVuWOQKEOohXKJX+nD02JAZ54D1RRWlv8L0NebauKAaFxACKzB74RTclt1+WNz5KHaLRDAPZbDEw==", + "dev": true + } + } + }, "fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -12395,6 +13209,23 @@ "integrity": "sha1-mzERErxsYSehbgFsbF1/GeCAXFs=", "dev": true }, + "find-replace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", + "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==", + "dev": true, + "requires": { + "array-back": "^3.0.1" + }, + "dependencies": { + "array-back": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", + "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", + "dev": true + } + } + }, "find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -12454,6 +13285,12 @@ "minipass": "^3.0.0" } }, + "fs-then-native": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fs-then-native/-/fs-then-native-2.0.0.tgz", + "integrity": "sha1-GaEk2U2QwiyOBF8ujdbr6jbUjGc=", + "dev": true + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -13390,6 +14227,52 @@ } } }, + "jsdoc-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/jsdoc-api/-/jsdoc-api-7.1.1.tgz", + "integrity": "sha512-0pkuPCzVXiqsDAsVrNFXCkHzlyNepBIDVtwwehry4RJAnZmXtlAz7rh8F9FRz53u3NeynGbex+bpYWwi8lE66A==", + "dev": true, + "requires": { + "array-back": "^6.2.2", + "cache-point": "^2.0.0", + "collect-all": "^1.0.4", + "file-set": "^4.0.2", + "fs-then-native": "^2.0.0", + "jsdoc": "^3.6.10", + "object-to-spawn-args": "^2.0.1", + "temp-path": "^1.0.0", + "walk-back": "^5.1.0" + } + }, + "jsdoc-parse": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsdoc-parse/-/jsdoc-parse-6.1.0.tgz", + "integrity": "sha512-n/hDGQJa69IBun1yZAjqzV4gVR41+flZ3bIlm9fKvNe2Xjsd1/+zCo2+R9ls8LxtePgIWbpA1jU7xkB2lRdLLg==", + "dev": true, + "requires": { + "array-back": "^6.2.2", + "lodash.omit": "^4.5.0", + "lodash.pick": "^4.4.0", + "reduce-extract": "^1.0.0", + "sort-array": "^4.1.4", + "test-value": "^3.0.0" + } + }, + "jsdoc-to-markdown": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/jsdoc-to-markdown/-/jsdoc-to-markdown-7.1.1.tgz", + "integrity": "sha512-CI86d63xAVNO+ENumWwmJ034lYe5iGU5GwjtTA11EuphP9tpnoi4hrKgR/J8uME0D+o4KUpVfwX1fjZhc8dEtg==", + "dev": true, + "requires": { + "array-back": "^6.2.2", + "command-line-tool": "^0.8.0", + "config-master": "^3.1.0", + "dmd": "^6.1.0", + "jsdoc-api": "^7.1.1", + "jsdoc-parse": "^6.1.0", + "walk-back": "^5.1.0" + } + }, "jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -13568,12 +14451,36 @@ "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", "dev": true }, + "lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=", + "dev": true + }, "lodash.ismatch": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz", "integrity": "sha1-dWy1FQyjum8RCFp4hJZF8Yj4Xzc=", "dev": true }, + "lodash.omit": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.omit/-/lodash.omit-4.5.0.tgz", + "integrity": "sha1-brGa5aHuHdnfC5aeZs4Lf6MLXmA=", + "dev": true + }, + "lodash.padend": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.6.1.tgz", + "integrity": "sha1-U8y6BH0G4VjTEfRdpiX05J5vFm4=", + "dev": true + }, + "lodash.pick": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", + "integrity": "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=", + "dev": true + }, "lodash.template": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", @@ -13994,6 +14901,12 @@ "mkdirp": "^1.0.3" } }, + "mkdirp2": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/mkdirp2/-/mkdirp2-1.0.5.tgz", + "integrity": "sha512-xOE9xbICroUDmG1ye2h4bZ8WBie9EGmACaco8K8cx6RlkJJrxGIqjGqztAI+NMhexXBcdGbSEzI6N3EJPevxZw==", + "dev": true + }, "mocha": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.2.2.tgz", @@ -14446,6 +15359,12 @@ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" }, + "object-get": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/object-get/-/object-get-2.1.1.tgz", + "integrity": "sha512-7n4IpLMzGGcLEMiQKsNR7vCe+N5E9LORFrtNUVy4sO3dj9a3HedZCxEL2T7QuLhcHN1NBuBsMOKaOsAYI9IIvg==", + "dev": true + }, "object-inspect": { "version": "1.12.0", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", @@ -14458,6 +15377,12 @@ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "dev": true }, + "object-to-spawn-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object-to-spawn-args/-/object-to-spawn-args-2.0.1.tgz", + "integrity": "sha512-6FuKFQ39cOID+BMZ3QaphcC8Y4cw6LXBLyIgPU+OhIYwviJamPAn+4mITapnSBQrejB+NNp+FMskhD8Cq+Ys3w==", + "dev": true + }, "object.assign": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", @@ -15170,6 +16095,78 @@ "strip-indent": "^3.0.0" } }, + "reduce-extract": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/reduce-extract/-/reduce-extract-1.0.0.tgz", + "integrity": "sha1-Z/I4W+2mUGG19fQxJmLosIDKFSU=", + "dev": true, + "requires": { + "test-value": "^1.0.1" + }, + "dependencies": { + "array-back": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", + "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", + "dev": true, + "requires": { + "typical": "^2.6.0" + } + }, + "test-value": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/test-value/-/test-value-1.1.0.tgz", + "integrity": "sha1-oJE29y7AQ9J8iTcHwrFZv6196T8=", + "dev": true, + "requires": { + "array-back": "^1.0.2", + "typical": "^2.4.2" + } + } + } + }, + "reduce-flatten": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-3.0.1.tgz", + "integrity": "sha512-bYo+97BmUUOzg09XwfkwALt4PQH1M5L0wzKerBt6WLm3Fhdd43mMS89HiT1B9pJIqko/6lWx3OnV4J9f2Kqp5Q==", + "dev": true + }, + "reduce-unique": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/reduce-unique/-/reduce-unique-2.0.1.tgz", + "integrity": "sha512-x4jH/8L1eyZGR785WY+ePtyMNhycl1N2XOLxhCbzZFaqF4AXjLzqSxa2UHgJ2ZVR/HHyPOvl1L7xRnW8ye5MdA==", + "dev": true + }, + "reduce-without": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/reduce-without/-/reduce-without-1.0.1.tgz", + "integrity": "sha1-aK0OrRGFXJo31OglbBW7+Hly/Iw=", + "dev": true, + "requires": { + "test-value": "^2.0.0" + }, + "dependencies": { + "array-back": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", + "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", + "dev": true, + "requires": { + "typical": "^2.6.0" + } + }, + "test-value": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/test-value/-/test-value-2.1.0.tgz", + "integrity": "sha1-Edpv9nDzRxpztiXKTz/c97t0gpE=", + "dev": true, + "requires": { + "array-back": "^1.0.3", + "typical": "^2.6.0" + } + } + } + }, "regenerator-runtime": { "version": "0.13.9", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", @@ -15547,6 +16544,30 @@ "socks": "^2.6.1" } }, + "sort-array": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/sort-array/-/sort-array-4.1.5.tgz", + "integrity": "sha512-Ya4peoS1fgFN42RN1REk2FgdNOeLIEMKFGJvs7VTP3OklF8+kl2SkpVliZ4tk/PurWsrWRsdNdU+tgyOBkB9sA==", + "dev": true, + "requires": { + "array-back": "^5.0.0", + "typical": "^6.0.1" + }, + "dependencies": { + "array-back": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-5.0.0.tgz", + "integrity": "sha512-kgVWwJReZWmVuWOQKEOohXKJX+nD02JAZ54D1RRWlv8L0NebauKAaFxACKzB74RTclt1+WNz5KHaLRDAPZbDEw==", + "dev": true + }, + "typical": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/typical/-/typical-6.0.1.tgz", + "integrity": "sha512-+g3NEp7fJLe9DPa1TArHm9QAA7YciZmWnfAqEaFrBihQ7epOv9i99rjtgb6Iz0wh3WuQDjsCTDfgRoGnmHN81A==", + "dev": true + } + } + }, "sort-keys": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-4.2.0.tgz", @@ -15667,6 +16688,32 @@ "tslib": "^2.3.1" } }, + "stream-connect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stream-connect/-/stream-connect-1.0.2.tgz", + "integrity": "sha1-GLyB8u2zW4tdmoAJIAqYUxRCipc=", + "dev": true, + "requires": { + "array-back": "^1.0.2" + }, + "dependencies": { + "array-back": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", + "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", + "dev": true, + "requires": { + "typical": "^2.6.0" + } + } + } + }, + "stream-via": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/stream-via/-/stream-via-1.0.4.tgz", + "integrity": "sha512-DBp0lSvX5G9KGRDTkR/R+a29H+Wk2xItOF+MpZLLNDWbEV9tGPnqLPxHEYjmiz8xGtJHRIqmI+hCjmNzqoA4nQ==", + "dev": true + }, "strict-uri-encode": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", @@ -15799,6 +16846,30 @@ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true }, + "table-layout": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-0.4.5.tgz", + "integrity": "sha512-zTvf0mcggrGeTe/2jJ6ECkJHAQPIYEwDoqsiqBjI24mvRmQbInK5jq33fyypaCBxX08hMkfmdOqj6haT33EqWw==", + "dev": true, + "requires": { + "array-back": "^2.0.0", + "deep-extend": "~0.6.0", + "lodash.padend": "^4.6.1", + "typical": "^2.6.1", + "wordwrapjs": "^3.0.0" + }, + "dependencies": { + "array-back": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", + "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", + "dev": true, + "requires": { + "typical": "^2.6.1" + } + } + } + }, "taffydb": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz", @@ -15824,6 +16895,12 @@ "integrity": "sha1-CnwOom06Oa+n4OvqnB/AvE2qAR0=", "dev": true }, + "temp-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/temp-path/-/temp-path-1.0.0.tgz", + "integrity": "sha1-JLFUOXOrRCiW2a02fdnL2/r+kYs=", + "dev": true + }, "temp-write": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/temp-write/-/temp-write-4.0.0.tgz", @@ -15837,6 +16914,27 @@ "uuid": "^3.3.2" } }, + "test-value": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/test-value/-/test-value-3.0.0.tgz", + "integrity": "sha512-sVACdAWcZkSU9x7AOmJo5TqE+GyNJknHaHsMrR6ZnhjVlVN9Yx6FjHrsKZ3BjIpPCT68zYesPWkakrNupwfOTQ==", + "dev": true, + "requires": { + "array-back": "^2.0.0", + "typical": "^2.6.1" + }, + "dependencies": { + "array-back": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", + "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", + "dev": true, + "requires": { + "typical": "^2.6.1" + } + } + } + }, "text-extensions": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz", @@ -15969,6 +17067,12 @@ "is-typedarray": "^1.0.0" } }, + "typical": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/typical/-/typical-2.6.1.tgz", + "integrity": "sha1-XAgOXWYcu+OCWdLnCjxyU+hziB0=", + "dev": true + }, "uc.micro": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", @@ -16138,6 +17242,12 @@ } } }, + "walk-back": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/walk-back/-/walk-back-5.1.0.tgz", + "integrity": "sha512-Uhxps5yZcVNbLEAnb+xaEEMdgTXl9qAQDzKYejG2AZ7qPwRQ81lozY9ECDbjLPNWm7YsO1IK5rsP1KoQzXAcGA==", + "dev": true + }, "wcwidth": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", @@ -16206,6 +17316,24 @@ "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", "dev": true }, + "wordwrapjs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-3.0.0.tgz", + "integrity": "sha512-mO8XtqyPvykVCsrwj5MlOVWvSnCdT+C+QVbm6blradR7JExAhbkZ7hZ9A+9NUtwzSqrlUo9a67ws0EiILrvRpw==", + "dev": true, + "requires": { + "reduce-flatten": "^1.0.1", + "typical": "^2.6.1" + }, + "dependencies": { + "reduce-flatten": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-1.0.1.tgz", + "integrity": "sha1-JYx479FT3fk8tWEjf2EYTzaW4yc=", + "dev": true + } + } + }, "workerpool": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz", diff --git a/package.json b/package.json index a68cff65..2be0745a 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,9 @@ "setup": "npm i && npm run bootstrap && cd repl && npm i", "repl": "cd repl && npm run start", "osc": "cd packages/osc && npm run server", - "build": "cd repl && npm run build" + "build": "cd repl && npm run build", + "jsdoc": "jsdoc packages/core/pattern.mjs -c jsdoc.config.json", + "jsdoc2md": "jsdoc2md packages/core/pattern.mjs -c jsdoc.config.json > api.md" }, "workspaces": [ "packages/*" @@ -34,6 +36,8 @@ "homepage": "https://strudel.tidalcycles.org", "devDependencies": { "events": "^3.3.0", + "jsdoc": "^3.6.10", + "jsdoc-to-markdown": "^7.1.1", "lerna": "^4.0.0", "mocha": "^9.1.4" } diff --git a/packages/core/pattern.mjs b/packages/core/pattern.mjs index f65a896d..942e7bd3 100644 --- a/packages/core/pattern.mjs +++ b/packages/core/pattern.mjs @@ -12,12 +12,26 @@ import State from './state.mjs'; import { isNote, toMidi, compose, removeUndefineds, flatten, id, listRange, curry, mod } from './util.mjs'; import drawLine from './drawLine.mjs'; +/** @class Class representing a pattern. */ export class Pattern { - // the following functions will get patternFactories as nested functions: + /** + * Create a pattern. + * @param {function} query - The function that maps a State to Haps . + */ constructor(query) { this.query = query; } + /** + * query events insude the tiven time span + * + * @param {Fraction | number} begin from time + * @param {Fraction | number} end to time + * @returns Hap[] + * @example + * const pattern = sequence('a', ['b', 'c']); + * const events = pattern.queryArc(0, 1); + */ queryArc(begin, end) { return this.query(new State(new TimeSpan(begin, end))); } @@ -838,8 +852,14 @@ Pattern.prototype.factories = { // Nothing export const silence = new Pattern((_) => []); +/** A discrete value that repeats once per cycle: + * + * @param {any} value - The value to repeat + * @returns {Pattern} + * @example + * pure('e4') + */ export function pure(value) { - // A discrete value that repeats once per cycle function query(state) { return state.span.spanCycles.map((subspan) => new Hap(Fraction(subspan.begin).wholeCycle(), subspan, value)); } @@ -859,8 +879,13 @@ export function reify(thing) { return pure(thing); } -// Basic functions for combining patterns - +/** The given items are played at the same time at the same length: + * + * @param {...any} items - The items to stack + * @return {Pattern} + * @example + * stack(g3, b3, [e4, d4]) + */ export function stack(...pats) { // Array test here is to avoid infinite recursions.. pats = pats.map((pat) => (Array.isArray(pat) ? sequence(...pat) : reify(pat))); @@ -868,10 +893,17 @@ export function stack(...pats) { return new Pattern(query); } +/** Concatenation: combines a list of patterns, switching between them successively, one per cycle: + * + * synonyms: {@link cat} + * + * @param {...any} items - The items to concatenate + * @return {Pattern} + * @example + * slowcat(e5, b4, [d5, c5]) + * + */ export function slowcat(...pats) { - // Concatenation: combines a list of patterns, switching between them - // successively, one per cycle. - // Array test here is to avoid infinite recursions.. pats = pats.map((pat) => (Array.isArray(pat) ? sequence(...pat) : reify(pat))); @@ -892,9 +924,11 @@ export function slowcat(...pats) { return new Pattern(query)._splitQueries(); } +/** Concatenation: combines a list of patterns, switching between them successively, one per cycle. Unlike slowcat, this version will skip cycles. + * @param {...any} items - The items to concatenate + * @return {Pattern} + */ export function slowcatPrime(...pats) { - // Concatenation: combines a list of patterns, switching between them - // successively, one per cycle. Unlike slowcat, this version will skip cycles. pats = pats.map(reify); const query = function (state) { const pat_n = Math.floor(state.span.begin) % pats.length; @@ -904,18 +938,33 @@ export function slowcatPrime(...pats) { return new Pattern(query)._splitQueries(); } +/** Concatenation: as with {@link slowcat}, but squashes a cycle from each pattern into one cycle + * + * Synonyms: {@link seq}, {@link sequence} + * + * @param {...any} items - The items to concatenate + * @return {Pattern} + * @example + * fastcat(e5, b4, [d5, c5]) + * sequence(e5, b4, [d5, c5]) + * seq(e5, b4, [d5, c5]) + */ export function fastcat(...pats) { - // Concatenation: as with slowcat, but squashes a cycle from each - // pattern into one cycle return slowcat(...pats)._fast(pats.length); } +/** See {@link slowcat} */ export function cat(...pats) { return slowcat(...pats); } +/** Like {@link fastcat}, but where each step has a temporal weight: + * @param {...Array} items - The items to concatenate + * @return {Pattern} + * @example + * timeCat([3,e3],[1, g3]) + */ export function timeCat(...timepats) { - // Like cat, but where each step has a temporal 'weight' const total = timepats.map((a) => a[0]).reduce((a, b) => a.add(b), Fraction(0)); let begin = Fraction(0); const pats = []; @@ -927,11 +976,12 @@ export function timeCat(...timepats) { return stack(...pats); } +/** See {@link fastcat} */ export function sequence(...pats) { return fastcat(...pats); } -// shorthand for sequence +/** See {@link fastcat} */ export function seq(...pats) { return fastcat(...pats); } From f81190bf3592aea8f04177c0fec346254a18566b Mon Sep 17 00:00:00 2001 From: alex Date: Sun, 1 May 2022 20:46:30 +0100 Subject: [PATCH 2/7] try adding some pattern docs --- packages/core/pattern.mjs | 91 +++++++++++++++++++++++++++++++++------ 1 file changed, 77 insertions(+), 14 deletions(-) diff --git a/packages/core/pattern.mjs b/packages/core/pattern.mjs index 942e7bd3..f342cbaa 100644 --- a/packages/core/pattern.mjs +++ b/packages/core/pattern.mjs @@ -36,10 +36,13 @@ export class Pattern { return this.query(new State(new TimeSpan(begin, end))); } + /** + * Returns a new pattern, with queries split at cycle boundaries. This makes + * some calculations easier to express, as all events are then constrained to + * happen within a cycle. + * @returns Pattern + */ _splitQueries() { - // Splits queries at cycle boundaries. This makes some calculations - // easier to express, as all events are then constrained to happen within - // a cycle. const pat = this; const q = (state) => { return flatten(state.span.spanCycles.map((subspan) => pat.query(state.setSpan(subspan)))); @@ -47,23 +50,44 @@ export class Pattern { return new Pattern(q); } + /** + * Returns a new pattern, where the given function is applied to the query + * timespan before passing it to the original pattern. + * @param {Function} func the function to apply + * @returns Pattern + */ withQuerySpan(func) { return new Pattern((state) => this.query(state.withSpan(func))); } - withQueryTime(func) { - // Returns a new pattern, with the function applied to both the begin - // and end of the the query timespan + /** + * As with {@link Pattern#withQuerySpan|withQuerySpan}, but the function is applied to both the + * begin and end time of the query timespan. + * @param {Function} func the function to apply + * @returns Pattern + */ + withQueryTime(func) { return new Pattern((state) => this.query(state.withSpan((span) => span.withTime(func)))); } + /** + * Similar to {@link Pattern#withQuerySpan|withQuerySpan}, but the function is applied to the timespans + * of all haps returned by pattern queries (both `part` timespans, and where + * present, `whole` timespans). + * @param {Function} func + * @returns Pattern + */ withEventSpan(func) { - // Returns a new pattern, with the function applied to each event - // timespan. return new Pattern((state) => this.query(state).map((hap) => hap.withSpan(func))); } - withEventTime(func) { + /** + * As with {@link Pattern#withEventSpan|withEventSpan}, but the function is applied to both the + * begin and end time of the hap timespans. + * @param {Function} func the function to apply + * @returns Pattern + */ + withEventTime(func) { // Returns a new pattern, with the function applied to both the begin // and end of each event timespan. return this.withEventSpan((span) => span.withTime(func)); @@ -126,14 +150,20 @@ export class Pattern { }); } + /** + * Returns a new pattern, with the function applied to the value of + * each event. It has the alias {@link Pattern#fmap|fmap}. + * @param {Function} func + * @returns Pattern + */ withValue(func) { - // Returns a new pattern, with the function applied to the value of - // each event. It has the alias 'fmap'. return new Pattern((state) => this.query(state).map((hap) => hap.withValue(func))); } - // alias - fmap(func) { + /** + * see {@link Pattern#withValue|withValue} + */ + fmap(func) { return this.withValue(func); } @@ -149,7 +179,13 @@ export class Pattern { return this._filterValues((val) => val != undefined); } - onsetsOnly() { + /** + * Returns a new pattern, with all haps without onsets filtered out. A hap + * with an onset is one with a `whole` timespan that begins at the same time + * as its `part` timespan. + * @returns Pattern + */ + onsetsOnly() { // Returns a new pattern that will only return events where the start // of the 'whole' timespan matches the start of the 'part' // timespan, i.e. the events that include their 'onset'. @@ -183,6 +219,17 @@ export class Pattern { return new Pattern(query); } + /** + * When this method is called on a pattern of functions, it matches its haps + * with those in the given pattern of values. A new pattern is returned, with + * each matching value applied to the corresponding function. + * + * In this `appBoth` variant, where timespans of the function and value haps + * are not the same but do intersect, the resulting hap has a timespan of the + * intersection. This applies to both the part and the whole timespan. + * @param {Pattern} pat_val + * @returns Pattern + */ appBoth(pat_val) { // Tidal's <*> const whole_func = function (span_a, span_b) { @@ -194,6 +241,15 @@ export class Pattern { return this._appWhole(whole_func, pat_val); } + /** + * As with {@link Pattern#appBoth|appBoth}, but the `whole` timespan is not the intersection, + * but the timespan from the function of patterns that this method is called + * on. In practice, this means that the pattern structure, including onsets, + * are preserved from the pattern of functions (often referred to as the left + * hand or inner pattern). + * @param {Pattern} pat_val + * @returns Pattern + */ appLeft(pat_val) { const pat_func = this; @@ -217,6 +273,13 @@ export class Pattern { return new Pattern(query); } + /** + * As with {@link Pattern#appLeft|appLeft}, but `whole` timespans are instead taken from the + * pattern of values, i.e. structure is preserved from the right hand/outer + * pattern. + * @param {Pattern} pat_val + * @returns Pattern + */ appRight(pat_val) { const pat_func = this; From e0c77a5fa8d91c990d58f71e4ecb1e901177d2f6 Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Mon, 2 May 2022 23:17:50 +0200 Subject: [PATCH 3/7] try out jsdoc-json --- doc.json | 990 ++++++++++++++++++++++++++++++++++++++++++++++ package-lock.json | 47 ++- package.json | 2 + 3 files changed, 1028 insertions(+), 11 deletions(-) create mode 100644 doc.json diff --git a/doc.json b/doc.json new file mode 100644 index 00000000..fc728c82 --- /dev/null +++ b/doc.json @@ -0,0 +1,990 @@ +{ + "docs": [ + { + "comment": "/** @class Class representing a pattern. */", + "meta": { + "range": [ + 1134, + 24952 + ], + "filename": "pattern.mjs", + "lineno": 16, + "columnno": 0, + "path": "/Users/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100000042", + "name": "exports.Pattern", + "type": "ClassDeclaration" + } + }, + "name": "Pattern", + "longname": "Pattern", + "kind": "class", + "classdesc": "

Class representing a pattern.

", + "scope": "global", + "description": "

Create a pattern.

", + "memberof": "Pattern", + "params": [ + { + "type": { + "names": [ + "function" + ] + }, + "description": "

The function that maps a State to Haps .

", + "name": "query" + } + ], + "___id": "T000002R000005", + "___s": true + }, + { + "comment": "/**\n * query events insude the tiven time span\n *\n * @param {Fraction | number} begin from time\n * @param {Fraction | number} end to time\n * @returns Hap[]\n * @example\n * const pattern = sequence('a', ['b', 'c']);\n * const events = pattern.queryArc(0, 1);\n */", + "meta": { + "range": [ + 1598, + 1684 + ], + "filename": "pattern.mjs", + "lineno": 35, + "columnno": 2, + "path": "/Users/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100000057", + "name": "Pattern#queryArc", + "type": "MethodDefinition", + "paramnames": [ + "begin", + "end" + ] + }, + "vars": { + "": null + } + }, + "description": "

query events insude the tiven time span

", + "params": [ + { + "type": { + "names": [ + "Fraction", + "number" + ] + }, + "description": "

from time

", + "name": "begin" + }, + { + "type": { + "names": [ + "Fraction", + "number" + ] + }, + "description": "

to time

", + "name": "end" + } + ], + "returns": [ + { + "description": "

Hap[]

" + } + ], + "examples": [ + "const pattern = sequence('a', ['b', 'c']);\nconst events = pattern.queryArc(0, 1);" + ], + "name": "queryArc", + "longname": "Pattern#queryArc", + "kind": "function", + "memberof": "Pattern", + "scope": "instance", + "___id": "T000002R000007", + "___s": true + }, + { + "comment": "/**\n * Returns a new pattern, with queries split at cycle boundaries. This makes\n * some calculations easier to express, as all events are then constrained to\n * happen within a cycle.\n * @returns Pattern\n */", + "meta": { + "range": [ + 1909, + 2110 + ], + "filename": "pattern.mjs", + "lineno": 45, + "columnno": 2, + "path": "/Users/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100000074", + "name": "Pattern#_splitQueries", + "type": "MethodDefinition", + "paramnames": [] + }, + "vars": { + "": null + } + }, + "description": "

Returns a new pattern, with queries split at cycle boundaries. This makes\nsome calculations easier to express, as all events are then constrained to\nhappen within a cycle.

", + "returns": [ + { + "description": "

Pattern

" + } + ], + "name": "_splitQueries", + "longname": "Pattern#_splitQueries", + "kind": "function", + "memberof": "Pattern", + "scope": "instance", + "params": [], + "___id": "T000002R000008", + "___s": true + }, + { + "comment": "/**\n * Returns a new pattern, where the given function is applied to the query\n * timespan before passing it to the original pattern.\n * @param {Function} func the function to apply\n * @returns Pattern\n */", + "meta": { + "range": [ + 2332, + 2426 + ], + "filename": "pattern.mjs", + "lineno": 59, + "columnno": 2, + "path": "/Users/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100000114", + "name": "Pattern#withQuerySpan", + "type": "MethodDefinition", + "paramnames": [ + "func" + ] + }, + "vars": { + "": null + } + }, + "description": "

Returns a new pattern, where the given function is applied to the query\ntimespan before passing it to the original pattern.

", + "params": [ + { + "type": { + "names": [ + "function" + ] + }, + "description": "

the function to apply

", + "name": "func" + } + ], + "returns": [ + { + "description": "

Pattern

" + } + ], + "name": "withQuerySpan", + "longname": "Pattern#withQuerySpan", + "kind": "function", + "memberof": "Pattern", + "scope": "instance", + "___id": "T000002R000011", + "___s": true + }, + { + "comment": "/**\n * As with {@link Pattern#withQuerySpan|withQuerySpan}, but the function is applied to both the\n * begin and end time of the query timespan.\n * @param {Function} func the function to apply\n * @returns Pattern\n */", + "meta": { + "range": [ + 2660, + 2779 + ], + "filename": "pattern.mjs", + "lineno": 69, + "columnno": 3, + "path": "/Users/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100000133", + "name": "Pattern#withQueryTime", + "type": "MethodDefinition", + "paramnames": [ + "func" + ] + }, + "vars": { + "": null + } + }, + "description": "

As with {@link Pattern#withQuerySpan|withQuerySpan}, but the function is applied to both the\nbegin and end time of the query timespan.

", + "params": [ + { + "type": { + "names": [ + "function" + ] + }, + "description": "

the function to apply

", + "name": "func" + } + ], + "returns": [ + { + "description": "

Pattern

" + } + ], + "name": "withQueryTime", + "longname": "Pattern#withQueryTime", + "kind": "function", + "memberof": "Pattern", + "scope": "instance", + "___id": "T000002R000012", + "___s": true + }, + { + "comment": "/**\n * Similar to {@link Pattern#withQuerySpan|withQuerySpan}, but the function is applied to the timespans\n * of all haps returned by pattern queries (both `part` timespans, and where\n * present, `whole` timespans).\n * @param {Function} func \n * @returns Pattern\n */", + "meta": { + "range": [ + 3065, + 3177 + ], + "filename": "pattern.mjs", + "lineno": 80, + "columnno": 2, + "path": "/Users/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100000158", + "name": "Pattern#withEventSpan", + "type": "MethodDefinition", + "paramnames": [ + "func" + ] + }, + "vars": { + "": null + } + }, + "description": "

Similar to {@link Pattern#withQuerySpan|withQuerySpan}, but the function is applied to the timespans\nof all haps returned by pattern queries (both part timespans, and where\npresent, whole timespans).

", + "params": [ + { + "type": { + "names": [ + "function" + ] + }, + "name": "func" + } + ], + "returns": [ + { + "description": "

Pattern

" + } + ], + "name": "withEventSpan", + "longname": "Pattern#withEventSpan", + "kind": "function", + "memberof": "Pattern", + "scope": "instance", + "___id": "T000002R000013", + "___s": true + }, + { + "comment": "/**\n * As with {@link Pattern#withEventSpan|withEventSpan}, but the function is applied to both the\n * begin and end time of the hap timespans.\n * @param {Function} func the function to apply\n * @returns Pattern\n */", + "meta": { + "range": [ + 3410, + 3610 + ], + "filename": "pattern.mjs", + "lineno": 90, + "columnno": 3, + "path": "/Users/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100000183", + "name": "Pattern#withEventTime", + "type": "MethodDefinition", + "paramnames": [ + "func" + ] + }, + "vars": { + "": null + } + }, + "description": "

As with {@link Pattern#withEventSpan|withEventSpan}, but the function is applied to both the\nbegin and end time of the hap timespans.

", + "params": [ + { + "type": { + "names": [ + "function" + ] + }, + "description": "

the function to apply

", + "name": "func" + } + ], + "returns": [ + { + "description": "

Pattern

" + } + ], + "name": "withEventTime", + "longname": "Pattern#withEventTime", + "kind": "function", + "memberof": "Pattern", + "scope": "instance", + "___id": "T000002R000014", + "___s": true + }, + { + "comment": "/**\n * Returns a new pattern, with the function applied to the value of\n * each event. It has the alias {@link Pattern#fmap|fmap}.\n * @param {Function} func \n * @returns Pattern\n */", + "meta": { + "range": [ + 5449, + 5558 + ], + "filename": "pattern.mjs", + "lineno": 159, + "columnno": 2, + "path": "/Users/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100000500", + "name": "Pattern#withValue", + "type": "MethodDefinition", + "paramnames": [ + "func" + ] + }, + "vars": { + "": null + } + }, + "description": "

Returns a new pattern, with the function applied to the value of\neach event. It has the alias {@link Pattern#fmap|fmap}.

", + "params": [ + { + "type": { + "names": [ + "function" + ] + }, + "name": "func" + } + ], + "returns": [ + { + "description": "

Pattern

" + } + ], + "name": "withValue", + "longname": "Pattern#withValue", + "kind": "function", + "memberof": "Pattern", + "scope": "instance", + "___id": "T000002R000054", + "___s": true + }, + { + "comment": "/**\n * see {@link Pattern#withValue|withValue}\n */", + "meta": { + "range": [ + 5620, + 5669 + ], + "filename": "pattern.mjs", + "lineno": 166, + "columnno": 3, + "path": "/Users/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100000525", + "name": "Pattern#fmap", + "type": "MethodDefinition", + "paramnames": [ + "func" + ] + }, + "vars": { + "": null + } + }, + "description": "

see {@link Pattern#withValue|withValue}

", + "name": "fmap", + "longname": "Pattern#fmap", + "kind": "function", + "memberof": "Pattern", + "scope": "instance", + "params": [], + "___id": "T000002R000055", + "___s": true + }, + { + "comment": "/**\n * Returns a new pattern, with all haps without onsets filtered out. A hap\n * with an onset is one with a `whole` timespan that begins at the same time\n * as its `part` timespan.\n * @returns Pattern\n */", + "meta": { + "range": [ + 6216, + 6488 + ], + "filename": "pattern.mjs", + "lineno": 188, + "columnno": 3, + "path": "/Users/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100000594", + "name": "Pattern#onsetsOnly", + "type": "MethodDefinition", + "paramnames": [] + }, + "vars": { + "": null + } + }, + "description": "

Returns a new pattern, with all haps without onsets filtered out. A hap\nwith an onset is one with a whole timespan that begins at the same time\nas its part timespan.

", + "returns": [ + { + "description": "

Pattern

" + } + ], + "name": "onsetsOnly", + "longname": "Pattern#onsetsOnly", + "kind": "function", + "memberof": "Pattern", + "scope": "instance", + "params": [], + "___id": "T000002R000059", + "___s": true + }, + { + "comment": "/**\n * When this method is called on a pattern of functions, it matches its haps\n * with those in the given pattern of values. A new pattern is returned, with\n * each matching value applied to the corresponding function. \n *\n * In this `appBoth` variant, where timespans of the function and value haps\n * are not the same but do intersect, the resulting hap has a timespan of the\n * intersection. This applies to both the part and the whole timespan.\n * @param {Pattern} pat_val \n * @returns Pattern\n */", + "meta": { + "range": [ + 7969, + 8250 + ], + "filename": "pattern.mjs", + "lineno": 233, + "columnno": 2, + "path": "/Users/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100000716", + "name": "Pattern#appBoth", + "type": "MethodDefinition", + "paramnames": [ + "pat_val" + ] + }, + "vars": { + "": null + } + }, + "description": "

When this method is called on a pattern of functions, it matches its haps\nwith those in the given pattern of values. A new pattern is returned, with\neach matching value applied to the corresponding function.

\n

In this appBoth variant, where timespans of the function and value haps\nare not the same but do intersect, the resulting hap has a timespan of the\nintersection. This applies to both the part and the whole timespan.

", + "params": [ + { + "type": { + "names": [ + "Pattern" + ] + }, + "name": "pat_val" + } + ], + "returns": [ + { + "description": "

Pattern

" + } + ], + "name": "appBoth", + "longname": "Pattern#appBoth", + "kind": "function", + "memberof": "Pattern", + "scope": "instance", + "___id": "T000002R000067", + "___s": true + }, + { + "comment": "/**\n * As with {@link Pattern#appBoth|appBoth}, but the `whole` timespan is not the intersection,\n * but the timespan from the function of patterns that this method is called\n * on. In practice, this means that the pattern structure, including onsets,\n * are preserved from the pattern of functions (often referred to as the left\n * hand or inner pattern).\n * @param {Pattern} pat_val \n * @returns Pattern\n */", + "meta": { + "range": [ + 8682, + 9430 + ], + "filename": "pattern.mjs", + "lineno": 253, + "columnno": 2, + "path": "/Users/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100000752", + "name": "Pattern#appLeft", + "type": "MethodDefinition", + "paramnames": [ + "pat_val" + ] + }, + "vars": { + "": null + } + }, + "description": "

As with {@link Pattern#appBoth|appBoth}, but the whole timespan is not the intersection,\nbut the timespan from the function of patterns that this method is called\non. In practice, this means that the pattern structure, including onsets,\nare preserved from the pattern of functions (often referred to as the left\nhand or inner pattern).

", + "params": [ + { + "type": { + "names": [ + "Pattern" + ] + }, + "name": "pat_val" + } + ], + "returns": [ + { + "description": "

Pattern

" + } + ], + "name": "appLeft", + "longname": "Pattern#appLeft", + "kind": "function", + "memberof": "Pattern", + "scope": "instance", + "___id": "T000002R000069", + "___s": true + }, + { + "comment": "/**\n * As with {@link Pattern#appLeft|appLeft}, but `whole` timespans are instead taken from the\n * pattern of values, i.e. structure is preserved from the right hand/outer\n * pattern.\n * @param {Pattern} pat_val \n * @returns Pattern\n */", + "meta": { + "range": [ + 9686, + 10431 + ], + "filename": "pattern.mjs", + "lineno": 283, + "columnno": 2, + "path": "/Users/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100000862", + "name": "Pattern#appRight", + "type": "MethodDefinition", + "paramnames": [ + "pat_val" + ] + }, + "vars": { + "": null + } + }, + "description": "

As with {@link Pattern#appLeft|appLeft}, but whole timespans are instead taken from the\npattern of values, i.e. structure is preserved from the right hand/outer\npattern.

", + "params": [ + { + "type": { + "names": [ + "Pattern" + ] + }, + "name": "pat_val" + } + ], + "returns": [ + { + "description": "

Pattern

" + } + ], + "name": "appRight", + "longname": "Pattern#appRight", + "kind": "function", + "memberof": "Pattern", + "scope": "instance", + "___id": "T000002R000081", + "___s": true + }, + { + "comment": "/** A discrete value that repeats once per cycle:\n *\n * @param {any} value - The value to repeat\n * @returns {Pattern}\n * @example\n * pure('e4')\n */", + "meta": { + "range": [ + 27168, + 27372 + ], + "filename": "pattern.mjs", + "lineno": 925, + "columnno": 0, + "path": "/Users/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100003931", + "name": "exports.pure", + "type": "FunctionDeclaration", + "paramnames": [ + "value" + ] + } + }, + "description": "

A discrete value that repeats once per cycle:

", + "params": [ + { + "type": { + "names": [ + "any" + ] + }, + "description": "

The value to repeat

", + "name": "value" + } + ], + "returns": [ + { + "type": { + "names": [ + "Pattern" + ] + } + } + ], + "examples": [ + "pure('e4')" + ], + "name": "pure", + "longname": "pure", + "kind": "function", + "scope": "global", + "___id": "T000002R000294", + "___s": true + }, + { + "comment": "/** The given items are played at the same time at the same length:\n *\n * @param {...any} items - The items to stack\n * @return {Pattern}\n * @example\n * stack(g3, b3, [e4, d4])\n */", + "meta": { + "range": [ + 27885, + 28158 + ], + "filename": "pattern.mjs", + "lineno": 952, + "columnno": 0, + "path": "/Users/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100003992", + "name": "exports.stack", + "type": "FunctionDeclaration", + "paramnames": [ + "pats" + ] + } + }, + "description": "

The given items are played at the same time at the same length:

", + "params": [ + { + "type": { + "names": [ + "any" + ] + }, + "variable": true, + "description": "

The items to stack

", + "name": "items" + } + ], + "returns": [ + { + "type": { + "names": [ + "Pattern" + ] + } + } + ], + "examples": [ + "stack(g3, b3, [e4, d4])" + ], + "name": "stack", + "longname": "stack", + "kind": "function", + "scope": "global", + "___id": "T000002R000301", + "___s": true + }, + { + "comment": "/** Concatenation: combines a list of patterns, switching between them successively, one per cycle:\n *\n * synonyms: {@link cat}\n *\n * @param {...any} items - The items to concatenate\n * @return {Pattern}\n * @example\n * slowcat(e5, b4, [d5, c5])\n *\n */", + "meta": { + "range": [ + 28412, + 29325 + ], + "filename": "pattern.mjs", + "lineno": 969, + "columnno": 0, + "path": "/Users/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100004042", + "name": "exports.slowcat", + "type": "FunctionDeclaration", + "paramnames": [ + "pats" + ] + } + }, + "description": "

Concatenation: combines a list of patterns, switching between them successively, one per cycle:

\n

synonyms: {@link cat}

", + "params": [ + { + "type": { + "names": [ + "any" + ] + }, + "variable": true, + "description": "

The items to concatenate

", + "name": "items" + } + ], + "returns": [ + { + "type": { + "names": [ + "Pattern" + ] + } + } + ], + "examples": [ + "slowcat(e5, b4, [d5, c5])" + ], + "name": "slowcat", + "longname": "slowcat", + "kind": "function", + "scope": "global", + "___id": "T000002R000305", + "___s": true + }, + { + "comment": "/** Concatenation: combines a list of patterns, switching between them successively, one per cycle. Unlike slowcat, this version will skip cycles.\n * @param {...any} items - The items to concatenate\n * @return {Pattern}\n */", + "meta": { + "range": [ + 29551, + 29823 + ], + "filename": "pattern.mjs", + "lineno": 994, + "columnno": 0, + "path": "/Users/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100004169", + "name": "exports.slowcatPrime", + "type": "FunctionDeclaration", + "paramnames": [ + "pats" + ] + } + }, + "description": "

Concatenation: combines a list of patterns, switching between them successively, one per cycle. Unlike slowcat, this version will skip cycles.

", + "params": [ + { + "type": { + "names": [ + "any" + ] + }, + "variable": true, + "description": "

The items to concatenate

", + "name": "items" + } + ], + "returns": [ + { + "type": { + "names": [ + "Pattern" + ] + } + } + ], + "name": "slowcatPrime", + "longname": "slowcatPrime", + "kind": "function", + "scope": "global", + "___id": "T000002R000313", + "___s": true + }, + { + "comment": "/** Concatenation: as with {@link slowcat}, but squashes a cycle from each pattern into one cycle\n *\n * Synonyms: {@link seq}, {@link sequence}\n *\n * @param {...any} items - The items to concatenate\n * @return {Pattern}\n * @example\n * fastcat(e5, b4, [d5, c5])\n * sequence(e5, b4, [d5, c5])\n * seq(e5, b4, [d5, c5])\n */", + "meta": { + "range": [ + 30145, + 30227 + ], + "filename": "pattern.mjs", + "lineno": 1015, + "columnno": 0, + "path": "/Users/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100004224", + "name": "exports.fastcat", + "type": "FunctionDeclaration", + "paramnames": [ + "pats" + ] + } + }, + "description": "

Concatenation: as with {@link slowcat}, but squashes a cycle from each pattern into one cycle

\n

Synonyms: {@link seq}, {@link sequence}

", + "params": [ + { + "type": { + "names": [ + "any" + ] + }, + "variable": true, + "description": "

The items to concatenate

", + "name": "items" + } + ], + "returns": [ + { + "type": { + "names": [ + "Pattern" + ] + } + } + ], + "examples": [ + "fastcat(e5, b4, [d5, c5])\nsequence(e5, b4, [d5, c5])\nseq(e5, b4, [d5, c5])" + ], + "name": "fastcat", + "longname": "fastcat", + "kind": "function", + "scope": "global", + "___id": "T000002R000319", + "___s": true + }, + { + "comment": "/** See {@link slowcat} */", + "meta": { + "range": [ + 30256, + 30315 + ], + "filename": "pattern.mjs", + "lineno": 1020, + "columnno": 0, + "path": "/Users/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100004241", + "name": "exports.cat", + "type": "FunctionDeclaration", + "paramnames": [ + "pats" + ] + } + }, + "description": "

See {@link slowcat}

", + "name": "cat", + "longname": "cat", + "kind": "function", + "scope": "global", + "___id": "T000002R000321", + "___s": true + }, + { + "comment": "/** Like {@link fastcat}, but where each step has a temporal weight:\n * @param {...Array} items - The items to concatenate\n * @return {Pattern}\n * @example\n * timeCat([3,e3],[1, g3])\n */", + "meta": { + "range": [ + 30504, + 30863 + ], + "filename": "pattern.mjs", + "lineno": 1030, + "columnno": 0, + "path": "/Users/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100004252", + "name": "exports.timeCat", + "type": "FunctionDeclaration", + "paramnames": [ + "timepats" + ] + } + }, + "description": "

Like {@link fastcat}, but where each step has a temporal weight:

", + "params": [ + { + "type": { + "names": [ + "Array" + ] + }, + "variable": true, + "description": "

The items to concatenate

", + "name": "items" + } + ], + "returns": [ + { + "type": { + "names": [ + "Pattern" + ] + } + } + ], + "examples": [ + "timeCat([3,e3],[1, g3])" + ], + "name": "timeCat", + "longname": "timeCat", + "kind": "function", + "scope": "global", + "___id": "T000002R000323", + "___s": true + }, + { + "comment": "/** See {@link fastcat} */", + "meta": { + "range": [ + 30892, + 30956 + ], + "filename": "pattern.mjs", + "lineno": 1043, + "columnno": 0, + "path": "/Users/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100004338", + "name": "exports.sequence", + "type": "FunctionDeclaration", + "paramnames": [ + "pats" + ] + } + }, + "description": "

See {@link fastcat}

", + "name": "sequence", + "longname": "sequence", + "kind": "function", + "scope": "global", + "___id": "T000002R000330", + "___s": true + }, + { + "comment": "/** See {@link fastcat} */", + "meta": { + "range": [ + 30985, + 31044 + ], + "filename": "pattern.mjs", + "lineno": 1048, + "columnno": 0, + "path": "/Users/felix/projects/strudel/packages/core", + "code": { + "id": "astnode100004349", + "name": "exports.seq", + "type": "FunctionDeclaration", + "paramnames": [ + "pats" + ] + } + }, + "description": "

See {@link fastcat}

", + "name": "seq", + "longname": "seq", + "kind": "function", + "scope": "global", + "___id": "T000002R000332", + "___s": true + }, + { + "kind": "package", + "longname": "package:undefined", + "files": [ + "/Users/felix/projects/strudel/packages/core/pattern.mjs" + ], + "___id": "T000002R000447", + "___s": true + } + ] +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 678e7707..d427fb65 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,13 +7,14 @@ "": { "name": "@strudel.cycles/monorepo", "version": "0.0.1", - "license": "GPL-3.0-or-later", + "license": "AGPL-3.0-or-later", "workspaces": [ "packages/*" ], "devDependencies": { "events": "^3.3.0", "jsdoc": "^3.6.10", + "jsdoc-json": "^2.0.2", "jsdoc-to-markdown": "^7.1.1", "lerna": "^4.0.0", "mocha": "^9.1.4" @@ -1875,6 +1876,10 @@ "resolved": "packages/core", "link": true }, + "node_modules/@strudel.cycles/embed": { + "resolved": "packages/embed", + "link": true + }, "node_modules/@strudel.cycles/eval": { "resolved": "packages/eval", "link": true @@ -5448,6 +5453,12 @@ "node": ">=12.17" } }, + "node_modules/jsdoc-json": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/jsdoc-json/-/jsdoc-json-2.0.2.tgz", + "integrity": "sha512-n0vVkWvBMHFNUsW6HUhMrVCk+nJZwW3kpd9/JiCgdYvjjZV3NcP5fV3+lTgOkOA/bTKJxbCKT8Au92FHII3pnA==", + "dev": true + }, "node_modules/jsdoc-parse": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsdoc-parse/-/jsdoc-parse-6.1.0.tgz", @@ -9750,7 +9761,7 @@ "packages/core": { "name": "@strudel.cycles/core", "version": "0.0.5", - "license": "GPL-3.0-or-later", + "license": "AGPL-3.0-or-later", "dependencies": { "bjork": "^0.0.1", "fraction.js": "^4.2.0" @@ -9759,10 +9770,15 @@ "mocha": "^9.2.2" } }, + "packages/embed": { + "name": "@strudel.cycles/embed", + "version": "0.0.2", + "license": "AGPL-3.0-or-later" + }, "packages/eval": { "name": "@strudel.cycles/eval", "version": "0.0.5", - "license": "GPL-3.0-or-later", + "license": "AGPL-3.0-or-later", "dependencies": { "@strudel.cycles/core": "^0.0.5", "estraverse": "^5.3.0", @@ -9789,7 +9805,7 @@ "packages/midi": { "name": "@strudel.cycles/midi", "version": "0.0.6", - "license": "GPL-3.0-or-later", + "license": "AGPL-3.0-or-later", "dependencies": { "@strudel.cycles/tone": "^0.0.6", "tone": "^14.7.77", @@ -9799,7 +9815,7 @@ "packages/mini": { "name": "@strudel.cycles/mini", "version": "0.0.7", - "license": "GPL-3.0-or-later", + "license": "AGPL-3.0-or-later", "dependencies": { "@strudel.cycles/core": "^0.0.5", "@strudel.cycles/eval": "^0.0.5", @@ -9809,7 +9825,7 @@ "packages/osc": { "name": "@strudel.cycles/osc", "version": "0.0.2", - "license": "GPL-3.0-or-later", + "license": "AGPL-3.0-or-later", "dependencies": { "osc-js": "^2.3.2" } @@ -9817,12 +9833,12 @@ "packages/serial": { "name": "@strudel.cycles/serial", "version": "0.0.6", - "license": "GPL-3.0-or-later" + "license": "AGPL-3.0-or-later" }, "packages/tonal": { "name": "@strudel.cycles/tonal", "version": "0.0.5", - "license": "GPL-3.0-or-later", + "license": "AGPL-3.0-or-later", "dependencies": { "@strudel.cycles/core": "^0.0.5", "@tonaljs/tonal": "^4.6.5", @@ -9847,7 +9863,7 @@ "packages/tone": { "name": "@strudel.cycles/tone", "version": "0.0.6", - "license": "GPL-3.0-or-later", + "license": "AGPL-3.0-or-later", "dependencies": { "@strudel.cycles/core": "^0.0.5", "@tonejs/piano": "^0.2.1", @@ -9858,7 +9874,7 @@ "packages/webaudio": { "name": "@strudel.cycles/webaudio", "version": "0.0.6", - "license": "GPL-3.0-or-later", + "license": "AGPL-3.0-or-later", "dependencies": { "@strudel.cycles/core": "^0.0.5" } @@ -9866,7 +9882,7 @@ "packages/xen": { "name": "@strudel.cycles/xen", "version": "0.0.5", - "license": "GPL-3.0-or-later", + "license": "AGPL-3.0-or-later", "dependencies": { "@strudel.cycles/core": "^0.0.5" } @@ -11381,6 +11397,9 @@ "mocha": "^9.2.2" } }, + "@strudel.cycles/embed": { + "version": "file:packages/embed" + }, "@strudel.cycles/eval": { "version": "file:packages/eval", "requires": { @@ -14244,6 +14263,12 @@ "walk-back": "^5.1.0" } }, + "jsdoc-json": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/jsdoc-json/-/jsdoc-json-2.0.2.tgz", + "integrity": "sha512-n0vVkWvBMHFNUsW6HUhMrVCk+nJZwW3kpd9/JiCgdYvjjZV3NcP5fV3+lTgOkOA/bTKJxbCKT8Au92FHII3pnA==", + "dev": true + }, "jsdoc-parse": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsdoc-parse/-/jsdoc-parse-6.1.0.tgz", diff --git a/package.json b/package.json index b724718d..df97c6f4 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "osc": "cd packages/osc && npm run server", "build": "cd repl && npm run build", "jsdoc": "jsdoc packages/core/pattern.mjs -c jsdoc.config.json", + "jsdoc-json": "jsdoc packages/core/pattern.mjs --template ./node_modules/jsdoc-json --destination doc.json -c jsdoc.config.json", "jsdoc2md": "jsdoc2md packages/core/pattern.mjs -c jsdoc.config.json > api.md" }, "workspaces": [ @@ -36,6 +37,7 @@ "devDependencies": { "events": "^3.3.0", "jsdoc": "^3.6.10", + "jsdoc-json": "^2.0.2", "jsdoc-to-markdown": "^7.1.1", "lerna": "^4.0.0", "mocha": "^9.1.4" From 56962196eab9b8b4d37e447019333d6547ce5610 Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Wed, 4 May 2022 22:47:13 +0200 Subject: [PATCH 4/7] configure jsdoc to parse all package files --- api.md | 140 ------------------------ doc.json | 271 +++++++++++++++++++++++++++------------------- jsdoc.config.json | 9 +- package.json | 5 +- 4 files changed, 168 insertions(+), 257 deletions(-) delete mode 100644 api.md diff --git a/api.md b/api.md deleted file mode 100644 index 5bda9d74..00000000 --- a/api.md +++ /dev/null @@ -1,140 +0,0 @@ -## Classes - -
-
Pattern
-

Class representing a pattern.

-
- -## Functions - -
-
pure(value)Pattern
-

A discrete value that repeats once per cycle:

-
stack(...items)Pattern
-

The given items are played at the same time at the same length:

-
slowcat(...items)Pattern
-

Concatenation: combines a list of patterns, switching between them successively, one per cycle:

-

synonyms: [cat](#cat)

-
slowcatPrime(...items)Pattern
-

Concatenation: combines a list of patterns, switching between them successively, one per cycle. Unlike slowcat, this version will skip cycles.

-
fastcat(...items)Pattern
-

Concatenation: as with [slowcat](#slowcat), but squashes a cycle from each pattern into one cycle

-

Synonyms: [seq](#seq), [sequence](#sequence)

-
cat()
-

See [slowcat](#slowcat)

-
timeCat(...items)Pattern
-

Like [fastcat](#fastcat), but where each step has a temporal weight:

-
sequence()
-

See [fastcat](#fastcat)

-
seq()
-

See [fastcat](#fastcat)

-
- - - -## pure(value) ⇒ [Pattern](#Pattern) -

A discrete value that repeats once per cycle:

- -**Kind**: global function - -| Param | Type | Description | -| --- | --- | --- | -| value | any |

The value to repeat

| - -**Example** -```js -pure('e4') -``` - - -## stack(...items) ⇒ [Pattern](#Pattern) -

The given items are played at the same time at the same length:

- -**Kind**: global function - -| Param | Type | Description | -| --- | --- | --- | -| ...items | any |

The items to stack

| - -**Example** -```js -stack(g3, b3, [e4, d4]) -``` - - -## slowcat(...items) ⇒ [Pattern](#Pattern) -

Concatenation: combines a list of patterns, switching between them successively, one per cycle:

-

synonyms: [cat](#cat)

- -**Kind**: global function - -| Param | Type | Description | -| --- | --- | --- | -| ...items | any |

The items to concatenate

| - -**Example** -```js -slowcat(e5, b4, [d5, c5]) -``` - - -## slowcatPrime(...items) ⇒ [Pattern](#Pattern) -

Concatenation: combines a list of patterns, switching between them successively, one per cycle. Unlike slowcat, this version will skip cycles.

- -**Kind**: global function - -| Param | Type | Description | -| --- | --- | --- | -| ...items | any |

The items to concatenate

| - - - -## fastcat(...items) ⇒ [Pattern](#Pattern) -

Concatenation: as with [slowcat](#slowcat), but squashes a cycle from each pattern into one cycle

-

Synonyms: [seq](#seq), [sequence](#sequence)

- -**Kind**: global function - -| Param | Type | Description | -| --- | --- | --- | -| ...items | any |

The items to concatenate

| - -**Example** -```js -fastcat(e5, b4, [d5, c5]) -sequence(e5, b4, [d5, c5]) -seq(e5, b4, [d5, c5]) -``` - - -## cat() -

See [slowcat](#slowcat)

- -**Kind**: global function - - -## timeCat(...items) ⇒ [Pattern](#Pattern) -

Like [fastcat](#fastcat), but where each step has a temporal weight:

- -**Kind**: global function - -| Param | Type | Description | -| --- | --- | --- | -| ...items | Array |

The items to concatenate

| - -**Example** -```js -timeCat([3,e3],[1, g3]) -``` - - -## sequence() -

See [fastcat](#fastcat)

- -**Kind**: global function - - -## seq() -

See [fastcat](#fastcat)

- -**Kind**: global function diff --git a/doc.json b/doc.json index fc728c82..f30bd098 100644 --- a/doc.json +++ b/doc.json @@ -4,15 +4,15 @@ "comment": "/** @class Class representing a pattern. */", "meta": { "range": [ - 1134, - 24952 + 1178, + 27040 ], "filename": "pattern.mjs", - "lineno": 16, + "lineno": 17, "columnno": 0, "path": "/Users/felix/projects/strudel/packages/core", "code": { - "id": "astnode100000042", + "id": "astnode100001837", "name": "exports.Pattern", "type": "ClassDeclaration" } @@ -35,22 +35,22 @@ "name": "query" } ], - "___id": "T000002R000005", + "___id": "T000002R000098", "___s": true }, { "comment": "/**\n * query events insude the tiven time span\n *\n * @param {Fraction | number} begin from time\n * @param {Fraction | number} end to time\n * @returns Hap[]\n * @example\n * const pattern = sequence('a', ['b', 'c']);\n * const events = pattern.queryArc(0, 1);\n */", "meta": { "range": [ - 1598, - 1684 + 1642, + 1728 ], "filename": "pattern.mjs", - "lineno": 35, + "lineno": 36, "columnno": 2, "path": "/Users/felix/projects/strudel/packages/core", "code": { - "id": "astnode100000057", + "id": "astnode100001852", "name": "Pattern#queryArc", "type": "MethodDefinition", "paramnames": [ @@ -98,22 +98,22 @@ "kind": "function", "memberof": "Pattern", "scope": "instance", - "___id": "T000002R000007", + "___id": "T000002R000100", "___s": true }, { "comment": "/**\n * Returns a new pattern, with queries split at cycle boundaries. This makes\n * some calculations easier to express, as all events are then constrained to\n * happen within a cycle.\n * @returns Pattern\n */", "meta": { "range": [ - 1909, - 2110 + 1953, + 2154 ], "filename": "pattern.mjs", - "lineno": 45, + "lineno": 46, "columnno": 2, "path": "/Users/felix/projects/strudel/packages/core", "code": { - "id": "astnode100000074", + "id": "astnode100001869", "name": "Pattern#_splitQueries", "type": "MethodDefinition", "paramnames": [] @@ -134,22 +134,22 @@ "memberof": "Pattern", "scope": "instance", "params": [], - "___id": "T000002R000008", + "___id": "T000002R000101", "___s": true }, { "comment": "/**\n * Returns a new pattern, where the given function is applied to the query\n * timespan before passing it to the original pattern.\n * @param {Function} func the function to apply\n * @returns Pattern\n */", "meta": { "range": [ - 2332, - 2426 + 2376, + 2470 ], "filename": "pattern.mjs", - "lineno": 59, + "lineno": 60, "columnno": 2, "path": "/Users/felix/projects/strudel/packages/core", "code": { - "id": "astnode100000114", + "id": "astnode100001909", "name": "Pattern#withQuerySpan", "type": "MethodDefinition", "paramnames": [ @@ -182,22 +182,22 @@ "kind": "function", "memberof": "Pattern", "scope": "instance", - "___id": "T000002R000011", + "___id": "T000002R000104", "___s": true }, { "comment": "/**\n * As with {@link Pattern#withQuerySpan|withQuerySpan}, but the function is applied to both the\n * begin and end time of the query timespan.\n * @param {Function} func the function to apply\n * @returns Pattern\n */", "meta": { "range": [ - 2660, - 2779 + 2704, + 2823 ], "filename": "pattern.mjs", - "lineno": 69, + "lineno": 70, "columnno": 3, "path": "/Users/felix/projects/strudel/packages/core", "code": { - "id": "astnode100000133", + "id": "astnode100001928", "name": "Pattern#withQueryTime", "type": "MethodDefinition", "paramnames": [ @@ -230,22 +230,22 @@ "kind": "function", "memberof": "Pattern", "scope": "instance", - "___id": "T000002R000012", + "___id": "T000002R000105", "___s": true }, { "comment": "/**\n * Similar to {@link Pattern#withQuerySpan|withQuerySpan}, but the function is applied to the timespans\n * of all haps returned by pattern queries (both `part` timespans, and where\n * present, `whole` timespans).\n * @param {Function} func \n * @returns Pattern\n */", "meta": { "range": [ - 3065, - 3177 + 3109, + 3221 ], "filename": "pattern.mjs", - "lineno": 80, + "lineno": 81, "columnno": 2, "path": "/Users/felix/projects/strudel/packages/core", "code": { - "id": "astnode100000158", + "id": "astnode100001953", "name": "Pattern#withEventSpan", "type": "MethodDefinition", "paramnames": [ @@ -277,22 +277,22 @@ "kind": "function", "memberof": "Pattern", "scope": "instance", - "___id": "T000002R000013", + "___id": "T000002R000106", "___s": true }, { "comment": "/**\n * As with {@link Pattern#withEventSpan|withEventSpan}, but the function is applied to both the\n * begin and end time of the hap timespans.\n * @param {Function} func the function to apply\n * @returns Pattern\n */", "meta": { "range": [ - 3410, - 3610 + 3454, + 3654 ], "filename": "pattern.mjs", - "lineno": 90, + "lineno": 91, "columnno": 3, "path": "/Users/felix/projects/strudel/packages/core", "code": { - "id": "astnode100000183", + "id": "astnode100001978", "name": "Pattern#withEventTime", "type": "MethodDefinition", "paramnames": [ @@ -325,22 +325,22 @@ "kind": "function", "memberof": "Pattern", "scope": "instance", - "___id": "T000002R000014", + "___id": "T000002R000107", "___s": true }, { "comment": "/**\n * Returns a new pattern, with the function applied to the value of\n * each event. It has the alias {@link Pattern#fmap|fmap}.\n * @param {Function} func \n * @returns Pattern\n */", "meta": { "range": [ - 5449, - 5558 + 5493, + 5602 ], "filename": "pattern.mjs", - "lineno": 159, + "lineno": 160, "columnno": 2, "path": "/Users/felix/projects/strudel/packages/core", "code": { - "id": "astnode100000500", + "id": "astnode100002295", "name": "Pattern#withValue", "type": "MethodDefinition", "paramnames": [ @@ -372,22 +372,22 @@ "kind": "function", "memberof": "Pattern", "scope": "instance", - "___id": "T000002R000054", + "___id": "T000002R000147", "___s": true }, { "comment": "/**\n * see {@link Pattern#withValue|withValue}\n */", "meta": { "range": [ - 5620, - 5669 + 5664, + 5713 ], "filename": "pattern.mjs", - "lineno": 166, + "lineno": 167, "columnno": 3, "path": "/Users/felix/projects/strudel/packages/core", "code": { - "id": "astnode100000525", + "id": "astnode100002320", "name": "Pattern#fmap", "type": "MethodDefinition", "paramnames": [ @@ -405,22 +405,22 @@ "memberof": "Pattern", "scope": "instance", "params": [], - "___id": "T000002R000055", + "___id": "T000002R000148", "___s": true }, { "comment": "/**\n * Returns a new pattern, with all haps without onsets filtered out. A hap\n * with an onset is one with a `whole` timespan that begins at the same time\n * as its `part` timespan.\n * @returns Pattern\n */", "meta": { "range": [ - 6216, - 6488 + 6260, + 6532 ], "filename": "pattern.mjs", - "lineno": 188, + "lineno": 189, "columnno": 3, "path": "/Users/felix/projects/strudel/packages/core", "code": { - "id": "astnode100000594", + "id": "astnode100002389", "name": "Pattern#onsetsOnly", "type": "MethodDefinition", "paramnames": [] @@ -441,22 +441,22 @@ "memberof": "Pattern", "scope": "instance", "params": [], - "___id": "T000002R000059", + "___id": "T000002R000152", "___s": true }, { "comment": "/**\n * When this method is called on a pattern of functions, it matches its haps\n * with those in the given pattern of values. A new pattern is returned, with\n * each matching value applied to the corresponding function. \n *\n * In this `appBoth` variant, where timespans of the function and value haps\n * are not the same but do intersect, the resulting hap has a timespan of the\n * intersection. This applies to both the part and the whole timespan.\n * @param {Pattern} pat_val \n * @returns Pattern\n */", "meta": { "range": [ - 7969, - 8250 + 8156, + 8437 ], "filename": "pattern.mjs", - "lineno": 233, + "lineno": 239, "columnno": 2, "path": "/Users/felix/projects/strudel/packages/core", "code": { - "id": "astnode100000716", + "id": "astnode100002525", "name": "Pattern#appBoth", "type": "MethodDefinition", "paramnames": [ @@ -488,22 +488,22 @@ "kind": "function", "memberof": "Pattern", "scope": "instance", - "___id": "T000002R000067", + "___id": "T000002R000161", "___s": true }, { "comment": "/**\n * As with {@link Pattern#appBoth|appBoth}, but the `whole` timespan is not the intersection,\n * but the timespan from the function of patterns that this method is called\n * on. In practice, this means that the pattern structure, including onsets,\n * are preserved from the pattern of functions (often referred to as the left\n * hand or inner pattern).\n * @param {Pattern} pat_val \n * @returns Pattern\n */", "meta": { "range": [ - 8682, - 9430 + 8869, + 9617 ], "filename": "pattern.mjs", - "lineno": 253, + "lineno": 259, "columnno": 2, "path": "/Users/felix/projects/strudel/packages/core", "code": { - "id": "astnode100000752", + "id": "astnode100002561", "name": "Pattern#appLeft", "type": "MethodDefinition", "paramnames": [ @@ -535,22 +535,22 @@ "kind": "function", "memberof": "Pattern", "scope": "instance", - "___id": "T000002R000069", + "___id": "T000002R000163", "___s": true }, { "comment": "/**\n * As with {@link Pattern#appLeft|appLeft}, but `whole` timespans are instead taken from the\n * pattern of values, i.e. structure is preserved from the right hand/outer\n * pattern.\n * @param {Pattern} pat_val \n * @returns Pattern\n */", "meta": { "range": [ - 9686, - 10431 + 9873, + 10618 ], "filename": "pattern.mjs", - "lineno": 283, + "lineno": 289, "columnno": 2, "path": "/Users/felix/projects/strudel/packages/core", "code": { - "id": "astnode100000862", + "id": "astnode100002671", "name": "Pattern#appRight", "type": "MethodDefinition", "paramnames": [ @@ -582,22 +582,22 @@ "kind": "function", "memberof": "Pattern", "scope": "instance", - "___id": "T000002R000081", + "___id": "T000002R000175", "___s": true }, { "comment": "/** A discrete value that repeats once per cycle:\n *\n * @param {any} value - The value to repeat\n * @returns {Pattern}\n * @example\n * pure('e4')\n */", "meta": { "range": [ - 27168, - 27372 + 31120, + 31324 ], "filename": "pattern.mjs", - "lineno": 925, + "lineno": 1044, "columnno": 0, "path": "/Users/felix/projects/strudel/packages/core", "code": { - "id": "astnode100003931", + "id": "astnode100006158", "name": "exports.pure", "type": "FunctionDeclaration", "paramnames": [ @@ -633,22 +633,22 @@ "longname": "pure", "kind": "function", "scope": "global", - "___id": "T000002R000294", + "___id": "T000002R000429", "___s": true }, { "comment": "/** The given items are played at the same time at the same length:\n *\n * @param {...any} items - The items to stack\n * @return {Pattern}\n * @example\n * stack(g3, b3, [e4, d4])\n */", "meta": { "range": [ - 27885, - 28158 + 31837, + 32110 ], "filename": "pattern.mjs", - "lineno": 952, + "lineno": 1071, "columnno": 0, "path": "/Users/felix/projects/strudel/packages/core", "code": { - "id": "astnode100003992", + "id": "astnode100006219", "name": "exports.stack", "type": "FunctionDeclaration", "paramnames": [ @@ -685,22 +685,22 @@ "longname": "stack", "kind": "function", "scope": "global", - "___id": "T000002R000301", + "___id": "T000002R000436", "___s": true }, { "comment": "/** Concatenation: combines a list of patterns, switching between them successively, one per cycle:\n *\n * synonyms: {@link cat}\n *\n * @param {...any} items - The items to concatenate\n * @return {Pattern}\n * @example\n * slowcat(e5, b4, [d5, c5])\n *\n */", "meta": { "range": [ - 28412, - 29325 + 32364, + 33277 ], "filename": "pattern.mjs", - "lineno": 969, + "lineno": 1088, "columnno": 0, "path": "/Users/felix/projects/strudel/packages/core", "code": { - "id": "astnode100004042", + "id": "astnode100006269", "name": "exports.slowcat", "type": "FunctionDeclaration", "paramnames": [ @@ -737,22 +737,22 @@ "longname": "slowcat", "kind": "function", "scope": "global", - "___id": "T000002R000305", + "___id": "T000002R000440", "___s": true }, { "comment": "/** Concatenation: combines a list of patterns, switching between them successively, one per cycle. Unlike slowcat, this version will skip cycles.\n * @param {...any} items - The items to concatenate\n * @return {Pattern}\n */", "meta": { "range": [ - 29551, - 29823 + 33503, + 33775 ], "filename": "pattern.mjs", - "lineno": 994, + "lineno": 1113, "columnno": 0, "path": "/Users/felix/projects/strudel/packages/core", "code": { - "id": "astnode100004169", + "id": "astnode100006396", "name": "exports.slowcatPrime", "type": "FunctionDeclaration", "paramnames": [ @@ -786,22 +786,22 @@ "longname": "slowcatPrime", "kind": "function", "scope": "global", - "___id": "T000002R000313", + "___id": "T000002R000448", "___s": true }, { "comment": "/** Concatenation: as with {@link slowcat}, but squashes a cycle from each pattern into one cycle\n *\n * Synonyms: {@link seq}, {@link sequence}\n *\n * @param {...any} items - The items to concatenate\n * @return {Pattern}\n * @example\n * fastcat(e5, b4, [d5, c5])\n * sequence(e5, b4, [d5, c5])\n * seq(e5, b4, [d5, c5])\n */", "meta": { "range": [ - 30145, - 30227 + 34097, + 34179 ], "filename": "pattern.mjs", - "lineno": 1015, + "lineno": 1134, "columnno": 0, "path": "/Users/felix/projects/strudel/packages/core", "code": { - "id": "astnode100004224", + "id": "astnode100006451", "name": "exports.fastcat", "type": "FunctionDeclaration", "paramnames": [ @@ -838,22 +838,22 @@ "longname": "fastcat", "kind": "function", "scope": "global", - "___id": "T000002R000319", + "___id": "T000002R000454", "___s": true }, { "comment": "/** See {@link slowcat} */", "meta": { "range": [ - 30256, - 30315 + 34208, + 34267 ], "filename": "pattern.mjs", - "lineno": 1020, + "lineno": 1139, "columnno": 0, "path": "/Users/felix/projects/strudel/packages/core", "code": { - "id": "astnode100004241", + "id": "astnode100006468", "name": "exports.cat", "type": "FunctionDeclaration", "paramnames": [ @@ -866,22 +866,22 @@ "longname": "cat", "kind": "function", "scope": "global", - "___id": "T000002R000321", + "___id": "T000002R000456", "___s": true }, { "comment": "/** Like {@link fastcat}, but where each step has a temporal weight:\n * @param {...Array} items - The items to concatenate\n * @return {Pattern}\n * @example\n * timeCat([3,e3],[1, g3])\n */", "meta": { "range": [ - 30504, - 30863 + 34456, + 34815 ], "filename": "pattern.mjs", - "lineno": 1030, + "lineno": 1149, "columnno": 0, "path": "/Users/felix/projects/strudel/packages/core", "code": { - "id": "astnode100004252", + "id": "astnode100006479", "name": "exports.timeCat", "type": "FunctionDeclaration", "paramnames": [ @@ -918,22 +918,22 @@ "longname": "timeCat", "kind": "function", "scope": "global", - "___id": "T000002R000323", + "___id": "T000002R000458", "___s": true }, { "comment": "/** See {@link fastcat} */", "meta": { "range": [ - 30892, - 30956 + 34844, + 34908 ], "filename": "pattern.mjs", - "lineno": 1043, + "lineno": 1162, "columnno": 0, "path": "/Users/felix/projects/strudel/packages/core", "code": { - "id": "astnode100004338", + "id": "astnode100006565", "name": "exports.sequence", "type": "FunctionDeclaration", "paramnames": [ @@ -946,22 +946,22 @@ "longname": "sequence", "kind": "function", "scope": "global", - "___id": "T000002R000330", + "___id": "T000002R000465", "___s": true }, { "comment": "/** See {@link fastcat} */", "meta": { "range": [ - 30985, - 31044 + 34937, + 34996 ], "filename": "pattern.mjs", - "lineno": 1048, + "lineno": 1167, "columnno": 0, "path": "/Users/felix/projects/strudel/packages/core", "code": { - "id": "astnode100004349", + "id": "astnode100006576", "name": "exports.seq", "type": "FunctionDeclaration", "paramnames": [ @@ -974,16 +974,63 @@ "longname": "seq", "kind": "function", "scope": "global", - "___id": "T000002R000332", + "___id": "T000002R000467", "___s": true }, { "kind": "package", "longname": "package:undefined", "files": [ - "/Users/felix/projects/strudel/packages/core/pattern.mjs" + "/Users/felix/projects/strudel/packages/core/controls.mjs", + "/Users/felix/projects/strudel/packages/core/drawLine.mjs", + "/Users/felix/projects/strudel/packages/core/euclid.mjs", + "/Users/felix/projects/strudel/packages/core/fraction.mjs", + "/Users/felix/projects/strudel/packages/core/gist.js", + "/Users/felix/projects/strudel/packages/core/hap.mjs", + "/Users/felix/projects/strudel/packages/core/index.mjs", + "/Users/felix/projects/strudel/packages/core/pattern.mjs", + "/Users/felix/projects/strudel/packages/core/signal.mjs", + "/Users/felix/projects/strudel/packages/core/speak.mjs", + "/Users/felix/projects/strudel/packages/core/state.mjs", + "/Users/felix/projects/strudel/packages/core/test/drawLine.test.mjs", + "/Users/felix/projects/strudel/packages/core/test/fraction.test.mjs", + "/Users/felix/projects/strudel/packages/core/test/pattern.test.mjs", + "/Users/felix/projects/strudel/packages/core/test/util.test.mjs", + "/Users/felix/projects/strudel/packages/core/test/value.test.mjs", + "/Users/felix/projects/strudel/packages/core/timespan.mjs", + "/Users/felix/projects/strudel/packages/core/util.mjs", + "/Users/felix/projects/strudel/packages/core/value.mjs", + "/Users/felix/projects/strudel/packages/embed/embed.js", + "/Users/felix/projects/strudel/packages/eval/evaluate.mjs", + "/Users/felix/projects/strudel/packages/eval/shapeshifter.mjs", + "/Users/felix/projects/strudel/packages/eval/test/evaluate.test.mjs", + "/Users/felix/projects/strudel/packages/eval/test/shapeshifter.test.mjs", + "/Users/felix/projects/strudel/packages/midi/midi.mjs", + "/Users/felix/projects/strudel/packages/mini/krill-parser.js", + "/Users/felix/projects/strudel/packages/mini/mini.mjs", + "/Users/felix/projects/strudel/packages/mini/test/mini.test.mjs", + "/Users/felix/projects/strudel/packages/osc/osc.mjs", + "/Users/felix/projects/strudel/packages/osc/server.js", + "/Users/felix/projects/strudel/packages/osc/tidal-sniffer.js", + "/Users/felix/projects/strudel/packages/serial/serial.mjs", + "/Users/felix/projects/strudel/packages/tonal/test/tonal.test.mjs", + "/Users/felix/projects/strudel/packages/tonal/tonal.mjs", + "/Users/felix/projects/strudel/packages/tonal/voicings.mjs", + "/Users/felix/projects/strudel/packages/tone/draw.mjs", + "/Users/felix/projects/strudel/packages/tone/pianoroll.mjs", + "/Users/felix/projects/strudel/packages/tone/test/tone.test.mjs", + "/Users/felix/projects/strudel/packages/tone/tone.mjs", + "/Users/felix/projects/strudel/packages/tone/ui.mjs", + "/Users/felix/projects/strudel/packages/webaudio/clockworker.mjs", + "/Users/felix/projects/strudel/packages/webaudio/index.mjs", + "/Users/felix/projects/strudel/packages/webaudio/scheduler.mjs", + "/Users/felix/projects/strudel/packages/webaudio/webaudio.mjs", + "/Users/felix/projects/strudel/packages/xen/test/xen.test.mjs", + "/Users/felix/projects/strudel/packages/xen/tune.mjs", + "/Users/felix/projects/strudel/packages/xen/tunejs.js", + "/Users/felix/projects/strudel/packages/xen/xen.mjs" ], - "___id": "T000002R000447", + "___id": "T000002R012553", "___s": true } ] diff --git a/jsdoc.config.json b/jsdoc.config.json index 27be8275..1e287280 100644 --- a/jsdoc.config.json +++ b/jsdoc.config.json @@ -1,6 +1,11 @@ { "source": { - "includePattern": ".+\\.(js(doc|x)?|mjs)$" + "includePattern": ".+\\.(js(doc|x)?|mjs)$", + "excludePattern": "node_modules|shift-parser|shift-reducer|shift-traverser" }, - "plugins": ["plugins/markdown"] + "plugins": ["plugins/markdown"], + "opts": { + "destination": "./out/", + "recurse": true + } } diff --git a/package.json b/package.json index df97c6f4..a13c740d 100644 --- a/package.json +++ b/package.json @@ -10,9 +10,8 @@ "repl": "cd repl && npm run start", "osc": "cd packages/osc && npm run server", "build": "cd repl && npm run build", - "jsdoc": "jsdoc packages/core/pattern.mjs -c jsdoc.config.json", - "jsdoc-json": "jsdoc packages/core/pattern.mjs --template ./node_modules/jsdoc-json --destination doc.json -c jsdoc.config.json", - "jsdoc2md": "jsdoc2md packages/core/pattern.mjs -c jsdoc.config.json > api.md" + "jsdoc": "jsdoc packages/ -c jsdoc.config.json", + "jsdoc-json": "jsdoc packages/ --template ./node_modules/jsdoc-json --destination doc.json -c jsdoc.config.json" }, "workspaces": [ "packages/*" From b0dfb44e96d30b5d293a101815528713ac09f781 Mon Sep 17 00:00:00 2001 From: alex Date: Thu, 5 May 2022 16:45:32 +0100 Subject: [PATCH 5/7] add license to those extracted during javascript minification (temporary hack) --- repl/etc/agpl-header.txt | 23 +++++++++++++++++++++++ repl/package.json | 3 ++- 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 repl/etc/agpl-header.txt diff --git a/repl/etc/agpl-header.txt b/repl/etc/agpl-header.txt new file mode 100644 index 00000000..7256f033 --- /dev/null +++ b/repl/etc/agpl-header.txt @@ -0,0 +1,23 @@ +/* + +Strudel - javascript-based environment for live coding algorithmic (musical) patterns +https://strudel.tidalcycles.org / https://github.com/tidalcycles/strudel/ + +Copyright (C) Strudel contributors +https://github.com/tidalcycles/strudel/graphs/contributors + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . + +*/ + diff --git a/repl/package.json b/repl/package.json index 6b8be459..5db12a06 100644 --- a/repl/package.json +++ b/repl/package.json @@ -22,12 +22,13 @@ }, "scripts": { "start": "react-scripts start", - "build": "BUILD_PATH='../docs' react-scripts build && npm run build-tutorial", + "build": "BUILD_PATH='../docs' react-scripts build && npm run build-tutorial && npm add-license", "test": "mocha ./src/test --colors", "snapshot": "cd ./src/ && rm -f ./tunes.snapshot.mjs && node ./shoot.mjs > ./tunes.snapshot.mjs", "eject": "react-scripts eject", "tutorial": "parcel src/tutorial/index.html --no-cache", "build-tutorial": "rm -rf ../docs/tutorial && parcel build src/tutorial/index.html --dist-dir ../docs/tutorial --public-url /tutorial --no-scope-hoist --no-cache", + "add-license": "cat etc/agpl-header.txt ../docs/static/js/*LICENSE.txt > /tmp/strudel-license.txt && cp /tmp/strudel-license.txt ../docs/static/js/*LICENSE.txt", "predeploy": "npm run build", "deploy": "gh-pages -d ../docs", "static": "npx serve ../docs" From f8f744dd87cd7a844db4dcbb943e3733910021cb Mon Sep 17 00:00:00 2001 From: alex Date: Thu, 5 May 2022 17:20:36 +0100 Subject: [PATCH 6/7] standardise on hap rather than event, especially in function names --- packages/core/hap.mjs | 11 ++- packages/core/pattern.mjs | 133 ++++++++++++++-------------- packages/core/speak.mjs | 8 +- packages/core/test/pattern.test.mjs | 30 +++---- packages/core/util.mjs | 14 +-- packages/midi/midi.mjs | 14 +-- packages/osc/osc.mjs | 8 +- packages/serial/serial.mjs | 12 +-- packages/tonal/tonal.mjs | 22 ++--- packages/tone/tone.mjs | 32 +++---- packages/webaudio/webaudio.mjs | 12 +-- packages/xen/tune.mjs | 4 +- packages/xen/xen.mjs | 12 +-- 13 files changed, 159 insertions(+), 153 deletions(-) diff --git a/packages/core/hap.mjs b/packages/core/hap.mjs index 599ac86e..d82ed662 100644 --- a/packages/core/hap.mjs +++ b/packages/core/hap.mjs @@ -14,7 +14,10 @@ export class Hap { then the whole will be returned as None, in which case the given value will have been sampled from the point halfway between the start and end of the 'part' timespan. - The context is to store a list of source code locations causing the event + The context is to store a list of source code locations causing the event. + + The word 'Event' is more or less a reserved word in javascript, hence this + class is named called 'Hap'. */ constructor(whole, part, value, context = {}, stateful = false) { @@ -37,18 +40,18 @@ export class Hap { } withSpan(func) { - // Returns a new event with the function f applies to the event timespan. + // Returns a new hap with the function f applies to the hap timespan. const whole = this.whole ? func(this.whole) : undefined; return new Hap(whole, func(this.part), this.value, this.context); } withValue(func) { - // Returns a new event with the function f applies to the event value. + // Returns a new hap with the function f applies to the hap value. return new Hap(this.whole, this.part, func(this.value), this.context); } hasOnset() { - // Test whether the event contains the onset, i.e that + // Test whether the hap contains the onset, i.e that // the beginning of the part is the same as that of the whole timespan.""" return this.whole != undefined && this.whole.begin.equals(this.part.begin); } diff --git a/packages/core/pattern.mjs b/packages/core/pattern.mjs index 8fa161ef..40fac2b1 100644 --- a/packages/core/pattern.mjs +++ b/packages/core/pattern.mjs @@ -24,14 +24,14 @@ export class Pattern { } /** - * query events insude the tiven time span + * query haps insude the tiven time span * * @param {Fraction | number} begin from time * @param {Fraction | number} end to time * @returns Hap[] * @example * const pattern = sequence('a', ['b', 'c']); - * const events = pattern.queryArc(0, 1); + * const haps = pattern.queryArc(0, 1); */ queryArc(begin, end) { return this.query(new State(new TimeSpan(begin, end))); @@ -39,7 +39,7 @@ export class Pattern { /** * Returns a new pattern, with queries split at cycle boundaries. This makes - * some calculations easier to express, as all events are then constrained to + * some calculations easier to express, as all haps are then constrained to * happen within a cycle. * @returns Pattern */ @@ -78,40 +78,43 @@ export class Pattern { * @param {Function} func * @returns Pattern */ - withEventSpan(func) { + withHapSpan(func) { return new Pattern((state) => this.query(state).map((hap) => hap.withSpan(func))); } /** - * As with {@link Pattern#withEventSpan|withEventSpan}, but the function is applied to both the + * As with {@link Pattern#withHapSpan|withHapSpan}, but the function is applied to both the * begin and end time of the hap timespans. * @param {Function} func the function to apply * @returns Pattern */ - withEventTime(func) { - // Returns a new pattern, with the function applied to both the begin - // and end of each event timespan. - return this.withEventSpan((span) => span.withTime(func)); + withHapTime(func) { + return this.withHapSpan((span) => span.withTime(func)); } - _withEvents(func) { + /** + * Returns a new pattern with the given function applied to all haps returned by queries. + * @param {Function} func + * @returns Pattern + */ + _withHaps(func) { return new Pattern((state) => func(this.query(state))); } - _withEvent(func) { - return this._withEvents((events) => events.map(func)); + _withHap(func) { + return this._withHaps((haps) => haps.map(func)); } _setContext(context) { - return this._withEvent((event) => event.setContext(context)); + return this._withHap((hap) => hap.setContext(context)); } _withContext(func) { - return this._withEvent((event) => event.setContext(func(event.context))); + return this._withHap((hap) => hap.setContext(func(hap.context))); } _stripContext() { - return this._withEvent((event) => event.setContext({})); + return this._withHap((hap) => hap.setContext({})); } withLocation(start, end) { @@ -153,7 +156,7 @@ export class Pattern { /** * Returns a new pattern, with the function applied to the value of - * each event. It has the alias {@link Pattern#fmap|fmap}. + * each hap. It has the alias {@link Pattern#fmap|fmap}. * @param {Function} func * @returns Pattern */ @@ -168,8 +171,8 @@ export class Pattern { return this.withValue(func); } - _filterEvents(event_test) { - return new Pattern((state) => this.query(state).filter(event_test)); + _filterHaps(hap_test) { + return new Pattern((state) => this.query(state).filter(hap_test)); } _filterValues(value_test) { @@ -187,15 +190,15 @@ export class Pattern { * @returns Pattern */ onsetsOnly() { - // Returns a new pattern that will only return events where the start + // Returns a new pattern that will only return haps where the start // of the 'whole' timespan matches the start of the 'part' - // timespan, i.e. the events that include their 'onset'. - return this._filterEvents((hap) => hap.hasOnset()); + // timespan, i.e. the haps that include their 'onset'. + return this._filterHaps((hap) => hap.hasOnset()); } discreteOnly() { - // removes continuous events that don't have a 'whole' timespan - return this._filterEvents((hap) => hap.whole); + // removes continuous haps that don't have a 'whole' timespan + return this._filterHaps((hap) => hap.whole); } _appWhole(whole_func, pat_val) { @@ -204,22 +207,22 @@ export class Pattern { // pattern of functions. const pat_func = this; const query = function (state) { - const event_funcs = pat_func.query(state); - const event_vals = pat_val.query(state); - const apply = function (event_func, event_val) { - const s = event_func.part.intersection(event_val.part); + const hap_funcs = pat_func.query(state); + const hap_vals = pat_val.query(state); + const apply = function (hap_func, hap_val) { + const s = hap_func.part.intersection(hap_val.part); if (s == undefined) { return undefined; } return new Hap( - whole_func(event_func.whole, event_val.whole), + whole_func(hap_func.whole, hap_val.whole), s, - event_func.value(event_val.value), - event_val.combineContext(event_func), + hap_func.value(hap_val.value), + hap_val.combineContext(hap_func), ); }; return flatten( - event_funcs.map((event_func) => removeUndefineds(event_vals.map((event_val) => apply(event_func, event_val)))), + hap_funcs.map((hap_func) => removeUndefineds(hap_vals.map((hap_val) => apply(hap_func, hap_val)))), ); }; return new Pattern(query); @@ -262,8 +265,8 @@ export class Pattern { const query = function (state) { const haps = []; for (const hap_func of pat_func.query(state)) { - const event_vals = pat_val.query(state.setSpan(hap_func.wholeOrPart())); - for (const hap_val of event_vals) { + const hap_vals = pat_val.query(state.setSpan(hap_func.wholeOrPart())); + for (const hap_val of hap_vals) { const new_whole = hap_func.whole; const new_part = hap_func.part.intersection(hap_val.part); if (new_part) { @@ -326,9 +329,9 @@ export class Pattern { ); } - _sortEventsByPart() { - return this._withEvents((events) => - events.sort((a, b) => + _sortHapsByPart() { + return this._withHaps((haps) => + haps.sort((a, b) => a.part.begin .sub(b.part.begin) .or(a.part.end.sub(b.part.end)) @@ -365,21 +368,21 @@ export class Pattern { } _asNumber(dropfails = false, softfail = false) { - return this._withEvent((event) => { - const asNumber = Number(event.value); + return this._withHap((hap) => { + const asNumber = Number(hap.value); if (!isNaN(asNumber)) { - return event.withValue(() => asNumber); + return hap.withValue(() => asNumber); } const specialValue = { e: Math.E, pi: Math.PI, - }[event.value]; + }[hap.value]; if (typeof specialValue !== 'undefined') { - return event.withValue(() => specialValue); + return hap.withValue(() => specialValue); } - if (isNote(event.value)) { + if (isNote(hap.value)) { // set context type to midi to let the player know its meant as midi number and not as frequency - return new Hap(event.whole, event.part, toMidi(event.value), { ...event.context, type: 'midi' }); + return new Hap(hap.whole, hap.part, toMidi(hap.value), { ...hap.context, type: 'midi' }); } if (dropfail) { // return 'nothing' @@ -387,10 +390,10 @@ export class Pattern { } if (softfail) { // return original hap - return event; + return hap; } - throw new Error('cannot parse as number: "' + event.value + '"'); - return event; + throw new Error('cannot parse as number: "' + hap.value + '"'); + return hap; }); if (dropfail) { return result._removeUndefineds(); @@ -466,7 +469,7 @@ export class Pattern { join() { // Flattens a pattern of patterns into a pattern, where wholes are - // the intersection of matched inner and outer events. + // the intersection of matched inner and outer haps. return this.bind(id); } @@ -476,7 +479,7 @@ export class Pattern { outerJoin() { // Flattens a pattern of patterns into a pattern, where wholes are - // taken from inner events. + // taken from inner haps. return this.outerBind(id); } @@ -486,35 +489,35 @@ export class Pattern { innerJoin() { // Flattens a pattern of patterns into a pattern, where wholes are - // taken from inner events. + // taken from inner haps. return this.innerBind(id); } - // Flatterns patterns of patterns, by retriggering/resetting inner patterns at onsets of outer pattern events + // Flatterns patterns of patterns, by retriggering/resetting inner patterns at onsets of outer pattern haps _trigJoin(cycleZero = false) { const pat_of_pats = this; return new Pattern((state) => { return ( pat_of_pats - // drop continuous events from the outer pattern. + // drop continuous haps from the outer pattern. .discreteOnly() .query(state) .map((outer_hap) => { return ( outer_hap.value - // trig = align the inner pattern cycle start to outer pattern events - // Trigzero = align the inner pattern cycle zero to outer pattern events + // trig = align the inner pattern cycle start to outer pattern haps + // Trigzero = align the inner pattern cycle zero to outer pattern haps .late(cycleZero ? outer_hap.whole.begin : outer_hap.whole.begin.cyclePos()) .query(state) .map((inner_hap) => new Hap( - // Supports continuous events in the inner pattern + // Supports continuous haps in the inner pattern inner_hap.whole ? inner_hap.whole.intersection(outer_hap.whole) : undefined, inner_hap.part.intersection(outer_hap.part), inner_hap.value, ).setContext(outer_hap.combineContext(inner_hap)), ) - // Drop events that didn't intersect + // Drop haps that didn't intersect .filter((hap) => hap.part) ); }) @@ -604,7 +607,7 @@ export class Pattern { const end = cycle.add(span.end.sub(cycle).div(factor).min(1)); return new TimeSpan(begin, end); }; - return this.withQuerySpan(qf).withEventSpan(ef)._splitQueries(); + return this.withQuerySpan(qf).withHapSpan(ef)._splitQueries(); } _compress(b, e) { @@ -620,7 +623,7 @@ export class Pattern { _fast(factor) { const fastQuery = this.withQueryTime((t) => t.mul(factor)); - return fastQuery.withEventTime((t) => t.div(factor)); + return fastQuery.withHapTime((t) => t.div(factor)); } _slow(factor) { @@ -655,7 +658,7 @@ export class Pattern { _early(offset) { // Equivalent of Tidal's <~ operator offset = Fraction(offset); - return this.withQueryTime((t) => t.add(offset)).withEventTime((t) => t.sub(offset)); + return this.withQueryTime((t) => t.add(offset)).withHapTime((t) => t.sub(offset)); } _late(offset) { @@ -669,7 +672,7 @@ export class Pattern { s = Fraction(s); const d = e.sub(s); return this.withQuerySpan((span) => span.withCycle((t) => t.mul(d).add(s))) - .withEventSpan((span) => span.withCycle((t) => t.sub(s).div(d))) + .withHapSpan((span) => span.withCycle((t) => t.sub(s).div(d))) ._splitQueries(); } @@ -709,7 +712,7 @@ export class Pattern { } log() { - return this._withEvent((e) => { + return this._withHap((e) => { return e.setContext({ ...e.context, logs: (e.context?.logs || []).concat([e.show()]) }); }); } @@ -877,14 +880,14 @@ export class Pattern { return silence; } - // sets absolute duration of events + // sets absolute duration of haps _duration(value) { - return this.withEventSpan((span) => new TimeSpan(span.begin, span.begin.add(value))); + return this.withHapSpan((span) => new TimeSpan(span.begin, span.begin.add(value))); } - // sets event relative duration of events + // sets hap relative duration of haps _legato(value) { - return this.withEventSpan((span) => new TimeSpan(span.begin, span.begin.add(span.end.sub(span.begin).mul(value)))); + return this.withHapSpan((span) => new TimeSpan(span.begin, span.begin.add(span.end.sub(span.begin).mul(value)))); } _velocity(velocity) { @@ -1101,7 +1104,7 @@ export function slowcat(...pats) { // For example if three patterns are slowcat-ed, the fourth cycle of the result should // be the second (rather than fourth) cycle from the first pattern. const offset = span.begin.floor().sub(span.begin.div(pats.length).floor()); - return pat.withEventTime((t) => t.add(offset)).query(state.setSpan(span.withTime((t) => t.sub(offset)))); + return pat.withHapTime((t) => t.add(offset)).query(state.setSpan(span.withTime((t) => t.sub(offset)))); }; return new Pattern(query)._splitQueries(); } diff --git a/packages/core/speak.mjs b/packages/core/speak.mjs index 0a1b7fe3..23ca8c36 100644 --- a/packages/core/speak.mjs +++ b/packages/core/speak.mjs @@ -26,11 +26,11 @@ function speak(words, lang, voice) { } Pattern.prototype._speak = function (lang, voice) { - return this._withEvent((event) => { - const onTrigger = (time, event) => { - speak(event.value, lang, voice); + return this._withHap((hap) => { + const onTrigger = (time, hap) => { + speak(hap.value, lang, voice); }; - return event.setContext({ ...event.context, onTrigger }); + return hap.setContext({ ...hap.context, onTrigger }); }); }; diff --git a/packages/core/test/pattern.test.mjs b/packages/core/test/pattern.test.mjs index df942d0f..aa4a4ab0 100644 --- a/packages/core/test/pattern.test.mjs +++ b/packages/core/test/pattern.test.mjs @@ -57,7 +57,7 @@ const third = Fraction(1, 3); const twothirds = Fraction(2, 3); const sameFirst = (a, b) => { - return assert.deepStrictEqual(a._sortEventsByPart().firstCycle(), b._sortEventsByPart().firstCycle()); + return assert.deepStrictEqual(a._sortHapsByPart().firstCycle(), b._sortHapsByPart().firstCycle()); }; describe('TimeSpan', function () { @@ -320,7 +320,7 @@ describe('Pattern', function () { }); }); describe('setSqueeze()', () => { - it('Can squeeze one pattern inside the events of another', () => { + it('Can squeeze one pattern inside the haps of another', () => { sameFirst( sequence(1, [2, 3]).setSqueeze(sequence('a', 'b', 'c')), sequence( @@ -394,7 +394,7 @@ describe('Pattern', function () { }); it('Makes things faster, with a pattern of factors', function () { assert.equal(pure('a').fast(sequence(1, 4)).firstCycle().length, 3); - // .fast(sequence(1,silence) is a quick hack to cut an event in two.. + // .fast(sequence(1,silence) is a quick hack to cut a hap in two.. assert.deepStrictEqual( pure('a').fast(sequence(1, 4)).firstCycle(), stack(pure('a').fast(sequence(1, silence)), sequence(silence, ['a', 'a'])).firstCycle(), @@ -468,7 +468,7 @@ describe('Pattern', function () { }); it('Can alternate', function () { assert.deepStrictEqual( - pure(10).when(slowcat(true, false), add(3)).fast(4)._sortEventsByPart().firstCycle(), + pure(10).when(slowcat(true, false), add(3)).fast(4)._sortHapsByPart().firstCycle(), fastcat(13, 10, 13, 10).firstCycle(), ); }); @@ -679,7 +679,7 @@ describe('Pattern', function () { }); }); describe('_setContext()', () => { - it('Can set the event context', () => { + it('Can set the hap context', () => { assert.deepStrictEqual( pure('a') ._setContext([ @@ -701,7 +701,7 @@ describe('Pattern', function () { }); }); describe('_withContext()', () => { - it('Can update the event context', () => { + it('Can update the hap context', () => { assert.deepStrictEqual( pure('a') ._setContext([ @@ -756,13 +756,13 @@ describe('Pattern', function () { }); }); describe('early', () => { - it('Can shift an event earlier', () => { + it('Can shift a hap earlier', () => { assert.deepStrictEqual(pure(30)._late(0.25).query(st(1, 2)), [ hap(ts(1 / 4, 5 / 4), ts(1, 5 / 4), 30), hap(ts(5 / 4, 9 / 4), ts(5 / 4, 2), 30), ]); }); - it('Can shift an event earlier, into negative time', () => { + it('Can shift a hap earlier, into negative time', () => { assert.deepStrictEqual(pure(30)._late(0.25).query(st(0, 1)), [ hap(ts(-3 / 4, 1 / 4), ts(0, 1 / 4), 30), hap(ts(1 / 4, 5 / 4), ts(1 / 4, 1), 30), @@ -780,9 +780,9 @@ describe('Pattern', function () { describe('jux', () => { it('Can juxtapose', () => { assert.deepStrictEqual( - pure({ a: 1 }).jux(fast(2))._sortEventsByPart().firstCycle(), + pure({ a: 1 }).jux(fast(2))._sortHapsByPart().firstCycle(), stack(pure({ a: 1, pan: 0 }), pure({ a: 1, pan: 1 }).fast(2)) - ._sortEventsByPart() + ._sortHapsByPart() .firstCycle(), ); }); @@ -790,9 +790,9 @@ describe('Pattern', function () { describe('juxBy', () => { it('Can juxtapose by half', () => { assert.deepStrictEqual( - pure({ a: 1 }).juxBy(0.5, fast(2))._sortEventsByPart().firstCycle(), + pure({ a: 1 }).juxBy(0.5, fast(2))._sortHapsByPart().firstCycle(), stack(pure({ a: 1, pan: 0.25 }), pure({ a: 1, pan: 0.75 }).fast(2)) - ._sortEventsByPart() + ._sortHapsByPart() .firstCycle(), ); }); @@ -821,7 +821,7 @@ describe('Pattern', function () { sequence(pure('a').fast(3), [pure('b').fast(3), pure('c').fast(3)]).firstCycle(), ); }); - it('Doesnt drop events in the 9th cycle', () => { + it('Doesnt drop haps in the 9th cycle', () => { // fixed with https://github.com/tidalcycles/strudel/commit/72eeaf446e3d5e186d63cc0d2276f0723cde017a assert.equal(sequence(1, 2, 3).ply(2).early(8).firstCycle().length, 6); }); @@ -848,7 +848,7 @@ describe('Pattern', function () { }); it('Can chop(2,3)', () => { assert.deepStrictEqual( - pure({ sound: 'a' }).fast(2).chop(2, 3)._sortEventsByPart().firstCycle(), + pure({ sound: 'a' }).fast(2).chop(2, 3)._sortHapsByPart().firstCycle(), sequence( [ { sound: 'a', begin: 0, end: 0.5 }, @@ -860,7 +860,7 @@ describe('Pattern', function () { { sound: 'a', begin: 2 / 3, end: 1 }, ], ) - ._sortEventsByPart() + ._sortHapsByPart() .firstCycle(), ); }); diff --git a/packages/core/util.mjs b/packages/core/util.mjs index d03e3b6b..35a0d8f4 100644 --- a/packages/core/util.mjs +++ b/packages/core/util.mjs @@ -35,27 +35,27 @@ export const fromMidi = (n) => { // const mod = (n: number, m: number): number => (n < 0 ? mod(n + m, m) : n % m); export const mod = (n, m) => ((n % m) + m) % m; -export const getPlayableNoteValue = (event) => { - let { value: note, context } = event; +export const getPlayableNoteValue = (hap) => { + let { value: note, context } = hap; // if value is number => interpret as midi number as long as its not marked as frequency if (typeof note === 'number' && context.type !== 'frequency') { - note = fromMidi(event.value); + note = fromMidi(hap.value); } else if (typeof note === 'string' && !isNote(note)) { throw new Error('not a note: ' + note); } return note; }; -export const getFrequency = (event) => { - let { value, context } = event; +export const getFrequency = (hap) => { + let { value, context } = hap; // if value is number => interpret as midi number as long as its not marked as frequency if (typeof value === 'object' && value.freq) { return value.freq; } if (typeof value === 'number' && context.type !== 'frequency') { - value = fromMidi(event.value); + value = fromMidi(hap.value); } else if (typeof value === 'string' && isNote(value)) { - value = fromMidi(toMidi(event.value)); + value = fromMidi(toMidi(hap.value)); } else if (typeof value !== 'number') { throw new Error('not a note or frequency:' + value); } diff --git a/packages/midi/midi.mjs b/packages/midi/midi.mjs index 502ac155..a9cf4df1 100644 --- a/packages/midi/midi.mjs +++ b/packages/midi/midi.mjs @@ -39,11 +39,11 @@ Pattern.prototype.midi = function (output, channel = 1) { }')`, ); } - return this._withEvent((event) => { - // const onTrigger = (time: number, event: any) => { - const onTrigger = (time, event) => { - let note = event.value; - const velocity = event.context?.velocity ?? 0.9; + return this._withHap((hap) => { + // const onTrigger = (time: number, hap: any) => { + const onTrigger = (time, hap) => { + let note = hap.value; + const velocity = hap.context?.velocity ?? 0.9; if (!isNote(note)) { throw new Error('not a note: ' + note); } @@ -75,10 +75,10 @@ Pattern.prototype.midi = function (output, channel = 1) { // await enableWebMidi() device.playNote(note, channel, { time, - duration: event.duration.valueOf() * 1000 - 5, + duration: hap.duration.valueOf() * 1000 - 5, velocity, }); }; - return event.setContext({ ...event.context, onTrigger }); + return hap.setContext({ ...hap.context, onTrigger }); }); }; diff --git a/packages/osc/osc.mjs b/packages/osc/osc.mjs index 02c8ad83..95030d6a 100644 --- a/packages/osc/osc.mjs +++ b/packages/osc/osc.mjs @@ -12,11 +12,11 @@ comm.open(); const latency = 0.1; Pattern.prototype.osc = function () { - return this._withEvent((event) => { - const onTrigger = (time, event, currentTime) => { + return this._withHap((hap) => { + const onTrigger = (time, hap, currentTime) => { // time should be audio time of onset // currentTime should be current time of audio context (slightly before time) - const keyvals = Object.entries(event.value).flat(); + const keyvals = Object.entries(hap.value).flat(); const offset = (time - currentTime + latency) * 1000; const ts = Math.floor(Date.now() + offset); const message = new OSC.Message('/dirt/play', ...keyvals); @@ -24,6 +24,6 @@ Pattern.prototype.osc = function () { bundle.timestamp(ts); // workaround for https://github.com/adzialocha/osc-js/issues/60 comm.send(bundle); }; - return event.setContext({ ...event.context, onTrigger }); + return hap.setContext({ ...hap.context, onTrigger }); }); }; diff --git a/packages/serial/serial.mjs b/packages/serial/serial.mjs index a2bba8c9..1cf99ce2 100644 --- a/packages/serial/serial.mjs +++ b/packages/serial/serial.mjs @@ -36,23 +36,23 @@ const latency = 0.1; // Pattern.prototype.midi = function (output: string | number, channel = 1) { Pattern.prototype.serial = async function (...args) { - return this._withEvent((event) => { + return this._withHap((hap) => { if (!serialWriter) { getWriter(...args); } - const onTrigger = (time, event, currentTime) => { + const onTrigger = (time, hap, currentTime) => { var message = ""; - if (typeof event.value === 'object') { - for (const [key, val] of Object.entries(event.value).flat()) { + if (typeof hap.value === 'object') { + for (const [key, val] of Object.entries(hap.value).flat()) { message += `${key}:${val};` } } else { - message = event.value; + message = hap.value; } const offset = (time - currentTime + latency) * 1000; window.setTimeout(serialWriter, offset, message); }; - return event.setContext({ ...event.context, onTrigger }); + return hap.setContext({ ...hap.context, onTrigger }); }); }; diff --git a/packages/tonal/tonal.mjs b/packages/tonal/tonal.mjs index ada2a63b..aa54098b 100644 --- a/packages/tonal/tonal.mjs +++ b/packages/tonal/tonal.mjs @@ -43,17 +43,17 @@ export function scaleTranspose(scale, offset, note) { // Pattern.prototype._transpose = function (intervalOrSemitones: string | number) { Pattern.prototype._transpose = function (intervalOrSemitones) { - return this._withEvent((event) => { + return this._withHap((hap) => { const interval = !isNaN(Number(intervalOrSemitones)) ? Interval.fromSemitones(intervalOrSemitones /* as number */) : String(intervalOrSemitones); - if (typeof event.value === 'number') { + if (typeof hap.value === 'number') { const semitones = typeof interval === 'string' ? Interval.semitones(interval) || 0 : interval; - return event.withValue(() => event.value + semitones); + return hap.withValue(() => hap.value + semitones); } // TODO: move simplify to player to preserve enharmonics // tone.js doesn't understand multiple sharps flats e.g. F##3 has to be turned into G3 - return event.withValue(() => Note.simplify(Note.transpose(event.value, interval))); + return hap.withValue(() => Note.simplify(Note.transpose(hap.value, interval))); }); }; @@ -64,26 +64,26 @@ Pattern.prototype._transpose = function (intervalOrSemitones) { // or even `stack(c3).superimpose(transpose.slowcat(7, 5))` or Pattern.prototype._scaleTranspose = function (offset /* : number | string */) { - return this._withEvent((event) => { - if (!event.context.scale) { + return this._withHap((hap) => { + if (!hap.context.scale) { throw new Error('can only use scaleTranspose after .scale'); } - if (typeof event.value !== 'string') { + if (typeof hap.value !== 'string') { throw new Error('can only use scaleTranspose with notes'); } - return event.withValue(() => scaleTranspose(event.context.scale, Number(offset), event.value)); + return hap.withValue(() => scaleTranspose(hap.context.scale, Number(offset), hap.value)); }); }; Pattern.prototype._scale = function (scale /* : string */) { - return this._withEvent((event) => { - let note = event.value; + return this._withHap((hap) => { + let note = hap.value; const asNumber = Number(note); if (!isNaN(asNumber)) { let [tonic, scaleName] = Scale.tokenize(scale); const { pc, oct = 3 } = Note.get(tonic); note = scaleTranspose(pc + ' ' + scaleName, asNumber, pc + oct); } - return event.withValue(() => note).setContext({ ...event.context, scale }); + return hap.withValue(() => note).setContext({ ...hap.context, scale }); }); }; diff --git a/packages/tone/tone.mjs b/packages/tone/tone.mjs index 705257ce..224bc8a6 100644 --- a/packages/tone/tone.mjs +++ b/packages/tone/tone.mjs @@ -52,36 +52,36 @@ export const getDefaultSynth = () => { // with this function, you can play the pattern with any tone synth Pattern.prototype.tone = function (instrument) { - return this._withEvent((event) => { - const onTrigger = (time, event) => { + return this._withHap((hap) => { + const onTrigger = (time, hap) => { let note; - let velocity = event.context?.velocity ?? 0.75; + let velocity = hap.context?.velocity ?? 0.75; if (instrument instanceof PluckSynth) { - note = getPlayableNoteValue(event); + note = getPlayableNoteValue(hap); instrument.triggerAttack(note, time); } else if (instrument instanceof NoiseSynth) { - instrument.triggerAttackRelease(event.duration.valueOf(), time); // noise has no value + instrument.triggerAttackRelease(hap.duration.valueOf(), time); // noise has no value } else if (instrument instanceof Piano) { - note = getPlayableNoteValue(event); + note = getPlayableNoteValue(hap); instrument.keyDown({ note, time, velocity }); - instrument.keyUp({ note, time: time + event.duration.valueOf(), velocity }); + instrument.keyUp({ note, time: time + hap.duration.valueOf(), velocity }); } else if (instrument instanceof Sampler) { - note = getPlayableNoteValue(event); - instrument.triggerAttackRelease(note, event.duration.valueOf(), time, velocity); + note = getPlayableNoteValue(hap); + instrument.triggerAttackRelease(note, hap.duration.valueOf(), time, velocity); } else if (instrument instanceof Players) { - if (!instrument.has(event.value)) { - throw new Error(`name "${event.value}" not defined for players`); + if (!instrument.has(hap.value)) { + throw new Error(`name "${hap.value}" not defined for players`); } - const player = instrument.player(event.value); + const player = instrument.player(hap.value); // velocity ? player.start(time); - player.stop(time + event.duration.valueOf()); + player.stop(time + hap.duration.valueOf()); } else { - note = getPlayableNoteValue(event); - instrument.triggerAttackRelease(note, event.duration.valueOf(), time, velocity); + note = getPlayableNoteValue(hap); + instrument.triggerAttackRelease(note, hap.duration.valueOf(), time, velocity); } }; - return event.setContext({ ...event.context, instrument, onTrigger }); + return hap.setContext({ ...hap.context, instrument, onTrigger }); }); }; diff --git a/packages/webaudio/webaudio.mjs b/packages/webaudio/webaudio.mjs index 832927d0..0b4c6f84 100644 --- a/packages/webaudio/webaudio.mjs +++ b/packages/webaudio/webaudio.mjs @@ -30,10 +30,10 @@ const adsr = (attack, decay, sustain, release, velocity, begin, end) => { }; Pattern.prototype.withAudioNode = function (createAudioNode) { - return this._withEvent((event) => { - return event.setContext({ - ...event.context, - createAudioNode: (t, e) => createAudioNode(t, e, event.context.createAudioNode?.(t, event)), + return this._withHap((hap) => { + return hap.setContext({ + ...hap.context, + createAudioNode: (t, e) => createAudioNode(t, e, hap.context.createAudioNode?.(t, hap)), }); }); }; @@ -84,9 +84,9 @@ Pattern.prototype.out = function () { console.warn('out: no source! call .osc() first'); } node?.connect(master); - })._withEvent((event) => { + })._withHap((hap) => { const onTrigger = (time, e) => e.context?.createAudioNode?.(time, e); - return event.setContext({ ...event.context, onTrigger }); + return hap.setContext({ ...hap.context, onTrigger }); }); }; diff --git a/packages/xen/tune.mjs b/packages/xen/tune.mjs index 825a9d01..5685e1a7 100644 --- a/packages/xen/tune.mjs +++ b/packages/xen/tune.mjs @@ -14,8 +14,8 @@ Pattern.prototype._tune = function (scale, tonic = 220) { } tune.loadScale(scale); tune.tonicize(tonic); - return this._asNumber()._withEvent((event) => { - return event.withValue(() => tune.note(event.value)).setContext({ ...event.context, type: 'frequency' }); + return this._asNumber()._withHap((hap) => { + return hap.withValue(() => tune.note(hap.value)).setContext({ ...hap.context, type: 'frequency' }); }); }; diff --git a/packages/xen/xen.mjs b/packages/xen/xen.mjs index f82844b0..ff5a13eb 100644 --- a/packages/xen/xen.mjs +++ b/packages/xen/xen.mjs @@ -49,18 +49,18 @@ function xenOffset(xenScale, offset, index = 0) { // scaleNameOrRatios: string || number[], steps?: number Pattern.prototype._xen = function (scaleNameOrRatios, steps) { - return this._asNumber()._withEvent((event) => { + return this._asNumber()._withHap((hap) => { const scale = getXenScale(scaleNameOrRatios); steps = steps || scale.length; - const frequency = xenOffset(scale, event.value); - return event.withValue(() => frequency).setContext({ ...event.context, type: 'frequency' }); + const frequency = xenOffset(scale, hap.value); + return hap.withValue(() => frequency).setContext({ ...hap.context, type: 'frequency' }); }); }; Pattern.prototype.tuning = function (steps) { - return this._asNumber()._withEvent((event) => { - const frequency = xenOffset(steps, event.value); - return event.withValue(() => frequency).setContext({ ...event.context, type: 'frequency' }); + return this._asNumber()._withHap((hap) => { + const frequency = xenOffset(steps, hap.value); + return hap.withValue(() => frequency).setContext({ ...hap.context, type: 'frequency' }); }); }; Pattern.prototype.define('xen', (scale, pat) => pat.xen(scale), { composable: true, patternified: true }); From 5419b0896c6f040894c9c47db27276f6e31fe149 Mon Sep 17 00:00:00 2001 From: alex Date: Thu, 5 May 2022 18:45:31 +0200 Subject: [PATCH 7/7] more docs --- packages/core/pattern.mjs | 72 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 69 insertions(+), 3 deletions(-) diff --git a/packages/core/pattern.mjs b/packages/core/pattern.mjs index 40fac2b1..6c4335a3 100644 --- a/packages/core/pattern.mjs +++ b/packages/core/pattern.mjs @@ -93,30 +93,56 @@ export class Pattern { } /** - * Returns a new pattern with the given function applied to all haps returned by queries. + * Returns a new pattern with the given function applied to the list of haps returned by every query. * @param {Function} func * @returns Pattern */ - _withHaps(func) { + _withHaps(func) { return new Pattern((state) => func(this.query(state))); } - _withHap(func) { + /** + * As with {@link Pattern#_withHaps}, but applies the function to every hap, rather than every list of haps. + * @param {Function} func + * @returns Pattern + */ + _withHap(func) { return this._withHaps((haps) => haps.map(func)); } + /** + * Returns a new pattern with the context field set to every hap set to the given value. + * @param {*} context + * @returns Pattern + */ _setContext(context) { return this._withHap((hap) => hap.setContext(context)); } + /** + * Returns a new pattern with the given function applied to the context field of every hap. + * @param {Function} func + * @returns Pattern + */ _withContext(func) { return this._withHap((hap) => hap.setContext(func(hap.context))); } + /** + * Returns a new pattern with the context field of every hap set to an empty object. + * @returns Pattern + */ _stripContext() { return this._withHap((hap) => hap.setContext({})); } + /** + * Returns a new pattern with the given location information added to the + * context of every hap. + * @param {Number} start + * @param {Number} end + * @returns Pattern + */ withLocation(start, end) { const location = { start: { line: start[0], column: start[1], offset: start[2] }, @@ -171,14 +197,30 @@ export class Pattern { return this.withValue(func); } + /** + * Returns a new Pattern, which only returns haps that meet the given test. + * @param {Function} hap_test - a function which returns false for haps to be removed from the pattern + * @returns Pattern + */ _filterHaps(hap_test) { return new Pattern((state) => this.query(state).filter(hap_test)); } + /** + * As with {@link Pattern#_filterHaps}, but the function is applied to values + * inside haps. + * @param {Function} value_test + * @returns Pattern + */ _filterValues(value_test) { return new Pattern((state) => this.query(state).filter((hap) => value_test(hap.value))); } + /** + * Returns a new pattern, with haps containing undefined values removed from + * query results. + * @returns Pattern + */ _removeUndefineds() { return this._filterValues((val) => val != undefined); } @@ -196,6 +238,11 @@ export class Pattern { return this._filterHaps((hap) => hap.hasOnset()); } + /** + * Returns a new pattern, with 'continuous' haps (those without 'whole' + * timespans) removed from query results. + * @returns Pattern + */ discreteOnly() { // removes continuous haps that don't have a 'whole' timespan return this._filterHaps((hap) => hap.whole); @@ -312,6 +359,13 @@ export class Pattern { return new Pattern(query); } + /** + * Queries the pattern for the first cycle, returning Haps. Mainly of use when + * debugging a pattern. + * @param {Boolean} with_context - set to true, otherwise the context field + * will be stripped from the resulting haps. + * @returns [Hap] + */ firstCycle(with_context = false) { var self = this; if (!with_context) { @@ -320,15 +374,27 @@ export class Pattern { return self.query(new State(new TimeSpan(Fraction(0), Fraction(1)))); } + /** + * Accessor for a list of values returned by querying the first cycle. + */ get _firstCycleValues() { return this.firstCycle().map((hap) => hap.value); } + + /** + * More human-readable version of the {@link Pattern#_firstCycleValues} accessor. + */ get _showFirstCycle() { return this.firstCycle().map( (hap) => `${hap.value}: ${hap.whole.begin.toFraction()} - ${hap.whole.end.toFraction()}`, ); } + /** + * Returns a new pattern, which returns haps sorted in temporal order. Mainly + * of use when comparing two patterns for equality, in tests. + * @returns Pattern + */ _sortHapsByPart() { return this._withHaps((haps) => haps.sort((a, b) =>