From 7590b82a52a6df00964dc7699620af33af01b6d5 Mon Sep 17 00:00:00 2001 From: snomiao Date: Fri, 12 Sep 2025 04:44:05 +0000 Subject: [PATCH] Revert "fix: Fix i18n collection by handling Vue/CSS imports in Node.js" This reverts commit 7444c05564cbf59db1e6017566b4c88b8ad8e7e1. --- browser_tests/i18nSetup.ts | 64 ++++++++--------------------- browser_tests/registerVueLoader.mjs | 15 ------- browser_tests/vueLoader.mjs | 63 ---------------------------- package.json | 2 +- scripts/collect-i18n-node-defs.ts | 38 +++-------------- scripts/mocks/dialogService.ts | 26 ------------ 6 files changed, 22 insertions(+), 186 deletions(-) delete mode 100644 browser_tests/registerVueLoader.mjs delete mode 100644 browser_tests/vueLoader.mjs delete mode 100644 scripts/mocks/dialogService.ts diff --git a/browser_tests/i18nSetup.ts b/browser_tests/i18nSetup.ts index ce7a1d908..e3172f58b 100644 --- a/browser_tests/i18nSetup.ts +++ b/browser_tests/i18nSetup.ts @@ -1,6 +1,6 @@ /** * Setup for i18n collection tests - * Handles preprocessing of files that contain TypeScript 'declare' keywords + * Handles preprocessing of litegraph files that contain TypeScript 'declare' keywords */ import { promises as fs } from 'fs' import { glob } from 'glob' @@ -10,28 +10,17 @@ import { fileURLToPath } from 'url' const __dirname = path.dirname(fileURLToPath(import.meta.url)) const rootDir = path.resolve(__dirname, '..') const litegraphSrcDir = path.join(rootDir, 'src/lib/litegraph/src') -const scriptsSrcDir = path.join(rootDir, 'src/scripts') const backupMap = new Map() export async function preprocessLitegraph() { console.log('Preprocessing litegraph files for i18n collection...') - // Search for all .ts files in litegraph src directory and scripts directory - const patterns = [ - path.join(litegraphSrcDir, '**/*.ts'), - path.join(scriptsSrcDir, '**/*.ts') - ] - - const files = ( - await Promise.all( - patterns.map((pattern) => - glob(pattern, { - ignore: ['**/*.test.ts', '**/*.spec.ts', '**/node_modules/**'] - }) - ) - ) - ).flat() + // Search for all .ts files in litegraph src directory + const pattern = path.join(litegraphSrcDir, '**/*.ts') + const files = await glob(pattern, { + ignore: ['**/*.test.ts', '**/*.spec.ts', '**/node_modules/**'] + }) let processedCount = 0 @@ -41,41 +30,23 @@ export async function preprocessLitegraph() { try { const originalContent = await fs.readFile(filePath, 'utf-8') - // Check if file needs any modifications - const hasDeclareKeywords = /^\s*declare\s+/m.test(originalContent) - const hasCssImports = /^(\s*)import\s+['"].*\.css['"];?$/m.test(originalContent) - - if (!hasDeclareKeywords && !hasCssImports) { - return // Skip files that don't need modifications + // Check for class property declarations with 'declare' keyword + if (!/^\s*declare\s+/m.test(originalContent)) { + return // Skip files without declare keywords } // Store original content in memory backupMap.set(filePath, originalContent) - let modifiedContent = originalContent - - // Remove 'declare' keyword from class properties if present - if (hasDeclareKeywords) { - modifiedContent = modifiedContent.replace( - /^(\s*)declare\s+/gm, - '$1// @ts-ignore - removed declare for Playwright\n$1' - ) - } - - // Comment out CSS imports to avoid Babel parsing errors - if (hasCssImports) { - modifiedContent = modifiedContent.replace( - /^(\s*)import\s+['"].*\.css['"];?$/gm, - '$1// CSS import commented for Playwright: $&' - ) - } + // Remove 'declare' keyword from class properties + const modifiedContent = originalContent.replace( + /^(\s*)declare\s+/gm, + '$1// @ts-ignore - removed declare for Playwright\n$1' + ) // Write modified content await fs.writeFile(filePath, modifiedContent) - const relativePath = filePath.includes(litegraphSrcDir) - ? path.relative(litegraphSrcDir, filePath) - : path.relative(scriptsSrcDir, filePath) - console.log(` ✓ Processed ${relativePath}`) + console.log(` ✓ Processed ${path.relative(litegraphSrcDir, filePath)}`) processedCount++ } catch (error: unknown) { console.warn( @@ -102,10 +73,7 @@ export async function restoreLitegraph() { await Promise.all( Array.from(backupMap.entries()).map(async ([filePath, originalContent]) => { await fs.writeFile(filePath, originalContent) - const relativePath = filePath.includes(litegraphSrcDir) - ? path.relative(litegraphSrcDir, filePath) - : path.relative(scriptsSrcDir, filePath) - console.log(` ✓ Restored ${relativePath}`) + console.log(` ✓ Restored ${path.relative(litegraphSrcDir, filePath)}`) }) ) diff --git a/browser_tests/registerVueLoader.mjs b/browser_tests/registerVueLoader.mjs deleted file mode 100644 index 7f2a17da8..000000000 --- a/browser_tests/registerVueLoader.mjs +++ /dev/null @@ -1,15 +0,0 @@ -/** - * Registration script for Vue loader - * Used with --import flag in Node.js to stub Vue files during i18n collection - */ - -import { register } from 'node:module' -import { pathToFileURL } from 'node:url' -import { dirname, join } from 'node:path' -import { fileURLToPath } from 'node:url' - -// Get the directory of this file -const __dirname = dirname(fileURLToPath(import.meta.url)) - -// Register the Vue loader -register(pathToFileURL(join(__dirname, 'vueLoader.mjs'))) \ No newline at end of file diff --git a/browser_tests/vueLoader.mjs b/browser_tests/vueLoader.mjs deleted file mode 100644 index dbb1bb27c..000000000 --- a/browser_tests/vueLoader.mjs +++ /dev/null @@ -1,63 +0,0 @@ -/** - * ES Module loader for Vue files and service mocks in Node.js - * Used during i18n collection to stub Vue component imports and services with Vue dependencies - */ - -export async function resolve(specifier, context, nextResolve) { - // Mock dialogService to avoid Vue imports - if (specifier.endsWith('/dialogService') || specifier.endsWith('/dialogService.ts')) { - const mockPath = new URL('../scripts/mocks/dialogService.ts', import.meta.url) - return { - url: mockPath.href, - shortCircuit: true - } - } - - // Pass through for non-Vue files - if (!specifier.endsWith('.vue')) { - return nextResolve(specifier, context) - } - - // Resolve Vue files normally - return nextResolve(specifier, context) -} - -export async function load(url, context, nextLoad) { - // Handle mock files - if (url.includes('/scripts/mocks/')) { - return nextLoad(url, context) - } - - // Handle CSS files - return empty module - if (url.endsWith('.css')) { - return { - format: 'module', - shortCircuit: true, - source: 'export default {}' - } - } - - // Only handle .vue files - if (!url.endsWith('.vue')) { - return nextLoad(url, context) - } - - // Return a stub Vue component as JavaScript - const componentName = url.split('/').pop().replace('.vue', '') - - const stubComponent = ` - export default { - name: '${componentName}', - render: () => null, - props: {}, - setup: () => ({}), - template: '
' - } - ` - - return { - format: 'module', - shortCircuit: true, - source: stubComponent - } -} \ No newline at end of file diff --git a/package.json b/package.json index c49b0ad79..f4e6035d3 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ "knip": "knip --cache", "knip:no-cache": "knip", "locale": "lobe-i18n locale", - "collect-i18n": "NODE_OPTIONS='--import ./browser_tests/registerVueLoader.mjs' npx playwright test --config=playwright.i18n.config.ts", + "collect-i18n": "npx playwright test --config=playwright.i18n.config.ts", "json-schema": "tsx scripts/generate-json-schema.ts", "storybook": "nx storybook -p 6006", "build-storybook": "storybook build" diff --git a/scripts/collect-i18n-node-defs.ts b/scripts/collect-i18n-node-defs.ts index a29d5263e..11abd660f 100644 --- a/scripts/collect-i18n-node-defs.ts +++ b/scripts/collect-i18n-node-defs.ts @@ -2,38 +2,10 @@ import * as fs from 'fs' import { comfyPageFixture as test } from '../browser_tests/fixtures/ComfyPage' import type { ComfyNodeDef } from '../src/schemas/nodeDefSchema' +import type { ComfyApi } from '../src/scripts/api' +import { ComfyNodeDefImpl } from '../src/stores/nodeDefStore' import { normalizeI18nKey } from '../src/utils/formatUtil' -// Simple NodeDef wrapper for i18n collection -// Avoids importing ComfyNodeDefImpl which has Vue dependencies -class SimpleNodeDef { - constructor(public readonly def: ComfyNodeDef) {} - - get name() { return this.def.name } - get display_name() { return this.def.display_name } - get inputs() { - // Simple transformation - just get the input specs - const inputs: Record = {} - if (this.def.input?.required) { - Object.entries(this.def.input.required).forEach(([key, spec]) => { - inputs[key] = { name: key, type: spec[0] } - }) - } - if (this.def.input?.optional) { - Object.entries(this.def.input.optional).forEach(([key, spec]) => { - inputs[key] = { name: key, type: spec[0] } - }) - } - return inputs - } - get outputs() { - return (this.def.output || []).map((type, index) => ({ - type, - name: this.def.output_name?.[index] || '' - })) - } -} - const localePath = './src/locales/en/main.json' const nodeDefsPath = './src/locales/en/nodeDefs.json' @@ -45,17 +17,17 @@ test('collect-i18n-node-defs', async ({ comfyPage }) => { }) }) - const nodeDefs: SimpleNodeDef[] = ( + const nodeDefs: ComfyNodeDefImpl[] = ( Object.values( await comfyPage.page.evaluate(async () => { - const api = window['app'].api as any + const api = window['app'].api as ComfyApi return await api.getNodeDefs() }) ) as ComfyNodeDef[] ) // Ignore DevTools nodes (used for internal testing) .filter((def) => !def.name.startsWith('DevTools')) - .map((def) => new SimpleNodeDef(def)) + .map((def) => new ComfyNodeDefImpl(def)) console.log(`Collected ${nodeDefs.length} node definitions`) diff --git a/scripts/mocks/dialogService.ts b/scripts/mocks/dialogService.ts deleted file mode 100644 index 9b7cc4d19..000000000 --- a/scripts/mocks/dialogService.ts +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Mock dialogService for i18n collection - * This avoids importing Vue components during Node.js execution - */ - -export const useDialogService = () => { - return { - showLoadWorkflowWarning: () => {}, - showMissingModelsWarning: () => {}, - showSettingsDialog: () => {}, - showAboutDialog: () => {}, - showExecutionErrorDialog: () => {}, - showTemplateWorkflowsDialog: () => {}, - showManagerDialog: () => {}, - showManagerProgressDialog: () => {}, - showErrorDialog: () => {}, - showApiNodesSignInDialog: () => Promise.resolve(false), - showSignInDialog: () => Promise.resolve(false), - showUpdatePasswordDialog: () => Promise.resolve(false), - showConfirmationDialog: () => Promise.resolve(false), - showNodeConflictDialog: () => Promise.resolve(false), - showPromptDialog: () => Promise.resolve(''), - showDataManagementDialog: () => {}, - showTopUpCreditsDialog: () => Promise.resolve(false) - } -} \ No newline at end of file