fix: StrUtil_Replace enum mapping - search select value was treated as literal text

Catalog contract: search is a select ("0"=content / "1"=digits / "2"=phone / "3"=email
/ "4"=ID card / "5"=custom regex) with the target in Config. Old implementation used
first(args, ["search","Config"]) so the enum value "0" was split on as literal text,
making content-replace never work (same family as W26-W33 enum mapping bugs).
Now implements all six modes with preset patterns, regex mode guarded by try/catch,
and falls back to legacy literal behavior when Config is empty.
This commit is contained in:
yu 2026-11-05 13:22:33 +08:00
parent 47b7a43be2
commit 624d13f2ef

View File

@ -111,9 +111,29 @@ register("StrUtil_InStr", (_ctx, _node, args) => {
});
register("StrUtil_Replace", (_ctx, _node, args) => {
const text = str(first(args, ["string"]));
const search = str(first(args, ["search", "Config"]));
// catalog 契约:search 为下拉枚举("0"内容/"1"数字/"2"手机号/"3"邮箱/"4"身份证/"5"自定义正则),查找目标在 Config
// 旧实现直接把枚举值 "0" 当字面文本分割,导致按内容替换永远不生效(W26 系枚举映射 bug 同族)
const modeRaw = first(args, ["search"]);
const mode = str(modeRaw === undefined ? "0" : modeRaw);
const config = str(first(args, ["Config"]));
const replacement = str(first(args, ["replace"]));
return text.split(search).join(replacement);
const presets: Record<string, RegExp> = {
"1": /\d+/g,
"2": /1[3-9]\d{9}/g,
"3": /[\w.+-]+@[\w-]+(?:\.[\w-]+)+/g,
"4": /\d{17}[\dXx]/g
};
if (presets[mode]) return text.replace(presets[mode], replacement);
if (mode === "5") {
try {
return text.replace(new RegExp(config, "g"), replacement);
} catch {
return text;
}
}
// "0" = 指定内容;兼容旧契约:Config 为空时退回把 search 当字面文本
const target = config || mode;
return text.split(target).join(replacement);
});
register(["StrUtil_LowerCase"], (_ctx, _node, args) => str(first(args, ["string"])).toLowerCase());
register(["StrUtil_UpperCase"], (_ctx, _node, args) => str(first(args, ["string"])).toUpperCase());