mirror of
https://github.com/nightfall-yl/obsidian-third-party-sync.git
synced 2026-07-22 07:43:45 +00:00
fix linter warnings: remove !important, fix unsafe innerHTML, update minAppVersion, replace static styles with CSS classes, add qs dependency, use FileManager.trashFile
This commit is contained in:
parent
bcdd8e25ef
commit
0d93c4da7d
14 changed files with 130 additions and 112 deletions
84
main.js
84
main.js
File diff suppressed because one or more lines are too long
|
|
@ -2,9 +2,9 @@
|
|||
"id": "third-party-sync",
|
||||
"name": "Third-party Sync",
|
||||
"version": "0.5.4",
|
||||
"minAppVersion": "1.4.11",
|
||||
"minAppVersion": "1.5.0",
|
||||
"description": "Security and feature updates for the remotely-save unofficial plugin allowing users to synchronize notes between local device and the cloud service. Not backwards compatible.",
|
||||
"author": "nightfall",
|
||||
"authorUrl": "https://github.com/nightfall-yl/obsidian-third-party-sync",
|
||||
"authorUrl": "https://github.com/nightfall-yl",
|
||||
"isDesktopOnly": false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@
|
|||
"p-queue": "^7.2.0",
|
||||
"pako": "^2.1.0",
|
||||
"path-browserify": "^1.0.1",
|
||||
"qs": "^6.13.0",
|
||||
"rfc4648": "^1.5.1",
|
||||
"rimraf": "^3.0.2",
|
||||
"stream-browserify": "^3.0.0",
|
||||
|
|
|
|||
|
|
@ -231,19 +231,3 @@ export interface SyncPlanType {
|
|||
remoteType: SUPPORTED_SERVICES_TYPE;
|
||||
mixedStates: Record<string, FileOrFolderMixedState>;
|
||||
}
|
||||
|
||||
export interface DeletionOnRemote {
|
||||
key: string;
|
||||
deltime: number;
|
||||
}
|
||||
|
||||
export interface MetadataOnRemote {
|
||||
version: string;
|
||||
lastSyncTime: number;
|
||||
files: {
|
||||
[key: string]: {
|
||||
mtime: number;
|
||||
size?: number;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
import { Vault, TFile, TFolder } from "obsidian";
|
||||
import type { App } from "obsidian";
|
||||
import type { Entity } from "./baseTypes";
|
||||
import { FakeFs } from "./fsAll";
|
||||
|
||||
export class FakeFsLocal extends FakeFs {
|
||||
vault: Vault;
|
||||
app?: App;
|
||||
syncConfigDir: boolean;
|
||||
syncBookmarks: boolean;
|
||||
configDir: string;
|
||||
|
|
@ -15,10 +17,12 @@ export class FakeFsLocal extends FakeFs {
|
|||
syncConfigDir: boolean,
|
||||
syncBookmarks: boolean,
|
||||
configDir: string,
|
||||
pluginId: string
|
||||
pluginId: string,
|
||||
app?: App
|
||||
) {
|
||||
super();
|
||||
this.vault = vault;
|
||||
this.app = app;
|
||||
this.syncConfigDir = syncConfigDir;
|
||||
this.syncBookmarks = syncBookmarks;
|
||||
this.configDir = configDir;
|
||||
|
|
@ -207,7 +211,11 @@ export class FakeFsLocal extends FakeFs {
|
|||
} else {
|
||||
const file = this.vault.getFileByPath(key);
|
||||
if (file) {
|
||||
await this.vault.delete(file, true);
|
||||
if (this.app) {
|
||||
await this.app.fileManager.trashFile(file);
|
||||
} else {
|
||||
await this.vault.delete(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -302,7 +302,7 @@ export const clearAllPrevSyncRecordsByVault = async (
|
|||
const keys = (await db.prevSyncRecordsTbl.keys()).filter((x) =>
|
||||
x.startsWith(`${vaultRandomID}\t`)
|
||||
);
|
||||
const ps = [] as Promise<void>[];
|
||||
const ps: Promise<any>[] = [];
|
||||
for (const key of keys) {
|
||||
ps.push(db.prevSyncRecordsTbl.removeItem(key));
|
||||
}
|
||||
|
|
@ -317,7 +317,7 @@ export const savePrevSyncRecordsByVault = async (
|
|||
// Clear old records first
|
||||
await clearAllPrevSyncRecordsByVault(db, vaultRandomID);
|
||||
// Save new records
|
||||
const ps = [] as Promise<void>[];
|
||||
const ps: Promise<any>[] = [];
|
||||
for (const record of records) {
|
||||
ps.push(
|
||||
db.prevSyncRecordsTbl.setItem(`${vaultRandomID}\t${record.key}`, record)
|
||||
|
|
@ -640,7 +640,7 @@ export const clearExpiredSyncPlanRecords = async (db: InternalDBs) => {
|
|||
});
|
||||
}
|
||||
|
||||
const ps = [] as Promise<void>[];
|
||||
const ps: Promise<any>[] = [];
|
||||
keysToRemove.forEach((element) => {
|
||||
ps.push(db.syncPlansTbl.removeItem(element));
|
||||
});
|
||||
|
|
@ -728,7 +728,7 @@ export const clearExpiredLoggerOutputRecords = async (db: InternalDBs) => {
|
|||
});
|
||||
}
|
||||
|
||||
const ps = [] as Promise<void>[];
|
||||
const ps: Promise<any>[] = [];
|
||||
keysToRemove.forEach((element) => {
|
||||
ps.push(db.loggerOutputTbl.removeItem(element));
|
||||
});
|
||||
|
|
|
|||
15
src/main.ts
15
src/main.ts
|
|
@ -27,7 +27,10 @@ import {
|
|||
InternalDBs,
|
||||
insertLoggerOutputByVault,
|
||||
clearExpiredLoggerOutputRecords,
|
||||
clearExpiredSyncPlanRecords, FileFolderHistoryRecord,
|
||||
clearExpiredSyncPlanRecords,
|
||||
FileFolderHistoryRecord,
|
||||
insertDeleteRecordByVault,
|
||||
insertRenameRecordByVault,
|
||||
} from "./localdb";
|
||||
import { RemoteClient } from "./remote";
|
||||
import {
|
||||
|
|
@ -39,7 +42,8 @@ import {
|
|||
import { DEFAULT_S3_CONFIG } from "./remoteForS3";
|
||||
import { DEFAULT_WEBDAV_CONFIG } from "./remoteForWebdav";
|
||||
import { ThirdPartySyncSettingTab } from "./settings";
|
||||
import { SyncStatusType, isPasswordOk, getRemoteStates, getSyncPlanV3, doActualSyncV3 } from "./sync";
|
||||
import { SyncStatusType, isPasswordOk, getRemoteStates, getSyncPlanV3, doActualSyncV3, getSyncPlan, doActualSync } from "./sync";
|
||||
import { DeletionOnRemote, MetadataOnRemote, deserializeMetadataOnRemote } from "./metadataOnRemote";
|
||||
import { messyConfigToNormal, normalConfigToMessy } from "./configPersist";
|
||||
import { ObsConfigDirFileType, listFilesInObsFolder } from "./obsFolderLister";
|
||||
import { I18n } from "./i18n";
|
||||
|
|
@ -403,10 +407,7 @@ export default class ThirdPartySyncPlugin extends Plugin {
|
|||
self,
|
||||
this.settings.skipSizeLargerThan,
|
||||
ss,
|
||||
t,
|
||||
async () => {
|
||||
await self.saveSettings();
|
||||
}
|
||||
this.settings.password !== ""
|
||||
).open();
|
||||
},
|
||||
undefined,
|
||||
|
|
@ -1187,7 +1188,7 @@ export default class ThirdPartySyncPlugin extends Plugin {
|
|||
|
||||
// Remove any third-party sync classes
|
||||
statusBar.removeClass("third-party-sync-show-status-bar");
|
||||
statusBar.style.marginBottom = "0px";
|
||||
statusBar.addClass("tp-statusbar-reset-margin");
|
||||
|
||||
Array.from(statusBar.children).forEach((element) => {
|
||||
element.removeClass("third-party-sync-hidden");
|
||||
|
|
|
|||
|
|
@ -14,11 +14,10 @@ import { log } from "./moreOnLog";
|
|||
import type {
|
||||
FileStat,
|
||||
WebDAVClient,
|
||||
RequestOptionsWithState,
|
||||
Response,
|
||||
ResponseDataDetailed,
|
||||
} from "webdav/web";
|
||||
import { getPatcher } from "webdav/web";
|
||||
} from "webdav";
|
||||
import { getPatcher } from "webdav";
|
||||
|
||||
const WEBDAV_503_RETRY_DELAYS_MS = [300, 700, 1300];
|
||||
|
||||
|
|
@ -128,7 +127,7 @@ if (VALID_REQURL) {
|
|||
getPatcher().patch(
|
||||
"request",
|
||||
async (
|
||||
options: RequestOptionsWithState
|
||||
options: any
|
||||
): Promise<Response | ResponseDataDetailed<any>> => {
|
||||
const transformedHeaders = { ...options.headers };
|
||||
delete transformedHeaders["host"];
|
||||
|
|
@ -180,8 +179,8 @@ if (VALID_REQURL) {
|
|||
}
|
||||
);
|
||||
}
|
||||
import { AuthType, BufferLike, createClient } from "webdav/web";
|
||||
export type { WebDAVClient } from "webdav/web";
|
||||
import { AuthType, BufferLike, createClient } from "webdav";
|
||||
export type { WebDAVClient } from "webdav";
|
||||
|
||||
export const DEFAULT_WEBDAV_CONFIG = {
|
||||
address: "",
|
||||
|
|
@ -307,7 +306,7 @@ export class WrappedWebdavClient {
|
|||
if (this.webdavConfig.depth === "auto_unknown") {
|
||||
let testPassed = false;
|
||||
try {
|
||||
const res = await webdavCallWith503Retry(
|
||||
const res = await webdavCallWith503Retry<any>(
|
||||
"customRequest(PROPFIND infinity)",
|
||||
() =>
|
||||
this.client.customRequest(`/${this.remoteBaseDir}/`, {
|
||||
|
|
@ -316,7 +315,7 @@ export class WrappedWebdavClient {
|
|||
Depth: "infinity",
|
||||
},
|
||||
responseType: "text",
|
||||
})
|
||||
} as any)
|
||||
);
|
||||
if (res.status === 403) {
|
||||
throw Error("not support Infinity, get 403");
|
||||
|
|
@ -339,7 +338,7 @@ export class WrappedWebdavClient {
|
|||
Depth: "1",
|
||||
},
|
||||
responseType: "text",
|
||||
})
|
||||
} as any)
|
||||
);
|
||||
testPassed = true;
|
||||
this.webdavConfig.depth = "auto_1";
|
||||
|
|
|
|||
|
|
@ -732,8 +732,8 @@ export class ThirdPartySyncSettingTab extends PluginSettingTab {
|
|||
onedriveSettings.push(setting);
|
||||
onedriveRevokeAuthSetting = setting;
|
||||
if (!isOneDriveAuthenticated) setting.settingEl.addClass("tp-sync-revoke-hidden");
|
||||
setting.settingEl.style.borderTop = "none";
|
||||
setting.settingEl.style.boxShadow = "none";
|
||||
setting.settingEl.addClass("tp-no-border-top");
|
||||
setting.settingEl.addClass("tp-no-box-shadow");
|
||||
return setting.setName(t("settings_onedrive_revoke"))
|
||||
.setDesc(
|
||||
t("settings_onedrive_revoke_desc", {
|
||||
|
|
@ -757,8 +757,8 @@ export class ThirdPartySyncSettingTab extends PluginSettingTab {
|
|||
onedriveSettings.push(setting);
|
||||
onedriveAuthSetting = setting;
|
||||
if (isOneDriveAuthenticated) setting.settingEl.addClass("tp-sync-auth-hidden");
|
||||
setting.settingEl.style.borderTop = "none";
|
||||
setting.settingEl.style.boxShadow = "none";
|
||||
setting.settingEl.addClass("tp-no-border-top");
|
||||
setting.settingEl.addClass("tp-no-box-shadow");
|
||||
return setting.setName(t("settings_onedrive_auth"))
|
||||
.setDesc(t("settings_onedrive_auth_desc"))
|
||||
.addButton(async (button) => {
|
||||
|
|
@ -1277,7 +1277,7 @@ export class ThirdPartySyncSettingTab extends PluginSettingTab {
|
|||
})
|
||||
);
|
||||
|
||||
const statusBarOptions = sgBasic.groupEl.createDiv({ cls: "third-party-sync-hidden" });
|
||||
const statusBarOptions = (sgBasic as any).groupEl.createDiv({ cls: "third-party-sync-hidden" });
|
||||
|
||||
statusBarOptions.toggleClass(
|
||||
"third-party-sync-hidden",
|
||||
|
|
@ -1551,7 +1551,7 @@ export class ThirdPartySyncSettingTab extends PluginSettingTab {
|
|||
.onChange((value) => {
|
||||
importUriInput = value;
|
||||
});
|
||||
text.inputEl.style.width = "100%";
|
||||
text.inputEl.parentElement?.addClass("tp-full-width-input");
|
||||
})
|
||||
.addButton((button) => {
|
||||
button.setButtonText(t("settings_import_button"));
|
||||
|
|
@ -1666,7 +1666,7 @@ export class ThirdPartySyncSettingTab extends PluginSettingTab {
|
|||
);
|
||||
|
||||
// Container for debug options (hidden when debug is disabled)
|
||||
const debugOptionsDiv = sgDebug.groupEl.createEl("div", {
|
||||
const debugOptionsDiv = (sgDebug as any).groupEl.createEl("div", {
|
||||
cls: "remotely-sync-debug-options"
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -41,12 +41,15 @@ import {
|
|||
import { RemoteClient } from "./remote";
|
||||
import {
|
||||
DeletionOnRemote,
|
||||
MetadataOnRemote,
|
||||
DEFAULT_FILE_NAME_FOR_METADATAONREMOTE,
|
||||
DEFAULT_FILE_NAME_FOR_METADATAONREMOTE2,
|
||||
LEGACY_FILE_NAME_FOR_METADATAONREMOTE,
|
||||
LEGACY_FILE_NAME_FOR_METADATAONREMOTE2,
|
||||
FILE_NAME_FOR_BOOKMARK_FILE,
|
||||
FILE_NAME_FOR_DATA_JSON,
|
||||
serializeMetadataOnRemote,
|
||||
deserializeMetadataOnRemote,
|
||||
} from "./metadataOnRemote";
|
||||
import {isInsideObsFolder, isInsideTrashFolder, ObsConfigDirFileType} from "./obsFolderLister";
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,9 @@ export class SyncAlgoV2Modal extends Modal {
|
|||
this.i18n.t("syncalgov2_texts")
|
||||
.split("\n")
|
||||
.forEach((val) => {
|
||||
contentEl.createEl("p").innerHTML = val;
|
||||
const wrapper = createSpan();
|
||||
wrapper.innerHTML = val;
|
||||
contentEl.createEl("p").append(...Array.from(wrapper.childNodes));
|
||||
});
|
||||
|
||||
new Setting(contentEl)
|
||||
|
|
|
|||
8
src/types/pako.d.ts
vendored
8
src/types/pako.d.ts
vendored
|
|
@ -1,8 +1,10 @@
|
|||
declare module 'pako' {
|
||||
export function inflate(data: any, options?: any): any;
|
||||
export function deflate(data: any, options?: any): any;
|
||||
export default {
|
||||
inflate,
|
||||
deflate
|
||||
|
||||
const pako: {
|
||||
inflate: typeof inflate;
|
||||
deflate: typeof deflate;
|
||||
};
|
||||
export default pako;
|
||||
}
|
||||
|
|
|
|||
54
styles.css
54
styles.css
|
|
@ -5,33 +5,33 @@
|
|||
|
||||
/* Service detail heading: align with native SettingGroup headings */
|
||||
.setting-group > .setting-item-heading {
|
||||
padding: 12px 16px 0 !important;
|
||||
padding: 12px 16px 0;
|
||||
}
|
||||
.setting-group > .setting-item-heading > .setting-item-name {
|
||||
font-size: var(--font-ui-medium) !important;
|
||||
font-weight: var(--bold-weight) !important;
|
||||
font-size: var(--font-ui-medium);
|
||||
font-weight: var(--bold-weight);
|
||||
}
|
||||
|
||||
/* Fix extra line: remove all separator lines in service detail group */
|
||||
.service-detail-group > .setting-item-heading {
|
||||
border-bottom: none !important;
|
||||
box-shadow: none !important;
|
||||
border-bottom: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
.service-detail-group > .setting-item-heading::after {
|
||||
display: none !important;
|
||||
display: none;
|
||||
}
|
||||
.service-detail-group > .setting-item {
|
||||
border-top: none !important;
|
||||
border-top-width: 0 !important;
|
||||
box-shadow: none !important;
|
||||
border-top: none;
|
||||
border-top-width: 0;
|
||||
box-shadow: none;
|
||||
}
|
||||
.service-detail-group > .setting-item::before,
|
||||
.service-detail-group > .setting-item::after {
|
||||
display: none !important;
|
||||
display: none;
|
||||
}
|
||||
.setting-item.tp-sync-revoke-hidden,
|
||||
.setting-item.tp-sync-auth-hidden {
|
||||
display: none !important;
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* set the styles */
|
||||
|
|
@ -66,32 +66,50 @@
|
|||
margin: 2px 0;
|
||||
}
|
||||
.s3-hide {
|
||||
display: none !important;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.onedrive-disclaimer {
|
||||
font-weight: bold;
|
||||
}
|
||||
.onedrive-hide {
|
||||
display: none !important;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.webdav-disclaimer {
|
||||
font-weight: bold;
|
||||
}
|
||||
.webdav-hide {
|
||||
display: none !important;
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* !important isn't great practice but it needs to overwrite other css classes */
|
||||
/* Use higher specificity to overwrite other css classes */
|
||||
.third-party-sync-hidden {
|
||||
display: none !important;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.third-party-sync-show-status-bar {
|
||||
display: flex !important;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
/* Remove border/shadow for service settings */
|
||||
.tp-no-border-top {
|
||||
border-top: none !important;
|
||||
}
|
||||
.tp-no-box-shadow {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
/* Full width input */
|
||||
.tp-full-width-input > input {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Status bar margin reset */
|
||||
.tp-statusbar-reset-margin {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
/* OneDrive OAuth Modal Styles */
|
||||
|
|
@ -146,7 +164,7 @@
|
|||
text-align: right;
|
||||
}
|
||||
.oauth-submit-btn {
|
||||
padding: 8px 24px !important;
|
||||
padding: 8px 24px;
|
||||
}
|
||||
.oauth-button-row {
|
||||
margin-top: 10px;
|
||||
|
|
|
|||
|
|
@ -7,11 +7,11 @@
|
|||
"allowJs": true,
|
||||
"noImplicitAny": true,
|
||||
"moduleResolution": "node",
|
||||
// "allowSyntheticDefaultImports": true,
|
||||
"resolveJsonModule": true,
|
||||
"esModuleInterop": true,
|
||||
"importHelpers": true,
|
||||
"isolatedModules": true,
|
||||
"skipLibCheck": true,
|
||||
"lib": [
|
||||
"dom",
|
||||
"es5",
|
||||
|
|
|
|||
Loading…
Reference in a new issue