Revert "fix: Fix i18n collection by handling Vue/CSS imports in Node.js"

This reverts commit 7444c05564.
This commit is contained in:
snomiao
2025-09-12 04:44:05 +00:00
parent 7444c05564
commit 7590b82a52
6 changed files with 22 additions and 186 deletions

View File

@@ -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<string, string>()
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)}`)
})
)

View File

@@ -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')))

View File

@@ -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: '<div></div>'
}
`
return {
format: 'module',
shortCircuit: true,
source: stubComponent
}
}

View File

@@ -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"

View File

@@ -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<string, any> = {}
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`)

View File

@@ -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)
}
}