mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-02 01:10:23 +08:00
Remove body name style rule support
This commit is contained in:
@@ -11,13 +11,6 @@ const ITEM_PREFIX: &str = "$item.";
|
|||||||
const ITEM_EXACT: &str = "$item";
|
const ITEM_EXACT: &str = "$item";
|
||||||
const CONDITION_SOURCES: &[&str] = &["current", "original"];
|
const CONDITION_SOURCES: &[&str] = &["current", "original"];
|
||||||
const CONDITION_TYPE_VALUES: &[&str] = &["string", "number", "boolean", "array", "object", "null"];
|
const CONDITION_TYPE_VALUES: &[&str] = &["string", "number", "boolean", "array", "object", "null"];
|
||||||
const NAME_STYLE_VALUES: &[&str] = &[
|
|
||||||
"snake_case",
|
|
||||||
"camelCase",
|
|
||||||
"PascalCase",
|
|
||||||
"kebab-case",
|
|
||||||
"capitalize",
|
|
||||||
];
|
|
||||||
|
|
||||||
static RANGE_RE: OnceLock<Regex> = OnceLock::new();
|
static RANGE_RE: OnceLock<Regex> = OnceLock::new();
|
||||||
|
|
||||||
@@ -160,8 +153,7 @@ pub fn body_rules_handle_path(rules: Option<&Value>, path: &str) -> bool {
|
|||||||
| Some("drop")
|
| Some("drop")
|
||||||
| Some("append")
|
| Some("append")
|
||||||
| Some("insert")
|
| Some("insert")
|
||||||
| Some("regex_replace")
|
| Some("regex_replace") => rule
|
||||||
| Some("name_style") => rule
|
|
||||||
.get("path")
|
.get("path")
|
||||||
.and_then(Value::as_str)
|
.and_then(Value::as_str)
|
||||||
.and_then(parse_body_path)
|
.and_then(parse_body_path)
|
||||||
@@ -379,37 +371,6 @@ pub fn apply_local_body_rules(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some("name_style") => {
|
|
||||||
let Some(path) = rule
|
|
||||||
.get("path")
|
|
||||||
.and_then(Value::as_str)
|
|
||||||
.and_then(parse_body_path)
|
|
||||||
else {
|
|
||||||
continue;
|
|
||||||
};
|
|
||||||
let Some(style) = rule.get("style").and_then(Value::as_str) else {
|
|
||||||
continue;
|
|
||||||
};
|
|
||||||
if !valid_name_style(style) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for target_path in iter_wildcard_targets(
|
|
||||||
body,
|
|
||||||
&path,
|
|
||||||
condition,
|
|
||||||
item_condition,
|
|
||||||
original_body,
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
) {
|
|
||||||
if let Some(target) = get_nested_value_mut(body, &target_path) {
|
|
||||||
let Some(current) = target.as_str().map(str::to_owned) else {
|
|
||||||
continue;
|
|
||||||
};
|
|
||||||
*target = Value::String(convert_name_style(¤t, style));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => continue,
|
_ => continue,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1068,97 +1029,6 @@ fn parse_non_negative_count(value: &Value) -> Option<usize> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn valid_name_style(style: &str) -> bool {
|
|
||||||
NAME_STYLE_VALUES.contains(&style)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn convert_name_style(name: &str, style: &str) -> String {
|
|
||||||
let words = split_identifier(name);
|
|
||||||
if words.is_empty() {
|
|
||||||
return name.to_string();
|
|
||||||
}
|
|
||||||
|
|
||||||
match style {
|
|
||||||
"snake_case" => words.join("_"),
|
|
||||||
"camelCase" => {
|
|
||||||
let mut result = words[0].clone();
|
|
||||||
for word in words.iter().skip(1) {
|
|
||||||
result.push_str(&capitalize_ascii(word));
|
|
||||||
}
|
|
||||||
result
|
|
||||||
}
|
|
||||||
"PascalCase" => words
|
|
||||||
.iter()
|
|
||||||
.map(|word| capitalize_ascii(word))
|
|
||||||
.collect::<String>(),
|
|
||||||
"kebab-case" => words.join("-"),
|
|
||||||
"capitalize" => name
|
|
||||||
.chars()
|
|
||||||
.next()
|
|
||||||
.map(|first| {
|
|
||||||
let mut result = first.to_uppercase().collect::<String>();
|
|
||||||
result.push_str(name.chars().skip(1).collect::<String>().as_str());
|
|
||||||
result
|
|
||||||
})
|
|
||||||
.unwrap_or_default(),
|
|
||||||
_ => name.to_string(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn split_identifier(name: &str) -> Vec<String> {
|
|
||||||
let normalized = name.replace(['_', '-'], " ");
|
|
||||||
let chars: Vec<char> = normalized.chars().collect();
|
|
||||||
let mut words = Vec::new();
|
|
||||||
let mut current = String::new();
|
|
||||||
|
|
||||||
for (index, ch) in chars.iter().copied().enumerate() {
|
|
||||||
if ch.is_whitespace() {
|
|
||||||
if !current.is_empty() {
|
|
||||||
words.push(std::mem::take(&mut current));
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let boundary = if current.is_empty() {
|
|
||||||
false
|
|
||||||
} else {
|
|
||||||
let prev = chars[index - 1];
|
|
||||||
let next = chars.get(index + 1).copied();
|
|
||||||
(prev.is_ascii_lowercase() && ch.is_ascii_uppercase())
|
|
||||||
|| (prev.is_ascii_alphabetic() && ch.is_ascii_digit())
|
|
||||||
|| (prev.is_ascii_digit() && ch.is_ascii_alphabetic())
|
|
||||||
|| (prev.is_ascii_uppercase()
|
|
||||||
&& ch.is_ascii_uppercase()
|
|
||||||
&& next.is_some_and(|next| next.is_ascii_lowercase()))
|
|
||||||
};
|
|
||||||
|
|
||||||
if boundary {
|
|
||||||
words.push(std::mem::take(&mut current));
|
|
||||||
}
|
|
||||||
current.push(ch);
|
|
||||||
}
|
|
||||||
|
|
||||||
if !current.is_empty() {
|
|
||||||
words.push(current);
|
|
||||||
}
|
|
||||||
|
|
||||||
words
|
|
||||||
.into_iter()
|
|
||||||
.filter(|word| !word.is_empty())
|
|
||||||
.map(|word| word.to_ascii_lowercase())
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn capitalize_ascii(word: &str) -> String {
|
|
||||||
let mut chars = word.chars();
|
|
||||||
let Some(first) = chars.next() else {
|
|
||||||
return String::new();
|
|
||||||
};
|
|
||||||
let mut result = first.to_uppercase().collect::<String>();
|
|
||||||
result.push_str(chars.as_str());
|
|
||||||
result
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_nested_value(value: &Value, path: &[BodyPathSegment]) -> Option<Value> {
|
fn get_nested_value(value: &Value, path: &[BodyPathSegment]) -> Option<Value> {
|
||||||
let mut current = value;
|
let mut current = value;
|
||||||
for segment in path {
|
for segment in path {
|
||||||
@@ -1390,7 +1260,6 @@ mod tests {
|
|||||||
{"action":"append","path":"messages","value":{"role":"assistant","content":"done"}},
|
{"action":"append","path":"messages","value":{"role":"assistant","content":"done"}},
|
||||||
{"action":"insert","path":"messages","index":-1,"value":{"role":"system","content":"before-last"}},
|
{"action":"insert","path":"messages","index":-1,"value":{"role":"system","content":"before-last"}},
|
||||||
{"action":"regex_replace","path":"tools[*].name","pattern":"tool","replacement":"utility","flags":"i","count":1},
|
{"action":"regex_replace","path":"tools[*].name","pattern":"tool","replacement":"utility","flags":"i","count":1},
|
||||||
{"action":"name_style","path":"tools[*].kind","style":"camelCase","condition":{"path":"$item.name","op":"starts_with","value":"Writer"}},
|
|
||||||
{"action":"drop","path":"tools[1-2].deprecated"}
|
{"action":"drop","path":"tools[1-2].deprecated"}
|
||||||
]);
|
]);
|
||||||
assert!(body_rules_are_locally_supported(Some(&rules)));
|
assert!(body_rules_are_locally_supported(Some(&rules)));
|
||||||
@@ -1434,9 +1303,6 @@ mod tests {
|
|||||||
assert_eq!(body["tools"][0]["name"], "Writerutility");
|
assert_eq!(body["tools"][0]["name"], "Writerutility");
|
||||||
assert_eq!(body["tools"][1]["name"], "Readutility");
|
assert_eq!(body["tools"][1]["name"], "Readutility");
|
||||||
assert_eq!(body["tools"][2]["name"], "Otherutility");
|
assert_eq!(body["tools"][2]["name"], "Otherutility");
|
||||||
assert_eq!(body["tools"][0]["kind"], "snakeCaseName");
|
|
||||||
assert_eq!(body["tools"][1]["kind"], "Pascal Case");
|
|
||||||
assert_eq!(body["tools"][2]["kind"], "kebab-case-value");
|
|
||||||
assert_eq!(body["tools"][0]["deprecated"], true);
|
assert_eq!(body["tools"][0]["deprecated"], true);
|
||||||
assert!(body["tools"][1].get("deprecated").is_none());
|
assert!(body["tools"][1].get("deprecated").is_none());
|
||||||
assert!(body["tools"][2].get("deprecated").is_none());
|
assert!(body["tools"][2].get("deprecated").is_none());
|
||||||
@@ -1601,15 +1467,14 @@ mod tests {
|
|||||||
let rules = serde_json::json!([
|
let rules = serde_json::json!([
|
||||||
{"action":"append","path":"messages","value":{}},
|
{"action":"append","path":"messages","value":{}},
|
||||||
{"action":"regex_replace","path":"tools[*].name","pattern":"foo","replacement":"bar"},
|
{"action":"regex_replace","path":"tools[*].name","pattern":"foo","replacement":"bar"},
|
||||||
{"action":"name_style","path":"tools[0-2].kind","style":"snake_case"},
|
|
||||||
{"action":"rename","from":"metadata.old","to":"metadata.new"}
|
{"action":"rename","from":"metadata.old","to":"metadata.new"}
|
||||||
]);
|
]);
|
||||||
|
|
||||||
assert!(body_rules_handle_path(Some(&rules), "messages"));
|
assert!(body_rules_handle_path(Some(&rules), "messages"));
|
||||||
assert!(body_rules_handle_path(Some(&rules), "tools[1].name"));
|
assert!(body_rules_handle_path(Some(&rules), "tools[1].name"));
|
||||||
assert!(body_rules_handle_path(Some(&rules), "tools[2].kind"));
|
|
||||||
assert!(body_rules_handle_path(Some(&rules), "metadata.old"));
|
assert!(body_rules_handle_path(Some(&rules), "metadata.old"));
|
||||||
assert!(body_rules_handle_path(Some(&rules), "metadata.new"));
|
assert!(body_rules_handle_path(Some(&rules), "metadata.new"));
|
||||||
|
assert!(!body_rules_handle_path(Some(&rules), "tools[2].kind"));
|
||||||
assert!(!body_rules_handle_path(Some(&rules), "tools[3].kind"));
|
assert!(!body_rules_handle_path(Some(&rules), "tools[3].kind"));
|
||||||
assert!(!body_rules_handle_path(Some(&rules), "instructions"));
|
assert!(!body_rules_handle_path(Some(&rules), "instructions"));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -160,19 +160,7 @@ export type HeaderRule = (HeaderRuleSet | HeaderRuleDrop | HeaderRuleRename) & {
|
|||||||
condition?: BodyRuleCondition
|
condition?: BodyRuleCondition
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
export type BodyRule = (BodyRuleSet | BodyRuleDrop | BodyRuleRename | BodyRuleAppend | BodyRuleInsert | BodyRuleRegexReplace) & {
|
||||||
* 请求体规则 - 转换命名风格
|
|
||||||
*
|
|
||||||
* - path 指向目标字符串字段,支持通配符如 "tools[*].name"
|
|
||||||
* - style 为目标命名风格
|
|
||||||
*/
|
|
||||||
export interface BodyRuleNameStyle {
|
|
||||||
action: 'name_style'
|
|
||||||
path: string
|
|
||||||
style: 'snake_case' | 'camelCase' | 'PascalCase' | 'kebab-case' | 'capitalize'
|
|
||||||
}
|
|
||||||
|
|
||||||
export type BodyRule = (BodyRuleSet | BodyRuleDrop | BodyRuleRename | BodyRuleAppend | BodyRuleInsert | BodyRuleRegexReplace | BodyRuleNameStyle) & {
|
|
||||||
condition?: BodyRuleCondition
|
condition?: BodyRuleCondition
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -622,14 +622,6 @@
|
|||||||
<code v-pre>{{$original}}</code> 引用原值
|
<code v-pre>{{$original}}</code> 引用原值
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
|
||||||
<div class="font-medium mb-0.5">
|
|
||||||
命名风格
|
|
||||||
</div>
|
|
||||||
<div class="text-muted-foreground">
|
|
||||||
批量转换字段命名:capitalize / snake_case / camelCase / PascalCase / kebab-case
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
<div>
|
||||||
<div class="font-medium mb-0.5">
|
<div class="font-medium mb-0.5">
|
||||||
条件运算符
|
条件运算符
|
||||||
@@ -692,7 +684,7 @@
|
|||||||
@update:model-value="(v: string) => updateEndpointBodyRuleAction(endpoint.id, index, v as BodyRuleAction)"
|
@update:model-value="(v: string) => updateEndpointBodyRuleAction(endpoint.id, index, v as BodyRuleAction)"
|
||||||
@update:open="(v) => handleBodyRuleSelectOpen(endpoint.id, index, v)"
|
@update:open="(v) => handleBodyRuleSelectOpen(endpoint.id, index, v)"
|
||||||
>
|
>
|
||||||
<SelectTrigger class="w-[96px] h-7 text-xs shrink-0">
|
<SelectTrigger class="w-[88px] h-7 text-xs shrink-0">
|
||||||
<SelectValue />
|
<SelectValue />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
@@ -714,9 +706,6 @@
|
|||||||
<SelectItem value="regex_replace">
|
<SelectItem value="regex_replace">
|
||||||
正则替换
|
正则替换
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
<SelectItem value="name_style">
|
|
||||||
命名风格
|
|
||||||
</SelectItem>
|
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
<Button
|
<Button
|
||||||
@@ -873,41 +862,6 @@
|
|||||||
:title="getRegexPatternValidationTip(rule)"
|
:title="getRegexPatternValidationTip(rule)"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="rule.action === 'name_style'">
|
|
||||||
<Input
|
|
||||||
:model-value="rule.path"
|
|
||||||
placeholder="字段路径(如 tools[*].name)"
|
|
||||||
size="sm"
|
|
||||||
class="flex-[2] min-w-0 h-7 text-xs"
|
|
||||||
@update:model-value="(v) => updateEndpointBodyRuleField(endpoint.id, index, 'path', v)"
|
|
||||||
/>
|
|
||||||
<span class="text-muted-foreground text-xs">→</span>
|
|
||||||
<Select
|
|
||||||
:model-value="rule.style || 'capitalize'"
|
|
||||||
@update:model-value="(v: string) => updateEndpointBodyRuleField(endpoint.id, index, 'style', v)"
|
|
||||||
>
|
|
||||||
<SelectTrigger class="w-[120px] h-7 text-xs shrink-0">
|
|
||||||
<SelectValue />
|
|
||||||
</SelectTrigger>
|
|
||||||
<SelectContent>
|
|
||||||
<SelectItem value="capitalize">
|
|
||||||
Capitalize
|
|
||||||
</SelectItem>
|
|
||||||
<SelectItem value="snake_case">
|
|
||||||
snake_case
|
|
||||||
</SelectItem>
|
|
||||||
<SelectItem value="camelCase">
|
|
||||||
camelCase
|
|
||||||
</SelectItem>
|
|
||||||
<SelectItem value="PascalCase">
|
|
||||||
PascalCase
|
|
||||||
</SelectItem>
|
|
||||||
<SelectItem value="kebab-case">
|
|
||||||
kebab-case
|
|
||||||
</SelectItem>
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
</template>
|
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
size="icon"
|
size="icon"
|
||||||
@@ -1066,7 +1020,6 @@ import {
|
|||||||
type HeaderRule,
|
type HeaderRule,
|
||||||
type BodyRule,
|
type BodyRule,
|
||||||
type BodyRuleRegexReplace,
|
type BodyRuleRegexReplace,
|
||||||
type BodyRuleNameStyle,
|
|
||||||
} from '@/api/endpoints'
|
} from '@/api/endpoints'
|
||||||
import { adminApi } from '@/api/admin'
|
import { adminApi } from '@/api/admin'
|
||||||
import { formatApiFormat } from '@/api/endpoints/types/api-format'
|
import { formatApiFormat } from '@/api/endpoints/types/api-format'
|
||||||
@@ -1091,7 +1044,7 @@ interface EditableRule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 编辑用的请求体规则类型
|
// 编辑用的请求体规则类型
|
||||||
type BodyRuleAction = 'set' | 'drop' | 'rename' | 'append' | 'insert' | 'regex_replace' | 'name_style'
|
type BodyRuleAction = 'set' | 'drop' | 'rename' | 'append' | 'insert' | 'regex_replace'
|
||||||
|
|
||||||
interface EditableBodyRule {
|
interface EditableBodyRule {
|
||||||
action: BodyRuleAction
|
action: BodyRuleAction
|
||||||
@@ -1104,7 +1057,6 @@ interface EditableBodyRule {
|
|||||||
replacement: string // regex_replace 用
|
replacement: string // regex_replace 用
|
||||||
flags: string // regex_replace 用(i/m/s)
|
flags: string // regex_replace 用(i/m/s)
|
||||||
count: string // regex_replace 用(空=默认全部;0=全部)
|
count: string // regex_replace 用(空=默认全部;0=全部)
|
||||||
style: string // name_style 用(snake_case/camelCase/PascalCase/kebab-case/capitalize)
|
|
||||||
condition: EditableConditionNode | null
|
condition: EditableConditionNode | null
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1481,8 +1433,7 @@ const RESERVED_BODY_FIELDS = new Set([
|
|||||||
'stream',
|
'stream',
|
||||||
])
|
])
|
||||||
|
|
||||||
const BODY_RULE_JSON_ACTIONS = new Set(['set', 'drop', 'rename', 'append', 'insert', 'regex_replace', 'name_style'])
|
const BODY_RULE_JSON_ACTIONS = new Set(['set', 'drop', 'rename', 'append', 'insert', 'regex_replace'])
|
||||||
const BODY_RULE_JSON_STYLES = new Set(['snake_case', 'camelCase', 'PascalCase', 'kebab-case', 'capitalize'])
|
|
||||||
const CONDITION_JSON_OPS = new Set(['eq', 'neq', 'gt', 'lt', 'gte', 'lte', 'starts_with', 'ends_with', 'contains', 'matches', 'exists', 'not_exists', 'in', 'type_is'])
|
const CONDITION_JSON_OPS = new Set(['eq', 'neq', 'gt', 'lt', 'gte', 'lte', 'starts_with', 'ends_with', 'contains', 'matches', 'exists', 'not_exists', 'in', 'type_is'])
|
||||||
|
|
||||||
function isJsonObject(value: unknown): value is Record<string, unknown> {
|
function isJsonObject(value: unknown): value is Record<string, unknown> {
|
||||||
@@ -1598,11 +1549,7 @@ function validateBodyRuleJson(rule: unknown, label: string, index: number): stri
|
|||||||
if (rule.count !== undefined && !Number.isInteger(rule.count)) return `${label}第 ${index + 1} 条:count 必须是整数`
|
if (rule.count !== undefined && !Number.isInteger(rule.count)) return `${label}第 ${index + 1} 条:count 必须是整数`
|
||||||
return validateJsonCondition(rule, label, index)
|
return validateJsonCondition(rule, label, index)
|
||||||
}
|
}
|
||||||
if (requireJsonString(rule, 'path', label, index)) return requireJsonString(rule, 'path', label, index)
|
return `${label}第 ${index + 1} 条:action 无效`
|
||||||
if (typeof rule.style !== 'string' || !BODY_RULE_JSON_STYLES.has(rule.style)) {
|
|
||||||
return `${label}第 ${index + 1} 条:style 无效`
|
|
||||||
}
|
|
||||||
return validateJsonCondition(rule, label, index)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseEndpointRulesJsonDraft(draft: string): { value: EndpointRulesJsonPayload | null; error: string | null } {
|
function parseEndpointRulesJsonDraft(draft: string): { value: EndpointRulesJsonPayload | null; error: string | null } {
|
||||||
@@ -2023,7 +1970,6 @@ function emptyBodyRule(action: BodyRuleAction = 'set'): EditableBodyRule {
|
|||||||
replacement: '',
|
replacement: '',
|
||||||
flags: '',
|
flags: '',
|
||||||
count: '',
|
count: '',
|
||||||
style: '',
|
|
||||||
condition: null,
|
condition: null,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2056,8 +2002,6 @@ function editableBodyRulesFromRules(rules: BodyRule[] | null | undefined): Edita
|
|||||||
count: rule.count === undefined || rule.count === null ? '' : String(rule.count),
|
count: rule.count === undefined || rule.count === null ? '' : String(rule.count),
|
||||||
condition: conditionToEditable(rule.condition),
|
condition: conditionToEditable(rule.condition),
|
||||||
})
|
})
|
||||||
} else if (rule.action === 'name_style') {
|
|
||||||
bodyRules.push({ ...emptyBodyRule('name_style'), path: rule.path || '', style: rule.style || 'capitalize', condition: conditionToEditable(rule.condition) })
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return bodyRules
|
return bodyRules
|
||||||
@@ -2457,7 +2401,7 @@ function updateEndpointBodyRuleAction(endpointId: string, index: number, action:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 更新请求体规则字段
|
// 更新请求体规则字段
|
||||||
function updateEndpointBodyRuleField(endpointId: string, index: number, field: 'path' | 'value' | 'from' | 'to' | 'index' | 'pattern' | 'replacement' | 'flags' | 'count' | 'style', value: string) {
|
function updateEndpointBodyRuleField(endpointId: string, index: number, field: 'path' | 'value' | 'from' | 'to' | 'index' | 'pattern' | 'replacement' | 'flags' | 'count', value: string) {
|
||||||
const rules = getEndpointEditBodyRules(endpointId)
|
const rules = getEndpointEditBodyRules(endpointId)
|
||||||
if (rules[index]) {
|
if (rules[index]) {
|
||||||
rules[index][field] = value
|
rules[index][field] = value
|
||||||
@@ -2685,8 +2629,6 @@ function isBodyRuleEffective(r: EditableBodyRule): boolean {
|
|||||||
return !!(r.path.trim() && r.index.trim())
|
return !!(r.path.trim() && r.index.trim())
|
||||||
case 'regex_replace':
|
case 'regex_replace':
|
||||||
return !!(r.path.trim() && r.pattern.trim())
|
return !!(r.path.trim() && r.pattern.trim())
|
||||||
case 'name_style':
|
|
||||||
return !!(r.path.trim() && r.style.trim())
|
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -2753,9 +2695,6 @@ function _formatBodyRuleLabel(rule: EditableBodyRule): string {
|
|||||||
const flags = rule.flags.trim()
|
const flags = rule.flags.trim()
|
||||||
const count = rule.count.trim()
|
const count = rule.count.trim()
|
||||||
return `${rule.path}: s/${rule.pattern}/${rule.replacement || ''}/${flags}${count ? ` ×${count}` : ''}`
|
return `${rule.path}: s/${rule.pattern}/${rule.replacement || ''}/${flags}${count ? ` ×${count}` : ''}`
|
||||||
} else if (rule.action === 'name_style') {
|
|
||||||
if (!rule.path || !rule.style) return '(未设置)'
|
|
||||||
return `${rule.path}→${rule.style}`
|
|
||||||
}
|
}
|
||||||
return '(未知)'
|
return '(未知)'
|
||||||
}
|
}
|
||||||
@@ -2796,9 +2735,6 @@ function hasBodyRulesChanges(endpoint: ProviderEndpoint): boolean {
|
|||||||
if (edited.replacement !== (original.replacement ?? '')) return true
|
if (edited.replacement !== (original.replacement ?? '')) return true
|
||||||
if (edited.flags !== (original.flags ?? '')) return true
|
if (edited.flags !== (original.flags ?? '')) return true
|
||||||
if (edited.count !== (original.count === undefined || original.count === null ? '' : String(original.count))) return true
|
if (edited.count !== (original.count === undefined || original.count === null ? '' : String(original.count))) return true
|
||||||
} else if (edited.action === 'name_style' && original.action === 'name_style') {
|
|
||||||
if (edited.path !== (original.path ?? '')) return true
|
|
||||||
if (edited.style !== (original.style ?? '')) return true
|
|
||||||
}
|
}
|
||||||
if (!conditionEquals(edited.condition, conditionToEditable(original.condition))) return true
|
if (!conditionEquals(edited.condition, conditionToEditable(original.condition))) return true
|
||||||
}
|
}
|
||||||
@@ -2839,8 +2775,6 @@ function rulesToBodyRules(rules: EditableBodyRule[]): BodyRule[] | null {
|
|||||||
...(isStrictNonNegativeIntegerString(rule.count) ? { count: parseInt(rule.count.trim(), 10) } : {}),
|
...(isStrictNonNegativeIntegerString(rule.count) ? { count: parseInt(rule.count.trim(), 10) } : {}),
|
||||||
}
|
}
|
||||||
result.push({ ...entry, ...(condition ? { condition } : {}) })
|
result.push({ ...entry, ...(condition ? { condition } : {}) })
|
||||||
} else if (rule.action === 'name_style' && rule.path.trim() && rule.style.trim()) {
|
|
||||||
result.push({ action: 'name_style', path: rule.path.trim(), style: rule.style.trim() as BodyRuleNameStyle['style'], ...(condition ? { condition } : {}) })
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2898,10 +2832,6 @@ function getBodyValidationErrorForEndpoint(endpointId: string): string | null {
|
|||||||
if (count) {
|
if (count) {
|
||||||
if (!isStrictNonNegativeIntegerString(count)) return `${prefix}替换次数必须是大于等于 0 的整数`
|
if (!isStrictNonNegativeIntegerString(count)) return `${prefix}替换次数必须是大于等于 0 的整数`
|
||||||
}
|
}
|
||||||
} else if (rule.action === 'name_style') {
|
|
||||||
if (!rule.path.trim()) return `${prefix}路径不能为空`
|
|
||||||
const validStyles = new Set(['snake_case', 'camelCase', 'PascalCase', 'kebab-case', 'capitalize'])
|
|
||||||
if (!rule.style.trim() || !validStyles.has(rule.style.trim())) return `${prefix}请选择有效的命名风格`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const conditionErr = validateEditableCondition(rule.condition)
|
const conditionErr = validateEditableCondition(rule.condition)
|
||||||
|
|||||||
Reference in New Issue
Block a user