This commit is contained in:
Felix Roos 2022-03-16 23:04:25 +01:00
parent d8d460f175
commit 4128213acb
13 changed files with 355 additions and 114 deletions

7
docs/dist/App.js vendored
View File

@ -1,6 +1,6 @@
import React, {useCallback, useLayoutEffect, useRef, useState} from "../_snowpack/pkg/react.js";
import * as Tone from "../_snowpack/pkg/tone.js";
import CodeMirror, {markEvent} from "./CodeMirror.js";
import CodeMirror, {markEvent, markParens} from "./CodeMirror.js";
import cx from "./cx.js";
import {evaluate} from "./evaluate.js";
import logo from "./logo.svg.proxy.js";
@ -68,6 +68,7 @@ function App() {
return /* @__PURE__ */ React.createElement("div", {
className: "min-h-screen flex flex-col"
}, /* @__PURE__ */ React.createElement("header", {
id: "header",
className: cx("flex-none w-full h-14 px-2 flex border-b border-gray-200 justify-between z-[10]", uiHidden ? "bg-transparent text-white" : "bg-white")
}, /* @__PURE__ */ React.createElement("div", {
className: "flex items-center space-x-2"
@ -116,7 +117,8 @@ function App() {
}, "👀 ", uiHidden ? "show ui" : "hide ui"))), /* @__PURE__ */ React.createElement("section", {
className: "grow flex flex-col text-gray-100"
}, /* @__PURE__ */ React.createElement("div", {
className: "grow relative"
className: "grow relative",
id: "code"
}, /* @__PURE__ */ React.createElement("div", {
className: cx("h-full transition-opacity", error ? "focus:ring-red-500" : "focus:ring-slate-800", uiHidden ? "opacity-0" : "opacity-100")
}, /* @__PURE__ */ React.createElement(CodeMirror, {
@ -129,6 +131,7 @@ function App() {
styleSelectedText: true,
cursorBlinkRate: 0
},
onCursor: markParens,
onChange: (_2, __, value) => setCode(value)
}), /* @__PURE__ */ React.createElement("span", {
className: "p-4 absolute top-0 right-0 text-xs whitespace-pre text-right pointer-events-none"

View File

@ -4,7 +4,7 @@ import "../_snowpack/pkg/codemirror/mode/javascript/javascript.js";
import "../_snowpack/pkg/codemirror/mode/pegjs/pegjs.js";
import "../_snowpack/pkg/codemirror/lib/codemirror.css.proxy.js";
import "../_snowpack/pkg/codemirror/theme/material.css.proxy.js";
export default function CodeMirror({value, onChange, options, editorDidMount}) {
export default function CodeMirror({value, onChange, onCursor, options, editorDidMount}) {
options = options || {
mode: "javascript",
theme: "material",
@ -16,7 +16,8 @@ export default function CodeMirror({value, onChange, options, editorDidMount}) {
value,
options,
onBeforeChange: onChange,
editorDidMount
editorDidMount,
onCursor: (editor, data) => onCursor?.(editor, data)
});
}
export const markEvent = (editor) => (time, event) => {
@ -24,8 +25,71 @@ export const markEvent = (editor) => (time, event) => {
if (!locs || !editor) {
return;
}
const marks = locs.map(({start, end}) => editor.getDoc().markText({line: start.line - 1, ch: start.column}, {line: end.line - 1, ch: end.column}, {css: "background-color: #FFCA28; color: black"}));
const marks = locs.map(({start, end}) => editor.getDoc().markText({line: start.line - 1, ch: start.column}, {line: end.line - 1, ch: end.column}, {css: "outline: 2px solid #FFCA28; box-sizing:border-box"}));
setTimeout(() => {
marks.forEach((mark) => mark.clear());
}, event.duration * 0.9 * 1e3);
}, event.duration * 1e3);
};
let parenMark;
export const markParens = (editor, data) => {
const v = editor.getDoc().getValue();
const marked = getCurrentParenArea(v, data);
parenMark?.clear();
parenMark = editor.getDoc().markText(...marked, {css: "background-color: #0000dd20"});
};
export function offsetToPosition(offset, code) {
const lines = code.split("\n");
let line = 0;
let ch = 0;
for (let i = 0; i < offset; i++) {
if (ch === lines[line].length) {
line++;
ch = 0;
} else {
ch++;
}
}
return {line, ch};
}
export function positionToOffset(position, code) {
const lines = code.split("\n");
let offset = 0;
for (let i = 0; i < position.line; i++) {
offset += lines[i].length + 1;
}
offset += position.ch;
return offset;
}
export function getCurrentParenArea(code, caretPosition) {
const caret = positionToOffset(caretPosition, code);
let open, i, begin, end;
i = caret;
open = 0;
while (i > 0) {
if (code[i - 1] === "(") {
open--;
} else if (code[i - 1] === ")") {
open++;
}
if (open === -1) {
break;
}
i--;
}
begin = i;
i = caret;
open = 0;
while (i < code.length) {
if (code[i] === "(") {
open--;
} else if (code[i] === ")") {
open++;
}
if (open === 1) {
break;
}
i++;
}
end = i;
return [begin, end].map((o) => offsetToPosition(o, code));
}

View File

@ -8,6 +8,7 @@ import "./tune.js";
import "./tune.js";
import "./pianoroll.js";
import "./draw.js";
import * as uiHelpers from "./ui.js";
import * as drawHelpers from "./draw.js";
import gist from "./gist.js";
import shapeshifter from "./shapeshifter.js";
@ -27,7 +28,7 @@ function hackLiteral(literal, names, func) {
}
hackLiteral(String, ["mini", "m"], bootstrapped.mini);
hackLiteral(String, ["pure", "p"], bootstrapped.pure);
Object.assign(globalThis, bootstrapped, Tone, toneHelpers, voicingHelpers, drawHelpers, {gist});
Object.assign(globalThis, bootstrapped, Tone, toneHelpers, voicingHelpers, drawHelpers, uiHelpers, {gist});
export const evaluate = async (code) => {
const shapeshifted = shapeshifter(code);
drawHelpers.cleanup();

2
docs/dist/tone.js vendored
View File

@ -36,7 +36,7 @@ Pattern.prototype.tone = function(instrument) {
break;
case "Piano":
note = getPlayableNoteValue(event2);
instrument.keyDown({note, time, velocity: 0.5});
instrument.keyDown({note, time, velocity});
instrument.keyUp({note, time: time + event2.duration, velocity});
break;
case "Sampler":

177
docs/dist/tunes.js vendored
View File

@ -265,63 +265,57 @@ export const technoDrums = `stack(
"~ x".tone(new Tone.NoiseSynth().toDestination()),
"[~ c4]*2".tone(new Tone.MetalSynth().set({envelope:{decay:0.06,sustain:0}}).chain(new Gain(0.5),getDestination()))
)`;
export const loungerave = `() => {
const delay = new FeedbackDelay(1/8, .2).chain(vol(0.5), out());
const kick = new MembraneSynth().chain(vol(.8), out());
const snare = new NoiseSynth().chain(vol(.8), out());
const hihat = new MetalSynth().set(adsr(0, .08, 0, .1)).chain(vol(.3).connect(delay),out());
const bass = new Synth().set({ ...osc('sawtooth'), ...adsr(0, .1, .4) }).chain(lowpass(900), vol(.5), out());
const keys = new PolySynth().set({ ...osc('sawtooth'), ...adsr(0, .5, .2, .7) }).chain(lowpass(1200), vol(.5), out());
const drums = stack(
"c1*2".tone(kick).mask("<x@7 ~>/8"),
"~ <x!7 [x@3 x]>".tone(snare).mask("<x@7 ~>/4"),
"[~ c4]*2".tone(hihat)
);
const thru = (x) => x.transpose("<0 1>/8").transpose(1);
const synths = stack(
"<C2 Bb1 Ab1 [G1 [G2 G1]]>/2".struct("[x [~ x] <[~ [~ x]]!3 [x x]>@2]/2").edit(thru).tone(bass),
"<Cm7 Bb7 Fm7 G7b9>/2".struct("~ [x@0.1 ~]").voicings().edit(thru).every(2, early(1/4)).tone(keys).mask("<x@7 ~>/8".early(1/4))
)
return stack(
drums,
synths
)
//.mask("<x ~>*4")
//.early("0.25 0");
}`;
export const caverave = `() => {
const delay = new FeedbackDelay(1/8, .4).chain(vol(0.5), out());
const kick = new MembraneSynth().chain(vol(.8), out());
const snare = new NoiseSynth().chain(vol(.8), out());
const hihat = new MetalSynth().set(adsr(0, .08, 0, .1)).chain(vol(.3).connect(delay),out());
const bass = new Synth().set({ ...osc('sawtooth'), ...adsr(0, .1, .4) }).chain(lowpass(900), vol(.5), out());
const keys = new PolySynth().set({ ...osc('sawtooth'), ...adsr(0, .5, .2, .7) }).chain(lowpass(1200), vol(.5), out());
const drums = stack(
"c1*2".tone(kick).mask("<x@7 ~>/8"),
"~ <x!7 [x@3 x]>".tone(snare).mask("<x@7 ~>/4"),
"[~ c4]*2".tone(hihat)
);
const thru = (x) => x.transpose("<0 1>/8").transpose(-1);
const synths = stack(
"<eb4 d4 c4 b3>/2".scale(timeCat([3,'C minor'],[1,'C melodic minor']).slow(8)).struct("[~ x]*2")
.edit(
scaleTranspose(0).early(0),
scaleTranspose(2).early(1/8),
scaleTranspose(7).early(1/4),
scaleTranspose(8).early(3/8)
).apply(thru).tone(keys).mask("<~ x>/16"),
"<C2 Bb1 Ab1 [G1 [G2 G1]]>/2".struct("[x [~ x] <[~ [~ x]]!3 [x x]>@2]/2".fast(2)).apply(thru).tone(bass),
"<Cm7 Bb7 Fm7 G7b13>/2".struct("~ [x@0.1 ~]".fast(2)).voicings().apply(thru).every(2, early(1/8)).tone(keys).mask("<x@7 ~>/8".early(1/4))
)
return stack(
drums.fast(2),
synths
).slow(2);
}`;
export const loungerave = `const delay = new FeedbackDelay(1/8, .2).chain(vol(0.5), out());
const kick = new MembraneSynth().chain(vol(.8), out());
const snare = new NoiseSynth().chain(vol(.8), out());
const hihat = new MetalSynth().set(adsr(0, .08, 0, .1)).chain(vol(.3).connect(delay),out());
const bass = new Synth().set({ ...osc('sawtooth'), ...adsr(0, .1, .4) }).chain(lowpass(900), vol(.5), out());
const keys = new PolySynth().set({ ...osc('sawtooth'), ...adsr(0, .5, .2, .7) }).chain(lowpass(1200), vol(.5), out());
const drums = stack(
"c1*2".tone(kick).mask("<x@7 ~>/8"),
"~ <x!7 [x@3 x]>".tone(snare).mask("<x@7 ~>/4"),
"[~ c4]*2".tone(hihat)
);
const thru = (x) => x.transpose("<0 1>/8").transpose(1);
const synths = stack(
"<C2 Bb1 Ab1 [G1 [G2 G1]]>/2".struct("[x [~ x] <[~ [~ x]]!3 [x x]>@2]/2").edit(thru).tone(bass),
"<Cm7 Bb7 Fm7 G7b9>/2".struct("~ [x@0.1 ~]").voicings().edit(thru).every(2, early(1/4)).tone(keys).mask("<x@7 ~>/8".early(1/4))
)
stack(
drums,
synths
)`;
export const caverave = `const delay = new FeedbackDelay(1/8, .4).chain(vol(0.5), out());
const kick = new MembraneSynth().chain(vol(.8), out());
const snare = new NoiseSynth().chain(vol(.8), out());
const hihat = new MetalSynth().set(adsr(0, .08, 0, .1)).chain(vol(.3).connect(delay),out());
const bass = new Synth().set({ ...osc('sawtooth'), ...adsr(0, .1, .4) }).chain(lowpass(900), vol(.5), out());
const keys = new PolySynth().set({ ...osc('sawtooth'), ...adsr(0, .5, .2, .7) }).chain(lowpass(1200), vol(.5), out());
const drums = stack(
"c1*2".tone(kick).mask("<x@7 ~>/8"),
"~ <x!7 [x@3 x]>".tone(snare).mask("<x@7 ~>/4"),
"[~ c4]*2".tone(hihat)
);
const thru = (x) => x.transpose("<0 1>/8").transpose(-1);
const synths = stack(
"<eb4 d4 c4 b3>/2".scale(timeCat([3,'C minor'],[1,'C melodic minor']).slow(8)).struct("[~ x]*2")
.edit(
scaleTranspose(0).early(0),
scaleTranspose(2).early(1/8),
scaleTranspose(7).early(1/4),
scaleTranspose(8).early(3/8)
).apply(thru).tone(keys).mask("<~ x>/16"),
"<C2 Bb1 Ab1 [G1 [G2 G1]]>/2".struct("[x [~ x] <[~ [~ x]]!3 [x x]>@2]/2".fast(2)).apply(thru).tone(bass),
"<Cm7 Bb7 Fm7 G7b13>/2".struct("~ [x@0.1 ~]".fast(2)).voicings().apply(thru).every(2, early(1/8)).tone(keys).mask("<x@7 ~>/8".early(1/4))
)
stack(
drums.fast(2),
synths
).slow(2)`;
export const callcenterhero = `()=>{
const bpm = 90;
const lead = polysynth().set({...osc('sine4'),...adsr(.004)}).chain(vol(0.15),out())
@ -489,31 +483,44 @@ export const wavyKalimba = `sampler({
.legato("<.4 .8 1 1.2 1.4 1.6 1.8 2>/8")
.fast(1)
})`;
export const jemblung = `() => {
const delay = new FeedbackDelay(1/8, .6).chain(vol(0.15), out());
const snare = noise({type:'white',...adsr(0,0.2,0)}).chain(lowpass(5000),vol(1.8),out());
const s = polysynth().set({...osc('sawtooth4'),...adsr(0.01,.2,.6,0.2)}).chain(vol(.23).connect(delay),out());
return stack(
stack(
"0 1 4 [3!2 5]".edit(
// chords
x=>x.add("0,3").duration("0.05!3 0.02"),
// bass
x=>x.add("-8").struct("x*8").duration(0.1)
),
// melody
"12 11*3 12 ~".duration(0.005)
)
.add("<0 1>")
.tune("jemblung2")
//.mul(22/5).round().xen("22edo")
//.mul(12/5).round().xen("12edo")
.tone(s),
// kick
"[c2 ~]*2".duration(0.05).tone(membrane().chain(out())),
// snare
"[~ c1]*2".early(0.001).tone(snare),
// hihat
"c2*8".tone(noise().chain(highpass(6000),vol(0.5).connect(delay),out())),
).slow(3)
}`;
export const jemblung = `const delay = new FeedbackDelay(1/8, .6).chain(vol(0.15), out());
const snare = noise({type:'white',...adsr(0,0.2,0)}).chain(lowpass(5000),vol(1.8),out());
const s = polysynth().set({...osc('sawtooth4'),...adsr(0.01,.2,.6,0.2)}).chain(vol(.23).connect(delay),out());
stack(
stack(
"0 1 4 [3!2 5]".edit(
// chords
x=>x.add("0,3").duration("0.05!3 0.02"),
// bass
x=>x.add("-8").struct("x*8").duration(0.1)
),
// melody
"12 11*3 12 ~".duration(0.005)
)
.add("<0 1>")
.tune("jemblung2")
//.mul(22/5).round().xen("22edo")
//.mul(12/5).round().xen("12edo")
.tone(s),
// kick
"[c2 ~]*2".duration(0.05).tone(membrane().chain(out())),
// snare
"[~ c1]*2".early(0.001).tone(snare),
// hihat
"c2*8".tone(noise().chain(highpass(6000),vol(0.5).connect(delay),out())),
).slow(3)`;
export const risingEnemy = `piano().then((p) =>
stack(
"2,6"
.scale('F3 dorian')
.transpose(sine2.struct("x*64").slow(4).mul(2).round())
.fast(2)
.struct("x x*3")
.legato(".9 .3"),
"0@3 -3*3".legato(".95@3 .4").scale('F2 dorian')
)
.transpose("<0 1 2 1>/2".early(0.5))
.transpose(5)
.fast(2 / 3)
.tone(p.toDestination())
)`;

36
docs/dist/ui.js vendored Normal file
View File

@ -0,0 +1,36 @@
import * as Tone from "../_snowpack/pkg/tone.js";
export const hideHeader = () => {
document.getElementById("header").style = "display:none";
};
function frame(callback) {
if (window.strudelAnimation) {
cancelAnimationFrame(window.strudelAnimation);
}
const animate = (animationTime) => {
const toneTime = Tone.getTransport().seconds;
callback(animationTime, toneTime);
window.strudelAnimation = requestAnimationFrame(animate);
};
requestAnimationFrame(animate);
}
export const backgroundImage = function(src, animateOptions) {
const container = document.getElementById("code");
const bg = "background-image:url(" + src + ");background-size:contain;";
container.style = bg;
const {className: initialClassName} = container;
const handleOption = (option, value) => {
({
style: () => container.style = bg + ";" + value,
className: () => container.className = value + " " + initialClassName
})[option]();
};
const funcOptions = Object.entries(animateOptions).filter(([_, v]) => typeof v === "function");
const stringOptions = Object.entries(animateOptions).filter(([_, v]) => typeof v === "string");
stringOptions.forEach(([option, value]) => handleOption(option, value));
if (funcOptions.length === 0) {
return;
}
frame((_, t) => funcOptions.forEach(([option, value]) => {
handleOption(option, value(t));
}));
};

View File

@ -1177,6 +1177,9 @@ select {
.opacity-100 {
opacity: 1;
}
.outline {
outline-style: solid;
}
.filter {
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
}
@ -1198,7 +1201,19 @@ body {
}
.CodeMirror-line > span {
background-color: #2a323690;
background-color: #2a323699;
}
.darken::before {
content: ' ';
position: absolute;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
display: block;
background: black;
opacity: 0.5;
}
.hover\:bg-slate-600:hover {

File diff suppressed because one or more lines are too long

View File

@ -41928,6 +41928,7 @@ var _xenMjs = require("./xen.mjs");
var _tuneMjs = require("./tune.mjs");
var _pianorollMjs = require("./pianoroll.mjs");
var _drawMjs = require("./draw.mjs");
var _uiMjs = require("./ui.mjs");
var _gistJs = require("./gist.js");
var _gistJsDefault = parcelHelpers.interopDefault(_gistJs);
var _shapeshifter = require("./shapeshifter");
@ -41959,7 +41960,7 @@ hackLiteral(String, [
'p'
], bootstrapped.pure); // comment out this line if you panic
// this will add everything to global scope, which is accessed by eval
Object.assign(globalThis, bootstrapped, _tone1, _tone, _voicings, _drawMjs, {
Object.assign(globalThis, bootstrapped, _tone1, _tone, _voicings, _drawMjs, _uiMjs, {
gist: _gistJsDefault.default
});
const evaluate = async (code)=>{
@ -41984,7 +41985,7 @@ const evaluate = async (code)=>{
};
};
},{"../../strudel.mjs":"ggZqJ","./tone":"aBpVm","./midi":"kToux","./voicings":"bexb4","./tonal.mjs":"j8DFK","./xen.mjs":"2MdCD","./tune.mjs":"ggPHE","./pianoroll.mjs":"6BZJ6","./draw.mjs":"dHJhg","./gist.js":"fYZxP","./shapeshifter":"67UCx","./parse":"dddDq","tone":"2tCfN","@parcel/transformer-js/src/esmodule-helpers.js":"gkKU3"}],"ggZqJ":[function(require,module,exports) {
},{"../../strudel.mjs":"ggZqJ","./tone":"aBpVm","./midi":"kToux","./voicings":"bexb4","./tonal.mjs":"j8DFK","./xen.mjs":"2MdCD","./tune.mjs":"ggPHE","./pianoroll.mjs":"6BZJ6","./draw.mjs":"dHJhg","./ui.mjs":"dezzj","./gist.js":"fYZxP","./shapeshifter":"67UCx","./parse":"dddDq","tone":"2tCfN","@parcel/transformer-js/src/esmodule-helpers.js":"gkKU3"}],"ggZqJ":[function(require,module,exports) {
var parcelHelpers = require("@parcel/transformer-js/src/esmodule-helpers.js");
parcelHelpers.defineInteropFlag(exports);
parcelHelpers.export(exports, "curry", ()=>curry
@ -56755,7 +56756,7 @@ Pattern.prototype.tone = function(instrument) {
instrument.keyDown({
note,
time,
velocity: 0.5
velocity
});
instrument.keyUp({
note,
@ -136276,7 +136277,52 @@ const cleanup = ()=>{
if (window.strudelScheduler) clearInterval(window.strudelScheduler);
};
},{"tone":"2tCfN","../../strudel.mjs":"ggZqJ","@parcel/transformer-js/src/esmodule-helpers.js":"gkKU3"}],"fYZxP":[function(require,module,exports) {
},{"tone":"2tCfN","../../strudel.mjs":"ggZqJ","@parcel/transformer-js/src/esmodule-helpers.js":"gkKU3"}],"dezzj":[function(require,module,exports) {
var parcelHelpers = require("@parcel/transformer-js/src/esmodule-helpers.js");
parcelHelpers.defineInteropFlag(exports);
parcelHelpers.export(exports, "hideHeader", ()=>hideHeader
);
parcelHelpers.export(exports, "backgroundImage", ()=>backgroundImage
);
var _tone = require("tone");
const hideHeader = ()=>{
document.getElementById('header').style = 'display:none';
};
function frame(callback) {
if (window.strudelAnimation) cancelAnimationFrame(window.strudelAnimation);
const animate = (animationTime)=>{
const toneTime = _tone.getTransport().seconds;
callback(animationTime, toneTime);
window.strudelAnimation = requestAnimationFrame(animate);
};
requestAnimationFrame(animate);
}
const backgroundImage = function(src, animateOptions) {
const container = document.getElementById('code');
const bg = 'background-image:url(' + src + ');background-size:contain;';
container.style = bg;
const { className: initialClassName } = container;
const handleOption = (option, value)=>{
({
style: ()=>container.style = bg + ';' + value
,
className: ()=>container.className = value + ' ' + initialClassName
})[option]();
};
const funcOptions = Object.entries(animateOptions).filter(([_, v])=>typeof v === 'function'
);
const stringOptions = Object.entries(animateOptions).filter(([_, v])=>typeof v === 'string'
);
stringOptions.forEach(([option, value])=>handleOption(option, value)
);
if (funcOptions.length === 0) return;
frame((_, t)=>funcOptions.forEach(([option, value])=>{
handleOption(option, value(t));
})
);
};
},{"tone":"2tCfN","@parcel/transformer-js/src/esmodule-helpers.js":"gkKU3"}],"fYZxP":[function(require,module,exports) {
var parcelHelpers = require("@parcel/transformer-js/src/esmodule-helpers.js");
parcelHelpers.defineInteropFlag(exports);
exports.default = (route)=>fetch(`https://gist.githubusercontent.com/${route}?cachebust=${Date.now()}`).then((res)=>res.text()
@ -171781,6 +171827,17 @@ var parcelHelpers = require("@parcel/transformer-js/src/esmodule-helpers.js");
parcelHelpers.defineInteropFlag(exports);
parcelHelpers.export(exports, "markEvent", ()=>markEvent
);
parcelHelpers.export(exports, "markParens", ()=>markParens
);
// returns { line, ch } from absolute character offset
parcelHelpers.export(exports, "offsetToPosition", ()=>offsetToPosition
);
// returns absolute character offset from { line, ch }
parcelHelpers.export(exports, "positionToOffset", ()=>positionToOffset
);
// given code and caret position, the functions returns the indices of the parens we are in
parcelHelpers.export(exports, "getCurrentParenArea", ()=>getCurrentParenArea
);
var _jsxRuntime = require("react/jsx-runtime");
var _react = require("react");
var _reactDefault = parcelHelpers.interopDefault(_react);
@ -171790,7 +171847,7 @@ var _pegjsJs = require("codemirror/mode/pegjs/pegjs.js");
// import 'codemirror/theme/material.css';
var _codemirrorCss = require("codemirror/lib/codemirror.css");
var _materialCss = require("codemirror/theme/material.css");
function CodeMirror({ value , onChange , options , editorDidMount }) {
function CodeMirror({ value , onChange , onCursor , options , editorDidMount }) {
options = options || {
mode: 'javascript',
theme: 'material',
@ -171802,7 +171859,8 @@ function CodeMirror({ value , onChange , options , editorDidMount }) {
value: value,
options: options,
onBeforeChange: onChange,
editorDidMount: editorDidMount
editorDidMount: editorDidMount,
onCursor: (editor, data)=>onCursor?.(editor, data)
}));
}
exports.default = CodeMirror;
@ -171816,8 +171874,9 @@ const markEvent = (editor)=>(time, event)=>{
}, {
line: end.line - 1,
ch: end.column
}, {
css: 'background-color: #FFCA28; color: black'
}, //{ css: 'background-color: #FFCA28; color: black' } // background-color is now used by parent marking
{
css: 'outline: 2px solid #FFCA28; box-sizing:border-box'
})
);
//Tone.Transport.schedule(() => { // problem: this can be cleared by scheduler...
@ -171825,13 +171884,67 @@ const markEvent = (editor)=>(time, event)=>{
marks.forEach((mark)=>mark.clear()
);
// }, '+' + event.duration * 0.5);
}, event.duration * 900);
}, event.duration /* * 0.9 */ * 1000);
}
; // idea: to improve highlighting, all patterns that appear anywhere in the code could be queried seperately
// the created events could then be used to highlight primitives as long as they are active
// this would create a less flickery output, with no duplications
// it would be seperated completely from the querying that happens to get the sound output
// it would also allow highlighting primitives that don't even end up in the sounding events (just for visual purposes)
;
let parenMark;
const markParens = (editor, data)=>{
const v = editor.getDoc().getValue();
const marked = getCurrentParenArea(v, data);
parenMark?.clear();
parenMark = editor.getDoc().markText(...marked, {
css: 'background-color: #0000dd20'
}); //
};
function offsetToPosition(offset, code) {
const lines = code.split('\n');
let line = 0;
let ch = 0;
for(let i = 0; i < offset; i++)if (ch === lines[line].length) {
line++;
ch = 0;
} else ch++;
return {
line,
ch
};
}
function positionToOffset(position, code) {
const lines = code.split('\n');
let offset = 0;
for(let i = 0; i < position.line; i++)offset += lines[i].length + 1;
offset += position.ch;
return offset;
}
function getCurrentParenArea(code, caretPosition) {
const caret = positionToOffset(caretPosition, code);
let open, i, begin, end;
// walk left
i = caret;
open = 0;
while(i > 0){
if (code[i - 1] === '(') open--;
else if (code[i - 1] === ')') open++;
if (open === -1) break;
i--;
}
begin = i;
// walk right
i = caret;
open = 0;
while(i < code.length){
if (code[i] === '(') open--;
else if (code[i] === ')') open++;
if (open === 1) break;
i++;
}
end = i;
return [
begin,
end
].map((o)=>offsetToPosition(o, code)
);
}
},{"react/jsx-runtime":"6AEwr","react":"21dqq","react-codemirror2":"l8gGc","codemirror/mode/javascript/javascript.js":"6YWC8","codemirror/mode/pegjs/pegjs.js":"ishmS","codemirror/lib/codemirror.css":"4uIDj","codemirror/theme/material.css":"5kHRb","@parcel/transformer-js/src/esmodule-helpers.js":"gkKU3"}],"l8gGc":[function(require,module,exports) {
'use strict';
@ -183050,4 +183163,4 @@ exports.default = cx;
},{"@parcel/transformer-js/src/esmodule-helpers.js":"gkKU3"}]},["3uVTb"], "3uVTb", "parcelRequire94c2")
//# sourceMappingURL=index.0eba8fed.js.map
//# sourceMappingURL=index.790bf3f2.js.map

File diff suppressed because one or more lines are too long

View File

@ -851,6 +851,8 @@ Ensure the default browser behavior of the `hidden` attribute.
opacity: 0;
}.opacity-100 {
opacity: 1;
}.outline {
outline-style: solid;
}.filter {
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
}.transition-opacity {
@ -1361,4 +1363,4 @@ span.CodeMirror-selectedtext { background: none; }
color: white !important;
}
/*# sourceMappingURL=index.4949a046.css.map */
/*# sourceMappingURL=index.c844960c.css.map */

File diff suppressed because one or more lines are too long

View File

@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<link rel="icon" href="/tutorial/favicon.e3ab9dd9.ico">
<link rel="stylesheet" type="text/css" href="/tutorial/index.4949a046.css">
<link rel="stylesheet" type="text/css" href="/tutorial/index.c844960c.css">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="Strudel REPL">
<title>Strudel Tutorial</title>
@ -11,6 +11,6 @@
<body>
<div id="root"></div>
<noscript>You need to enable JavaScript to run this app.</noscript>
<script src="/tutorial/index.0eba8fed.js" defer=""></script>
<script src="/tutorial/index.790bf3f2.js" defer=""></script>
</body>
</html>