brushup readme

add delete handling
icon fix
This commit is contained in:
vorotamoroz committed 2021-10-13 21:38:44 +09:00
1 parent ed0d8372cb
commit 44efde7762
23 files changed
+563 -217

No files matched your search

+91 -15
View File
@@ -1,24 +1,100 @@
# obsidian-livesync # obsidian-livesync
This is the obsidian plugin that enables livesync between multi terminals. This is the obsidian plugin that enables livesync between multi terminals.
<!-- screenshot/movie will coming. --> <!-- screenshot/movie will coming. -->
**It's on the bleeding edge. Do not use for your "precious" Vault.** **It's on the bleeding edge. Do not use for your "precious" Vault.**
## This plugin enables.. ## This plugin enables..
- Live sync
- Self-Hosted data synchronization with conflict detection and resolving in Obsidian.
## how to use the experimental build - Live sync
- Self-Hosted data synchronization with conflict detection and resolving in Obsidian.
1. download this repo and expand `[your-vault]/.obsidian/plugins/` (PC, Mac and Android will work) ## how to use the experimental build
1. enable obsidian livesync in the settings dialog.
1. If you use your self-hosted CouchDB, set your server's info.
1. or Use [IBM Cloudant](https://www.ibm.com/cloud/cloudant), take an account and enable **Cloudant** in [Catalog](https://cloud.ibm.com/catalog#services)
Note please choose "IAM and legacy credentials" for the Authentication method
Setup details are in Couldant Setup Section.
1. Setup LiveSync or SyncOnSave or SyncOnStart as you like.
### Cloudant Setup 1. download this repo and expand `[your-vault]/.obsidian/plugins/` (PC, Mac and Android will work)
**WIP** 1. enable obsidian livesync in the settings dialog.
1. If you use your self-hosted CouchDB, set your server's info.
1. or Use [IBM Cloudant](https://www.ibm.com/cloud/cloudant), take an account and enable **Cloudant** in [Catalog](https://cloud.ibm.com/catalog#services)
Note please choose "IAM and legacy credentials" for the Authentication method
Setup details are in Couldant Setup Section.
1. Setup LiveSync or SyncOnSave or SyncOnStart as you like.
## Cloudant Setup
### Creating an Instance
1. Hit the "Create Resource" button.
![step 1](./instruction_images/cloudant_1.png)
1. In IBM Cloud Catalog, search "Cloudant".
![step 2](instruction_images/cloudant_2.png)
1. You can choise "Lite plan" in free.
![step 3](instruction_images/cloudant_3.png)
Select Multitenant(it's the default) and the region as you like.
![step 4](instruction_images/cloudant_4.png) 3. Be sure to select "IAM and Legacy credentials" for "Authentication Method".
![step 5](instruction_images/cloudant_5.png)
4. Select Lite and be sure to check the capacity.
![step 6](instruction_images/cloudant_6.png)
5. And hit "Create" on the right panel.
![step 7](instruction_images/cloudant_7.png)
6. When all of the above steps have been done, Open "Resource list" on the left pane. you can see the Cloudant instance in the "Service and software". Click it.
![step 8](instruction_images/cloudant_8.png)
7. In resource details, there's information to connect from obsidian-livesync.
Copy the "External Endpoint(preferred)" address. <sup>(\*1)</sup>
![step 9](instruction_images/cloudant_9.png)
### CouchDB setup
1. Hit the "Launch Dashboard" button, Cloudant dashboard will be shown.
Yes, it's almost CouchDB's fauxton.
![step 1](instruction_images/couchdb_1.png)
1. First, you have to enable the CORS option.
Hit the Account menu and open the "CORS" tab.
Initially, "Origin Domains" is set to "Restrict to specific domains"., so set to "All domains(\*)"
_NOTE: of course We want to set "app://obsidian.md" but it's not acceptable on Cloudant._
![step 2](instruction_images/couchdb_2.png)
1. And open the "Databases" tab and hit the "Create Database" button.
Enter the name as you like <sup>(\*2)</sup> and Hit the "Create" button below.
![step 3](instruction_images/couchdb_3.png)
1. If the database was shown with joyful messages, then you can close this browser tab now.
![step 4](instruction_images/couchdb_4.png)
### Credentials Setup
1. Back into IBM Cloud, Open the "Service credentials". You'll get an empty list, hit the "New credential" button.
![step 1](instruction_images/credentials_1.png)
1. The dialog to create a credential will be shown.
type any name or leave it default, hit the "Add" button.
![step 2](instruction_images/credentials_2.png)
_NOTE: This "name" is not related to your username that uses in Obsidian-livesync._
1. Back to "Service credentials", the new credential should be created.
open details.
![step 3](instruction_images/credentials_3.png)
The username and password pair is inside this JSON.
"username" and "password" are so.
follow the figure, it's
"apikey-v2-2unu15184f7o8emr90xlqgkm2ncwhbltml6tgnjl9sd5"<sup>(\*3)</sup> and "c2c11651d75497fa3d3c486e4c8bdf27"<sup>(\*4)</sup>
### obsidian-livesync setting
![xx](instruction_images/obsidian_sync_1.png)
example values.
| Items | Value | example |
| ------------------- | ----------- | --------------------------------------------------------------------------- |
| CouchDB Remote URI: | (\*1)/(\*2) | https://xxxxxxxxxxxxxxxxx-bluemix.cloudantnosqldb.appdomain.cloud/sync-test |
| CouchDB Username | (\*3) | apikey-v2-2unu15184f7o8emr90xlqgkm2ncwhbltml6tgnjl9sd5 |
| CouchDB Password | (\*4) | c2c11651d75497fa3d3c486e4c8bdf27 |
Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

+216 -74
View File
@@ -2319,6 +2319,27 @@ const escapeStringToHTML = (str) => {
return escape[match]; return escape[match];
}); });
}; };
const isValidRemoteCouchDBURI = (uri) => {
if (uri.startsWith("https://"))
return true;
if (uri.startsWith("http://"))
return true;
return false;
};
const connectRemoteCouchDB = (uri, auth) => __awaiter(void 0, void 0, void 0, function* () {
if (!isValidRemoteCouchDBURI(uri))
;
let db = new o(uri, {
auth,
});
try {
let info = yield db.info();
return { db: db, info: info };
}
catch (ex) {
return;
}
});
//<--Functions //<--Functions
class ObsidianLiveSyncPlugin extends obsidian.Plugin { class ObsidianLiveSyncPlugin extends obsidian.Plugin {
constructor() { constructor() {
@@ -2327,15 +2348,22 @@ class ObsidianLiveSyncPlugin extends obsidian.Plugin {
//---> Sync //---> Sync
this.syncHandler = null; this.syncHandler = null;
} }
addLog(message) { addLog(message, isNotify) {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
let timestamp = new Date().toLocaleString(); let timestamp = new Date().toLocaleString();
let newmessage = timestamp + "->" + (typeof message == "string" ? message : JSON.stringify(message, null, 2)); let messagecontent = typeof message == "string" ? message : JSON.stringify(message, null, 2);
let newmessage = timestamp + "->" + messagecontent;
this.logMessage = [].concat(this.logMessage).concat([newmessage]).slice(-100); this.logMessage = [].concat(this.logMessage).concat([newmessage]).slice(-100);
// this.logMessage = [...this.logMessage, timestamp + ":" + newmessage].slice(-100); // this.logMessage = [...this.logMessage, timestamp + ":" + newmessage].slice(-100);
console.log(newmessage); console.log(newmessage);
if (this.statusBar2 != null) { if (this.statusBar2 != null) {
this.statusBar2.setText(newmessage); this.statusBar2.setText(newmessage.substring(0, 60));
}
if (this.onLogChanged != null) {
this.onLogChanged();
}
if (isNotify) {
new obsidian.Notice(messagecontent);
} }
}); });
} }
@@ -2350,8 +2378,12 @@ class ObsidianLiveSyncPlugin extends obsidian.Plugin {
yield this.app.vault.createFolder(c); yield this.app.vault.createFolder(c);
} }
catch (ex) { catch (ex) {
this.addLog("ensure excep"); // basically skip exceptions.
this.addLog(ex); if (ex.message && ex.message == "Folder already exists.") ;
else {
this.addLog("Folder Create Error");
this.addLog(ex);
}
} }
c += "/"; c += "/";
} }
@@ -2368,19 +2400,31 @@ class ObsidianLiveSyncPlugin extends obsidian.Plugin {
} }
}); });
} }
deleteVaultItem(file) {
return __awaiter(this, void 0, void 0, function* () {
let dir = file.parent;
yield this.app.vault.delete(file);
this.addLog(`deleted:${file.path}`);
this.addLog(`other items:${dir.children.length}`);
if (dir.children.length == 0) {
this.addLog(`all files deleted by replication, so delete dir`);
yield this.deleteVaultItem(dir);
}
});
}
doc2storate_modify(doc, file, force) { doc2storate_modify(doc, file, force) {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
if (doc._deleted) { if (doc._deleted) {
//basically pass. //basically pass.
//but if there're no docs left, delete file. //but if there're no docs left, delete file.
try { try {
let lastDocs = this.localDatabase.get(doc._id); let lastDocs = yield this.localDatabase.get(doc._id);
this.addLog(`delete skipped:${doc._id}`); this.addLog(`delete skipped:${lastDocs._id}`);
} }
catch (ex) { catch (ex) {
if (ex.status || ex.status == 404) { if (ex.status || ex.status == 404) {
//no op. //no op.
yield this.app.vault.delete(file); yield this.deleteVaultItem(file);
} }
} }
return; return;
@@ -2421,18 +2465,15 @@ class ObsidianLiveSyncPlugin extends obsidian.Plugin {
if (this.syncHandler != null) { if (this.syncHandler != null) {
return false; return false;
} }
let db = new o(this.settings.couchDB_URI, { let dbret = yield connectRemoteCouchDB(this.settings.couchDB_URI, {
auth: { username: this.settings.couchDB_USER,
username: this.settings.couchDB_USER, password: this.settings.couchDB_PASSWORD,
password: this.settings.couchDB_PASSWORD,
},
}); });
try { if (dbret === false) {
let info = yield db.info(); this.addLog(`could not connect to ${this.settings.couchDB_URI}`, true);
}
catch (ex) {
return; return;
} }
let db = dbret.db;
this.syncHandler = this.localDatabase.sync(db, { live: true, retry: true }); this.syncHandler = this.localDatabase.sync(db, { live: true, retry: true });
this.syncHandler this.syncHandler
.on("change", (e) => __awaiter(this, void 0, void 0, function* () { .on("change", (e) => __awaiter(this, void 0, void 0, function* () {
@@ -2440,20 +2481,22 @@ class ObsidianLiveSyncPlugin extends obsidian.Plugin {
for (var change of docs) { for (var change of docs) {
yield this.pouchdbChanged(change); yield this.pouchdbChanged(change);
} }
this.addLog(`replicated ${docs.length} doc(s)`);
localStorage.setItem("last-sync-no", e.change.last_seq + ""); localStorage.setItem("last-sync-no", e.change.last_seq + "");
// new Notice(`changed:${JSON.stringify(e)}`); // new Notice(`changed:${JSON.stringify(e)}`);
})) }))
.on("active", () => { .on("active", () => {
// new Notice(`Replication activated`); // new Notice(`Replication activated`);
this.addLog("Replication activated");
}) })
.on("complete", (e) => { .on("complete", (e) => {
new obsidian.Notice(`Replication completed`); this.addLog("Replication completed", true);
}) })
.on("denied", (e) => { .on("denied", (e) => {
new obsidian.Notice(`Replication denied`); this.addLog("Replication denied", true);
}) })
.on("error", (e) => { .on("error", (e) => {
new obsidian.Notice(`Replication error`); this.addLog("Replication error", true);
}) })
.on("paused", (e) => { .on("paused", (e) => {
// new Notice(`Replication paused`); // new Notice(`Replication paused`);
@@ -2500,7 +2543,6 @@ class ObsidianLiveSyncPlugin extends obsidian.Plugin {
} }
initializeDatabase() { initializeDatabase() {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
// debugger;
let vaultName = this.app.vault.getName(); let vaultName = this.app.vault.getName();
this.localDatabase = new o(vaultName + "-livesync", { this.localDatabase = new o(vaultName + "-livesync", {
auto_compaction: true, auto_compaction: true,
@@ -2513,14 +2555,17 @@ class ObsidianLiveSyncPlugin extends obsidian.Plugin {
//<-- Sync //<-- Sync
replicate() { replicate() {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
let db = new o(this.settings.couchDB_URI, { let dbret = yield connectRemoteCouchDB(this.settings.couchDB_URI, {
auth: { username: this.settings.couchDB_USER,
username: this.settings.couchDB_USER, password: this.settings.couchDB_PASSWORD,
password: this.settings.couchDB_PASSWORD,
},
}); });
if (dbret === false) {
this.addLog("could not connect to database");
return;
}
try { try {
var info = yield db.info(); let db = dbret.db;
var info = dbret.info;
new obsidian.Notice(`Connected to ${info.db_name}`); new obsidian.Notice(`Connected to ${info.db_name}`);
this.localDatabase this.localDatabase
.sync(db, { .sync(db, {
@@ -2528,7 +2573,6 @@ class ObsidianLiveSyncPlugin extends obsidian.Plugin {
// since: "0", // since: "0",
}) })
.on("change", (e) => __awaiter(this, void 0, void 0, function* () { .on("change", (e) => __awaiter(this, void 0, void 0, function* () {
// debugger;
let docs = e.change.docs; let docs = e.change.docs;
for (var change of docs) { for (var change of docs) {
this.addLog("replication change arrived"); this.addLog("replication change arrived");
@@ -2536,8 +2580,6 @@ class ObsidianLiveSyncPlugin extends obsidian.Plugin {
yield this.pouchdbChanged(change); yield this.pouchdbChanged(change);
} }
localStorage.setItem("last-sync-no", e.change.last_seq + ""); localStorage.setItem("last-sync-no", e.change.last_seq + "");
// this.addLog(e.change.last_seq);
// new Notice(`changed:${JSON.stringify(e)}`);
})) }))
.on("active", () => { .on("active", () => {
new obsidian.Notice(`Replication activated`); new obsidian.Notice(`Replication activated`);
@@ -2564,27 +2606,36 @@ class ObsidianLiveSyncPlugin extends obsidian.Plugin {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
this.addLog("loading plugin"); this.addLog("loading plugin");
yield this.loadSettings(); yield this.loadSettings();
this.addRibbonIcon("dice", "Replicate", () => __awaiter(this, void 0, void 0, function* () { obsidian.addIcon("replicate", `<g transform="matrix(1.15 0 0 1.15 -8.31 -9.52)" fill="currentColor" fill-rule="evenodd">
<path d="m85 22.2c-0.799-4.74-4.99-8.37-9.88-8.37-0.499 0-1.1 0.101-1.6 0.101-2.4-3.03-6.09-4.94-10.3-4.94-6.09 0-11.2 4.14-12.8 9.79-5.59 1.11-9.78 6.05-9.78 12 0 6.76 5.39 12.2 12 12.2h29.9c5.79 0 10.1-4.74 10.1-10.6 0-4.84-3.29-8.88-7.68-10.2zm-2.99 14.7h-29.5c-2.3-0.202-4.29-1.51-5.29-3.53-0.899-2.12-0.699-4.54 0.698-6.46 1.2-1.61 2.99-2.52 4.89-2.52 0.299 0 0.698 0 0.998 0.101l1.8 0.303v-2.02c0-3.63 2.4-6.76 5.89-7.57 0.599-0.101 1.2-0.202 1.8-0.202 2.89 0 5.49 1.62 6.79 4.24l0.598 1.21 1.3-0.504c0.599-0.202 1.3-0.303 2-0.303 1.3 0 2.5 0.404 3.59 1.11 1.6 1.21 2.6 3.13 2.6 5.15v1.61h2c2.6 0 4.69 2.12 4.69 4.74-0.099 2.52-2.2 4.64-4.79 4.64z"/>
<path d="m53.2 49.2h-41.6c-1.8 0-3.2 1.4-3.2 3.2v28.6c0 1.8 1.4 3.2 3.2 3.2h15.8v4h-7v6h24v-6h-7v-4h15.8c1.8 0 3.2-1.4 3.2-3.2v-28.6c0-1.8-1.4-3.2-3.2-3.2zm-2.8 29h-36v-23h36z"/>
<path d="m73 49.2c1.02 1.29 1.53 2.97 1.53 4.56 0 2.97-1.74 5.65-4.39 7.04v-4.06l-7.46 7.33 7.46 7.14v-4.06c7.66-1.98 12.2-9.61 10-17-0.102-0.297-0.205-0.595-0.307-0.892z"/>
<path d="m24.1 43c-0.817-0.991-1.53-2.97-1.53-4.56 0-2.97 1.74-5.65 4.39-7.04v4.06l7.46-7.33-7.46-7.14v4.06c-7.66 1.98-12.2 9.61-10 17 0.102 0.297 0.205 0.595 0.307 0.892z"/>
</g>`);
obsidian.addIcon("view-log", `<g transform="matrix(1.28 0 0 1.28 -131 -411)" fill="currentColor" fill-rule="evenodd">
<path d="m103 330h76v12h-76z"/>
<path d="m106 346v44h70v-44zm45 16h-20v-8h20z"/>
</g>`);
this.addRibbonIcon("replicate", "Replicate", () => __awaiter(this, void 0, void 0, function* () {
yield this.replicate(); yield this.replicate();
})); }));
this.addRibbonIcon("dice", "pull file force", () => __awaiter(this, void 0, void 0, function* () { // this.addRibbonIcon("dice", "pull file force", async () => {
this.localDatabase // this.localDatabase
.changes({ // .changes({
since: 0, // since: 0,
include_docs: true, // include_docs: true,
}) // })
.on("change", (change) => __awaiter(this, void 0, void 0, function* () { // .on("change", async (change) => {
yield this.pouchdbChanged(change.doc); // await this.pouchdbChanged(change.doc);
localStorage.setItem("last-sync-no", change.seq + ""); // localStorage.setItem("last-sync-no", change.seq + "");
// received a change // // received a change
})) // })
.on("error", function (err) { // .on("error", function (err) {
// handle errors // // handle errors
}); // });
})); // });
this.addRibbonIcon("dice", "Toggle Sync", () => { this.addRibbonIcon("view-log", "Show log", () => {
this.toggleSync(); new LogDisplayModal(this.app, this).open();
// Vault.recurseChildren();
}); });
this.statusBar = this.addStatusBarItem(); this.statusBar = this.addStatusBarItem();
this.statusBar2 = this.addStatusBarItem(); this.statusBar2 = this.addStatusBarItem();
@@ -2639,17 +2690,66 @@ class ObsidianLiveSyncPlugin extends obsidian.Plugin {
this.registerEvent(this.app.workspace.on("file-open", this.watchWorkspaceOpen)); this.registerEvent(this.app.workspace.on("file-open", this.watchWorkspaceOpen));
} }
watchWorkspaceOpen(file) { watchWorkspaceOpen(file) {
if (file == null)
return;
this.showIfConflicted(file); this.showIfConflicted(file);
} }
watchVaultChange(file, ...args) { watchVaultChange(file, ...args) {
this.updateDB(file); this.updateDB(file);
} }
watchVaultDelete(file) { watchVaultDelete(file) {
this.deleteDB(file); // debugger;
if (file.children) {
//folder
this.deleteFolderOnDB(file);
// this.app.vault.delete(file);
}
else {
this.deleteDB(file);
}
}
deleteFolderOnDB(folder) {
return __awaiter(this, void 0, void 0, function* () {
this.addLog(`delete folder:${folder.path}`);
for (var v of folder.children) {
let entry = v;
this.addLog(`->entry:${entry.path}`);
if (entry.children) {
this.addLog(`->is dir`);
yield this.deleteFolderOnDB(entry);
yield this.app.vault.delete(entry);
}
else {
this.addLog(`->is file`);
yield this.deleteDB(entry);
}
}
yield this.app.vault.delete(folder);
});
} }
watchVaultRename(file, oldFile) { watchVaultRename(file, oldFile) {
this.updateDB(file); if (file.children) {
this.deleteDBbyPath(oldFile); // this.renameFolder(file,oldFile);
this.addLog(`folder name changed:(this operation is not supported) ${file.path}`);
}
else {
this.updateDB(file);
this.deleteDBbyPath(oldFile);
}
}
renameFolder(folder, oldFile) {
return __awaiter(this, void 0, void 0, function* () {
for (var v of folder.children) {
let entry = v;
if (entry.children) {
yield this.deleteFolderOnDB(entry);
this.app.vault.delete(entry);
}
else {
yield this.deleteDB(entry);
}
}
});
} }
// --> conflict resolving // --> conflict resolving
getConflictedDoc(path, rev) { getConflictedDoc(path, rev) {
@@ -2673,7 +2773,21 @@ class ObsidianLiveSyncPlugin extends obsidian.Plugin {
} }
getConflictedStatus(path) { getConflictedStatus(path) {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
let test = yield this.localDatabase.get(path, { conflicts: true }); let test = null;
try {
test = yield this.localDatabase.get(path, { conflicts: true });
}
catch (ex) {
if (ex.status && ex.status == 404) {
this.addLog(`Getting conflicted status, but there was not ${path}`);
// NO OP.
}
else {
throw ex;
}
}
if (test == null)
return false;
if (!test._conflicts) if (!test._conflicts)
return false; return false;
if (test._conflicts.length == 0) if (test._conflicts.length == 0)
@@ -2756,7 +2870,10 @@ class ObsidianLiveSyncPlugin extends obsidian.Plugin {
let doc = yield this.localDatabase.get(filename); let doc = yield this.localDatabase.get(filename);
yield this.doc2storate_modify(doc, file, force); yield this.doc2storate_modify(doc, file, force);
} }
else ; else {
this.addLog(`target files:${filename} is two or more files in your vault`);
//something went wrong..
}
//when to opened file; //when to opened file;
}); });
} }
@@ -2790,8 +2907,8 @@ class ObsidianLiveSyncPlugin extends obsidian.Plugin {
}; };
try { try {
let old = yield this.localDatabase.get(fullpath); let old = yield this.localDatabase.get(fullpath);
let oldData = { data: old.data }; let oldData = { data: old.data, deleted: old._deleted };
let newData = { data: d.data }; let newData = { data: d.data, deleted: d._deleted };
if (JSON.stringify(oldData) == JSON.stringify(newData)) { if (JSON.stringify(oldData) == JSON.stringify(newData)) {
this.addLog("no changed" + fullpath); this.addLog("no changed" + fullpath);
return; return;
@@ -2805,7 +2922,7 @@ class ObsidianLiveSyncPlugin extends obsidian.Plugin {
} }
} }
let ret = yield this.localDatabase.put(d); let ret = yield this.localDatabase.put(d);
this.addLog("put database " + fullpath); this.addLog("put database:" + fullpath);
this.addLog(ret); this.addLog(ret);
if (this.settings.syncOnSave) { if (this.settings.syncOnSave) {
yield this.replicate(); yield this.replicate();
@@ -2862,6 +2979,36 @@ class ObsidianLiveSyncPlugin extends obsidian.Plugin {
}); });
} }
} }
class LogDisplayModal extends obsidian.Modal {
constructor(app, plugin) {
super(app);
this.plugin = plugin;
}
updateLog() {
let logs = [...this.plugin.logMessage];
let msg = "";
for (var v of logs) {
msg += escapeStringToHTML(v) + "<br>";
}
this.logEl.innerHTML = msg;
}
onOpen() {
let { contentEl } = this;
contentEl.empty();
contentEl.createEl("h2", { text: "Sync Status" });
let div = contentEl.createDiv("");
div.addClass("op-scrollable");
div.addClass("op-pre");
this.logEl = div;
this.plugin.onLogChanged = this.updateLog;
this.updateLog();
}
onClose() {
let { contentEl } = this;
contentEl.empty();
this.plugin.onLogChanged = null;
}
}
class ConflictResolveModal extends obsidian.Modal { class ConflictResolveModal extends obsidian.Modal {
constructor(app, diff, callback) { constructor(app, diff, callback) {
super(app); super(app);
@@ -2927,29 +3074,24 @@ class ObsidianLiveSyncSettingTab extends obsidian.PluginSettingTab {
} }
test() { test() {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
let db = new o(this.plugin.settings.couchDB_URI, { let db = yield connectRemoteCouchDB(this.plugin.settings.couchDB_URI, {
auth: { username: this.plugin.settings.couchDB_USER,
username: this.plugin.settings.couchDB_USER, password: this.plugin.settings.couchDB_PASSWORD,
password: this.plugin.settings.couchDB_PASSWORD,
},
}); });
try { if (db === false) {
var info = yield db.info(); this.plugin.addLog(`could not connect to ${this.plugin.settings.couchDB_URI}`);
new obsidian.Notice(`Connected to ${info.db_name}`); new obsidian.Notice(`could not connect to ${this.plugin.settings.couchDB_URI}`);
} return;
catch (ex) {
new obsidian.Notice("Could not connect to db:" + ex);
} }
new obsidian.Notice(`Connected to ${db.info.db_name}`);
this.plugin.addLog(`Connected to ${db.info.db_name}`);
}); });
} }
display() { display() {
let { containerEl } = this; let { containerEl } = this;
containerEl.empty(); containerEl.empty();
containerEl.createEl("h2", { text: "Settings for obsidian-livesync." }); containerEl.createEl("h2", { text: "Settings for obsidian-livesync." });
new obsidian.Setting(containerEl) new obsidian.Setting(containerEl).setName("CouchDB Remote URI").addText((text) => text
.setName("CouchDB Remote URI")
.setDesc("It's a secret")
.addText((text) => text
.setPlaceholder("https://........") .setPlaceholder("https://........")
.setValue(this.plugin.settings.couchDB_URI) .setValue(this.plugin.settings.couchDB_URI)
.onChange((value) => __awaiter(this, void 0, void 0, function* () { .onChange((value) => __awaiter(this, void 0, void 0, function* () {
@@ -3007,7 +3149,7 @@ class ObsidianLiveSyncSettingTab extends obsidian.PluginSettingTab {
yield this.plugin.saveSettings(); yield this.plugin.saveSettings();
}))); })));
new obsidian.Setting(containerEl) new obsidian.Setting(containerEl)
.setName("Database Operations") .setName("Local Database Operations")
.addButton((button) => button .addButton((button) => button
.setButtonText("Reset local database") .setButtonText("Reset local database")
.setDisabled(false) .setDisabled(false)
@@ -3025,4 +3167,4 @@ class ObsidianLiveSyncSettingTab extends obsidian.PluginSettingTab {
} }
module.exports = ObsidianLiveSyncPlugin; module.exports = ObsidianLiveSyncPlugin;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFpbi5qcyIsInNvdXJjZXMiOlsibm9kZV9tb2R1bGVzL3RzbGliL3RzbGliLmVzNi5qcyIsInBvdWNoZGItYnJvd3Nlci13ZWJwYWNrL2Rpc3QvcG91Y2hkYi1icm93c2VyLmpzIiwibm9kZV9tb2R1bGVzL2RpZmYtbWF0Y2gtcGF0Y2gvaW5kZXguanMiLCJtYWluLnRzIl0sInNvdXJjZXNDb250ZW50IjpudWxsLCJuYW1lcyI6WyJQbHVnaW4iLCJQb3VjaERCIiwiTm90aWNlIiwiZGVib3VuY2UiLCJkaWZmX21hdGNoX3BhdGNoIiwiTW9kYWwiLCJESUZGX0RFTEVURSIsIkRJRkZfRVFVQUwiLCJESUZGX0lOU0VSVCIsIlBsdWdpblNldHRpbmdUYWIiLCJTZXR0aW5nIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBdURBO0FBQ08sU0FBUyxTQUFTLENBQUMsT0FBTyxFQUFFLFVBQVUsRUFBRSxDQUFDLEVBQUUsU0FBUyxFQUFFO0FBQzdELElBQUksU0FBUyxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsT0FBTyxLQUFLLFlBQVksQ0FBQyxHQUFHLEtBQUssR0FBRyxJQUFJLENBQUMsQ0FBQyxVQUFVLE9BQU8sRUFBRSxFQUFFLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFO0FBQ2hILElBQUksT0FBTyxLQUFLLENBQUMsS0FBSyxDQUFDLEdBQUcsT0FBTyxDQUFDLEVBQUUsVUFBVSxPQUFPLEVBQUUsTUFBTSxFQUFFO0FBQy9ELFFBQVEsU0FBUyxTQUFTLENBQUMsS0FBSyxFQUFFLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxFQUFFLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRTtBQUNuRyxRQUFRLFNBQVMsUUFBUSxDQUFDLEtBQUssRUFBRSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxFQUFFLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRTtBQUN0RyxRQUFRLFNBQVMsSUFBSSxDQUFDLE1BQU0sRUFBRSxFQUFFLE1BQU0sQ0FBQyxJQUFJLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsR0FBRyxLQUFLLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsUUFBUSxDQUFDLENBQUMsRUFBRTtBQUN0SCxRQUFRLElBQUksQ0FBQyxDQUFDLFNBQVMsR0FBRyxTQUFTLENBQUMsS0FBSyxDQUFDLE9BQU8sRUFBRSxVQUFVLElBQUksRUFBRSxDQUFDLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztBQUM5RSxLQUFLLENBQUMsQ0FBQztBQUNQOztBQzdFQSxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsT0FBTyxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxRQUFRLEVBQUUsT0FBTyxPQUFPLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLFVBQVUsRUFBRSxPQUFPLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxRQUFRLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsVUFBVSxFQUFFLE9BQU8sQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxxQkFBcUIsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLE9BQU8sTUFBTSxDQUFDLG1CQUFtQixDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsT0FBTyxNQUFNLENBQUMsbUJBQW1CLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFLFNBQVMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLElBQUksT0FBTyxFQUFFLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLFVBQVUsRUFBRSxPQUFPLENBQUMsQ0FBQyxjQUFjLEVBQUUsQ0FBQyxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLEdBQUcsQ0FBQyxFQUFFLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxVQUFVLEVBQUUsT0FBTyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLEVBQUUsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLFVBQVUsRUFBRSxPQUFPLENBQUMsQ0FBQyxNQUFNLElBQUksU0FBUyxDQUFDLGtFQUFrRSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDLENBQUMsYUFBYSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUF Line truncated //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFpbi5qcyIsInNvdXJjZXMiOlsibm9kZV9tb2R1bGVzL3RzbGliL3RzbGliLmVzNi5qcyIsInBvdWNoZGItYnJvd3Nlci13ZWJwYWNrL2Rpc3QvcG91Y2hkYi1icm93c2VyLmpzIiwibm9kZV9tb2R1bGVzL2RpZmYtbWF0Y2gtcGF0Y2gvaW5kZXguanMiLCJtYWluLnRzIl0sInNvdXJjZXNDb250ZW50IjpudWxsLCJuYW1lcyI6WyJQb3VjaERCIiwiUGx1Z2luIiwiTm90aWNlIiwiYWRkSWNvbiIsImRlYm91bmNlIiwiZGlmZl9tYXRjaF9wYXRjaCIsIk1vZGFsIiwiRElGRl9ERUxFVEUiLCJESUZGX0VRVUFMIiwiRElGRl9JTlNFUlQiLCJQbHVnaW5TZXR0aW5nVGFiIiwiU2V0dGluZyJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7O0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQXVEQTtBQUNPLFNBQVMsU0FBUyxDQUFDLE9BQU8sRUFBRSxVQUFVLEVBQUUsQ0FBQyxFQUFFLFNBQVMsRUFBRTtBQUM3RCxJQUFJLFNBQVMsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLE9BQU8sS0FBSyxZQUFZLENBQUMsR0FBRyxLQUFLLEdBQUcsSUFBSSxDQUFDLENBQUMsVUFBVSxPQUFPLEVBQUUsRUFBRSxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRTtBQUNoSCxJQUFJLE9BQU8sS0FBSyxDQUFDLEtBQUssQ0FBQyxHQUFHLE9BQU8sQ0FBQyxFQUFFLFVBQVUsT0FBTyxFQUFFLE1BQU0sRUFBRTtBQUMvRCxRQUFRLFNBQVMsU0FBUyxDQUFDLEtBQUssRUFBRSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUMsRUFBRSxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUU7QUFDbkcsUUFBUSxTQUFTLFFBQVEsQ0FBQyxLQUFLLEVBQUUsRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUMsRUFBRSxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUU7QUFDdEcsUUFBUSxTQUFTLElBQUksQ0FBQyxNQUFNLEVBQUUsRUFBRSxNQUFNLENBQUMsSUFBSSxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEdBQUcsS0FBSyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLFFBQVEsQ0FBQyxDQUFDLEVBQUU7QUFDdEgsUUFBUSxJQUFJLENBQUMsQ0FBQyxTQUFTLEdBQUcsU0FBUyxDQUFDLEtBQUssQ0FBQyxPQUFPLEVBQUUsVUFBVSxJQUFJLEVBQUUsQ0FBQyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7QUFDOUUsS0FBSyxDQUFDLENBQUM7QUFDUDs7QUM3RUEsSUFBSSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLE9BQU8sVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxJQUFJLElBQUksQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsUUFBUSxFQUFFLE9BQU8sT0FBTyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxVQUFVLEVBQUUsT0FBTyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sUUFBUSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLFVBQVUsRUFBRSxPQUFPLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMscUJBQXFCLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxPQUFPLE1BQU0sQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLHFCQUFxQixDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLE9BQU8sTUFBTSxDQUFDLG1CQUFtQixDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxTQUFTLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxJQUFJLE9BQU8sRUFBRSxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFDLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxVQUFVLEVBQUUsT0FBTyxDQUFDLENBQUMsY0FBYyxFQUFFLENBQUMsQ0FBQyxjQUFjLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsRUFBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxHQUFHLENBQUMsRUFBRSxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsVUFBVSxFQUFFLE9BQU8sQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLGFBQWEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxVQUFVLEVBQUUsT0FBTyxDQUFDLENBQUMsTUFBTSxJQUFJLFNBQVMsQ0FBQyxrRUFBa0UsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsbUJBQW1CLENBQUMsQ0FBQyxDQUFDLGFBQWEsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUF Line truncated
+216 -84
View File
@@ -1,4 +1,4 @@
import { App, debounce, Modal, Notice, Plugin, PluginSettingTab, Setting, TFile, Vault, DataWriteOptions, View } from "obsidian"; import { App, debounce, Modal, Notice, Plugin, PluginSettingTab, Setting, TFile, addIcon, TFolder } from "obsidian";
import { PouchDB } from "./pouchdb-browser-webpack/dist/pouchdb-browser"; import { PouchDB } from "./pouchdb-browser-webpack/dist/pouchdb-browser";
import { DIFF_DELETE, DIFF_EQUAL, DIFF_INSERT, diff_match_patch } from "diff-match-patch"; import { DIFF_DELETE, DIFF_EQUAL, DIFF_INSERT, diff_match_patch } from "diff-match-patch";
@@ -104,22 +104,47 @@ const escapeStringToHTML = (str: string) => {
return escape[match]; return escape[match];
}); });
}; };
const isValidRemoteCouchDBURI = (uri: string): boolean => {
if (uri.startsWith("https://")) return true;
if (uri.startsWith("http://")) return true;
return false;
};
const connectRemoteCouchDB = async (uri: string, auth: { username: string; password: string }): Promise<false | { db: PouchDB.Database; info: any }> => {
if (!isValidRemoteCouchDBURI(uri)) false;
let db = new PouchDB(uri, {
auth,
});
try {
let info = await db.info();
return { db: db, info: info };
} catch (ex) {
return;
}
};
//<--Functions //<--Functions
export default class ObsidianLiveSyncPlugin extends Plugin { export default class ObsidianLiveSyncPlugin extends Plugin {
settings: ObsidianLiveSyncSettings; settings: ObsidianLiveSyncSettings;
localDatabase: PouchDB.Database<Notes>; localDatabase: PouchDB.Database<Notes>;
logMessage: string[] = []; logMessage: string[] = [];
onLogChanged: () => void;
async addLog(message: any) { async addLog(message: any, isNotify?: boolean) {
let timestamp = new Date().toLocaleString(); let timestamp = new Date().toLocaleString();
let newmessage = timestamp + "->" + (typeof message == "string" ? message : JSON.stringify(message, null, 2)); let messagecontent = typeof message == "string" ? message : JSON.stringify(message, null, 2);
let newmessage = timestamp + "->" + messagecontent;
this.logMessage = [].concat(this.logMessage).concat([newmessage]).slice(-100); this.logMessage = [].concat(this.logMessage).concat([newmessage]).slice(-100);
// this.logMessage = [...this.logMessage, timestamp + ":" + newmessage].slice(-100); // this.logMessage = [...this.logMessage, timestamp + ":" + newmessage].slice(-100);
console.log(newmessage); console.log(newmessage);
if (this.statusBar2 != null) { if (this.statusBar2 != null) {
this.statusBar2.setText(newmessage); this.statusBar2.setText(newmessage.substring(0, 60));
}
if (this.onLogChanged != null) {
this.onLogChanged();
}
if (isNotify) {
new Notice(messagecontent);
} }
} }
@@ -132,8 +157,13 @@ export default class ObsidianLiveSyncPlugin extends Plugin {
try { try {
await this.app.vault.createFolder(c); await this.app.vault.createFolder(c);
} catch (ex) { } catch (ex) {
this.addLog("ensure excep"); // basically skip exceptions.
this.addLog(ex); if (ex.message && ex.message == "Folder already exists.") {
// especialy this message is.
} else {
this.addLog("Folder Create Error");
this.addLog(ex);
}
} }
c += "/"; c += "/";
} }
@@ -148,17 +178,27 @@ export default class ObsidianLiveSyncPlugin extends Plugin {
await this.app.vault.trigger("create", newfile); await this.app.vault.trigger("create", newfile);
} }
} }
async deleteVaultItem(file: TFile | TFolder) {
let dir = file.parent;
await this.app.vault.delete(file);
this.addLog(`deleted:${file.path}`);
this.addLog(`other items:${dir.children.length}`);
if (dir.children.length == 0) {
this.addLog(`all files deleted by replication, so delete dir`);
await this.deleteVaultItem(dir);
}
}
async doc2storate_modify(doc: Notes, file: TFile, force?: boolean) { async doc2storate_modify(doc: Notes, file: TFile, force?: boolean) {
if (doc._deleted) { if (doc._deleted) {
//basically pass. //basically pass.
//but if there're no docs left, delete file. //but if there're no docs left, delete file.
try { try {
let lastDocs = this.localDatabase.get(doc._id); let lastDocs = await this.localDatabase.get(doc._id);
this.addLog(`delete skipped:${doc._id}`); this.addLog(`delete skipped:${lastDocs._id}`);
} catch (ex) { } catch (ex) {
if (ex.status || ex.status == 404) { if (ex.status || ex.status == 404) {
//no op. //no op.
await this.app.vault.delete(file); await this.deleteVaultItem(file);
} }
} }
return; return;
@@ -203,17 +243,17 @@ export default class ObsidianLiveSyncPlugin extends Plugin {
if (this.syncHandler != null) { if (this.syncHandler != null) {
return false; return false;
} }
let db = new PouchDB(this.settings.couchDB_URI, {
auth: { let dbret = await connectRemoteCouchDB(this.settings.couchDB_URI, {
username: this.settings.couchDB_USER, username: this.settings.couchDB_USER,
password: this.settings.couchDB_PASSWORD, password: this.settings.couchDB_PASSWORD,
},
}); });
try { if (dbret === false) {
let info = await db.info(); this.addLog(`could not connect to ${this.settings.couchDB_URI}`, true);
} catch (ex) {
return; return;
} }
let db = dbret.db;
this.syncHandler = this.localDatabase.sync(db, { live: true, retry: true }); this.syncHandler = this.localDatabase.sync(db, { live: true, retry: true });
this.syncHandler this.syncHandler
@@ -222,20 +262,22 @@ export default class ObsidianLiveSyncPlugin extends Plugin {
for (var change of docs) { for (var change of docs) {
await this.pouchdbChanged(change as Notes); await this.pouchdbChanged(change as Notes);
} }
this.addLog(`replicated ${docs.length} doc(s)`);
localStorage.setItem("last-sync-no", e.change.last_seq + ""); localStorage.setItem("last-sync-no", e.change.last_seq + "");
// new Notice(`changed:${JSON.stringify(e)}`); // new Notice(`changed:${JSON.stringify(e)}`);
}) })
.on("active", () => { .on("active", () => {
// new Notice(`Replication activated`); // new Notice(`Replication activated`);
this.addLog("Replication activated");
}) })
.on("complete", (e) => { .on("complete", (e) => {
new Notice(`Replication completed`); this.addLog("Replication completed", true);
}) })
.on("denied", (e) => { .on("denied", (e) => {
new Notice(`Replication denied`); this.addLog("Replication denied", true);
}) })
.on("error", (e) => { .on("error", (e) => {
new Notice(`Replication error`); this.addLog("Replication error", true);
}) })
.on("paused", (e) => { .on("paused", (e) => {
// new Notice(`Replication paused`); // new Notice(`Replication paused`);
@@ -274,7 +316,6 @@ export default class ObsidianLiveSyncPlugin extends Plugin {
this.statusBar.setText("Sync:" + statusStr); this.statusBar.setText("Sync:" + statusStr);
} }
async initializeDatabase() { async initializeDatabase() {
// debugger;
let vaultName = this.app.vault.getName(); let vaultName = this.app.vault.getName();
this.localDatabase = new PouchDB<Notes>(vaultName + "-livesync", { this.localDatabase = new PouchDB<Notes>(vaultName + "-livesync", {
@@ -289,14 +330,17 @@ export default class ObsidianLiveSyncPlugin extends Plugin {
statusBar2: HTMLElement; statusBar2: HTMLElement;
//<-- Sync //<-- Sync
async replicate() { async replicate() {
let db = new PouchDB(this.settings.couchDB_URI, { let dbret = await connectRemoteCouchDB(this.settings.couchDB_URI, {
auth: { username: this.settings.couchDB_USER,
username: this.settings.couchDB_USER, password: this.settings.couchDB_PASSWORD,
password: this.settings.couchDB_PASSWORD,
},
}); });
if (dbret === false) {
this.addLog("could not connect to database");
return;
}
try { try {
var info = await db.info(); let db = dbret.db;
var info = dbret.info;
new Notice(`Connected to ${info.db_name}`); new Notice(`Connected to ${info.db_name}`);
this.localDatabase this.localDatabase
.sync(db, { .sync(db, {
@@ -304,8 +348,6 @@ export default class ObsidianLiveSyncPlugin extends Plugin {
// since: "0", // since: "0",
}) })
.on("change", async (e) => { .on("change", async (e) => {
// debugger;
let docs = e.change.docs; let docs = e.change.docs;
for (var change of docs) { for (var change of docs) {
this.addLog("replication change arrived"); this.addLog("replication change arrived");
@@ -313,8 +355,6 @@ export default class ObsidianLiveSyncPlugin extends Plugin {
await this.pouchdbChanged(change as Notes); await this.pouchdbChanged(change as Notes);
} }
localStorage.setItem("last-sync-no", e.change.last_seq + ""); localStorage.setItem("last-sync-no", e.change.last_seq + "");
// this.addLog(e.change.last_seq);
// new Notice(`changed:${JSON.stringify(e)}`);
}) })
.on("active", () => { .on("active", () => {
new Notice(`Replication activated`); new Notice(`Replication activated`);
@@ -339,31 +379,47 @@ export default class ObsidianLiveSyncPlugin extends Plugin {
this.addLog("loading plugin"); this.addLog("loading plugin");
await this.loadSettings(); await this.loadSettings();
addIcon(
this.addRibbonIcon("dice", "Replicate", async () => { "replicate",
`<g transform="matrix(1.15 0 0 1.15 -8.31 -9.52)" fill="currentColor" fill-rule="evenodd">
<path d="m85 22.2c-0.799-4.74-4.99-8.37-9.88-8.37-0.499 0-1.1 0.101-1.6 0.101-2.4-3.03-6.09-4.94-10.3-4.94-6.09 0-11.2 4.14-12.8 9.79-5.59 1.11-9.78 6.05-9.78 12 0 6.76 5.39 12.2 12 12.2h29.9c5.79 0 10.1-4.74 10.1-10.6 0-4.84-3.29-8.88-7.68-10.2zm-2.99 14.7h-29.5c-2.3-0.202-4.29-1.51-5.29-3.53-0.899-2.12-0.699-4.54 0.698-6.46 1.2-1.61 2.99-2.52 4.89-2.52 0.299 0 0.698 0 0.998 0.101l1.8 0.303v-2.02c0-3.63 2.4-6.76 5.89-7.57 0.599-0.101 1.2-0.202 1.8-0.202 2.89 0 5.49 1.62 6.79 4.24l0.598 1.21 1.3-0.504c0.599-0.202 1.3-0.303 2-0.303 1.3 0 2.5 0.404 3.59 1.11 1.6 1.21 2.6 3.13 2.6 5.15v1.61h2c2.6 0 4.69 2.12 4.69 4.74-0.099 2.52-2.2 4.64-4.79 4.64z"/>
<path d="m53.2 49.2h-41.6c-1.8 0-3.2 1.4-3.2 3.2v28.6c0 1.8 1.4 3.2 3.2 3.2h15.8v4h-7v6h24v-6h-7v-4h15.8c1.8 0 3.2-1.4 3.2-3.2v-28.6c0-1.8-1.4-3.2-3.2-3.2zm-2.8 29h-36v-23h36z"/>
<path d="m73 49.2c1.02 1.29 1.53 2.97 1.53 4.56 0 2.97-1.74 5.65-4.39 7.04v-4.06l-7.46 7.33 7.46 7.14v-4.06c7.66-1.98 12.2-9.61 10-17-0.102-0.297-0.205-0.595-0.307-0.892z"/>
<path d="m24.1 43c-0.817-0.991-1.53-2.97-1.53-4.56 0-2.97 1.74-5.65 4.39-7.04v4.06l7.46-7.33-7.46-7.14v4.06c-7.66 1.98-12.2 9.61-10 17 0.102 0.297 0.205 0.595 0.307 0.892z"/>
</g>`
);
addIcon(
"view-log",
`<g transform="matrix(1.28 0 0 1.28 -131 -411)" fill="currentColor" fill-rule="evenodd">
<path d="m103 330h76v12h-76z"/>
<path d="m106 346v44h70v-44zm45 16h-20v-8h20z"/>
</g>`
);
this.addRibbonIcon("replicate", "Replicate", async () => {
await this.replicate(); await this.replicate();
}); });
this.addRibbonIcon("dice", "pull file force", async () => { // this.addRibbonIcon("dice", "pull file force", async () => {
this.localDatabase // this.localDatabase
.changes({ // .changes({
since: 0, // since: 0,
include_docs: true, // include_docs: true,
}) // })
.on("change", async (change) => { // .on("change", async (change) => {
await this.pouchdbChanged(change.doc); // await this.pouchdbChanged(change.doc);
localStorage.setItem("last-sync-no", change.seq + ""); // localStorage.setItem("last-sync-no", change.seq + "");
// received a change // // received a change
}) // })
.on("error", function (err) { // .on("error", function (err) {
// handle errors // // handle errors
}); // });
}); // });
this.addRibbonIcon("dice", "Toggle Sync", () => {
this.toggleSync(); this.addRibbonIcon("view-log", "Show log", () => {
// Vault.recurseChildren(); new LogDisplayModal(this.app, this).open();
}); });
this.statusBar = this.addStatusBarItem(); this.statusBar = this.addStatusBarItem();
this.statusBar2 = this.addStatusBarItem(); this.statusBar2 = this.addStatusBarItem();
this.watchVaultChange = debounce(this.watchVaultChange.bind(this), 200, false); this.watchVaultChange = debounce(this.watchVaultChange.bind(this), 200, false);
@@ -423,17 +479,57 @@ export default class ObsidianLiveSyncPlugin extends Plugin {
this.registerEvent(this.app.workspace.on("file-open", this.watchWorkspaceOpen)); this.registerEvent(this.app.workspace.on("file-open", this.watchWorkspaceOpen));
} }
watchWorkspaceOpen(file: TFile) { watchWorkspaceOpen(file: TFile) {
if (file == null) return;
this.showIfConflicted(file); this.showIfConflicted(file);
} }
watchVaultChange(file: TFile, ...args: any[]) { watchVaultChange(file: TFile, ...args: any[]) {
this.updateDB(file); this.updateDB(file);
} }
watchVaultDelete(file: TFile) { watchVaultDelete(file: TFile & TFolder) {
this.deleteDB(file); // debugger;
if (file.children) {
//folder
this.deleteFolderOnDB(file);
// this.app.vault.delete(file);
} else {
this.deleteDB(file);
}
} }
watchVaultRename(file: any, oldFile: any) { async deleteFolderOnDB(folder: TFolder) {
this.updateDB(file); this.addLog(`delete folder:${folder.path}`);
this.deleteDBbyPath(oldFile); for (var v of folder.children) {
let entry = v as TFile & TFolder;
this.addLog(`->entry:${entry.path}`);
if (entry.children) {
this.addLog(`->is dir`);
await this.deleteFolderOnDB(entry);
await this.app.vault.delete(entry);
} else {
this.addLog(`->is file`);
await this.deleteDB(entry);
}
}
await this.app.vault.delete(folder);
}
watchVaultRename(file: TFile & TFolder, oldFile: any) {
if (file.children) {
// this.renameFolder(file,oldFile);
this.addLog(`folder name changed:(this operation is not supported) ${file.path}`);
} else {
this.updateDB(file);
this.deleteDBbyPath(oldFile);
}
}
async renameFolder(folder: TFolder, oldFile: any) {
for (var v of folder.children) {
let entry = v as TFile & TFolder;
if (entry.children) {
await this.deleteFolderOnDB(entry);
this.app.vault.delete(entry);
} else {
await this.deleteDB(entry);
}
}
} }
// --> conflict resolving // --> conflict resolving
@@ -454,7 +550,18 @@ export default class ObsidianLiveSyncPlugin extends Plugin {
return false; return false;
} }
async getConflictedStatus(path: string): Promise<diff_check_result> { async getConflictedStatus(path: string): Promise<diff_check_result> {
let test = await this.localDatabase.get(path, { conflicts: true }); let test: Notes & PouchDB.Core.GetMeta = null;
try {
test = await this.localDatabase.get(path, { conflicts: true });
} catch (ex) {
if (ex.status && ex.status == 404) {
this.addLog(`Getting conflicted status, but there was not ${path}`);
// NO OP.
} else {
throw ex;
}
}
if (test == null) return false;
if (!test._conflicts) return false; if (!test._conflicts) return false;
if (test._conflicts.length == 0) return false; if (test._conflicts.length == 0) return false;
// should be two or more conflicts; // should be two or more conflicts;
@@ -527,6 +634,7 @@ export default class ObsidianLiveSyncPlugin extends Plugin {
let doc = await this.localDatabase.get(filename); let doc = await this.localDatabase.get(filename);
await this.doc2storate_modify(doc, file, force); await this.doc2storate_modify(doc, file, force);
} else { } else {
this.addLog(`target files:${filename} is two or more files in your vault`);
//something went wrong.. //something went wrong..
} }
//when to opened file; //when to opened file;
@@ -559,8 +667,8 @@ export default class ObsidianLiveSyncPlugin extends Plugin {
}; };
try { try {
let old = await this.localDatabase.get(fullpath); let old = await this.localDatabase.get(fullpath);
let oldData = { data: old.data }; let oldData = { data: old.data, deleted: old._deleted };
let newData = { data: d.data }; let newData = { data: d.data, deleted: d._deleted };
if (JSON.stringify(oldData) == JSON.stringify(newData)) { if (JSON.stringify(oldData) == JSON.stringify(newData)) {
this.addLog("no changed" + fullpath); this.addLog("no changed" + fullpath);
return; return;
@@ -575,7 +683,7 @@ export default class ObsidianLiveSyncPlugin extends Plugin {
} }
let ret = await this.localDatabase.put(d); let ret = await this.localDatabase.put(d);
this.addLog("put database " + fullpath); this.addLog("put database:" + fullpath);
this.addLog(ret); this.addLog(ret);
if (this.settings.syncOnSave) { if (this.settings.syncOnSave) {
await this.replicate(); await this.replicate();
@@ -623,8 +731,36 @@ export default class ObsidianLiveSyncPlugin extends Plugin {
} }
} }
class LogDisplayModal extends Modal { class LogDisplayModal extends Modal {
constructor(app: App) { plugin: ObsidianLiveSyncPlugin;
logEl: HTMLDivElement;
constructor(app: App, plugin: ObsidianLiveSyncPlugin) {
super(app); super(app);
this.plugin = plugin;
}
updateLog() {
let logs = [...this.plugin.logMessage];
let msg = "";
for (var v of logs) {
msg += escapeStringToHTML(v) + "<br>";
}
this.logEl.innerHTML = msg;
}
onOpen() {
let { contentEl } = this;
contentEl.empty();
contentEl.createEl("h2", { text: "Sync Status" });
let div = contentEl.createDiv("");
div.addClass("op-scrollable");
div.addClass("op-pre");
this.logEl = div;
this.plugin.onLogChanged = this.updateLog;
this.updateLog();
}
onClose() {
let { contentEl } = this;
contentEl.empty();
this.plugin.onLogChanged = null;
} }
} }
class ConflictResolveModal extends Modal { class ConflictResolveModal extends Modal {
@@ -700,18 +836,17 @@ class ObsidianLiveSyncSettingTab extends PluginSettingTab {
this.plugin = plugin; this.plugin = plugin;
} }
async test(): Promise<void> { async test(): Promise<void> {
let db = new PouchDB(this.plugin.settings.couchDB_URI, { let db = await connectRemoteCouchDB(this.plugin.settings.couchDB_URI, {
auth: { username: this.plugin.settings.couchDB_USER,
username: this.plugin.settings.couchDB_USER, password: this.plugin.settings.couchDB_PASSWORD,
password: this.plugin.settings.couchDB_PASSWORD,
},
}); });
try { if (db === false) {
var info = await db.info(); this.plugin.addLog(`could not connect to ${this.plugin.settings.couchDB_URI}`);
new Notice(`Connected to ${info.db_name}`); new Notice(`could not connect to ${this.plugin.settings.couchDB_URI}`);
} catch (ex) { return;
new Notice("Could not connect to db:" + ex);
} }
new Notice(`Connected to ${db.info.db_name}`);
this.plugin.addLog(`Connected to ${db.info.db_name}`);
} }
display(): void { display(): void {
let { containerEl } = this; let { containerEl } = this;
@@ -720,18 +855,15 @@ class ObsidianLiveSyncSettingTab extends PluginSettingTab {
containerEl.createEl("h2", { text: "Settings for obsidian-livesync." }); containerEl.createEl("h2", { text: "Settings for obsidian-livesync." });
new Setting(containerEl) new Setting(containerEl).setName("CouchDB Remote URI").addText((text) =>
.setName("CouchDB Remote URI") text
.setDesc("It's a secret") .setPlaceholder("https://........")
.addText((text) => .setValue(this.plugin.settings.couchDB_URI)
text .onChange(async (value) => {
.setPlaceholder("https://........") this.plugin.settings.couchDB_URI = value;
.setValue(this.plugin.settings.couchDB_URI) await this.plugin.saveSettings();
.onChange(async (value) => { })
this.plugin.settings.couchDB_URI = value; );
await this.plugin.saveSettings();
})
);
new Setting(containerEl) new Setting(containerEl)
.setName("CouchDB Username") .setName("CouchDB Username")
.setDesc("username") .setDesc("username")
@@ -794,7 +926,7 @@ class ObsidianLiveSyncSettingTab extends PluginSettingTab {
}) })
); );
new Setting(containerEl) new Setting(containerEl)
.setName("Database Operations") .setName("Local Database Operations")
.addButton((button) => .addButton((button) =>
button button
.setButtonText("Reset local database") .setButtonText("Reset local database")
+28 -31
View File
@@ -1,40 +1,37 @@
import typescript from '@rollup/plugin-typescript'; import typescript from "@rollup/plugin-typescript";
import { nodeResolve } from '@rollup/plugin-node-resolve'; import { nodeResolve } from "@rollup/plugin-node-resolve";
import commonjs from '@rollup/plugin-commonjs'; import commonjs from "@rollup/plugin-commonjs";
import nodePolyfills from 'rollup-plugin-polyfill-node'; import nodePolyfills from "rollup-plugin-polyfill-node";
const isProd = (process.env.BUILD === 'production'); const isProd = process.env.BUILD === "production";
const banner = const banner = `/*
`/*
THIS IS A GENERATED/BUNDLED FILE BY ROLLUP THIS IS A GENERATED/BUNDLED FILE BY ROLLUP
if you want to view the source visit the plugins github repository if you want to view the source visit the plugins github repository
*/ */
`; `;
export default { export default {
input: 'main.ts', input: "main.ts",
output: { output: {
dir: '.', dir: ".",
sourcemap: 'inline', sourcemap: "inline",
sourcemapExcludeSources: isProd, sourcemapExcludeSources: isProd,
format: 'cjs', format: "cjs",
exports: 'default', exports: "default",
banner, banner,
}, },
// treeshake: "safest", // treeshake: "safest",
external: ['obsidian'], external: ["obsidian"],
plugins: [ plugins: [
typescript({exclude:["pouchdb-browser.js"]}), typescript({ exclude: ["pouchdb-browser.js", "pouchdb-browser-webpack"] }),
nodePolyfills( nodeResolve({
// // {crypto:true} browser: true,
{ include: "pouchdb-browser" } }),
), commonjs(),
nodeResolve({ // nodePolyfills(
browser: true, // // // {crypto:true}
// preferBuiltins: true // { include: "pouchdb-browser" }
}), // ),
commonjs(), ],
]
}; };
+10 -12
View File
@@ -1,22 +1,20 @@
/* Sets all the text color to red! */
/* body {
color: red;
} */
.added { .added {
color:black; color: black;
background-color: white; background-color: white;
} }
.normal { .normal {
color:lightgray; color: lightgray;
} }
.deleted { .deleted {
color:white; color: white;
background-color: black; background-color: black;
/* text-decoration: line-through; */ /* text-decoration: line-through; */
} }
.op-scrollable{ .op-scrollable {
overflow-y:scroll; overflow-y: scroll;
/* min-height: 280px; */ /* min-height: 280px; */
max-height: 280px; max-height: 280px;
} }
.op-pre {
white-space: pre-wrap;
}
+2 -1
View File
@@ -12,5 +12,6 @@
"lib": ["dom", "es5", "scripthost", "es2015"] "lib": ["dom", "es5", "scripthost", "es2015"]
}, },
"include": ["**/*.ts"], "include": ["**/*.ts"],
"exclude": ["pouchdb-browser.js"] "files": ["./main.ts"],
"exclude": ["pouchdb-browser-webpack"]
} }