diff --git a/src/apps/cli/commands/p2p.ts b/src/apps/cli/commands/p2p.ts index f7c78e2..e6542ad 100644 --- a/src/apps/cli/commands/p2p.ts +++ b/src/apps/cli/commands/p2p.ts @@ -2,14 +2,15 @@ import type { LiveSyncBaseCore } from "@/LiveSyncBaseCore"; import { P2P_DEFAULT_SETTINGS } from "@lib/common/types"; import type { ServiceContext } from "@lib/services/base/ServiceBase"; import { LiveSyncTrysteroReplicator } from "@lib/replication/trystero/LiveSyncTrysteroReplicator"; -import { addP2PEventHandlers } from "@lib/replication/trystero/addP2PEventHandlers"; +import { compatGlobal } from "@lib/common/coreEnvFunctions.ts"; + type CLIP2PPeer = { peerId: string; name: string; }; function delay(ms: number): Promise { - return new Promise((resolve) => setTimeout(resolve, ms)); + return new Promise((resolve) => compatGlobal.setTimeout(resolve, ms)); } export function parseTimeoutSeconds(value: string, commandName: string): number { diff --git a/src/apps/cli/commands/runCommand.ts b/src/apps/cli/commands/runCommand.ts index 74ee8ab..9ce1a2f 100644 --- a/src/apps/cli/commands/runCommand.ts +++ b/src/apps/cli/commands/runCommand.ts @@ -18,6 +18,7 @@ import { promptForPassphrase, readStdinAsUtf8, toArrayBuffer, toDatabaseRelative import { collectPeers, openP2PHost, parseTimeoutSeconds, syncWithPeer } from "./p2p"; import { performFullScan } from "@lib/serviceFeatures/offlineScanner"; import { UnresolvedErrorManager } from "@lib/services/base/UnresolvedErrorManager"; +import { compatGlobal } from "@lib/common/coreEnvFunctions.ts"; function redactConnectionString(uri: string): string { return uri.replace(/\/\/([^@/]+)@/u, "//***@"); @@ -150,11 +151,11 @@ export async function runCommand(options: CLIOptions, context: CLICommandContext ); } } - pollTimer = setTimeout(poll, currentIntervalMs); + pollTimer = compatGlobal.setTimeout(poll, currentIntervalMs); }; - let pollTimer: ReturnType = setTimeout(poll, currentIntervalMs); + let pollTimer = compatGlobal.setTimeout(poll, currentIntervalMs); core.services.appLifecycle.onUnload.addHandler(async () => { - clearTimeout(pollTimer); + compatGlobal.clearTimeout(pollTimer); return true; }); } else { diff --git a/src/apps/cli/testdeno/bench-couchdb.ts b/src/apps/cli/testdeno/bench-couchdb.ts index 6ed6df7..f419697 100644 --- a/src/apps/cli/testdeno/bench-couchdb.ts +++ b/src/apps/cli/testdeno/bench-couchdb.ts @@ -3,6 +3,7 @@ import { applyRemoteSyncSettings, initSettingsFile } from "./helpers/settings.ts import { assertFilesEqual, runCliOrFail } from "./helpers/cli.ts"; import { startCouchdb, stopCouchdb } from "./helpers/docker.ts"; import { createDeterministicDataset, type DatasetEntry } from "./helpers/dataset.ts"; +import { compatGlobal } from "@lib/common/coreEnvFunctions.ts"; type BenchmarkConfig = { couchdbBackendUri: string; @@ -137,7 +138,7 @@ function startCouchdbProxy(options: { backendUri: string; proxyUri: string; requ }, }, async (request) => { - await new Promise((resolve) => setTimeout(resolve, halfDelayMs)); + await new Promise((resolve) => compatGlobal.setTimeout(resolve, halfDelayMs)); const targetUrl = new URL(request.url); targetUrl.protocol = backend.protocol; diff --git a/src/apps/cli/testdeno/helpers/backgroundCli.ts b/src/apps/cli/testdeno/helpers/backgroundCli.ts index ef81fea..52ac46b 100644 --- a/src/apps/cli/testdeno/helpers/backgroundCli.ts +++ b/src/apps/cli/testdeno/helpers/backgroundCli.ts @@ -1,5 +1,6 @@ import { CLI_DIR, TEE_ENABLED, formatTeeCommand, createLineTeeWriter } from "./cli.ts"; import { join } from "@std/path"; +import { compatGlobal } from "@lib/common/coreEnvFunctions.ts"; const CLI_DIST = join(CLI_DIR, "dist", "index.cjs"); const VERBOSE_ENABLED = Deno.env.get("LIVESYNC_CLI_VERBOSE") === "1"; @@ -77,7 +78,9 @@ export class BackgroundCliProcess { if (this.combined.includes(needle)) return; const status = await Promise.race([ this.child.status.then((s) => ({ type: "status" as const, status: s })), - new Promise<{ type: "tick" }>((resolve) => setTimeout(() => resolve({ type: "tick" }), 100)), + new Promise<{ type: "tick" }>((resolve) => + compatGlobal.setTimeout(() => resolve({ type: "tick" }), 100) + ), ]); if (status.type === "status") { throw new Error( diff --git a/src/apps/cli/testdeno/helpers/cli.ts b/src/apps/cli/testdeno/helpers/cli.ts index c393c26..aae6b67 100644 --- a/src/apps/cli/testdeno/helpers/cli.ts +++ b/src/apps/cli/testdeno/helpers/cli.ts @@ -1,4 +1,5 @@ import { join } from "@std/path"; +import { compatGlobal } from "@lib/common/coreEnvFunctions.ts"; // --------------------------------------------------------------------------- // Path resolution @@ -25,7 +26,7 @@ const VERBOSE_ENABLED = Deno.env.get("LIVESYNC_CLI_VERBOSE") === "1"; const DEBUG_ENABLED = Deno.env.get("LIVESYNC_CLI_DEBUG") === "1"; function sleep(ms: number): Promise { - return new Promise((resolve) => setTimeout(resolve, ms)); + return new Promise((resolve) => compatGlobal.setTimeout(resolve, ms)); } function concatChunks(chunks: Uint8Array[]): Uint8Array { diff --git a/src/apps/cli/testdeno/helpers/docker.ts b/src/apps/cli/testdeno/helpers/docker.ts index 3c0e6ce..9c5d6bd 100644 --- a/src/apps/cli/testdeno/helpers/docker.ts +++ b/src/apps/cli/testdeno/helpers/docker.ts @@ -1,3 +1,5 @@ +import { compatGlobal } from "@lib/common/coreEnvFunctions.ts"; + /** * Docker service management for tests. * @@ -256,7 +258,7 @@ function untrackContainer(container: string): void { } function sleep(ms: number): Promise { - return new Promise((resolve) => setTimeout(resolve, ms)); + return new Promise((resolve) => compatGlobal.setTimeout(resolve, ms)); } async function waitForCouchdbStable(hostname: string, user: string, password: string): Promise { diff --git a/src/apps/cli/testdeno/helpers/net.ts b/src/apps/cli/testdeno/helpers/net.ts index fa5debd..dd8b076 100644 --- a/src/apps/cli/testdeno/helpers/net.ts +++ b/src/apps/cli/testdeno/helpers/net.ts @@ -1,3 +1,5 @@ +import { compatGlobal } from "@lib/common/coreEnvFunctions.ts"; + type WaitForPortOptions = { timeoutMs?: number; intervalMs?: number; @@ -5,7 +7,7 @@ type WaitForPortOptions = { }; function sleep(ms: number): Promise { - return new Promise((resolve) => setTimeout(resolve, ms)); + return new Promise((resolve) => compatGlobal.setTimeout(resolve, ms)); } async function connectWithTimeout(hostname: string, port: number, timeoutMs: number): Promise { @@ -13,13 +15,13 @@ async function connectWithTimeout(hostname: string, port: number, timeoutMs: num try { const connPromise = Deno.connect({ hostname, port }); const timeoutPromise = new Promise((_, reject) => { - timer = setTimeout(() => reject(new Error(`connect timeout after ${timeoutMs}ms`)), timeoutMs); + timer = compatGlobal.setTimeout(() => reject(new Error(`connect timeout after ${timeoutMs}ms`)), timeoutMs); }); const conn = await Promise.race([connPromise, timeoutPromise]); conn.close(); } finally { if (timer !== undefined) { - clearTimeout(timer); + compatGlobal.clearTimeout(timer); } } } diff --git a/src/apps/cli/testdeno/helpers/p2p.ts b/src/apps/cli/testdeno/helpers/p2p.ts index a04b080..98d8603 100644 --- a/src/apps/cli/testdeno/helpers/p2p.ts +++ b/src/apps/cli/testdeno/helpers/p2p.ts @@ -1,6 +1,7 @@ import { runCli } from "./cli.ts"; import { isLocalP2pRelay, startP2pRelay, stopP2pRelay, startCoturn, stopCoturn } from "./docker.ts"; import { waitForPort } from "./net.ts"; +import { compatGlobal } from "@lib/common/coreEnvFunctions.ts"; export type PeerEntry = { id: string; @@ -8,7 +9,7 @@ export type PeerEntry = { }; function sleep(ms: number): Promise { - return new Promise((resolve) => setTimeout(resolve, ms)); + return new Promise((resolve) => compatGlobal.setTimeout(resolve, ms)); } function parseRelayEndpoint(relay: string): { hostname: string; port: number } { diff --git a/src/apps/cli/testdeno/test-sync-two-local-databases.ts b/src/apps/cli/testdeno/test-sync-two-local-databases.ts index 5717d40..422d5d0 100644 --- a/src/apps/cli/testdeno/test-sync-two-local-databases.ts +++ b/src/apps/cli/testdeno/test-sync-two-local-databases.ts @@ -28,6 +28,7 @@ import { TempDir } from "./helpers/temp.ts"; import { runCliOrFail, jsonFieldIsNa } from "./helpers/cli.ts"; import { applyCouchdbSettings, initSettingsFile } from "./helpers/settings.ts"; import { startCouchdb, stopCouchdb } from "./helpers/docker.ts"; +import { compatGlobal } from "@lib/common/coreEnvFunctions.ts"; // --------------------------------------------------------------------------- // Load configuration @@ -109,7 +110,7 @@ async function runSuite( config: { uri: string; user: string; password: string }, dbname: string ): Promise { - const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); + const sleep = (ms: number) => new Promise((resolve) => compatGlobal.setTimeout(resolve, ms)); const runWithRetry = async (label: string, fn: () => Promise, retries = SYNC_RETRY): Promise => { let lastErr: unknown; for (let i = 0; i <= retries; i++) { diff --git a/src/apps/webapp/bootstrap.ts b/src/apps/webapp/bootstrap.ts index b3fa072..a6d9800 100644 --- a/src/apps/webapp/bootstrap.ts +++ b/src/apps/webapp/bootstrap.ts @@ -1,11 +1,12 @@ import { LiveSyncWebApp } from "./main"; import { VaultHistoryStore, type VaultHistoryItem } from "./vaultSelector"; +import { compatGlobal, _activeDocument } from "@lib/common/coreEnvFunctions.ts"; const historyStore = new VaultHistoryStore(); let app: LiveSyncWebApp | null = null; function getRequiredElement(id: string): T { - const element = document.getElementById(id); + const element = _activeDocument.getElementById(id); if (!element) { throw new Error(`Missing element: #${id}`); } @@ -22,7 +23,7 @@ function setBusyState(isBusy: boolean): void { const pickNewBtn = getRequiredElement("pick-new-vault"); pickNewBtn.disabled = isBusy; - const historyButtons = document.querySelectorAll(".vault-item button"); + const historyButtons = _activeDocument.querySelectorAll(".vault-item button"); historyButtons.forEach((button) => { button.disabled = isBusy; }); @@ -45,24 +46,24 @@ async function renderHistoryList(): Promise { emptyEl.classList.toggle("is-hidden", items.length > 0); for (const item of items) { - const row = document.createElement("div"); + const row = _activeDocument.createElement("div"); row.className = "vault-item"; - const info = document.createElement("div"); + const info = _activeDocument.createElement("div"); info.className = "vault-item-info"; - const name = document.createElement("div"); + const name = _activeDocument.createElement("div"); name.className = "vault-item-name"; name.textContent = item.name; - const meta = document.createElement("div"); + const meta = _activeDocument.createElement("div"); meta.className = "vault-item-meta"; const label = item.id === lastUsedId ? "Last used" : "Used"; meta.textContent = `${label}: ${formatLastUsed(item.lastUsedAt)}`; info.append(name, meta); - const useButton = document.createElement("button"); + const useButton = _activeDocument.createElement("button"); useButton.type = "button"; useButton.textContent = "Use this vault"; useButton.addEventListener("click", () => { @@ -120,7 +121,7 @@ async function initializeVaultSelector(): Promise { await renderHistoryList(); } -window.addEventListener("load", async () => { +compatGlobal.addEventListener("load", async () => { try { await initializeVaultSelector(); } catch (error) { @@ -129,11 +130,11 @@ window.addEventListener("load", async () => { } }); -window.addEventListener("beforeunload", () => { +compatGlobal.addEventListener("beforeunload", () => { void app?.shutdown(); }); -(window as any).livesyncApp = { +(compatGlobal as any).livesyncApp = { getApp: () => app, historyStore, }; diff --git a/src/apps/webapp/main.ts b/src/apps/webapp/main.ts index ea32268..8b3dd4b 100644 --- a/src/apps/webapp/main.ts +++ b/src/apps/webapp/main.ts @@ -19,6 +19,7 @@ import { SetupManager } from "@/modules/features/SetupManager"; import { useSetupManagerHandlersFeature } from "@/serviceFeatures/setupObsidian/setupManagerHandlers"; import { useP2PReplicatorCommands } from "@lib/replication/trystero/useP2PReplicatorCommands"; import { useP2PReplicatorFeature } from "@lib/replication/trystero/useP2PReplicatorFeature"; +import { compatGlobal, _activeDocument } from "@lib/common/coreEnvFunctions.ts"; const SETTINGS_DIR = ".livesync"; const SETTINGS_FILE = "settings.json"; @@ -102,8 +103,8 @@ class LiveSyncWebApp { console.log("[AppLifecycle] Restart requested"); await this.shutdown(); await this.initialize(); - setTimeout(() => { - window.location.reload(); + compatGlobal.setTimeout(() => { + compatGlobal.location.reload(); }, 1000); }); @@ -235,7 +236,7 @@ class LiveSyncWebApp { } private showError(message: string) { - const statusEl = document.getElementById("status"); + const statusEl = _activeDocument.getElementById("status"); if (statusEl) { statusEl.className = "error"; statusEl.textContent = `Error: ${message}`; @@ -243,7 +244,7 @@ class LiveSyncWebApp { } private showWarning(message: string) { - const statusEl = document.getElementById("status"); + const statusEl = _activeDocument.getElementById("status"); if (statusEl) { statusEl.className = "warning"; statusEl.textContent = `Warning: ${message}`; @@ -251,7 +252,7 @@ class LiveSyncWebApp { } private showSuccess(message: string) { - const statusEl = document.getElementById("status"); + const statusEl = _activeDocument.getElementById("status"); if (statusEl) { statusEl.className = "success"; statusEl.textContent = message; diff --git a/src/apps/webapp/managers/FSAPIStorageEventManagerAdapter.ts b/src/apps/webapp/managers/FSAPIStorageEventManagerAdapter.ts index b17d69e..7c7285d 100644 --- a/src/apps/webapp/managers/FSAPIStorageEventManagerAdapter.ts +++ b/src/apps/webapp/managers/FSAPIStorageEventManagerAdapter.ts @@ -11,6 +11,7 @@ import type { } from "@lib/managers/adapters"; import type { FileEventItemSentinel } from "@lib/managers/StorageEventManager"; import type { FSAPIFile, FSAPIFolder } from "@/apps/webapp/adapters/FSAPITypes"; +import { compatGlobal } from "@lib/common/coreEnvFunctions.ts"; /** * FileSystem API-specific type guard adapter @@ -149,14 +150,14 @@ class FSAPIWatchAdapter implements IStorageEventWatchAdapter { async beginWatch(handlers: IStorageEventWatchHandlers): Promise { // Use FileSystemObserver if available (Chrome 124+) - if (typeof (window as any).FileSystemObserver === "undefined") { + if (typeof (compatGlobal as any).FileSystemObserver === "undefined") { console.log("[FSAPIWatchAdapter] FileSystemObserver not available, file watching disabled"); console.log("[FSAPIWatchAdapter] Consider using Chrome 124+ for real-time file watching"); return Promise.resolve(); } try { - const FileSystemObserver = (window as any).FileSystemObserver; + const FileSystemObserver = (compatGlobal as any).FileSystemObserver; this.observer = new FileSystemObserver(async (records: any[]) => { for (const record of records) { diff --git a/src/apps/webapp/test-entry.ts b/src/apps/webapp/test-entry.ts index 3dcb8fe..ab70ee2 100644 --- a/src/apps/webapp/test-entry.ts +++ b/src/apps/webapp/test-entry.ts @@ -12,6 +12,7 @@ import { LiveSyncWebApp } from "./main"; import type { ObsidianLiveSyncSettings } from "@lib/common/types"; import type { FilePathWithPrefix } from "@lib/common/types"; +import { compatGlobal } from "@lib/common/coreEnvFunctions.ts"; // -------------------------------------------------------------------------- // Internal state – one app instance per page / browser context @@ -41,7 +42,7 @@ async function waitForIdle(core: any, timeoutMs = 60_000): Promise { (core.services?.fileProcessing?.processing?.value ?? 0) + (core.services?.replication?.storageApplyingCount?.value ?? 0); if (q === 0) return; - await new Promise((r) => setTimeout(r, 300)); + await new Promise((r) => compatGlobal.setTimeout(r, 300)); } throw new Error(`waitForIdle timed out after ${timeoutMs} ms`); } @@ -116,7 +117,7 @@ export interface LiveSyncTestAPI { const livesyncTest: LiveSyncTestAPI = { async init(vaultName: string, settings: Partial): Promise { // Clean up any stale OPFS data from previous runs. - const opfsRoot = await navigator.storage.getDirectory(); + const opfsRoot = await compatGlobal.navigator.storage.getDirectory(); try { await opfsRoot.removeEntry(vaultName, { recursive: true }); } catch { @@ -200,4 +201,4 @@ const livesyncTest: LiveSyncTestAPI = { }; // Expose on window for Playwright page.evaluate() calls. -(window as any).livesyncTest = livesyncTest; +(compatGlobal as any).livesyncTest = livesyncTest; diff --git a/src/apps/webapp/tsconfig.json b/src/apps/webapp/tsconfig.json index f79193a..c838f6e 100644 --- a/src/apps/webapp/tsconfig.json +++ b/src/apps/webapp/tsconfig.json @@ -21,7 +21,7 @@ "noFallthroughCasesInSwitch": true, /* Path mapping */ - "baseUrl": ".", + // "baseUrl": ".", "paths": { "@/*": ["../../*"], "@lib/*": ["../../lib/src/*"] diff --git a/src/apps/webapp/vaultSelector.ts b/src/apps/webapp/vaultSelector.ts index 79764a9..fac24ca 100644 --- a/src/apps/webapp/vaultSelector.ts +++ b/src/apps/webapp/vaultSelector.ts @@ -1,3 +1,5 @@ +import { compatGlobal } from "@lib/common/coreEnvFunctions.ts"; + const HANDLE_DB_NAME = "livesync-webapp-handles"; const HANDLE_STORE_NAME = "handles"; const LAST_USED_KEY = "meta:lastUsedVaultId"; @@ -170,7 +172,7 @@ export class VaultHistoryStore { } async pickNewVault(): Promise { - const picker = (window as any).showDirectoryPicker; + const picker = (compatGlobal as any).showDirectoryPicker; if (typeof picker !== "function") { throw new Error("FileSystem API showDirectoryPicker is not supported in this browser"); } diff --git a/src/apps/webpeer/src/P2PReplicatorShim.ts b/src/apps/webpeer/src/P2PReplicatorShim.ts index 11c9a9c..8048804 100644 --- a/src/apps/webpeer/src/P2PReplicatorShim.ts +++ b/src/apps/webpeer/src/P2PReplicatorShim.ts @@ -17,7 +17,9 @@ import { type PeerStatus, type PluginShim, } from "@lib/replication/trystero/P2PReplicatorPaneCommon"; -import { P2PLogCollector, type P2PReplicatorBase, useP2PReplicator } from "@lib/replication/trystero/P2PReplicatorCore"; +import { useP2PReplicator } from "@lib/replication/trystero/P2PReplicatorCore"; +import { P2PLogCollector } from "@lib/replication/trystero/P2PLogCollector"; +import type { P2PReplicatorBase } from "@lib/replication/trystero/P2PReplicatorBase.ts"; import type { SimpleStore } from "octagonal-wheels/databases/SimpleStoreBase"; import { reactiveSource } from "octagonal-wheels/dataobject/reactive_v2"; import { EVENT_SETTING_SAVED } from "@lib/events/coreEvents"; @@ -31,6 +33,7 @@ import { SimpleStoreIDBv2 } from "octagonal-wheels/databases/SimpleStoreIDBv2"; import type { BrowserAPIService } from "@lib/services/implements/browser/BrowserAPIService"; import type { InjectableSettingService } from "@lib/services/implements/injectable/InjectableSettingService"; import { LiveSyncTrysteroReplicator } from "@lib/replication/trystero/LiveSyncTrysteroReplicator"; +import { compatGlobal } from "@lib/common/coreEnvFunctions.ts"; function addToList(item: string, list: string) { return unique( @@ -137,7 +140,7 @@ export class P2PReplicatorShim implements P2PReplicatorBase { this._initP2PReplicator(); - setTimeout(() => { + compatGlobal.setTimeout(() => { if (this.settings.P2P_AutoStart && this.settings.P2P_Enabled) { void this.open(); } @@ -164,12 +167,12 @@ export class P2PReplicatorShim implements P2PReplicatorBase { getConfig(key: string) { const vaultName = this.services.vault.getVaultName(); const dbKey = `${vaultName}-${key}`; - return localStorage.getItem(dbKey); + return compatGlobal.localStorage.getItem(dbKey); } setConfig(key: string, value: string) { const vaultName = this.services.vault.getVaultName(); const dbKey = `${vaultName}-${key}`; - localStorage.setItem(dbKey, value); + compatGlobal.localStorage.setItem(dbKey, value); } getDeviceName(): string { diff --git a/src/apps/webpeer/src/main.ts b/src/apps/webpeer/src/main.ts index befae65..045a1ff 100644 --- a/src/apps/webpeer/src/main.ts +++ b/src/apps/webpeer/src/main.ts @@ -1,9 +1,10 @@ import { mount } from "svelte"; import "./app.css"; import App from "./App.svelte"; +import { _activeDocument } from "@lib/common/coreEnvFunctions.ts"; const app = mount(App, { - target: document.getElementById("app")!, + target: _activeDocument.getElementById("app")!, }); export default app; diff --git a/src/apps/webpeer/src/uitest.ts b/src/apps/webpeer/src/uitest.ts index 04132b0..e13b4dd 100644 --- a/src/apps/webpeer/src/uitest.ts +++ b/src/apps/webpeer/src/uitest.ts @@ -1,9 +1,10 @@ import { mount } from "svelte"; import "./app.css"; import App from "./UITest.svelte"; +import { _activeDocument } from "@lib/common/coreEnvFunctions.ts"; const app = mount(App, { - target: document.getElementById("app")!, + target: _activeDocument.getElementById("app")!, }); export default app; diff --git a/src/apps/webpeer/tsconfig.app.json b/src/apps/webpeer/tsconfig.app.json index c070f33..ebea849 100644 --- a/src/apps/webpeer/tsconfig.app.json +++ b/src/apps/webpeer/tsconfig.app.json @@ -1,7 +1,7 @@ { "extends": "../../../tsconfig.json", "compilerOptions": { - "sourceRoot": "../", + // "sourceRoot": "../", "target": "ESNext", "useDefineForClassFields": true, "module": "ESNext", diff --git a/src/features/ConfigSync/PluginDialogModal.ts b/src/features/ConfigSync/PluginDialogModal.ts index 34cb27c..f5dc12e 100644 --- a/src/features/ConfigSync/PluginDialogModal.ts +++ b/src/features/ConfigSync/PluginDialogModal.ts @@ -19,7 +19,7 @@ export class PluginDialogModal extends Modal { this.contentEl.setCssStyles({ overflow: "auto", display: "flex", - flexDirection: "column" + flexDirection: "column", }); this.titleEl.setText("Customization Sync (Beta3)"); if (!this.component) { diff --git a/src/lib b/src/lib index 3dad956..7157dbc 160000 --- a/src/lib +++ b/src/lib @@ -1 +1 @@ -Subproject commit 3dad9565aa2b58dc3190dcb88182d0f2acd8fb87 +Subproject commit 7157dbc62cbdd551e6a5f9ff417bf05a833e9099 diff --git a/src/modules/coreObsidian/UILib/dialogs.ts b/src/modules/coreObsidian/UILib/dialogs.ts index ef94340..93ac895 100644 --- a/src/modules/coreObsidian/UILib/dialogs.ts +++ b/src/modules/coreObsidian/UILib/dialogs.ts @@ -194,7 +194,7 @@ export class MessageBox extends AutoClosableModal { const div = contentEl.createDiv(); div.setCssStyles({ userSelect: "text", - "webkitUserSelect": "text" + webkitUserSelect: "text", }); void MarkdownRenderer.render(this.plugin.app, this.contentMd, div, "/", this.plugin); const buttonSetting = new Setting(contentEl); @@ -214,7 +214,7 @@ export class MessageBox extends AutoClosableModal { flexDirection: "column", alignItems: "center", justifyContent: "center", - flexGrow: "1" + flexGrow: "1", }); } contentEl.addEventListener("click", () => { @@ -244,7 +244,7 @@ export class MessageBox extends AutoClosableModal { if (this.wideButton) { btn.buttonEl.setCssStyles({ flexGrow: "1", - width: "100%" + width: "100%", }); } return btn; diff --git a/utilsdeno/refactor-globals.ts b/utilsdeno/refactor-globals.ts index 86f35c6..36b75f3 100644 --- a/utilsdeno/refactor-globals.ts +++ b/utilsdeno/refactor-globals.ts @@ -45,7 +45,7 @@ const TARGET_GLOBALS = new Set([ "navigator", "location", "document", - "window" + "window", ]); let modifiedFilesCount = 0; @@ -59,22 +59,13 @@ for (const sourceFile of project.getSourceFiles()) { continue; } - // Exclude submodule files under src/lib/ - if (posixFilePath.startsWith(posixLibSrc)) { - continue; - } - - // Exclude independent application modules under src/apps/ - if (posixFilePath.startsWith(`${posixSrc}/apps/`)) { + // Exclude coreEnvFunctions.ts to avoid self-referential definitions + if (posixFilePath.endsWith("/coreEnvFunctions.ts") || posixFilePath.endsWith("/coreEnvFunctions")) { continue; } // Exclude unit and integration test files - if ( - posixFilePath.endsWith(".spec.ts") || - posixFilePath.endsWith(".test.ts") || - posixFilePath.includes("/_test/") - ) { + if (posixFilePath.endsWith(".spec.ts") || posixFilePath.endsWith(".test.ts") || posixFilePath.includes("/_test/")) { continue; } @@ -101,6 +92,14 @@ for (const sourceFile of project.getSourceFiles()) { } } + // 1.5. Skip if it is the right-hand side of a QualifiedName (e.g. the "requestAnimationFrame" in "typeof compatGlobal.requestAnimationFrame") + if (parent.getKind() === SyntaxKind.QualifiedName) { + const qualified = parent.asKindOrThrow(SyntaxKind.QualifiedName); + if (qualified.getRight() === idNode) { + continue; + } + } + // 2. Skip if it is the operand of a typeof expression (e.g. "typeof window") if (parent.getKind() === SyntaxKind.TypeOfExpression) { continue; @@ -153,6 +152,8 @@ for (const sourceFile of project.getSourceFiles()) { let replacement = ""; if (name === "window" || name === "globalThis") { replacement = "compatGlobal"; + } else if (name === "document") { + replacement = "_activeDocument"; } else { replacement = `compatGlobal.${name}`; } @@ -174,23 +175,33 @@ for (const sourceFile of project.getSourceFiles()) { node.replaceWithText(replacement); } - // Ensure compatGlobal is imported - const hasCompatGlobalImport = sourceFile.getImportDeclarations().some((imp) => { - return imp.getNamedImports().some((ni) => ni.getName() === "compatGlobal"); - }); + // Determine what needs to be imported based on replacements + const needsCompatGlobal = nodesToReplace.some((r) => r.replacement.includes("compatGlobal")); + const needsActiveDocument = nodesToReplace.some((r) => r.replacement.includes("_activeDocument")); - if (!hasCompatGlobalImport) { + const requiredImports: string[] = []; + if (needsCompatGlobal) requiredImports.push("compatGlobal"); + if (needsActiveDocument) requiredImports.push("_activeDocument"); + + if (requiredImports.length > 0) { const existingImport = sourceFile.getImportDeclarations().find((imp) => { const spec = imp.getModuleSpecifierValue(); return spec === "@lib/common/coreEnvFunctions" || spec === "@lib/common/coreEnvFunctions.ts"; }); if (existingImport) { - existingImport.addNamedImport("compatGlobal"); + for (const nameToImport of requiredImports) { + const alreadyImported = existingImport + .getNamedImports() + .some((ni) => ni.getName() === nameToImport); + if (!alreadyImported) { + existingImport.addNamedImport(nameToImport); + } + } } else { sourceFile.addImportDeclaration({ - namedImports: ["compatGlobal"], - moduleSpecifier: "@lib/common/coreEnvFunctions.ts" + namedImports: requiredImports, + moduleSpecifier: "@lib/common/coreEnvFunctions.ts", }); } } diff --git a/utilsdeno/refactor-styles.ts b/utilsdeno/refactor-styles.ts index 4851d4c..4bdb4c6 100644 --- a/utilsdeno/refactor-styles.ts +++ b/utilsdeno/refactor-styles.ts @@ -41,7 +41,7 @@ function matchStyleAccess(node: Node): { element: Node; propertyName: string; is return { element: expr.getExpression(), propertyName: node.getName(), - isComputed: false + isComputed: false, }; } } else if (Node.isElementAccessExpression(node)) { @@ -52,7 +52,7 @@ function matchStyleAccess(node: Node): { element: Node; propertyName: string; is return { element: expr.getExpression(), propertyName: arg.getText(), - isComputed: true + isComputed: true, }; } } @@ -74,7 +74,7 @@ function getStyleAssignment(statement: Node) { property: styleAccess.propertyName, valueText: expr.getRight().getText(), isComputed: styleAccess.isComputed, - statementNode: statement + statementNode: statement, }; } @@ -100,11 +100,7 @@ for (const sourceFile of project.getSourceFiles()) { } // Exclude unit and integration test files - if ( - posixFilePath.endsWith(".spec.ts") || - posixFilePath.endsWith(".test.ts") || - posixFilePath.includes("/_test/") - ) { + if (posixFilePath.endsWith(".spec.ts") || posixFilePath.endsWith(".test.ts") || posixFilePath.includes("/_test/")) { continue; } @@ -126,12 +122,14 @@ for (const sourceFile of project.getSourceFiles()) { if (assignment) { const currentGroup: StyleGroup = { elementText: assignment.elementText, - assignments: [{ - property: assignment.property, - valueText: assignment.valueText, - isComputed: assignment.isComputed, - statementNode: assignment.statementNode - }] + assignments: [ + { + property: assignment.property, + valueText: assignment.valueText, + isComputed: assignment.isComputed, + statementNode: assignment.statementNode, + }, + ], }; // Look ahead to collect consecutive assignments to the same element @@ -143,7 +141,7 @@ for (const sourceFile of project.getSourceFiles()) { property: nextAssignment.property, valueText: nextAssignment.valueText, isComputed: nextAssignment.isComputed, - statementNode: nextAssignment.statementNode + statementNode: nextAssignment.statementNode, }); j++; } else { @@ -190,7 +188,12 @@ for (const sourceFile of project.getSourceFiles()) { const { line } = sourceFile.getLineAndColumnAtPos(firstNode.getStart()); console.log(` Line ${line}: Replacing consecutive style assignments on "${group.elementText}" with:`); - console.log(newText.split("\n").map((l) => ` ${l}`).join("\n")); + console.log( + newText + .split("\n") + .map((l) => ` ${l}`) + .join("\n") + ); if (!isDryRun) { firstNode.replaceWithText(newText);