can now generate mdx from nunjucks

This commit is contained in:
Felix Roos 2022-05-24 00:03:59 +02:00
parent b5b0fbbd38
commit 4acdabe439
10 changed files with 627 additions and 274 deletions

570
doc.json

File diff suppressed because it is too large Load Diff

View File

@ -16,8 +16,9 @@ import drawLine from './drawLine.mjs';
/** @class Class representing a pattern. */
export class Pattern {
/**
* Create a pattern.
* @param {function} query - The function that maps a State to Haps .
* Create a pattern. As an end user, you will most likely not create a Pattern directly.
*
* @param {function} query - The function that maps a {@link State} to an array of {@link Hap}.
*/
constructor(query) {
this.query = query;
@ -731,11 +732,31 @@ export class Pattern {
return this._compress(span.begin, span.end);
}
/**
* Speed up a pattern by the given factor.
*
* @name fast
* @memberof Pattern
* @param {number | Pattern} factor speed up factor
* @returns Pattern
* @example
* seq(e5, b4, d5, c5).fast(2)
*/
_fast(factor) {
const fastQuery = this.withQueryTime((t) => t.mul(factor));
return fastQuery.withHapTime((t) => t.div(factor));
}
/**
* Slow down a pattern over the given number of cycles.
*
* @name slow
* @memberof Pattern
* @param {number | Pattern} factor slow down factor
* @returns Pattern
* @example
* seq(e5, b4, d5, c5).slow(2)
*/
_slow(factor) {
return this._fast(Fraction(1).div(factor));
}
@ -1022,6 +1043,7 @@ export class Pattern {
return this._withContext((context) => ({ ...context, velocity: (context.velocity || 1) * velocity }));
}
// move this to controls? (speed and unit are controls)
_loopAt(factor, cps = 1) {
return this.speed((1 / factor) * cps)
.unit('c')
@ -1265,8 +1287,8 @@ export function slowcatPrime(...pats) {
* @return {Pattern}
* @example
* fastcat(e5, b4, [d5, c5])
* sequence(e5, b4, [d5, c5])
* seq(e5, b4, [d5, c5])
* // sequence(e5, b4, [d5, c5])
* // seq(e5, b4, [d5, c5])
*/
export function fastcat(...pats) {
return slowcat(...pats)._fast(pats.length);

View File

@ -8,7 +8,8 @@ function ApiDoc() {
if (!visible) {
return (
<p>
The API Docs are a work in progress, but you can preview it by clicking <a href="?api=true#api-docs">here</a>
There remaining function documentation is a work in progress, but you can preview it by clicking{' '}
<a href="?api=true#everything-else">here</a>. Beware that everything is not properly ordered from this point.
</p>
);
}
@ -16,8 +17,8 @@ function ApiDoc() {
return (
<div>
<p>
The following Chapter is the technical API documentation. It is autogenerated from the jsdoc comments in the
source files. <a href="?#api-docs">hide</a>
The following Chapter is autogenerated from the jsdoc comments in the source files.{' '}
<a href="?#everything-else">hide</a>. Beware that everything is not properly ordered from this point.
</p>
{docs
.filter((item) => !item.name?.startsWith('_') && item.kind !== 'package')

View File

@ -7,6 +7,8 @@ This program is free software: you can redistribute it and/or modify it under th
import React from 'react';
import ReactDOM from 'react-dom';
import Tutorial from './tutorial.mdx';
import ApiDoc from './ApiDoc'
import Api from './api.mdx';
import './style.scss';
import '@strudel.cycles/react/dist/style.css';
@ -30,6 +32,8 @@ ReactDOM.render(
</header>
<main className="p-4 pl-6 max-w-3xl prose">
<Tutorial />
<Api />
<ApiDoc />
</main>
</div>
</React.StrictMode>,

123
tutorial/api.mdx Normal file
View File

@ -0,0 +1,123 @@
import { MiniRepl } from './MiniRepl';
The following is generated from the source documentation.
## TOC
## Pattern Factories
The following functions will return a pattern. We will see later what that means.
### pure
<p>A discrete value that repeats once per cycle:</p>
**Parameters**
- value (any): The value to repeat
**Examples**
<div className="space-y-2">
<MiniRepl tune={`pure('e4')`} />
</div>
### slowcat
<p>Concatenation: combines a list of patterns, switching between them successively, one per cycle:</p>
<p>synonyms: <a href="#cat">cat</a></p>
**Parameters**
- items (any): The items to concatenate
**Examples**
<div className="space-y-2">
<MiniRepl tune={`slowcat(e5, b4, [d5, c5])`} />
</div>
### fastcat
<p>Concatenation: as with <a href="#slowcat">slowcat</a>, but squashes a cycle from each pattern into one cycle</p>
<p>Synonyms: <a href="#seq">seq</a>, <a href="#sequence">sequence</a></p>
**Parameters**
- items (any): The items to concatenate
**Examples**
<div className="space-y-2">
<MiniRepl tune={`fastcat(e5, b4, [d5, c5])
// sequence(e5, b4, [d5, c5])
// seq(e5, b4, [d5, c5])`} />
</div>
### stack
<p>The given items are played at the same time at the same length:</p>
**Parameters**
- items (any): The items to stack
**Examples**
<div className="space-y-2">
<MiniRepl tune={`stack(g3, b3, [e4, d4])`} />
</div>
### timeCat
<p>Like <a href="#fastcat">fastcat</a>, but where each step has a temporal weight:</p>
**Parameters**
- items (Array): The items to concatenate
**Examples**
<div className="space-y-2">
<MiniRepl tune={`timeCat([3,e3],[1, g3])`} />
</div>
## Pattern Modifiers
### Pattern.slow
<p>Slow down a pattern over the given number of cycles.</p>
**Parameters**
- factor (number|Pattern): slow down factor
**Examples**
<div className="space-y-2">
<MiniRepl tune={`seq(e5, b4, d5, c5).slow(2)`} />
</div>
### Pattern.fast
<p>Speed up a pattern by the given factor.</p>
**Parameters**
- factor (number|Pattern): speed up factor
**Examples**
<div className="space-y-2">
<MiniRepl tune={`seq(e5, b4, d5, c5).fast(2)`} />
</div>
## Everything Else

View File

@ -21,6 +21,7 @@
"autoprefixer": "^10.4.7",
"install": "^0.13.0",
"npm": "^8.10.0",
"nunjucks": "^3.2.3",
"postcss": "^8.4.13",
"rehype-autolink-headings": "^6.1.1",
"rehype-slug": "^5.0.1",
@ -795,6 +796,12 @@
"semver": "bin/semver.js"
}
},
"node_modules/a-sync-waterfall": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/a-sync-waterfall/-/a-sync-waterfall-1.0.1.tgz",
"integrity": "sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA==",
"dev": true
},
"node_modules/acorn": {
"version": "7.4.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
@ -858,6 +865,12 @@
"integrity": "sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA==",
"dev": true
},
"node_modules/asap": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
"integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==",
"dev": true
},
"node_modules/autoprefixer": {
"version": "10.4.7",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.7.tgz",
@ -1146,6 +1159,15 @@
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/commander": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz",
"integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==",
"dev": true,
"engines": {
"node": ">= 6"
}
},
"node_modules/convert-source-map": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz",
@ -4825,6 +4847,31 @@
"inBundle": true,
"license": "ISC"
},
"node_modules/nunjucks": {
"version": "3.2.3",
"resolved": "https://registry.npmjs.org/nunjucks/-/nunjucks-3.2.3.tgz",
"integrity": "sha512-psb6xjLj47+fE76JdZwskvwG4MYsQKXUtMsPh6U0YMvmyjRtKRFcxnlXGWglNybtNTNVmGdp94K62/+NjF5FDQ==",
"dev": true,
"dependencies": {
"a-sync-waterfall": "^1.0.0",
"asap": "^2.0.3",
"commander": "^5.1.0"
},
"bin": {
"nunjucks-precompile": "bin/precompile"
},
"engines": {
"node": ">= 6.9.0"
},
"peerDependencies": {
"chokidar": "^3.3.0"
},
"peerDependenciesMeta": {
"chokidar": {
"optional": true
}
}
},
"node_modules/object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
@ -6992,6 +7039,12 @@
}
}
},
"a-sync-waterfall": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/a-sync-waterfall/-/a-sync-waterfall-1.0.1.tgz",
"integrity": "sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA==",
"dev": true
},
"acorn": {
"version": "7.4.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
@ -7040,6 +7093,12 @@
"integrity": "sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA==",
"dev": true
},
"asap": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
"integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==",
"dev": true
},
"autoprefixer": {
"version": "10.4.7",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.7.tgz",
@ -7224,6 +7283,12 @@
"integrity": "sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==",
"dev": true
},
"commander": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz",
"integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==",
"dev": true
},
"convert-source-map": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz",
@ -9740,6 +9805,17 @@
}
}
},
"nunjucks": {
"version": "3.2.3",
"resolved": "https://registry.npmjs.org/nunjucks/-/nunjucks-3.2.3.tgz",
"integrity": "sha512-psb6xjLj47+fE76JdZwskvwG4MYsQKXUtMsPh6U0YMvmyjRtKRFcxnlXGWglNybtNTNVmGdp94K62/+NjF5FDQ==",
"dev": true,
"requires": {
"a-sync-waterfall": "^1.0.0",
"asap": "^2.0.3",
"commander": "^5.1.0"
}
},
"object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",

