Cleanup and build script update

This commit is contained in:
Anton Duda 2025-10-24 19:37:01 +03:00
parent 0ef71cd431
commit 28652c6b31
9 changed files with 40 additions and 173 deletions

View file

@ -5,6 +5,19 @@ source ./.env
# Exit immediately if a command exits with a non-zero status.
set -e
if [ "$1" = "prod" ]; then
TARGET_DIR="$TARGET_VAULT_DIR"
echo ">>> Building for PROD vault"
else
TARGET_DIR="$TARGET_TEST_VAULT_DIR"
echo ">>> Building for TEST vault"
fi
if [ -z "$TARGET_DIR" ]; then
echo "Error: Target directory is not defined. Check your .env file."
exit 1
fi
# Define plugin source and build directories
PLUGIN_DIR="."
BUILD_DIR="$PLUGIN_DIR/build"
@ -24,18 +37,19 @@ npm run build
echo "--- Copying Plugin Files to Test Vault ---"
# Create target directory in test vault if it doesn't exist
mkdir -p "$TARGET_TEST_VAULT_DIR"
echo "Ensured target directory exists: $TARGET_TEST_VAULT_DIR"
mkdir -p "$TARGET_DIR"
echo "Ensured target directory exists: $TARGET_DIR"
# Copy built files
cp "$BUILD_DIR/main.js" "$TARGET_TEST_VAULT_DIR/main.js"
cp -X "$BUILD_DIR/main.js" "$TARGET_DIR/main.js"
echo "Copied main.js"
cp "$BUILD_DIR/main.css" "$TARGET_TEST_VAULT_DIR/styles.css"
cp -X "$BUILD_DIR/main.css" "$TARGET_DIR/styles.css"
echo "Copied styles.css"
cp "$PLUGIN_DIR/manifest.json" "$TARGET_TEST_VAULT_DIR/manifest.json"
cp -X "$PLUGIN_DIR/manifest.json" "$TARGET_DIR/manifest.json"
echo "Copied manifest.json"
echo "--- Plugin Build and Copy Complete ---"
echo "Plugin files are ready in: $TARGET_TEST_VAULT_DIR"
echo "Plugin files are ready in: $TARGET_DIR"

View file

@ -1,35 +0,0 @@
#!/bin/bash
# Exit immediately if a command exits with a non-zero status.
set -e
# Define plugin source and build directories
PLUGIN_DIR="."
BUILD_DIR="$PLUGIN_DIR/build"
echo "--- Building Strudel Obsidian Plugin ---"
# Install dependencies if node_modules doesn't exist
if [ ! -d "node_modules" ]; then
echo "Node modules not found. Installing dependencies..."
npm install
fi
# Run the build script
echo "Running build..."
npm run build
echo "--- Copying Plugin Files to Test Vault ---"
# Copy built files
cp -X "$BUILD_DIR/main.js" "$TARGET_VAULT_DIR/main.js"
echo "Copied main.js"
cp -X "$BUILD_DIR/main.css" "$TARGET_VAULT_DIR/styles.css"
echo "Copied styles.css"
cp -X "$PLUGIN_DIR/manifest.json" "$TARGET_VAULT_DIR/manifest.json"
echo "Copied manifest.json"
echo "--- Plugin Build and Copy Complete ---"
echo "Plugin files are ready in: $TARGET_VAULT_DIR"

View file

@ -3,7 +3,7 @@
"name": "Strudel REPL",
"version": "0.0.1",
"minAppVersion": "1.9.14",
"description": "",
"description": "Live-coding music environment — Strudel REPL integrated into your vault.",
"author": "Anton Duda",
"isDesktopOnly": false
}

View file

@ -6,6 +6,8 @@
"scripts": {
"dev": "vite preview",
"build": "tsc -noEmit -skipLibCheck && vite build",
"deploy:test": "bash ./build_and_copy_plugin.sh",
"deploy:prod": "bash ./build_and_copy_plugin.sh prod",
"version": "node version-bump.mjs && git add manifest.json versions.json"
},
"keywords": [],

View file

