From aff5e643ac056233976d256daedc7b1c4f5f5836 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Forment?= <45191785+Bubobubobubobubo@users.noreply.github.com> Date: Fri, 28 Jul 2023 01:23:38 +0200 Subject: [PATCH] Init commit --- index.html | 163 +++++ package.json | 24 + postcss.config.js | 6 + src/API.ts | 124 ++++ src/AppSettings.ts | 94 +++ src/Clock.ts | 57 ++ src/EditorSetup.ts | 113 +++ src/Evaluator.ts | 31 + src/Time.ts | 11 + src/TransportNode.js | 49 ++ src/TransportProcessor.js | 37 + src/highlightSelection.ts | 114 +++ src/main.ts | 452 ++++++++++++ src/output.css | 1405 ++++++++++++++++++++++++++++++++++++ src/style.css | 3 + src/themes/materialDark.ts | 209 ++++++ src/vite-env.d.ts | 1 + tailwind.config.js | 12 + tsconfig.json | 23 + yarn.lock | 920 +++++++++++++++++++++++ 20 files changed, 3848 insertions(+) create mode 100644 index.html create mode 100644 package.json create mode 100644 postcss.config.js create mode 100644 src/API.ts create mode 100644 src/AppSettings.ts create mode 100644 src/Clock.ts create mode 100644 src/EditorSetup.ts create mode 100644 src/Evaluator.ts create mode 100644 src/Time.ts create mode 100644 src/TransportNode.js create mode 100644 src/TransportProcessor.js create mode 100644 src/highlightSelection.ts create mode 100644 src/main.ts create mode 100644 src/output.css create mode 100644 src/style.css create mode 100644 src/themes/materialDark.ts create mode 100644 src/vite-env.d.ts create mode 100644 tailwind.config.js create mode 100644 tsconfig.json create mode 100644 yarn.lock diff --git a/index.html b/index.html new file mode 100644 index 0000000..26d1b8a --- /dev/null +++ b/index.html @@ -0,0 +1,163 @@ + + + + + + + Topos + + + + +
+
+ + + + + + + Topos + + + +
+
+ +
+ + + +
+ + +
+ +
+
    +
  • + 1 +
  • +
  • + 2 +
  • +
  • + 3 +
  • +
  • + 4 +
  • +
  • + 5 +
  • +
  • + 6 +
  • +
  • + 7 +
  • +
  • + 8 +
  • +
  • + 9 +
  • + +
