mirror of
https://github.com/eliasstepanik/strudel-docker.git
synced 2026-01-19 17:48:33 +00:00
commit
466574a856
@ -3,7 +3,7 @@ import { closeBrackets } from '@codemirror/autocomplete';
|
|||||||
import { history } from '@codemirror/commands';
|
import { history } from '@codemirror/commands';
|
||||||
import { javascript } from '@codemirror/lang-javascript';
|
import { javascript } from '@codemirror/lang-javascript';
|
||||||
import { defaultHighlightStyle, syntaxHighlighting } from '@codemirror/language';
|
import { defaultHighlightStyle, syntaxHighlighting } from '@codemirror/language';
|
||||||
import { Compartment, EditorState } from '@codemirror/state';
|
import { Compartment, EditorState, Prec } from '@codemirror/state';
|
||||||
import { EditorView, highlightActiveLineGutter, highlightActiveLine, keymap, lineNumbers } from '@codemirror/view';
|
import { EditorView, highlightActiveLineGutter, highlightActiveLine, keymap, lineNumbers } from '@codemirror/view';
|
||||||
import { Pattern, Drawer, repl, cleanupDraw } from '@strudel.cycles/core';
|
import { Pattern, Drawer, repl, cleanupDraw } from '@strudel.cycles/core';
|
||||||
// import { isAutoCompletionEnabled } from './Autocomplete';
|
// import { isAutoCompletionEnabled } from './Autocomplete';
|
||||||
@ -44,27 +44,28 @@ export function initEditor({ initialCode = '', onChange, onEvaluate, onStop, set
|
|||||||
syntaxHighlighting(defaultHighlightStyle),
|
syntaxHighlighting(defaultHighlightStyle),
|
||||||
history(),
|
history(),
|
||||||
EditorView.updateListener.of((v) => onChange(v)),
|
EditorView.updateListener.of((v) => onChange(v)),
|
||||||
keymap.of([
|
Prec.highest(
|
||||||
{
|
keymap.of([
|
||||||
key: 'Ctrl-Enter',
|
{
|
||||||
run: () => onEvaluate?.(),
|
key: 'Ctrl-Enter',
|
||||||
},
|
run: () => onEvaluate?.(),
|
||||||
{
|
|
||||||
key: 'Alt-Enter',
|
|
||||||
run: () => onEvaluate?.(),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'Ctrl-.',
|
|
||||||
run: () => onStop?.(),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'Alt-.',
|
|
||||||
run: (_, e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
onStop?.();
|
|
||||||
},
|
},
|
||||||
},
|
{
|
||||||
/* {
|
key: 'Alt-Enter',
|
||||||
|
run: () => onEvaluate?.(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'Ctrl-.',
|
||||||
|
run: () => onStop?.(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'Alt-.',
|
||||||
|
run: (_, e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
onStop?.();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
/* {
|
||||||
key: 'Ctrl-Shift-.',
|
key: 'Ctrl-Shift-.',
|
||||||
run: () => (onPanic ? onPanic() : onStop?.()),
|
run: () => (onPanic ? onPanic() : onStop?.()),
|
||||||
},
|
},
|
||||||
@ -72,7 +73,8 @@ export function initEditor({ initialCode = '', onChange, onEvaluate, onStop, set
|
|||||||
key: 'Ctrl-Shift-Enter',
|
key: 'Ctrl-Shift-Enter',
|
||||||
run: () => (onReEvaluate ? onReEvaluate() : onEvaluate?.()),
|
run: () => (onReEvaluate ? onReEvaluate() : onEvaluate?.()),
|
||||||
}, */
|
}, */
|
||||||
]),
|
]),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -150,6 +152,11 @@ export class StrudelMirror {
|
|||||||
onEvaluate: () => this.evaluate(),
|
onEvaluate: () => this.evaluate(),
|
||||||
onStop: () => this.stop(),
|
onStop: () => this.stop(),
|
||||||
});
|
});
|
||||||
|
const cmEditor = this.root.querySelector('.cm-editor');
|
||||||
|
if (cmEditor) {
|
||||||
|
this.root.style.backgroundColor = 'var(--background)';
|
||||||
|
cmEditor.style.backgroundColor = 'transparent';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
async drawFirstFrame() {
|
async drawFirstFrame() {
|
||||||
if (!this.onDraw) {
|
if (!this.onDraw) {
|
||||||
@ -190,6 +197,10 @@ export class StrudelMirror {
|
|||||||
}
|
}
|
||||||
setFontFamily(family) {
|
setFontFamily(family) {
|
||||||
this.root.style.fontFamily = family;
|
this.root.style.fontFamily = family;
|
||||||
|
const scroller = this.root.querySelector('.cm-scroller');
|
||||||
|
if (scroller) {
|
||||||
|
scroller.style.fontFamily = family;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
reconfigureExtension(key, value) {
|
reconfigureExtension(key, value) {
|
||||||
if (!extensions[key]) {
|
if (!extensions[key]) {
|
||||||
|
|||||||
@ -2,3 +2,4 @@ export * from './codemirror.mjs';
|
|||||||
export * from './highlight.mjs';
|
export * from './highlight.mjs';
|
||||||
export * from './flash.mjs';
|
export * from './flash.mjs';
|
||||||
export * from './slider.mjs';
|
export * from './slider.mjs';
|
||||||
|
export * from './themes.mjs';
|
||||||
|
|||||||
39
packages/codemirror/themes.mjs
vendored
39
packages/codemirror/themes.mjs
vendored
@ -473,6 +473,9 @@ function stringifySafe(json) {
|
|||||||
return JSON.stringify(json, getCircularReplacer());
|
return JSON.stringify(json, getCircularReplacer());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const theme = (theme) => themes[theme] || themes.strudelTheme;
|
||||||
|
|
||||||
|
// css style injection helpers
|
||||||
export function injectStyle(rule) {
|
export function injectStyle(rule) {
|
||||||
const newStyle = document.createElement('style');
|
const newStyle = document.createElement('style');
|
||||||
document.head.appendChild(newStyle);
|
document.head.appendChild(newStyle);
|
||||||
@ -481,4 +484,38 @@ export function injectStyle(rule) {
|
|||||||
return () => styleSheet.deleteRule(ruleIndex);
|
return () => styleSheet.deleteRule(ruleIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const theme = (theme) => themes[theme] || themes.strudelTheme;
|
let currentTheme, resetThemeStyle, themeStyle;
|
||||||
|
export function initTheme(theme) {
|
||||||
|
themeStyle = document.createElement('style');
|
||||||
|
themeStyle.id = 'strudel-theme';
|
||||||
|
document.head.append(themeStyle);
|
||||||
|
activateTheme(theme);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function activateTheme(name) {
|
||||||
|
if (currentTheme === name) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!settings[name]) {
|
||||||
|
console.warn('theme', name, 'has no settings.. defaulting to strudelTheme settings');
|
||||||
|
}
|
||||||
|
const themeSettings = settings[name] || settings.strudelTheme;
|
||||||
|
// set css variables
|
||||||
|
themeStyle.innerHTML = `:root {
|
||||||
|
${Object.entries(themeSettings)
|
||||||
|
// important to override fallback
|
||||||
|
.map(([key, value]) => `--${key}: ${value} !important;`)
|
||||||
|
.join('\n')}
|
||||||
|
}`;
|
||||||
|
// tailwind dark mode
|
||||||
|
if (themeSettings.light) {
|
||||||
|
document.documentElement.classList.remove('dark');
|
||||||
|
} else {
|
||||||
|
document.documentElement.classList.add('dark');
|
||||||
|
}
|
||||||
|
resetThemeStyle?.();
|
||||||
|
resetThemeStyle = undefined;
|
||||||
|
if (themeSettings.customStyle) {
|
||||||
|
resetThemeStyle = injectStyle(themeSettings.customStyle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
58
website/src/components/HeadCommonNew.astro
Normal file
58
website/src/components/HeadCommonNew.astro
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
---
|
||||||
|
import { pwaInfo } from 'virtual:pwa-info';
|
||||||
|
import '../styles/index.css';
|
||||||
|
|
||||||
|
const { BASE_URL } = import.meta.env;
|
||||||
|
const baseNoTrailing = BASE_URL.endsWith('/') ? BASE_URL.slice(0, -1) : BASE_URL;
|
||||||
|
---
|
||||||
|
|
||||||
|
<!-- Global Metadata -->
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width" />
|
||||||
|
<meta name="generator" content={Astro.generator} />
|
||||||
|
|
||||||
|
<link rel="icon" type="image/svg+xml" href={`${baseNoTrailing}/favicon.ico`} />
|
||||||
|
|
||||||
|
<meta
|
||||||
|
name="description"
|
||||||
|
content="Strudel is a music live coding environment for the browser, porting the TidalCycles pattern language to JavaScript."
|
||||||
|
/>
|
||||||
|
<link rel="icon" href={`${baseNoTrailing}/favicon.ico`} />
|
||||||
|
<link rel="apple-touch-icon" href={`${baseNoTrailing}/icons/apple-icon-180.png`} sizes="180x180" />
|
||||||
|
<meta name="theme-color" content="#222222" />
|
||||||
|
|
||||||
|
<base href={BASE_URL} />
|
||||||
|
|
||||||
|
<!-- Scrollable a11y code helper -->
|
||||||
|
<script src{`${baseNoTrailing}/make-scrollable-code-focusable.js`} is:inline></script>
|
||||||
|
|
||||||
|
<script src="/src/pwa.ts"></script>
|
||||||
|
<!-- this does not work for some reason: -->
|
||||||
|
<!-- <style is:global define:vars={strudelTheme}></style> -->
|
||||||
|
<!-- the following variables are just a fallback to make sure everything is readable without JS -->
|
||||||
|
<style is:global>
|
||||||
|
:root {
|
||||||
|
--background: #222;
|
||||||
|
--lineBackground: #22222299;
|
||||||
|
--foreground: #fff;
|
||||||
|
--caret: #ffcc00;
|
||||||
|
--selection: rgba(128, 203, 196, 0.5);
|
||||||
|
--selectionMatch: #036dd626;
|
||||||
|
--lineHighlight: #00000050;
|
||||||
|
--gutterBackground: transparent;
|
||||||
|
--gutterForeground: #8a919966;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
{pwaInfo && <Fragment set:html={pwaInfo.webManifest.linkTag} />}
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// https://medium.com/quick-code/100vh-problem-with-ios-safari-92ab23c852a8
|
||||||
|
const appHeight = () => {
|
||||||
|
const doc = document.documentElement;
|
||||||
|
doc.style.setProperty('--app-height', `${window.innerHeight - 1}px`);
|
||||||
|
};
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
window.addEventListener('resize', appHeight);
|
||||||
|
appHeight();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@ -1,13 +1,13 @@
|
|||||||
---
|
---
|
||||||
import HeadCommon from '../../components/HeadCommon.astro';
|
import HeadCommonNew from '../../components/HeadCommonNew.astro';
|
||||||
---
|
---
|
||||||
|
|
||||||
<html lang="en" class="dark">
|
<html lang="en" class="dark">
|
||||||
<head>
|
<head>
|
||||||
<HeadCommon />
|
<HeadCommonNew />
|
||||||
<title>Strudel Vanilla REPL</title>
|
<title>Strudel Vanilla REPL</title>
|
||||||
</head>
|
</head>
|
||||||
<body class="h-app-height bg-background">
|
<body class="h-app-height">
|
||||||
<div class="settings">
|
<div class="settings">
|
||||||
<form name="settings" class="flex flex-col space-y-1 bg-[#00000080]">
|
<form name="settings" class="flex flex-col space-y-1 bg-[#00000080]">
|
||||||
<label
|
<label
|
||||||
@ -60,10 +60,8 @@ import HeadCommon from '../../components/HeadCommon.astro';
|
|||||||
<option>vscode</option>
|
<option>vscode</option>
|
||||||
</select> </label
|
</select> </label
|
||||||
><br />
|
><br />
|
||||||
<!-- <label>fontFamily
|
<label>fontFamily
|
||||||
<select name="fontFamily">
|
<select name="fontFamily">
|
||||||
<option>monospace</option>
|
|
||||||
<option>helvetica</option>
|
|
||||||
<option value="monospace">monospace</option>
|
<option value="monospace">monospace</option>
|
||||||
<option value="BigBlueTerminal">BigBlueTerminal</option>
|
<option value="BigBlueTerminal">BigBlueTerminal</option>
|
||||||
<option value="x3270">x3270</option>
|
<option value="x3270">x3270</option>
|
||||||
@ -76,7 +74,7 @@ import HeadCommon from '../../components/HeadCommon.astro';
|
|||||||
<option value="mode7">mode7</option>
|
<option value="mode7">mode7</option>
|
||||||
</select>
|
</select>
|
||||||
</label>
|
</label>
|
||||||
<br /> -->
|
<br />
|
||||||
<label>fontSize <input type="number" name="fontSize" /></label>
|
<label>fontSize <input type="number" name="fontSize" /></label>
|
||||||
<br />
|
<br />
|
||||||
<label><input type="checkbox" name="isLineNumbersDisplayed" />isLineNumbersDisplayed</label>
|
<label><input type="checkbox" name="isLineNumbersDisplayed" />isLineNumbersDisplayed</label>
|
||||||
|
|||||||
@ -1,7 +1,3 @@
|
|||||||
:root {
|
|
||||||
--foreground: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
body,
|
body,
|
||||||
input {
|
input {
|
||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { logger, getDrawContext, silence, controls, evalScope, hash2code, code2hash } from '@strudel.cycles/core';
|
import { logger, getDrawContext, silence, controls, evalScope, hash2code, code2hash } from '@strudel.cycles/core';
|
||||||
import { StrudelMirror } from '@strudel/codemirror';
|
import { StrudelMirror, initTheme, activateTheme } from '@strudel/codemirror';
|
||||||
import { transpiler } from '@strudel.cycles/transpiler';
|
import { transpiler } from '@strudel.cycles/transpiler';
|
||||||
import {
|
import {
|
||||||
getAudioContext,
|
getAudioContext,
|
||||||
@ -24,6 +24,7 @@ const initialSettings = {
|
|||||||
fontFamily: 'monospace',
|
fontFamily: 'monospace',
|
||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
};
|
};
|
||||||
|
initTheme(initialSettings.theme);
|
||||||
|
|
||||||
async function run() {
|
async function run() {
|
||||||
const container = document.getElementById('code');
|
const container = document.getElementById('code');
|
||||||
@ -196,4 +197,6 @@ form.addEventListener('change', () => {
|
|||||||
const values = getFormValues(form, initialSettings);
|
const values = getFormValues(form, initialSettings);
|
||||||
// console.log('values', values);
|
// console.log('values', values);
|
||||||
editor.updateSettings(values);
|
editor.updateSettings(values);
|
||||||
|
// TODO: only activateTheme when it changes
|
||||||
|
activateTheme(values.theme);
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user