throw out nunjucks

This commit is contained in:
Felix Roos 2022-12-19 20:48:57 +01:00
parent bf373d894d
commit 0a9604d10e
7 changed files with 268 additions and 205 deletions

View File

@ -1147,7 +1147,7 @@ export function slowcatPrime(...pats) {
/** Concatenation: as with {@link slowcat}, but squashes a cycle from each pattern into one cycle /** Concatenation: as with {@link slowcat}, but squashes a cycle from each pattern into one cycle
* *
* Synonyms: {@link seq}, {@link sequence} * Synonyms: {@link Pattern.seq}, {@link Pattern.sequence}
* *
* @param {...any} items - The items to concatenate * @param {...any} items - The items to concatenate
* @return {Pattern} * @return {Pattern}
@ -1172,7 +1172,7 @@ export function cat(...pats) {
return slowcat(...pats); return slowcat(...pats);
} }
/** Like {@link seq}, but each step has a length, relative to the whole. /** Like {@link Pattern.seq}, but each step has a length, relative to the whole.
* @return {Pattern} * @return {Pattern}
* @example * @example
* timeCat([3,e3],[1, g3]).note() // "e3@3 g3".note() * timeCat([3,e3],[1, g3]).note() // "e3@3 g3".note()

39
tutorial/JsDoc.jsx Normal file
View File

@ -0,0 +1,39 @@
import jsdoc from '../doc.json'; // doc.json is built with `npm run jsdoc-json`
const docs = jsdoc.docs.reduce((acc, obj) => Object.assign(acc, { [obj.longname]: obj }), {});
import { MiniRepl } from './MiniRepl';
export function JsDoc({ name, h = 3 }) {
const item = docs[name];
if (!item) {
console.warn('Not found: ' + name);
return <div />;
}
const CustomHeading = `h${h}`;
const description = 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>`;
});
return (
<>
{!!h && <CustomHeading>{item.longname}</CustomHeading>}
<div dangerouslySetInnerHTML={{ __html: description }} />
<ul>
{item.params?.map((param, i) => (
<li key={i}>
{param.name} ({param.type?.names?.join('|')}): {param.description?.replace(/(<([^>]+)>)/gi, '')}
</li>
))}
</ul>
{item.examples?.length ? (
<div className="space-y-2">
{item.examples?.map((example, k) => (
<MiniRepl tune={example} key={k} />
))}
</div>
) : (
<div />
)}
</>
);
}

View File

@ -6,7 +6,7 @@ This program is free software: you can redistribute it and/or modify it under th
import React from 'react'; import React from 'react';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import Tutorial from './tutorial.rendered.mdx'; import Tutorial from './tutorial.mdx';
// import ApiDoc from './ApiDoc'; // import ApiDoc from './ApiDoc';
import './style.scss'; import './style.scss';
import '@strudel.cycles/react/dist/style.css'; import '@strudel.cycles/react/dist/style.css';

View File

@ -21,7 +21,6 @@
"autoprefixer": "^10.4.7", "autoprefixer": "^10.4.7",
"install": "^0.13.0", "install": "^0.13.0",
"npm": "^8.10.0", "npm": "^8.10.0",
"nunjucks": "^3.2.3",
"postcss": "^8.4.13", "postcss": "^8.4.13",
"rehype-autolink-headings": "^6.1.1", "rehype-autolink-headings": "^6.1.1",
"rehype-slug": "^5.0.1", "rehype-slug": "^5.0.1",
@ -796,12 +795,6 @@
"semver": "bin/semver.js" "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": { "node_modules/acorn": {
"version": "7.4.1", "version": "7.4.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
@ -865,12 +858,6 @@
"integrity": "sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA==", "integrity": "sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA==",
"dev": true "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": { "node_modules/autoprefixer": {
"version": "10.4.7", "version": "10.4.7",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.7.tgz", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.7.tgz",
@ -1159,15 +1146,6 @@
"url": "https://github.com/sponsors/wooorm" "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": { "node_modules/convert-source-map": {
"version": "1.8.0", "version": "1.8.0",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz",
@ -4847,31 +4825,6 @@
"inBundle": true, "inBundle": true,
"license": "ISC" "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": { "node_modules/object-assign": {
"version": "4.1.1", "version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
@ -7039,12 +6992,6 @@
} }
} }
}, },
"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": { "acorn": {
"version": "7.4.1", "version": "7.4.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
@ -7093,12 +7040,6 @@
"integrity": "sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA==", "integrity": "sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA==",
"dev": true "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": { "autoprefixer": {
"version": "10.4.7", "version": "10.4.7",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.7.tgz", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.7.tgz",
@ -7283,12 +7224,6 @@
"integrity": "sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==", "integrity": "sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==",
"dev": true "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": { "convert-source-map": {
"version": "1.8.0", "version": "1.8.0",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz",
@ -9805,17 +9740,6 @@
} }
} }
}, },
"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": { "object-assign": {
"version": "4.1.1", "version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",

View File

@ -8,7 +8,7 @@
"build": "npm run render && vite build", "build": "npm run render && vite build",
"preview": "vite preview", "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 > tutorial.rendered.mdx" "render": "npm run jsdoc-json"
}, },
"type": "module", "type": "module",
"dependencies": { "dependencies": {
@ -25,7 +25,6 @@
"autoprefixer": "^10.4.7", "autoprefixer": "^10.4.7",
"install": "^0.13.0", "install": "^0.13.0",
"npm": "^8.10.0", "npm": "^8.10.0",
"nunjucks": "^3.2.3",
"postcss": "^8.4.13", "postcss": "^8.4.13",
"rehype-autolink-headings": "^6.1.1", "rehype-autolink-headings": "^6.1.1",
"rehype-slug": "^5.0.1", "rehype-slug": "^5.0.1",

View File

@ -1,48 +0,0 @@
import nunjucks from 'nunjucks';
import { readFile } from 'node:fs/promises';
import { fileURLToPath } from 'url';
import { dirname } from 'path';
const __dirname = dirname(fileURLToPath(import.meta.url));
const jsdoc = JSON.parse(await readFile(`${__dirname}/../doc.json`, 'utf8'));
// import jsdoc from '../doc.json' assert { type: 'json' }; // node 18
const env = nunjucks.configure('.', { 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
?.map(
(param, i) =>
`- ${param.name} (${param.type?.names?.join('|')}): ${param.description?.replace(/(<([^>]+)>)/gi, '')}`,
)
.join('\n') || ''
}
${
item.examples?.length
? `
<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('tutorial.mdx', { docs });
console.log(rendered);

View File

@ -1,4 +1,5 @@
import { MiniRepl } from './MiniRepl'; import { MiniRepl } from './MiniRepl';
import { JsDoc } from './JsDoc';
# Table of Contents # Table of Contents
@ -407,43 +408,77 @@ The sampler will always pick the closest matching sample for the current note!
## Sampler Effects ## Sampler Effects
{{ 'Pattern.begin' | jsdoc }} ### Pattern.begin
{{ 'Pattern.end' | jsdoc }} <JsDoc name="Pattern.begin" h={0} />
{{ 'Pattern.loopAt' | jsdoc }} ### Pattern.end
{{ 'Pattern.chop' | jsdoc }} <JsDoc name="Pattern.end" h={0} />
### Pattern.loopAt
<JsDoc name="Pattern.loopAt" h={0} />
### Pattern.chop
<JsDoc name="Pattern.chop" h={0} />
## Audio Effects ## Audio Effects
Wether you're using a synth or a sample, you can apply these effects: Wether you're using a synth or a sample, you can apply these effects:
{{ 'gain' | jsdoc }} ### gain
{{ 'velocity' | jsdoc }} <JsDoc name="gain" h={0} />
{{ 'cutoff' | jsdoc }} ### velocity
{{ 'resonance' | jsdoc }} <JsDoc name="velocity" h={0} />
{{ 'hcutoff' | jsdoc }} ### cutoff
{{ 'hresonance' | jsdoc }} <JsDoc name="cutoff" h={0} />
{{ 'bandf' | jsdoc }} ### resonance
{{ 'bandq' | jsdoc }} <JsDoc name="resonance" h={0} />
{{ 'vowel' | jsdoc }} ### hcutoff
{{ 'pan' | jsdoc }} <JsDoc name="hcutoff" h={0} />
{{ 'coarse' | jsdoc }} ### hresonance
{{ 'shape' | jsdoc }} <JsDoc name="hresonance" h={0} />
{{ 'crush' | jsdoc }} ### bandf
<JsDoc name="bandf" h={0} />
### bandq
<JsDoc name="bandq" h={0} />
### vowel
<JsDoc name="vowel" h={0} />
### pan
<JsDoc name="pan" h={0} />
### coarse
<JsDoc name="coarse" h={0} />
### shape
<JsDoc name="shape" h={0} />
### crush
<JsDoc name="crush" h={0} />
<br /> <br />
@ -508,18 +543,28 @@ You can use this with any function that declares a type (like `n`, `s`, `note`,
The following functions will return a pattern. The following functions will return a pattern.
<!-- <!--
{{ 'pure' | jsdoc }} ### pure
<JsDoc name="pure" h={0} />
Most of the time, you won't need that function as input values of pattern creating functions are purified by default. Most of the time, you won't need that function as input values of pattern creating functions are purified by default.
--> -->
{{ 'cat' | jsdoc }} ### cat
{{ 'seq' | jsdoc }} <JsDoc name="cat" h={0} />
{{ 'stack' | jsdoc }} ### seq
{{ 'timeCat' | jsdoc }} <JsDoc name="seq" h={0} />
### stack
<JsDoc name="stack" h={0} />
### timeCat
<JsDoc name="timeCat" h={0} />
<!-- ## polymeter <!-- ## polymeter
@ -580,132 +625,234 @@ When using JS patterns, there is a lot more you can do.
The following functions modify a pattern temporal structure in some way. The following functions modify a pattern temporal structure in some way.
{{ 'Pattern.slow' | jsdoc }} ### Pattern.slow
{{ 'Pattern.fast' | jsdoc }} <JsDoc name="Pattern.slow" h={0} />
{{ 'Pattern.early' | jsdoc }} ### Pattern.fast
{{ 'Pattern.late' | jsdoc }} <JsDoc name="Pattern.fast" h={0} />
{{ 'Pattern.legato' | jsdoc }} ### Pattern.early
{{ 'Pattern.struct' | jsdoc }} <JsDoc name="Pattern.early" h={0} />
{{ 'Pattern.euclid' | jsdoc }} ### Pattern.late
{{ 'Pattern.euclidLegato' | jsdoc }} <JsDoc name="Pattern.late" h={0} />
{{ 'Pattern.rev' | jsdoc }} ### Pattern.legato
{{ 'Pattern.iter' | jsdoc }} <JsDoc name="Pattern.legato" h={0} />
{{ 'Pattern.iterBack' | jsdoc }} ### Pattern.struct
<JsDoc name="Pattern.struct" h={0} />
### Pattern.euclid
<JsDoc name="Pattern.euclid" h={0} />
### Pattern.euclidLegato
<JsDoc name="Pattern.euclidLegato" h={0} />
### Pattern.rev
<JsDoc name="Pattern.rev" h={0} />
### Pattern.iter
<JsDoc name="Pattern.iter" h={0} />
### Pattern.iterBack
<JsDoc name="Pattern.iterBack" h={0} />
## Conditional Modifiers ## Conditional Modifiers
{{ 'Pattern.every' | jsdoc }} ### Pattern.every
{{ 'Pattern.each' | jsdoc }} <JsDoc name="Pattern.every" h={0} />
{{ 'Pattern.when' | jsdoc }} ### Pattern.when
<JsDoc name="Pattern.when" h={0} />
## Accumulation Modifiers ## Accumulation Modifiers
{{ 'Pattern.stack' | jsdoc }} ### Pattern.stack
{{ 'Pattern.superimpose' | jsdoc }} <JsDoc name="Pattern.stack" h={0} />
{{ 'Pattern.layer' | jsdoc }} ### Pattern.superimpose
{{ 'Pattern.off' | jsdoc }} <JsDoc name="Pattern.superimpose" h={0} />
{{ 'Pattern.echo' | jsdoc }} ### Pattern.layer
{{ 'Pattern.echoWith' | jsdoc }} <JsDoc name="Pattern.layer" h={0} />
### Pattern.off
<JsDoc name="Pattern.off" h={0} />
### Pattern.echo
<JsDoc name="Pattern.echo" h={0} />
### Pattern.echoWith
<JsDoc name="Pattern.echoWith" h={0} />
## Concat Modifiers ## Concat Modifiers
{{ 'Pattern.seq' | jsdoc }} ### Pattern.seq
{{ 'Pattern.cat' | jsdoc }} <JsDoc name="Pattern.seq" h={0} />
### Pattern.cat
<JsDoc name="Pattern.cat" h={0} />
## Value Modifiers ## Value Modifiers
{{ 'Pattern.add' | jsdoc }} ### Pattern.add
{{ 'Pattern.sub' | jsdoc }} <JsDoc name="Pattern.add" h={0} />
{{ 'Pattern.mul' | jsdoc }} ### Pattern.sub
{{ 'Pattern.div' | jsdoc }} <JsDoc name="Pattern.sub" h={0} />
{{ 'Pattern.round' | jsdoc }} ### Pattern.mul
{{ 'Pattern.apply' | jsdoc }} <JsDoc name="Pattern.mul" h={0} />
{{ 'Pattern.range' | jsdoc }} ### Pattern.div
{{ 'Pattern.chunk' | jsdoc }} <JsDoc name="Pattern.div" h={0} />
{{ 'Pattern.chunkBack' | jsdoc }} ### Pattern.round
<JsDoc name="Pattern.round" h={0} />
### Pattern.apply
<JsDoc name="Pattern.apply" h={0} />
### Pattern.range
<JsDoc name="Pattern.range" h={0} />
### Pattern.chunk
<JsDoc name="Pattern.chunk" h={0} />
### Pattern.chunkBack
<JsDoc name="Pattern.chunkBack" h={0} />
## Continuous Signals ## Continuous Signals
Signals are patterns with continuous values, meaning they have theoretically infinite steps. Signals are patterns with continuous values, meaning they have theoretically infinite steps.
They can provide streams of numbers that can be sampled at discrete points in time. They can provide streams of numbers that can be sampled at discrete points in time.
{{ 'saw' | jsdoc }} ### saw
{{ 'sine' | jsdoc }} <JsDoc name="saw" h={0} />
{{ 'cosine' | jsdoc }} ### sine
{{ 'tri' | jsdoc }} <JsDoc name="sine" h={0} />
{{ 'square' | jsdoc }} ### cosine
<JsDoc name="cosine" h={0} />
### tri
<JsDoc name="tri" h={0} />
### square
<JsDoc name="square" h={0} />
### Ranges from -1 to 1 ### Ranges from -1 to 1
There is also `saw2`, `sine2`, `cosine2`, `tri2` and `square2` which have a range from -1 to 1! There is also `saw2`, `sine2`, `cosine2`, `tri2` and `square2` which have a range from -1 to 1!
{{ 'rand' | jsdoc }} ### rand
{{ 'perlin' | jsdoc }} <JsDoc name="rand" h={0} />
{{ 'irand' | jsdoc }} ### perlin
<JsDoc name="perlin" h={0} />
### irand
<JsDoc name="irand" h={0} />
## Random Modifiers ## Random Modifiers
These methods add random behavior to your Patterns. These methods add random behavior to your Patterns.
{{ 'chooseCycles' | jsdoc }} ### chooseCycles
{{ 'Pattern.degradeBy' | jsdoc }} <JsDoc name="chooseCycles" h={0} />
{{ 'Pattern.degrade' | jsdoc }} ### Pattern.degradeBy
{{ 'Pattern.undegradeBy' | jsdoc }} <JsDoc name="Pattern.degradeBy" h={0} />
{{ 'Pattern.sometimesBy' | jsdoc }} ### Pattern.degrade
{{ 'Pattern.sometimes' | jsdoc }} <JsDoc name="Pattern.degrade" h={0} />
{{ 'Pattern.someCyclesBy' | jsdoc }} ### Pattern.undegradeBy
{{ 'Pattern.someCycles' | jsdoc }} <JsDoc name="Pattern.undegradeBy" h={0} />
{{ 'Pattern.often' | jsdoc }} ### Pattern.sometimesBy
{{ 'Pattern.rarely' | jsdoc }} <JsDoc name="Pattern.sometimesBy" h={0} />
{{ 'Pattern.almostNever' | jsdoc }} ### Pattern.sometimes
{{ 'Pattern.almostAlways' | jsdoc }} <JsDoc name="Pattern.sometimes" h={0} />
{{ 'Pattern.never' | jsdoc }} ### Pattern.someCyclesBy
{{ 'Pattern.always' | jsdoc }} <JsDoc name="Pattern.someCyclesBy" h={0} />
### Pattern.someCycles
<JsDoc name="Pattern.someCycles" h={0} />
### Pattern.often
<JsDoc name="Pattern.often" h={0} />
### Pattern.rarely
<JsDoc name="Pattern.rarely" h={0} />
### Pattern.almostNever
<JsDoc name="Pattern.almostNever" h={0} />
### Pattern.almostAlways
<JsDoc name="Pattern.almostAlways" h={0} />
### Pattern.never
<JsDoc name="Pattern.never" h={0} />
### Pattern.always
<JsDoc name="Pattern.always" h={0} />
<br /> <br />
<br /> <br />
@ -822,7 +969,9 @@ Now you're all set!
If you now hear sound, congratulations! If not, you can get help on the [#strudel channel in the TidalCycles discord](https://discord.com/invite/HGEdXmRkzT). If you now hear sound, congratulations! If not, you can get help on the [#strudel channel in the TidalCycles discord](https://discord.com/invite/HGEdXmRkzT).
{{ 'Pattern.osc' | jsdoc }} ### Pattern.osc
<JsDoc name="Pattern.osc" h={0} />
## Superdirt Params ## Superdirt Params