+ +
+
+ + + diff --git a/package.json b/package.json new file mode 100644 index 0000000..b4e0111 --- /dev/null +++ b/package.json @@ -0,0 +1,24 @@ +{ + "name": "topos", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc && vite build", + "preview": "vite preview" + }, + "devDependencies": { + "typescript": "^5.0.2", + "vite": "^4.4.5" + }, + "dependencies": { + "@codemirror/lang-javascript": "^6.1.9", + "@replit/codemirror-vim": "^6.0.14", + "autoprefixer": "^10.4.14", + "codemirror": "^6.0.1", + "postcss": "^8.4.27", + "tailwindcss": "^3.3.3", + "zzfx": "^1.2.0" + } +} diff --git a/postcss.config.js b/postcss.config.js new file mode 100644 index 0000000..2e7af2b --- /dev/null +++ b/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +} diff --git a/src/API.ts b/src/API.ts new file mode 100644 index 0000000..ef3671d --- /dev/null +++ b/src/API.ts @@ -0,0 +1,124 @@ +import { Editor } from "./main"; +import { tryEvaluate } from "./Evaluator"; +import { ZZFX, zzfx } from "zzfx"; + + +export class UserAPI { + + variables: { [key: string]: any } = {} + globalGain: GainNode + audioNodes: AudioNode[] = [] + + constructor(public app: Editor) { + this.globalGain = this.app.audioContext.createGain() + // Give default parameters to the reverb + + this.globalGain.gain.value = 0.2; + this.globalGain.connect(this.app.audioContext.destination) + } + + private registerNode(node: T): T{ + this.audioNodes.push(node) + return node + } + + killAll() { + this.audioNodes.forEach(node => { + node.disconnect() + }) + } + + var(name: string, value: any) { + this.variables[name] = value + } + get(name: string) { return this.variables[name] } + + pick(array: T[]): T { return array[Math.floor(Math.random() * array.length)] } + + almostNever() { return Math.random() > 0.9 } + sometimes() { return Math.random() > 0.5 } + rarely() { return Math.random() > 0.75 } + often() { return Math.random() > 0.25 } + almostAlways() { return Math.random() > 0.1 } + randInt(min: number, max: number) { return Math.floor(Math.random() * (max - min + 1)) + min } + + // Iterators + get i() { return this.app.universes[this.app.selected_universe].global.evaluations } + e(index:number) { return this.app.universes[this.app.selected_universe].locals[index].evaluations } + + + // Script launcher: can launch any number of scripts + script(...args: number[]): void { + args.forEach(arg => { tryEvaluate(this.app, this.app.universes[this.app.selected_universe].locals[arg]) }) + } + + // Small ZZFX interface for playing with this synth + zzfx(...thing: number[]) { + zzfx(...thing); + } + + on(beat: number = 1, pulse: number = 1): boolean { + return this.app.clock.time_position.beat === beat && this.app.clock.time_position.pulse === pulse + } + + pulse(pulse: number) { + return this.app.clock.time_position.pulse === pulse + } + + modPulse(pulse: number) { + return this.app.clock.time_position.pulse % pulse === 0 + } + + mute() { + this.globalGain.gain.value = 0 + } + + volume(volume: number) { + this.globalGain.gain.value = volume + } + vol = this.volume + + + beep( + frequency: number = 400, duration: number = 0.2, + type: OscillatorType = "sine", filter: BiquadFilterType = "lowpass", + cutoff: number = 10000, resonance: number = 1, + ) { + const oscillator = this.registerNode(this.app.audioContext.createOscillator()); + const gainNode = this.registerNode(this.app.audioContext.createGain()); + const limiterNode = this.registerNode(this.app.audioContext.createDynamicsCompressor()); + const filterNode = this.registerNode(this.app.audioContext.createBiquadFilter()); + // All this for the limiter + limiterNode.threshold.setValueAtTime(-5.0, this.app.audioContext.currentTime); + limiterNode.knee.setValueAtTime(0, this.app.audioContext.currentTime); + limiterNode.ratio.setValueAtTime(20.0, this.app.audioContext.currentTime); + limiterNode.attack.setValueAtTime(0.001, this.app.audioContext.currentTime); + limiterNode.release.setValueAtTime(0.05, this.app.audioContext.currentTime); + + + // Filter + filterNode.type = filter; + filterNode.frequency.value = cutoff; + filterNode.Q.value = resonance; + + + oscillator.type = type; + oscillator.frequency.value = frequency || 400; + gainNode.gain.value = 0.25; + oscillator + .connect(filterNode) + .connect(gainNode) + .connect(limiterNode) + .connect(this.globalGain) + oscillator.start(); + gainNode.gain.exponentialRampToValueAtTime(0.00001, this.app.audioContext.currentTime + duration); + oscillator.stop(this.app.audioContext.currentTime + duration); + // Clean everything after a node has been played + oscillator.onended = () => { + oscillator.disconnect(); + gainNode.disconnect(); + filterNode.disconnect(); + limiterNode.disconnect(); + } + } +} \ No newline at end of file diff --git a/src/AppSettings.ts b/src/AppSettings.ts new file mode 100644 index 0000000..c12654f --- /dev/null +++ b/src/AppSettings.ts @@ -0,0 +1,94 @@ +export type Universes = { [key: string]: Universe } + +export interface Universe { + global: File + locals: { [key: number]: File } + init: File +} + +export interface File { + candidate: string + committed: string + evaluations: number +} + +export interface Settings { + vimMode: boolean + theme: string + font: string + universes: Universes +} + +export const template_universe = { + global: { candidate: "", committed: "", evaluations: 0 }, + locals: { + 1: { candidate: "", committed: "", evaluations: 0}, + 2: { candidate: "", committed: "", evaluations: 0}, + 3: { candidate: "", committed: "", evaluations: 0}, + 4: { candidate: "", committed: "", evaluations: 0}, + 5: { candidate: "", committed: "", evaluations: 0}, + 6: { candidate: "", committed: "", evaluations: 0}, + 7: { candidate: "", committed: "", evaluations: 0}, + 8: { candidate: "", committed: "", evaluations: 0}, + 9: { candidate: "", committed: "", evaluations: 0}, + }, + init: { candidate: "", committed: "", evaluations: 0 } +} + +export const template_universes = { + "Default": { + global: { candidate: "", committed: "", evaluations: 0 }, + locals: { + 1: { candidate: "", committed: "", evaluations: 0}, + 2: { candidate: "", committed: "", evaluations: 0}, + 3: { candidate: "", committed: "", evaluations: 0}, + 4: { candidate: "", committed: "", evaluations: 0}, + 5: { candidate: "", committed: "", evaluations: 0}, + 6: { candidate: "", committed: "", evaluations: 0}, + 7: { candidate: "", committed: "", evaluations: 0}, + 8: { candidate: "", committed: "", evaluations: 0}, + 9: { candidate: "", committed: "", evaluations: 0}, + }, + init: { candidate: "", committed: "", evaluations: 0 } + } +} + + +export class AppSettings { + + public vimMode: boolean = false + public theme: string = "materialDark" + public font: string = "SpaceMono" + public universes: Universes + + constructor() { + + const settingsFromStorage = JSON.parse(localStorage.getItem('topos') || "{}"); + + if (settingsFromStorage && Object.keys(settingsFromStorage).length !== 0) { + // let settings = JSON.parse(localStorage.getItem("topos") as string) + this.vimMode = settingsFromStorage.vimMode + this.theme = settingsFromStorage.theme + this.font = settingsFromStorage.font + this.universes = settingsFromStorage.universes + } else { + this.universes = template_universes + } + + } + + + get data(): Settings { + return { + vimMode: this.vimMode, + theme: this.theme, + font: this.font, + universes: this.universes + } + } + + saveApplicationToLocalStorage(universes: Universes): void{ + this.universes = universes; + localStorage.setItem('topos', JSON.stringify(this.data)) + } +} \ No newline at end of file diff --git a/src/Clock.ts b/src/Clock.ts new file mode 100644 index 0000000..7a4e6a8 --- /dev/null +++ b/src/Clock.ts @@ -0,0 +1,57 @@ +// @ts-ignore +import { TransportNode } from './TransportNode'; + +import { Editor } from './main'; + +export interface TimePosition { + bar: number + beat: number + pulse: number +} + +export class Clock { + + evaluations: number + transportNode: TransportNode + bpm: number + time_signature: number[] + time_position: TimePosition + ppqn: number + + constructor(public app: Editor, ctx: AudioContext) { + this.time_position = { bar: 0, beat: 0, pulse: 0 } + this.bpm = 120; + this.time_signature = [4, 4]; + this.ppqn = 48; + this.evaluations = 0; + ctx.audioWorklet.addModule('src/TransportProcessor.js').then((e) => { + this.transportNode = new TransportNode(ctx, {}, this.app); + this.transportNode.connect(ctx.destination); + return e + }) + .catch((e) => { + console.log('Error loading TransportProcessor.js:', e); + }) + } + + start(): void { + // Check if the clock is already running + if (this.transportNode?.state === 'running') { + console.log('Already started') + } else { + this.app.audioContext.resume() + this.transportNode?.start(); + } + } + + pause(): void { + this.transportNode?.pause(); + } + + stop(): void { + this.transportNode?.stop(); + } + + // Public methods + public toString(): string { return `` } +} \ No newline at end of file diff --git a/src/EditorSetup.ts b/src/EditorSetup.ts new file mode 100644 index 0000000..879602c --- /dev/null +++ b/src/EditorSetup.ts @@ -0,0 +1,113 @@ +import { javascript } from "@codemirror/lang-javascript" +import { + keymap, + highlightSpecialChars, + drawSelection, + highlightActiveLine, + dropCursor, + rectangularSelection, + lineNumbers, + crosshairCursor, + highlightActiveLineGutter +} from "@codemirror/view" +import { + Extension, + EditorState +} from "@codemirror/state" +import { + defaultHighlightStyle, + syntaxHighlighting, + indentOnInput, + bracketMatching, + foldKeymap +} from "@codemirror/language" +import { + defaultKeymap, + historyKeymap, + history, +} from "@codemirror/commands" +import { + searchKeymap, + highlightSelectionMatches +} from "@codemirror/search" +import { + autocompletion, + completionKeymap, + closeBrackets, + closeBracketsKeymap +} from "@codemirror/autocomplete" +import { + lintKeymap +} from "@codemirror/lint" + +import { materialDark } from "./themes/materialDark" + +// (The superfluous function calls around the list of extensions work +// around current limitations in tree-shaking software.) + +/// This is an extension value that just pulls together a number of +/// extensions that you might want in a basic editor. It is meant as a +/// convenient helper to quickly set up CodeMirror without installing +/// and importing a lot of separate packages. +/// +/// Specifically, it includes... +/// +/// - [the default command bindings](#commands.defaultKeymap) +/// - [line numbers](#view.lineNumbers) +/// - [special character highlighting](#view.highlightSpecialChars) +/// - [the undo history](#commands.history) +/// - [a fold gutter](#language.foldGutter) +/// - [custom selection drawing](#view.drawSelection) +/// - [drop cursor](#view.dropCursor) +/// - [multiple selections](#state.EditorState^allowMultipleSelections) +/// - [reindentation on input](#language.indentOnInput) +/// - [the default highlight style](#language.defaultHighlightStyle) (as fallback) +/// - [bracket matching](#language.bracketMatching) +/// - [bracket closing](#autocomplete.closeBrackets) +/// - [autocompletion](#autocomplete.autocompletion) +/// - [rectangular selection](#view.rectangularSelection) and [crosshair cursor](#view.crosshairCursor) +/// - [active line highlighting](#view.highlightActiveLine) +/// - [active line gutter highlighting](#view.highlightActiveLineGutter) +/// - [selection match highlighting](#search.highlightSelectionMatches) +/// - [search](#search.searchKeymap) +/// - [linting](#lint.lintKeymap) +/// +/// (You'll probably want to add some language package to your setup +/// too.) +/// +/// This extension does not allow customization. The idea is that, +/// once you decide you want to configure your editor more precisely, +/// you take this package's source (which is just a bunch of imports +/// and an array literal), copy it into your own code, and adjust it +/// as desired. + +export const editorSetup: Extension = (() => [ + materialDark, + lineNumbers(), + javascript(), + highlightActiveLineGutter(), + highlightSpecialChars(), + history(), + // foldGutter(), + drawSelection(), + dropCursor(), + EditorState.allowMultipleSelections.of(true), + indentOnInput(), + syntaxHighlighting(defaultHighlightStyle, {fallback: true}), + bracketMatching(), + closeBrackets(), + autocompletion(), + rectangularSelection(), + crosshairCursor(), + highlightActiveLine(), + highlightSelectionMatches(), + keymap.of([ + ...closeBracketsKeymap, + ...defaultKeymap, + ...searchKeymap, + ...historyKeymap, + ...foldKeymap, + ...completionKeymap, + ...lintKeymap + ]) +])() \ No newline at end of file diff --git a/src/Evaluator.ts b/src/Evaluator.ts new file mode 100644 index 0000000..4eb0e28 --- /dev/null +++ b/src/Evaluator.ts @@ -0,0 +1,31 @@ +import type { Editor } from './main'; +import type { File } from './AppSettings'; + +/* This mode of evaluation can only work if the whole buffer is evaluated at once */ +export const tryEvaluate = (application: Editor, code: File): void => { + let isValidCode: boolean; + try { + Function(`with (this) {try{${code.candidate}} catch (e) {console.log(e)}};`).call(application.api) + code.evaluations++; + isValidCode = true; + } catch (error) { + Function(`with (this) {try{${code.committed}} catch (e) {console.log(e)}};`).call(application.api) + code.evaluations++; + isValidCode = false; + } + + if (isValidCode) { + code.committed = code.candidate; + } else { + evaluate(application, code); + } +} + +export const evaluate = (application: Editor, code: File): void => { + Function(`with (this) {try{${code.committed}} catch (e) {console.log(e)}};`).call(application.api) + code.evaluations++; +} + +export const evaluateCommand = (application: Editor, command: string): void => { + Function(`with (this) {try{${command}} catch (e) {console.log(e)}};`).call(application.api) +} \ No newline at end of file diff --git a/src/Time.ts b/src/Time.ts new file mode 100644 index 0000000..336aaa2 --- /dev/null +++ b/src/Time.ts @@ -0,0 +1,11 @@ +class Ligne { + + public start: number + public end: number + + constructor(start: number, end: number)) { + this.start = start + this.end = end + } + +} \ No newline at end of file diff --git a/src/TransportNode.js b/src/TransportNode.js new file mode 100644 index 0000000..38d14d9 --- /dev/null +++ b/src/TransportNode.js @@ -0,0 +1,49 @@ +import { evaluate, tryEvaluate, evaluateCommand } from "./Evaluator"; + +export class TransportNode extends AudioWorkletNode { + + constructor(context, options, application) { + super(context, "transport", options); + this.app = application + this.port.addEventListener("message", this.handleMessage); + this.port.start(); + /** @type {HTMLSpanElement} */ + this.$clock = document.getElementById("clockviewer"); + this.offset_time = 0; + } + /** @type {(this: MessagePort, ev: MessageEvent) => any} */ + handleMessage = (message) => { + if (message.data === "bang") { + let info = this.convertTimeToBarsBeats(this.context.currentTime); + this.$clock.innerHTML = `${info.bar} / ${info.beat} / ${info.ppqn}` + this.app.clock.time_position = { bar: info.bar, beat: info.beat, pulse: info.ppqn } + tryEvaluate( this.app, this.app.global_buffer ); + } + }; + + start() { + this.port.postMessage("start"); + } + + pause() { + this.port.postMessage("pause"); + } + + convertTimeToBarsBeats(currentTime) { + // Calculate the duration of one beat in seconds + const beatDuration = 60 / this.app.clock.bpm; + + // Calculate the beat number + const beatNumber = (currentTime - this.offset_time) / beatDuration; + + // Calculate the bar and beat numbers + const beatsPerBar = this.app.clock.time_signature[0]; + const barNumber = Math.floor(beatNumber / beatsPerBar) + 1; // Adding 1 to make it 1-indexed + const beatWithinBar = Math.floor(beatNumber % beatsPerBar) + 1; // Adding 1 to make it 1-indexed + + // Calculate the PPQN position + const ppqnPosition = Math.floor((beatNumber % 1) * this.app.clock.ppqn); + return { bar: barNumber, beat: beatWithinBar, ppqn: ppqnPosition }; +} + +} \ No newline at end of file diff --git a/src/TransportProcessor.js b/src/TransportProcessor.js new file mode 100644 index 0000000..026eea9 --- /dev/null +++ b/src/TransportProcessor.js @@ -0,0 +1,37 @@ +class TransportProcessor extends AudioWorkletProcessor { + + constructor(options) { + super(options); + this.port.addEventListener("message", this.handleMessage); + this.port.start(); + this.interval = 0.001; + this.origin = currentTime; + this.next = this.origin + this.interval; + } + + handleMessage = (message) => { + if (message.data === "start") { + this.origin = currentTime; + this.next = this.origin + this.interval; + } else if (message.data === "pause") { + this.next = Infinity; + } else if (message.data === "stop") { + this.origin = currentTime; + this.next = Infinity; + } + }; + + process(inputs, outputs, parameters) { + if (currentTime >= this.next) { + while (this.next < currentTime) + this.next += this.interval; + this.port.postMessage("bang"); + } + return true; + } +} + +registerProcessor( + "transport", + TransportProcessor +); \ No newline at end of file diff --git a/src/highlightSelection.ts b/src/highlightSelection.ts new file mode 100644 index 0000000..eae44d3 --- /dev/null +++ b/src/highlightSelection.ts @@ -0,0 +1,114 @@ +import { Decoration, DecorationSet } from "@codemirror/view" +import { StateField, StateEffect, ChangeDesc } from "@codemirror/state" +import { EditorView } from "@codemirror/view" +import { invertedEffects } from "@codemirror/commands" +import { Extension } from "@codemirror/state" + + +function mapRange(range: {from: number, to: number}, change: ChangeDesc) { + let from = change.mapPos(range.from), to = change.mapPos(range.to) + return from < to ? {from, to} : undefined +} + +const addHighlight = StateEffect.define<{from: number, to: number}>({ + map: mapRange +}) + +const removeHighlight = StateEffect.define<{from: number, to: number}>({ + map: mapRange +}) + +const highlight = Decoration.mark({ + attributes: {style: `background-color: #ffad42`} +}) + +const highlightedRanges = StateField.define({ + create() { + return Decoration.none + }, + update(ranges, tr) { + ranges = ranges.map(tr.changes) + for (let e of tr.effects) { + if (e.is(addHighlight)) + ranges = addRange(ranges, e.value) + else if (e.is(removeHighlight)) + ranges = cutRange(ranges, e.value) + } + return ranges + }, + provide: field => EditorView.decorations.from(field) +}) + +function cutRange(ranges: DecorationSet, r: {from: number, to: number}) { + let leftover: any[] = [] + ranges.between(r.from, r.to, (from, to, deco) => { + if (from < r.from) leftover.push(deco.range(from, r.from)) + if (to > r.to) leftover.push(deco.range(r.to, to)) + }) + return ranges.update({ + filterFrom: r.from, + filterTo: r.to, + filter: () => false, + add: leftover + }) +} + +function addRange(ranges: DecorationSet, r: {from: number, to: number}) { + ranges.between(r.from, r.to, (from, to) => { + if (from < r.from) r = {from, to: r.to} + if (to > r.to) r = {from: r.from, to} + }) + return ranges.update({ + filterFrom: r.from, + filterTo: r.to, + filter: () => false, + add: [highlight.range(r.from, r.to)] + }) +} + + +const invertHighlight = invertedEffects.of(tr => { + let found = [] + for (let e of tr.effects) { + if (e.is(addHighlight)) found.push(removeHighlight.of(e.value)) + else if (e.is(removeHighlight)) found.push(addHighlight.of(e.value)) + } + let ranges = tr.startState.field(highlightedRanges) + tr.changes.iterChangedRanges((chFrom, chTo) => { + ranges.between(chFrom, chTo, (rFrom, rTo) => { + if (rFrom >= chFrom || rTo <= chTo) { + let from = Math.max(chFrom, rFrom), to = Math.min(chTo, rTo) + if (from < to) found.push(addHighlight.of({from, to})) + } + }) + }) + return found +}) + +export function highlightSelection(view: EditorView) { + view.dispatch({ + effects: view.state.selection.ranges.filter(r => !r.empty) + .map(r => addHighlight.of(r)) + }) + return true +} + +export function unhighlightSelection(view: EditorView) { + let highlighted = view.state.field(highlightedRanges) + let effects: any[] = [] + for (let sel of view.state.selection.ranges) { + highlighted.between(sel.from, sel.to, (rFrom, rTo) => { + let from = Math.max(sel.from, rFrom), to = Math.min(sel.to, rTo) + if (from < to) effects.push(removeHighlight.of({from, to})) + }) + } + view.dispatch({effects}) + return true +} + +export function rangeHighlighting(): Extension { + return [ + highlightedRanges, + invertHighlight, + ] +} \ No newline at end of file diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..33ddb91 --- /dev/null +++ b/src/main.ts @@ -0,0 +1,452 @@ +import './style.css' +import { EditorView } from "codemirror"; +import { editorSetup } from './EditorSetup'; +import { EditorState, Compartment } from "@codemirror/state"; +import { javascript } from "@codemirror/lang-javascript"; +import { Clock } from './Clock' +import { vim } from "@replit/codemirror-vim"; +import { AppSettings } from './AppSettings'; +import { ViewUpdate } from '@codemirror/view'; +import { + highlightSelection, + unhighlightSelection, + rangeHighlighting +} from "./highlightSelection"; +import { UserAPI } from './API'; +import { Extension } from '@codemirror/state'; +import { Universes, File, template_universe } from './AppSettings'; +import { tryEvaluate } from './Evaluator'; + + + +export class Editor { + + // Data structures for editor text management + universes: Universes + selected_universe: string + local_index: number = 1 + editor_mode: 'global' | 'local' | 'init' = 'local' + + settings = new AppSettings() + editorExtensions: Extension[] = [] + userPlugins: Extension[] = [] + state: EditorState + api: UserAPI + + // Audio stuff + audioContext: AudioContext + view: EditorView + clock: Clock + + // Transport elements + play_button: HTMLButtonElement = document.getElementById('play-button') as HTMLButtonElement + pause_button: HTMLButtonElement = document.getElementById('pause-button') as HTMLButtonElement + clear_button: HTMLButtonElement = document.getElementById('clear-button') as HTMLButtonElement + + // Script selection elements + local_button: HTMLButtonElement = document.getElementById('local-button') as HTMLButtonElement + global_button: HTMLButtonElement = document.getElementById('global-button') as HTMLButtonElement + init_button: HTMLButtonElement = document.getElementById('init-button') as HTMLButtonElement + universe_viewer: HTMLDivElement = document.getElementById('universe-viewer') as HTMLDivElement + + // Buffer modal + buffer_modal: HTMLDivElement = document.getElementById('modal-buffers') as HTMLDivElement + buffer_search: HTMLInputElement = document.getElementById('buffer-search') as HTMLInputElement + settings_modal: HTMLDivElement = document.getElementById('modal-settings') as HTMLDivElement + + // Local script tabs + local_script_tabs: HTMLDivElement = document.getElementById('local-script-tabs') as HTMLDivElement + + constructor() { + + + + // ================================================================================ + // Loading the universe from local storage + // ================================================================================ + + this.selected_universe = "Default"; + this.universe_viewer.innerHTML = `Topos: ${this.selected_universe}` + this.universes = this.settings.universes + + // ================================================================================ + // Audio context and clock + // ================================================================================ + + this.audioContext = new AudioContext({ sampleRate: 44100, latencyHint: 0.000001}); + this.clock = new Clock(this, this.audioContext); + + // ================================================================================ + // User API + // ================================================================================ + + this.api = new UserAPI(this); + + // ================================================================================ + // CodeMirror Management + // ================================================================================ + + this.editorExtensions = [ + editorSetup, + rangeHighlighting(), + javascript(), + EditorView.updateListener.of((v:ViewUpdate) => { + // This is the event listener for the editor + }), + ...this.userPlugins + ] + + let dynamicPlugins = new Compartment; + this.state = EditorState.create({ + extensions: [ + ...this.editorExtensions, + EditorView.lineWrapping, + dynamicPlugins.of(this.userPlugins) + ], + doc: this.universes[this.selected_universe].locals[this.local_index].candidate + }) + + this.view = new EditorView({ + parent: document.getElementById('editor') as HTMLElement, + state: this.state + }); + + // ================================================================================ + // Application event listeners + // ================================================================================ + + document.addEventListener('keydown', (event: KeyboardEvent) => { + + // TAB should do nothing + if (event.key === 'Tab') { + event.preventDefault(); + } + + // Ctrl + Shift + V: Vim Mode + if ((event.key === 'v' || event.key === 'V') && event.ctrlKey && event.shiftKey) { + this.settings.vimMode = !this.settings.vimMode + event.preventDefault(); + this.userPlugins = this.settings.vimMode ? [] : [vim()] + this.view.dispatch({ + effects: dynamicPlugins.reconfigure(this.userPlugins) + }) + } + + // Ctrl + Enter or Return: Evaluate the hovered code block + if ((event.key === 'Enter' || event.key === 'Return') && event.ctrlKey) { + event.preventDefault(); + const code = this.getCodeBlock(); + this.currentFile.candidate = this.view.state.doc.toString() + tryEvaluate(this, this.currentFile) + } + + // Shift + Enter or Ctrl + E: evaluate the line + if ((event.key === 'Enter' && event.shiftKey) || (event.key === 'e' && event.ctrlKey)) { + event.preventDefault(); // Prevents the addition of a new line + this.currentFile.candidate = this.view.state.doc.toString() + const code = this.getSelectedLines(); + } + + // This is the modal to switch between universes + if (event.metaKey && event.key === "b") { + this.openBuffersModal() + } + + // This is the modal that opens up the settings + if (event.shiftKey && event.key === "Escape") { + this.openSettingsModal() + } + + + }); + + // ================================================================================ + // Interface buttons + // ================================================================================ + + let tabs = document.querySelectorAll('[id^="tab-"]'); + // Iterate over the tabs with an index + for (let i = 0; i < tabs.length; i++) { + tabs[i].addEventListener('click', (event) => { + + // Updating the CSS accordingly + tabs[i].classList.add('bg-orange-300') + for (let j = 0; j < tabs.length; j++) { + if (j != i) tabs[j].classList.remove('bg-orange-300') + } + this.currentFile.candidate = this.view.state.doc.toString() + + let tab = event.target as HTMLElement + let tab_id = tab.id.split('-')[1] + this.local_index = parseInt(tab_id) + this.updateEditorView() + }) + } + + this.play_button.addEventListener('click', () => { + this.play_button.children[0].classList.add('fill-orange-300') + this.pause_button.children[0].classList.remove('fill-orange-300') + this.clock.start() + }) + + this.clear_button.addEventListener('click', () => { + // Reset the current universe to a template + if (confirm('Do you want to reset the current universe?')) { + this.universes[this.selected_universe] = template_universe + this.updateEditorView() + } + }); + + this.pause_button.addEventListener('click', () => { + // Change the color of the button + this.play_button.children[0].classList.remove('fill-orange-300') + this.pause_button.children[0].classList.add('fill-orange-300') + this.clock.pause() + }) + + this.local_button.addEventListener('click', () => this.changeModeFromInterface('local')) + this.global_button.addEventListener('click', () => this.changeModeFromInterface('global')) + this.init_button.addEventListener('click', () => this.changeModeFromInterface('init')) + + this.buffer_search.addEventListener('keydown', (event) => { + if (event.key === "Enter") { + let query = this.buffer_search.value + if (query.length > 2 && query.length < 20) { + this.loadUniverse(query) + this.buffer_search.value = "" + this.closeBuffersModal() + } + } + }) + } + + get global_buffer() { + return this.universes[this.selected_universe.toString()].global + } + + get init_buffer() { + return this.universes[this.selected_universe.toString()].init + } + + changeModeFromInterface(mode: 'global' | 'local' | 'init') { + + const interface_buttons = [this.local_button, this.global_button, this.init_button] + + let changeColor = (button: HTMLElement) => { + interface_buttons.forEach(button => { + // Get the child svg element of each button + let svg = button.children[0] as HTMLElement + if (svg.classList.contains('text-orange-300')) { + svg.classList.remove('text-orange-300') + svg.classList.add('text-white') + } + }) + button.children[0].classList.add('text-orange-300') + } + + if (mode === this.editor_mode) return + switch (mode) { + case 'local': + if (this.local_script_tabs.classList.contains('hidden')) { + this.local_script_tabs.classList.remove('hidden') + } + this.currentFile.candidate = this.view.state.doc.toString() + changeColor(this.local_button) + this.editor_mode = 'local'; + break; + case 'global': + if (!this.local_script_tabs.classList.contains('hidden')) { + this.local_script_tabs.classList.add('hidden') + } + this.currentFile.candidate = this.view.state.doc.toString() + changeColor(this.global_button) + this.editor_mode = 'global'; + break; + case 'init': + if (!this.local_script_tabs.classList.contains('hidden')) { + this.local_script_tabs.classList.add('hidden') + } + this.currentFile.candidate = this.view.state.doc.toString() + changeColor(this.init_button) + this.editor_mode = 'init'; + break; + } + this.updateEditorView(); + } + + updateEditorView():void { + // Remove everything from the editor + this.view.dispatch({ + changes: { + from: 0, + to: this.view.state.doc.toString().length, + insert:'' + } + }) + + // Insert something + this.view.dispatch({ + changes: { + from: 0, + insert: this.currentFile.candidate + } + }); + } + + get currentFile(): File { + switch (this.editor_mode) { + case 'global': return this.global_buffer; + case 'local': return this.universes[this.selected_universe].locals[this.local_index]; + case 'init': return this.init_buffer; + } + } + + loadUniverse(universeName: string) { + this.currentFile.candidate = this.view.state.doc.toString() + let editor = this; + + function whichBuffer(editor: Editor): File { + switch (editor.editor_mode) { + case 'global': return editor.global_buffer + case 'local': return editor.universes[ + editor.selected_universe].locals[editor.local_index] + case 'init': return editor.init_buffer + } + } + + let selectedUniverse = universeName.trim() + if (this.universes[selectedUniverse] === undefined) { + this.universes[selectedUniverse] = template_universe + } + this.selected_universe = selectedUniverse + this.universe_viewer.innerHTML = `Topos: ${selectedUniverse}` + this.global_buffer = this.universes[this.selected_universe.toString()].global + this.init_buffer = this.universes[this.selected_universe.toString()].init + // We should also update the editor accordingly + this.view.dispatch({ + changes: { from: 0, to: this.view.state.doc.toString().length, insert:'' } + }) + this.view.dispatch({ + changes: { from: 0, insert: this.currentFile.candidate } + }); + } + + getCodeBlock(): string { + // Capture the position of the cursor + let cursor = this.view.state.selection.main.head + const state = this.view.state; + const { head } = state.selection.main; + const currentLine = state.doc.lineAt(head); + let startLine = currentLine; + while (startLine.number > 1 && !/^\s*$/.test(state.doc.line(startLine.number - 1).text)) { + startLine = state.doc.line(startLine.number - 1); + } + let endLine = currentLine; + while ( + endLine.number < state.doc.lines && !/^\s*$/.test(state.doc.line(endLine.number + 1).text)) { + endLine = state.doc.line(endLine.number + 1); + } + + this.view.dispatch({selection: {anchor: 0 + startLine.from, head: endLine.to}}); + highlightSelection(this.view); + + setTimeout(() => { + unhighlightSelection(this.view) + this.view.dispatch({selection: {anchor: cursor, head: cursor}}); + }, 200); + + let result_string = state.doc.sliceString(startLine.from, endLine.to); + result_string = result_string.split('\n').map((line, index, lines) => { + const trimmedLine = line.trim(); + if (index === lines.length - 1 || /^\s/.test(lines[index + 1]) || trimmedLine.startsWith('@')) { + return line; + } else { + return line + ';\\'; + } + }).join('\n'); + return result_string + } + + getSelectedLines = (): string => { + const state = this.view.state; + const { from, to } = state.selection.main; + const fromLine = state.doc.lineAt(from); + const toLine = state.doc.lineAt(to); + this.view.dispatch({selection: {anchor: 0 + fromLine.from, head: toLine.to}}); + // Release the selection and get the cursor back to its original position + + // Blink the text! + highlightSelection(this.view); + + setTimeout(() => { + unhighlightSelection(this.view) + this.view.dispatch({selection: {anchor: from, head: from}}); + }, 200); + return state.doc.sliceString(fromLine.from, toLine.to); + } + + openSettingsModal() { + // If the modal is hidden, unhide it and hide the editor + if (document.getElementById('modal-settings')!.classList.contains('invisible')) { + document.getElementById('editor')!.classList.add('invisible') + document.getElementById('modal-settings')!.classList.remove('invisible') + } else { + this.closeSettingsModal(); + } + } + + closeSettingsModal() { + document.getElementById('editor')!.classList.remove('invisible') + document.getElementById('modal-settings')!.classList.add('invisible') + } + + openBuffersModal() { + // If the modal is hidden, unhide it and hide the editor + if (document.getElementById('modal-buffers')!.classList.contains('invisible')) { + document.getElementById('editor')!.classList.add('invisible') + document.getElementById('modal-buffers')!.classList.remove('invisible') + document.getElementById('buffer-search')!.focus() + } else { + this.closeBuffersModal(); + } + } + + closeBuffersModal() { + // @ts-ignore + document.getElementById('buffer-search')!.value = '' + document.getElementById('editor')!.classList.remove('invisible') + document.getElementById('modal-buffers')!.classList.add('invisible') + document.getElementById('modal')!.classList.add('invisible') + } +} + +const app = new Editor() + +function startClock() { + document.getElementById('editor')!.classList.remove('invisible') + document.getElementById('modal')!.classList.add('hidden') + document.getElementById('start-button')!.removeEventListener('click', startClock); + document.removeEventListener('keydown', startOnEnter) + app.clock.start() + app.view.focus() + // Change the play button svg color to orange + document.getElementById('pause-button')!.children[0].classList.remove('fill-orange-300') + document.getElementById('play-button')!.children[0].classList.add('fill-orange-300') +} + +function startOnEnter(e: KeyboardEvent) { + if (e.code === 'Enter' || e.code === "Space") startClock() +} + +document.addEventListener('keydown', startOnEnter) +document.getElementById('start-button')!.addEventListener( + 'click', startClock); + +// When the user leaves the page, all the universes should be saved in the localStorage +window.addEventListener('beforeunload', () => { + // Iterate over all local files and set the candidate to the committed + app.currentFile.candidate = app.view.state.doc.toString() + app.currentFile.committed = app.view.state.doc.toString() + app.settings.saveApplicationToLocalStorage(app.universes) + return null; +}); \ No newline at end of file diff --git a/src/output.css b/src/output.css new file mode 100644 index 0000000..714c984 --- /dev/null +++ b/src/output.css @@ -0,0 +1,1405 @@ +/* +! tailwindcss v3.3.3 | MIT License | https://tailwindcss.com +*/ + +/* +1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4) +2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116) +*/ + +*, +::before, +::after { + box-sizing: border-box; + /* 1 */ + border-width: 0; + /* 2 */ + border-style: solid; + /* 2 */ + border-color: #e5e7eb; + /* 2 */ +} + +::before, +::after { + --tw-content: ''; +} + +/* +1. Use a consistent sensible line-height in all browsers. +2. Prevent adjustments of font size after orientation changes in iOS. +3. Use a more readable tab size. +4. Use the user's configured `sans` font-family by default. +5. Use the user's configured `sans` font-feature-settings by default. +6. Use the user's configured `sans` font-variation-settings by default. +*/ + +html { + line-height: 1.5; + /* 1 */ + -webkit-text-size-adjust: 100%; + /* 2 */ + -moz-tab-size: 4; + /* 3 */ + -o-tab-size: 4; + tab-size: 4; + /* 3 */ + font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + /* 4 */ + font-feature-settings: normal; + /* 5 */ + font-variation-settings: normal; + /* 6 */ +} + +/* +1. Remove the margin in all browsers. +2. Inherit line-height from `html` so users can set them as a class directly on the `html` element. +*/ + +body { + margin: 0; + /* 1 */ + line-height: inherit; + /* 2 */ +} + +/* +1. Add the correct height in Firefox. +2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655) +3. Ensure horizontal rules are visible by default. +*/ + +hr { + height: 0; + /* 1 */ + color: inherit; + /* 2 */ + border-top-width: 1px; + /* 3 */ +} + +/* +Add the correct text decoration in Chrome, Edge, and Safari. +*/ + +abbr:where([title]) { + -webkit-text-decoration: underline dotted; + text-decoration: underline dotted; +} + +/* +Remove the default font size and weight for headings. +*/ + +h1, +h2, +h3, +h4, +h5, +h6 { + font-size: inherit; + font-weight: inherit; +} + +/* +Reset links to optimize for opt-in styling instead of opt-out. +*/ + +a { + color: inherit; + text-decoration: inherit; +} + +/* +Add the correct font weight in Edge and Safari. +*/ + +b, +strong { + font-weight: bolder; +} + +/* +1. Use the user's configured `mono` font family by default. +2. Correct the odd `em` font sizing in all browsers. +*/ + +code, +kbd, +samp, +pre { + font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; + /* 1 */ + font-size: 1em; + /* 2 */ +} + +/* +Add the correct font size in all browsers. +*/ + +small { + font-size: 80%; +} + +/* +Prevent `sub` and `sup` elements from affecting the line height in all browsers. +*/ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sub { + bottom: -0.25em; +} + +sup { + top: -0.5em; +} + +/* +1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297) +2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016) +3. Remove gaps between table borders by default. +*/ + +table { + text-indent: 0; + /* 1 */ + border-color: inherit; + /* 2 */ + border-collapse: collapse; + /* 3 */ +} + +/* +1. Change the font styles in all browsers. +2. Remove the margin in Firefox and Safari. +3. Remove default padding in all browsers. +*/ + +button, +input, +optgroup, +select, +textarea { + font-family: inherit; + /* 1 */ + font-feature-settings: inherit; + /* 1 */ + font-variation-settings: inherit; + /* 1 */ + font-size: 100%; + /* 1 */ + font-weight: inherit; + /* 1 */ + line-height: inherit; + /* 1 */ + color: inherit; + /* 1 */ + margin: 0; + /* 2 */ + padding: 0; + /* 3 */ +} + +/* +Remove the inheritance of text transform in Edge and Firefox. +*/ + +button, +select { + text-transform: none; +} + +/* +1. Correct the inability to style clickable types in iOS and Safari. +2. Remove default button styles. +*/ + +button, +[type='button'], +[type='reset'], +[type='submit'] { + -webkit-appearance: button; + /* 1 */ + background-color: transparent; + /* 2 */ + background-image: none; + /* 2 */ +} + +/* +Use the modern Firefox focus style for all focusable elements. +*/ + +:-moz-focusring { + outline: auto; +} + +/* +Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737) +*/ + +:-moz-ui-invalid { + box-shadow: none; +} + +/* +Add the correct vertical alignment in Chrome and Firefox. +*/ + +progress { + vertical-align: baseline; +} + +/* +Correct the cursor style of increment and decrement buttons in Safari. +*/ + +::-webkit-inner-spin-button, +::-webkit-outer-spin-button { + height: auto; +} + +/* +1. Correct the odd appearance in Chrome and Safari. +2. Correct the outline style in Safari. +*/ + +[type='search'] { + -webkit-appearance: textfield; + /* 1 */ + outline-offset: -2px; + /* 2 */ +} + +/* +Remove the inner padding in Chrome and Safari on macOS. +*/ + +::-webkit-search-decoration { + -webkit-appearance: none; +} + +/* +1. Correct the inability to style clickable types in iOS and Safari. +2. Change font properties to `inherit` in Safari. +*/ + +::-webkit-file-upload-button { + -webkit-appearance: button; + /* 1 */ + font: inherit; + /* 2 */ +} + +/* +Add the correct display in Chrome and Safari. +*/ + +summary { + display: list-item; +} + +/* +Removes the default spacing and border for appropriate elements. +*/ + +blockquote, +dl, +dd, +h1, +h2, +h3, +h4, +h5, +h6, +hr, +figure, +p, +pre { + margin: 0; +} + +fieldset { + margin: 0; + padding: 0; +} + +legend { + padding: 0; +} + +ol, +ul, +menu { + list-style: none; + margin: 0; + padding: 0; +} + +/* +Reset default styling for dialogs. +*/ + +dialog { + padding: 0; +} + +/* +Prevent resizing textareas horizontally by default. +*/ + +textarea { + resize: vertical; +} + +/* +1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300) +2. Set the default placeholder color to the user's configured gray 400 color. +*/ + +input::-moz-placeholder, textarea::-moz-placeholder { + opacity: 1; + /* 1 */ + color: #9ca3af; + /* 2 */ +} + +input::placeholder, +textarea::placeholder { + opacity: 1; + /* 1 */ + color: #9ca3af; + /* 2 */ +} + +/* +Set the default cursor for buttons. +*/ + +button, +[role="button"] { + cursor: pointer; +} + +/* +Make sure disabled buttons don't get the pointer cursor. +*/ + +:disabled { + cursor: default; +} + +/* +1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14) +2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210) + This can trigger a poorly considered lint error in some tools but is included by design. +*/ + +img, +svg, +video, +canvas, +audio, +iframe, +embed, +object { + display: block; + /* 1 */ + vertical-align: middle; + /* 2 */ +} + +/* +Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14) +*/ + +img, +video { + max-width: 100%; + height: auto; +} + +/* Make elements with the HTML hidden attribute stay hidden by default */ + +[hidden] { + display: none; +} + +*, ::before, ::after { + --tw-border-spacing-x: 0; + --tw-border-spacing-y: 0; + --tw-translate-x: 0; + --tw-translate-y: 0; + --tw-rotate: 0; + --tw-skew-x: 0; + --tw-skew-y: 0; + --tw-scale-x: 1; + --tw-scale-y: 1; + --tw-pan-x: ; + --tw-pan-y: ; + --tw-pinch-zoom: ; + --tw-scroll-snap-strictness: proximity; + --tw-gradient-from-position: ; + --tw-gradient-via-position: ; + --tw-gradient-to-position: ; + --tw-ordinal: ; + --tw-slashed-zero: ; + --tw-numeric-figure: ; + --tw-numeric-spacing: ; + --tw-numeric-fraction: ; + --tw-ring-inset: ; + --tw-ring-offset-width: 0px; + --tw-ring-offset-color: #fff; + --tw-ring-color: rgb(59 130 246 / 0.5); + --tw-ring-offset-shadow: 0 0 #0000; + --tw-ring-shadow: 0 0 #0000; + --tw-shadow: 0 0 #0000; + --tw-shadow-colored: 0 0 #0000; + --tw-blur: ; + --tw-brightness: ; + --tw-contrast: ; + --tw-grayscale: ; + --tw-hue-rotate: ; + --tw-invert: ; + --tw-saturate: ; + --tw-sepia: ; + --tw-drop-shadow: ; + --tw-backdrop-blur: ; + --tw-backdrop-brightness: ; + --tw-backdrop-contrast: ; + --tw-backdrop-grayscale: ; + --tw-backdrop-hue-rotate: ; + --tw-backdrop-invert: ; + --tw-backdrop-opacity: ; + --tw-backdrop-saturate: ; + --tw-backdrop-sepia: ; +} + +::backdrop { + --tw-border-spacing-x: 0; + --tw-border-spacing-y: 0; + --tw-translate-x: 0; + --tw-translate-y: 0; + --tw-rotate: 0; + --tw-skew-x: 0; + --tw-skew-y: 0; + --tw-scale-x: 1; + --tw-scale-y: 1; + --tw-pan-x: ; + --tw-pan-y: ; + --tw-pinch-zoom: ; + --tw-scroll-snap-strictness: proximity; + --tw-gradient-from-position: ; + --tw-gradient-via-position: ; + --tw-gradient-to-position: ; + --tw-ordinal: ; + --tw-slashed-zero: ; + --tw-numeric-figure: ; + --tw-numeric-spacing: ; + --tw-numeric-fraction: ; + --tw-ring-inset: ; + --tw-ring-offset-width: 0px; + --tw-ring-offset-color: #fff; + --tw-ring-color: rgb(59 130 246 / 0.5); + --tw-ring-offset-shadow: 0 0 #0000; + --tw-ring-shadow: 0 0 #0000; + --tw-shadow: 0 0 #0000; + --tw-shadow-colored: 0 0 #0000; + --tw-blur: ; + --tw-brightness: ; + --tw-contrast: ; + --tw-grayscale: ; + --tw-hue-rotate: ; + --tw-invert: ; + --tw-saturate: ; + --tw-sepia: ; + --tw-drop-shadow: ; + --tw-backdrop-blur: ; + --tw-backdrop-brightness: ; + --tw-backdrop-contrast: ; + --tw-backdrop-grayscale: ; + --tw-backdrop-hue-rotate: ; + --tw-backdrop-invert: ; + --tw-backdrop-opacity: ; + --tw-backdrop-saturate: ; + --tw-backdrop-sepia: ; +} + +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border-width: 0; +} + +.pointer-events-none { + pointer-events: none; +} + +.invisible { + visibility: hidden; +} + +.fixed { + position: fixed; +} + +.absolute { + position: absolute; +} + +.relative { + position: relative; +} + +.inset-y-0 { + top: 0px; + bottom: 0px; +} + +.bottom-0 { + bottom: 0px; +} + +.bottom-2 { + bottom: 0.5rem; +} + +.bottom-2\.5 { + bottom: 0.625rem; +} + +.left-0 { + left: 0px; +} + +.right-0 { + right: 0px; +} + +.right-2 { + right: 0.5rem; +} + +.right-2\.5 { + right: 0.625rem; +} + +.top-0 { + top: 0px; +} + +.z-50 { + z-index: 50; +} + +.m-auto { + margin: auto; +} + +.mx-auto { + margin-left: auto; + margin-right: auto; +} + +.mb-0 { + margin-bottom: 0px; +} + +.mb-2 { + margin-bottom: 0.5rem; +} + +.mb-4 { + margin-bottom: 1rem; +} + +.ml-2 { + margin-left: 0.5rem; +} + +.ml-4 { + margin-left: 1rem; +} + +.mr-5 { + margin-right: 1.25rem; +} + +.mt-1 { + margin-top: 0.25rem; +} + +.mr-2 { + margin-right: 0.5rem; +} + +.mr-8 { + margin-right: 2rem; +} + +.mr-20 { + margin-right: 5rem; +} + +.mr-6 { + margin-right: 1.5rem; +} + +.mr-4 { + margin-right: 1rem; +} + +.ml-auto { + margin-left: auto; +} + +.block { + display: block; +} + +.inline-block { + display: inline-block; +} + +.flex { + display: flex; +} + +.inline-flex { + display: inline-flex; +} + +.hidden { + display: none; +} + +.h-10 { + height: 2.5rem; +} + +.h-4 { + height: 1rem; +} + +.h-6 { + height: 1.5rem; +} + +.h-screen { + height: 100vh; +} + +.h-3 { + height: 0.75rem; +} + +.h-8 { + height: 2rem; +} + +.h-\[calc\(100\%-1rem\)\] { + height: calc(100% - 1rem); +} + +.max-h-full { + max-height: 100%; +} + +.min-h-screen { + min-height: 100vh; +} + +.w-10 { + width: 2.5rem; +} + +.w-14 { + width: 3.5rem; +} + +.w-4 { + width: 1rem; +} + +.w-6 { + width: 1.5rem; +} + +.w-full { + width: 100%; +} + +.w-2 { + width: 0.5rem; +} + +.w-3 { + width: 0.75rem; +} + +.w-8 { + width: 2rem; +} + +.max-w-2xl { + max-width: 42rem; +} + +.flex-grow { + flex-grow: 1; +} + +.grow { + flex-grow: 1; +} + +.cursor-not-allowed { + cursor: not-allowed; +} + +.flex-row { + flex-direction: row; +} + +.flex-col { + flex-direction: column; +} + +.flex-wrap { + flex-wrap: wrap; +} + +.items-start { + align-items: flex-start; +} + +.items-center { + align-items: center; +} + +.justify-center { + justify-content: center; +} + +.justify-between { + justify-content: space-between; +} + +.space-y-6 > :not([hidden]) ~ :not([hidden]) { + --tw-space-y-reverse: 0; + margin-top: calc(1.5rem * calc(1 - var(--tw-space-y-reverse))); + margin-bottom: calc(1.5rem * var(--tw-space-y-reverse)); +} + +.space-x-8 > :not([hidden]) ~ :not([hidden]) { + --tw-space-x-reverse: 0; + margin-right: calc(2rem * var(--tw-space-x-reverse)); + margin-left: calc(2rem * calc(1 - var(--tw-space-x-reverse))); +} + +.space-x-4 > :not([hidden]) ~ :not([hidden]) { + --tw-space-x-reverse: 0; + margin-right: calc(1rem * var(--tw-space-x-reverse)); + margin-left: calc(1rem * calc(1 - var(--tw-space-x-reverse))); +} + +.space-x-2 > :not([hidden]) ~ :not([hidden]) { + --tw-space-x-reverse: 0; + margin-right: calc(0.5rem * var(--tw-space-x-reverse)); + margin-left: calc(0.5rem * calc(1 - var(--tw-space-x-reverse))); +} + +.overflow-hidden { + overflow: hidden; +} + +.overflow-y-auto { + overflow-y: auto; +} + +.overflow-x-hidden { + overflow-x: hidden; +} + +.overflow-y-hidden { + overflow-y: hidden; +} + +.rounded { + border-radius: 0.25rem; +} + +.rounded-full { + border-radius: 9999px; +} + +.rounded-lg { + border-radius: 0.5rem; +} + +.rounded-md { + border-radius: 0.375rem; +} + +.rounded-b { + border-bottom-right-radius: 0.25rem; + border-bottom-left-radius: 0.25rem; +} + +.rounded-t { + border-top-left-radius: 0.25rem; + border-top-right-radius: 0.25rem; +} + +.border { + border-width: 1px; +} + +.border-r { + border-right-width: 1px; +} + +.border-b { + border-bottom-width: 1px; +} + +.border-t { + border-top-width: 1px; +} + +.border-gray-300 { + --tw-border-opacity: 1; + border-color: rgb(209 213 219 / var(--tw-border-opacity)); +} + +.border-gray-200 { + --tw-border-opacity: 1; + border-color: rgb(229 231 235 / var(--tw-border-opacity)); +} + +.bg-black { + --tw-bg-opacity: 1; + background-color: rgb(0 0 0 / var(--tw-bg-opacity)); +} + +.bg-blue-700 { + --tw-bg-opacity: 1; + background-color: rgb(29 78 216 / var(--tw-bg-opacity)); +} + +.bg-gray-100 { + --tw-bg-opacity: 1; + background-color: rgb(243 244 246 / var(--tw-bg-opacity)); +} + +.bg-white { + --tw-bg-opacity: 1; + background-color: rgb(255 255 255 / var(--tw-bg-opacity)); +} + +.bg-blue-800 { + --tw-bg-opacity: 1; + background-color: rgb(30 64 175 / var(--tw-bg-opacity)); +} + +.bg-blue-600 { + --tw-bg-opacity: 1; + background-color: rgb(37 99 235 / var(--tw-bg-opacity)); +} + +.bg-gray-800 { + --tw-bg-opacity: 1; + background-color: rgb(31 41 55 / var(--tw-bg-opacity)); +} + +.bg-blue-500 { + --tw-bg-opacity: 1; + background-color: rgb(59 130 246 / var(--tw-bg-opacity)); +} + +.bg-transparent { + background-color: transparent; +} + +.bg-orange-300 { + --tw-bg-opacity: 1; + background-color: rgb(253 186 116 / var(--tw-bg-opacity)); +} + +.bg-green-300 { + --tw-bg-opacity: 1; + background-color: rgb(134 239 172 / var(--tw-bg-opacity)); +} + +.bg-red-300 { + --tw-bg-opacity: 1; + background-color: rgb(252 165 165 / var(--tw-bg-opacity)); +} + +.bg-red-500 { + --tw-bg-opacity: 1; + background-color: rgb(239 68 68 / var(--tw-bg-opacity)); +} + +.bg-opacity-50 { + --tw-bg-opacity: 0.5; +} + +.fill-orange-300 { + fill: #fdba74; +} + +.p-1 { + padding: 0.25rem; +} + +.p-1\.5 { + padding: 0.375rem; +} + +.p-2 { + padding: 0.5rem; +} + +.p-4 { + padding: 1rem; +} + +.p-6 { + padding: 1.5rem; +} + +.px-16 { + padding-left: 4rem; + padding-right: 4rem; +} + +.px-2 { + padding-left: 0.5rem; + padding-right: 0.5rem; +} + +.px-4 { + padding-left: 1rem; + padding-right: 1rem; +} + +.px-7 { + padding-left: 1.75rem; + padding-right: 1.75rem; +} + +.py-0 { + padding-top: 0px; + padding-bottom: 0px; +} + +.py-1 { + padding-top: 0.25rem; + padding-bottom: 0.25rem; +} + +.py-14 { + padding-top: 3.5rem; + padding-bottom: 3.5rem; +} + +.py-2 { + padding-top: 0.5rem; + padding-bottom: 0.5rem; +} + +.py-3 { + padding-top: 0.75rem; + padding-bottom: 0.75rem; +} + +.py-4 { + padding-top: 1rem; + padding-bottom: 1rem; +} + +.px-5 { + padding-left: 1.25rem; + padding-right: 1.25rem; +} + +.py-2\.5 { + padding-top: 0.625rem; + padding-bottom: 0.625rem; +} + +.pb-4 { + padding-bottom: 1rem; +} + +.pl-10 { + padding-left: 2.5rem; +} + +.pl-2 { + padding-left: 0.5rem; +} + +.pl-2\.5 { + padding-left: 0.625rem; +} + +.pl-3 { + padding-left: 0.75rem; +} + +.pr-8 { + padding-right: 2rem; +} + +.pl-4 { + padding-left: 1rem; +} + +.pl-6 { + padding-left: 1.5rem; +} + +.pl-5 { + padding-left: 1.25rem; +} + +.text-center { + text-align: center; +} + +.text-base { + font-size: 1rem; + line-height: 1.5rem; +} + +.text-sm { + font-size: 0.875rem; + line-height: 1.25rem; +} + +.text-xl { + font-size: 1.25rem; + line-height: 1.75rem; +} + +.text-xs { + font-size: 0.75rem; + line-height: 1rem; +} + +.font-bold { + font-weight: 700; +} + +.font-medium { + font-weight: 500; +} + +.font-semibold { + font-weight: 600; +} + +.italic { + font-style: italic; +} + +.leading-relaxed { + line-height: 1.625; +} + +.text-black { + --tw-text-opacity: 1; + color: rgb(0 0 0 / var(--tw-text-opacity)); +} + +.text-gray-500 { + --tw-text-opacity: 1; + color: rgb(107 114 128 / var(--tw-text-opacity)); +} + +.text-gray-700 { + --tw-text-opacity: 1; + color: rgb(55 65 81 / var(--tw-text-opacity)); +} + +.text-gray-800 { + --tw-text-opacity: 1; + color: rgb(31 41 55 / var(--tw-text-opacity)); +} + +.text-gray-900 { + --tw-text-opacity: 1; + color: rgb(17 24 39 / var(--tw-text-opacity)); +} + +.text-white { + --tw-text-opacity: 1; + color: rgb(255 255 255 / var(--tw-text-opacity)); +} + +.text-gray-400 { + --tw-text-opacity: 1; + color: rgb(156 163 175 / var(--tw-text-opacity)); +} + +.text-blue-200 { + --tw-text-opacity: 1; + color: rgb(191 219 254 / var(--tw-text-opacity)); +} + +.text-blue-800 { + --tw-text-opacity: 1; + color: rgb(30 64 175 / var(--tw-text-opacity)); +} + +.text-rose-800 { + --tw-text-opacity: 1; + color: rgb(159 18 57 / var(--tw-text-opacity)); +} + +.text-sky-700 { + --tw-text-opacity: 1; + color: rgb(3 105 161 / var(--tw-text-opacity)); +} + +.text-sky-300 { + --tw-text-opacity: 1; + color: rgb(125 211 252 / var(--tw-text-opacity)); +} + +.text-orange-300 { + --tw-text-opacity: 1; + color: rgb(253 186 116 / var(--tw-text-opacity)); +} + +.text-orange-500 { + --tw-text-opacity: 1; + color: rgb(249 115 22 / var(--tw-text-opacity)); +} + +.underline { + text-decoration-line: underline; +} + +.line-through { + text-decoration-line: line-through; +} + +.shadow { + --tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1); + --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} + +.outline { + outline-style: solid; +} + +.outline-0 { + outline-width: 0px; +} + +.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-colors { + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} + +.duration-200 { + transition-duration: 200ms; +} + +.hover\:bg-blue-800:hover { + --tw-bg-opacity: 1; + background-color: rgb(30 64 175 / var(--tw-bg-opacity)); +} + +.hover\:bg-gray-100:hover { + --tw-bg-opacity: 1; + background-color: rgb(243 244 246 / var(--tw-bg-opacity)); +} + +.hover\:bg-white:hover { + --tw-bg-opacity: 1; + background-color: rgb(255 255 255 / var(--tw-bg-opacity)); +} + +.hover\:bg-gray-900:hover { + --tw-bg-opacity: 1; + background-color: rgb(17 24 39 / var(--tw-bg-opacity)); +} + +.hover\:bg-gray-500:hover { + --tw-bg-opacity: 1; + background-color: rgb(107 114 128 / var(--tw-bg-opacity)); +} + +.hover\:bg-gray-800:hover { + --tw-bg-opacity: 1; + background-color: rgb(31 41 55 / var(--tw-bg-opacity)); +} + +.hover\:bg-gray-200:hover { + --tw-bg-opacity: 1; + background-color: rgb(229 231 235 / var(--tw-bg-opacity)); +} + +.hover\:text-gray-900:hover { + --tw-text-opacity: 1; + color: rgb(17 24 39 / var(--tw-text-opacity)); +} + +.focus\:z-10:focus { + z-index: 10; +} + +.focus\:outline-none:focus { + outline: 2px solid transparent; + outline-offset: 2px; +} + +.focus\:ring-4:focus { + --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); + --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color); + box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000); +} + +.focus\:ring-blue-300:focus { + --tw-ring-opacity: 1; + --tw-ring-color: rgb(147 197 253 / var(--tw-ring-opacity)); +} + +:is([dir="rtl"] .rtl\:border-l) { + border-left-width: 1px; +} + +:is([dir="rtl"] .rtl\:border-r-0) { + border-right-width: 0px; +} + +@media (prefers-color-scheme: dark) { + .dark\:border-gray-700 { + --tw-border-opacity: 1; + border-color: rgb(55 65 81 / var(--tw-border-opacity)); + } + + .dark\:border-gray-500 { + --tw-border-opacity: 1; + border-color: rgb(107 114 128 / var(--tw-border-opacity)); + } + + .dark\:border-gray-600 { + --tw-border-opacity: 1; + border-color: rgb(75 85 99 / var(--tw-border-opacity)); + } + + .dark\:bg-black { + --tw-bg-opacity: 1; + background-color: rgb(0 0 0 / var(--tw-bg-opacity)); + } + + .dark\:bg-blue-600 { + --tw-bg-opacity: 1; + background-color: rgb(37 99 235 / var(--tw-bg-opacity)); + } + + .dark\:bg-gray-800 { + --tw-bg-opacity: 1; + background-color: rgb(31 41 55 / var(--tw-bg-opacity)); + } + + .dark\:bg-gray-700 { + --tw-bg-opacity: 1; + background-color: rgb(55 65 81 / var(--tw-bg-opacity)); + } + + .dark\:text-gray-200 { + --tw-text-opacity: 1; + color: rgb(229 231 235 / var(--tw-text-opacity)); + } + + .dark\:text-gray-400 { + --tw-text-opacity: 1; + color: rgb(156 163 175 / var(--tw-text-opacity)); + } + + .dark\:text-white { + --tw-text-opacity: 1; + color: rgb(255 255 255 / var(--tw-text-opacity)); + } + + .dark\:text-gray-500 { + --tw-text-opacity: 1; + color: rgb(107 114 128 / var(--tw-text-opacity)); + } + + .dark\:text-gray-300 { + --tw-text-opacity: 1; + color: rgb(209 213 219 / var(--tw-text-opacity)); + } + + .dark\:hover\:bg-blue-700:hover { + --tw-bg-opacity: 1; + background-color: rgb(29 78 216 / var(--tw-bg-opacity)); + } + + .dark\:hover\:bg-gray-800:hover { + --tw-bg-opacity: 1; + background-color: rgb(31 41 55 / var(--tw-bg-opacity)); + } + + .dark\:hover\:bg-gray-600:hover { + --tw-bg-opacity: 1; + background-color: rgb(75 85 99 / var(--tw-bg-opacity)); + } + + .dark\:hover\:text-white:hover { + --tw-text-opacity: 1; + color: rgb(255 255 255 / var(--tw-text-opacity)); + } + + .dark\:focus\:ring-blue-800:focus { + --tw-ring-opacity: 1; + --tw-ring-color: rgb(30 64 175 / var(--tw-ring-opacity)); + } + + .dark\:focus\:ring-gray-600:focus { + --tw-ring-opacity: 1; + --tw-ring-color: rgb(75 85 99 / var(--tw-ring-opacity)); + } +} + +@media (min-width: 768px) { + .md\:inset-0 { + inset: 0px; + } +} + +@media (min-width: 1024px) { + .lg\:space-x-8 > :not([hidden]) ~ :not([hidden]) { + --tw-space-x-reverse: 0; + margin-right: calc(2rem * var(--tw-space-x-reverse)); + margin-left: calc(2rem * calc(1 - var(--tw-space-x-reverse))); + } +} diff --git a/src/style.css b/src/style.css new file mode 100644 index 0000000..b5c61c9 --- /dev/null +++ b/src/style.css @@ -0,0 +1,3 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; diff --git a/src/themes/materialDark.ts b/src/themes/materialDark.ts new file mode 100644 index 0000000..a2bb087 --- /dev/null +++ b/src/themes/materialDark.ts @@ -0,0 +1,209 @@ +import { EditorView } from '@codemirror/view' +import { Extension } from '@codemirror/state' +import { HighlightStyle, syntaxHighlighting } from '@codemirror/language' +import { tags as t } from '@lezer/highlight' + +const base00 = 'black', base01 = '#505d64', + base02 = 'white', base03 = '#707d8b', + base04 = '#a0a4ae', base05 = '#bdbdbd', + base06 = '#e0e0e0', base07 = '#fdf6e3', + base_red = '#ff5f52', base_deeporange = '#ff6e40', + base_pink = '#fa5788', base_yellow = '#facf4e', + base_orange = '#ffad42', base_cyan = '#1E6AE1', + base_indigo = '#7186f0', base_purple = '#D09EBF', + base_green = '#82d47c', base_lightgreen = '#82d47c', + base_teal = '#4ebaaa' + +const invalid = base_red, + darkBackground = '#fdf6e3', + highlightBackground = '#545b61', + background = base00, + tooltipBackground = base01, + selection = base07, + cursor = base04 + +/// The editor theme styles for Material Dark. +export const materialDarkTheme = EditorView.theme( + { + '&': { + color: base05, + backgroundColor: background + }, + + '.cm-content': { + caretColor: cursor + }, + + '.cm-cursor, .cm-dropCursor': { borderLeftColor: cursor }, + '&.cm-focused .cm-selectionBackground, .cm-selectionBackground, .cm-content ::selection': + { backgroundColor: selection, border: `0.5px solid ${base_teal}` }, + + '.cm-panels': { backgroundColor: darkBackground, color: base03 }, + '.cm-panels.cm-panels-top': { borderBottom: '2px solid black' }, + '.cm-panels.cm-panels-bottom': { borderTop: '2px solid black' }, + + '.cm-searchMatch': { + outline: `1px solid ${base_yellow}`, + backgroundColor: 'transparent' + }, + '.cm-searchMatch.cm-searchMatch-selected': { + backgroundColor: highlightBackground + }, + + '.cm-activeLine': { backgroundColor: highlightBackground }, + '.cm-selectionMatch': { + backgroundColor: darkBackground, + outline: `1px solid ${base_teal}` + }, + + '&.cm-focused .cm-matchingBracket': { + color: base06, + outline: `1px solid ${base_teal}` + }, + + '&.cm-focused .cm-nonmatchingBracket': { + color: base_red + }, + + '.cm-gutters': { + backgroundColor: base00, + borderRight: `1px solid ${base07}`, + color: base02 + }, + + '.cm-activeLineGutter': { + backgroundColor: highlightBackground, + color: base07 + }, + + '.cm-foldPlaceholder': { + backgroundColor: 'transparent', + border: 'none', + color: `${base07}`, + }, + + '.cm-tooltip': { + border: 'none', + backgroundColor: tooltipBackground + }, + '.cm-tooltip .cm-tooltip-arrow:before': { + borderTopColor: 'transparent', + borderBottomColor: 'transparent' + }, + '.cm-tooltip .cm-tooltip-arrow:after': { + borderTopColor: tooltipBackground, + borderBottomColor: tooltipBackground + }, + '.cm-tooltip-autocomplete': { + '& > ul > li[aria-selected]': { + backgroundColor: highlightBackground, + color: base03 + } + } + }, + { dark: true } +) + +/// The highlighting style for code in the Material Dark theme. +export const materialDarkHighlightStyle = HighlightStyle.define([ + { tag: t.keyword, color: base_purple }, + { + tag: [t.name, t.deleted, t.character, t.macroName], + color: base_cyan + }, + { tag: [t.propertyName], color: base_yellow }, + { tag: [t.variableName], color: base05 }, + { tag: [t.function(t.variableName)], color: base_cyan }, + { tag: [t.labelName], color: base_purple }, + { + tag: [t.color, t.constant(t.name), t.standard(t.name)], + color: base_yellow + }, + { tag: [t.definition(t.name), t.separator], color: base_pink }, + { tag: [t.brace], color: base_purple }, + { + tag: [t.annotation], + color: invalid + }, + { + tag: [t.number, t.changed, t.annotation, t.modifier, t.self, t.namespace], + color: base_orange + }, + { + tag: [t.typeName, t.className], + color: base_orange + }, + { + tag: [t.operator, t.operatorKeyword], + color: base_indigo + }, + { + tag: [t.tagName], + color: base_deeporange + }, + { + tag: [t.squareBracket], + color: base_red + }, + { + tag: [t.angleBracket], + color: base02 + }, + { + tag: [t.attributeName], + color: base05 + }, + { + tag: [t.regexp], + color: invalid + }, + { + tag: [t.quote], + color: base_green + }, + { tag: [t.string], color: base_lightgreen }, + { + tag: t.link, + color: base_cyan, + textDecoration: 'underline', + textUnderlinePosition: 'under' + }, + { + tag: [t.url, t.escape, t.special(t.string)], + color: base_yellow + }, + { tag: [t.meta], color: base03 }, + { tag: [t.comment], color: base02, fontStyle: 'italic' }, + { tag: t.monospace, color: base05 }, + { tag: t.strong, fontWeight: 'bold', color: base_red }, + { tag: t.emphasis, fontStyle: 'italic', color: base_lightgreen }, + { tag: t.strikethrough, textDecoration: 'line-through' }, + { tag: t.heading, fontWeight: 'bold', color: base_yellow }, + { tag: t.heading1, fontWeight: 'bold', color: base_yellow }, + { + tag: [t.heading2, t.heading3, t.heading4], + fontWeight: 'bold', + color: base_yellow + }, + { + tag: [t.heading5, t.heading6], + color: base_yellow + }, + { tag: [t.atom, t.bool, t.special(t.variableName)], color: base_cyan }, + { + tag: [t.processingInstruction, t.inserted], + color: base_red + }, + { + tag: [t.contentSeparator], + color: base_cyan + }, + { tag: t.invalid, color: base02, borderBottom: `1px dotted ${base_red}` } +]) + +/// Extension to enable the Material Dark theme (both the editor theme and +/// the highlight style). +export const materialDark: Extension = [ + materialDarkTheme, + syntaxHighlighting(materialDarkHighlightStyle) +] \ No newline at end of file diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts new file mode 100644 index 0000000..11f02fe --- /dev/null +++ b/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/tailwind.config.js b/tailwind.config.js new file mode 100644 index 0000000..d37737f --- /dev/null +++ b/tailwind.config.js @@ -0,0 +1,12 @@ +/** @type {import('tailwindcss').Config} */ +export default { + content: [ + "./index.html", + "./src/**/*.{js,ts,jsx,tsx}", + ], + theme: { + extend: {}, + }, + plugins: [], +} + diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..75abdef --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "module": "ESNext", + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src"] +} diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..e4fa2de --- /dev/null +++ b/yarn.lock @@ -0,0 +1,920 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@alloc/quick-lru@^5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@alloc/quick-lru/-/quick-lru-5.2.0.tgz#7bf68b20c0a350f936915fcae06f58e32007ce30" + integrity sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw== + +"@codemirror/autocomplete@^6.0.0": + version "6.9.0" + resolved "https://registry.yarnpkg.com/@codemirror/autocomplete/-/autocomplete-6.9.0.tgz#1a1e63122288b8f8e1e9d7aff2eb39a83e04d8a9" + integrity sha512-Fbwm0V/Wn3BkEJZRhr0hi5BhCo5a7eBL6LYaliPjOSwCyfOpnjXY59HruSxOUNV+1OYer0Tgx1zRNQttjXyDog== + dependencies: + "@codemirror/language" "^6.0.0" + "@codemirror/state" "^6.0.0" + "@codemirror/view" "^6.6.0" + "@lezer/common" "^1.0.0" + +"@codemirror/commands@^6.0.0": + version "6.2.4" + resolved "https://registry.yarnpkg.com/@codemirror/commands/-/commands-6.2.4.tgz#b8a0e5ce72448c092ba4c4b1d902e6f183948aec" + integrity sha512-42lmDqVH0ttfilLShReLXsDfASKLXzfyC36bzwcqzox9PlHulMcsUOfHXNo2X2aFMVNUoQ7j+d4q5bnfseYoOA== + dependencies: + "@codemirror/language" "^6.0.0" + "@codemirror/state" "^6.2.0" + "@codemirror/view" "^6.0.0" + "@lezer/common" "^1.0.0" + +"@codemirror/lang-javascript@^6.1.9": + version "6.1.9" + resolved "https://registry.yarnpkg.com/@codemirror/lang-javascript/-/lang-javascript-6.1.9.tgz#19065ad32db7b3797829eca01b8d9c69da5fd0d6" + integrity sha512-z3jdkcqOEBT2txn2a87A0jSy6Te3679wg/U8QzMeftFt+4KA6QooMwfdFzJiuC3L6fXKfTXZcDocoaxMYfGz0w== + dependencies: + "@codemirror/autocomplete" "^6.0.0" + "@codemirror/language" "^6.6.0" + "@codemirror/lint" "^6.0.0" + "@codemirror/state" "^6.0.0" + "@codemirror/view" "^6.0.0" + "@lezer/common" "^1.0.0" + "@lezer/javascript" "^1.0.0" + +"@codemirror/language@^6.0.0", "@codemirror/language@^6.6.0": + version "6.8.0" + resolved "https://registry.yarnpkg.com/@codemirror/language/-/language-6.8.0.tgz#f2d7eea6b338c25593d800f2293b062d9f9856db" + integrity sha512-r1paAyWOZkfY0RaYEZj3Kul+MiQTEbDvYqf8gPGaRvNneHXCmfSaAVFjwRUPlgxS8yflMxw2CTu6uCMp8R8A2g== + dependencies: + "@codemirror/state" "^6.0.0" + "@codemirror/view" "^6.0.0" + "@lezer/common" "^1.0.0" + "@lezer/highlight" "^1.0.0" + "@lezer/lr" "^1.0.0" + style-mod "^4.0.0" + +"@codemirror/lint@^6.0.0": + version "6.4.0" + resolved "https://registry.yarnpkg.com/@codemirror/lint/-/lint-6.4.0.tgz#3507e937aa9415ef0831ff04734ef0e736e75014" + integrity sha512-6VZ44Ysh/Zn07xrGkdtNfmHCbGSHZzFBdzWi0pbd7chAQ/iUcpLGX99NYRZTa7Ugqg4kEHCqiHhcZnH0gLIgSg== + dependencies: + "@codemirror/state" "^6.0.0" + "@codemirror/view" "^6.0.0" + crelt "^1.0.5" + +"@codemirror/search@^6.0.0": + version "6.5.0" + resolved "https://registry.yarnpkg.com/@codemirror/search/-/search-6.5.0.tgz#308f9968434e0e6ed59c9ec36a0239eb1dfc5d92" + integrity sha512-64/M40YeJPToKvGO6p3fijo2vwUEj4nACEAXElCaYQ50HrXSvRaK+NHEhSh73WFBGdvIdhrV+lL9PdJy2RfCYA== + dependencies: + "@codemirror/state" "^6.0.0" + "@codemirror/view" "^6.0.0" + crelt "^1.0.5" + +"@codemirror/state@^6.0.0", "@codemirror/state@^6.1.4", "@codemirror/state@^6.2.0": + version "6.2.1" + resolved "https://registry.yarnpkg.com/@codemirror/state/-/state-6.2.1.tgz#6dc8d8e5abb26b875e3164191872d69a5e85bd73" + integrity sha512-RupHSZ8+OjNT38zU9fKH2sv+Dnlr8Eb8sl4NOnnqz95mCFTZUaiRP8Xv5MeeaG0px2b8Bnfe7YGwCV3nsBhbuw== + +"@codemirror/view@^6.0.0", "@codemirror/view@^6.6.0": + version "6.15.3" + resolved "https://registry.yarnpkg.com/@codemirror/view/-/view-6.15.3.tgz#b26dac3e1812821daa6da25f59ffb26c9b9b75f3" + integrity sha512-chNgR8H7Ipx7AZUt0+Kknk7BCow/ron3mHd1VZdM7hQXiI79+UlWqcxpCiexTxZQ+iSkqndk3HHAclJOcjSuog== + dependencies: + "@codemirror/state" "^6.1.4" + style-mod "^4.0.0" + w3c-keyname "^2.2.4" + +"@esbuild/android-arm64@0.18.16": + version "0.18.16" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.18.16.tgz#34f562abc0015933aabd41b3d50d8d3359e30155" + integrity sha512-wsCqSPqLz+6Ov+OM4EthU43DyYVVyfn15S4j1bJzylDpc1r1jZFFfJQNfDuT8SlgwuqpmpJXK4uPlHGw6ve7eA== + +"@esbuild/android-arm@0.18.16": + version "0.18.16" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.18.16.tgz#ef6f9aa59a79a9b9330a2e73f7eb402c6630c267" + integrity sha512-gCHjjQmA8L0soklKbLKA6pgsLk1byULuHe94lkZDzcO3/Ta+bbeewJioEn1Fr7kgy9NWNFy/C+MrBwC6I/WCug== + +"@esbuild/android-x64@0.18.16": + version "0.18.16" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.18.16.tgz#ed7444cb17542932c67b15e20528686853239cfd" + integrity sha512-ldsTXolyA3eTQ1//4DS+E15xl0H/3DTRJaRL0/0PgkqDsI0fV/FlOtD+h0u/AUJr+eOTlZv4aC9gvfppo3C4sw== + +"@esbuild/darwin-arm64@0.18.16": + version "0.18.16" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.18.16.tgz#3c5a083e6e08a50f478fa243939989d86be1c6bf" + integrity sha512-aBxruWCII+OtluORR/KvisEw0ALuw/qDQWvkoosA+c/ngC/Kwk0lLaZ+B++LLS481/VdydB2u6tYpWxUfnLAIw== + +"@esbuild/darwin-x64@0.18.16": + version "0.18.16" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.18.16.tgz#a8f3b61bee2807131cbe28eb164ad2b0333b59f5" + integrity sha512-6w4Dbue280+rp3LnkgmriS1icOUZDyPuZo/9VsuMUTns7SYEiOaJ7Ca1cbhu9KVObAWfmdjUl4gwy9TIgiO5eA== + +"@esbuild/freebsd-arm64@0.18.16": + version "0.18.16" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.16.tgz#9bdbb3f0e5f0842b21c9b8602e70c106174ac24c" + integrity sha512-x35fCebhe9s979DGKbVAwXUOcTmCIE32AIqB9CB1GralMIvxdnMLAw5CnID17ipEw9/3MvDsusj/cspYt2ZLNQ== + +"@esbuild/freebsd-x64@0.18.16": + version "0.18.16" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.18.16.tgz#24f73956436495cc7a5a4bf06be6b661aea6a2c1" + integrity sha512-YM98f+PeNXF3GbxIJlUsj+McUWG1irguBHkszCIwfr3BXtXZsXo0vqybjUDFfu9a8Wr7uUD/YSmHib+EeGAFlg== + +"@esbuild/linux-arm64@0.18.16": + version "0.18.16" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.18.16.tgz#244569757f9cbd912f5a595a8ad8144f8c915f13" + integrity sha512-XIqhNUxJiuy+zsR77+H5Z2f7s4YRlriSJKtvx99nJuG5ATuJPjmZ9n0ANgnGlPCpXGSReFpgcJ7O3SMtzIFeiQ== + +"@esbuild/linux-arm@0.18.16": + version "0.18.16" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.18.16.tgz#d63923c63af534032cc5ea0b2a0b3de10f8357f5" + integrity sha512-b5ABb+5Ha2C9JkeZXV+b+OruR1tJ33ePmv9ZwMeETSEKlmu/WJ45XTTG+l6a2KDsQtJJ66qo/hbSGBtk0XVLHw== + +"@esbuild/linux-ia32@0.18.16": + version "0.18.16" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.18.16.tgz#a8825ccea6309f0bccfc5d87b43163ba804c2f20" + integrity sha512-no+pfEpwnRvIyH+txbBAWtjxPU9grslmTBfsmDndj7bnBmr55rOo/PfQmRfz7Qg9isswt1FP5hBbWb23fRWnow== + +"@esbuild/linux-loong64@0.18.16": + version "0.18.16" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.18.16.tgz#f530e820fc3c61cf2206155b994aeab53b6d25be" + integrity sha512-Zbnczs9ZXjmo0oZSS0zbNlJbcwKXa/fcNhYQjahDs4Xg18UumpXG/lwM2lcSvHS3mTrRyCYZvJbmzYc4laRI1g== + +"@esbuild/linux-mips64el@0.18.16": + version "0.18.16" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.18.16.tgz#2d47ace539257896865d243641bd6716684a1e82" + integrity sha512-YMF7hih1HVR/hQVa/ot4UVffc5ZlrzEb3k2ip0nZr1w6fnYypll9td2qcoMLvd3o8j3y6EbJM3MyIcXIVzXvQQ== + +"@esbuild/linux-ppc64@0.18.16": + version "0.18.16" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.18.16.tgz#d6913e7e9be9e242a6a20402800141bdbe7009f7" + integrity sha512-Wkz++LZ29lDwUyTSEnzDaaP5OveOgTU69q9IyIw9WqLRxM4BjTBjz9un4G6TOvehWpf/J3gYVFN96TjGHrbcNQ== + +"@esbuild/linux-riscv64@0.18.16": + version "0.18.16" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.18.16.tgz#8f33b627389c8234fe61f4636c134f17fb1d9b09" + integrity sha512-LFMKZ30tk78/mUv1ygvIP+568bwf4oN6reG/uczXnz6SvFn4e2QUFpUpZY9iSJT6Qpgstrhef/nMykIXZtZWGQ== + +"@esbuild/linux-s390x@0.18.16": + version "0.18.16" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.18.16.tgz#4d44c030f78962cf410f604f92fcc1505e4afdde" + integrity sha512-3ZC0BgyYHYKfZo3AV2/66TD/I9tlSBaW7eWTEIkrQQKfJIifKMMttXl9FrAg+UT0SGYsCRLI35Gwdmm96vlOjg== + +"@esbuild/linux-x64@0.18.16": + version "0.18.16" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.18.16.tgz#8846d00e16b1e93eb488c8b4dd51c946adfc236f" + integrity sha512-xu86B3647DihHJHv/wx3NCz2Dg1gjQ8bbf9cVYZzWKY+gsvxYmn/lnVlqDRazObc3UMwoHpUhNYaZset4X8IPA== + +"@esbuild/netbsd-x64@0.18.16": + version "0.18.16" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.18.16.tgz#6514a86bd07744f3100d2813ea2fb6520d53e72e" + integrity sha512-uVAgpimx9Ffw3xowtg/7qQPwHFx94yCje+DoBx+LNm2ePDpQXHrzE+Sb0Si2VBObYz+LcRps15cq+95YM7gkUw== + +"@esbuild/openbsd-x64@0.18.16": + version "0.18.16" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.18.16.tgz#ae67ce766d58aab6c0e6037f1a76f15df4a2a5fe" + integrity sha512-6OjCQM9wf7z8/MBi6BOWaTL2AS/SZudsZtBziXMtNI8r/U41AxS9x7jn0ATOwVy08OotwkPqGRMkpPR2wcTJXA== + +"@esbuild/sunos-x64@0.18.16": + version "0.18.16" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.18.16.tgz#998efe8a58374b7351ac710455051639a6ce6a05" + integrity sha512-ZoNkruFYJp9d1LbUYCh8awgQDvB9uOMZqlQ+gGEZR7v6C+N6u7vPr86c+Chih8niBR81Q/bHOSKGBK3brJyvkQ== + +"@esbuild/win32-arm64@0.18.16": + version "0.18.16" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.18.16.tgz#8de33682243508eef8d4de1816df2c05adad2b21" + integrity sha512-+j4anzQ9hrs+iqO+/wa8UE6TVkKua1pXUb0XWFOx0FiAj6R9INJ+WE//1/Xo6FG1vB5EpH3ko+XcgwiDXTxcdw== + +"@esbuild/win32-ia32@0.18.16": + version "0.18.16" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.18.16.tgz#95c9f4274fb3ef9e449d464ffe3e3b7fa091503b" + integrity sha512-5PFPmq3sSKTp9cT9dzvI67WNfRZGvEVctcZa1KGjDDu4n3H8k59Inbk0du1fz0KrAbKKNpJbdFXQMDUz7BG4rQ== + +"@esbuild/win32-x64@0.18.16": + version "0.18.16" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.18.16.tgz#5be58d31d0120c68af8e38b702e6937ce764cd68" + integrity sha512-sCIVrrtcWN5Ua7jYXNG1xD199IalrbfV2+0k/2Zf2OyV2FtnQnMgdzgpRAbi4AWlKJj1jkX+M+fEGPQj6BQB4w== + +"@jridgewell/gen-mapping@^0.3.2": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098" + integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ== + dependencies: + "@jridgewell/set-array" "^1.0.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/resolve-uri@3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" + integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== + +"@jridgewell/set-array@^1.0.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" + integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== + +"@jridgewell/sourcemap-codec@1.4.14": + version "1.4.14" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" + integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== + +"@jridgewell/sourcemap-codec@^1.4.10": + version "1.4.15" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" + integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== + +"@jridgewell/trace-mapping@^0.3.9": + version "0.3.18" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz#25783b2086daf6ff1dcb53c9249ae480e4dd4cd6" + integrity sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA== + dependencies: + "@jridgewell/resolve-uri" "3.1.0" + "@jridgewell/sourcemap-codec" "1.4.14" + +"@lezer/common@^1.0.0": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@lezer/common/-/common-1.0.3.tgz#1808f70e2b0a7b1fdcbaf5c074723d2d4ed1e4c5" + integrity sha512-JH4wAXCgUOcCGNekQPLhVeUtIqjH0yPBs7vvUdSjyQama9618IOKFJwkv2kcqdhF0my8hQEgCTEJU0GIgnahvA== + +"@lezer/highlight@^1.0.0", "@lezer/highlight@^1.1.3": + version "1.1.6" + resolved "https://registry.yarnpkg.com/@lezer/highlight/-/highlight-1.1.6.tgz#87e56468c0f43c2a8b3dc7f0b7c2804b34901556" + integrity sha512-cmSJYa2us+r3SePpRCjN5ymCqCPv+zyXmDl0ciWtVaNiORT/MxM7ZgOMQZADD0o51qOaOg24qc/zBViOIwAjJg== + dependencies: + "@lezer/common" "^1.0.0" + +"@lezer/javascript@^1.0.0": + version "1.4.4" + resolved "https://registry.yarnpkg.com/@lezer/javascript/-/javascript-1.4.4.tgz#f876c1ad2ecc2a52d9e33b5f5c0bd9935ea2d8c0" + integrity sha512-0BiBjpEcrt2IXrIzEAsdTLylrVhGHRqVQL3baTBx1sf4qewjIvhG1/pTUumu7W/7YR0AASjLQOQxFmo5EvNmzQ== + dependencies: + "@lezer/highlight" "^1.1.3" + "@lezer/lr" "^1.3.0" + +"@lezer/lr@^1.0.0", "@lezer/lr@^1.3.0": + version "1.3.9" + resolved "https://registry.yarnpkg.com/@lezer/lr/-/lr-1.3.9.tgz#cb299816d1c58efcca23ebbeb70bb4204fdd001b" + integrity sha512-XPz6dzuTHlnsbA5M2DZgjflNQ+9Hi5Swhic0RULdp3oOs3rh6bqGZolosVqN/fQIT8uNiepzINJDnS39oweTHQ== + dependencies: + "@lezer/common" "^1.0.0" + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@replit/codemirror-vim@^6.0.14": + version "6.0.14" + resolved "https://registry.yarnpkg.com/@replit/codemirror-vim/-/codemirror-vim-6.0.14.tgz#8f44740b0497406b551726946c9b30f21c867671" + integrity sha512-wwhqhvL76FdRTdwfUWpKCbv0hkp2fvivfMosDVlL/popqOiNLtUhL02ThgHZH8mus/NkVr5Mj582lyFZqQrjOA== + +any-promise@^1.0.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" + integrity sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A== + +anymatch@~3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +arg@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.2.tgz#c81433cc427c92c4dcf4865142dbca6f15acd59c" + integrity sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg== + +autoprefixer@^10.4.14: + version "10.4.14" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.14.tgz#e28d49902f8e759dd25b153264e862df2705f79d" + integrity sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ== + dependencies: + browserslist "^4.21.5" + caniuse-lite "^1.0.30001464" + fraction.js "^4.2.0" + normalize-range "^0.1.2" + picocolors "^1.0.0" + postcss-value-parser "^4.2.0" + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +binary-extensions@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^3.0.2, braces@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +browserslist@^4.21.5: + version "4.21.9" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.9.tgz#e11bdd3c313d7e2a9e87e8b4b0c7872b13897635" + integrity sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg== + dependencies: + caniuse-lite "^1.0.30001503" + electron-to-chromium "^1.4.431" + node-releases "^2.0.12" + update-browserslist-db "^1.0.11" + +camelcase-css@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5" + integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA== + +caniuse-lite@^1.0.30001464, caniuse-lite@^1.0.30001503: + version "1.0.30001517" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001517.tgz#90fabae294215c3495807eb24fc809e11dc2f0a8" + integrity sha512-Vdhm5S11DaFVLlyiKu4hiUTkpZu+y1KA/rZZqVQfOD5YdDT/eQKlkt7NaE0WGOFgX32diqt9MiP9CAiFeRklaA== + +chokidar@^3.5.3: + version "3.5.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +codemirror@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-6.0.1.tgz#62b91142d45904547ee3e0e0e4c1a79158035a29" + integrity sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg== + dependencies: + "@codemirror/autocomplete" "^6.0.0" + "@codemirror/commands" "^6.0.0" + "@codemirror/language" "^6.0.0" + "@codemirror/lint" "^6.0.0" + "@codemirror/search" "^6.0.0" + "@codemirror/state" "^6.0.0" + "@codemirror/view" "^6.0.0" + +commander@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" + integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +crelt@^1.0.5: + version "1.0.6" + resolved "https://registry.yarnpkg.com/crelt/-/crelt-1.0.6.tgz#7cc898ea74e190fb6ef9dae57f8f81cf7302df72" + integrity sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g== + +cssesc@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" + integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== + +didyoumean@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/didyoumean/-/didyoumean-1.2.2.tgz#989346ffe9e839b4555ecf5666edea0d3e8ad037" + integrity sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw== + +dlv@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/dlv/-/dlv-1.1.3.tgz#5c198a8a11453596e751494d49874bc7732f2e79" + integrity sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA== + +electron-to-chromium@^1.4.431: + version "1.4.468" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.468.tgz#3cbf64ad67d9f12bfe69fefe5eb1935ec4f6ab7a" + integrity sha512-6M1qyhaJOt7rQtNti1lBA0GwclPH+oKCmsra/hkcWs5INLxfXXD/dtdnaKUYQu/pjOBP/8Osoe4mAcNvvzoFag== + +esbuild@^0.18.10: + version "0.18.16" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.18.16.tgz#bbeb058c556152bcbff4e8168e7c93020ccf09c3" + integrity sha512-1xLsOXrDqwdHxyXb/x/SOyg59jpf/SH7YMvU5RNSU7z3TInaASNJWNFJ6iRvLvLETZMasF3d1DdZLg7sgRimRQ== + optionalDependencies: + "@esbuild/android-arm" "0.18.16" + "@esbuild/android-arm64" "0.18.16" + "@esbuild/android-x64" "0.18.16" + "@esbuild/darwin-arm64" "0.18.16" + "@esbuild/darwin-x64" "0.18.16" + "@esbuild/freebsd-arm64" "0.18.16" + "@esbuild/freebsd-x64" "0.18.16" + "@esbuild/linux-arm" "0.18.16" + "@esbuild/linux-arm64" "0.18.16" + "@esbuild/linux-ia32" "0.18.16" + "@esbuild/linux-loong64" "0.18.16" + "@esbuild/linux-mips64el" "0.18.16" + "@esbuild/linux-ppc64" "0.18.16" + "@esbuild/linux-riscv64" "0.18.16" + "@esbuild/linux-s390x" "0.18.16" + "@esbuild/linux-x64" "0.18.16" + "@esbuild/netbsd-x64" "0.18.16" + "@esbuild/openbsd-x64" "0.18.16" + "@esbuild/sunos-x64" "0.18.16" + "@esbuild/win32-arm64" "0.18.16" + "@esbuild/win32-ia32" "0.18.16" + "@esbuild/win32-x64" "0.18.16" + +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + +fast-glob@^3.2.12: + version "3.3.1" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.1.tgz#784b4e897340f3dbbef17413b3f11acf03c874c4" + integrity sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + +fastq@^1.6.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a" + integrity sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw== + dependencies: + reusify "^1.0.4" + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +fraction.js@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.2.0.tgz#448e5109a313a3527f5a3ab2119ec4cf0e0e2950" + integrity sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA== + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +fsevents@~2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +glob-parent@^5.1.2, glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob-parent@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== + dependencies: + is-glob "^4.0.3" + +glob@7.1.6: + version "7.1.6" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" + integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-core-module@^2.11.0: + version "2.12.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.12.1.tgz#0c0b6885b6f80011c71541ce15c8d66cf5a4f9fd" + integrity sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg== + dependencies: + has "^1.0.3" + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +jiti@^1.18.2: + version "1.19.1" + resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.19.1.tgz#fa99e4b76a23053e0e7cde098efe1704a14c16f1" + integrity sha512-oVhqoRDaBXf7sjkll95LHVS6Myyyb1zaunVwk4Z0+WPSW4gjS0pl01zYKHScTuyEhQsFxV5L4DR5r+YqSyqyyg== + +lilconfig@^2.0.5, lilconfig@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.1.0.tgz#78e23ac89ebb7e1bfbf25b18043de756548e7f52" + integrity sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ== + +lines-and-columns@^1.1.6: + version "1.2.4" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" + integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== + +merge2@^1.3.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +micromatch@^4.0.4, micromatch@^4.0.5: + version "4.0.5" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + dependencies: + braces "^3.0.2" + picomatch "^2.3.1" + +minimatch@^3.0.4: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +mz@^2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" + integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q== + dependencies: + any-promise "^1.0.0" + object-assign "^4.0.1" + thenify-all "^1.0.0" + +nanoid@^3.3.6: + version "3.3.6" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.6.tgz#443380c856d6e9f9824267d960b4236ad583ea4c" + integrity sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA== + +node-releases@^2.0.12: + version "2.0.13" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.13.tgz#d5ed1627c23e3461e819b02e57b75e4899b1c81d" + integrity sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ== + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +normalize-range@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" + integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA== + +object-assign@^4.0.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== + +object-hash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-3.0.0.tgz#73f97f753e7baffc0e2cc9d6e079079744ac82e9" + integrity sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw== + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +picocolors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" + integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== + +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +pify@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog== + +pirates@^4.0.1: + version "4.0.6" + resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9" + integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg== + +postcss-import@^15.1.0: + version "15.1.0" + resolved "https://registry.yarnpkg.com/postcss-import/-/postcss-import-15.1.0.tgz#41c64ed8cc0e23735a9698b3249ffdbf704adc70" + integrity sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew== + dependencies: + postcss-value-parser "^4.0.0" + read-cache "^1.0.0" + resolve "^1.1.7" + +postcss-js@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-js/-/postcss-js-4.0.1.tgz#61598186f3703bab052f1c4f7d805f3991bee9d2" + integrity sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw== + dependencies: + camelcase-css "^2.0.1" + +postcss-load-config@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-4.0.1.tgz#152383f481c2758274404e4962743191d73875bd" + integrity sha512-vEJIc8RdiBRu3oRAI0ymerOn+7rPuMvRXslTvZUKZonDHFIczxztIyJ1urxM1x9JXEikvpWWTUUqal5j/8QgvA== + dependencies: + lilconfig "^2.0.5" + yaml "^2.1.1" + +postcss-nested@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/postcss-nested/-/postcss-nested-6.0.1.tgz#f83dc9846ca16d2f4fa864f16e9d9f7d0961662c" + integrity sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ== + dependencies: + postcss-selector-parser "^6.0.11" + +postcss-selector-parser@^6.0.11: + version "6.0.13" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz#d05d8d76b1e8e173257ef9d60b706a8e5e99bf1b" + integrity sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ== + dependencies: + cssesc "^3.0.0" + util-deprecate "^1.0.2" + +postcss-value-parser@^4.0.0, postcss-value-parser@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" + integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== + +postcss@^8.4.23, postcss@^8.4.26, postcss@^8.4.27: + version "8.4.27" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.27.tgz#234d7e4b72e34ba5a92c29636734349e0d9c3057" + integrity sha512-gY/ACJtJPSmUFPDCHtX78+01fHa64FaU4zaaWfuh1MhGJISufJAH4cun6k/8fwsHYeK4UQmENQK+tRLCFJE8JQ== + dependencies: + nanoid "^3.3.6" + picocolors "^1.0.0" + source-map-js "^1.0.2" + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +read-cache@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/read-cache/-/read-cache-1.0.0.tgz#e664ef31161166c9751cdbe8dbcf86b5fb58f774" + integrity sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA== + dependencies: + pify "^2.3.0" + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +resolve@^1.1.7, resolve@^1.22.2: + version "1.22.2" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.2.tgz#0ed0943d4e301867955766c9f3e1ae6d01c6845f" + integrity sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g== + dependencies: + is-core-module "^2.11.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +rollup@^3.25.2: + version "3.26.3" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-3.26.3.tgz#bbc8818cadd0aebca348dbb3d68d296d220967b8" + integrity sha512-7Tin0C8l86TkpcMtXvQu6saWH93nhG3dGQ1/+l5V2TDMceTxO7kDiK6GzbfLWNNxqJXm591PcEZUozZm51ogwQ== + optionalDependencies: + fsevents "~2.3.2" + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +source-map-js@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" + integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== + +style-mod@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/style-mod/-/style-mod-4.0.3.tgz#136c4abc905f82a866a18b39df4dc08ec762b1ad" + integrity sha512-78Jv8kYJdjbvRwwijtCevYADfsI0lGzYJe4mMFdceO8l75DFFDoqBhR1jVDicDRRaX4//g1u9wKeo+ztc2h1Rw== + +sucrase@^3.32.0: + version "3.34.0" + resolved "https://registry.yarnpkg.com/sucrase/-/sucrase-3.34.0.tgz#1e0e2d8fcf07f8b9c3569067d92fbd8690fb576f" + integrity sha512-70/LQEZ07TEcxiU2dz51FKaE6hCTWC6vr7FOk3Gr0U60C3shtAN+H+BFr9XlYe5xqf3RA8nrc+VIwzCfnxuXJw== + dependencies: + "@jridgewell/gen-mapping" "^0.3.2" + commander "^4.0.0" + glob "7.1.6" + lines-and-columns "^1.1.6" + mz "^2.7.0" + pirates "^4.0.1" + ts-interface-checker "^0.1.9" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +tailwindcss@^3.3.3: + version "3.3.3" + resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.3.3.tgz#90da807393a2859189e48e9e7000e6880a736daf" + integrity sha512-A0KgSkef7eE4Mf+nKJ83i75TMyq8HqY3qmFIJSWy8bNt0v1lG7jUcpGpoTFxAwYcWOphcTBLPPJg+bDfhDf52w== + dependencies: + "@alloc/quick-lru" "^5.2.0" + arg "^5.0.2" + chokidar "^3.5.3" + didyoumean "^1.2.2" + dlv "^1.1.3" + fast-glob "^3.2.12" + glob-parent "^6.0.2" + is-glob "^4.0.3" + jiti "^1.18.2" + lilconfig "^2.1.0" + micromatch "^4.0.5" + normalize-path "^3.0.0" + object-hash "^3.0.0" + picocolors "^1.0.0" + postcss "^8.4.23" + postcss-import "^15.1.0" + postcss-js "^4.0.1" + postcss-load-config "^4.0.1" + postcss-nested "^6.0.1" + postcss-selector-parser "^6.0.11" + resolve "^1.22.2" + sucrase "^3.32.0" + +thenify-all@^1.0.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726" + integrity sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA== + dependencies: + thenify ">= 3.1.0 < 4" + +"thenify@>= 3.1.0 < 4": + version "3.3.1" + resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.1.tgz#8932e686a4066038a016dd9e2ca46add9838a95f" + integrity sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw== + dependencies: + any-promise "^1.0.0" + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +ts-interface-checker@^0.1.9: + version "0.1.13" + resolved "https://registry.yarnpkg.com/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz#784fd3d679722bc103b1b4b8030bcddb5db2a699" + integrity sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA== + +typescript@^5.0.2: + version "5.1.6" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.1.6.tgz#02f8ac202b6dad2c0dd5e0913745b47a37998274" + integrity sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA== + +update-browserslist-db@^1.0.11: + version "1.0.11" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz#9a2a641ad2907ae7b3616506f4b977851db5b940" + integrity sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA== + dependencies: + escalade "^3.1.1" + picocolors "^1.0.0" + +util-deprecate@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + +vite@^4.4.5: + version "4.4.6" + resolved "https://registry.yarnpkg.com/vite/-/vite-4.4.6.tgz#97a0a43868ec773fd88980d7c323c80233521cf1" + integrity sha512-EY6Mm8vJ++S3D4tNAckaZfw3JwG3wa794Vt70M6cNJ6NxT87yhq7EC8Rcap3ahyHdo8AhCmV9PTk+vG1HiYn1A== + dependencies: + esbuild "^0.18.10" + postcss "^8.4.26" + rollup "^3.25.2" + optionalDependencies: + fsevents "~2.3.2" + +w3c-keyname@^2.2.4: + version "2.2.8" + resolved "https://registry.yarnpkg.com/w3c-keyname/-/w3c-keyname-2.2.8.tgz#7b17c8c6883d4e8b86ac8aba79d39e880f8869c5" + integrity sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ== + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +yaml@^2.1.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.1.tgz#02fe0975d23cd441242aa7204e09fc28ac2ac33b" + integrity sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ== + +zzfx@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/zzfx/-/zzfx-1.2.0.tgz#021e5df8e1605f507e2dde15608eba22798b424b" + integrity sha512-RtFz6PTMfCmxTfaCOv6GWAV4YaL/T0hltiMGkd87clybO8WLPlH6kX8sNkZGFKw9YPyu1UNsUYf/5/Vn4dondA==