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.
**This is NOT the official sync service provided by Obsidian.**
**Note:** The Obsidian API is still in early alpha and is subject to change at any time!
## !!!Caution!!!
This sample plugin demonstrates some of the basic functionality the plugin API can do.
- Changes the default font color to red using `styles.css`. As of October 2021, the plugin is under development. **DO NOT USE IT for any serious vaults.** Prepare for data loss!
- Adds a ribbon icon, which shows a Notice when clicked.
- Adds a command "Open Sample Modal" which opens a Modal. ## Usage
- Adds a plugin setting tab to the settings page.
- Registers a global click event and output 'click' to the console. Remote service in support list:
- Registers a global interval which logs 'setInterval' to the console.
- [ ] AWS S3
### First time developing plugins? - [ ] webdav
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

301
main.ts
View File

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

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

@ -1,22 +1,17 @@
{ {
"compilerOptions": { "compilerOptions": {
"baseUrl": ".", "baseUrl": ".",
"inlineSourceMap": true, "inlineSourceMap": true,
"inlineSources": true, "inlineSources": true,
"module": "ESNext", "module": "ESNext",
"target": "es6", "target": "es6",
"allowJs": true, "allowJs": true,
"noImplicitAny": true, "noImplicitAny": true,
"moduleResolution": "node", "moduleResolution": "node",
"importHelpers": true, // "allowSyntheticDefaultImports": true,
"lib": [ "esModuleInterop": true,
"dom", "importHelpers": true,
"es5", "lib": ["dom", "es5", "scripthost", "es2015"]
"scripthost", },
"es2015" "include": ["**/*.ts"]
] }
},
"include": [
"**/*.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" }
}