diff --git a/README.md b/README.md index 31e5155..ea74d1f 100644 --- a/README.md +++ b/README.md @@ -1,96 +1,20 @@ -# Obsidian Sample Plugin +# Obsidian MacTagger Plugin -This is a sample plugin for Obsidian (https://obsidian.md). +This plugin is now just drafts (or proof of concept) of an idea that has been spinning in my head for a long time. "What if I sync Mac OS (iOS) tags with Obsidian tags?". -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. +**Warning**: Anything you do yo do at your own risk! Please test plugin on sandbox before use on your prod vault. Or do backup :) -**Note:** The Obsidian API is still in early alpha and is subject to change at any time! +## Works now +- Two commands: + 1. `Write Mac OS tags` - wrtie all tags (frontmatter and body) from current Obsidian note as mac os file tags. + 2. `Write Mac OS tags for current folder` - some as previsoly but for all file in current folder. -This sample plugin demonstrates some of the basic functionality the plugin API can do. -- Changes the default font color to red using `styles.css`. -- Adds a ribbon icon, which shows a Notice when clicked. -- Adds a command "Open Sample Modal" which opens a Modal. -- Adds a plugin setting tab to the settings page. -- Registers a global click event and output 'click' to the console. -- Registers a global interval which logs 'setInterval' to the console. +## To-Do +- Sync tags while file saved. +- Setting options overwrite or not existing mac os tag. +- Setting options with tags list allowed for sync. Maybe black/whit list. -## First time developing plugins? +## Contribute +I will be grateful for any contribution! -Quick starting guide for new plugin devs: - -- Check if [someone already developed a plugin for what you want](https://obsidian.md/plugins)! There might be an existing plugin similar enough that you can partner up with. -- Make a copy of this repo as a template with the "Use this template" button (login to GitHub if you don't see it). -- Clone your repo to a local development folder. For convenience, you can place this folder in your `.obsidian/plugins/your-plugin-name` folder. -- Install NodeJS, then run `npm i` in the command line under your repo folder. -- Run `npm run dev` to compile your plugin from `main.ts` to `main.js`. -- Make changes to `main.ts` (or create new `.ts` files). Those changes should be automatically compiled into `main.js`. -- Reload Obsidian to load the new version of your plugin. -- Enable plugin in settings window. -- For updates to the Obsidian API run `npm update` in the command line under your repo folder. - -## Releasing new releases - -- Update your `manifest.json` with your new version number, such as `1.0.1`, and the minimum Obsidian version required for your latest release. -- Update your `versions.json` file with `"new-plugin-version": "minimum-obsidian-version"` so older versions of Obsidian can download an older version of your plugin that's compatible. -- Create new GitHub release using your new version number as the "Tag version". Use the exact version number, don't include a prefix `v`. See here for an example: https://github.com/obsidianmd/obsidian-sample-plugin/releases -- Upload the files `manifest.json`, `main.js`, `styles.css` as binary attachments. Note: The manifest.json file must be in two places, first the root path of your repository and also in the release. -- Publish the release. - -> You can simplify the version bump process by running `npm version patch`, `npm version minor` or `npm version major` after updating `minAppVersion` manually in `manifest.json`. -> The command will bump version in `manifest.json` and `package.json`, and add the entry for the new version to `versions.json` - -## Adding your plugin to the community plugin list - -- Check https://github.com/obsidianmd/obsidian-releases/blob/master/plugin-review.md -- 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. - -## How to use - -- Clone this repo. -- `npm i` or `yarn` to install dependencies -- `npm run dev` to start compilation in watch mode. - -## Manually installing the plugin - -- Copy over `main.js`, `styles.css`, `manifest.json` to your vault `VaultFolder/.obsidian/plugins/your-plugin-id/`. - -## Improve code quality with eslint (optional) -- [ESLint](https://eslint.org/) is a tool that analyzes your code to quickly find problems. You can run ESLint against your plugin to find common bugs and ways to improve your code. -- To use eslint with this project, make sure to install eslint from terminal: - - `npm install -g eslint` -- To use eslint to analyze this project use this command: - - `eslint main.ts` - - eslint will then create a report with suggestions for code improvement by file and line number. -- If your source code is in a folder, such as `src`, you can use eslint with this command to analyze all files in that folder: - - `eslint .\src\` - -## Funding URL - -You can include funding URLs where people who use your plugin can financially support it. - -The simple way is to set the `fundingUrl` field to your link in your `manifest.json` file: - -```json -{ - "fundingUrl": "https://buymeacoffee.com" -} -``` - -If you have multiple URLs, you can also do: - -```json -{ - "fundingUrl": { - "Buy Me a Coffee": "https://buymeacoffee.com", - "GitHub Sponsor": "https://github.com/sponsors", - "Patreon": "https://www.patreon.com/" - } -} -``` - -## API Documentation - -See https://github.com/obsidianmd/obsidian-api +Сreate issues, write comments, send feature requests also a pull requests. diff --git a/main.ts b/main.ts index 50b75f3..d4c22a3 100644 --- a/main.ts +++ b/main.ts @@ -1,137 +1,68 @@ -import { App, Editor, MarkdownView, Modal, Notice, Plugin, PluginSettingTab, Setting } from 'obsidian'; +import { Editor, MarkdownView, Plugin, TFile } from 'obsidian'; +import { exec } from "child_process"; -// Remember to rename these classes and interfaces! - -interface MyPluginSettings { - mySetting: string; -} - -const DEFAULT_SETTINGS: MyPluginSettings = { - mySetting: 'default' -} - -export default class MyPlugin extends Plugin { - settings: MyPluginSettings; +const plist = require('plist'); +export default class MacTagPlugin extends Plugin { 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', + id: 'write-macos-tag', + name: "Write Mac OS tags", editorCallback: (editor: Editor, view: MarkdownView) => { - console.log(editor.getSelection()); - editor.replaceSelection('Sample Editor Command'); + this.writeTags(view.file); } }); - // 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(); + id: 'write-macos-tag-folder', + name: "Write Mac OS tags for current folder", + editorCallback: (editor: Editor, view: MarkdownView) => { + view.file.parent.children.forEach((file) => { + if (file instanceof TFile) { + this.writeTags(file); } - - // 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()); + writeTags(file: TFile) { + //@ts-ignore + const fileWithPath = `${this.app.vault.adapter.basePath}/${file.path}`; + const plTags: string = plist.build(this.getTags(file)); + + exec(`xattr -w com.apple.metadata:_kMDItemUserTags '${plTags}' '${fileWithPath}'`,(error, stdout, stderr) => { + if (error) { + console.log(`error: ${error.message}`); + return; + } + if (stderr) { + console.log(`stderr: ${stderr}`); + return; + } + }); } - 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(); - - containerEl.createEl('h2', {text: 'Settings for my awesome plugin.'}); - - 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) => { - console.log('Secret: ' + value); - this.plugin.settings.mySetting = value; - await this.plugin.saveSettings(); - })); + getTags(file: TFile): string[] { + const tags: string[] = []; + const metadata = this.app.metadataCache.getFileCache(file); + if (metadata?.tags) { + metadata.tags.forEach(function (value) { + tags.push(value.tag); + }); + } + if (metadata?.frontmatter) { + if (metadata.frontmatter.tags){ + const frontmattertags: string[] = typeof metadata.frontmatter.tags === "string" ? [metadata.frontmatter.tags] : metadata.frontmatter.tags; + frontmattertags.forEach(function (value) { + tags.push(value); + }); + } + } + return tags.map((s: string)=> s.replace("#", "")) } } diff --git a/manifest.json b/manifest.json index 0897aff..683c813 100644 --- a/manifest.json +++ b/manifest.json @@ -1,11 +1,10 @@ { - "id": "obsidian-sample-plugin", - "name": "Sample Plugin", - "version": "1.0.0", + "id": "obsidian-mactagger-plugin", + "name": "MacTagger Plugin", + "version": "0.0.1", "minAppVersion": "0.15.0", - "description": "This is a sample plugin for Obsidian. This plugin demonstrates some of the capabilities of the Obsidian API.", - "author": "Obsidian", - "authorUrl": "https://obsidian.md", - "fundingUrl": "https://obsidian.md/pricing", - "isDesktopOnly": false + "description": "The plugin sets Mac OS tags according to the tags specified in Obsidian notes", + "author": "Maxim Syomochkin", + "authorUrl": "https://mak-sim.ru", + "isDesktopOnly": true } diff --git a/package.json b/package.json index 3ada219..b2bb40c 100644 --- a/package.json +++ b/package.json @@ -20,5 +20,8 @@ "obsidian": "latest", "tslib": "2.4.0", "typescript": "4.7.4" + }, + "dependencies": { + "plist": "^3.0.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. - -*/ diff --git a/versions.json b/versions.json index 26382a1..4fde155 100644 --- a/versions.json +++ b/versions.json @@ -1,3 +1,3 @@ { - "1.0.0": "0.15.0" + "0.0.1": "0.15.0" }