Update variables v2 state handling

This commit is contained in:
2026-02-01 02:49:35 +08:00
parent 4b0541610b
commit bcf664e9a0
6 changed files with 1008 additions and 128 deletions

View File

@@ -21,6 +21,7 @@ import {
const MODULE_ID = 'varCommands';
const TAG_RE_XBGETVAR = /\{\{xbgetvar::([^}]+)\}\}/gi;
const TAG_RE_XBGETVAR_YAML = /\{\{xbgetvar_yaml::([^}]+)\}\}/gi;
const TAG_RE_XBGETVAR_YAML_IDX = /\{\{xbgetvar_yaml_idx::([^}]+)\}\}/gi;
let events = null;
let initialized = false;
@@ -183,6 +184,121 @@ export function replaceXbGetVarYamlInString(s) {
});
}
/**
* 将 {{xbgetvar_yaml_idx::路径}} 替换为带索引注释的 YAML
*/
export function replaceXbGetVarYamlIdxInString(s) {
s = String(s ?? '');
if (!s || s.indexOf('{{xbgetvar_yaml_idx::') === -1) return s;
TAG_RE_XBGETVAR_YAML_IDX.lastIndex = 0;
return s.replace(TAG_RE_XBGETVAR_YAML_IDX, (_, p) => {
const value = lwbResolveVarPath(p);
if (!value) return '';
try {
const parsed = JSON.parse(value);
if (typeof parsed === 'object' && parsed !== null) {
return formatYamlWithIndex(parsed, 0).trim();
}
return value;
} catch {
return value;
}
});
}
function formatYamlWithIndex(obj, indent) {
const pad = ' '.repeat(indent);
if (Array.isArray(obj)) {
if (obj.length === 0) return `${pad}[]`;
const lines = [];
obj.forEach((item, idx) => {
if (item && typeof item === 'object' && !Array.isArray(item)) {
const keys = Object.keys(item);
if (keys.length === 0) {
lines.push(`${pad}- {} # [${idx}]`);
} else {
const firstKey = keys[0];
const firstVal = item[firstKey];
const firstFormatted = formatValue(firstVal, indent + 2);
if (typeof firstVal === 'object' && firstVal !== null) {
lines.push(`${pad}- ${firstKey}: # [${idx}]`);
lines.push(firstFormatted);
} else {
lines.push(`${pad}- ${firstKey}: ${firstFormatted} # [${idx}]`);
}
for (let i = 1; i < keys.length; i++) {
const k = keys[i];
const v = item[k];
const vFormatted = formatValue(v, indent + 2);
if (typeof v === 'object' && v !== null) {
lines.push(`${pad} ${k}:`);
lines.push(vFormatted);
} else {
lines.push(`${pad} ${k}: ${vFormatted}`);
}
}
}
} else if (Array.isArray(item)) {
lines.push(`${pad}- # [${idx}]`);
lines.push(formatYamlWithIndex(item, indent + 1));
} else {
lines.push(`${pad}- ${formatScalar(item)} # [${idx}]`);
}
});
return lines.join('\n');
}
if (obj && typeof obj === 'object') {
if (Object.keys(obj).length === 0) return `${pad}{}`;
const lines = [];
for (const [key, val] of Object.entries(obj)) {
const vFormatted = formatValue(val, indent + 1);
if (typeof val === 'object' && val !== null) {
lines.push(`${pad}${key}:`);
lines.push(vFormatted);
} else {
lines.push(`${pad}${key}: ${vFormatted}`);
}
}
return lines.join('\n');
}
return `${pad}${formatScalar(obj)}`;
}
function formatValue(val, indent) {
if (Array.isArray(val)) return formatYamlWithIndex(val, indent);
if (val && typeof val === 'object') return formatYamlWithIndex(val, indent);
return formatScalar(val);
}
function formatScalar(v) {
if (v === null) return 'null';
if (v === undefined) return '';
if (typeof v === 'boolean') return String(v);
if (typeof v === 'number') return String(v);
if (typeof v === 'string') {
const needsQuote =
v === '' ||
/^\s|\s$/.test(v) || // 首尾空格
/[:[]\]{}&*!|>'"%@`#,]/.test(v) || // YAML 易歧义字符
/^(?:true|false|null)$/i.test(v) || // YAML 关键字
/^-?(?:\d+(?:\.\d+)?|\.\d+)$/.test(v); // 纯数字字符串
if (needsQuote) {
return `"${v.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"`;
}
return v;
}
return String(v);
}
export function replaceXbGetVarInChat(chat) {
if (!Array.isArray(chat)) return;
@@ -194,10 +310,12 @@ export function replaceXbGetVarInChat(chat) {
const old = String(msg[key] ?? '');
const hasJson = old.indexOf('{{xbgetvar::') !== -1;
const hasYaml = old.indexOf('{{xbgetvar_yaml::') !== -1;
if (!hasJson && !hasYaml) continue;
const hasYamlIdx = old.indexOf('{{xbgetvar_yaml_idx::') !== -1;
if (!hasJson && !hasYaml && !hasYamlIdx) continue;
let result = hasJson ? replaceXbGetVarInString(old) : old;
result = hasYaml ? replaceXbGetVarYamlInString(result) : result;
result = hasYamlIdx ? replaceXbGetVarYamlIdxInString(result) : result;
msg[key] = result;
} catch {}
}
@@ -215,10 +333,12 @@ export function applyXbGetVarForMessage(messageId, writeback = true) {
const old = String(msg[key] ?? '');
const hasJson = old.indexOf('{{xbgetvar::') !== -1;
const hasYaml = old.indexOf('{{xbgetvar_yaml::') !== -1;
if (!hasJson && !hasYaml) return;
const hasYamlIdx = old.indexOf('{{xbgetvar_yaml_idx::') !== -1;
if (!hasJson && !hasYaml && !hasYamlIdx) return;
let out = hasJson ? replaceXbGetVarInString(old) : old;
out = hasYaml ? replaceXbGetVarYamlInString(out) : out;
out = hasYamlIdx ? replaceXbGetVarYamlIdxInString(out) : out;
if (writeback && out !== old) {
msg[key] = out;
}
@@ -1111,7 +1231,9 @@ export function cleanupVarCommands() {
initialized = false;
}
/**
* 按值从数组中删除元素2.0 pop 操作)
*/
export {
MODULE_ID,
};