From 5aaaa4dadefd8f90629120a9b7f647f552dd5f2d Mon Sep 17 00:00:00 2001 From: snipd-min Date: Wed, 13 May 2026 13:22:14 +0200 Subject: [PATCH] Some fixes --- eslint.config.mjs | 5 +++++ package-lock.json | 20 +++++++++++--------- src/formatting_modal.ts | 8 ++++---- src/main.ts | 8 ++++---- src/secure_storage.ts | 14 +++++++------- src/settings_modal.ts | 28 ++++++++++++++-------------- src/utils.ts | 2 +- 7 files changed, 46 insertions(+), 39 deletions(-) diff --git a/eslint.config.mjs b/eslint.config.mjs index 4d7017a..50209fc 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -14,6 +14,11 @@ export default defineConfig([ languageOptions: { parser: tsparser, parserOptions: { project: "./tsconfig.json" }, + globals: { + activeWindow: "readonly", + activeDocument: "readonly", + console: "readonly", + }, }, // Optional project overrides diff --git a/package-lock.json b/package-lock.json index 44b4f13..febd508 100644 --- a/package-lock.json +++ b/package-lock.json @@ -679,6 +679,7 @@ "integrity": "sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, @@ -771,7 +772,6 @@ "integrity": "sha512-KWiFQpSAqEIyrTXko3hFNLeQvSK8zXlJQzhhxsyVn58WFRYXST99b3Nqnu+ttOtjds2Pl2grUHGpe2NzhPynuQ==", "dev": true, "license": "Apache-2.0", - "peer": true, "engines": { "node": ">=18" } @@ -795,8 +795,7 @@ "resolved": "https://registry.npmjs.org/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz", "integrity": "sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@microsoft/eslint-plugin-sdl": { "version": "1.1.0", @@ -979,6 +978,7 @@ "integrity": "sha512-qwxv6dq682yVvgKKp2qWwLgRbscDAYktPptK4JPojCwwi3R9cwrvIxS4lvBpzmcqzR4bdn54Z0IG1uHFskW4dA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.33.1", "@typescript-eslint/types": "8.33.1", @@ -1220,6 +1220,7 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -1602,8 +1603,7 @@ "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz", "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/cross-spawn": { "version": "7.0.6", @@ -2021,6 +2021,7 @@ "integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -4804,8 +4805,7 @@ "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.3.tgz", "integrity": "sha512-i/n8VsZydrugj3Iuzll8+x/00GH2vnYsk1eomD8QiRrSAeW6ItbCQDtfXCeJHd0iwiNagqjQkvpvREEPtW3IoQ==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/supports-color": { "version": "7.2.0", @@ -5488,6 +5488,7 @@ "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", "dev": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -5502,6 +5503,7 @@ "integrity": "sha512-KALyxkpYV5Ix7UhvjTwJXZv76VWsHG+NjNlt/z+a17SOQSiOcBdUXdbJdyXi7RPxrBFECtFOiPwUJQusJuCqrg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@typescript-eslint/eslint-plugin": "8.46.4", "@typescript-eslint/parser": "8.46.4", @@ -5556,6 +5558,7 @@ "integrity": "sha512-tK3GPFWbirvNgsNKto+UmB/cRtn6TZfyw0D6IKrW55n6Vbs7KJoZtI//kpTKzE/DUmmnAFD8/Ca46s7Obs92/w==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.46.4", "@typescript-eslint/types": "8.46.4", @@ -5796,8 +5799,7 @@ "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/which": { "version": "2.0.2", diff --git a/src/formatting_modal.ts b/src/formatting_modal.ts index a353626..bb0317d 100644 --- a/src/formatting_modal.ts +++ b/src/formatting_modal.ts @@ -87,7 +87,7 @@ export class FormattingConfigModal extends Modal { varSpan.addEventListener('click', () => { void (async () => { try { - await globalThis.navigator.clipboard.writeText(varName); + await activeWindow.navigator.clipboard.writeText(varName); new Notice(`Copied ${varName} to clipboard`); } catch { new Notice(`Failed to copy ${varName} to clipboard`); @@ -133,7 +133,7 @@ export class FormattingConfigModal extends Modal { varSpan.addEventListener('click', () => { void (async () => { try { - await globalThis.navigator.clipboard.writeText(varName); + await activeWindow.navigator.clipboard.writeText(varName); new Notice(`Copied ${varName} to clipboard`); } catch { new Notice(`Failed to copy ${varName} to clipboard`); @@ -179,7 +179,7 @@ export class FormattingConfigModal extends Modal { varSpan.addEventListener('click', () => { void (async () => { try { - await globalThis.navigator.clipboard.writeText(varName); + await activeWindow.navigator.clipboard.writeText(varName); new Notice(`Copied ${varName} to clipboard`); } catch { new Notice(`Failed to copy ${varName} to clipboard`); @@ -213,7 +213,7 @@ export class FormattingConfigModal extends Modal { varSpan.addEventListener('click', () => { void (async () => { try { - await globalThis.navigator.clipboard.writeText(varName); + await activeWindow.navigator.clipboard.writeText(varName); new Notice(`Copied ${varName} to clipboard`); } catch { new Notice(`Failed to copy ${varName} to clipboard`); diff --git a/src/main.ts b/src/main.ts index e7c7c69..6ae7205 100644 --- a/src/main.ts +++ b/src/main.ts @@ -184,7 +184,7 @@ export default class SnipdPlugin extends Plugin { private clearStatusBarPersistentMessageAfterDelay(delayMs: number): void { this.registerInterval( - globalThis.window.setTimeout(() => { + activeWindow.setTimeout(() => { this.clearStatusBarPersistentMessage(); }, delayMs) ); @@ -1239,13 +1239,13 @@ export default class SnipdPlugin extends Plugin { const milliseconds = minutes * 60 * 1000; debugLog('Snipd plugin: setting interval to ', milliseconds, 'milliseconds'); if (this.scheduleInterval !== null) { - globalThis.window.clearInterval(this.scheduleInterval); + activeWindow.clearInterval(this.scheduleInterval); this.scheduleInterval = null; } if (!milliseconds) { return; } - this.scheduleInterval = globalThis.window.setInterval(() => { + this.scheduleInterval = activeWindow.setInterval(() => { void this.syncSnipd(); }, milliseconds); this.registerInterval(this.scheduleInterval); @@ -1304,7 +1304,7 @@ export default class SnipdPlugin extends Plugin { if (!this.app.isMobile) { this.statusBar = new StatusBar(this.addStatusBarItem()); this.registerInterval( - globalThis.window.setInterval(() => { + activeWindow.setInterval(() => { this.statusBar.display(); }, 1000) ); diff --git a/src/secure_storage.ts b/src/secure_storage.ts index ffaec5c..9615564 100644 --- a/src/secure_storage.ts +++ b/src/secure_storage.ts @@ -5,7 +5,7 @@ export class SecureStorage { private static async deriveKey(vaultPath: string): Promise { const encoder = new TextEncoder(); - const keyMaterial = await globalThis.crypto.subtle.importKey( + const keyMaterial = await activeWindow.crypto.subtle.importKey( 'raw', encoder.encode(vaultPath + this.SERVICE_NAME), 'PBKDF2', @@ -15,7 +15,7 @@ export class SecureStorage { const salt = encoder.encode('snipd-secure-storage-salt-v1'); - return globalThis.crypto.subtle.deriveKey( + return activeWindow.crypto.subtle.deriveKey( { name: 'PBKDF2', salt: salt, @@ -39,9 +39,9 @@ export class SecureStorage { const encoder = new TextEncoder(); const data = encoder.encode(apiKey); - const iv = globalThis.crypto.getRandomValues(new Uint8Array(12)); + const iv = activeWindow.crypto.getRandomValues(new Uint8Array(12)); - const encryptedData = await globalThis.crypto.subtle.encrypt( + const encryptedData = await activeWindow.crypto.subtle.encrypt( { name: this.ALGORITHM, iv: iv @@ -55,7 +55,7 @@ export class SecureStorage { combined.set(iv); combined.set(encryptedArray, iv.length); - return globalThis.btoa(String.fromCharCode(...combined)); + return activeWindow.btoa(String.fromCharCode(...combined)); } catch { throw new Error('Failed to encrypt API key'); } @@ -69,12 +69,12 @@ export class SecureStorage { try { const key = await this.deriveKey(vaultPath); - const combined = Uint8Array.from(globalThis.atob(encryptedApiKey), c => c.charCodeAt(0)); + const combined = Uint8Array.from(activeWindow.atob(encryptedApiKey), c => c.charCodeAt(0)); const iv = combined.slice(0, 12); const encryptedData = combined.slice(12); - const decryptedData = await globalThis.crypto.subtle.decrypt( + const decryptedData = await activeWindow.crypto.subtle.decrypt( { name: this.ALGORITHM, iv: iv diff --git a/src/settings_modal.ts b/src/settings_modal.ts index 4c25a11..a5b2718 100644 --- a/src/settings_modal.ts +++ b/src/settings_modal.ts @@ -16,7 +16,7 @@ export class SnipdSettingModal extends PluginSettingTab { hide() { if (this.refreshInterval !== null) { - globalThis.window.clearInterval(this.refreshInterval); + activeWindow.clearInterval(this.refreshInterval); this.refreshInterval = null; } this.plugin.settingsTab = null; @@ -32,7 +32,7 @@ export class SnipdSettingModal extends PluginSettingTab { // Cannot use electron API in Obsidian openExternal(url: string) { - globalThis.window.open(url); + activeWindow.open(url); } async connectToSnipd(button: HTMLElement, container: HTMLElement, uuid?: string): Promise { @@ -105,7 +105,7 @@ export class SnipdSettingModal extends PluginSettingTab { if (!this.plugin.settings.apiKey) { const authSection = containerEl.createDiv({ cls: 'snipd-auth-section' }); - authSection.createEl('div', { text: 'Connect Obsidian to Snipd', cls: 'snipd-auth-heading' }); + authSection.createDiv({ text: 'Connect Obsidian to Snipd', cls: 'snipd-auth-heading' }); const subtitleRow = authSection.createDiv({ cls: 'snipd-auth-subtitle-row' }); @@ -129,7 +129,7 @@ export class SnipdSettingModal extends PluginSettingTab { const syncStatusContainer = containerEl.createDiv({ cls: 'snipd-sync-status' }); const syncStatusHeader = syncStatusContainer.createDiv({ cls: 'snipd-sync-status-header' }); - syncStatusHeader.createEl('div', { text: 'Sync status', cls: 'snipd-sync-status-title' }); + syncStatusHeader.createDiv({ text: 'Sync status', cls: 'snipd-sync-status-title' }); if (this.plugin.settings.isSyncing) { const stopButton = syncStatusHeader.createEl('button', { @@ -162,24 +162,24 @@ export class SnipdSettingModal extends PluginSettingTab { const episodeCount = this.plugin.settings.current_batch_episode_count; const snipCount = this.plugin.settings.current_batch_snip_count; - syncStatusBody.createEl('div', { + syncStatusBody.createDiv({ text: `Syncing: Batch ${displayBatch} of ${totalBatches} (${remainingBatches} remaining)`, cls: 'snipd-sync-status-text' }); if (episodeCount > 0 || snipCount > 0) { - syncStatusBody.createEl('div', { + syncStatusBody.createDiv({ text: `Current batch: ${episodeCount} episode${episodeCount !== 1 ? 's' : ''}, ${snipCount} snip${snipCount !== 1 ? 's' : ''}`, cls: 'snipd-sync-status-text' }); } - syncStatusBody.createEl('div', { + syncStatusBody.createDiv({ text: `Progress: ${progressPercent}%`, cls: 'snipd-sync-status-text' }); } else { - syncStatusBody.createEl('div', { + syncStatusBody.createDiv({ text: 'Preparing sync...', cls: 'snipd-sync-status-text' }); @@ -188,19 +188,19 @@ export class SnipdSettingModal extends PluginSettingTab { const lastSyncDate = new Date(this.plugin.settings.lastSyncTimestamp); const formattedDate = lastSyncDate.toLocaleString(); - syncStatusBody.createEl('div', { + syncStatusBody.createDiv({ text: `Last sync: ${formattedDate}`, cls: 'snipd-sync-status-text' }); if (this.plugin.settings.lastSyncEpisodeCount > 0 || this.plugin.settings.lastSyncSnipCount > 0) { - syncStatusBody.createEl('div', { + syncStatusBody.createDiv({ text: `Last synced: ${this.plugin.settings.lastSyncEpisodeCount} episodes, ${this.plugin.settings.lastSyncSnipCount} snips`, cls: 'snipd-sync-status-text' }); } } else { - syncStatusBody.createEl('div', { + syncStatusBody.createDiv({ text: 'No sync performed yet', cls: 'snipd-sync-status-text' }); @@ -304,7 +304,7 @@ export class SnipdSettingModal extends PluginSettingTab { button.setButtonText(isBusy ? "Syncing..." : "Reset & sync"); button.setDisabled(isBusy); button.onClick(() => { - const confirmed = globalThis.window.confirm( + const confirmed = activeWindow.confirm( "This will remove all synced Snipd data from your vault and start a fresh sync. Continue?" ); if (!confirmed) { @@ -320,12 +320,12 @@ export class SnipdSettingModal extends PluginSettingTab { }); if (this.refreshInterval !== null) { - globalThis.window.clearInterval(this.refreshInterval); + activeWindow.clearInterval(this.refreshInterval); this.refreshInterval = null; } if (this.plugin.settings.isSyncing || this.plugin.settings.isTestSyncing) { - this.refreshInterval = globalThis.window.setInterval(() => { + this.refreshInterval = activeWindow.setInterval(() => { this.display(); }, 1000); } diff --git a/src/utils.ts b/src/utils.ts index bf557ff..946efc5 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -8,7 +8,7 @@ export const isDev = (): boolean => { export const debugLog = (...args: unknown[]): void => { if (isDev()) { - globalThis.console.log('[Snipd]', ...args); + console.debug('[Snipd]', ...args); } };