mirror of
https://github.com/dudaanton/obsidian-strudel-plugin.git
synced 2026-07-22 16:30:26 +00:00
Compare commits
No commits in common. "master" and "0.0.2" have entirely different histories.
17 changed files with 945 additions and 4043 deletions
3
.eslintignore
Normal file
3
.eslintignore
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
node_modules/
|
||||
|
||||
main.js
|
||||
84
.eslintrc
Normal file
84
.eslintrc
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
{
|
||||
"parser": "vue-eslint-parser",
|
||||
"plugins": ["@typescript-eslint/eslint-plugin", "eslint-plugin-vue", "prettier"],
|
||||
"extends": ["plugin:@typescript-eslint/recommended", "plugin:vue/vue3-recommended", "plugin:prettier/recommended"],
|
||||
"parserOptions": {
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"ecmaVersion": 2018,
|
||||
"sourceType": "module"
|
||||
},
|
||||
"env": {
|
||||
"node": true
|
||||
},
|
||||
"ignorePatterns": [
|
||||
"docker-formatter.*",
|
||||
"node_modules/*",
|
||||
".nuxt/*",
|
||||
"dist/*",
|
||||
"dist-electron/*",
|
||||
"server/*",
|
||||
"scripts/*",
|
||||
"src/assets/*"
|
||||
],
|
||||
"rules": {
|
||||
"arrow-body-style": 0,
|
||||
"class-methods-use-this": 0,
|
||||
"comma-dangle": 0,
|
||||
"func-names": 0,
|
||||
"import/extensions": 0,
|
||||
"import/no-dynamic-require": 0,
|
||||
"import/no-extraneous-dependencies": 0,
|
||||
"import/no-named-as-default-member": 0,
|
||||
"import/no-unresolved": 0,
|
||||
"import/prefer-default-export": 0,
|
||||
"linebreak-style": 0,
|
||||
"max-len": [
|
||||
"warn",
|
||||
{
|
||||
"code": 120,
|
||||
"ignoreTemplateLiterals": true,
|
||||
"ignoreComments": true,
|
||||
"ignoreStrings": true
|
||||
}
|
||||
],
|
||||
"no-await-in-loop": 0,
|
||||
"no-console": 0,
|
||||
"no-loop-func": 0,
|
||||
"no-mixed-operators": 0,
|
||||
"no-param-reassign": 0,
|
||||
"no-restricted-syntax": 0,
|
||||
"no-shadow": 0,
|
||||
"no-trailing-spaces": 1,
|
||||
"no-underscore-dangle": 0,
|
||||
"no-use-before-define": 0,
|
||||
"prefer-destructuring": 0,
|
||||
"semi": 0,
|
||||
"space-before-function-paren": 0,
|
||||
"vue/multi-word-component-names": "off",
|
||||
"vue/no-dupe-keys": "warn",
|
||||
"vue/no-mutating-props": ["warn", { "shallowOnly": true }],
|
||||
"vue/no-unused-vars": ["warn", { "ignorePattern": "^_" }],
|
||||
"vue/no-use-v-if-with-v-for": "warn",
|
||||
"vue/prop-name-casing": "error",
|
||||
"vue/return-in-computed-property": "off",
|
||||
"vue/require-prop-types": "error",
|
||||
"vue/require-toggle-inside-transition": "warn",
|
||||
"vue/require-typed-object-prop": "error",
|
||||
"vue/require-v-for-key": "warn",
|
||||
"vue/valid-v-for": "warn",
|
||||
"@typescript-eslint/explicit-function-return-type": "off",
|
||||
"@typescript-eslint/no-empty-interface": "off",
|
||||
"@typescript-eslint/no-explicit-any": 0,
|
||||
"@typescript-eslint/no-inferrable-types": ["warn", { "ignoreParameters": true }],
|
||||
"@typescript-eslint/no-unsafe-declaration-merging": "off",
|
||||
"@typescript-eslint/no-unused-vars": [
|
||||
"warn",
|
||||
{
|
||||
"argsIgnorePattern": "^_",
|
||||
"varsIgnorePattern": "^_"
|
||||
}
|
||||
],
|
||||
"prettier/prettier": ["warn"]
|
||||
}
|
||||
}
|
||||
|
||||
3
.npmrc
3
.npmrc
|
|
@ -1,2 +1 @@
|
|||
tag-version-prefix=""
|
||||
legacy-peer-deps=true
|
||||
tag-version-prefix=""
|
||||
|
|
@ -1,149 +0,0 @@
|
|||
import obsidianmd from "eslint-plugin-obsidianmd";
|
||||
import vue from "eslint-plugin-vue";
|
||||
import tseslint from "typescript-eslint";
|
||||
import vueParser from "vue-eslint-parser";
|
||||
import prettierRecommended from "eslint-plugin-prettier/recommended";
|
||||
|
||||
export default [
|
||||
{
|
||||
ignores: [
|
||||
"node_modules/**",
|
||||
"build/**",
|
||||
"dist/**",
|
||||
"main.js",
|
||||
"src/strudel/**",
|
||||
"src/assets/**",
|
||||
"docker-formatter.*",
|
||||
],
|
||||
},
|
||||
|
||||
...obsidianmd.configs.recommended,
|
||||
|
||||
// Workaround: obsidianmd recommended preset declares the typed rule
|
||||
// `no-plugin-as-component` globally, which crashes on non-TS files
|
||||
// (it calls getParserServices). Disable it for everything except TS.
|
||||
{
|
||||
files: ["**/*.json", "**/*.vue", "**/*.js", "**/*.mjs", "**/*.cjs"],
|
||||
rules: {
|
||||
"obsidianmd/no-plugin-as-component": "off",
|
||||
},
|
||||
},
|
||||
|
||||
// Preserve product/acronym casing in UI strings. `ignoreWords` is
|
||||
// case-sensitive, so list every form that appears in source.
|
||||
{
|
||||
rules: {
|
||||
"obsidianmd/ui/sentence-case": [
|
||||
"error",
|
||||
{
|
||||
enforceCamelCaseLower: true,
|
||||
ignoreWords: ["Strudel", "strudel", "REPL", "repl", "URLs", "urls", "URL", "url"],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
|
||||
...vue.configs["flat/recommended"],
|
||||
|
||||
{
|
||||
files: ["**/*.vue"],
|
||||
languageOptions: {
|
||||
parser: vueParser,
|
||||
parserOptions: {
|
||||
parser: tseslint.parser,
|
||||
ecmaVersion: "latest",
|
||||
sourceType: "module",
|
||||
extraFileExtensions: [".vue"],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
files: ["src/**/*.ts", "src/**/*.tsx"],
|
||||
languageOptions: {
|
||||
parserOptions: {
|
||||
projectService: true,
|
||||
tsconfigRootDir: import.meta.dirname,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
prettierRecommended,
|
||||
|
||||
// Generic rules — apply to all linted files
|
||||
{
|
||||
rules: {
|
||||
"arrow-body-style": 0,
|
||||
"class-methods-use-this": 0,
|
||||
"comma-dangle": 0,
|
||||
"func-names": 0,
|
||||
"linebreak-style": 0,
|
||||
"max-len": [
|
||||
"warn",
|
||||
{
|
||||
code: 120,
|
||||
ignoreTemplateLiterals: true,
|
||||
ignoreComments: true,
|
||||
ignoreStrings: true,
|
||||
},
|
||||
],
|
||||
"no-await-in-loop": 0,
|
||||
"no-console": 0,
|
||||
"no-loop-func": 0,
|
||||
"no-mixed-operators": 0,
|
||||
"no-param-reassign": 0,
|
||||
"no-restricted-syntax": 0,
|
||||
"no-shadow": 0,
|
||||
"no-trailing-spaces": 1,
|
||||
"no-underscore-dangle": 0,
|
||||
"no-use-before-define": 0,
|
||||
"prefer-destructuring": 0,
|
||||
semi: 0,
|
||||
"space-before-function-paren": 0,
|
||||
"prettier/prettier": ["warn"],
|
||||
},
|
||||
},
|
||||
|
||||
// Vue rules — apply only to .vue files
|
||||
{
|
||||
files: ["**/*.vue"],
|
||||
rules: {
|
||||
"vue/multi-word-component-names": "off",
|
||||
"vue/no-dupe-keys": "warn",
|
||||
"vue/no-mutating-props": ["warn", { shallowOnly: true }],
|
||||
"vue/no-unused-vars": ["warn", { ignorePattern: "^_" }],
|
||||
"vue/no-use-v-if-with-v-for": "warn",
|
||||
"vue/prop-name-casing": "error",
|
||||
"vue/return-in-computed-property": "off",
|
||||
"vue/require-prop-types": "error",
|
||||
"vue/require-toggle-inside-transition": "warn",
|
||||
"vue/require-typed-object-prop": "error",
|
||||
"vue/require-v-for-key": "warn",
|
||||
"vue/valid-v-for": "warn",
|
||||
},
|
||||
},
|
||||
|
||||
// TS rules — apply only where @typescript-eslint plugin is registered
|
||||
{
|
||||
files: ["**/*.ts", "**/*.tsx"],
|
||||
rules: {
|
||||
"@typescript-eslint/explicit-function-return-type": "off",
|
||||
"@typescript-eslint/no-empty-interface": "off",
|
||||
"@typescript-eslint/no-explicit-any": 0,
|
||||
"@typescript-eslint/no-inferrable-types": ["warn", { ignoreParameters: true }],
|
||||
"@typescript-eslint/no-unsafe-declaration-merging": "off",
|
||||
"@typescript-eslint/no-unsafe-argument": "off",
|
||||
"@typescript-eslint/no-unsafe-assignment": "off",
|
||||
"@typescript-eslint/no-unsafe-call": "off",
|
||||
"@typescript-eslint/no-unsafe-member-access": "off",
|
||||
"@typescript-eslint/no-unsafe-return": "off",
|
||||
"@typescript-eslint/no-unused-vars": [
|
||||
"warn",
|
||||
{
|
||||
argsIgnorePattern: "^_",
|
||||
varsIgnorePattern: "^_",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
];
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"id": "strudel-repl",
|
||||
"name": "Strudel REPL",
|
||||
"version": "0.0.3",
|
||||
"version": "0.0.2",
|
||||
"minAppVersion": "1.9.14",
|
||||
"description": "Live-coding music environment — Strudel REPL integrated into your vault.",
|
||||
"author": "Anton Duda",
|
||||
|
|
|
|||
4546
package-lock.json
generated
4546
package-lock.json
generated
File diff suppressed because it is too large
Load diff
21
package.json
21
package.json
|
|
@ -1,12 +1,11 @@
|
|||
{
|
||||
"name": "strudel-obsidian-plugin",
|
||||
"version": "0.0.3",
|
||||
"version": "0.0.2",
|
||||
"description": "Strudel REPL Obsidian plugin",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
"dev": "vite preview",
|
||||
"build": "tsc -noEmit -skipLibCheck && vite build",
|
||||
"lint": "eslint \"src/**/*.{ts,tsx,vue}\"",
|
||||
"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"
|
||||
|
|
@ -19,34 +18,28 @@
|
|||
"@types/js-yaml": "^4.0.9",
|
||||
"@types/luxon": "^3.6.2",
|
||||
"@types/node": "^24.9.1",
|
||||
"@typescript-eslint/eslint-plugin": "^8.60.0",
|
||||
"@typescript-eslint/parser": "^8.60.0",
|
||||
"@typescript-eslint/eslint-plugin": "5.61.0",
|
||||
"@typescript-eslint/parser": "5.61.0",
|
||||
"@vitejs/plugin-vue": "^5.2.4",
|
||||
"builtin-modules": "3.3.0",
|
||||
"esbuild": "0.17.3",
|
||||
"esbuild-plugin-vue3": "^0.3.2",
|
||||
"eslint": "^10.4.1",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"eslint-plugin-obsidianmd": "^0.3.0",
|
||||
"eslint-plugin-prettier": "^5.5.6",
|
||||
"eslint-plugin-vue": "^10.9.1",
|
||||
"globals": "^17.6.0",
|
||||
"eslint": "8.31.0",
|
||||
"eslint-config-prettier": "9.0.0",
|
||||
"eslint-plugin-prettier": "5.0.0",
|
||||
"eslint-plugin-vue": "9.23.0",
|
||||
"obsidian": "latest",
|
||||
"prettier": "^3.5.3",
|
||||
"prettier-eslint": "16.1.2",
|
||||
"sass-embedded": "^1.93.2",
|
||||
"tslib": "2.4.0",
|
||||
"typescript": "^5.8.3",
|
||||
"typescript-eslint": "^8.60.0",
|
||||
"vite": "^6.3.5",
|
||||
"vue-eslint-parser": "^10.4.0",
|
||||
"vue-tsc": "^2.2.10"
|
||||
},
|
||||
"dependencies": {
|
||||
"@codemirror/language": "https://github.com/lishid/cm-language",
|
||||
"@codemirror/merge": "^6.11.0",
|
||||
"@codemirror/state": "^6.5.2",
|
||||
"@codemirror/view": "^6.38.8",
|
||||
"@internationalized/date": "^3.8.2",
|
||||
"@tonaljs/tonal": "^4.10.0",
|
||||
"@vueuse/core": "^13.9.0",
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import { STRUDEL_CODEBLOCK_KEYWORD } from '@/constants/keywords'
|
||||
import { Editor, Notice } from 'obsidian'
|
||||
|
||||
export const createStrudelBlock = (editor: Editor) => {
|
||||
export const createStrudelBlock = async (editor: Editor) => {
|
||||
if (!editor) {
|
||||
new Notice('No active Markdown editor found.', 3000)
|
||||
new Notice('No active markdown editor found.', 3000)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -15,6 +15,7 @@ export const createStrudelBlock = (editor: Editor) => {
|
|||
|
||||
\`\`\``
|
||||
|
||||
|
||||
if (selection) {
|
||||
editor.replaceSelection(strudelBlock)
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ export class StrudelHeaderWidget extends WidgetType {
|
|||
}
|
||||
|
||||
toDOM() {
|
||||
const container = activeDocument.createElement('div')
|
||||
const container = document.createElement('div')
|
||||
container.id = this.strudelBlock.id
|
||||
|
||||
container.createDiv({ attr: { 'data-strudel-id': this.strudelBlock.id } })
|
||||
|
|
@ -29,7 +29,7 @@ export class StrudelHeaderWidget extends WidgetType {
|
|||
// deleting the container from the DOM. This means Vue doesn't have enough time
|
||||
// to unmount the component from the old container.
|
||||
// To avoid this issue, we render the block with a slight delay.
|
||||
window.setTimeout(() => {
|
||||
setTimeout(() => {
|
||||
this.strudelBlock.show()
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { RangeSetBuilder, StateEffect, StateField } from '@codemirror/state'
|
||||
import { RangeSetBuilder, StateEffect, StateField, Prec } from '@codemirror/state'
|
||||
import { Decoration, DecorationSet, EditorView } from '@codemirror/view'
|
||||
|
||||
export const setMiniLocations = StateEffect.define<{
|
||||
|
|
@ -110,7 +110,7 @@ const miniLocationHighlights = EditorView.decorations.compute(
|
|||
const colorMod = hap.value?.color ? ` strudel-mark_${hap.value.color}` : ''
|
||||
const classStr = `strudel-mark${colorMod}`
|
||||
// Get explicit channels for color values
|
||||
/*
|
||||
/*
|
||||
const swatch = document.createElement('div');
|
||||
swatch.style.color = color;
|
||||
document.body.appendChild(swatch);
|
||||
|
|
@ -142,3 +142,4 @@ const miniLocationHighlights = EditorView.decorations.compute(
|
|||
)
|
||||
|
||||
export const highlightExtension = [miniLocations, visibleMiniLocations, miniLocationHighlights]
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,115 @@
|
|||
import { nanoid } from 'nanoid'
|
||||
import { App } from 'obsidian'
|
||||
import { createPinia } from 'pinia'
|
||||
import { createApp, defineComponent, Component as VueComponent } from 'vue'
|
||||
|
||||
/**
|
||||
* Helper class for managing Vue components in Obsidian
|
||||
*/
|
||||
export class VueRenderer {
|
||||
private static instance: VueRenderer
|
||||
private app: App
|
||||
private vueApps: Map<string, any> = new Map()
|
||||
|
||||
private constructor(app: App) {
|
||||
this.app = app
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the singleton instance of VueRenderer
|
||||
* @param app Obsidian App instance
|
||||
* @returns VueRenderer instance
|
||||
*/
|
||||
public static getInstance(app: App): VueRenderer {
|
||||
if (!VueRenderer.instance) {
|
||||
VueRenderer.instance = new VueRenderer(app)
|
||||
}
|
||||
return VueRenderer.instance
|
||||
}
|
||||
|
||||
/**
|
||||
* Mount a Vue component to a DOM element
|
||||
* @param container The DOM element to mount the component to
|
||||
* @param component The Vue component to mount
|
||||
* @param props Props to pass to the component
|
||||
* @returns A unique ID for the mounted component
|
||||
*/
|
||||
public mountComponent(
|
||||
container: HTMLElement,
|
||||
component: VueComponent,
|
||||
props: Record<string, any> = {}
|
||||
): string {
|
||||
// Create a unique ID for this component instance
|
||||
const id = `vue-component-${Date.now()}-${Math.floor(Math.random() * 10000)}`
|
||||
|
||||
// Create a wrapper div for the Vue app
|
||||
const mountPoint = document.createElement('div')
|
||||
mountPoint.id = id
|
||||
container.appendChild(mountPoint)
|
||||
|
||||
const pinia = createPinia()
|
||||
|
||||
// Create a Vue app with the component
|
||||
const app = createApp(component, props)
|
||||
|
||||
app.use(pinia)
|
||||
|
||||
// Mount the app to the container
|
||||
app.mount(`#${id}`)
|
||||
|
||||
// Store the app reference for cleanup
|
||||
this.vueApps.set(id, app)
|
||||
|
||||
return id
|
||||
}
|
||||
|
||||
/**
|
||||
* Unmount a Vue component by its ID
|
||||
* @param id The ID of the component to unmount
|
||||
*/
|
||||
public unmountComponent(id: string): void {
|
||||
const app = this.vueApps.get(id)
|
||||
if (app) {
|
||||
app.unmount()
|
||||
this.vueApps.delete(id)
|
||||
const mountPoint = document.getElementById(id)
|
||||
if (mountPoint) {
|
||||
mountPoint.remove()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a wrapper for a Vue component that can be used with Obsidian's Component system
|
||||
* @param component The Vue component to wrap
|
||||
* @param props Props to pass to the component
|
||||
* @returns A function that can be used to mount the component
|
||||
*/
|
||||
public createComponentWrapper(
|
||||
component: VueComponent,
|
||||
props: Record<string, any> = {}
|
||||
): (container: HTMLElement) => string {
|
||||
return (container: HTMLElement) => {
|
||||
return this.mountComponent(container, component, props)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a simple Vue component from a template string
|
||||
* @param template The Vue template string
|
||||
* @param options Additional Vue component options
|
||||
* @returns A Vue component
|
||||
*/
|
||||
export function createVueComponent(
|
||||
template: string,
|
||||
options: Record<string, any> = {}
|
||||
): VueComponent {
|
||||
return defineComponent({
|
||||
template,
|
||||
...options,
|
||||
})
|
||||
}
|
||||
|
||||
export function genid(): string {
|
||||
return `vue-${nanoid()}`
|
||||
|
|
|
|||
35
src/main.ts
35
src/main.ts
|
|
@ -12,15 +12,18 @@ import { samples } from '@/strudel/init.js'
|
|||
import './editor/SyntaxHighlighting.js'
|
||||
import { createStrudelBlock } from './commands/createStrudelBlock'
|
||||
|
||||
interface PluginData {}
|
||||
|
||||
export default class StrudelPlugin extends Plugin {
|
||||
strudelConfig: StrudelConfig
|
||||
private data: PluginData = {}
|
||||
|
||||
private vueApp: VueApp | null = null
|
||||
|
||||
initializeVue() {
|
||||
const rootContainer = activeDocument.createElement('div')
|
||||
const rootContainer = document.createElement('div')
|
||||
rootContainer.id = 'strudel-vue-root'
|
||||
activeDocument.body.appendChild(rootContainer)
|
||||
document.body.appendChild(rootContainer)
|
||||
|
||||
this.vueApp = createApp(VueEntry)
|
||||
this.vueApp.use(createPinia())
|
||||
|
|
@ -38,18 +41,18 @@ export default class StrudelPlugin extends Plugin {
|
|||
|
||||
this.addSettingTab(new StrudelSettingTab(this.app, this))
|
||||
|
||||
console.debug('Strudel REPL plugin loaded.')
|
||||
console.log('Strudel REPL Plugin loaded.')
|
||||
|
||||
this.initializeVue()
|
||||
|
||||
this.registerEditorExtension(strudelEditorExtension)
|
||||
this.registerEditorExtension(highlightExtension)
|
||||
|
||||
void GlobalStore.getInstance().initStrudel()
|
||||
GlobalStore.getInstance().initStrudel()
|
||||
|
||||
this.addCommand({
|
||||
id: 'play',
|
||||
name: 'Play strudel block at caret',
|
||||
name: 'Play strudel block at cursor',
|
||||
editorCallback: (editor: Editor) => {
|
||||
const cursor = editor.getCursor()
|
||||
|
||||
|
|
@ -65,22 +68,22 @@ export default class StrudelPlugin extends Plugin {
|
|||
},
|
||||
})
|
||||
|
||||
this.addCommand({
|
||||
id: 'create-strudel-block',
|
||||
name: 'Create new Strudel block',
|
||||
editorCallback: (editor: Editor) => {
|
||||
createStrudelBlock(editor)
|
||||
},
|
||||
})
|
||||
// this.addCommand({
|
||||
// id: 'create-strudel-block',
|
||||
// name: 'Create new strudel block',
|
||||
// callback: () => {
|
||||
// createStrudelBlock()
|
||||
// },
|
||||
// })
|
||||
}
|
||||
|
||||
onunload() {
|
||||
GlobalStore.getInstance().destroy()
|
||||
if (this.vueApp) {
|
||||
this.vueApp.unmount()
|
||||
activeDocument.getElementById('strudel-vue-root')?.remove()
|
||||
document.getElementById('strudel-vue-root')?.remove()
|
||||
}
|
||||
console.debug('Strudel REPL plugin unloaded.')
|
||||
console.log('Strudel REPL plugin unloaded.')
|
||||
}
|
||||
|
||||
async loadSettings() {
|
||||
|
|
@ -106,6 +109,8 @@ class StrudelSettingTab extends PluginSettingTab {
|
|||
|
||||
containerEl.empty()
|
||||
|
||||
containerEl.createEl('h2', { text: 'Strudel REPL Settings' })
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName('Sounds cache directory')
|
||||
.setDesc('Directory where Strudel will store cached sounds.')
|
||||
|
|
@ -133,7 +138,7 @@ class StrudelSettingTab extends PluginSettingTab {
|
|||
|
||||
new Setting(containerEl)
|
||||
.setName('Samples to preload')
|
||||
.setDesc('Audio sample urls to preload on startup for faster access.')
|
||||
.setDesc('URLs of audio samples to preload on startup for faster access.')
|
||||
.addTextArea((text) =>
|
||||
text
|
||||
.setPlaceholder('Enter sample URLs, one per line')
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ export class CacheService {
|
|||
const data = JSON.parse(content)
|
||||
return data
|
||||
}
|
||||
} catch {
|
||||
} catch (error) {
|
||||
// ignore error
|
||||
}
|
||||
}
|
||||
|
|
@ -63,6 +63,6 @@ export class CacheService {
|
|||
}
|
||||
|
||||
escapeFileName(fileName: string): string {
|
||||
return fileName.replace(/[^a-z0-9_\-.]/gi, '_')
|
||||
return fileName.replace(/[^a-z0-9_\-\.]/gi, '_')
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,9 +22,8 @@ export class StrudelConfig {
|
|||
public saveToCache = true
|
||||
public samplesToPreload: string[] = [...defaultSamples]
|
||||
|
||||
private constructor() {
|
||||
return
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
private constructor() {}
|
||||
|
||||
public static getInstance(): StrudelConfig {
|
||||
if (!StrudelConfig.instance) {
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ export class GlobalStore {
|
|||
const view = activeLeaf?.view as MarkdownView
|
||||
|
||||
if (activeLeaf && view.editor) {
|
||||
return (view.editor as Editor & { cm: EditorView }).cm
|
||||
return (view.editor as Editor & { cm: EditorView }).cm as EditorView
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -73,7 +73,7 @@ export class GlobalStore {
|
|||
this.isPlaying.value = false
|
||||
}
|
||||
|
||||
public drawer: any = null
|
||||
public drawer: any | null = null
|
||||
|
||||
public async initStrudel() {
|
||||
this.repl = await init({
|
||||
|
|
@ -119,7 +119,7 @@ export class GlobalStore {
|
|||
const currentFrame = haps.filter((hap: any) => hap.isActive(time))
|
||||
highlightMiniLocations(editor, time, currentFrame)
|
||||
|
||||
const rootStyles = getComputedStyle(activeDocument.getElementsByTagName('body')[0])
|
||||
const rootStyles = getComputedStyle(document.getElementsByTagName('body')[0])
|
||||
const playheadColor = rootStyles.getPropertyValue('--text-accent').trim()
|
||||
const inactiveColor = rootStyles
|
||||
.getPropertyValue('--background-modifier-active-hover')
|
||||
|
|
|
|||
4
src/vue-shims.d.ts
vendored
4
src/vue-shims.d.ts
vendored
|
|
@ -1,5 +1,7 @@
|
|||
declare module '*.vue' {
|
||||
import { DefineComponent } from 'vue'
|
||||
const component: DefineComponent<Record<string, unknown>, Record<string, unknown>, any>
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
const component: DefineComponent<{}, {}, any>
|
||||
export default component
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
{
|
||||
"0.0.1": "1.9.14",
|
||||
"0.0.2": "1.9.14",
|
||||
"0.0.3": "1.9.14",
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue