fix(substore): normalize mojibake flag prefixes
This commit is contained in:
+36
-10
@@ -2,12 +2,13 @@
|
||||
* Sub-Store 节点命名公共工具
|
||||
*
|
||||
* 远程引用地址:
|
||||
* https://git.orionc.me/orion/script/raw/branch/main/substore/common.js?v=20260603-3
|
||||
* https://git.orionc.me/orion/script/raw/branch/main/substore/common.js?v=20260603-4
|
||||
*/
|
||||
(function (root) {
|
||||
const regexSpecialChars = new Set(['.', '*', '+', '?', '^', '$', '{', '}', '(', ')', '|', '[', ']', '\\']);
|
||||
const leadingFlagRegex = /^([\u{1F1E6}-\u{1F1FF}]{2}|🏴☠️)\s*/u;
|
||||
const inlineFlagRegex = /^(.{1,24}?)([\u{1F1E6}-\u{1F1FF}]{2}|🏴☠️)\s*(.*)$/u;
|
||||
const leadingMojibakeFlagRegex = /^((?:ð[\u0080-\u00BF]{3}){2})\s*/;
|
||||
|
||||
const escapeRegex = value => [...String(value)]
|
||||
.map(char => regexSpecialChars.has(char) ? `\\${char}` : char)
|
||||
@@ -17,7 +18,29 @@
|
||||
.replace(/\s{2,}/g, ' ')
|
||||
.trim();
|
||||
|
||||
const normalizeLeadingFlagSpacing = value => String(value)
|
||||
const decodeMojibakeUtf8 = value => {
|
||||
try {
|
||||
const encoded = [...String(value)]
|
||||
.map(char => `%${char.charCodeAt(0).toString(16).padStart(2, '0')}`)
|
||||
.join('');
|
||||
return decodeURIComponent(encoded);
|
||||
} catch (error) {
|
||||
return '';
|
||||
}
|
||||
};
|
||||
|
||||
const normalizeLeadingMojibakeFlag = value => String(value)
|
||||
.replace(leadingMojibakeFlagRegex, (match, mojibakeFlag) => {
|
||||
const decodedFlag = decodeMojibakeUtf8(mojibakeFlag);
|
||||
return leadingFlagRegex.test(decodedFlag) ? `${decodedFlag} ` : '';
|
||||
})
|
||||
.trim();
|
||||
|
||||
const stripLeadingMojibakeFlag = value => String(value)
|
||||
.replace(leadingMojibakeFlagRegex, '')
|
||||
.trim();
|
||||
|
||||
const normalizeLeadingFlagSpacing = value => normalizeLeadingMojibakeFlag(value)
|
||||
.replace(leadingFlagRegex, '$1 ')
|
||||
.replace(/\s{2,}/g, ' ')
|
||||
.trim();
|
||||
@@ -51,17 +74,18 @@
|
||||
};
|
||||
|
||||
const splitLeadingFlag = name => {
|
||||
const leadingFlagMatch = String(name).match(leadingFlagRegex);
|
||||
if (!leadingFlagMatch) return { flag: '', text: String(name).trim() };
|
||||
const cleanName = normalizeLeadingMojibakeFlag(name);
|
||||
const leadingFlagMatch = cleanName.match(leadingFlagRegex);
|
||||
if (!leadingFlagMatch) return { flag: '', text: cleanName.trim() };
|
||||
|
||||
return {
|
||||
flag: leadingFlagMatch[1],
|
||||
text: String(name).slice(leadingFlagMatch[0].length).trim()
|
||||
text: cleanName.slice(leadingFlagMatch[0].length).trim()
|
||||
};
|
||||
};
|
||||
|
||||
const splitLeadingOrInlineFlag = name => {
|
||||
const cleanName = String(name);
|
||||
const cleanName = normalizeLeadingMojibakeFlag(name);
|
||||
const leadingFlagMatch = cleanName.match(leadingFlagRegex);
|
||||
if (leadingFlagMatch) {
|
||||
return {
|
||||
@@ -89,7 +113,7 @@
|
||||
const sortedAliases = sortRegionAliases(aliases);
|
||||
|
||||
const regionCodeOf = name => {
|
||||
const cleanName = String(name);
|
||||
const cleanName = normalizeLeadingMojibakeFlag(name);
|
||||
const leadingFlagMatch = cleanName.match(leadingFlagRegex);
|
||||
if (leadingFlagMatch) return flagToRegionCode(leadingFlagMatch[1]);
|
||||
|
||||
@@ -108,7 +132,7 @@
|
||||
};
|
||||
|
||||
const aliasRegionPrefixOf = name => {
|
||||
const cleanNameLower = String(name).toLowerCase();
|
||||
const cleanNameLower = stripLeadingMojibakeFlag(name).toLowerCase();
|
||||
for (const [, replacement, aliasLower] of sortedAliases) {
|
||||
if (cleanNameLower.includes(aliasLower)) return replacement;
|
||||
}
|
||||
@@ -117,7 +141,7 @@
|
||||
};
|
||||
|
||||
const normalizeLeadingRegion = name => {
|
||||
const cleanName = String(name).trim();
|
||||
const cleanName = stripLeadingMojibakeFlag(name);
|
||||
const cleanNameLower = cleanName.toLowerCase();
|
||||
|
||||
for (const [alias, replacement, aliasLower] of sortedAliases) {
|
||||
@@ -254,7 +278,7 @@
|
||||
const embeddedDescriptorRegex = new RegExp(`\\s*(?:${descriptorPattern})(?=\\s|\\d|$)`, 'gi');
|
||||
const bracketDescriptorRegex = new RegExp(`\\s*\\[(?:${descriptorPattern})(?:\\s+(?:${descriptorPattern}))*]\\s*`, 'gi');
|
||||
|
||||
const [head, ...segments] = String(name).split('|');
|
||||
const [head, ...segments] = stripLeadingMojibakeFlag(name).split('|');
|
||||
const keptSegments = segments
|
||||
.map(segment => segment.trim())
|
||||
.filter(segment => segment && !descriptorOnlyRegex.test(segment));
|
||||
@@ -282,11 +306,13 @@
|
||||
moveMultiplierToEnd,
|
||||
normalizeHyphenatedRegionFeatures,
|
||||
normalizeLeadingFlagSpacing,
|
||||
normalizeLeadingMojibakeFlag,
|
||||
normalizeMultiplierText,
|
||||
normalizeRegionSequence,
|
||||
normalizeWhitespace,
|
||||
regionCodeToFlag,
|
||||
sortRegionAliases,
|
||||
stripLeadingMojibakeFlag,
|
||||
splitLeadingFlag,
|
||||
splitLeadingOrInlineFlag,
|
||||
stripLineDescriptors
|
||||
|
||||
Reference in New Issue
Block a user