From 9a48f59166bf4ceef1814fde59aa2538c4b8916e Mon Sep 17 00:00:00 2001 From: Michael Gartner Date: Fri, 24 Jan 2025 08:11:27 -0600 Subject: [PATCH 1/3] init --- README.md | 73 +- apps/obsidian/.env.example | 1 + apps/obsidian/README.md | 5 + apps/obsidian/manifest.json | 10 + apps/obsidian/package.json | 29 + apps/obsidian/scripts/build.ts | 27 + apps/obsidian/scripts/compile.ts | 180 ++++ apps/obsidian/scripts/dev.ts | 27 + apps/obsidian/src/components/AppContext.tsx | 18 + apps/obsidian/src/components/SampleModal.tsx | 36 + .../src/components/SampleSettings.tsx | 47 + apps/obsidian/src/components/Settings.tsx | 12 + apps/obsidian/src/index.ts | 31 + apps/obsidian/src/styles/styles.css | 3 + apps/obsidian/src/utils/registerCommands.ts | 45 + apps/obsidian/tsconfig.json | 18 + apps/roam/tsconfig.json | 4 - package-lock.json | 825 ++++++++++++++++++ packages/typescript-config/base.json | 4 + turbo.json | 1 + 20 files changed, 1361 insertions(+), 35 deletions(-) create mode 100644 apps/obsidian/.env.example create mode 100644 apps/obsidian/README.md create mode 100644 apps/obsidian/manifest.json create mode 100644 apps/obsidian/package.json create mode 100644 apps/obsidian/scripts/build.ts create mode 100644 apps/obsidian/scripts/compile.ts create mode 100644 apps/obsidian/scripts/dev.ts create mode 100644 apps/obsidian/src/components/AppContext.tsx create mode 100644 apps/obsidian/src/components/SampleModal.tsx create mode 100644 apps/obsidian/src/components/SampleSettings.tsx create mode 100644 apps/obsidian/src/components/Settings.tsx create mode 100644 apps/obsidian/src/index.ts create mode 100644 apps/obsidian/src/styles/styles.css create mode 100644 apps/obsidian/src/utils/registerCommands.ts create mode 100644 apps/obsidian/tsconfig.json diff --git a/README.md b/README.md index daa67cd20..594ae2300 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,36 @@ Welcome to the monorepo for [Discourse Graphs](https://discoursegraphs.com). Dis ## Local development +### Turborepo + +This repository uses [Turborepo](https://turbo.build/repo/docs) as a build system, enabling a streamlined and efficient workflow for managing multiple applications and shared packages in a monorepo setup. + +Using Turborepo allows for things like: + +- **Centralize shared resources**: Shared configurations, utilities, and components are maintained in a single place, reducing duplication and inconsistency. +- **Incremental builds**: Only changes in code are rebuilt, which speeds up development. +- **Parallel processing**: Tasks across applications and packages run concurrently, saving time. +- **Dependency graph management**: Turborepo tracks relationships between projects, ensuring that tasks run in the correct order. + +Learn more about how monorepos improve development workflows [here](https://vercel.com/blog/monorepos) and [here](https://github.com/babel/babel/blob/master/doc/design/monorepo.md). + +### Apps & Packages + +`apps` + +- [website](https://github.com/DiscourseGraphs/discourse-graph/tree/main/apps/website): The public-facing website for Discourse Graphs, available at [discoursegraphs.com](https://discoursegraphs.com). Uses Next.js. +- [roam](https://github.com/DiscourseGraphs/discourse-graph/tree/main/apps/roam): The Roam Research extension that implements the Discourse Graph protocol. +- [obsidian](https://github.com/DiscourseGraphs/discourse-graph/tree/main/apps/obsidian): The Obsidian plugin that implements the Discourse Graph protocol. + +`packages` + +- [tailwind-config](https://github.com/DiscourseGraphs/discourse-graph/tree/main/packages/tailwind-config): Shared tailwind config +- [typescript-config](https://github.com/DiscourseGraphs/discourse-graph/tree/main/packages/typescript-config): Shared tsconfig.jsons +- [eslint-config](https://github.com/DiscourseGraphs/discourse-graph/tree/main/packages/eslint-config): ESLint preset +- [ui](https://github.com/DiscourseGraphs/discourse-graph/tree/main/packages/ui): Core React components + +### Getting Started + To get started with local development: 1. Clone the repository: @@ -23,45 +53,26 @@ npm install turbo dev ``` -You can use the `--filter` flag to run a single application: +You can use the `--filter` flag to run a single application, eg: ```bash turbo dev --filter roam ``` -### Turborepo - -This repository uses [Turborepo](https://turbo.build/repo/docs) as a build system, enabling a streamlined and efficient workflow for managing multiple applications and shared packages in a monorepo setup. - -Using Turborepo allows for things like: - -- Centralize shared resources: Shared configurations, utilities, and components are maintained in a single place, reducing duplication and inconsistency. -- Incremental builds: Only changes in code are rebuilt, which speeds up development. -- Parallel processing: Tasks across applications and packages run concurrently, saving time. -- Dependency graph management: Turborepo tracks relationships between projects, ensuring that tasks run in the correct order. - -Learn more about how monorepos improve development workflows [here](https://vercel.com/blog/monorepos) and [here](https://github.com/babel/babel/blob/master/doc/design/monorepo.md). - -### Apps & Packages - -This Turborepo includes the following packages and applications: +#### Roam -`apps` - -- [website](https://github.com/DiscourseGraphs/discourse-graph/tree/main/apps/website): The public-facing website for Discourse Graphs, available at [discoursegraphs.com](https://discoursegraphs.com). Uses Next.js. -- [roam](https://github.com/DiscourseGraphs/discourse-graph/tree/main/apps/roam): The Roam Research extension that implements the Discourse Graph protocol. - -`packages` - -- [tailwind-config](https://github.com/DiscourseGraphs/discourse-graph/tree/main/packages/tailwind-config): Shared tailwind config -- [typescript-config](https://github.com/DiscourseGraphs/discourse-graph/tree/main/packages/typescript-config): Shared tsconfig.jsons -- [eslint-config](https://github.com/DiscourseGraphs/discourse-graph/tree/main/packages/eslint-config): ESLint preset -- [ui](https://github.com/DiscourseGraphs/discourse-graph/tree/main/packages/ui): Core React components +- go to your graph, open up settings, and go to the extensions tab +- click "Enable developer mode (the settings cog icon) +- click "Load extension" +- and choose the `dist` folder on your computer which is in the `discourse-graph/apps/roam` directory +- you can set a hotkey to `Reload developer extension` -### Deployment +#### Obsidian -- The Next.js website is automatically deployed to Vercel. -- The Roam Discourse Graph extension is manually deployed to Vercel blob storage using `npm run deploy`. (this will be automated in the future) +- copy the `.env.example` file to `.env` +- fill in the `OBSIDIAN_PLUGIN_PATH` with the path to your Obsidian plugins folder +- run `turbo dev --filter @discourse-graphs/obsidian` +- install the [Plugin Reloader](https://obsidian.md/plugins?id=plugin-reloader) or [BRAT](https://obsidian.md/plugins?id=obsidian42-brat)/[Hot Reload](https://github.com/pjeby/hot-reload) to reload the plugin after changes ## Contributing diff --git a/apps/obsidian/.env.example b/apps/obsidian/.env.example new file mode 100644 index 000000000..46070cc2b --- /dev/null +++ b/apps/obsidian/.env.example @@ -0,0 +1 @@ +# OBSIDIAN_PLUGIN_PATH="path/to/your/obsidian/plugins/folder" \ No newline at end of file diff --git a/apps/obsidian/README.md b/apps/obsidian/README.md new file mode 100644 index 000000000..cc6995b98 --- /dev/null +++ b/apps/obsidian/README.md @@ -0,0 +1,5 @@ +# Discourse Graphs + +The Discourse Graph extension enables Roam users to seamlessly add additional semantic structure to their notes, including specified page types and link types that model scientific discourse, to enable more complex and structured knowledge synthesis work, such as a complex interdisciplinary literature review, and enhanced collaboration with others on this work. + +For more information about Discourse Graphs, check out our website at [https://discoursegraphs.com](https://discoursegraphs.com) diff --git a/apps/obsidian/manifest.json b/apps/obsidian/manifest.json new file mode 100644 index 000000000..3b7fc93f0 --- /dev/null +++ b/apps/obsidian/manifest.json @@ -0,0 +1,10 @@ +{ + "id": "@discourse-graph/obsidian", + "name": "Discourse Graph", + "version": "0.1.0", + "minAppVersion": "1.7.0", + "description": "Discourse Graph Plugin for Obsidian", + "author": "Discourse Graphs", + "authorUrl": "https://discoursegraphs.com", + "isDesktopOnly": false +} diff --git a/apps/obsidian/package.json b/apps/obsidian/package.json new file mode 100644 index 000000000..506f90ab7 --- /dev/null +++ b/apps/obsidian/package.json @@ -0,0 +1,29 @@ +{ + "name": "@discourse-graphs/obsidian", + "version": "0.1.0", + "description": "Discourse Graph Plugin for obsidian.md", + "main": "dist/main.js", + "private": true, + "scripts": { + "dev": "tsx scripts/dev.ts", + "build": "tsx scripts/build.ts" + }, + "keywords": [], + "author": "", + "license": "MIT", + "devDependencies": { + "@types/node": "^16.11.6", + "@typescript-eslint/eslint-plugin": "5.29.0", + "@typescript-eslint/parser": "5.29.0", + "builtin-modules": "3.3.0", + "esbuild": "0.17.3", + "obsidian": "^1.7.2", + "tslib": "2.4.0", + "tsx": "^4.19.2", + "typescript": "4.7.4" + }, + "dependencies": { + "react": "^19.0.0", + "react-dom": "^19.0.0" + } +} diff --git a/apps/obsidian/scripts/build.ts b/apps/obsidian/scripts/build.ts new file mode 100644 index 000000000..975de29f2 --- /dev/null +++ b/apps/obsidian/scripts/build.ts @@ -0,0 +1,27 @@ +import { compile } from "./compile"; + +const build = async () => { + process.env = { + ...process.env, + NODE_ENV: process.env.NODE_ENV || "production", + }; + + console.log("Compiling ..."); + try { + await compile({}); + console.log("Compiling complete"); + } catch (error) { + console.error("Build failed on compile:", error); + process.exit(1); + } +}; + +const main = async () => { + try { + await build(); + } catch (error) { + console.error(error); + process.exit(1); + } +}; +if (require.main === module) main(); diff --git a/apps/obsidian/scripts/compile.ts b/apps/obsidian/scripts/compile.ts new file mode 100644 index 000000000..b41e4e609 --- /dev/null +++ b/apps/obsidian/scripts/compile.ts @@ -0,0 +1,180 @@ +import esbuild from "esbuild"; +import fs from "fs"; +import path from "path"; +import { z } from "zod"; +import builtins from "builtin-modules"; +import dotenv from "dotenv"; + +dotenv.config(); + +const DEFAULT_FILES_INCLUDED = ["manifest.json"]; +const isProd = process.env.NODE_ENV === "production"; + +const cliArgs = z.object({ + out: z.string().optional(), + root: z.string().optional(), + format: z.enum(["esm", "cjs"]).optional(), + external: z.array(z.string()), + mirror: z.string().optional(), +}); + +type Builder = (opts: esbuild.BuildOptions) => Promise; +export type CliOpts = Record; + +export const args = { + out: "main", + format: "cjs", + root: ".", + mirror: process.env.OBSIDIAN_PLUGIN_PATH, + external: [ + "obsidian", + "electron", + "@codemirror/autocomplete", + "@codemirror/collab", + "@codemirror/commands", + "@codemirror/language", + "@codemirror/lint", + "@codemirror/search", + "@codemirror/state", + "@codemirror/view", + "@lezer/common", + "@lezer/highlight", + "@lezer/lr", + ...builtins, + ], +} as CliOpts; + +const readDir = (directoryPath: string): string[] => { + try { + if (!fs.existsSync(directoryPath)) { + console.error(`Directory does not exist: ${directoryPath}`); + return []; + } + + return fs + .readdirSync(directoryPath, { withFileTypes: true }) + .flatMap((f) => { + const fullPath = `${directoryPath}/${f.name}`; + return f.isDirectory() ? readDir(fullPath) : [fullPath]; + }); + } catch (error) { + console.error(`Error reading directory ${directoryPath}:`, error); + return []; + } +}; + +const appPath = (p: string): string => + path.resolve(fs.realpathSync(process.cwd()), p); + +export const compile = ({ + opts = args, + builder = async (opts) => { + await esbuild.build(opts); + }, +}: { + opts?: CliOpts; + builder?: Builder; +}) => { + const { root = ".", out, format, external, mirror } = cliArgs.parse(opts); + + const srcRoot = path.join(root, "src"); + const entryTs = "index.ts"; + const outdir = path.resolve(process.cwd(), root, "dist"); + const stylesDir = path.join(root, "src", "styles"); + const outputStylesFile = path.join(outdir, "styles.css"); + + fs.mkdirSync(outdir, { recursive: true }); + + const buildPromises = [] as Promise[]; + buildPromises.push( + builder({ + absWorkingDir: process.cwd(), + entryPoints: [path.join(srcRoot, entryTs)], + outdir, + bundle: true, + format, + sourcemap: isProd ? undefined : "inline", + minify: isProd, + entryNames: out, + external: external, + plugins: [ + { + name: "log", + setup: (build) => { + build.onEnd((result) => { + console.log(`built with ${result.errors.length} errors`); + }); + }, + }, + { + name: "combineStyles", + setup(build) { + build.onEnd(async () => { + const styleFiles = fs + .readdirSync(stylesDir) + .filter((file) => file.endsWith(".css")); + const combinedStyles = styleFiles + .map((file) => + fs.readFileSync(path.join(stylesDir, file), "utf8"), + ) + .join("\n"); + fs.writeFileSync(outputStylesFile, combinedStyles); + }); + }, + }, + { + name: "copyDefaultFiles", + setup(build) { + build.onEnd(async () => { + DEFAULT_FILES_INCLUDED.map((f) => path.join(root, f)) + .filter((f) => fs.existsSync(f)) + .forEach((f) => { + fs.cpSync(f, path.join(outdir, path.basename(f))); + }); + }); + }, + }, + { + name: "mirrorFiles", + setup(build) { + build.onEnd(async () => { + if (!mirror) return; + + const normalizedMirrorPath = path.normalize(mirror); + const resolvedMirrorPath = path.resolve( + root, + normalizedMirrorPath, + ); + + if (!fs.existsSync(resolvedMirrorPath)) { + fs.mkdirSync(resolvedMirrorPath, { recursive: true }); + } + + readDir(outdir) + .filter((file) => fs.existsSync(appPath(file))) + .forEach((file) => { + const destinationPath = path.join( + resolvedMirrorPath, + path.relative(outdir, file), + ); + fs.cpSync(appPath(file), destinationPath); + }); + }); + }, + }, + ], + }), + ); + + return Promise.all(buildPromises); +}; + +const main = async () => { + try { + await compile({}); + } catch (error) { + console.error(error); + process.exit(1); + } +}; +if (require.main === module) main(); diff --git a/apps/obsidian/scripts/dev.ts b/apps/obsidian/scripts/dev.ts new file mode 100644 index 000000000..3b5e789fc --- /dev/null +++ b/apps/obsidian/scripts/dev.ts @@ -0,0 +1,27 @@ +import esbuild from "esbuild"; +import dotenv from "dotenv"; +import { compile, args } from "./compile"; + +dotenv.config(); + +const dev = () => { + process.env.NODE_ENV = process.env.NODE_ENV || "development"; + return new Promise((resolve) => { + compile({ + opts: args, + builder: (opts: esbuild.BuildOptions) => + esbuild.context(opts).then((esb) => esb.watch()), + }); + process.on("exit", resolve); + }); +}; + +const main = async () => { + try { + await dev(); + } catch (error) { + console.error(error); + process.exit(1); + } +}; +if (require.main === module) main(); diff --git a/apps/obsidian/src/components/AppContext.tsx b/apps/obsidian/src/components/AppContext.tsx new file mode 100644 index 000000000..e1e3c0e94 --- /dev/null +++ b/apps/obsidian/src/components/AppContext.tsx @@ -0,0 +1,18 @@ +import { createContext, useContext } from "react"; +import { App } from "obsidian"; + +export const AppContext = createContext(undefined); + +export const useApp = (): App | undefined => { + return useContext(AppContext); +}; + +export const ContextProvider = ({ + app, + children, +}: { + app: App; + children: React.ReactNode; +}) => { + return {children}; +}; diff --git a/apps/obsidian/src/components/SampleModal.tsx b/apps/obsidian/src/components/SampleModal.tsx new file mode 100644 index 000000000..e1ce8b939 --- /dev/null +++ b/apps/obsidian/src/components/SampleModal.tsx @@ -0,0 +1,36 @@ +import { App, Modal } from "obsidian"; +import { createRoot } from "react-dom/client"; + +const ModalComponent = ({ context }: { context: Modal }) => { + return ( +
+

SO RED

+

Lorum ipsum dolor sit amet.

+ +
+ ); +}; + +export class SampleModal extends Modal { + constructor(app: App) { + super(app); + } + + onOpen() { + const { contentEl } = this; + const root = createRoot(contentEl); + root.render(); + } + + onClose() { + const { contentEl } = this; + contentEl.empty(); + } +} diff --git a/apps/obsidian/src/components/SampleSettings.tsx b/apps/obsidian/src/components/SampleSettings.tsx new file mode 100644 index 000000000..6d049622c --- /dev/null +++ b/apps/obsidian/src/components/SampleSettings.tsx @@ -0,0 +1,47 @@ +import { StrictMode } from "react"; +import { App, PluginSettingTab, Setting } from "obsidian"; +import type DiscourseGraphPlugin from "../index"; +import Settings from "./Settings"; +import { Root, createRoot } from "react-dom/client"; +import { ContextProvider } from "./AppContext"; + +export class SettingsTab extends PluginSettingTab { + root: Root | null = null; + plugin: DiscourseGraphPlugin; + + constructor(app: App, plugin: DiscourseGraphPlugin) { + super(app, plugin); + this.plugin = plugin; + } + + display(): void { + const { containerEl } = this; + containerEl.empty(); + + // Example react component in settings + const settingsComponentEl = containerEl.createDiv(); + this.root = createRoot(settingsComponentEl); + this.root.render( + + + + + , + ); + + // Example obsidian settings + const obsidianSettingsEl = containerEl.createDiv(); + new Setting(obsidianSettingsEl) + .setName("Setting #1") + .setDesc("It's a secret") + .addText((text) => + text + .setPlaceholder("Enter your secret") + .setValue(this.plugin.settings.mySetting) + .onChange(async (value) => { + this.plugin.settings.mySetting = value; + await this.plugin.saveSettings(); + }), + ); + } +} diff --git a/apps/obsidian/src/components/Settings.tsx b/apps/obsidian/src/components/Settings.tsx new file mode 100644 index 000000000..da282bc77 --- /dev/null +++ b/apps/obsidian/src/components/Settings.tsx @@ -0,0 +1,12 @@ +import { useApp } from "~/components/AppContext"; + +const Settings = () => { + const app = useApp(); + if (!app) { + return
An error occured
; + } + + return

Settings for {app.vault.getName()}

; +}; + +export default Settings; diff --git a/apps/obsidian/src/index.ts b/apps/obsidian/src/index.ts new file mode 100644 index 000000000..d95f759ac --- /dev/null +++ b/apps/obsidian/src/index.ts @@ -0,0 +1,31 @@ +import { Plugin } from "obsidian"; +import { registerCommands } from "~/utils/registerCommands"; +import { SettingsTab } from "~/components/SampleSettings"; + +type Settings = { + mySetting: string; +}; + +const DEFAULT_SETTINGS: Settings = { + mySetting: "default", +}; + +export default class DiscourseGraphPlugin extends Plugin { + settings: Settings = { mySetting: "default" }; + + async onload() { + await this.loadSettings(); + registerCommands(this); + this.addSettingTab(new SettingsTab(this.app, this)); + } + + onunload() {} + + async loadSettings() { + this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData()); + } + + async saveSettings() { + await this.saveData(this.settings); + } +} diff --git a/apps/obsidian/src/styles/styles.css b/apps/obsidian/src/styles/styles.css new file mode 100644 index 000000000..26f590cea --- /dev/null +++ b/apps/obsidian/src/styles/styles.css @@ -0,0 +1,3 @@ +.modal-content { + background-color: red; +} diff --git a/apps/obsidian/src/utils/registerCommands.ts b/apps/obsidian/src/utils/registerCommands.ts new file mode 100644 index 000000000..f2235bf3e --- /dev/null +++ b/apps/obsidian/src/utils/registerCommands.ts @@ -0,0 +1,45 @@ +import { Editor, MarkdownFileInfo, MarkdownView } from "obsidian"; +import { SampleModal } from "~/components/SampleModal"; +import type DiscourseGraphPlugin from "~/index"; + +export const registerCommands = (plugin: DiscourseGraphPlugin) => { + // This adds a simple command that can be triggered anywhere + plugin.addCommand({ + id: "open-sample-modal-simple", + name: "Open sample modal (simple)", + callback: () => { + new SampleModal(plugin.app).open(); + }, + }); + + // This adds an editor command that can perform some operation on the current editor instance + plugin.addCommand({ + id: "sample-editor-command", + name: "Sample editor command", + editorCallback: (editor: Editor, view: MarkdownView | MarkdownFileInfo) => { + console.log(editor.getSelection()); + editor.replaceSelection("Sample Editor Command"); + }, + }); + + // This adds a complex command that can check whether the current state of the app allows execution of the command + plugin.addCommand({ + id: "open-sample-modal-complex", + name: "Open sample modal (complex)", + checkCallback: (checking: boolean) => { + // Conditions to check + const markdownView = + plugin.app.workspace.getActiveViewOfType(MarkdownView); + if (markdownView) { + // If checking is true, we're simply "checking" if the command can be run. + // If checking is false, then we want to actually perform the operation. + if (!checking) { + new SampleModal(plugin.app).open(); + } + + // This command will only show up in Command Palette when the check function returns true + return true; + } + }, + }); +}; diff --git a/apps/obsidian/tsconfig.json b/apps/obsidian/tsconfig.json new file mode 100644 index 000000000..bbeebdcda --- /dev/null +++ b/apps/obsidian/tsconfig.json @@ -0,0 +1,18 @@ +{ + "extends": "@repo/typescript-config/react-library.json", + "compilerOptions": { + "baseUrl": ".", + "inlineSourceMap": true, + "inlineSources": true, + "module": "ESNext", + "target": "ES6", + "allowJs": true, + "noImplicitAny": true, + "moduleResolution": "node", + "importHelpers": true, + "isolatedModules": true, + "strictNullChecks": true, + "lib": ["DOM", "ES5", "ES6", "ES7"] + }, + "include": ["**/*.ts"] +} diff --git a/apps/roam/tsconfig.json b/apps/roam/tsconfig.json index 8e44f2e9e..e25fb5139 100644 --- a/apps/roam/tsconfig.json +++ b/apps/roam/tsconfig.json @@ -4,15 +4,11 @@ "extends": "@repo/typescript-config/react-library.json", "compilerOptions": { "baseUrl": ".", - "paths": { - "~/*": ["src/*"] - }, "outDir": "dist", "target": "ESNext", "lib": ["DOM", "DOM.Iterable", "ESNext"], "allowJs": false, "esModuleInterop": false, - "allowSyntheticDefaultImports": true, "module": "ESNext", "moduleResolution": "Node", "forceConsistentCasingInFileNames": true, diff --git a/package-lock.json b/package-lock.json index cfa5f288a..780d7c6ff 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,6 +22,685 @@ "node": ">=18" } }, + "apps/obsidian": { + "name": "@discourse-graphs/obsidian", + "version": "0.1.0", + "license": "MIT", + "dependencies": { + "react": "^19.0.0", + "react-dom": "^19.0.0" + }, + "devDependencies": { + "@types/node": "^16.11.6", + "@typescript-eslint/eslint-plugin": "5.29.0", + "@typescript-eslint/parser": "5.29.0", + "builtin-modules": "3.3.0", + "esbuild": "0.17.3", + "obsidian": "^1.7.2", + "tslib": "2.4.0", + "tsx": "^4.19.2", + "typescript": "4.7.4" + } + }, + "apps/obsidian/node_modules/@esbuild/android-arm": { + "version": "0.17.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.3.tgz", + "integrity": "sha512-1Mlz934GvbgdDmt26rTLmf03cAgLg5HyOgJN+ZGCeP3Q9ynYTNMn2/LQxIl7Uy+o4K6Rfi2OuLsr12JQQR8gNg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "apps/obsidian/node_modules/@esbuild/android-arm64": { + "version": "0.17.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.3.tgz", + "integrity": "sha512-XvJsYo3dO3Pi4kpalkyMvfQsjxPWHYjoX4MDiB/FUM4YMfWcXa5l4VCwFWVYI1+92yxqjuqrhNg0CZg3gSouyQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "apps/obsidian/node_modules/@esbuild/android-x64": { + "version": "0.17.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.3.tgz", + "integrity": "sha512-nuV2CmLS07Gqh5/GrZLuqkU9Bm6H6vcCspM+zjp9TdQlxJtIe+qqEXQChmfc7nWdyr/yz3h45Utk1tUn8Cz5+A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "apps/obsidian/node_modules/@esbuild/darwin-arm64": { + "version": "0.17.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.3.tgz", + "integrity": "sha512-01Hxaaat6m0Xp9AXGM8mjFtqqwDjzlMP0eQq9zll9U85ttVALGCGDuEvra5Feu/NbP5AEP1MaopPwzsTcUq1cw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "apps/obsidian/node_modules/@esbuild/darwin-x64": { + "version": "0.17.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.3.tgz", + "integrity": "sha512-Eo2gq0Q/er2muf8Z83X21UFoB7EU6/m3GNKvrhACJkjVThd0uA+8RfKpfNhuMCl1bKRfBzKOk6xaYKQZ4lZqvA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "apps/obsidian/node_modules/@esbuild/freebsd-arm64": { + "version": "0.17.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.3.tgz", + "integrity": "sha512-CN62ESxaquP61n1ZjQP/jZte8CE09M6kNn3baos2SeUfdVBkWN5n6vGp2iKyb/bm/x4JQzEvJgRHLGd5F5b81w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "apps/obsidian/node_modules/@esbuild/freebsd-x64": { + "version": "0.17.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.3.tgz", + "integrity": "sha512-feq+K8TxIznZE+zhdVurF3WNJ/Sa35dQNYbaqM/wsCbWdzXr5lyq+AaTUSER2cUR+SXPnd/EY75EPRjf4s1SLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "apps/obsidian/node_modules/@esbuild/linux-arm": { + "version": "0.17.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.3.tgz", + "integrity": "sha512-CLP3EgyNuPcg2cshbwkqYy5bbAgK+VhyfMU7oIYyn+x4Y67xb5C5ylxsNUjRmr8BX+MW3YhVNm6Lq6FKtRTWHQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "apps/obsidian/node_modules/@esbuild/linux-arm64": { + "version": "0.17.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.3.tgz", + "integrity": "sha512-JHeZXD4auLYBnrKn6JYJ0o5nWJI9PhChA/Nt0G4MvLaMrvXuWnY93R3a7PiXeJQphpL1nYsaMcoV2QtuvRnF/g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "apps/obsidian/node_modules/@esbuild/linux-ia32": { + "version": "0.17.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.3.tgz", + "integrity": "sha512-FyXlD2ZjZqTFh0sOQxFDiWG1uQUEOLbEh9gKN/7pFxck5Vw0qjWSDqbn6C10GAa1rXJpwsntHcmLqydY9ST9ZA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "apps/obsidian/node_modules/@esbuild/linux-loong64": { + "version": "0.17.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.3.tgz", + "integrity": "sha512-OrDGMvDBI2g7s04J8dh8/I7eSO+/E7nMDT2Z5IruBfUO/RiigF1OF6xoH33Dn4W/OwAWSUf1s2nXamb28ZklTA==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "apps/obsidian/node_modules/@esbuild/linux-mips64el": { + "version": "0.17.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.3.tgz", + "integrity": "sha512-DcnUpXnVCJvmv0TzuLwKBC2nsQHle8EIiAJiJ+PipEVC16wHXaPEKP0EqN8WnBe0TPvMITOUlP2aiL5YMld+CQ==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "apps/obsidian/node_modules/@esbuild/linux-ppc64": { + "version": "0.17.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.3.tgz", + "integrity": "sha512-BDYf/l1WVhWE+FHAW3FzZPtVlk9QsrwsxGzABmN4g8bTjmhazsId3h127pliDRRu5674k1Y2RWejbpN46N9ZhQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "apps/obsidian/node_modules/@esbuild/linux-riscv64": { + "version": "0.17.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.3.tgz", + "integrity": "sha512-WViAxWYMRIi+prTJTyV1wnqd2mS2cPqJlN85oscVhXdb/ZTFJdrpaqm/uDsZPGKHtbg5TuRX/ymKdOSk41YZow==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "apps/obsidian/node_modules/@esbuild/linux-s390x": { + "version": "0.17.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.3.tgz", + "integrity": "sha512-Iw8lkNHUC4oGP1O/KhumcVy77u2s6+KUjieUqzEU3XuWJqZ+AY7uVMrrCbAiwWTkpQHkr00BuXH5RpC6Sb/7Ug==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "apps/obsidian/node_modules/@esbuild/linux-x64": { + "version": "0.17.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.3.tgz", + "integrity": "sha512-0AGkWQMzeoeAtXQRNB3s4J1/T2XbigM2/Mn2yU1tQSmQRmHIZdkGbVq2A3aDdNslPyhb9/lH0S5GMTZ4xsjBqg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "apps/obsidian/node_modules/@esbuild/netbsd-x64": { + "version": "0.17.3", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.3.tgz", + "integrity": "sha512-4+rR/WHOxIVh53UIQIICryjdoKdHsFZFD4zLSonJ9RRw7bhKzVyXbnRPsWSfwybYqw9sB7ots/SYyufL1mBpEg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "apps/obsidian/node_modules/@esbuild/openbsd-x64": { + "version": "0.17.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.3.tgz", + "integrity": "sha512-cVpWnkx9IYg99EjGxa5Gc0XmqumtAwK3aoz7O4Dii2vko+qXbkHoujWA68cqXjhh6TsLaQelfDO4MVnyr+ODeA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "apps/obsidian/node_modules/@esbuild/sunos-x64": { + "version": "0.17.3", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.3.tgz", + "integrity": "sha512-RxmhKLbTCDAY2xOfrww6ieIZkZF+KBqG7S2Ako2SljKXRFi+0863PspK74QQ7JpmWwncChY25JTJSbVBYGQk2Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "apps/obsidian/node_modules/@esbuild/win32-arm64": { + "version": "0.17.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.3.tgz", + "integrity": "sha512-0r36VeEJ4efwmofxVJRXDjVRP2jTmv877zc+i+Pc7MNsIr38NfsjkQj23AfF7l0WbB+RQ7VUb+LDiqC/KY/M/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "apps/obsidian/node_modules/@esbuild/win32-ia32": { + "version": "0.17.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.3.tgz", + "integrity": "sha512-wgO6rc7uGStH22nur4aLFcq7Wh86bE9cOFmfTr/yxN3BXvDEdCSXyKkO+U5JIt53eTOgC47v9k/C1bITWL/Teg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "apps/obsidian/node_modules/@esbuild/win32-x64": { + "version": "0.17.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.3.tgz", + "integrity": "sha512-FdVl64OIuiKjgXBjwZaJLKp0eaEckifbhn10dXWhysMJkWblg3OEEGKSIyhiD5RSgAya8WzP3DNkngtIg3Nt7g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "apps/obsidian/node_modules/@types/node": { + "version": "16.18.125", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.125.tgz", + "integrity": "sha512-w7U5ojboSPfZP4zD98d+/cjcN2BDW6lKH2M0ubipt8L8vUC7qUAC6ENKGSJL4tEktH2Saw2K4y1uwSjyRGKMhw==", + "dev": true, + "license": "MIT" + }, + "apps/obsidian/node_modules/@typescript-eslint/eslint-plugin": { + "version": "5.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.29.0.tgz", + "integrity": "sha512-kgTsISt9pM53yRFQmLZ4npj99yGl3x3Pl7z4eA66OuTzAGC4bQB5H5fuLwPnqTKU3yyrrg4MIhjF17UYnL4c0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "5.29.0", + "@typescript-eslint/type-utils": "5.29.0", + "@typescript-eslint/utils": "5.29.0", + "debug": "^4.3.4", + "functional-red-black-tree": "^1.0.1", + "ignore": "^5.2.0", + "regexpp": "^3.2.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "apps/obsidian/node_modules/@typescript-eslint/parser": { + "version": "5.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.29.0.tgz", + "integrity": "sha512-ruKWTv+x0OOxbzIw9nW5oWlUopvP/IQDjB5ZqmTglLIoDTctLlAJpAQFpNPJP/ZI7hTT9sARBosEfaKbcFuECw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/scope-manager": "5.29.0", + "@typescript-eslint/types": "5.29.0", + "@typescript-eslint/typescript-estree": "5.29.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "apps/obsidian/node_modules/@typescript-eslint/scope-manager": { + "version": "5.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.29.0.tgz", + "integrity": "sha512-etbXUT0FygFi2ihcxDZjz21LtC+Eps9V2xVx09zFoN44RRHPrkMflidGMI+2dUs821zR1tDS6Oc9IXxIjOUZwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "5.29.0", + "@typescript-eslint/visitor-keys": "5.29.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "apps/obsidian/node_modules/@typescript-eslint/type-utils": { + "version": "5.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.29.0.tgz", + "integrity": "sha512-JK6bAaaiJozbox3K220VRfCzLa9n0ib/J+FHIwnaV3Enw/TO267qe0pM1b1QrrEuy6xun374XEAsRlA86JJnyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/utils": "5.29.0", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "apps/obsidian/node_modules/@typescript-eslint/types": { + "version": "5.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.29.0.tgz", + "integrity": "sha512-X99VbqvAXOMdVyfFmksMy3u8p8yoRGITgU1joBJPzeYa0rhdf5ok9S56/itRoUSh99fiDoMtarSIJXo7H/SnOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "apps/obsidian/node_modules/@typescript-eslint/typescript-estree": { + "version": "5.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.29.0.tgz", + "integrity": "sha512-mQvSUJ/JjGBdvo+1LwC+GY2XmSYjK1nAaVw2emp/E61wEVYEyibRHCqm1I1vEKbXCpUKuW4G7u9ZCaZhJbLoNQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/types": "5.29.0", + "@typescript-eslint/visitor-keys": "5.29.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "apps/obsidian/node_modules/@typescript-eslint/utils": { + "version": "5.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.29.0.tgz", + "integrity": "sha512-3Eos6uP1nyLOBayc/VUdKZikV90HahXE5Dx9L5YlSd/7ylQPXhLk1BYb29SDgnBnTp+jmSZUU0QxUiyHgW4p7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.9", + "@typescript-eslint/scope-manager": "5.29.0", + "@typescript-eslint/types": "5.29.0", + "@typescript-eslint/typescript-estree": "5.29.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "apps/obsidian/node_modules/@typescript-eslint/visitor-keys": { + "version": "5.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.29.0.tgz", + "integrity": "sha512-Hpb/mCWsjILvikMQoZIE3voc9wtQcS0A9FUw3h8bhr9UxBdtI/tw1ZDZUOXHXLOVMedKCH5NxyzATwnU78bWCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "5.29.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "apps/obsidian/node_modules/esbuild": { + "version": "0.17.3", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.3.tgz", + "integrity": "sha512-9n3AsBRe6sIyOc6kmoXg2ypCLgf3eZSraWFRpnkto+svt8cZNuKTkb1bhQcitBcvIqjNiK7K0J3KPmwGSfkA8g==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.17.3", + "@esbuild/android-arm64": "0.17.3", + "@esbuild/android-x64": "0.17.3", + "@esbuild/darwin-arm64": "0.17.3", + "@esbuild/darwin-x64": "0.17.3", + "@esbuild/freebsd-arm64": "0.17.3", + "@esbuild/freebsd-x64": "0.17.3", + "@esbuild/linux-arm": "0.17.3", + "@esbuild/linux-arm64": "0.17.3", + "@esbuild/linux-ia32": "0.17.3", + "@esbuild/linux-loong64": "0.17.3", + "@esbuild/linux-mips64el": "0.17.3", + "@esbuild/linux-ppc64": "0.17.3", + "@esbuild/linux-riscv64": "0.17.3", + "@esbuild/linux-s390x": "0.17.3", + "@esbuild/linux-x64": "0.17.3", + "@esbuild/netbsd-x64": "0.17.3", + "@esbuild/openbsd-x64": "0.17.3", + "@esbuild/sunos-x64": "0.17.3", + "@esbuild/win32-arm64": "0.17.3", + "@esbuild/win32-ia32": "0.17.3", + "@esbuild/win32-x64": "0.17.3" + } + }, + "apps/obsidian/node_modules/react": { + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/react/-/react-19.0.0.tgz", + "integrity": "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "apps/obsidian/node_modules/react-dom": { + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.0.0.tgz", + "integrity": "sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ==", + "license": "MIT", + "dependencies": { + "scheduler": "^0.25.0" + }, + "peerDependencies": { + "react": "^19.0.0" + } + }, + "apps/obsidian/node_modules/scheduler": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.25.0.tgz", + "integrity": "sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==", + "license": "MIT" + }, + "apps/obsidian/node_modules/tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", + "dev": true, + "license": "0BSD" + }, + "apps/obsidian/node_modules/typescript": { + "version": "4.7.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", + "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, "apps/roam": { "version": "0.8.0", "hasInstallScript": true, @@ -6649,6 +7328,30 @@ "node": ">=6.9.0" } }, + "node_modules/@codemirror/state": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.5.1.tgz", + "integrity": "sha512-3rA9lcwciEB47ZevqvD8qgbzhM9qMb8vCcQCNmDfVRPQG4JT9mSb0Jg8H7YjKGGQcFnLN323fj9jdnG59Kx6bg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@marijn/find-cluster-break": "^1.0.0" + } + }, + "node_modules/@codemirror/view": { + "version": "6.36.2", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.36.2.tgz", + "integrity": "sha512-DZ6ONbs8qdJK0fdN7AB82CgI6tYXf4HWk1wSVa0+9bhVznCuuvhQtX8bFBoy3dv8rZSQqUd8GvhVAcielcidrA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@codemirror/state": "^6.5.0", + "style-mod": "^4.1.0", + "w3c-keyname": "^2.2.4" + } + }, "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", @@ -6671,6 +7374,10 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "node_modules/@discourse-graphs/obsidian": { + "resolved": "apps/obsidian", + "link": true + }, "node_modules/@emnapi/runtime": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.3.1.tgz", @@ -7775,6 +8482,14 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@marijn/find-cluster-break": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz", + "integrity": "sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/@microsoft/tsdoc": { "version": "0.14.2", "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.14.2.tgz", @@ -8494,6 +9209,16 @@ "workspaces": "dist/cli.js" } }, + "node_modules/@types/codemirror": { + "version": "5.60.8", + "resolved": "https://registry.npmjs.org/@types/codemirror/-/codemirror-5.60.8.tgz", + "integrity": "sha512-VjFgDF/eB+Aklcy15TtOTLQeMjTo07k7KAjql8OK5Dirr7a6sJY4T1uVBDuTVG9VEmn1uUsohOpYnVfgC6/jyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/tern": "*" + } + }, "node_modules/@types/debug": { "version": "4.1.12", "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", @@ -8658,6 +9383,16 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/tern": { + "version": "0.23.9", + "resolved": "https://registry.npmjs.org/@types/tern/-/tern-0.23.9.tgz", + "integrity": "sha512-ypzHFE/wBzh+BlH6rrBgS5I/Z7RD21pGhZ2rltb/+ZrVM1awdZwjx7hE5XfuYgHWk9uvV5HLZN3SloevCAp3Bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "*" + } + }, "node_modules/@types/through": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/@types/through/-/through-0.0.33.tgz", @@ -11852,6 +12587,35 @@ "node": ">=4.0" } }, + "node_modules/eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^2.0.0" + }, + "engines": { + "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=5" + } + }, + "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10" + } + }, "node_modules/eslint-visitor-keys": { "version": "3.4.3", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", @@ -12428,6 +13192,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", + "dev": true, + "license": "MIT" + }, "node_modules/functions-have-names": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", @@ -15100,6 +15871,16 @@ "mkdirp": "bin/cmd.js" } }, + "node_modules/moment": { + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -15623,6 +16404,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/obsidian": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/obsidian/-/obsidian-1.7.2.tgz", + "integrity": "sha512-k9hN9brdknJC+afKr5FQzDRuEFGDKbDjfCazJwpgibwCAoZNYHYV8p/s3mM8I6AsnKrPKNXf8xGuMZ4enWelZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/codemirror": "5.60.8", + "moment": "2.29.4" + }, + "peerDependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -16760,6 +17556,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, "node_modules/registry-auth-token": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.3.2.tgz", @@ -17762,6 +18571,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/style-mod": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.2.tgz", + "integrity": "sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/styled-jsx": { "version": "5.1.6", "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz", @@ -18773,6 +19590,14 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/w3c-keyname": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", + "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/wcwidth": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", diff --git a/packages/typescript-config/base.json b/packages/typescript-config/base.json index 5117f2a3d..29e044f50 100644 --- a/packages/typescript-config/base.json +++ b/packages/typescript-config/base.json @@ -1,6 +1,10 @@ { "$schema": "https://json.schemastore.org/tsconfig", "compilerOptions": { + "paths": { + "~/*": ["src/*"] + }, + "allowSyntheticDefaultImports": true, "declaration": true, "declarationMap": true, "esModuleInterop": true, diff --git a/turbo.json b/turbo.json index ff2f6d494..4cb713730 100644 --- a/turbo.json +++ b/turbo.json @@ -15,6 +15,7 @@ "dependsOn": ["^check-types"] }, "dev": { + "passThroughEnv": ["OBSIDIAN_PLUGIN_PATH"], "cache": false, "persistent": true, "inputs": ["$TURBO_DEFAULT$", ".env*"] From 3b4d16a4a18fccb30e357f8d690e72244f18255c Mon Sep 17 00:00:00 2001 From: Michael Gartner Date: Fri, 24 Jan 2025 11:17:56 -0600 Subject: [PATCH 2/3] combine settings components --- .../src/components/SampleSettings.tsx | 47 ------------------- apps/obsidian/src/components/Settings.tsx | 47 ++++++++++++++++++- apps/obsidian/src/index.ts | 2 +- 3 files changed, 46 insertions(+), 50 deletions(-) delete mode 100644 apps/obsidian/src/components/SampleSettings.tsx diff --git a/apps/obsidian/src/components/SampleSettings.tsx b/apps/obsidian/src/components/SampleSettings.tsx deleted file mode 100644 index 6d049622c..000000000 --- a/apps/obsidian/src/components/SampleSettings.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import { StrictMode } from "react"; -import { App, PluginSettingTab, Setting } from "obsidian"; -import type DiscourseGraphPlugin from "../index"; -import Settings from "./Settings"; -import { Root, createRoot } from "react-dom/client"; -import { ContextProvider } from "./AppContext"; - -export class SettingsTab extends PluginSettingTab { - root: Root | null = null; - plugin: DiscourseGraphPlugin; - - constructor(app: App, plugin: DiscourseGraphPlugin) { - super(app, plugin); - this.plugin = plugin; - } - - display(): void { - const { containerEl } = this; - containerEl.empty(); - - // Example react component in settings - const settingsComponentEl = containerEl.createDiv(); - this.root = createRoot(settingsComponentEl); - this.root.render( - - - - - , - ); - - // Example obsidian settings - const obsidianSettingsEl = containerEl.createDiv(); - new Setting(obsidianSettingsEl) - .setName("Setting #1") - .setDesc("It's a secret") - .addText((text) => - text - .setPlaceholder("Enter your secret") - .setValue(this.plugin.settings.mySetting) - .onChange(async (value) => { - this.plugin.settings.mySetting = value; - await this.plugin.saveSettings(); - }), - ); - } -} diff --git a/apps/obsidian/src/components/Settings.tsx b/apps/obsidian/src/components/Settings.tsx index da282bc77..cfe4d098c 100644 --- a/apps/obsidian/src/components/Settings.tsx +++ b/apps/obsidian/src/components/Settings.tsx @@ -1,4 +1,8 @@ -import { useApp } from "~/components/AppContext"; +import { StrictMode } from "react"; +import { App, PluginSettingTab, Setting } from "obsidian"; +import type DiscourseGraphPlugin from "../index"; +import { Root, createRoot } from "react-dom/client"; +import { ContextProvider, useApp } from "./AppContext"; const Settings = () => { const app = useApp(); @@ -9,4 +13,43 @@ const Settings = () => { return

Settings for {app.vault.getName()}

; }; -export default Settings; +export class SettingsTab extends PluginSettingTab { + root: Root | null = null; + plugin: DiscourseGraphPlugin; + + constructor(app: App, plugin: DiscourseGraphPlugin) { + super(app, plugin); + this.plugin = plugin; + } + + display(): void { + const { containerEl } = this; + containerEl.empty(); + + // Example react component in settings + const settingsComponentEl = containerEl.createDiv(); + this.root = createRoot(settingsComponentEl); + this.root.render( + + + + + , + ); + + // Example obsidian settings + const obsidianSettingsEl = containerEl.createDiv(); + new Setting(obsidianSettingsEl) + .setName("Setting #1") + .setDesc("It's a secret") + .addText((text) => + text + .setPlaceholder("Enter your secret") + .setValue(this.plugin.settings.mySetting) + .onChange(async (value) => { + this.plugin.settings.mySetting = value; + await this.plugin.saveSettings(); + }), + ); + } +} diff --git a/apps/obsidian/src/index.ts b/apps/obsidian/src/index.ts index d95f759ac..021a7d356 100644 --- a/apps/obsidian/src/index.ts +++ b/apps/obsidian/src/index.ts @@ -1,6 +1,6 @@ import { Plugin } from "obsidian"; import { registerCommands } from "~/utils/registerCommands"; -import { SettingsTab } from "~/components/SampleSettings"; +import { SettingsTab } from "~/components/Settings"; type Settings = { mySetting: string; From 8235455482631a913cdfcdc12362b7695dacf4fd Mon Sep 17 00:00:00 2001 From: Michael Gartner Date: Sun, 26 Jan 2025 12:31:06 -0600 Subject: [PATCH 3/3] Update apps/obsidian/scripts/dev.ts handle SIGINT and SIGTERM signals Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- apps/obsidian/scripts/dev.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/apps/obsidian/scripts/dev.ts b/apps/obsidian/scripts/dev.ts index 3b5e789fc..46dbc226a 100644 --- a/apps/obsidian/scripts/dev.ts +++ b/apps/obsidian/scripts/dev.ts @@ -10,7 +10,17 @@ const dev = () => { compile({ opts: args, builder: (opts: esbuild.BuildOptions) => - esbuild.context(opts).then((esb) => esb.watch()), + esbuild.context(opts).then((esb) => { + esb.watch(); + // Cleanup on process termination + const cleanup = () => { + esb.dispose(); + resolve(0); + }; + process.on('SIGINT', cleanup); + process.on('SIGTERM', cleanup); + return esb; + }), }); process.on("exit", resolve); });