严格校验自动项目名称
Project CI / Native shell tests (pull_request) Successful in 16m33s
Project CI / Repository checks (pull_request) Failing after 11s
Project CI / Backend tests (pull_request) Failing after 9s
Project CI / Frontend tests (pull_request) Successful in 3m53s

自动命名仅接受二至十六个汉字。

补充格式、路径、凭据和长度边界回归测试。
This commit is contained in:
2026-09-02 20:38:46 +08:00
parent c030a2429b
commit 77746c63d2
2 changed files with 35 additions and 32 deletions
@@ -26,40 +26,25 @@ pub(crate) struct AutomaticProjectNameAttachment {
pub(crate) media_type: Option<String>,
}
fn is_chinese_project_name_character(value: char) -> bool {
matches!(
value,
'\u{3400}'..='\u{4DBF}'
| '\u{4E00}'..='\u{9FFF}'
| '\u{F900}'..='\u{FAFF}'
| '\u{20000}'..='\u{2FA1F}'
| '\u{30000}'..='\u{323AF}'
)
}
pub(crate) fn normalize_suggested_project_name(value: &str) -> Option<String> {
let value = value.trim();
let mut lines = value.lines();
let first_line = lines.next()?.trim();
if first_line.is_empty() || lines.next().is_some() {
let character_count = value.chars().count();
if !(2..=16).contains(&character_count) || !value.chars().all(is_chinese_project_name_character)
{
return None;
}
let first_line = first_line
.strip_prefix("项目名称:")
.or_else(|| first_line.strip_prefix("项目名称:"))
.or_else(|| first_line.strip_prefix("项目名:"))
.or_else(|| first_line.strip_prefix("项目名:"))
.unwrap_or(first_line)
.trim();
let bytes = first_line.as_bytes();
let stripped = if bytes.len() >= 2 {
let first = first_line.chars().next()?;
let last = first_line.chars().last()?;
if (first == '"' && last == '"')
|| (first == '“' && last == '”')
|| (first == '\'' && last == '\'')
|| (first == '`' && last == '`')
{
first_line[first.len_utf8()..first_line.len() - last.len_utf8()].trim()
} else {
first_line
}
} else {
first_line
};
if stripped.chars().count() < 2 {
return None;
}
normalize_game_creation_project_name(stripped).ok()
normalize_game_creation_project_name(value).ok()
}
pub(crate) fn build_automatic_project_name_prompt(
@@ -1607,8 +1607,16 @@ fn rename_local_game_project_rejects_unsafe_names_and_uninitialized_projects() {
#[test]
fn automatic_project_name_suggestions_are_normalized_fail_closed() {
assert_eq!(
normalize_suggested_project_name(" 项目名称:《星轨夜航 "),
Some("星轨夜航".to_string())
normalize_suggested_project_name(" 星轨夜航 "),
Some("星轨夜航".to_string())
);
assert_eq!(
normalize_suggested_project_name("星河"),
Some("星河".to_string())
);
assert_eq!(
normalize_suggested_project_name("一二三四五六七八九十甲乙丙丁戊己"),
Some("一二三四五六七八九十甲乙丙丁戊己".to_string())
);
assert_eq!(
normalize_suggested_project_name("星轨夜航\n解释"),
@@ -1621,6 +1629,16 @@ fn automatic_project_name_suggestions_are_normalized_fail_closed() {
"",
"项目名:名",
"名称\n控制字符",
"**星轨夜航**",
"https://example.com",
"C:\\projects\\game",
"Bearer sk-secret",
"“星轨夜航”",
"《星轨夜航》",
"项目名称:星轨夜航",
"星轨夜航2",
"星轨Game",
&"".repeat(17),
&"".repeat(81),
] {
assert!(