From 5d09dbad120baa0aee9668419bc483aed2ff54eb Mon Sep 17 00:00:00 2001 From: Maxime Cannoodt Date: Sun, 26 Jun 2022 22:46:39 +0200 Subject: [PATCH] update plugin --- plugin/esbuild.config.mjs | 88 +++++++++++++------------ plugin/main.ts | 91 +++++++++++--------------- plugin/src/NoteSharingService.ts | 6 +- plugin/src/encryption.ts | 5 +- plugin/src/obsidian/PluginSettings.ts | 7 ++ plugin/src/obsidian/SettingsTab.ts | 32 +++++++++ plugin/tsconfig.json | 36 +++++----- server/prisma/dev.db | Bin 163840 -> 167936 bytes server/tsconfig.json | 1 - 9 files changed, 144 insertions(+), 122 deletions(-) create mode 100644 plugin/src/obsidian/PluginSettings.ts create mode 100644 plugin/src/obsidian/SettingsTab.ts diff --git a/plugin/esbuild.config.mjs b/plugin/esbuild.config.mjs index f1fe201..c85d645 100644 --- a/plugin/esbuild.config.mjs +++ b/plugin/esbuild.config.mjs @@ -1,52 +1,54 @@ import esbuild from "esbuild"; import process from "process"; -import builtins from 'builtin-modules' +import builtins from "builtin-modules"; -const banner = -`/* +const banner = `/* THIS IS A GENERATED/BUNDLED FILE BY ESBUILD if you want to view the source, please visit the github repository of this plugin */ `; -const prod = (process.argv[2] === 'production'); +const prod = process.argv[2] === "production"; -esbuild.build({ - banner: { - js: banner, - }, - entryPoints: ['main.ts'], - bundle: true, - external: [ - 'obsidian', - 'electron', - '@codemirror/autocomplete', - '@codemirror/closebrackets', - '@codemirror/collab', - '@codemirror/commands', - '@codemirror/comment', - '@codemirror/fold', - '@codemirror/gutter', - '@codemirror/highlight', - '@codemirror/history', - '@codemirror/language', - '@codemirror/lint', - '@codemirror/matchbrackets', - '@codemirror/panel', - '@codemirror/rangeset', - '@codemirror/rectangular-selection', - '@codemirror/search', - '@codemirror/state', - '@codemirror/stream-parser', - '@codemirror/text', - '@codemirror/tooltip', - '@codemirror/view', - ...builtins], - format: 'cjs', - watch: !prod, - target: 'es2016', - logLevel: "info", - sourcemap: prod ? false : 'inline', - treeShaking: true, - outfile: 'main.js', -}).catch(() => process.exit(1)); +esbuild + .build({ + banner: { + js: banner, + }, + entryPoints: ["main.ts"], + bundle: true, + external: [ + "obsidian", + "electron", + "@codemirror/autocomplete", + "@codemirror/closebrackets", + "@codemirror/collab", + "@codemirror/commands", + "@codemirror/comment", + "@codemirror/fold", + "@codemirror/gutter", + "@codemirror/highlight", + "@codemirror/history", + "@codemirror/language", + "@codemirror/lint", + "@codemirror/matchbrackets", + "@codemirror/panel", + "@codemirror/rangeset", + "@codemirror/rectangular-selection", + "@codemirror/search", + "@codemirror/state", + "@codemirror/stream-parser", + "@codemirror/text", + "@codemirror/tooltip", + "@codemirror/view", + ...builtins, + ], + format: "cjs", + watch: !prod, + target: "es2016", + logLevel: "info", + sourcemap: prod ? false : "inline", + treeShaking: true, + outfile: "main.js", + }) + .catch(() => process.exit(1)); diff --git a/plugin/main.ts b/plugin/main.ts index 163a40c..627ec83 100644 --- a/plugin/main.ts +++ b/plugin/main.ts @@ -1,20 +1,21 @@ -import { App, MarkdownView, Plugin, PluginSettingTab, Setting } from "obsidian"; -import { encryptMarkdown } from "src/encryption"; +import { + EventRef, + MarkdownView, + Menu, + Plugin, + TAbstractFile, + TFile, +} from "obsidian"; import { NoteSharingService } from "src/NoteSharingService"; +import { DEFAULT_SETTINGS, PluginSettings } from "src/obsidian/PluginSettings"; +import SettingsTab from "src/obsidian/SettingsTab"; // Remember to rename these classes and interfaces! -interface MyPluginSettings { - serverUrl: string; -} - -const DEFAULT_SETTINGS: MyPluginSettings = { - serverUrl: "http://localhost:8080", -}; - -export default class MyPlugin extends Plugin { - settings: MyPluginSettings; - noteSharingService: NoteSharingService; +export default class NoteSharingPlugin extends Plugin { + private settings: PluginSettings; + private noteSharingService: NoteSharingService; + private eventRef: EventRef; async onload() { await this.loadSettings(); @@ -22,25 +23,28 @@ export default class MyPlugin extends Plugin { this.settings.serverUrl ); - // This adds a settings tab so the user can configure various aspects of the plugin + // Init settings tab this.addSettingTab(new SettingsTab(this.app, this)); - // This adds a complex command that can check whether the current state of the app allows execution of the command + // Add note sharing command this.addCommand({ id: "obsidian-note-sharing-share-note", name: "Create share link", checkCallback: (checking: boolean) => { - // Conditions to check - const markdownView = + // Only works on Markdown views + const activeView = this.app.workspace.getActiveViewOfType(MarkdownView); - if (markdownView) { - if (!checking) { - this.noteSharingService.shareNote(markdownView); - } - return true; - } + if (!activeView) return false; + if (checking) return true; + this.noteSharingService.shareNote(activeView.getViewData()); }, }); + + this.eventRef = this.app.workspace.on( + "file-menu", + (menu, file, source) => this.onMenuOpenCallback(menu, file, source) + ); + this.registerEvent(this.eventRef); } onunload() {} @@ -57,34 +61,19 @@ export default class MyPlugin extends Plugin { await this.saveData(this.settings); this.noteSharingService.serverUrl = this.settings.serverUrl; } -} -class SettingsTab extends PluginSettingTab { - plugin: MyPlugin; - - constructor(app: App, plugin: MyPlugin) { - super(app, plugin); - this.plugin = plugin; - } - - display(): void { - const { containerEl } = this; - - containerEl.empty(); - - containerEl.createEl("h2", { text: "Obsidian Note Sharing" }); - - new Setting(containerEl) - .setName("Server URL") - .setDesc("Server URL hosting the encrypted notes.") - .addText((text) => - text - .setPlaceholder("enter URL") - .setValue(this.plugin.settings.serverUrl) - .onChange(async (value) => { - this.plugin.settings.serverUrl = value; - await this.plugin.saveSettings(); - }) - ); + // https://github.dev/platers/obsidian-linter/blob/c30ceb17dcf2c003ca97862d94cbb0fd47b83d52/src/main.ts#L139-L149 + onMenuOpenCallback(menu: Menu, file: TAbstractFile, source: string) { + if (file instanceof TFile && file.extension === "md") { + menu.addItem((item) => { + item.setIcon("paper-plane-glyph"); + item.setTitle("Share note"); + item.onClick(async (evt) => { + this.noteSharingService.shareNote( + await this.app.vault.read(file) + ); + }); + }); + } } } diff --git a/plugin/src/NoteSharingService.ts b/plugin/src/NoteSharingService.ts index f8a993f..5a31f69 100644 --- a/plugin/src/NoteSharingService.ts +++ b/plugin/src/NoteSharingService.ts @@ -1,4 +1,4 @@ -import { MarkdownView, requestUrl } from "obsidian"; +import { requestUrl } from "obsidian"; import { encryptMarkdown } from "./encryption"; export class NoteSharingService { @@ -12,8 +12,8 @@ export class NoteSharingService { * @param mdView Markdown file to share. * @returns link to shared note with attached decryption key. */ - public async shareNote(mdView: MarkdownView): Promise { - const cryptData = encryptMarkdown(mdView); + public async shareNote(mdText: string): Promise { + const cryptData = encryptMarkdown(mdText); let url = await this.postNote(cryptData.ciphertext, cryptData.hmac); url += `#${cryptData.key}`; console.log(`Note shared: ${url}`); diff --git a/plugin/src/encryption.ts b/plugin/src/encryption.ts index f38b181..61f03c8 100644 --- a/plugin/src/encryption.ts +++ b/plugin/src/encryption.ts @@ -1,4 +1,4 @@ -import { MarkdownView, moment } from "obsidian"; +import { moment } from "obsidian"; import { generateKey, encryptString } from "./crypto"; export interface EncryptedMarkdown { @@ -7,8 +7,7 @@ export interface EncryptedMarkdown { key: string; } -export function encryptMarkdown(mdView: MarkdownView): EncryptedMarkdown { - const plaintext = mdView.getViewData(); +export function encryptMarkdown(plaintext: string): EncryptedMarkdown { const key = generateKey(moment.now() + plaintext); const { ciphertext, hmac } = encryptString(plaintext, key); return { ciphertext, hmac, key }; diff --git a/plugin/src/obsidian/PluginSettings.ts b/plugin/src/obsidian/PluginSettings.ts new file mode 100644 index 0000000..43cc087 --- /dev/null +++ b/plugin/src/obsidian/PluginSettings.ts @@ -0,0 +1,7 @@ +export interface PluginSettings { + serverUrl: string; +} + +export const DEFAULT_SETTINGS: PluginSettings = { + serverUrl: "http://localhost:8080", +}; diff --git a/plugin/src/obsidian/SettingsTab.ts b/plugin/src/obsidian/SettingsTab.ts new file mode 100644 index 0000000..0df1994 --- /dev/null +++ b/plugin/src/obsidian/SettingsTab.ts @@ -0,0 +1,32 @@ +import NoteSharingPlugin from "main"; +import { App, PluginSettingTab, Setting } from "obsidian"; + +export default class SettingsTab extends PluginSettingTab { + plugin: NoteSharingPlugin; + + constructor(app: App, plugin: NoteSharingPlugin) { + super(app, plugin); + this.plugin = plugin; + } + + display(): void { + const { containerEl } = this; + + containerEl.empty(); + + containerEl.createEl("h2", { text: "Obsidian Note Sharing" }); + + new Setting(containerEl) + .setName("Server URL") + .setDesc("Server URL hosting the encrypted notes.") + .addText((text) => + text + .setPlaceholder("enter URL") + .setValue(this.plugin.settings.serverUrl) + .onChange(async (value) => { + this.plugin.settings.serverUrl = value; + await this.plugin.saveSettings(); + }) + ); + } +} diff --git a/plugin/tsconfig.json b/plugin/tsconfig.json index 1383e2f..08c3248 100644 --- a/plugin/tsconfig.json +++ b/plugin/tsconfig.json @@ -1,23 +1,17 @@ { - "compilerOptions": { - "baseUrl": ".", - "inlineSourceMap": true, - "inlineSources": true, - "module": "ESNext", - "target": "ES6", - "allowJs": true, - "noImplicitAny": true, - "moduleResolution": "node", - "importHelpers": true, - "isolatedModules": true, - "lib": [ - "DOM", - "ES5", - "ES6", - "ES7" - ] - }, - "include": [ - "**/*.ts" - ] + "compilerOptions": { + "baseUrl": ".", + "inlineSourceMap": true, + "inlineSources": true, + "module": "ESNext", + "target": "ES6", + "allowJs": true, + "noImplicitAny": true, + "moduleResolution": "node", + "importHelpers": true, + "isolatedModules": true, + "outDir": "./build" /* Specify an output folder for all emitted files. */, + "lib": ["DOM", "ES5", "ES6", "ES7"] + }, + "include": ["**/*.ts"] } diff --git a/server/prisma/dev.db b/server/prisma/dev.db index eca1353bbccfd58e64530ff73e009c9bf561cf46..a8360e4098a5b221085d7b47ffd8e3dadf60f3d4 100644 GIT binary patch delta 4732 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 B9(4c! diff --git a/server/tsconfig.json b/server/tsconfig.json index a2b8d46..d859901 100644 --- a/server/tsconfig.json +++ b/server/tsconfig.json @@ -4,7 +4,6 @@ "lib": ["esnext"], "target": "es2016" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, "module": "commonjs" /* Specify what module code is generated. */, - "outDir": "./build" /* Specify an output folder for all emitted files. */, "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */, "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */, "strict": true /* Enable all strict type-checking options. */,