File size: 3,689 Bytes
c6535db
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
/**
 * Generates a RFC4122 compliant UUID v4 using the native crypto API when available
 * @returns {string} A properly formatted UUID string
 */
export const generateUUID = () => {
    // Use native crypto.randomUUID() if available (modern browsers)
    if (
        typeof crypto !== 'undefined' &&
        typeof crypto.randomUUID === 'function'
    ) {
        return crypto.randomUUID()
    }

    // Fallback implementation for older browsers
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
        const r = (Math.random() * 16) | 0
        const v = c === 'x' ? r : (r & 0x3) | 0x8
        return v.toString(16)
    })
}

const hasAnnotation = (filepath) =>
    /\[(input|output|temp)\]/i.test(filepath)

const createAnnotation = (filepath, rootFolder = 'input') =>
    !hasAnnotation(filepath) && rootFolder !== 'input' ? ` [${rootFolder}]` : ''

const createPath = (filename, subfolder = '') =>
    subfolder ? `${subfolder}/${filename}` : filename

/** Creates annotated filepath in format used by folder_paths.py */
export function createAnnotatedPath(
    item,
    options = {}
) {
    const { rootFolder = 'input', subfolder } = options
    if (typeof item === 'string')
        return `${createPath(item, subfolder)}${createAnnotation(item, rootFolder)}`
    return `${createPath(item.filename ?? '', item.subfolder)}${
        item.type ? createAnnotation(item.type, rootFolder) : ''
    }`
}

/**
 * Parses a filepath into its filename and subfolder components.
 *
 * @example
 * parseFilePath('folder/file.txt')    // → { filename: 'file.txt', subfolder: 'folder' }
 * parseFilePath('/folder/file.txt')   // → { filename: 'file.txt', subfolder: 'folder' }
 * parseFilePath('file.txt')           // → { filename: 'file.txt', subfolder: '' }
 * parseFilePath('folder//file.txt')   // → { filename: 'file.txt', subfolder: 'folder' }
 *
 * @param filepath The filepath to parse
 * @returns Object containing filename and subfolder
 */
export function parseFilePath(filepath) {
        if (!filepath?.trim()) return { filename: '', subfolder: '' }

        const normalizedPath = filepath
            .replace(/[\\/]+/g, '/') // Normalize path separators
            .replace(/^\//, '') // Remove leading slash
            .replace(/\/$/, '') // Remove trailing slash

        const lastSlashIndex = normalizedPath.lastIndexOf('/')

        if (lastSlashIndex === -1) {
            return {
                filename: normalizedPath,
                subfolder: ''
            }
        }

        return {
            filename: normalizedPath.slice(lastSlashIndex + 1),
            subfolder: normalizedPath.slice(0, lastSlashIndex)
        }
    }

export function useValueTransform(
    transform,
    initialValue
) {
    let internalValue = initialValue
    let cachedValue = transform(initialValue)
    let isChanged = false

    return {
        get: () => {
            if (!isChanged) return cachedValue
            cachedValue = transform(internalValue)
            return cachedValue
        },
        set: (value) => {
            isChanged = true
            internalValue = value
        }
    }
}

export function isBase64(str) {
    // 移除可能的Data URL前缀
    const base64String = str.replace(/^data:image\/\w+;base64,/, '');

    // Base64正则表达式
    const base64Regex = /^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)?$/;

    // 检查长度是否为4的倍数且符合Base64字符集
    return base64String.length % 4 === 0 && base64Regex.test(base64String);
}

export const isURL = str => {
    if (!str) return false;
    return str.startsWith('http://') || str.startsWith('https://');
}