@ -8,85 +8,27 @@
<ObsidianIcon v-if="isCurrentBlockPlaying" icon="refresh-ccw" @click="play()" />
</div>
<canvas v-show="isCurrentBlockPlaying" ref="canvas"></canvas>
<!-- <div ref="editorRef"></div> -->
</div>
</template>
<script setup lang="ts">
import ObsidianIcon from './obsidian/Icon.vue'
import { Strudel } from '@/entities/Strudel'
import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
import { initStrudel } from '@/strudel/init.js'
import { computed, onMounted, onUnmounted, ref } from 'vue'
import { GlobalStore } from '@/stores/GlobalStore'
import { updateMiniLocations } from '@/editor/StrudelHighlight'
import { MarkdownView, WorkspaceLeaf } from 'obsidian'
import { EditorView } from '@codemirror/view'
const props = defineProps<{
strudelBlock: Strudel
}>()
const editorRef = ref<HTMLElement | null>(null)
const { isPlaying, currentBlock } = GlobalStore.getInstance()
const isCurrentBlockPlaying = computed(() => {
return isPlaying.value && currentBlock.value?.id === props.strudelBlock.id
})
watch(
() => props.strudelBlock,
(newBlock) => {
if (isCurrentBlockPlaying.value) {
// GlobalStore.getInstance().repl.setCode(newBlock.code)
// GlobalStore.getInstance().resetMiniLocations()
}
},
{ deep: true }
)
const canvas = ref<HTMLCanvasElement | null>(null)
//
// const editor = new StrudelMirror({
// defaultOutput: webaudioOutput,
// getTime: () => getAudioContext().currentTime,
// transpiler,
// root: document.getElementById('editor'),
// initialCode: funk42,
// drawTime,
// onDraw: (haps, time) => drawPianoroll({ haps, time, ctx: drawContext, drawTime, fold: 0 }),
// prebake: async () => {
// initAudioOnFirstClick(); // needed to make the browser happy (don't await this here..)
// const loadModules = evalScope(
// import('@strudel/core'),
// import('@strudel/draw'),
// import('@strudel/mini'),
// import('@strudel/tonal'),
// import('@strudel/webaudio'),
// );
// await Promise.all([loadModules, registerSynthSounds(), registerSoundfonts()]);
// },
// });
//
// document.getElementById('play').addEventListener('click', () => editor.evaluate());
// document.getElementById('stop').addEventListener('click', () => editor.stop());
const test = () => {
const activeLeaf = GlobalStore.getInstance()
.app.workspace.getLeavesOfType('markdown')
.find(
(leaf: WorkspaceLeaf) =>
(leaf.view as MarkdownView).file?.path === props.strudelBlock.filePath
)
const view = activeLeaf?.view as MarkdownView
if (activeLeaf && view.editor) {
// updateMiniLocations((view.editor as any).cm as EditorView, [])
}
}
const play = () => {
GlobalStore.getInstance().play(props.strudelBlock)
}

View file

