for automatic review

This commit is contained in:
vorotamoroz
2026-06-17 05:51:01 +01:00
parent 497fd04081
commit 2d5cdccf7d
24 changed files with 123 additions and 85 deletions
+3 -2
View File
@@ -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<void> {
return new Promise((resolve) => setTimeout(resolve, ms));
return new Promise((resolve) => compatGlobal.setTimeout(resolve, ms));
}
export function parseTimeoutSeconds(value: string, commandName: string): number {
+4 -3
View File
@@ -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<typeof setTimeout> = setTimeout(poll, currentIntervalMs);
let pollTimer = compatGlobal.setTimeout(poll, currentIntervalMs);
core.services.appLifecycle.onUnload.addHandler(async () => {
clearTimeout(pollTimer);
compatGlobal.clearTimeout(pollTimer);
return true;
});
} else {
+2 -1
View File
@@ -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;
@@ -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(
+2 -1
View File
@@ -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<void> {
return new Promise((resolve) => setTimeout(resolve, ms));
return new Promise((resolve) => compatGlobal.setTimeout(resolve, ms));
}
function concatChunks(chunks: Uint8Array[]): Uint8Array {
+3 -1
View File
@@ -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<void> {
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<void> {
+5 -3
View File
@@ -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<void> {
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<void> {
@@ -13,13 +15,13 @@ async function connectWithTimeout(hostname: string, port: number, timeoutMs: num
try {
const connPromise = Deno.connect({ hostname, port });
const timeoutPromise = new Promise<never>((_, 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);
}
}
}
+2 -1
View File
@@ -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<void> {
return new Promise((resolve) => setTimeout(resolve, ms));
return new Promise((resolve) => compatGlobal.setTimeout(resolve, ms));
}
function parseRelayEndpoint(relay: string): { hostname: string; port: number } {
@@ -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<void> {
const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
const sleep = (ms: number) => new Promise((resolve) => compatGlobal.setTimeout(resolve, ms));
const runWithRetry = async <T>(label: string, fn: () => Promise<T>, retries = SYNC_RETRY): Promise<T> => {
let lastErr: unknown;
for (let i = 0; i <= retries; i++) {
+11 -10
View File
@@ -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<T extends HTMLElement>(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<HTMLButtonElement>("pick-new-vault");
pickNewBtn.disabled = isBusy;
const historyButtons = document.querySelectorAll<HTMLButtonElement>(".vault-item button");
const historyButtons = _activeDocument.querySelectorAll<HTMLButtonElement>(".vault-item button");
historyButtons.forEach((button) => {
button.disabled = isBusy;
});
@@ -45,24 +46,24 @@ async function renderHistoryList(): Promise<VaultHistoryItem[]> {
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<void> {
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,
};
+6 -5
View File
@@ -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;
@@ -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<void> {
// 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) {
+4 -3
View File
@@ -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<void> {
(core.services?.fileProcessing?.processing?.value ?? 0) +
(core.services?.replication?.storageApplyingCount?.value ?? 0);
if (q === 0) return;
await new Promise<void>((r) => setTimeout(r, 300));
await new Promise<void>((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<ObsidianLiveSyncSettings>): Promise<void> {
// 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;
+1 -1
View File
@@ -21,7 +21,7 @@
"noFallthroughCasesInSwitch": true,
/* Path mapping */
"baseUrl": ".",
// "baseUrl": ".",
"paths": {
"@/*": ["../../*"],
"@lib/*": ["../../lib/src/*"]
+3 -1
View File
@@ -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<FileSystemDirectoryHandle> {
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");
}
+7 -4
View File
@@ -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 {
+2 -1
View File
@@ -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;
+2 -1
View File
@@ -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;
+1 -1
View File
@@ -1,7 +1,7 @@
{
"extends": "../../../tsconfig.json",
"compilerOptions": {
"sourceRoot": "../",
// "sourceRoot": "../",
"target": "ESNext",
"useDefineForClassFields": true,
"module": "ESNext",
+1 -1
View File
@@ -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) {
+1 -1
Submodule src/lib updated: 3dad9565aa...7157dbc62c
+3 -3
View File
@@ -194,7 +194,7 @@ export class MessageBox<T extends readonly string[]> 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<T extends readonly string[]> extends AutoClosableModal {
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
flexGrow: "1"
flexGrow: "1",
});
}
contentEl.addEventListener("click", () => {
@@ -244,7 +244,7 @@ export class MessageBox<T extends readonly string[]> extends AutoClosableModal {
if (this.wideButton) {
btn.buttonEl.setCssStyles({
flexGrow: "1",
width: "100%"
width: "100%",
});
}
return btn;
+32 -21
View File
@@ -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",
});
}
}
+19 -16
View File
@@ -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);