From 08d79f06740f88c3d8f24ad7ada941cae5b5f5de Mon Sep 17 00:00:00 2001 From: fyears Date: Sun, 17 Oct 2021 22:50:12 +0800 Subject: [PATCH] first working prototype --- .gitignore | 3 + README.md | 76 +++--------- main.ts | 301 +++++++++++++++++++++++++++++------------------ manifest.json | 20 ++-- package.json | 48 ++++++-- rollup.config.js | 30 ----- styles.css | 5 +- tsconfig.json | 39 +++--- versions.json | 7 +- 9 files changed, 280 insertions(+), 249 deletions(-) delete mode 100644 rollup.config.js diff --git a/.gitignore b/.gitignore index 2fd7c5e..3502795 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,6 @@ main.js # obsidian data.json + +# hidden files +.* diff --git a/README.md b/README.md index 9e4fe9c..9840f45 100644 --- a/README.md +++ b/README.md @@ -1,57 +1,19 @@ -## Obsidian Sample Plugin - -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. -- 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. - -### First time developing plugins? - -Quick starting guide for new plugin devs: - -- 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. -- Publish the release. - -### Adding your plugin to the community plugin list - -- 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/`. - -### API Documentation - -See https://github.com/obsidianmd/obsidian-api +# Save Remote + +This is yet another sync plugin for Obsidian. + +## Disclaimer + +**This is NOT the official sync service provided by Obsidian.** + +## !!!Caution!!! + +As of October 2021, the plugin is under development. **DO NOT USE IT for any serious vaults.** Prepare for data loss! + +## Usage + +Remote service in support list: + +- [ ] AWS S3 +- [ ] webdav + diff --git a/main.ts b/main.ts index 36e175e..b060ade 100644 --- a/main.ts +++ b/main.ts @@ -1,112 +1,189 @@ -import { App, Modal, Notice, Plugin, PluginSettingTab, Setting } from 'obsidian'; - -interface MyPluginSettings { - mySetting: string; -} - -const DEFAULT_SETTINGS: MyPluginSettings = { - mySetting: 'default' -} - -export default class MyPlugin extends Plugin { - settings: MyPluginSettings; - - async onload() { - console.log('loading plugin'); - - await this.loadSettings(); - - this.addRibbonIcon('dice', 'Sample Plugin', () => { - new Notice('This is a notice!'); - }); - - this.addStatusBarItem().setText('Status Bar Text'); - - this.addCommand({ - id: 'open-sample-modal', - name: 'Open Sample Modal', - // callback: () => { - // console.log('Simple Callback'); - // }, - checkCallback: (checking: boolean) => { - let leaf = this.app.workspace.activeLeaf; - if (leaf) { - if (!checking) { - new SampleModal(this.app).open(); - } - return true; - } - return false; - } - }); - - this.addSettingTab(new SampleSettingTab(this.app, this)); - - this.registerCodeMirror((cm: CodeMirror.Editor) => { - console.log('codemirror', cm); - }); - - this.registerDomEvent(document, 'click', (evt: MouseEvent) => { - console.log('click', evt); - }); - - this.registerInterval(window.setInterval(() => console.log('setInterval'), 5 * 60 * 1000)); - } - - onunload() { - console.log('unloading plugin'); - } - - 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() { - let {contentEl} = this; - contentEl.setText('Woah!'); - } - - onClose() { - let {contentEl} = this; - contentEl.empty(); - } -} - -class SampleSettingTab extends PluginSettingTab { - plugin: MyPlugin; - - constructor(app: App, plugin: MyPlugin) { - super(app, plugin); - this.plugin = plugin; - } - - display(): void { - let {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(); - })); - } -} +import * as path from "path"; +import { + App, + Modal, + Notice, + Plugin, + PluginSettingTab, + Setting, + request, + Platform, +} from "obsidian"; +import * as CodeMirror from "codemirror"; + +import { ListObjectsCommand, S3Client } from "@aws-sdk/client-s3"; + +interface SaveRemotePluginSettings { + s3Endpoint: string; + s3Region: string; + s3AccessKeyID: string; + s3SecretAccessKey: string; + s3BucketName: string; +} + +const DEFAULT_SETTINGS: SaveRemotePluginSettings = { + s3Endpoint: "", + s3Region: "", + s3AccessKeyID: "", + s3SecretAccessKey: "", + s3BucketName: "", +}; + +const ignoreHiddenFiles = (item: string) => { + const basename = path.basename(item); + return basename === "." || basename[0] !== "."; +}; + +const getTextToInsert = (x: any) => { + return "\n```json\n" + JSON.stringify(x, null, 2) + "\n```\n"; +}; + +export default class SaveRemotePlugin extends Plugin { + settings: SaveRemotePluginSettings; + cm: CodeMirror.Editor; + + async onload() { + console.log("loading plugin obsidian-save-remote"); + + await this.loadSettings(); + + + this.addRibbonIcon("dice", "Save Remote Plugin", async () => { + new Notice(`checking connection`); + + const s3Client = new S3Client({ + region: this.settings.s3Region, + endpoint: this.settings.s3Endpoint, + credentials: { + accessKeyId: this.settings.s3AccessKeyID, + secretAccessKey: this.settings.s3SecretAccessKey, + }, + }); + console.log(s3Client) + + try { + const data = await s3Client.send( + new ListObjectsCommand({ + Bucket: this.settings.s3BucketName, + }) + ); + this.cm.replaceRange( + getTextToInsert(data), + CodeMirror.Pos(this.cm.lastLine()) + ); + new Notice("good!"); + } catch (err) { + console.log("Error", err); + } + }); + + this.addSettingTab(new SaveRemoteSettingTab(this.app, this)); + + this.registerCodeMirror((cm: CodeMirror.Editor) => { + this.cm = cm; + console.log("codemirror registered."); + }); + + // this.registerDomEvent(document, "click", (evt: MouseEvent) => { + // console.log("click", evt); + // }); + + // this.registerInterval( + // window.setInterval(() => console.log("setInterval"), 5 * 60 * 1000) + // ); + } + + onunload() { + console.log("unloading plugin obsidian-save-remote"); + } + + async loadSettings() { + this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData()); + } + + async saveSettings() { + await this.saveData(this.settings); + } +} + +class SaveRemoteSettingTab extends PluginSettingTab { + plugin: SaveRemotePlugin; + + constructor(app: App, plugin: SaveRemotePlugin) { + super(app, plugin); + this.plugin = plugin; + } + + display(): void { + let { containerEl } = this; + + containerEl.empty(); + + containerEl.createEl("h2", { text: "Settings for Save Remote" }); + + new Setting(containerEl) + .setName("s3Endpoint") + .setDesc("s3Endpoint") + .addText((text) => + text + .setPlaceholder("") + .setValue(this.plugin.settings.s3Endpoint) + .onChange(async (value) => { + this.plugin.settings.s3Endpoint = value; + await this.plugin.saveSettings(); + }) + ); + + new Setting(containerEl) + .setName("s3Region") + .setDesc("s3Region") + .addText((text) => + text + .setPlaceholder("") + .setValue(`${this.plugin.settings.s3Region}`) + .onChange(async (value) => { + this.plugin.settings.s3Region = value; + await this.plugin.saveSettings(); + }) + ); + + new Setting(containerEl) + .setName("s3AccessKeyID") + .setDesc("s3AccessKeyID") + .addText((text) => + text + .setPlaceholder("") + .setValue(`${this.plugin.settings.s3AccessKeyID}`) + .onChange(async (value) => { + this.plugin.settings.s3AccessKeyID = value; + await this.plugin.saveSettings(); + }) + ); + + new Setting(containerEl) + .setName("s3SecretAccessKey") + .setDesc("s3SecretAccessKey") + .addText((text) => + text + .setPlaceholder("") + .setValue(`${this.plugin.settings.s3SecretAccessKey}`) + .onChange(async (value) => { + this.plugin.settings.s3SecretAccessKey = value; + await this.plugin.saveSettings(); + }) + ); + + new Setting(containerEl) + .setName("s3BucketName") + .setDesc("s3BucketName") + .addText((text) => + text + .setPlaceholder("") + .setValue(`${this.plugin.settings.s3BucketName}`) + .onChange(async (value) => { + this.plugin.settings.s3BucketName = value; + await this.plugin.saveSettings(); + }) + ); + } +} diff --git a/manifest.json b/manifest.json index 4ca4889..cf67c1e 100644 --- a/manifest.json +++ b/manifest.json @@ -1,10 +1,10 @@ -{ - "id": "obsidian-sample-plugin", - "name": "Sample Plugin", - "version": "1.0.1", - "minAppVersion": "0.9.12", - "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/about", - "isDesktopOnly": false -} +{ + "id": "obsdian-save-remote", + "name": "Save remote", + "version": "0.0.1", + "minAppVersion": "0.12.15", + "description": "This is yet another plugin allowing users to sync notes between local device and the cloud.", + "author": "fyears", + "authorUrl": "https://github.com/fyears", + "isDesktopOnly": false +} diff --git a/package.json b/package.json index 29e2406..67e04dc 100644 --- a/package.json +++ b/package.json @@ -1,23 +1,51 @@ { - "name": "obsidian-sample-plugin", - "version": "0.12.0", - "description": "This is a sample plugin for Obsidian (https://obsidian.md)", - "main": "main.js", + "name": "obsidian-save-remote", + "version": "0.0.1", + "description": "This is yet another sync plugin for Obsidian app.", "scripts": { - "dev": "rollup --config rollup.config.js -w", - "build": "rollup --config rollup.config.js --environment BUILD:production" + "dev": "parcel watch", + "build": "parcel build", + "format": "npx prettier --write .", + "clean": "npx rimraf main.js" + }, + "source": "main.ts", + "targets": { + "frontend": { + "context": "browser", + "outputFormat": "commonjs", + "isLibrary": true, + "includeNodeModules": { + "obsidian": false + }, + "sourceMap": false, + "distDir": "." + } }, "keywords": [], "author": "", - "license": "MIT", + "license": "Apache-2.0", "devDependencies": { "@rollup/plugin-commonjs": "^18.0.0", + "@rollup/plugin-json": "^4.1.0", "@rollup/plugin-node-resolve": "^11.2.1", "@rollup/plugin-typescript": "^8.2.1", "@types/node": "^14.14.37", - "obsidian": "^0.12.0", - "rollup": "^2.32.1", + "parcel": "^2.0.0", + "prettier": "^2.4.1", "tslib": "^2.2.0", - "typescript": "^4.2.4" + "typescript": "^4.4.3", + "webdav-server": "^2.6.2" + }, + "dependencies": { + "@aws-sdk/client-s3": "^3.37.0", + "codemirror": "^5.63.1", + "rimraf": "^3.0.2", + "webdav": "^4.7.0", + "webdav-fs": "^4.0.0", + "obsidian": "^0.12.0" + }, + "@parcel/transformer-js": { + "inlineFS": false, + "inlineEnvironment": false } } diff --git a/rollup.config.js b/rollup.config.js deleted file mode 100644 index dd4d041..0000000 --- a/rollup.config.js +++ /dev/null @@ -1,30 +0,0 @@ -import typescript from '@rollup/plugin-typescript'; -import {nodeResolve} from '@rollup/plugin-node-resolve'; -import commonjs from '@rollup/plugin-commonjs'; - -const isProd = (process.env.BUILD === 'production'); - -const banner = -`/* -THIS IS A GENERATED/BUNDLED FILE BY ROLLUP -if you want to view the source visit the plugins github repository -*/ -`; - -export default { - input: 'main.ts', - output: { - dir: '.', - sourcemap: 'inline', - sourcemapExcludeSources: isProd, - format: 'cjs', - exports: 'default', - banner, - }, - external: ['obsidian'], - plugins: [ - typescript(), - nodeResolve({browser: true}), - commonjs(), - ] -}; \ No newline at end of file diff --git a/styles.css b/styles.css index cfd0fd7..7ccb711 100644 --- a/styles.css +++ b/styles.css @@ -1,4 +1 @@ -/* Sets all the text color to red! */ -body { - color: red; -} +/* set the styles */ diff --git a/tsconfig.json b/tsconfig.json index 09cf7ec..4618070 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,22 +1,17 @@ -{ - "compilerOptions": { - "baseUrl": ".", - "inlineSourceMap": true, - "inlineSources": true, - "module": "ESNext", - "target": "es6", - "allowJs": true, - "noImplicitAny": true, - "moduleResolution": "node", - "importHelpers": true, - "lib": [ - "dom", - "es5", - "scripthost", - "es2015" - ] - }, - "include": [ - "**/*.ts" - ] -} +{ + "compilerOptions": { + "baseUrl": ".", + "inlineSourceMap": true, + "inlineSources": true, + "module": "ESNext", + "target": "es6", + "allowJs": true, + "noImplicitAny": true, + "moduleResolution": "node", + // "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + "importHelpers": true, + "lib": ["dom", "es5", "scripthost", "es2015"] + }, + "include": ["**/*.ts"] +} diff --git a/versions.json b/versions.json index ba14785..846ce11 100644 --- a/versions.json +++ b/versions.json @@ -1,4 +1,3 @@ -{ - "1.0.1": "0.9.12", - "1.0.0": "0.9.7" -} +{ + "0.0.1": "0.12.15" +}