diff --git a/.cursorrules b/.cursorrules index 2dd4862b8..6f43623a3 100644 --- a/.cursorrules +++ b/.cursorrules @@ -49,7 +49,7 @@ DO NOT use deprecated PrimeVue components. Use these replacements instead: ## Development Guidelines 1. Leverage VueUse functions for performance-enhancing styles -2. Use lodash for utility functions +2. Use es-toolkit for utility functions 3. Use TypeScript for type safety 4. Implement proper props and emits definitions 5. Utilize Vue 3's Teleport component when needed diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 9598b1300..551b03721 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -18,7 +18,7 @@ Use Tailwind CSS for styling Leverage VueUse functions for performance-enhancing styles -Use lodash for utility functions +Use es-toolkit for utility functions Use TypeScript for type safety diff --git a/.github/workflows/update-manager-types.yaml b/.github/workflows/update-manager-types.yaml index 7b3a340ba..7933c7cbe 100644 --- a/.github/workflows/update-manager-types.yaml +++ b/.github/workflows/update-manager-types.yaml @@ -61,6 +61,11 @@ jobs: exit 1 fi + - name: Lint generated types + run: | + echo "Linting generated ComfyUI-Manager API types..." + npm run lint:fix:no-cache -- ./src/types/generatedManagerTypes.ts + - name: Check for changes id: check-changes run: | diff --git a/.github/workflows/update-registry-types.yaml b/.github/workflows/update-registry-types.yaml index 5382ae1ff..39a653697 100644 --- a/.github/workflows/update-registry-types.yaml +++ b/.github/workflows/update-registry-types.yaml @@ -61,6 +61,11 @@ jobs: exit 1 fi + - name: Lint generated types + run: | + echo "Linting generated Comfy Registry API types..." + npm run lint:fix:no-cache -- ./src/types/comfyRegistryTypes.ts + - name: Check for changes id: check-changes run: | diff --git a/.gitignore b/.gitignore index b49947757..a5347cd65 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,9 @@ yarn-error.log* pnpm-debug.log* lerna-debug.log* +# ESLint cache +.eslintcache + node_modules dist dist-ssr diff --git a/browser_tests/fixtures/utils/taskHistory.ts b/browser_tests/fixtures/utils/taskHistory.ts index 93d5b9b07..2c42c8492 100644 --- a/browser_tests/fixtures/utils/taskHistory.ts +++ b/browser_tests/fixtures/utils/taskHistory.ts @@ -1,5 +1,5 @@ +import _ from 'es-toolkit/compat' import fs from 'fs' -import _ from 'lodash' import path from 'path' import type { Request, Route } from 'playwright' import { v4 as uuidv4 } from 'uuid' @@ -75,7 +75,9 @@ export default class TaskHistory { private async handleGetView(route: Route) { const fileName = getFilenameParam(route.request()) - if (!this.outputContentTypes.has(fileName)) route.continue() + if (!this.outputContentTypes.has(fileName)) { + return route.continue() + } const asset = this.loadAsset(fileName) return route.fulfill({ diff --git a/browser_tests/tests/sidebar/workflows.spec.ts b/browser_tests/tests/sidebar/workflows.spec.ts index 9b853168f..8a700ccdc 100644 --- a/browser_tests/tests/sidebar/workflows.spec.ts +++ b/browser_tests/tests/sidebar/workflows.spec.ts @@ -317,6 +317,25 @@ test.describe('Workflows sidebar', () => { ]) }) + test('Can duplicate workflow from context menu', async ({ comfyPage }) => { + await comfyPage.setupWorkflowsDirectory({ + 'workflow1.json': 'default.json' + }) + + const { workflowsTab } = comfyPage.menu + await workflowsTab.open() + + await workflowsTab + .getPersistedItem('workflow1.json') + .click({ button: 'right' }) + await comfyPage.clickContextMenuItem('Duplicate') + + expect(await workflowsTab.getOpenedWorkflowNames()).toEqual([ + '*Unsaved Workflow.json', + '*workflow1 (Copy).json' + ]) + }) + test('Can drop workflow from workflows sidebar', async ({ comfyPage }) => { await comfyPage.setupWorkflowsDirectory({ 'workflow1.json': 'default.json' diff --git a/eslint.config.js b/eslint.config.js index 53ad76e3f..7479bb107 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -14,7 +14,10 @@ export default [ ignores: [ 'src/scripts/*', 'src/extensions/core/*', - 'src/types/vue-shim.d.ts' + 'src/types/vue-shim.d.ts', + // Generated files that don't need linting + 'src/types/comfyRegistryTypes.ts', + 'src/types/generatedManagerTypes.ts' ] }, { diff --git a/package-lock.json b/package-lock.json index 135a1d41d..0ba6681f4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@comfyorg/comfyui-frontend", - "version": "1.26.1", + "version": "1.26.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@comfyorg/comfyui-frontend", - "version": "1.26.1", + "version": "1.26.2", "license": "GPL-3.0-only", "dependencies": { "@alloc/quick-lru": "^5.2.0", @@ -30,12 +30,12 @@ "axios": "^1.8.2", "dompurify": "^3.2.5", "dotenv": "^16.4.5", + "es-toolkit": "^1.39.9", "extendable-media-recorder": "^9.2.27", "extendable-media-recorder-wav-encoder": "^7.0.129", "firebase": "^11.6.0", "fuse.js": "^7.0.0", "jsondiffpatch": "^0.6.0", - "lodash": "^4.17.21", "loglevel": "^1.9.2", "marked": "^15.0.11", "pinia": "^2.1.7", @@ -62,7 +62,6 @@ "@trivago/prettier-plugin-sort-imports": "^5.2.0", "@types/dompurify": "^3.0.5", "@types/fs-extra": "^11.0.4", - "@types/lodash": "^4.17.6", "@types/node": "^20.14.8", "@types/semver": "^7.7.0", "@types/three": "^0.169.0", @@ -4887,12 +4886,6 @@ "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==", "license": "MIT" }, - "node_modules/@types/lodash": { - "version": "4.17.6", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.6.tgz", - "integrity": "sha512-OpXEVoCKSS3lQqjx9GGGOapBeuW5eUboYHRlHP9urXPX25IKZ6AnP5ZRxtVf63iieUbsHxLn8NQ5Nlftc6yzAA==", - "dev": true - }, "node_modules/@types/markdown-it": { "version": "14.1.2", "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz", @@ -7998,6 +7991,15 @@ "node": ">= 0.4" } }, + "node_modules/es-toolkit": { + "version": "1.39.9", + "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.39.9.tgz", + "integrity": "sha512-9OtbkZmTA2Qc9groyA1PUNeb6knVTkvB2RSdr/LcJXDL8IdEakaxwXLHXa7VX/Wj0GmdMJPR3WhnPGhiP3E+qg==", + "workspaces": [ + "docs", + "benchmarks" + ] + }, "node_modules/esbuild": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", @@ -11450,7 +11452,8 @@ "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true }, "node_modules/lodash-es": { "version": "4.17.21", diff --git a/package.json b/package.json index 27cc90d77..91e7cc3a0 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@comfyorg/comfyui-frontend", "private": true, - "version": "1.26.1", + "version": "1.26.2", "type": "module", "repository": "https://github.com/Comfy-Org/ComfyUI_frontend", "homepage": "https://comfy.org", @@ -21,8 +21,10 @@ "test:component": "vitest run src/components/", "prepare": "husky || true", "preview": "vite preview", - "lint": "eslint src", - "lint:fix": "eslint src --fix", + "lint": "eslint src --cache", + "lint:fix": "eslint src --cache --fix", + "lint:no-cache": "eslint src", + "lint:fix:no-cache": "eslint src --fix", "knip": "knip", "locale": "lobe-i18n locale", "collect-i18n": "playwright test --config=playwright.i18n.config.ts", @@ -39,7 +41,6 @@ "@trivago/prettier-plugin-sort-imports": "^5.2.0", "@types/dompurify": "^3.0.5", "@types/fs-extra": "^11.0.4", - "@types/lodash": "^4.17.6", "@types/node": "^20.14.8", "@types/semver": "^7.7.0", "@types/three": "^0.169.0", @@ -98,12 +99,12 @@ "axios": "^1.8.2", "dompurify": "^3.2.5", "dotenv": "^16.4.5", + "es-toolkit": "^1.39.9", "extendable-media-recorder": "^9.2.27", "extendable-media-recorder-wav-encoder": "^7.0.129", "firebase": "^11.6.0", "fuse.js": "^7.0.0", "jsondiffpatch": "^0.6.0", - "lodash": "^4.17.21", "loglevel": "^1.9.2", "marked": "^15.0.11", "pinia": "^2.1.7", diff --git a/src/CLAUDE.md b/src/CLAUDE.md index a4b273c7b..8a651b3c1 100644 --- a/src/CLAUDE.md +++ b/src/CLAUDE.md @@ -51,7 +51,7 @@ const template = await fetch('/templates/default.json') ## General Guidelines -- Use lodash for utility functions +- Use es-toolkit for utility functions - Implement proper TypeScript types - Follow Vue 3 composition API style guide - Use vue-i18n for ALL user-facing strings in `src/locales/en/main.json` diff --git a/src/components/actionbar/ComfyActionbar.vue b/src/components/actionbar/ComfyActionbar.vue index be113867a..4389fcf59 100644 --- a/src/components/actionbar/ComfyActionbar.vue +++ b/src/components/actionbar/ComfyActionbar.vue @@ -20,7 +20,7 @@ import { useLocalStorage, watchDebounced } from '@vueuse/core' -import { clamp } from 'lodash' +import { clamp } from 'es-toolkit/compat' import Panel from 'primevue/panel' import { Ref, computed, inject, nextTick, onMounted, ref, watch } from 'vue' diff --git a/src/components/common/SearchBox.vue b/src/components/common/SearchBox.vue index c2a7e7482..de9b64d19 100644 --- a/src/components/common/SearchBox.vue +++ b/src/components/common/SearchBox.vue @@ -42,7 +42,7 @@