mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-03-16 18:37:33 +00:00
Compare commits
5 Commits
queue_text
...
fetch-node
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
da7df96a27 | ||
|
|
2591d39da3 | ||
|
|
674d04c9cf | ||
|
|
8209765eec | ||
|
|
9d48638464 |
@@ -1,59 +0,0 @@
|
||||
import { Plugin } from 'vite'
|
||||
|
||||
/**
|
||||
* Vite plugin that adds an alias export for Vue's createBaseVNode as createElementVNode.
|
||||
*
|
||||
* This plugin addresses compatibility issues where some components or libraries
|
||||
* might be using the older createElementVNode function name instead of createBaseVNode.
|
||||
* It modifies the Vue vendor chunk during build to add the alias export.
|
||||
*
|
||||
* @returns {Plugin} A Vite plugin that modifies the Vue vendor chunk exports
|
||||
*/
|
||||
export function addElementVnodeExportPlugin(): Plugin {
|
||||
return {
|
||||
name: 'add-element-vnode-export-plugin',
|
||||
|
||||
renderChunk(code, chunk, _options) {
|
||||
if (chunk.name.startsWith('vendor-vue')) {
|
||||
const exportRegex = /(export\s*\{)([^}]*)(\}\s*;?\s*)$/
|
||||
const match = code.match(exportRegex)
|
||||
|
||||
if (match) {
|
||||
const existingExports = match[2].trim()
|
||||
const exportsArray = existingExports
|
||||
.split(',')
|
||||
.map((e) => e.trim())
|
||||
.filter(Boolean)
|
||||
|
||||
const hasCreateBaseVNode = exportsArray.some((e) =>
|
||||
e.startsWith('createBaseVNode')
|
||||
)
|
||||
const hasCreateElementVNode = exportsArray.some((e) =>
|
||||
e.includes('createElementVNode')
|
||||
)
|
||||
|
||||
if (hasCreateBaseVNode && !hasCreateElementVNode) {
|
||||
const newExportStatement = `${match[1]} ${existingExports ? existingExports + ',' : ''} createBaseVNode as createElementVNode ${match[3]}`
|
||||
const newCode = code.replace(exportRegex, newExportStatement)
|
||||
|
||||
console.log(
|
||||
`[add-element-vnode-export-plugin] Added 'createBaseVNode as createElementVNode' export to vendor-vue chunk.`
|
||||
)
|
||||
|
||||
return { code: newCode, map: null }
|
||||
} else if (!hasCreateBaseVNode) {
|
||||
console.warn(
|
||||
`[add-element-vnode-export-plugin] Warning: 'createBaseVNode' not found in exports of vendor-vue chunk. Cannot add alias.`
|
||||
)
|
||||
}
|
||||
} else {
|
||||
console.warn(
|
||||
`[add-element-vnode-export-plugin] Warning: Could not find expected export block format in vendor-vue chunk.`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,24 @@
|
||||
import type { OutputOptions } from 'rollup'
|
||||
import { HtmlTagDescriptor, Plugin } from 'vite'
|
||||
import glob from 'fast-glob'
|
||||
import fs from 'fs-extra'
|
||||
import { dirname, join } from 'node:path'
|
||||
import { HtmlTagDescriptor, Plugin, normalizePath } from 'vite'
|
||||
|
||||
interface VendorLibrary {
|
||||
interface ImportMapSource {
|
||||
name: string
|
||||
pattern: RegExp
|
||||
pattern: string | RegExp
|
||||
entry: string
|
||||
recursiveDependence?: boolean
|
||||
override?: Record<string, Partial<ImportMapSource>>
|
||||
}
|
||||
|
||||
const parseDeps = (root: string, pkg: string) => {
|
||||
const pkgPath = join(root, 'node_modules', pkg, 'package.json')
|
||||
if (fs.existsSync(pkgPath)) {
|
||||
const content = fs.readFileSync(pkgPath, 'utf-8')
|
||||
const pkg = JSON.parse(content)
|
||||
return Object.keys(pkg.dependencies || {})
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -23,53 +38,89 @@ interface VendorLibrary {
|
||||
* @returns {Plugin} A Vite plugin that generates and injects an import map
|
||||
*/
|
||||
export function generateImportMapPlugin(
|
||||
vendorLibraries: VendorLibrary[]
|
||||
importMapSources: ImportMapSource[]
|
||||
): Plugin {
|
||||
const importMapEntries: Record<string, string> = {}
|
||||
const resolvedImportMapSources: Map<string, ImportMapSource> = new Map()
|
||||
const assetDir = 'assets/lib'
|
||||
let root: string
|
||||
|
||||
return {
|
||||
name: 'generate-import-map-plugin',
|
||||
|
||||
// Configure manual chunks during the build process
|
||||
configResolved(config) {
|
||||
root = config.root
|
||||
|
||||
if (config.build) {
|
||||
// Ensure rollupOptions exists
|
||||
if (!config.build.rollupOptions) {
|
||||
config.build.rollupOptions = {}
|
||||
}
|
||||
|
||||
const outputOptions: OutputOptions = {
|
||||
manualChunks: (id: string) => {
|
||||
for (const lib of vendorLibraries) {
|
||||
if (lib.pattern.test(id)) {
|
||||
return `vendor-${lib.name}`
|
||||
}
|
||||
for (const source of importMapSources) {
|
||||
resolvedImportMapSources.set(source.name, source)
|
||||
if (source.recursiveDependence) {
|
||||
const deps = parseDeps(root, source.name)
|
||||
|
||||
while (deps.length) {
|
||||
const dep = deps.shift()!
|
||||
const depSource = Object.assign({}, source, {
|
||||
name: dep,
|
||||
pattern: dep,
|
||||
...source.override?.[dep]
|
||||
})
|
||||
resolvedImportMapSources.set(depSource.name, depSource)
|
||||
|
||||
const _deps = parseDeps(root, depSource.name)
|
||||
deps.unshift(..._deps)
|
||||
}
|
||||
return null
|
||||
},
|
||||
// Disable minification of internal exports to preserve function names
|
||||
minifyInternalExports: false
|
||||
}
|
||||
}
|
||||
config.build.rollupOptions.output = outputOptions
|
||||
|
||||
const external: (string | RegExp)[] = []
|
||||
for (const [, source] of resolvedImportMapSources) {
|
||||
external.push(source.pattern)
|
||||
}
|
||||
config.build.rollupOptions.external = external
|
||||
}
|
||||
},
|
||||
|
||||
generateBundle(_options, bundle) {
|
||||
for (const fileName in bundle) {
|
||||
const chunk = bundle[fileName]
|
||||
if (chunk.type === 'chunk' && !chunk.isEntry) {
|
||||
// Find matching vendor library by chunk name
|
||||
const vendorLib = vendorLibraries.find(
|
||||
(lib) => chunk.name === `vendor-${lib.name}`
|
||||
)
|
||||
generateBundle(_options) {
|
||||
for (const [, source] of resolvedImportMapSources) {
|
||||
if (source.entry) {
|
||||
const moduleFile = join(source.name, source.entry)
|
||||
const sourceFile = join(root, 'node_modules', moduleFile)
|
||||
const targetFile = join(root, 'dist', assetDir, moduleFile)
|
||||
|
||||
if (vendorLib) {
|
||||
const relativePath = `./${chunk.fileName.replace(/\\/g, '/')}`
|
||||
importMapEntries[vendorLib.name] = relativePath
|
||||
importMapEntries[source.name] =
|
||||
'./' + normalizePath(join(assetDir, moduleFile))
|
||||
|
||||
console.log(
|
||||
`[ImportMap Plugin] Found chunk: ${chunk.name} -> Mapped '${vendorLib.name}' to '${relativePath}'`
|
||||
)
|
||||
const targetDir = dirname(targetFile)
|
||||
if (!fs.existsSync(targetDir)) {
|
||||
fs.mkdirSync(targetDir, { recursive: true })
|
||||
}
|
||||
fs.copyFileSync(sourceFile, targetFile)
|
||||
}
|
||||
|
||||
if (source.recursiveDependence) {
|
||||
const files = glob.sync(['**/*.{js,mjs}'], {
|
||||
cwd: join(root, 'node_modules', source.name)
|
||||
})
|
||||
|
||||
for (const file of files) {
|
||||
const moduleFile = join(source.name, file)
|
||||
const sourceFile = join(root, 'node_modules', moduleFile)
|
||||
const targetFile = join(root, 'dist', assetDir, moduleFile)
|
||||
|
||||
importMapEntries[normalizePath(join(source.name, dirname(file)))] =
|
||||
'./' + normalizePath(join(assetDir, moduleFile))
|
||||
|
||||
const targetDir = dirname(targetFile)
|
||||
if (!fs.existsSync(targetDir)) {
|
||||
fs.mkdirSync(targetDir, { recursive: true })
|
||||
}
|
||||
fs.copyFileSync(sourceFile, targetFile)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
export { addElementVnodeExportPlugin } from './addElementVnodeExportPlugin'
|
||||
export { comfyAPIPlugin } from './comfyAPIPlugin'
|
||||
export { generateImportMapPlugin } from './generateImportMapPlugin'
|
||||
|
||||
97
src/extensions/core/apiNode.ts
Normal file
97
src/extensions/core/apiNode.ts
Normal file
@@ -0,0 +1,97 @@
|
||||
import { t } from '@/i18n'
|
||||
import { api } from '@/scripts/api'
|
||||
import { app } from '@/scripts/app'
|
||||
import { useExtensionService } from '@/services/extensionService'
|
||||
import { useToastStore } from '@/stores/toastStore'
|
||||
|
||||
useExtensionService().registerExtension({
|
||||
name: 'Comfy.FetchApi',
|
||||
|
||||
async nodeCreated(node) {
|
||||
if (node.constructor.comfyClass !== 'FetchApi') return
|
||||
|
||||
const onExecuted = node.onExecuted
|
||||
const msg = t('toastMessages.unableToFetchFile')
|
||||
|
||||
const downloadFile = async (
|
||||
typeValue: string,
|
||||
subfolderValue: string,
|
||||
filenameValue: string
|
||||
) => {
|
||||
try {
|
||||
const params = [
|
||||
'filename=' + encodeURIComponent(filenameValue),
|
||||
'type=' + encodeURIComponent(typeValue),
|
||||
'subfolder=' + encodeURIComponent(subfolderValue),
|
||||
app.getRandParam().substring(1)
|
||||
].join('&')
|
||||
|
||||
const fetchURL = `/view?${params}`
|
||||
const response = await api.fetchApi(fetchURL)
|
||||
|
||||
if (!response.ok) {
|
||||
console.error(response)
|
||||
useToastStore().addAlert(msg)
|
||||
return false
|
||||
}
|
||||
|
||||
const blob = await response.blob()
|
||||
const downloadFilename = filenameValue
|
||||
|
||||
const url = window.URL.createObjectURL(blob)
|
||||
const a = document.createElement('a')
|
||||
a.style.display = 'none'
|
||||
a.href = url
|
||||
a.download = downloadFilename
|
||||
|
||||
document.body.appendChild(a)
|
||||
a.click()
|
||||
document.body.removeChild(a)
|
||||
|
||||
window.URL.revokeObjectURL(url)
|
||||
|
||||
return true
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
useToastStore().addAlert(msg)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
const type = node.widgets?.find((w) => w.name === 'type')
|
||||
const subfolder = node.widgets?.find((w) => w.name === 'subfolder')
|
||||
const filename = node.widgets?.find((w) => w.name === 'filename')
|
||||
|
||||
node.onExecuted = function (message: any) {
|
||||
onExecuted?.apply(this, arguments as any)
|
||||
|
||||
const typeInput = message.result[0]
|
||||
const subfolderInput = message.result[1]
|
||||
const filenameInput = message.result[2]
|
||||
const autoDownload = node.widgets?.find((w) => w.name === 'auto_download')
|
||||
|
||||
if (type && subfolder && filename) {
|
||||
type.value = typeInput
|
||||
subfolder.value = subfolderInput
|
||||
filename.value = filenameInput
|
||||
|
||||
if (autoDownload && autoDownload.value) {
|
||||
downloadFile(typeInput, subfolderInput, filenameInput)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
node.addWidget('button', 'download', 'download', async () => {
|
||||
if (type && subfolder && filename) {
|
||||
await downloadFile(
|
||||
type.value as string,
|
||||
subfolder.value as string,
|
||||
filename.value as string
|
||||
)
|
||||
} else {
|
||||
console.error(msg)
|
||||
useToastStore().addAlert(msg)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
@@ -1,3 +1,4 @@
|
||||
import './apiNode'
|
||||
import './clipspace'
|
||||
import './contextMenuFilter'
|
||||
import './dynamicPrompts'
|
||||
|
||||
@@ -266,7 +266,7 @@ useExtensionService().registerExtension({
|
||||
LOAD_3D_ANIMATION(node) {
|
||||
const fileInput = document.createElement('input')
|
||||
fileInput.type = 'file'
|
||||
fileInput.accept = '.fbx,glb,gltf'
|
||||
fileInput.accept = '.gltf,.glb,.fbx'
|
||||
fileInput.style.display = 'none'
|
||||
fileInput.onchange = async () => {
|
||||
if (fileInput.files?.length) {
|
||||
@@ -452,31 +452,43 @@ useExtensionService().registerExtension({
|
||||
|
||||
const onExecuted = node.onExecuted
|
||||
|
||||
node.onExecuted = function (message: any) {
|
||||
onExecuted?.apply(this, arguments as any)
|
||||
useLoad3dService().waitForLoad3d(node, (load3d) => {
|
||||
const config = new Load3DConfiguration(load3d)
|
||||
|
||||
let filePath = message.result[0]
|
||||
const modelWidget = node.widgets?.find((w) => w.name === 'model_file')
|
||||
|
||||
if (!filePath) {
|
||||
const msg = t('toastMessages.unableToGetModelFilePath')
|
||||
console.error(msg)
|
||||
useToastStore().addAlert(msg)
|
||||
}
|
||||
if (modelWidget) {
|
||||
const lastTimeModelFile = node.properties['Last Time Model File']
|
||||
|
||||
let cameraState = message.result[1]
|
||||
if (lastTimeModelFile) {
|
||||
modelWidget.value = lastTimeModelFile
|
||||
|
||||
useLoad3dService().waitForLoad3d(node, (load3d) => {
|
||||
const modelWidget = node.widgets?.find((w) => w.name === 'model_file')
|
||||
|
||||
if (modelWidget) {
|
||||
modelWidget.value = filePath.replaceAll('\\', '/')
|
||||
|
||||
const config = new Load3DConfiguration(load3d)
|
||||
const cameraState = node.properties['Camera Info']
|
||||
|
||||
config.configure('output', modelWidget, cameraState)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
node.onExecuted = function (message: any) {
|
||||
onExecuted?.apply(this, arguments as any)
|
||||
|
||||
let filePath = message.result[0]
|
||||
|
||||
if (!filePath) {
|
||||
const msg = t('toastMessages.unableToGetModelFilePath')
|
||||
console.error(msg)
|
||||
useToastStore().addAlert(msg)
|
||||
}
|
||||
|
||||
let cameraState = message.result[1]
|
||||
|
||||
modelWidget.value = filePath.replaceAll('\\', '/')
|
||||
|
||||
node.properties['Last Time Model File'] = modelWidget.value
|
||||
|
||||
config.configure('output', modelWidget, cameraState)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
@@ -526,29 +538,42 @@ useExtensionService().registerExtension({
|
||||
|
||||
const onExecuted = node.onExecuted
|
||||
|
||||
node.onExecuted = function (message: any) {
|
||||
onExecuted?.apply(this, arguments as any)
|
||||
useLoad3dService().waitForLoad3d(node, (load3d) => {
|
||||
const config = new Load3DConfiguration(load3d)
|
||||
|
||||
let filePath = message.result[0]
|
||||
const modelWidget = node.widgets?.find((w) => w.name === 'model_file')
|
||||
|
||||
if (!filePath) {
|
||||
const msg = t('toastMessages.unableToGetModelFilePath')
|
||||
console.error(msg)
|
||||
useToastStore().addAlert(msg)
|
||||
}
|
||||
if (modelWidget) {
|
||||
const lastTimeModelFile = node.properties['Last Time Model File']
|
||||
|
||||
let cameraState = message.result[1]
|
||||
if (lastTimeModelFile) {
|
||||
modelWidget.value = lastTimeModelFile
|
||||
|
||||
useLoad3dService().waitForLoad3d(node, (load3d) => {
|
||||
const modelWidget = node.widgets?.find((w) => w.name === 'model_file')
|
||||
if (modelWidget) {
|
||||
modelWidget.value = filePath.replaceAll('\\', '/')
|
||||
|
||||
const config = new Load3DConfiguration(load3d)
|
||||
const cameraState = node.properties['Camera Info']
|
||||
|
||||
config.configure('output', modelWidget, cameraState)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
node.onExecuted = function (message: any) {
|
||||
onExecuted?.apply(this, arguments as any)
|
||||
|
||||
let filePath = message.result[0]
|
||||
|
||||
if (!filePath) {
|
||||
const msg = t('toastMessages.unableToGetModelFilePath')
|
||||
console.error(msg)
|
||||
useToastStore().addAlert(msg)
|
||||
}
|
||||
|
||||
let cameraState = message.result[1]
|
||||
|
||||
modelWidget.value = filePath.replaceAll('\\', '/')
|
||||
|
||||
node.properties['Last Time Model File'] = modelWidget.value
|
||||
|
||||
config.configure('output', modelWidget, cameraState)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
@@ -132,6 +132,14 @@ export class LoaderManager implements LoaderManagerInterface {
|
||||
if (this.modelManager.materialMode === 'original') {
|
||||
const mtlUrl = url.replace(/(filename=.*?)\.obj/, '$1.mtl')
|
||||
|
||||
const subfolderMatch = url.match(/[?&]subfolder=([^&]*)/)
|
||||
|
||||
const subfolder = subfolderMatch
|
||||
? decodeURIComponent(subfolderMatch[1])
|
||||
: '3d'
|
||||
|
||||
this.mtlLoader.setSubfolder(subfolder)
|
||||
|
||||
try {
|
||||
const materials = await this.mtlLoader.loadAsync(mtlUrl)
|
||||
materials.preload()
|
||||
|
||||
@@ -38,6 +38,10 @@ class OverrideMTLLoader extends Loader {
|
||||
this.loadRootFolder = loadRootFolder
|
||||
}
|
||||
|
||||
setSubfolder(subfolder) {
|
||||
this.subfolder = subfolder
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts loading from the given URL and passes the loaded MTL asset
|
||||
* to the `onLoad()` callback.
|
||||
@@ -135,7 +139,8 @@ class OverrideMTLLoader extends Loader {
|
||||
const materialCreator = new OverrideMaterialCreator(
|
||||
this.resourcePath || path,
|
||||
this.materialOptions,
|
||||
this.loadRootFolder
|
||||
this.loadRootFolder,
|
||||
this.subfolder
|
||||
)
|
||||
materialCreator.setCrossOrigin(this.crossOrigin)
|
||||
materialCreator.setManager(this.manager)
|
||||
@@ -155,7 +160,7 @@ class OverrideMTLLoader extends Loader {
|
||||
*/
|
||||
|
||||
class OverrideMaterialCreator {
|
||||
constructor(baseUrl = '', options = {}, loadRootFolder) {
|
||||
constructor(baseUrl = '', options = {}, loadRootFolder, subfolder) {
|
||||
this.baseUrl = baseUrl
|
||||
this.options = options
|
||||
this.materialsInfo = {}
|
||||
@@ -164,6 +169,7 @@ class OverrideMaterialCreator {
|
||||
this.nameLookup = {}
|
||||
|
||||
this.loadRootFolder = loadRootFolder
|
||||
this.subfolder = subfolder
|
||||
|
||||
this.crossOrigin = 'anonymous'
|
||||
|
||||
@@ -283,16 +289,25 @@ class OverrideMaterialCreator {
|
||||
/**
|
||||
* Override for ComfyUI api url
|
||||
*/
|
||||
function resolveURL(baseUrl, url, loadRootFolder) {
|
||||
function resolveURL(baseUrl, url, loadRootFolder, subfolder) {
|
||||
if (typeof url !== 'string' || url === '') return ''
|
||||
|
||||
if (baseUrl.endsWith('/')) {
|
||||
baseUrl = baseUrl.slice(0, -1)
|
||||
}
|
||||
|
||||
if (!baseUrl.endsWith('api')) {
|
||||
baseUrl = '/api'
|
||||
}
|
||||
|
||||
baseUrl =
|
||||
baseUrl +
|
||||
'/view?filename=' +
|
||||
url +
|
||||
'&type=' +
|
||||
loadRootFolder +
|
||||
'&subfolder=3d'
|
||||
'&subfolder=' +
|
||||
subfolder
|
||||
|
||||
return baseUrl
|
||||
}
|
||||
@@ -302,7 +317,12 @@ class OverrideMaterialCreator {
|
||||
|
||||
const texParams = scope.getTextureParams(value, params)
|
||||
const map = scope.loadTexture(
|
||||
resolveURL(scope.baseUrl, texParams.url, scope.loadRootFolder)
|
||||
resolveURL(
|
||||
scope.baseUrl,
|
||||
texParams.url,
|
||||
scope.loadRootFolder,
|
||||
scope.subfolder
|
||||
)
|
||||
)
|
||||
|
||||
map.repeat.copy(texParams.scale)
|
||||
|
||||
@@ -1273,7 +1273,8 @@
|
||||
"failedToPurchaseCredits": "Failed to purchase credits: {error}",
|
||||
"unauthorizedDomain": "Your domain {domain} is not authorized to use this service. Please contact {email} to add your domain to the whitelist.",
|
||||
"useApiKeyTip": "Tip: Can't access normal login? Use the Comfy API Key option.",
|
||||
"nothingSelected": "Nothing selected"
|
||||
"nothingSelected": "Nothing selected",
|
||||
"unableToFetchFile": "Unable to fetch file"
|
||||
},
|
||||
"auth": {
|
||||
"apiKey": {
|
||||
|
||||
@@ -1359,6 +1359,7 @@
|
||||
"pendingTasksDeleted": "Tareas pendientes eliminadas",
|
||||
"pleaseSelectNodesToGroup": "Por favor, seleccione los nodos (u otros grupos) para crear un grupo para",
|
||||
"pleaseSelectOutputNodes": "Por favor, selecciona los nodos de salida",
|
||||
"unableToFetchFile": "No se pudo obtener el archivo",
|
||||
"unableToGetModelFilePath": "No se puede obtener la ruta del archivo del modelo",
|
||||
"unauthorizedDomain": "Tu dominio {domain} no está autorizado para usar este servicio. Por favor, contacta a {email} para agregar tu dominio a la lista blanca.",
|
||||
"updateRequested": "Actualización solicitada",
|
||||
|
||||
@@ -3403,7 +3403,7 @@
|
||||
"clear": {
|
||||
},
|
||||
"height": {
|
||||
"name": "altura"
|
||||
"name": "alto"
|
||||
},
|
||||
"image": {
|
||||
"name": "imagen"
|
||||
@@ -3417,20 +3417,26 @@
|
||||
"name": "ancho"
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
{
|
||||
"outputs": {
|
||||
"0": {
|
||||
"name": "imagen"
|
||||
},
|
||||
"1": {
|
||||
"name": "mask"
|
||||
},
|
||||
"2": {
|
||||
"name": "ruta_malla"
|
||||
},
|
||||
"3": {
|
||||
"name": "normal"
|
||||
},
|
||||
{
|
||||
"4": {
|
||||
"name": "lineart"
|
||||
},
|
||||
{
|
||||
"name": "camera_info"
|
||||
"5": {
|
||||
"name": "info_cámara"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"Load3DAnimation": {
|
||||
"display_name": "Cargar 3D - Animación",
|
||||
@@ -3438,7 +3444,7 @@
|
||||
"clear": {
|
||||
},
|
||||
"height": {
|
||||
"name": "altura"
|
||||
"name": "alto"
|
||||
},
|
||||
"image": {
|
||||
"name": "imagen"
|
||||
@@ -3452,17 +3458,23 @@
|
||||
"name": "ancho"
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
{
|
||||
"outputs": {
|
||||
"0": {
|
||||
"name": "imagen"
|
||||
},
|
||||
"1": {
|
||||
"name": "mask"
|
||||
},
|
||||
"2": {
|
||||
"name": "ruta_malla"
|
||||
},
|
||||
"3": {
|
||||
"name": "normal"
|
||||
},
|
||||
{
|
||||
"name": "camera_info"
|
||||
"4": {
|
||||
"name": "info_cámara"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"LoadAudio": {
|
||||
"display_name": "CargarAudio",
|
||||
|
||||
@@ -1359,6 +1359,7 @@
|
||||
"pendingTasksDeleted": "Tâches en attente supprimées",
|
||||
"pleaseSelectNodesToGroup": "Veuillez sélectionner les nœuds (ou autres groupes) pour créer un groupe pour",
|
||||
"pleaseSelectOutputNodes": "Veuillez sélectionner les nœuds de sortie",
|
||||
"unableToFetchFile": "Impossible de récupérer le fichier",
|
||||
"unableToGetModelFilePath": "Impossible d'obtenir le chemin du fichier modèle",
|
||||
"unauthorizedDomain": "Votre domaine {domain} n'est pas autorisé à utiliser ce service. Veuillez contacter {email} pour ajouter votre domaine à la liste blanche.",
|
||||
"updateRequested": "Mise à jour demandée",
|
||||
|
||||
@@ -3417,20 +3417,26 @@
|
||||
"name": "largeur"
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
{
|
||||
"outputs": {
|
||||
"0": {
|
||||
"name": "image"
|
||||
},
|
||||
"1": {
|
||||
"name": "masque"
|
||||
},
|
||||
"2": {
|
||||
"name": "chemin_maillage"
|
||||
},
|
||||
"3": {
|
||||
"name": "normale"
|
||||
},
|
||||
{
|
||||
"name": "ligne artistique"
|
||||
"4": {
|
||||
"name": "lineart"
|
||||
},
|
||||
{
|
||||
"name": "informations caméra"
|
||||
"5": {
|
||||
"name": "info_caméra"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"Load3DAnimation": {
|
||||
"display_name": "Charger 3D - Animation",
|
||||
@@ -3452,17 +3458,23 @@
|
||||
"name": "largeur"
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
{
|
||||
"name": "normal"
|
||||
"outputs": {
|
||||
"0": {
|
||||
"name": "image"
|
||||
},
|
||||
{
|
||||
"name": "camera_info"
|
||||
"1": {
|
||||
"name": "masque"
|
||||
},
|
||||
"2": {
|
||||
"name": "chemin_maillage"
|
||||
},
|
||||
"3": {
|
||||
"name": "normale"
|
||||
},
|
||||
"4": {
|
||||
"name": "info_caméra"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"LoadAudio": {
|
||||
"display_name": "ChargerAudio",
|
||||
|
||||
@@ -1359,6 +1359,7 @@
|
||||
"pendingTasksDeleted": "保留中のタスクが削除されました",
|
||||
"pleaseSelectNodesToGroup": "グループを作成するためのノード(または他のグループ)を選択してください",
|
||||
"pleaseSelectOutputNodes": "出力ノードを選択してください",
|
||||
"unableToFetchFile": "ファイルを取得できません",
|
||||
"unableToGetModelFilePath": "モデルファイルのパスを取得できません",
|
||||
"unauthorizedDomain": "あなたのドメイン {domain} はこのサービスを利用する権限がありません。ご利用のドメインをホワイトリストに追加するには、{email} までご連絡ください。",
|
||||
"updateRequested": "更新が要求されました",
|
||||
|
||||
@@ -3417,23 +3417,29 @@
|
||||
"name": "幅"
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
{
|
||||
"outputs": {
|
||||
"0": {
|
||||
"name": "画像"
|
||||
},
|
||||
"1": {
|
||||
"name": "マスク"
|
||||
},
|
||||
"2": {
|
||||
"name": "メッシュパス"
|
||||
},
|
||||
"3": {
|
||||
"name": "法線"
|
||||
},
|
||||
{
|
||||
"4": {
|
||||
"name": "線画"
|
||||
},
|
||||
{
|
||||
"5": {
|
||||
"name": "カメラ情報"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"Load3DAnimation": {
|
||||
"display_name": "3Dを読み込む - アニメーション",
|
||||
"display_name": "3D読み込み - アニメーション",
|
||||
"inputs": {
|
||||
"clear": {
|
||||
},
|
||||
@@ -3452,17 +3458,23 @@
|
||||
"name": "幅"
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
{
|
||||
"outputs": {
|
||||
"0": {
|
||||
"name": "画像"
|
||||
},
|
||||
"1": {
|
||||
"name": "マスク"
|
||||
},
|
||||
"2": {
|
||||
"name": "メッシュパス"
|
||||
},
|
||||
"3": {
|
||||
"name": "法線"
|
||||
},
|
||||
{
|
||||
"4": {
|
||||
"name": "カメラ情報"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"LoadAudio": {
|
||||
"display_name": "音声を読み込む",
|
||||
|
||||
@@ -1359,6 +1359,7 @@
|
||||
"pendingTasksDeleted": "보류 중인 작업이 삭제되었습니다",
|
||||
"pleaseSelectNodesToGroup": "그룹을 만들기 위해 노드(또는 다른 그룹)를 선택해 주세요",
|
||||
"pleaseSelectOutputNodes": "출력 노드를 선택해 주세요",
|
||||
"unableToFetchFile": "파일을 가져올 수 없습니다",
|
||||
"unableToGetModelFilePath": "모델 파일 경로를 가져올 수 없습니다",
|
||||
"unauthorizedDomain": "귀하의 도메인 {domain}은(는) 이 서비스를 사용할 수 있는 권한이 없습니다. 도메인을 허용 목록에 추가하려면 {email}로 문의해 주세요.",
|
||||
"updateRequested": "업데이트 요청됨",
|
||||
|
||||
@@ -3398,7 +3398,7 @@
|
||||
}
|
||||
},
|
||||
"Load3D": {
|
||||
"display_name": "3D 로드",
|
||||
"display_name": "3D 불러오기",
|
||||
"inputs": {
|
||||
"clear": {
|
||||
},
|
||||
@@ -3417,23 +3417,29 @@
|
||||
"name": "너비"
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
{
|
||||
"outputs": {
|
||||
"0": {
|
||||
"name": "이미지"
|
||||
},
|
||||
"1": {
|
||||
"name": "마스크"
|
||||
},
|
||||
"2": {
|
||||
"name": "메시 경로"
|
||||
},
|
||||
"3": {
|
||||
"name": "노멀"
|
||||
},
|
||||
{
|
||||
"4": {
|
||||
"name": "라인아트"
|
||||
},
|
||||
{
|
||||
"5": {
|
||||
"name": "카메라 정보"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"Load3DAnimation": {
|
||||
"display_name": "3D 로드 - 애니메이션",
|
||||
"display_name": "3D 불러오기 - 애니메이션",
|
||||
"inputs": {
|
||||
"clear": {
|
||||
},
|
||||
@@ -3452,17 +3458,23 @@
|
||||
"name": "너비"
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
{
|
||||
"outputs": {
|
||||
"0": {
|
||||
"name": "이미지"
|
||||
},
|
||||
"1": {
|
||||
"name": "마스크"
|
||||
},
|
||||
"2": {
|
||||
"name": "메시 경로"
|
||||
},
|
||||
"3": {
|
||||
"name": "노멀"
|
||||
},
|
||||
{
|
||||
"4": {
|
||||
"name": "카메라 정보"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"LoadAudio": {
|
||||
"display_name": "오디오 로드",
|
||||
|
||||
@@ -1359,6 +1359,7 @@
|
||||
"pendingTasksDeleted": "Ожидающие задачи удалены",
|
||||
"pleaseSelectNodesToGroup": "Пожалуйста, выберите узлы (или другие группы) для создания группы",
|
||||
"pleaseSelectOutputNodes": "Пожалуйста, выберите выходные узлы",
|
||||
"unableToFetchFile": "Не удалось получить файл",
|
||||
"unableToGetModelFilePath": "Не удалось получить путь к файлу модели",
|
||||
"unauthorizedDomain": "Ваш домен {domain} не авторизован для использования этого сервиса. Пожалуйста, свяжитесь с {email}, чтобы добавить ваш домен в белый список.",
|
||||
"updateRequested": "Запрошено обновление",
|
||||
|
||||
@@ -3409,7 +3409,7 @@
|
||||
"name": "изображение"
|
||||
},
|
||||
"model_file": {
|
||||
"name": "файл_модели"
|
||||
"name": "файл модели"
|
||||
},
|
||||
"upload 3d model": {
|
||||
},
|
||||
@@ -3417,23 +3417,29 @@
|
||||
"name": "ширина"
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
{
|
||||
"outputs": {
|
||||
"0": {
|
||||
"name": "изображение"
|
||||
},
|
||||
"1": {
|
||||
"name": "mask"
|
||||
},
|
||||
"2": {
|
||||
"name": "путь к mesh"
|
||||
},
|
||||
"3": {
|
||||
"name": "нормаль"
|
||||
},
|
||||
{
|
||||
"name": "линеарт"
|
||||
"4": {
|
||||
"name": "линейный рисунок"
|
||||
},
|
||||
{
|
||||
"name": "информация_камеры"
|
||||
"5": {
|
||||
"name": "информация о камере"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"Load3DAnimation": {
|
||||
"display_name": "Загрузить 3D — Анимация",
|
||||
"display_name": "Загрузить 3D - Анимация",
|
||||
"inputs": {
|
||||
"clear": {
|
||||
},
|
||||
@@ -3452,17 +3458,23 @@
|
||||
"name": "ширина"
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
{
|
||||
"outputs": {
|
||||
"0": {
|
||||
"name": "изображение"
|
||||
},
|
||||
"1": {
|
||||
"name": "mask"
|
||||
},
|
||||
"2": {
|
||||
"name": "путь_к_модели"
|
||||
},
|
||||
"3": {
|
||||
"name": "нормаль"
|
||||
},
|
||||
{
|
||||
"name": "информация_камеры"
|
||||
"4": {
|
||||
"name": "информация_о_камере"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"LoadAudio": {
|
||||
"display_name": "Загрузить аудио",
|
||||
|
||||
@@ -1359,6 +1359,7 @@
|
||||
"pendingTasksDeleted": "待处理任务已删除",
|
||||
"pleaseSelectNodesToGroup": "请选取节点(或其他组)以创建分组",
|
||||
"pleaseSelectOutputNodes": "请选择输出节点",
|
||||
"unableToFetchFile": "无法获取文件",
|
||||
"unableToGetModelFilePath": "无法获取模型文件路径",
|
||||
"unauthorizedDomain": "您的域名 {domain} 未被授权使用此服务。请联系 {email} 将您的域名添加到白名单。",
|
||||
"updateRequested": "已请求更新",
|
||||
|
||||
@@ -3417,20 +3417,26 @@
|
||||
"name": "宽度"
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
{
|
||||
"name": "法线"
|
||||
"outputs": {
|
||||
"0": {
|
||||
"name": "image"
|
||||
},
|
||||
{
|
||||
"name": "线稿"
|
||||
"1": {
|
||||
"name": "mask"
|
||||
},
|
||||
{
|
||||
"name": "相机信息"
|
||||
"2": {
|
||||
"name": "mesh_path"
|
||||
},
|
||||
"3": {
|
||||
"name": "normal"
|
||||
},
|
||||
"4": {
|
||||
"name": "lineart"
|
||||
},
|
||||
"5": {
|
||||
"name": "camera_info"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"Load3DAnimation": {
|
||||
"display_name": "加载3D动画",
|
||||
@@ -3452,17 +3458,23 @@
|
||||
"name": "宽度"
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
{
|
||||
"outputs": {
|
||||
"0": {
|
||||
"name": "图像"
|
||||
},
|
||||
"1": {
|
||||
"name": "遮罩"
|
||||
},
|
||||
"2": {
|
||||
"name": "mesh_path"
|
||||
},
|
||||
"3": {
|
||||
"name": "法线"
|
||||
},
|
||||
{
|
||||
"4": {
|
||||
"name": "相机信息"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"LoadAudio": {
|
||||
"display_name": "加载音频",
|
||||
|
||||
@@ -8,11 +8,7 @@ import { createHtmlPlugin } from 'vite-plugin-html'
|
||||
import vueDevTools from 'vite-plugin-vue-devtools'
|
||||
import type { UserConfigExport } from 'vitest/config'
|
||||
|
||||
import {
|
||||
addElementVnodeExportPlugin,
|
||||
comfyAPIPlugin,
|
||||
generateImportMapPlugin
|
||||
} from './build/plugins'
|
||||
import { comfyAPIPlugin, generateImportMapPlugin } from './build/plugins'
|
||||
|
||||
dotenv.config()
|
||||
|
||||
@@ -77,11 +73,40 @@ export default defineConfig({
|
||||
: [vue()]),
|
||||
comfyAPIPlugin(IS_DEV),
|
||||
generateImportMapPlugin([
|
||||
{ name: 'vue', pattern: /[\\/]node_modules[\\/]vue[\\/]/ },
|
||||
{ name: 'primevue', pattern: /[\\/]node_modules[\\/]primevue[\\/]/ },
|
||||
{ name: 'vue-i18n', pattern: /[\\/]node_modules[\\/]vue-i18n[\\/]/ }
|
||||
{
|
||||
name: 'vue',
|
||||
pattern: 'vue',
|
||||
entry: './dist/vue.esm-browser.prod.js'
|
||||
},
|
||||
{
|
||||
name: 'vue-i18n',
|
||||
pattern: 'vue-i18n',
|
||||
entry: './dist/vue-i18n.esm-browser.prod.js'
|
||||
},
|
||||
{
|
||||
name: 'primevue',
|
||||
pattern: /^primevue\/?.*/,
|
||||
entry: './index.mjs',
|
||||
recursiveDependence: true
|
||||
},
|
||||
{
|
||||
name: '@primevue/themes',
|
||||
pattern: /^@primevue\/themes\/?.*/,
|
||||
entry: './index.mjs',
|
||||
recursiveDependence: true
|
||||
},
|
||||
{
|
||||
name: '@primevue/forms',
|
||||
pattern: /^@primevue\/forms\/?.*/,
|
||||
entry: './index.mjs',
|
||||
recursiveDependence: true,
|
||||
override: {
|
||||
'@primeuix/forms': {
|
||||
entry: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
]),
|
||||
addElementVnodeExportPlugin(),
|
||||
|
||||
Icons({
|
||||
compiler: 'vue3'
|
||||
|
||||
Reference in New Issue
Block a user