View File

@ -7,7 +7,8 @@
"start": "vite",
"build": "npm run jsdoc-json && vite build",
"preview": "vite preview",
"jsdoc-json": "jsdoc ../packages/ --template ../node_modules/jsdoc-json --destination ../doc.json -c ../jsdoc.config.json"
"jsdoc-json": "jsdoc ../packages/ --template ../node_modules/jsdoc-json --destination ../doc.json -c ../jsdoc.config.json",
"render": "npm run jsdoc-json && node ./render.js > api.mdx"
},
"type": "module",
"dependencies": {
@ -24,6 +25,7 @@
"autoprefixer": "^10.4.7",
"install": "^0.13.0",
"npm": "^8.10.0",
"nunjucks": "^3.2.3",
"postcss": "^8.4.13",
"rehype-autolink-headings": "^6.1.1",
"rehype-slug": "^5.0.1",

49
tutorial/render.js Normal file
View File

@ -0,0 +1,49 @@
import nunjucks from 'nunjucks';
import jsdoc from '../doc.json' assert { type: 'json' };
// TODO: load tutorial.mdx and append rendered api.mdx to the bottom (to make sure TOC works)
// TODO: split
const env = nunjucks.configure('templates', { autoescape: false });
const docs = jsdoc.docs.reduce((acc, obj) => Object.assign(acc, { [obj.longname]: obj }), {});
function renderAsMDX(name) {
const item = docs[name];
if (!item) {
console.warn('Not found: ' + name);
return '';
}
return `### ${item.longname}
${item.description.replaceAll(/\{\@link ([a-zA-Z]+)?\#?([a-zA-Z]*)\}/g, (_, a, b) => {
// console.log(_, 'a', a, 'b', b);
return `<a href="#${a}${b ? `-${b}` : ''}">${a}${b ? `#${b}` : ''}</a>`;
})}
${!!item.params?.length ? '**Parameters**' : ''}
${
item.params
?.map(
(param, i) =>
`- ${param.name} (${param.type?.names?.join('|')}): ${param.description?.replace(/(<([^>]+)>)/gi, '')}`,
)
.join('\n') || ''
}
${
item.examples?.length
? `**Examples**
<div className="space-y-2">
${item.examples?.map((example, k) => `<MiniRepl tune={\`${example}\`} />`).join('\n\n')}
</div>`
: ''
}`;
}
env.addFilter('jsdoc', renderAsMDX);
const rendered = nunjucks.render('api.mdx', { docs });
console.log(rendered);

View File

@ -0,0 +1,35 @@
import { MiniRepl } from './MiniRepl';
The following is generated from the source documentation.
## TOC
## Pattern Factories
The following functions will return a pattern. We will see later what that means.
{{ 'pure' | jsdoc }}
{{ 'slowcat' | jsdoc }}
{{ 'fastcat' | jsdoc }}
{{ 'stack' | jsdoc }}
{{ 'timeCat' | jsdoc }}
{{ 'polyrhythm' | jsdoc }}
## Pattern Modifiers
{{ 'Pattern.slow' | jsdoc }}
{{ 'Pattern.fast' | jsdoc }}
{{ 'Pattern.early' | jsdoc }}
{{ 'Pattern.late' | jsdoc }}
{{ 'Pattern.rev' | jsdoc }}
## Everything Else

View File

@ -694,11 +694,8 @@ If you want to contribute in another way, either
- [Join the Discord Channel](https://discord.gg/remJ6gQA)
- [play with the Strudel REPL](https://strudel.tidalcycles.org/)
import ApiDoc from './ApiDoc';
<br />
<br />
# API Docs
<ApiDoc />