first working prototype

This commit is contained in:
fyears 2021-10-17 22:50:12 +08:00
parent 1daf02eb25
commit 08d79f0674
9 changed files with 280 additions and 249 deletions

3
.gitignore vendored
View File

@ -12,3 +12,6 @@ main.js
# obsidian # obsidian
data.json data.json
# hidden files
.*

View File

@ -1,57 +1,19 @@
## Obsidian Sample Plugin # Save Remote
This is a sample plugin for Obsidian (https://obsidian.md). This is yet another sync plugin for Obsidian.
This project uses Typescript to provide type checking and documentation. ## Disclaimer
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 is NOT the official sync service provided by Obsidian.**
This sample plugin demonstrates some of the basic functionality the plugin API can do. ## !!!Caution!!!
- 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? As of October 2021, the plugin is under development. **DO NOT USE IT for any serious vaults.** Prepare for data loss!
Quick starting guide for new plugin devs: ## Usage
- Make a copy of this repo as a template with the "Use this template" button (login to GitHub if you don't see it). Remote service in support list:
- 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 - [ ] AWS S3
- [ ] webdav
- 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

203
main.ts
View File

@ -1,60 +1,100 @@
import { App, Modal, Notice, Plugin, PluginSettingTab, Setting } from 'obsidian'; import * as path from "path";
import {
App,
Modal,
Notice,
Plugin,
PluginSettingTab,
Setting,
request,
Platform,
} from "obsidian";
import * as CodeMirror from "codemirror";
interface MyPluginSettings { import { ListObjectsCommand, S3Client } from "@aws-sdk/client-s3";
mySetting: string;
interface SaveRemotePluginSettings {
s3Endpoint: string;
s3Region: string;
s3AccessKeyID: string;
s3SecretAccessKey: string;
s3BucketName: string;
} }
const DEFAULT_SETTINGS: MyPluginSettings = { const DEFAULT_SETTINGS: SaveRemotePluginSettings = {
mySetting: 'default' s3Endpoint: "",
} s3Region: "",
s3AccessKeyID: "",
s3SecretAccessKey: "",
s3BucketName: "",
};
export default class MyPlugin extends Plugin { const ignoreHiddenFiles = (item: string) => {
settings: MyPluginSettings; 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() { async onload() {
console.log('loading plugin'); console.log("loading plugin obsidian-save-remote");
await this.loadSettings(); await this.loadSettings();
this.addRibbonIcon('dice', 'Sample Plugin', () => {
new Notice('This is a notice!'); 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)
this.addStatusBarItem().setText('Status Bar Text'); try {
const data = await s3Client.send(
this.addCommand({ new ListObjectsCommand({
id: 'open-sample-modal', Bucket: this.settings.s3BucketName,
name: 'Open Sample Modal', })
// callback: () => { );
// console.log('Simple Callback'); this.cm.replaceRange(
// }, getTextToInsert(data),
checkCallback: (checking: boolean) => { CodeMirror.Pos(this.cm.lastLine())
let leaf = this.app.workspace.activeLeaf; );
if (leaf) { new Notice("good!");
if (!checking) { } catch (err) {
new SampleModal(this.app).open(); console.log("Error", err);
}
return true;
}
return false;
} }
}); });
this.addSettingTab(new SampleSettingTab(this.app, this)); this.addSettingTab(new SaveRemoteSettingTab(this.app, this));
this.registerCodeMirror((cm: CodeMirror.Editor) => { this.registerCodeMirror((cm: CodeMirror.Editor) => {
console.log('codemirror', cm); this.cm = cm;
console.log("codemirror registered.");
}); });
this.registerDomEvent(document, 'click', (evt: MouseEvent) => { // this.registerDomEvent(document, "click", (evt: MouseEvent) => {
console.log('click', evt); // console.log("click", evt);
}); // });
this.registerInterval(window.setInterval(() => console.log('setInterval'), 5 * 60 * 1000)); // this.registerInterval(
// window.setInterval(() => console.log("setInterval"), 5 * 60 * 1000)
// );
} }
onunload() { onunload() {
console.log('unloading plugin'); console.log("unloading plugin obsidian-save-remote");
} }
async loadSettings() { async loadSettings() {
@ -66,26 +106,10 @@ export default class MyPlugin extends Plugin {
} }
} }
class SampleModal extends Modal { class SaveRemoteSettingTab extends PluginSettingTab {
constructor(app: App) { plugin: SaveRemotePlugin;
super(app);
}
onOpen() { constructor(app: App, plugin: SaveRemotePlugin) {
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); super(app, plugin);
this.plugin = plugin; this.plugin = plugin;
} }
@ -95,18 +119,71 @@ class SampleSettingTab extends PluginSettingTab {
containerEl.empty(); containerEl.empty();
containerEl.createEl('h2', {text: 'Settings for my awesome plugin.'}); containerEl.createEl("h2", { text: "Settings for Save Remote" });
new Setting(containerEl) new Setting(containerEl)
.setName('Setting #1') .setName("s3Endpoint")
.setDesc('It\'s a secret') .setDesc("s3Endpoint")
.addText(text => text .addText((text) =>
.setPlaceholder('Enter your secret') text
.setValue(this.plugin.settings.mySetting) .setPlaceholder("")
.setValue(this.plugin.settings.s3Endpoint)
.onChange(async (value) => { .onChange(async (value) => {
console.log('Secret: ' + value); this.plugin.settings.s3Endpoint = value;
this.plugin.settings.mySetting = value;
await this.plugin.saveSettings(); 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();
})
);
} }
} }

View File

@ -1,10 +1,10 @@
{ {
"id": "obsidian-sample-plugin", "id": "obsdian-save-remote",
"name": "Sample Plugin", "name": "Save remote",
"version": "1.0.1", "version": "0.0.1",
"minAppVersion": "0.9.12", "minAppVersion": "0.12.15",
"description": "This is a sample plugin for Obsidian. This plugin demonstrates some of the capabilities of the Obsidian API.", "description": "This is yet another plugin allowing users to sync notes between local device and the cloud.",
"author": "Obsidian", "author": "fyears",
"authorUrl": "https://obsidian.md/about", "authorUrl": "https://github.com/fyears",
"isDesktopOnly": false "isDesktopOnly": false
} }

View File

@ -1,23 +1,51 @@
{ {
"name": "obsidian-sample-plugin", "name": "obsidian-save-remote",
"version": "0.12.0", "version": "0.0.1",
"description": "This is a sample plugin for Obsidian (https://obsidian.md)", "description": "This is yet another sync plugin for Obsidian app.",
"main": "main.js",
"scripts": { "scripts": {
"dev": "rollup --config rollup.config.js -w", "dev": "parcel watch",
"build": "rollup --config rollup.config.js --environment BUILD:production" "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": [], "keywords": [],
"author": "", "author": "",
"license": "MIT", "license": "Apache-2.0",
"devDependencies": { "devDependencies": {
"@rollup/plugin-commonjs": "^18.0.0", "@rollup/plugin-commonjs": "^18.0.0",
"@rollup/plugin-json": "^4.1.0",
"@rollup/plugin-node-resolve": "^11.2.1", "@rollup/plugin-node-resolve": "^11.2.1",
"@rollup/plugin-typescript": "^8.2.1", "@rollup/plugin-typescript": "^8.2.1",
"@types/node": "^14.14.37", "@types/node": "^14.14.37",
"obsidian": "^0.12.0", "parcel": "^2.0.0",
"rollup": "^2.32.1", "prettier": "^2.4.1",
"tslib": "^2.2.0", "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
} }
} }

View File

@ -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(),
]
};

View File

@ -1,4 +1 @@
/* Sets all the text color to red! */ /* set the styles */
body {
color: red;
}

View File

@ -8,15 +8,10 @@
"allowJs": true, "allowJs": true,
"noImplicitAny": true, "noImplicitAny": true,
"moduleResolution": "node", "moduleResolution": "node",
// "allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"importHelpers": true, "importHelpers": true,
"lib": [ "lib": ["dom", "es5", "scripthost", "es2015"]
"dom",
"es5",
"scripthost",
"es2015"
]
}, },
"include": [ "include": ["**/*.ts"]
"**/*.ts"
]
} }

View File

@ -1,4 +1,3 @@
{ {
"1.0.1": "0.9.12", "0.0.1": "0.12.15"
"1.0.0": "0.9.7"
} }