fix: 完善移动端订阅生成并同步分流配置文档

This commit is contained in:
2026-10-04 12:11:40 +08:00
parent 349ab8329e
commit 812d8a9441
25 changed files with 791 additions and 67 deletions

View File

@@ -1,3 +1,4 @@
export * from './protocols.js';
export * from './schemas.js';
export * from './dto.js';
export { splitRuleExpression } from './rule-syntax.js';

View File

@@ -48,5 +48,9 @@ export function clientSupports(client: ClientType, node: NodeCapabilityInput): C
return { ok: false, reason: `Surge 不支持该 VMess 加密方式:${node.security}` };
}
}
if (client === 'clash' && node.protocol === 'vmess'
&& !['auto', 'none', 'zero', 'aes-128-gcm', 'chacha20-poly1305', 'chacha20-ietf-poly1305'].includes(node.security ?? 'auto')) {
return { ok: false, reason: `Clash 不支持该 VMess 加密方式:${node.security}` };
}
return { ok: true };
}

View File

@@ -1,5 +1,5 @@
/** Split structural commas while preserving quoted values and nested expressions. */
function split(value: string): string[] | null {
export function splitRuleExpression(value: string): string[] | null {
const parts: string[] = [];
let start = 0, depth = 0, quote = '', escaped = false;
for (let i = 0; i < value.length; i++) {
@@ -28,11 +28,11 @@ export const SURGE_PROTOCOLS = ['HTTP', 'HTTPS', 'TCP', 'UDP', 'QUIC', 'STUN', '
export function logicalValueValid(operator: string, value: string, depth = 1): boolean {
value = value.trim();
if (depth > 10 || !value.startsWith('(') || !value.endsWith(')')) return false;
const children = split(value.slice(1, -1));
const children = splitRuleExpression(value.slice(1, -1));
if (!children?.length || (operator === 'NOT' && children.length !== 1)) return false;
return children.every((child) => {
if (!child.startsWith('(') || !child.endsWith(')')) return false;
const parts = split(child.slice(1, -1));
const parts = splitRuleExpression(child.slice(1, -1));
if (!parts || parts.length < 2 || !parts[1] || parts.slice(2).some((flag) => !['no-resolve', 'extended-matching'].includes(flag))) return false;
if (['AND', 'OR', 'NOT'].includes(parts[0])) return logicalValueValid(parts[0], parts[1], depth + 1);
return leafTypes.has(parts[0]) && (parts[0] !== 'PROTOCOL' || SURGE_PROTOCOLS.includes(parts[1]));