Generating documentation using factory

This commit is contained in:
2023-08-25 12:36:37 +02:00
parent 94acee819a
commit 58c0a2cf66
3 changed files with 407 additions and 370 deletions

View File

@ -51,7 +51,7 @@ Array.prototype.in = function <T>(this: T[], value: T): boolean {
return this.includes(value); return this.includes(value);
}; };
async function loadSamples() { export async function loadSamples() {
// const ds = "https://raw.githubusercontent.com/felixroos/dough-samples/main/"; // const ds = "https://raw.githubusercontent.com/felixroos/dough-samples/main/";
return Promise.all([ return Promise.all([
initAudioOnFirstClick(), initAudioOnFirstClick(),
@ -62,8 +62,6 @@ async function loadSamples() {
]); ]);
} }
loadSamples();
export const generateCacheKey = (...args: any[]): string => { export const generateCacheKey = (...args: any[]): string => {
return args.map((arg) => JSON.stringify(arg)).join(","); return args.map((arg) => JSON.stringify(arg)).join(",");
}; };
@ -92,6 +90,10 @@ export class UserAPI {
//this.load = samples("github:tidalcycles/Dirt-Samples/master"); //this.load = samples("github:tidalcycles/Dirt-Samples/master");
} }
_all_samples = (): object => {
return soundMap.get();
};
_reportError = (error: any): void => { _reportError = (error: any): void => {
console.log(error); console.log(error);
clearTimeout(this.errorTimeoutID); clearTimeout(this.errorTimeoutID);

View File

@ -1,11 +1,41 @@
import { type Editor } from "./main";
const key_shortcut = (shortcut: string): string => { const key_shortcut = (shortcut: string): string => {
return `<kbd class="lg:px-2 lg:py-1.5 px-1 py-1 lg:text-sm text-xs font-semibold text-gray-800 bg-gray-100 border border-gray-200 rounded-lg dark:bg-gray-600 dark:text-gray-100 dark:border-gray-500">${shortcut}</kbd>`; return `<kbd class="lg:px-2 lg:py-1.5 px-1 py-1 lg:text-sm text-xs font-semibold text-gray-800 bg-gray-100 border border-gray-200 rounded-lg dark:bg-gray-600 dark:text-gray-100 dark:border-gray-500">${shortcut}</kbd>`;
}; };
const injectAvailableSamples = (): string => { const samples_to_markdown = (samples: object) => {
return ""; let markdownList = "";
let keys = Object.keys(samples);
let i = -1;
while (i++ < keys.length - 1) {
//@ts-ignore
if (!samples[keys[i]].data) continue;
//@ts-ignore
if (!samples[keys[i]].data.samples) continue;
markdownList += `**${keys[i]}** (_${
//@ts-ignore
samples[keys[i]].data.samples.length
}_) `;
// let i2 = -1;
// while (i2++ < samples[keys[i]].data.samples.length - 1) {
// console.log(samples[keys[i]].data.samples[i2]);
// markdownList += `\t- <audio controls> <source src="${
// samples[keys[i]].data.samples[i2]
// }" type="audio/wav">\n
// </audio>
// `;
// }
}
return markdownList;
}; };
const injectAvailableSamples = (application: Editor): string => {
let test = samples_to_markdown(application.api._all_samples());
return test;
};
export const documentation_factory = (application: Editor) => {
const introduction: string = ` const introduction: string = `
# Welcome # Welcome
@ -27,7 +57,6 @@ Press ${key_shortcut(
)} to switch to the global file. This is where everything starts! Evaluate the following script there by pasting and pressing ${key_shortcut( )} to switch to the global file. This is where everything starts! Evaluate the following script there by pasting and pressing ${key_shortcut(
"Ctrl + Enter" "Ctrl + Enter"
)}. You are now making music: )}. You are now making music:
<pre><code class="language-javascript"> <pre><code class="language-javascript">
bpm(80) bpm(80)
mod(0.25) :: sound('sawtooth') mod(0.25) :: sound('sawtooth')
@ -318,7 +347,6 @@ mod(0.25) && midi(60)
"Ctrl + Shift + I" "Ctrl + Shift + I"
)} in many web browsers. )} in many web browsers.
- <icode>midi_output(output_name: string)</icode>: Selects the MIDI output to use. You can use the <icode>midi_outputs()</icode> function to get a list of available MIDI outputs first. If the MIDI output is not available, the function will do nothing and keep on with the currently selected MIDI Port. - <icode>midi_output(output_name: string)</icode>: Selects the MIDI output to use. You can use the <icode>midi_outputs()</icode> function to get a list of available MIDI outputs first. If the MIDI output is not available, the function will do nothing and keep on with the currently selected MIDI Port.
`; `;
const sound: string = ` const sound: string = `
@ -547,9 +575,13 @@ mod(.5)::snd('pad').crush(divseq(2, 16, 8, 4)).clip(.5).out()
const samples: string = ` const samples: string = `
# Audio Samples # Audio Samples
Audio samples are dynamically loaded from the web. By default, Topos is providing some samples coming from the classic [Dirt-Samples](https://github.com/tidalcycles/Dirt-Samples) but also from the [Topos-Samples](https://github.com/Bubobubobubobubo/Topos-Samples) repository. You can contribute to the latter if you want to share your samples with the community! For each sample folder, we are indicating how many of them are available in parentheses.
- **sample_folder** (_how_many_)
## Available audio samples ## Available audio samples
${injectAvailableSamples()} ${injectAvailableSamples(application)}
`; `;
@ -676,8 +708,6 @@ You will often need to use iterators and/or counters to index over data structur
- <icode>drunk_min(min: number)</icode>: sets the minimum value. - <icode>drunk_min(min: number)</icode>: sets the minimum value.
- <icode>drunk_wrap(wrap: boolean)</icode>: whether to wrap the drunk walk to 0 once the upper limit is reached or not. - <icode>drunk_wrap(wrap: boolean)</icode>: whether to wrap the drunk walk to 0 once the upper limit is reached or not.
## Scripts ## Scripts
You can control scripts programatically. This is the core concept of Topos after all! You can control scripts programatically. This is the core concept of Topos after all!
@ -769,8 +799,6 @@ Chance operators returning a boolean value are also available:
- <icode>delay(ms: number, func: Function): void</icode>: Delays the execution of a function by a given number of milliseconds. - <icode>delay(ms: number, func: Function): void</icode>: Delays the execution of a function by a given number of milliseconds.
- <icode>delayr(ms: number, nb: number, func: Function): void</icode>: Delays the execution of a function by a given number of milliseconds, repeated a given number of times. - <icode>delayr(ms: number, nb: number, func: Function): void</icode>: Delays the execution of a function by a given number of milliseconds, repeated a given number of times.
`; `;
const reference: string = ` const reference: string = `
@ -814,7 +842,7 @@ Topos is made to be controlled entirely with a keyboard. It is recommanded to st
- Switch the editor to Vim Mode: ${key_shortcut("Ctrl + V")}. - Switch the editor to Vim Mode: ${key_shortcut("Ctrl + V")}.
`; `;
export const documentation = { return {
introduction: introduction, introduction: introduction,
interface: software_interface, interface: software_interface,
code: code, code: code,
@ -829,3 +857,4 @@ export const documentation = {
shortcuts: shortcuts, shortcuts: shortcuts,
about: about, about: about,
}; };
};

View File

@ -14,10 +14,10 @@ import { indentWithTab } from "@codemirror/commands";
import { vim } from "@replit/codemirror-vim"; import { vim } from "@replit/codemirror-vim";
import { AppSettings, Universe } from "./AppSettings"; import { AppSettings, Universe } from "./AppSettings";
import { editorSetup } from "./EditorSetup"; import { editorSetup } from "./EditorSetup";
import { documentation } from "./Documentation"; import { documentation_factory } from "./Documentation";
import { EditorView } from "codemirror"; import { EditorView } from "codemirror";
import { Clock } from "./Clock"; import { Clock } from "./Clock";
import { UserAPI } from "./API"; import { loadSamples, UserAPI } from "./API";
import "./style.css"; import "./style.css";
import { import {
Universes, Universes,
@ -27,9 +27,6 @@ import {
} from "./AppSettings"; } from "./AppSettings";
import { tryEvaluate } from "./Evaluator"; import { tryEvaluate } from "./Evaluator";
type Documentation = { [key: string]: string };
const Docs: Documentation = documentation;
// Importing showdown and setting up the markdown converter // Importing showdown and setting up the markdown converter
import showdown from "showdown"; import showdown from "showdown";
showdown.setFlavor("github"); showdown.setFlavor("github");
@ -78,6 +75,7 @@ export class Editor {
userPlugins: Extension[] = []; userPlugins: Extension[] = [];
state: EditorState; state: EditorState;
api: UserAPI; api: UserAPI;
docs: { [key: string]: string } = {};
// Audio stuff // Audio stuff
audioContext: AudioContext; audioContext: AudioContext;
@ -236,6 +234,13 @@ export class Editor {
let dynamicPlugins = new Compartment(); let dynamicPlugins = new Compartment();
// ================================================================================
// Building the documentation
loadSamples().then(() => {
this.docs = documentation_factory(this);
});
// ================================================================================
// ================================================================================ // ================================================================================
// Application event listeners // Application event listeners
// ================================================================================ // ================================================================================
@ -662,10 +667,11 @@ export class Editor {
const converter = new showdown.Converter({ const converter = new showdown.Converter({
emoji: true, emoji: true,
moreStyling: true, moreStyling: true,
backslashEscapesHTMLTags: true,
extensions: [showdownHighlight({ auto_detection: true }), ...bindings], extensions: [showdownHighlight({ auto_detection: true }), ...bindings],
}); });
const converted_markdown = converter.makeHtml( const converted_markdown = converter.makeHtml(
Docs[this.currentDocumentationPane] this.docs[this.currentDocumentationPane]
); );
function wrapCodeWithPre(inputString: string): string { function wrapCodeWithPre(inputString: string): string {
let newString = inputString.replace(/<code>/g, "<pre><code>"); let newString = inputString.replace(/<code>/g, "<pre><code>");