feat(substore): 支持规范化带连字符的节点区域特征名称

This commit is contained in:
Orion
2026-06-03 14:51:53 +08:00
parent 6c1e055281
commit ca3413a1ee
3 changed files with 44 additions and 1 deletions
+4
View File
@@ -143,6 +143,7 @@ https://git.orionc.me/orion/script/raw/branch/main/substore/common.js
- 常见城市转短码,例如 `Los Angeles` -> `LAX``San Jose` -> `SJC``Seattle` -> `SEA``东京` -> `TYO` - 常见城市转短码,例如 `Los Angeles` -> `LAX``San Jose` -> `SJC``Seattle` -> `SEA``东京` -> `TYO`
- 国家/地区别名表覆盖常见英文、中文国家名;城市尽量使用三字 IATA/城市码,避免 `LA` 这类两字码被旗帜操作误识别为国家。 - 国家/地区别名表覆盖常见英文、中文国家名;城市尽量使用三字 IATA/城市码,避免 `LA` 这类两字码被旗帜操作误识别为国家。
- 支持国旗在中间的节点名,例如 `Pro-🇭🇰 Sharon|守夜人` -> `🇭🇰 HK Pro-Sharon|守夜人` - 支持国旗在中间的节点名,例如 `Pro-🇭🇰 Sharon|守夜人` -> `🇭🇰 HK Pro-Sharon|守夜人`
- 支持保留连字符命名里的入口/落地特征,例如 `HK-Go-05-HostHatch` -> `HK 05 GO-HostHatch`
- 将倍率移动到节点核心末尾、订阅后缀之前,例如 `US 2X 02 - Alpha Air` -> `US 02 2X - Alpha Air` - 将倍率移动到节点核心末尾、订阅后缀之前,例如 `US 2X 02 - Alpha Air` -> `US 02 2X - Alpha Air`
- 清理 `[DIP China-Hongkong]``[DIP]` - 清理 `[DIP China-Hongkong]``[DIP]`
- 清理 Alpha Flower 这类 `IEPL 专线 3``标准 1``高级 1` 的冗余线路尾号。 - 清理 Alpha Flower 这类 `IEPL 专线 3``标准 1``高级 1` 的冗余线路尾号。
@@ -160,6 +161,9 @@ https://git.orionc.me/orion/script/raw/branch/main/substore/common.js
Pro-🇭🇰 Sharon|守夜人 - Alpha 8K Snell Pro-🇭🇰 Sharon|守夜人 - Alpha 8K Snell
=> 🇭🇰 HK Pro-Sharon|守夜人 - Alpha 8K Snell => 🇭🇰 HK Pro-Sharon|守夜人 - Alpha 8K Snell
🇭🇰 HK-Go-05-HostHatch - VK
=> 🇭🇰 HK 05 GO-HostHatch - VK
``` ```
## 注意事项 ## 注意事项
+39
View File
@@ -191,6 +191,44 @@
.trim(); .trim();
}; };
const normalizeHyphenatedRegionFeatures = name => {
const hyphenatedMatch = String(name).match(/^([A-Z]{2})(?:\s+([A-Z]{3}))?-(.+)$/);
if (!hyphenatedMatch) return name;
const countryCode = hyphenatedMatch[1];
let regionCode = hyphenatedMatch[2]
? `${countryCode} ${hyphenatedMatch[2]}`
: countryCode;
const tokens = hyphenatedMatch[3].split('-').map(token => token.trim()).filter(Boolean);
if (
!hyphenatedMatch[2] &&
tokens.length >= 2 &&
/^[A-Z]{3}$/.test(tokens[0]) &&
/^\d{1,2}$/.test(tokens[1])
) {
regionCode = `${countryCode} ${tokens.shift()}`;
}
const sequenceIndex = tokens.findIndex(token => /^\d{1,2}$/.test(token));
if (sequenceIndex === -1) return name;
const sequenceNumber = tokens[sequenceIndex].padStart(2, '0');
const ingressTokens = tokens
.slice(0, sequenceIndex)
.map(token => token.toUpperCase());
const egressTokens = tokens.slice(sequenceIndex + 1);
const featureText = ingressTokens.length && egressTokens.length
? `${ingressTokens.join('-')}-${egressTokens.join('-')}`
: [...ingressTokens, ...egressTokens].join('-');
return [regionCode, sequenceNumber, featureText]
.filter(Boolean)
.join(' ')
.replace(/\s{2,}/g, ' ')
.trim();
};
const stripLineDescriptors = (name, descriptorKeywords) => { const stripLineDescriptors = (name, descriptorKeywords) => {
const descriptorPattern = descriptorKeywords.map(escapeRegex).join('|'); const descriptorPattern = descriptorKeywords.map(escapeRegex).join('|');
const descriptorOnlyRegex = new RegExp(`^(?:${descriptorPattern})+$`, 'i'); const descriptorOnlyRegex = new RegExp(`^(?:${descriptorPattern})+$`, 'i');
@@ -223,6 +261,7 @@
flagToRegionCode, flagToRegionCode,
joinAlias, joinAlias,
moveMultiplierToEnd, moveMultiplierToEnd,
normalizeHyphenatedRegionFeatures,
normalizeLeadingFlagSpacing, normalizeLeadingFlagSpacing,
normalizeMultiplierText, normalizeMultiplierText,
normalizeRegionSequence, normalizeRegionSequence,
+1 -1
View File
@@ -770,7 +770,7 @@ async function operator(proxies) {
core = joinAlias(flagRegionCode, core); core = joinAlias(flagRegionCode, core);
} }
core = normalizeRegionSequence(moveMultiplierToEnd(simplifyCoreName(core))) core = normalizeRegionSequence(utils.normalizeHyphenatedRegionFeatures(moveMultiplierToEnd(simplifyCoreName(core))))
.replace(/^([A-Z]{2}(?:\s+[A-Z]{3})?\s+\d{2}\s+(?:标准|高级))\s+1(?=$|\s)/i, '$1'); .replace(/^([A-Z]{2}(?:\s+[A-Z]{3})?\s+\d{2}\s+(?:标准|高级))\s+1(?=$|\s)/i, '$1');
return flag ? `${flag} ${core}` : core; return flag ? `${flag} ${core}` : core;