From 7330e7499a6886f686ee7689d1b60534b1ccbbf4 Mon Sep 17 00:00:00 2001 From: Aleksey Rowan <79934725+aleksey-rowan@users.noreply.github.com> Date: Wed, 15 Nov 2023 14:10:43 -0500 Subject: [PATCH 1/6] build: minify prod build closes #70 --- esbuild.config.mjs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/esbuild.config.mjs b/esbuild.config.mjs index b13282b..a5de8b8 100644 --- a/esbuild.config.mjs +++ b/esbuild.config.mjs @@ -38,6 +38,7 @@ const context = await esbuild.context({ sourcemap: prod ? false : "inline", treeShaking: true, outfile: "main.js", + minify: prod, }); if (prod) { @@ -45,4 +46,4 @@ if (prod) { process.exit(0); } else { await context.watch(); -} \ No newline at end of file +} From f4debcda6ba26922cb125526a1c3be0a53cf05c2 Mon Sep 17 00:00:00 2001 From: "iulianOnofrei (U-lee-aan)" <5748627+revolter@users.noreply.github.com> Date: Fri, 19 Jan 2024 21:14:58 +0200 Subject: [PATCH 2/6] Fix inconsistent indentation --- tsconfig.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tsconfig.json b/tsconfig.json index 2d6fbdf..c44b729 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -10,7 +10,7 @@ "moduleResolution": "node", "importHelpers": true, "isolatedModules": true, - "strictNullChecks": true, + "strictNullChecks": true, "lib": [ "DOM", "ES5", From de770934b29b0eb4c33be6add1ffeb7fac9d18e1 Mon Sep 17 00:00:00 2001 From: "iulianOnofrei (U-lee-aan)" <5748627+revolter@users.noreply.github.com> Date: Sun, 21 Jan 2024 15:20:39 +0200 Subject: [PATCH 3/6] Fix incorrect TypeScript spelling --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index bb0348e..9dad79e 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,8 @@ This is a sample plugin for Obsidian (https://obsidian.md). -This project uses Typescript to provide type checking and documentation. -The repo depends on the latest plugin API (obsidian.d.ts) in Typescript Definition format, which contains TSDoc comments describing what it does. +This project uses TypeScript to provide type checking and documentation. +The repo depends on the latest plugin API (obsidian.d.ts) in TypeScript Definition format, which contains TSDoc comments describing what it does. **Note:** The Obsidian API is still in early alpha and is subject to change at any time! From 47ec36c11ee8804784821cdbfda9c320a81744f6 Mon Sep 17 00:00:00 2001 From: "Tobias V. Langhoff" Date: Sat, 2 Mar 2024 22:30:14 +0100 Subject: [PATCH 4/6] Update README.md Update link to plugin guidelines --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bb0348e..0bc05a1 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ Quick starting guide for new plugin devs: ## Adding your plugin to the community plugin list -- Check https://github.com/obsidianmd/obsidian-releases/blob/master/plugin-review.md +- Check the [plugin guidelines](https://docs.obsidian.md/Plugins/Releasing/Plugin+guidelines). - Publish an initial version. - Make sure you have a `README.md` file in the root of your repo. - Make a pull request at https://github.com/obsidianmd/obsidian-releases to add your plugin. From 92050ad841e28de8b18cc3fc591ab3c9da6f5e30 Mon Sep 17 00:00:00 2001 From: Clare Macrae Date: Mon, 11 Nov 2024 19:58:31 +0000 Subject: [PATCH 5/6] Remove statement that API is unstable --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 578b2e2..c773152 100644 --- a/README.md +++ b/README.md @@ -5,8 +5,6 @@ This is a sample plugin for Obsidian (https://obsidian.md). This project uses TypeScript to provide type checking and documentation. The repo depends on the latest plugin API (obsidian.d.ts) in TypeScript Definition format, which contains TSDoc comments describing what it does. -**Note:** The Obsidian API is still in early alpha and is subject to change at any time! - This sample plugin demonstrates some of the basic functionality the plugin API can do. - Adds a ribbon icon, which shows a Notice when clicked. - Adds a command "Open Sample Modal" which opens a Modal. From 0647b948c5927e747280ab5b1ab4c079a4ffaafb Mon Sep 17 00:00:00 2001 From: xenofem Date: Sat, 18 Jan 2025 12:52:59 -0500 Subject: [PATCH 6/6] Obsidian Safe Filenames plugin --- main.ts | 141 ++++---------------------------------------------- manifest.json | 11 ++-- package.json | 6 +-- styles.css | 8 --- 4 files changed, 18 insertions(+), 148 deletions(-) delete mode 100644 styles.css diff --git a/main.ts b/main.ts index 2d07212..0261989 100644 --- a/main.ts +++ b/main.ts @@ -1,134 +1,13 @@ -import { App, Editor, MarkdownView, Modal, Notice, Plugin, PluginSettingTab, Setting } from 'obsidian'; +import { Plugin } from 'obsidian'; -// Remember to rename these classes and interfaces! +const UNSAFE_CHAR_REGEX = /[*?<>"]/g; -interface MyPluginSettings { - mySetting: string; -} - -const DEFAULT_SETTINGS: MyPluginSettings = { - mySetting: 'default' -} - -export default class MyPlugin extends Plugin { - settings: MyPluginSettings; - - async onload() { - await this.loadSettings(); - - // This creates an icon in the left ribbon. - const ribbonIconEl = this.addRibbonIcon('dice', 'Sample Plugin', (evt: MouseEvent) => { - // Called when the user clicks the icon. - new Notice('This is a notice!'); - }); - // Perform additional things with the ribbon - ribbonIconEl.addClass('my-plugin-ribbon-class'); - - // This adds a status bar item to the bottom of the app. Does not work on mobile apps. - const statusBarItemEl = this.addStatusBarItem(); - statusBarItemEl.setText('Status Bar Text'); - - // This adds a simple command that can be triggered anywhere - this.addCommand({ - id: 'open-sample-modal-simple', - name: 'Open sample modal (simple)', - callback: () => { - new SampleModal(this.app).open(); - } - }); - // This adds an editor command that can perform some operation on the current editor instance - this.addCommand({ - id: 'sample-editor-command', - name: 'Sample editor command', - editorCallback: (editor: Editor, view: MarkdownView) => { - 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 - this.addCommand({ - id: 'open-sample-modal-complex', - name: 'Open sample modal (complex)', - checkCallback: (checking: boolean) => { - // Conditions to check - const markdownView = this.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(this.app).open(); - } - - // This command will only show up in Command Palette when the check function returns true - return true; - } - } - }); - - // This adds a settings tab so the user can configure various aspects of the plugin - this.addSettingTab(new SampleSettingTab(this.app, this)); - - // If the plugin hooks up any global DOM events (on parts of the app that doesn't belong to this plugin) - // Using this function will automatically remove the event listener when this plugin is disabled. - this.registerDomEvent(document, 'click', (evt: MouseEvent) => { - console.log('click', evt); - }); - - // When registering intervals, this function will automatically clear the interval when the plugin is disabled. - this.registerInterval(window.setInterval(() => console.log('setInterval'), 5 * 60 * 1000)); - } - - onunload() { - - } - - async loadSettings() { - this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData()); - } - - async saveSettings() { - await this.saveData(this.settings); - } -} - -class SampleModal extends Modal { - constructor(app: App) { - super(app); - } - - onOpen() { - const {contentEl} = this; - contentEl.setText('Woah!'); - } - - onClose() { - const {contentEl} = this; - contentEl.empty(); - } -} - -class SampleSettingTab extends PluginSettingTab { - plugin: MyPlugin; - - constructor(app: App, plugin: MyPlugin) { - super(app, plugin); - this.plugin = plugin; - } - - display(): void { - const {containerEl} = this; - - containerEl.empty(); - - new Setting(containerEl) - .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(); - })); - } +export default class SafeFilenames extends Plugin { + async onload() { + this.registerEvent(this.app.vault.on('rename', (file, oldPath) => { + if (UNSAFE_CHAR_REGEX.test(file.path)) { + this.app.fileManager.renameFile(file, file.path.replaceAll(UNSAFE_CHAR_REGEX, '')); + } + })); + } } diff --git a/manifest.json b/manifest.json index dfa940e..1c80431 100644 --- a/manifest.json +++ b/manifest.json @@ -1,11 +1,10 @@ { - "id": "sample-plugin", - "name": "Sample Plugin", + "id": "safe-filenames", + "name": "Safe Filenames", "version": "1.0.0", "minAppVersion": "0.15.0", - "description": "Demonstrates some of the capabilities of the Obsidian API.", - "author": "Obsidian", - "authorUrl": "https://obsidian.md", - "fundingUrl": "https://obsidian.md/pricing", + "description": "Prevents renaming files with characters that can't be synced cross-platform.", + "author": "xenofem", + "authorUrl": "https://xeno.science", "isDesktopOnly": false } diff --git a/package.json b/package.json index 6a00766..0319f4e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { - "name": "obsidian-sample-plugin", + "name": "obsidian-safe-filenames", "version": "1.0.0", - "description": "This is a sample plugin for Obsidian (https://obsidian.md)", + "description": "Obsidian plugin to prevent renaming files with unsafe characters", "main": "main.js", "scripts": { "dev": "node esbuild.config.mjs", @@ -9,7 +9,7 @@ "version": "node version-bump.mjs && git add manifest.json versions.json" }, "keywords": [], - "author": "", + "author": "xenofem", "license": "MIT", "devDependencies": { "@types/node": "^16.11.6", diff --git a/styles.css b/styles.css deleted file mode 100644 index 71cc60f..0000000 --- a/styles.css +++ /dev/null @@ -1,8 +0,0 @@ -/* - -This CSS file will be included with your plugin, and -available in the app when your plugin is enabled. - -If your plugin does not need CSS, delete this file. - -*/