@ -29,8 +29,6 @@ const miniLocations = StateField.define<DecorationSet>({
locations = locations.map(tr.changes)
}
// console.log('miniLocations update', tr.effects)
for (const e of tr.effects) {
if (e.is(setMiniLocations)) {
// this is called on eval, with the mini locations obtained from the transpiler
@ -71,14 +69,11 @@ const visibleMiniLocations = StateField.define<{
// we can NOT create new marks because the context.locations haven't changed since eval time
// this is why we need to find a way to update the existing decorations, showing the ones that have an active range
const haps = new Map()
// console.log(e.value, e.value.haps)
for (const hap of e.value.haps) {
if (!hap.context?.locations || !hap.whole) {
continue
}
for (const { start, end } of hap.context.locations) {
// start += e.value.shift
// end += e.value.shift
const id = `${start}:${end}`
if (!haps.has(id) || haps.get(id).whole.begin.lt(hap.whole.begin)) {
haps.set(id, hap)
@ -101,8 +96,6 @@ const miniLocationHighlights = EditorView.decorations.compute(
const { haps } = state.field(visibleMiniLocations)
const builder = new RangeSetBuilder<Decoration>()
// console.log('highlighting mini locations', haps, shift)
while (iterator.value) {
const {
from,
@ -112,12 +105,9 @@ const miniLocationHighlights = EditorView.decorations.compute(
},
} = iterator
// console.log(haps, id)
if (haps.has(id)) {
const hap = haps.get(id)
const colorMod = hap.value?.color ? ` strudel-mark_${hap.value.color}` : ''
// const style = hap.value?.markcss || `outline: solid 2px ${color}`
const classStr = `strudel-mark${colorMod}`
// Get explicit channels for color values
/*
@ -139,7 +129,6 @@ const miniLocationHighlights = EditorView.decorations.compute(
from,
to,
Decoration.mark({
// attributes: { style: `outline: solid 2px rgba(${channels.join(', ')})` },
attributes: { class: classStr },
})
)
@ -154,11 +143,3 @@ const miniLocationHighlights = EditorView.decorations.compute(
export const highlightExtension = [miniLocations, visibleMiniLocations, miniLocationHighlights]
// export const isPatternHighlightingEnabled = (on, config) => {
// on &&
// config &&
// setTimeout(() => {
// updateMiniLocations(config.editor, config.miniLocations)
// }, 100)
// return on ? Prec.highest(highlightExtension) : []
// }

View file

@ -5,8 +5,6 @@ export class Strudel {
public lineFrom: number
public drawContext: CanvasRenderingContext2D | null = null
public lineFromWhenPlaybackStarts: number | null = null
constructor(data: { id: string; code: string; filePath: string; lineFrom: number }) {
this.id = data.id
this.code = data.code
@ -24,12 +22,4 @@ export class Strudel {
setDrawContext(ctx: CanvasRenderingContext2D) {
this.drawContext = ctx
}
playbackStarted() {
this.lineFromWhenPlaybackStarts = this.lineFrom
}
playbackStopped() {
this.lineFromWhenPlaybackStarts = null
}
}

View file

@ -6,19 +6,21 @@ interface StrudelConfigData {
samplesToPreload: string[]
}
const defaultSamples: string[] = [
'https://raw.githubusercontent.com/felixroos/dough-samples/main/tidal-drum-machines.json',
'https://raw.githubusercontent.com/felixroos/dough-samples/main/piano.json',
'https://raw.githubusercontent.com/felixroos/dough-samples/main/Dirt-Samples.json',
'https://raw.githubusercontent.com/felixroos/dough-samples/main/EmuSP12.json',
'https://raw.githubusercontent.com/felixroos/dough-samples/main/vcsl.json',
'https://raw.githubusercontent.com/felixroos/dough-samples/main/mridangam.json',
]
export class StrudelConfig {
private static instance: StrudelConfig
public cacheDir: string | null = null
public saveToCache = true
public samplesToPreload: string[] = [
'https://raw.githubusercontent.com/felixroos/dough-samples/main/tidal-drum-machines.json',
'https://raw.githubusercontent.com/felixroos/dough-samples/main/piano.json',
'https://raw.githubusercontent.com/felixroos/dough-samples/main/Dirt-Samples.json',
'https://raw.githubusercontent.com/felixroos/dough-samples/main/EmuSP12.json',
'https://raw.githubusercontent.com/felixroos/dough-samples/main/vcsl.json',
'https://raw.githubusercontent.com/felixroos/dough-samples/main/mridangam.json',
]
public samplesToPreload: string[] = [...defaultSamples]
// eslint-disable-next-line @typescript-eslint/no-empty-function
private constructor() {}
@ -30,12 +32,14 @@ export class StrudelConfig {
return StrudelConfig.instance
}
public applySettings(data: StrudelConfigData): void {
this.cacheDir = data.cacheDir || null
if (data.saveToCache !== undefined) {
public applySettings(data?: StrudelConfigData): void {
this.cacheDir = data?.cacheDir || null
if (data?.saveToCache !== undefined) {
this.saveToCache = data.saveToCache
}
this.samplesToPreload = data.samplesToPreload ? [...data.samplesToPreload] : []
this.samplesToPreload = data?.samplesToPreload
? [...data.samplesToPreload]
: [...defaultSamples]
}
public getCacheDir(): string | null {

View file

@ -62,33 +62,13 @@ export class GlobalStore {
public drawer: any | null = null
// public resetMiniLocations() {
// const editor = this.getActiveEditor()
// if (this.currentBlock.value && editor) {
// updateMiniLocations(this.getActiveEditor(), [])
// }
// }
// public recalculateMiniLocations() {
// if (this.currentBlock.value) {
// const locations = recalculateMiniLocations(this.currentBlock.value.code)
// updateMiniLocations(this.getActiveEditor(), locations || [])
// }
// }
public async initStrudel() {
this.repl = await init({
afterEval: (options: any) => {
// console.log('afterEval', options.meta?.miniLocations)
if (options.meta?.miniLocations) {
const locations = options.meta.miniLocations
// for (const loc of locations) {
// loc[0] = loc[0] + this.currentBlock.lineFrom
// loc[1] = loc[1] + this.currentBlock.lineFrom
// }
const editor = this.getActiveEditor()
if (this.currentBlock.value && editor) {
this.currentBlock.value.playbackStarted()
updateMiniLocations(editor, locations || [], this.currentBlock.value.lineFrom)
}
}
@ -100,22 +80,12 @@ export class GlobalStore {
},
onToggle: (started: boolean) => {
if (started) {
this.currentBlock.value.playbackStarted()
this.drawer.start(this.repl.scheduler)
// if (this.solo) {
// // stop other repls when this one is started
// document.dispatchEvent(
// new CustomEvent('start-repl', {
// detail: this.id,
// })
// )
// }
} else {
this.drawer.stop()
const editor = this.getActiveEditor()
if (editor) {
this.currentBlock.value?.playbackStopped()
updateMiniLocations(editor, [], 0)
}
@ -133,7 +103,6 @@ export class GlobalStore {
return
}
// console.log(this.currentBlock.value.lineFrom)
const currentFrame = haps.filter((hap: any) => hap.isActive(time))
highlightMiniLocations(editor, time, currentFrame)