UNPKG

sd-wildcards-utils

Version:

Parse Stable Diffusion wildcards source to a YAML object.

1,027 lines (1,013 loc) 39.7 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('yaml'), require('array-hyper-unique'), require('@bluelovers/extract-brackets'), require('lazy-aggregate-error'), require('picomatch')) : typeof define === 'function' && define.amd ? define(['exports', 'yaml', 'array-hyper-unique', '@bluelovers/extract-brackets', 'lazy-aggregate-error', 'picomatch'], factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.SdWildcardsUtils = {}, global.yaml, global.arrayHyperUnique, global.extractBrackets, global.lazyAggregateError, global.picomatch)); })(this, (function (exports, yaml, arrayHyperUnique, extractBrackets, lazyAggregateError, picomatch) { 'use strict'; function getOptionsShared(opts) { var _opts; (_opts = opts) !== null && _opts !== void 0 ? _opts : opts = {}; return { allowMultiRoot: opts.allowMultiRoot, disableUniqueItemValues: opts.disableUniqueItemValues, minifyPrompts: opts.minifyPrompts, disableUnsafeQuote: opts.disableUnsafeQuote }; } function defaultOptionsStringifyMinify() { return { lineWidth: 0, minifyPrompts: true }; } function defaultOptionsStringify(opts) { return { blockQuote: true, defaultKeyType: 'PLAIN', defaultStringType: 'PLAIN', collectionStyle: 'block', uniqueKeys: true, ...opts }; } function defaultOptionsParseDocument(opts) { var _opts2; (_opts2 = opts) !== null && _opts2 !== void 0 ? _opts2 : opts = {}; opts = { prettyErrors: true, ...opts, toStringDefaults: defaultOptionsStringify({ ...getOptionsShared(opts), ...opts.toStringDefaults }) }; return opts; } function getOptionsFromDocument(doc, opts) { return { ...doc.options, ...opts }; } let ExtractParents; function stripZeroStr(value) { return value.replace(/[\x00\u200b]+/g, ''); } function trimPrompts(value) { return value.replace(/\xa0/g, ' ').replace(/^\s+|\s+$/g, '').replace(/^\s+|\s+$/gm, '').replace(/\n\s*\n/g, '\n').replace(/\s{2,}/gm, ' ').replace(/,\s{2,}/gm, ', ').replace(/\s+,/gm, ',').replace(/,+\s*$/g, ''); } function normalizeWildcardsYamlString(value) { value = stripZeroStr(value).replace(/\xa0/g, ' ').replace(/[,.]+(?=,)/gm, '').replace(/[ .]+$/gm, '').replace(/(\w) +(?=,)/gm, '$1').replace(/(,) {2,}(?=\S)/gm, '$1 ').replace(/\{\s+(\d+(?:\.\d+)?(?:-(?:\d+(?:\.\d+)?)?\$\$|::))/gm, '{$1').replace(/\|\s(\d+(?:\.\d+)?::)/gm, '|$1').replace(/^[ \t]+-[ \t]*$/gm, '').replace(/^([ \t]+-)[ \t]{1,}(?:[ ,.]+|(?=[^ \t]))/gm, '$1 '); return value; } function trimPromptsDynamic(value) { if (value.includes('=')) { var _ExtractParents; (_ExtractParents = ExtractParents) !== null && _ExtractParents !== void 0 ? _ExtractParents : ExtractParents = new extractBrackets.Extractor('{', '}'); const ebs = ExtractParents.extract(value); let i = 0; let _do; let arr = ebs.reduce((a, eb) => { let s = typeof eb.nest[0] === 'string' && eb.nest[0]; let input = eb.str; let pre = value.slice(i, eb.index[0]); if (_do) { pre = pre.replace(/^[\s\r\n]+/g, ''); } _do = s === null || s === void 0 ? void 0 : s.includes('='); if (_do) { input = input.replace(/^\s*([\w_]+)\s*=\s*/, '$1='); } a.push(pre); a.push('{' + input.trim() + '}'); i = eb.index[0] + eb.str.length + 2; return a; }, []); let pre = value.slice(i); if (_do) { pre = pre.replace(/[\s\r\n]+$|^[\s\r\n]+/g, ''); } arr.push(pre); value = arr.join(''); } return value; } function formatPrompts(value, opts) { var _opts; (_opts = opts) !== null && _opts !== void 0 ? _opts : opts = {}; value = stripZeroStr(value); value = trimPrompts(value); value = normalizeWildcardsYamlString(value); if (opts.minifyPrompts) { value = value.replace(/(,)\s+/gm, '$1').replace(/\s+(,)/gm, '$1').replace(/(?<=,\|})\s+/gm, '').replace(/\s+(?=\{(?:\s*\d+(?:\.\d+)?::)?,)/gm, ''); value = trimPromptsDynamic(value); } return value; } function stripBlankLines(value, appendEOF) { value = value.replace(/(\r?\n)[\s\r\n\t\xa0]+(\r?\n)/g, '$1$2').replace(/(\r?\n)(?:\r?\n)(?=[\s\t\xa0])/g, '$1').replace(/[ \xa0\t]+$/gm, ''); if (appendEOF) { value = value.replace(/\s+$/, ''); value += '\n\n'; } return value; } function isWildcardsYAMLDocument(doc) { return yaml.isDocument(doc); } function isWildcardsYAMLDocumentAndContentsIsMap(doc) { return yaml.isDocument(doc) && yaml.isMap(doc.contents); } function isWildcardsYAMLMap(doc) { return yaml.isMap(doc); } const SYMBOL_YAML_NODE_TYPE_ALIAS = /*#__PURE__*/Symbol.for('yaml.alias'); const SYMBOL_YAML_NODE_TYPE_DOC = /*#__PURE__*/Symbol.for('yaml.document'); const SYMBOL_YAML_NODE_TYPE_MAP = /*#__PURE__*/Symbol.for('yaml.map'); const SYMBOL_YAML_NODE_TYPE_PAIR = /*#__PURE__*/Symbol.for('yaml.pair'); const SYMBOL_YAML_NODE_TYPE_SCALAR = /*#__PURE__*/Symbol.for('yaml.scalar'); const SYMBOL_YAML_NODE_TYPE_SEQ = /*#__PURE__*/Symbol.for('yaml.seq'); const SYMBOL_YAML_NODE_TYPE = /*#__PURE__*/Symbol.for('yaml.node.type'); const RE_DYNAMIC_PROMPTS_WILDCARDS = /(?<!#[^\n]*)__([&~!@])?([\w*](?:[*\w\/_\-]+?))(\([^\n#]+\))?__/; const RE_DYNAMIC_PROMPTS_WILDCARDS_UNSAFE = /(?<!#[^\n]*)__([&~!@])?([\w*](?:[*\w\/_\-\s]+?))(\([^\n#]+\))?__/; /** * for `matchAll` * * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/matchAll */ const RE_DYNAMIC_PROMPTS_WILDCARDS_GLOBAL = /*#__PURE__*/new RegExp(RE_DYNAMIC_PROMPTS_WILDCARDS, RE_DYNAMIC_PROMPTS_WILDCARDS.flags + 'g'); const RE_DYNAMIC_PROMPTS_WILDCARDS_UNSAFE_GLOBAL = /*#__PURE__*/new RegExp(RE_DYNAMIC_PROMPTS_WILDCARDS_UNSAFE, RE_DYNAMIC_PROMPTS_WILDCARDS_UNSAFE.flags + 'g'); const RE_WILDCARDS_NAME = /^[\w\-_\/]+$/; const RE_WILDCARDS_NAME_STAR = /^[\w\-_\/*]+$/; /** * Checks if the input string matches the dynamic prompts wildcards pattern. * * @param input - The input string to check. * @returns A boolean indicating whether the input string matches the pattern. * * @remarks * This function uses the `matchDynamicPromptsWildcards` function to perform the check. * It returns `true` if the input string is a full match, and `false` otherwise. * * @example * ```typescript * const input1 = "__season_clothes(season=winter)__"; * console.log(isDynamicPromptsWildcards(input1)); // Output: true * * const input2 = "__season_clothes(season=__season_clothes__)__"; * console.log(isDynamicPromptsWildcards(input2)); // Output: true * * const input3 = "This is not a wildcards pattern"; * console.log(isDynamicPromptsWildcards(input3)); // Output: false * ``` */ function isDynamicPromptsWildcards(input) { return matchDynamicPromptsWildcards(input).isFullMatch; } /** * Matches the input string against the dynamic prompts wildcards pattern. * * @see https://github.com/adieyal/sd-dynamic-prompts/blob/main/docs/SYNTAX.md * * @param input - The input string to match. * @returns An object containing the matched groups or `null` if no match is found. * * @remarks * This function uses the `RE_DYNAMIC_PROMPTS_WILDCARDS` regular expression to perform the match. * The returned object contains the following properties: * - `name`: The name extracted from the input string. * - `variables`: The variables extracted from the input string. * - `keyword`: The keyword extracted from the input string. * - `source`: The original matched source string. * - `isFullMatch`: A boolean indicating whether the input string is a full match. * * @example * ```typescript * const input = "\_\_season_clothes(season=winter)\_\_"; * const result = matchDynamicPromptsWildcards(input); * console.log(result); * // Output: { name: 'season_clothes', variables: '(season=winter)', keyword: undefined, source: '\__season_clothes(season=winter)\__', isFullMatch: true } * ``` * * @example * __season_clothes(season=winter)__ * __season_clothes(season=__season_clothes__)__ * __season_clothes(season=!__season_clothes__)__ * * __season_clothes(season=__@season_clothes__)__ * __season_clothes(season=__~season_clothes__)__ * * __@season_clothes(season=__season_clothes__)__ * __~season_clothes(season=__season_clothes__)__ * * __season_clothes(season={summer|autumn|winter|spring})__ * __season_clothes(season=!{summer|autumn|winter|spring})__ * * __season_clothes(season={@summer|autumn|winter|spring})__ * __season_clothes(season={!summer|autumn|winter|spring})__ * * __season_clothes(season=)__ */ function matchDynamicPromptsWildcards(input, opts) { const m = input.match(opts !== null && opts !== void 0 && opts.unsafe ? RE_DYNAMIC_PROMPTS_WILDCARDS_UNSAFE : RE_DYNAMIC_PROMPTS_WILDCARDS); return _matchDynamicPromptsWildcardsCore(m, input); } function _matchDynamicPromptsWildcardsCore(m, input) { if (!m) return null; let [source, keyword, name, variables] = m; return { name, variables, keyword, source, isFullMatch: source === (input !== null && input !== void 0 ? input : m.input), isStarWildcards: name.includes('*') }; } function* matchDynamicPromptsWildcardsAllGenerator(input, opts) { const ls = input.matchAll(opts !== null && opts !== void 0 && opts.unsafe ? RE_DYNAMIC_PROMPTS_WILDCARDS_UNSAFE_GLOBAL : RE_DYNAMIC_PROMPTS_WILDCARDS_GLOBAL); for (let m of ls) { yield _matchDynamicPromptsWildcardsCore(m, input); } } function matchDynamicPromptsWildcardsAll(input, opts) { const arr = [...matchDynamicPromptsWildcardsAllGenerator(input, opts)]; return opts !== null && opts !== void 0 && opts.unique ? arrayHyperUnique.array_unique_overwrite(arr) : arr; } /** * Checks if the given name is a valid Wildcards name. * * @param name - The name to check. * @returns A boolean indicating whether the name is valid. * * @remarks * A valid Wildcards name should: * - Only contain alphanumeric characters, hyphens, or underscores. * - Not start or end with an underscore. * - Not contain consecutive underscores. * * @example * ```typescript * const name1 = "season_clothes"; * console.log(isWildcardsName(name1)); // Output: true * * const name2 = "_season_clothes"; * console.log(isWildcardsName(name2)); // Output: false * * const name3 = "season_clothes_"; * console.log(isWildcardsName(name3)); // Output: false * * const name4 = "season__clothes"; * console.log(isWildcardsName(name4)); // Output: false * * const name5 = "season-clothes"; * console.log(isWildcardsName(name5)); // Output: true * ``` */ function isWildcardsName(name) { return RE_WILDCARDS_NAME.test(name) && !_isBadWildcardsNameCore(name); } function isBadWildcardsName(name) { return !RE_WILDCARDS_NAME.test(name) || _isBadWildcardsNameCore(name); } function isBadWildcardsPath(name) { return !RE_WILDCARDS_NAME_STAR.test(name) || _isBadWildcardsNameCore(name); } function _isBadWildcardsNameCore(name) { return /^[\s_\/\\-]|[\s_\/\\-]$|[\s_\/\\-]\/|\/[\s_\/\\-]|\/\/|[\s_\/\\-]{2,}/.test(name); } function assertWildcardsName(name) { if (isBadWildcardsName(name)) { throw new SyntaxError(`Invalid Wildcards Name Syntax: ${name}`); } } function assertWildcardsPath(name) { if (isBadWildcardsPath(name)) { throw new SyntaxError(`Invalid Paths Syntax [UNSAFE_SYNTAX] "${name}"`); } } function convertWildcardsNameToPaths(name) { return name.split('/'); } function isWildcardsPathSyntx(path) { return RE_DYNAMIC_PROMPTS_WILDCARDS.test(path); } function wildcardsPathToPaths(path) { if (isWildcardsPathSyntx(path)) { path = matchDynamicPromptsWildcards(path).name; } return convertWildcardsNameToPaths(path); } function getNodeTypeSymbol(node) { // @ts-ignore return node === null || node === void 0 ? void 0 : node[SYMBOL_YAML_NODE_TYPE]; } function _getNodeTypeCore(sym) { try { return Symbol.keyFor(sym); } catch (e) {} } function getNodeType(node) { return _getNodeTypeCore(getNodeTypeSymbol(node)); } function isSameNodeType(a, b) { const s = getNodeTypeSymbol(a); return s && getNodeTypeSymbol(b) === s; } let _extractor; function _checkBrackets(value) { var _extractor2; (_extractor2 = _extractor) !== null && _extractor2 !== void 0 ? _extractor2 : _extractor = new extractBrackets.Extractor('{', '}'); return _extractor.extractSync(value, e => { if (e) { var _e$self, _result$index; let result = (_e$self = e.self) === null || _e$self === void 0 ? void 0 : _e$self.result; if (!result) { return { value, error: `Invalid Error [UNKNOWN]: ${e}` }; } let near = extractBrackets.infoNearExtractionError(value, e.self); return { value, index: (_result$index = result.index) === null || _result$index === void 0 ? void 0 : _result$index[0], near, error: `Invalid Syntax [BRACKET] ${e.message} near "${near}"` }; } }); } // @ts-ignore function _validMap(key, node, ...args) { const idx = node.items.findIndex(pair => !yaml.isPair(pair) || (pair === null || pair === void 0 ? void 0 : pair.value) == null); if (idx !== -1) { // @ts-ignore const paths = handleVisitPathsFull(key, node, ...args); const elem = node.items[idx]; throw new SyntaxError(`Invalid SYNTAX. paths: [${paths}], key: ${key}, node: ${node}, elem: ${elem}`); } } // @ts-ignore function _validSeq(key, nodeSeq, ...args) { for (const index in nodeSeq.items) { const entry = nodeSeq.items[index]; if (!yaml.isScalar(entry)) { // @ts-ignore const paths = handleVisitPathsFull(key, nodeSeq, ...args); throw new SyntaxError(`Invalid SYNTAX. entry type should be 'Scalar', but got '${getNodeType(entry)}'. paths: [${paths}], entryIndex: ${index}, entry: ${entry}, nodeKey: ${key}, node: ${nodeSeq}`); } } } function _validPair(key, pair, ...args) { const keyNode = pair.key; const notOk = !isSafeKey(typeof keyNode === 'string' ? keyNode : keyNode.value); if (notOk) { // @ts-ignore const paths = handleVisitPathsFull(key, pair, ...args); throw new SyntaxError(`Invalid Key. paths: [${paths}], key: ${key}, keyNodeValue: "${keyNode === null || keyNode === void 0 ? void 0 : keyNode.value}", keyNode: ${keyNode}`); } } function createDefaultVisitWildcardsYAMLOptions(opts) { var _opts; let defaults = { Map: _validMap, Seq: _validSeq }; (_opts = opts) !== null && _opts !== void 0 ? _opts : opts = {}; if (!opts.allowUnsafeKey) { defaults.Pair = _validPair; } if (!opts.disableUniqueItemValues) { const fn = defaults.Seq; defaults.Seq = (key, node, ...args) => { // @ts-ignore fn(key, node, ...args); uniqueSeqItems(node.items); }; } return defaults; } function validWildcardsYamlData(data, opts) { var _opts2; (_opts2 = opts) !== null && _opts2 !== void 0 ? _opts2 : opts = {}; if (yaml.isDocument(data)) { if (yaml.isNode(data.contents) && !yaml.isMap(data.contents)) { throw TypeError(`The 'contents' property of the provided YAML document must be a YAMLMap. Received: ${data.contents}`); } visitWildcardsYAML(data, createDefaultVisitWildcardsYAMLOptions(opts)); data = data.toJSON(); } if (typeof data === 'undefined' || data === null) { if (opts.allowEmptyDocument) { return; } throw new TypeError(`The provided JSON contents should not be empty. ${data}`); } let rootKeys = Object.keys(data); if (!rootKeys.length) { throw TypeError(`The provided JSON contents must contain at least one key.`); } else if (rootKeys.length !== 1 && !opts.allowMultiRoot) { throw TypeError(`The provided JSON object cannot have more than one root key. Only one root key is allowed unless explicitly allowed by the 'allowMultiRoot' option.`); } } function isSafeKey(key) { return typeof key === 'string' && /^[._\w-]+$/.test(key) && !/^[\._-]|[\._-]$/.test(key); } function _validKey(key) { if (!isSafeKey(key)) { throw new SyntaxError(`Invalid Key. key: ${key}`); } } function _checkValue(value) { let m = /(?:^|[\s{},])_(?=[^_]|$)|(?<!_)_(?:[\s{},]|$)|\/_+|_+\/(?!\()|\([\w_]+\s*=(?:!|\s*[{}$])/.exec(value); if (m) { let near = _nearString(value, m.index, m[0]); let match = m[0]; return { value, match, index: m.index, near, error: `Invalid Syntax [UNSAFE_SYNTAX] "${match}" in value near "${near}"` }; } else if (/[{}]/.test(value)) { return _checkBrackets(value); } } function _nearString(value, index, match, offset = 15) { let s = Math.max(0, index - offset); let e = index + ((match === null || match === void 0 ? void 0 : match.length) || 0) + offset; return value.slice(s, e); } function visitWildcardsYAML(node, visitorOptions) { return yaml.visit(node, visitorOptions); } function defaultCheckerIgnoreCase(a, b) { if (typeof a === 'string' && typeof b === 'string') { a = a.toLowerCase(); b = b.toLowerCase(); } return arrayHyperUnique.defaultChecker(a, b); } function uniqueSeqItemsChecker(a, b) { if (yaml.isScalar(a) && yaml.isScalar(b)) { return defaultCheckerIgnoreCase(a.value, b.value); } return defaultCheckerIgnoreCase(a, b); } function uniqueSeqItems(items) { return arrayHyperUnique.array_unique_overwrite(items, { // @ts-ignore checker: uniqueSeqItemsChecker }); } /** * This function is used to find a single root node in a YAML structure. * It traverses the YAML structure and returns the first node that has only one child. * If the node is a Document, it will start from its contents. * * @param node - The YAML node to start the search from. * @param result - An optional object to store the result. * @returns - An object containing the paths, key, value, and parent of the found single root node. * If no single root node is found, it returns the input `result` object. * @throws - Throws a TypeError if the Document Node is passed as a child node. */ function deepFindSingleRootAt(node, result) { if (yaml.isMap(node) && node.items.length === 1) { var _result$paths$slice, _result$paths; let child = node.items[0]; let key = child.key.value; let paths = (_result$paths$slice = result === null || result === void 0 || (_result$paths = result.paths) === null || _result$paths === void 0 ? void 0 : _result$paths.slice()) !== null && _result$paths$slice !== void 0 ? _result$paths$slice : []; paths.push(key); let value = child.value; if (yaml.isSeq(value)) { return result; } return deepFindSingleRootAt(value, { paths, key, value, parent: node }); } else if (yaml.isDocument(node)) { if (result) { throw new TypeError(`The Document Node should not as Child Node`); } let value = node.contents; return deepFindSingleRootAt(value, { paths: [], key: void 0, value, parent: node }); } return result; } function _handleVisitPathsCore(nodePaths) { return nodePaths.filter(p => yaml.isPair(p)); } function convertPairsToPathsList(nodePaths) { return nodePaths.map(p => p.key.value); } function handleVisitPaths(nodePaths) { return convertPairsToPathsList(_handleVisitPathsCore(nodePaths)); } function handleVisitPathsFull(key, _node, nodePaths) { const paths = handleVisitPaths(nodePaths); if (typeof key === 'number') { paths.push(key); } return paths; } /** * This function is used to find all paths of sequences in a given YAML structure. * It traverses the YAML structure and collects the paths of all sequences (Seq nodes). * * @param node - The YAML node to start the search from. It can be a Node, Document. * @returns - An array of arrays, where each inner array represents a path of sequence nodes. * Each path is represented as an array of paths, where each path is a key or index. */ function findWildcardsYAMLPathsAll(node) { const ls = []; visitWildcardsYAML(node, { Seq(...args) { const paths = handleVisitPathsFull(...args); ls.push(paths); } }); return ls; } const RE_UNSAFE_QUOTE = /['"]/; const RE_UNSAFE_VALUE = /^\s*-|[{$~!@}\n|:?#'"%]/; const RE_UNSAFE_PLAIN = /-/; function _visitNormalizeScalar(key, node, runtime) { let value = node.value; if (typeof value === 'string') { if (runtime.checkUnsafeQuote && RE_UNSAFE_QUOTE.test(value)) { throw new SyntaxError(`Invalid SYNTAX [UNSAFE_QUOTE]. key: ${key}, node: ${node}`); } else if (node.type === 'QUOTE_DOUBLE' || node.type === 'QUOTE_SINGLE' && !value.includes('\\')) { node.type = 'PLAIN'; } value = formatPrompts(value, runtime.options); if (!value.length) { throw new SyntaxError(`Invalid SYNTAX [EMPTY_VALUE]. key: ${key}, node: ${node}`); } else if (RE_UNSAFE_VALUE.test(value)) { if (node.type === 'PLAIN') { node.type = 'BLOCK_LITERAL'; } else if (node.type === 'BLOCK_FOLDED' && /#/.test(value)) { node.type = 'BLOCK_LITERAL'; } } else if (node.type === 'PLAIN' && RE_UNSAFE_PLAIN.test(value)) { node.type = 'QUOTE_DOUBLE'; } let res = _checkValue(value); if (res !== null && res !== void 0 && res.error) { throw new SyntaxError(`${res.error}. key: ${key}, node: ${node}`); } node.value = value; } } function getTopRootContents(doc) { if (isWildcardsYAMLDocument(doc)) { // @ts-ignore doc = doc.contents; } if (isWildcardsYAMLMap(doc)) { return doc; } throw new TypeError(`Input document is not a YAML Document or a YAML Map. Please provide a valid YAML structure.`); } function getTopRootNodes(doc) { return getTopRootContents(doc).items; } function mergeWildcardsYAMLDocumentRoots(ls) { return ls.reduce(_mergeWildcardsYAMLDocumentRootsCore); } function _mergeWildcardsYAMLDocumentRootsCore(a, b) { // @ts-ignore a.contents.items.push(...b.contents.items); return a; } /** * @example * import { deepmergeAll } from 'deepmerge-plus'; * * mergeWildcardsYAMLDocumentJsonBy(ls, { * deepmerge: deepmergeAll, * }) */ function mergeWildcardsYAMLDocumentJsonBy(ls, opts) { return opts.deepmerge(ls.map(_toJSON)); } function _toJSON(v) { // @ts-ignore return yaml.isDocument(v) ? v.toJSON() : v; } function _mergeSeqCore(a, b) { a.items.push(...b.items); return a; } function mergeSeq(a, b) { if (yaml.isSeq(a) && yaml.isSeq(b)) { return _mergeSeqCore(a, b); } throw new TypeError(`Only allow merge YAMLSeq`); } /** * Merges a single root YAMLMap or Document with a list of YAMLMap or Document. * The function only merges the root nodes of the provided YAML structures. * * @throws {TypeError} - If the merge target is not a YAMLMap or Document. * @throws {TypeError} - If the current node is not a YAMLMap. * @throws {TypeError} - If the current node does not support deep merge. */ function mergeFindSingleRoots(doc, list) { if (!yaml.isDocument(doc) && !yaml.isMap(doc)) { throw TypeError(`The merge target should be a YAMLMap or Document. doc: ${doc}`); } list = [list].flat(); for (let node of list) { let result = deepFindSingleRootAt(node); let paths = result === null || result === void 0 ? void 0 : result.paths; if (result) { let current = doc.getIn(paths); if (current) { if (!yaml.isMap(current)) { throw new TypeError(`Only YAMLMap can be merged [1]. path: ${paths}, type: ${getNodeType(current)} node: ${current}`); } result.value.items // @ts-ignore .forEach(p => { const key = p.key.value; const sub = current.get(key); if (sub) { if (yaml.isSeq(sub) && yaml.isSeq(p.value)) { _mergeSeqCore(sub, p.value); } else if (yaml.isMap(sub) && yaml.isMap(p.value)) { const errKeys = []; const errors = []; for (const pair of p.value.items) { try { if (yaml.isSeq(pair.value)) { let sub2 = sub.get(pair.key); if (yaml.isSeq(sub2)) { _mergeSeqCore(sub2, pair.value); continue; } } sub.add(pair, false); } catch (e) { errKeys.push(pair.key.value); errors.push(e); } } if (errors.length) { throw new lazyAggregateError.AggregateErrorExtra(errors, `Failure when merging sub YAMLMap. Paths: ${JSON.stringify(paths.concat(key))}. Conflicting keys: ${JSON.stringify(errKeys)}`); } } else { if (!isSameNodeType(sub, p.value)) { throw new TypeError(`Only allow merge same node type at paths: ${JSON.stringify(paths.concat(key))}, a: ${getNodeType(sub)}, b: ${getNodeType(p.value)}`); } else { throw new TypeError(`Current does not support deep merge at paths: ${JSON.stringify(paths.concat(key))}, a: ${sub}, b: ${p.value}`); } } } else { current.items.push(p); } }); } else { doc.setIn(paths, result.value); } } else { throw new TypeError(`Only YAMLMap can be merged [2]. path: ${paths}, node: ${node}`); } } return doc; } function pathsToWildcardsPath(paths, full) { let s = paths.join('/'); if (full) { s = `__${s}__`; } return s; } function pathsToDotPath(paths) { return paths.join('.'); } function findPath(data, paths, findOpts, prefix = [], list = []) { var _findOpts, _prefix, _list; (_findOpts = findOpts) !== null && _findOpts !== void 0 ? _findOpts : findOpts = {}; (_prefix = prefix) !== null && _prefix !== void 0 ? _prefix : prefix = []; (_list = list) !== null && _list !== void 0 ? _list : list = []; let _cache = { paths: paths.slice(), findOpts, prefix, globOpts: findPathOptionsToGlobOptions(findOpts) }; if (yaml.isDocument(data)) { // @ts-ignore _cache.data = data; data = data.toJSON(); } return _findPathCore(data, paths.slice(), findOpts, prefix, list, _cache); } function findPathOptionsToGlobOptions(findOpts) { return { ...(findOpts === null || findOpts === void 0 ? void 0 : findOpts.globOpts), ignore: findOpts === null || findOpts === void 0 ? void 0 : findOpts.ignore }; } function _findPathCore(data, paths, findOpts, prefix, list, _cache) { paths = paths.slice(); const current = paths.shift(); const deep = paths.length > 0; for (const key in data) { if (findOpts.onlyFirstMatchAll && list.length) { break; } const target = prefix.slice().concat(key); const search = prefix.slice().concat(current); const bool = picomatch.isMatch(pathsToWildcardsPath(target), pathsToWildcardsPath(search), _cache.globOpts); if (bool) { const value = data[key]; const notArray = !Array.isArray(value); if (deep) { if (notArray && typeof value !== 'string') { _findPathCore(value, paths, findOpts, target, list, _cache); continue; } } else if (!notArray) { list.push({ key: target, value }); continue; } else if (!deep && _cache.findOpts.allowWildcardsAtEndMatchRecord && current.includes('*') && typeof value === 'object' && value) { list.push({ key: target, value }); continue; } if (!current.includes('*') || notArray && !deep) { throw new TypeError(`Invalid Type. paths: [${target}], isMatch: ${bool}, deep: ${deep}, deep paths: [${paths}], notArray: ${notArray}, match: [${search}], value: ${value}, _cache : ${JSON.stringify(_cache)}`); } } } if (prefix.length === 0 && findOpts.throwWhenNotFound && !list.length) { throw new RangeError(`Invalid Paths. paths: [${[current, ...paths]}], _cache : ${JSON.stringify(_cache)}`); } return list; } /** * Checks if all self-link wildcards exist in a given object. * * @param obj - The object to check, can be a YAML string, Uint8Array, or a YAML Document/Node. * @param chkOpts - Optional options for the check. * @returns An object containing the results of the check. * * @throws Will throw an error if the provided object is not a YAML Document/Node and cannot be parsed as a YAML string. * * @remarks * This function will parse the provided object into a YAML Document/Node if it is not already one. * It will then extract all self-link wildcards from the YAML string representation of the object. * For each wildcard, it will check if it exists in the JSON representation of the object using the `findPath` function. * The function will return an object containing arrays of wildcard names that exist, do not exist, or were ignored due to the ignore option. * It will also include an array of any errors that occurred during the check. */ function checkAllSelfLinkWildcardsExists(obj, chkOpts) { var _chkOpts, _chkOpts$ignore; (_chkOpts = chkOpts) !== null && _chkOpts !== void 0 ? _chkOpts : chkOpts = {}; const maxErrors = chkOpts.maxErrors > 0 ? chkOpts.maxErrors : 10; if (!(yaml.isDocument(obj) || yaml.isNode(obj))) { obj = parseWildcardsYaml(obj); } const str = obj.toString(); const json = obj.toJSON(); let entries = matchDynamicPromptsWildcardsAll(str, { unsafe: true, ...chkOpts.optsMatch, unique: true }); let isMatchIgnore = () => false; if ((_chkOpts$ignore = chkOpts.ignore) !== null && _chkOpts$ignore !== void 0 && _chkOpts$ignore.length) { isMatchIgnore = picomatch(chkOpts.ignore); } const listHasExists = []; const listHasExistsWildcards = []; const ignoreList = []; const errors = []; for (const entry of entries) { if (isMatchIgnore(entry.name)) { ignoreList.push(entry.name); continue; } const paths = convertWildcardsNameToPaths(entry.name); // @ts-ignore let list = []; try { assertWildcardsPath(entry.name); list = findPath(json, paths, { onlyFirstMatchAll: true, throwWhenNotFound: true, allowWildcardsAtEndMatchRecord: chkOpts.allowWildcardsAtEndMatchRecord }); if (chkOpts.report) { listHasExists.push(...list.map(v => v.key.join('/'))); if (entry.name.includes('*')) { listHasExistsWildcards.push(entry.name); } } } catch (e) { errors.push(e); if (errors.length >= maxErrors) { let e2 = new RangeError(`Max Errors. errors.length ${errors.length} >= ${maxErrors}`); errors.unshift(e2); break; } continue; } } return { obj, listHasExists, listHasExistsWildcards, ignoreList, errors }; } function normalizeDocument(doc, opts) { let options = getOptionsFromDocument(doc, opts); const defaults = createDefaultVisitWildcardsYAMLOptions(options); let checkUnsafeQuote = !options.disableUnsafeQuote; let visitorOptions = { ...defaults, Scalar(key, node) { return _visitNormalizeScalar(key, node, { checkUnsafeQuote, options }); } }; visitWildcardsYAML(doc, visitorOptions); } /** * Converts the given YAML data to a string, applying normalization and formatting. * * @returns - A string representation of the input YAML data, with normalization and formatting applied. * * @throws - Throws a `SyntaxError` if the input data is invalid according to the `validWildcardsYamlData` function. * * @remarks * This function takes the input YAML data and applies normalization and formatting using the provided options. * If the input data is a `Document` object, it first normalizes the document using the `normalizeDocument` function. * Then, it converts the normalized document to a string using the `toString` method with the specified options. * If the input data is not a `Document` object, it directly converts the data to a string using the `stringify` function with the specified options. * * @example * ```typescript * const yamlData: IRecordWildcards = { * key1: ['value1', 'value2'], * key2: { * subkey1: ['value3', 'value4'], * }, * }; * * const yamlString = stringifyWildcardsYamlData(yamlData); * console.log(yamlString); * // Output: * // key1: * // - value1 * // - value2 * // key2: * // subkey1: * // - value3 * // - value4 * ``` */ function stringifyWildcardsYamlData(data, opts) { const isDoc = yaml.isDocument(data); if (isDoc) { opts = getOptionsFromDocument(data, opts); } opts = defaultOptionsStringify(opts); if (isDoc) { normalizeDocument(data, opts); return data.toString(opts); } return yaml.stringify(data, opts); } /** * Parses Stable Diffusion wildcards source to a YAML object. * * @returns - If `Contents` extends `ParsedNode`, returns a parsed `Document.Parsed` with the specified `Contents` and `Strict`. * Otherwise, returns a parsed `Document` with the specified `Contents` and `Strict`. * * @throws - Throws a `SyntaxError` if the YAML data is invalid according to the `validWildcardsYamlData` function. * * @remarks * This function parses the given `source` string or Uint8Array to a YAML object. * It uses the `parseDocument` function from the `yaml` library with `keepSourceTokens: true` option. * Then, it validates the parsed data using the `validWildcardsYamlData` function. * Finally, it returns the parsed data. */ function parseWildcardsYaml(source, opts) { opts = defaultOptionsParseDocument(opts); if (opts.allowEmptyDocument) { var _source; (_source = source) !== null && _source !== void 0 ? _source : source = ''; } let data = yaml.parseDocument(source.toString(), opts); validWildcardsYamlData(data, opts); // @ts-ignore return data; } exports.RE_DYNAMIC_PROMPTS_WILDCARDS = RE_DYNAMIC_PROMPTS_WILDCARDS; exports.RE_DYNAMIC_PROMPTS_WILDCARDS_GLOBAL = RE_DYNAMIC_PROMPTS_WILDCARDS_GLOBAL; exports.RE_DYNAMIC_PROMPTS_WILDCARDS_UNSAFE = RE_DYNAMIC_PROMPTS_WILDCARDS_UNSAFE; exports.RE_DYNAMIC_PROMPTS_WILDCARDS_UNSAFE_GLOBAL = RE_DYNAMIC_PROMPTS_WILDCARDS_UNSAFE_GLOBAL; exports.RE_WILDCARDS_NAME = RE_WILDCARDS_NAME; exports.RE_WILDCARDS_NAME_STAR = RE_WILDCARDS_NAME_STAR; exports.SYMBOL_YAML_NODE_TYPE = SYMBOL_YAML_NODE_TYPE; exports.SYMBOL_YAML_NODE_TYPE_ALIAS = SYMBOL_YAML_NODE_TYPE_ALIAS; exports.SYMBOL_YAML_NODE_TYPE_DOC = SYMBOL_YAML_NODE_TYPE_DOC; exports.SYMBOL_YAML_NODE_TYPE_MAP = SYMBOL_YAML_NODE_TYPE_MAP; exports.SYMBOL_YAML_NODE_TYPE_PAIR = SYMBOL_YAML_NODE_TYPE_PAIR; exports.SYMBOL_YAML_NODE_TYPE_SCALAR = SYMBOL_YAML_NODE_TYPE_SCALAR; exports.SYMBOL_YAML_NODE_TYPE_SEQ = SYMBOL_YAML_NODE_TYPE_SEQ; exports._checkBrackets = _checkBrackets; exports._checkValue = _checkValue; exports._findPathCore = _findPathCore; exports._getNodeTypeCore = _getNodeTypeCore; exports._handleVisitPathsCore = _handleVisitPathsCore; exports._isBadWildcardsNameCore = _isBadWildcardsNameCore; exports._matchDynamicPromptsWildcardsCore = _matchDynamicPromptsWildcardsCore; exports._mergeSeqCore = _mergeSeqCore; exports._mergeWildcardsYAMLDocumentRootsCore = _mergeWildcardsYAMLDocumentRootsCore; exports._nearString = _nearString; exports._toJSON = _toJSON; exports._validKey = _validKey; exports._validMap = _validMap; exports._validPair = _validPair; exports._validSeq = _validSeq; exports._visitNormalizeScalar = _visitNormalizeScalar; exports.assertWildcardsName = assertWildcardsName; exports.assertWildcardsPath = assertWildcardsPath; exports.checkAllSelfLinkWildcardsExists = checkAllSelfLinkWildcardsExists; exports.convertPairsToPathsList = convertPairsToPathsList; exports.convertWildcardsNameToPaths = convertWildcardsNameToPaths; exports.createDefaultVisitWildcardsYAMLOptions = createDefaultVisitWildcardsYAMLOptions; exports.deepFindSingleRootAt = deepFindSingleRootAt; exports.default = parseWildcardsYaml; exports.defaultCheckerIgnoreCase = defaultCheckerIgnoreCase; exports.defaultOptionsParseDocument = defaultOptionsParseDocument; exports.defaultOptionsStringify = defaultOptionsStringify; exports.defaultOptionsStringifyMinify = defaultOptionsStringifyMinify; exports.findPath = findPath; exports.findPathOptionsToGlobOptions = findPathOptionsToGlobOptions; exports.findWildcardsYAMLPathsAll = findWildcardsYAMLPathsAll; exports.formatPrompts = formatPrompts; exports.getNodeType = getNodeType; exports.getNodeTypeSymbol = getNodeTypeSymbol; exports.getOptionsFromDocument = getOptionsFromDocument; exports.getOptionsShared = getOptionsShared; exports.getTopRootContents = getTopRootContents; exports.getTopRootNodes = getTopRootNodes; exports.handleVisitPaths = handleVisitPaths; exports.handleVisitPathsFull = handleVisitPathsFull; exports.isBadWildcardsName = isBadWildcardsName; exports.isBadWildcardsPath = isBadWildcardsPath; exports.isDynamicPromptsWildcards = isDynamicPromptsWildcards; exports.isSafeKey = isSafeKey; exports.isSameNodeType = isSameNodeType; exports.isWildcardsName = isWildcardsName; exports.isWildcardsPathSyntx = isWildcardsPathSyntx; exports.isWildcardsYAMLDocument = isWildcardsYAMLDocument; exports.isWildcardsYAMLDocumentAndContentsIsMap = isWildcardsYAMLDocumentAndContentsIsMap; exports.isWildcardsYAMLMap = isWildcardsYAMLMap; exports.matchDynamicPromptsWildcards = matchDynamicPromptsWildcards; exports.matchDynamicPromptsWildcardsAll = matchDynamicPromptsWildcardsAll; exports.matchDynamicPromptsWildcardsAllGenerator = matchDynamicPromptsWildcardsAllGenerator; exports.mergeFindSingleRoots = mergeFindSingleRoots; exports.mergeSeq = mergeSeq; exports.mergeWildcardsYAMLDocumentJsonBy = mergeWildcardsYAMLDocumentJsonBy; exports.mergeWildcardsYAMLDocumentRoots = mergeWildcardsYAMLDocumentRoots; exports.normalizeDocument = normalizeDocument; exports.normalizeWildcardsYamlString = normalizeWildcardsYamlString; exports.parseWildcardsYaml = parseWildcardsYaml; exports.pathsToDotPath = pathsToDotPath; exports.pathsToWildcardsPath = pathsToWildcardsPath; exports.stringifyWildcardsYamlData = stringifyWildcardsYamlData; exports.stripBlankLines = stripBlankLines; exports.stripZeroStr = stripZeroStr; exports.trimPrompts = trimPrompts; exports.trimPromptsDynamic = trimPromptsDynamic; exports.uniqueSeqItems = uniqueSeqItems; exports.uniqueSeqItemsChecker = uniqueSeqItemsChecker; exports.validWildcardsYamlData = validWildcardsYamlData; exports.visitWildcardsYAML = visitWildcardsYAML; exports.wildcardsPathToPaths = wildcardsPathToPaths; Object.defineProperty(exports, '__esModule', { value: true }); })); //# sourceMappingURL=index.umd.development.cjs.map