diff --git a/Build/lib/clash.ts b/Build/lib/clash.ts index 17f5020a..72e16757 100644 --- a/Build/lib/clash.ts +++ b/Build/lib/clash.ts @@ -1,4 +1,5 @@ import picocolors from 'picocolors'; +import { domainWildCardToRegex } from './misc'; const identity = (x: T): T => x; const unsupported = Symbol('unsupported'); @@ -8,6 +9,7 @@ const PROCESSOR: Record s DOMAIN: identity, 'DOMAIN-SUFFIX': identity, 'DOMAIN-KEYWORD': identity, + 'DOMAIN-WILDCARD': (_raw, _type, value) => `DOMAIN-REGEX,${domainWildCardToRegex(value)}`, GEOIP: identity, 'IP-CIDR': identity, 'IP-CIDR6': identity, @@ -17,8 +19,8 @@ const PROCESSOR: Record s 'DST-PORT': identity, 'PROCESS-NAME': identity, 'PROCESS-PATH': identity, - 'DEST-PORT': (_raw, type, value) => `DST-PORT,${value}`, - 'IN-PORT': (_raw, type, value) => `SRC-PORT,${value}`, + 'DEST-PORT': (_raw, _type, value) => `DST-PORT,${value}`, + 'IN-PORT': (_raw, _type, value) => `SRC-PORT,${value}`, 'URL-REGEX': unsupported, 'USER-AGENT': unsupported }; diff --git a/Build/lib/create-file.ts b/Build/lib/create-file.ts index 72a98be8..e0ba9558 100644 --- a/Build/lib/create-file.ts +++ b/Build/lib/create-file.ts @@ -110,6 +110,7 @@ const sortTypeOrder: Record = { 'DOMAIN-KEYWORD': 10, // experimental domain wildcard support 'DOMAIN-WILDCARD': 20, + 'DOMAIN-REGEX': 21, 'USER-AGENT': 30, 'PROCESS-NAME': 40, [defaultSortTypeOrder]: 50, // default sort order for unknown type diff --git a/Build/lib/misc.ts b/Build/lib/misc.ts index 163009cd..0c2ee940 100644 --- a/Build/lib/misc.ts +++ b/Build/lib/misc.ts @@ -1,6 +1,7 @@ import { dirname } from 'path'; import fs from 'fs'; import fsp from 'fs/promises'; +import { makeRe } from 'picomatch'; export const isTruthy = (i: T | 0 | '' | false | null | undefined): i is T => !!i; @@ -28,3 +29,7 @@ export const writeFile: Write = async (destination: string, input, dir = dirname } return fsp.writeFile(destination, input, { encoding: 'utf-8' }); }; + +export const domainWildCardToRegex = (domain: string) => { + return makeRe(domain, { contains: false, strictSlashes: true }).source; +}; diff --git a/Build/lib/singbox.ts b/Build/lib/singbox.ts index 1492d695..fcd5dc30 100644 --- a/Build/lib/singbox.ts +++ b/Build/lib/singbox.ts @@ -1,4 +1,5 @@ import picocolors from 'picocolors'; +import { domainWildCardToRegex } from './misc'; const unsupported = Symbol('unsupported'); @@ -7,6 +8,7 @@ const PROCESSOR: Record [ DOMAIN: (_1, _2, value) => ['domain', value], 'DOMAIN-SUFFIX': (_1, _2, value) => ['domain_suffix', value], 'DOMAIN-KEYWORD': (_1, _2, value) => ['domain_keyword', value], + 'DOMAIN-WILDCARD': (_1, _2, value) => ['domain_regex', domainWildCardToRegex(value)], GEOIP: unsupported, 'IP-CIDR': (_1, _2, value) => ['ip_cidr', value.endsWith(',no-resolve') ? value.slice(0, -11) : value], 'IP-CIDR6': (_1, _2, value) => ['ip_cidr', value.endsWith(',no-resolve') ? value.slice(0, -11) : value], diff --git a/package.json b/package.json index 62308c3d..1ae9750a 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "mnemonist": "^0.39.8", "path-scurry": "^1.11.1", "picocolors": "^1.0.1", + "picomatch": "^4.0.2", "punycode": "^2.3.1", "table": "^6.8.2", "tar-stream": "^3.1.7", @@ -49,6 +50,7 @@ "@types/better-sqlite3": "^7.6.11", "@types/chai": "^4.3.17", "@types/mocha": "^10.0.7", + "@types/picomatch": "^3.0.1", "@types/punycode": "^2.1.4", "@types/tar-stream": "^3.1.3", "chai": "4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 33972510..9af4be0f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -37,7 +37,7 @@ importers: version: 0.2.5 fdir: specifier: ^6.2.0 - version: 6.2.0 + version: 6.2.0(picomatch@4.0.2) foxact: specifier: ^0.2.36 version: 0.2.36 @@ -53,6 +53,9 @@ importers: picocolors: specifier: ^1.0.1 version: 1.0.1 + picomatch: + specifier: ^4.0.2 + version: 4.0.2 punycode: specifier: ^2.3.1 version: 2.3.1 @@ -93,6 +96,9 @@ importers: '@types/mocha': specifier: ^10.0.7 version: 10.0.7 + '@types/picomatch': + specifier: ^3.0.1 + version: 3.0.1 '@types/punycode': specifier: ^2.1.4 version: 2.1.4 @@ -436,6 +442,9 @@ packages: '@types/node@20.14.11': resolution: {integrity: sha512-kprQpL8MMeszbz6ojB5/tU8PLN4kesnN8Gjzw349rDlNgsSzg90lAVj3llK99Dh7JON+t9AuscPPFW6mPbTnSA==} + '@types/picomatch@3.0.1': + resolution: {integrity: sha512-1MRgzpzY0hOp9pW/kLRxeQhUWwil6gnrUYd3oEpeYBqp/FexhaCPv3F8LsYr47gtUU45fO2cm1dbwkSrHEo8Uw==} + '@types/punycode@2.1.4': resolution: {integrity: sha512-trzh6NzBnq8yw5e35f8xe8VTYjqM3NE7bohBtvDVf/dtUer3zYTLK1Ka3DG3p7bdtoaOHZucma6FfVKlQ134pQ==} @@ -1259,6 +1268,10 @@ packages: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} + picomatch@4.0.2: + resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} + engines: {node: '>=12'} + pirates@4.0.6: resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} engines: {node: '>= 6'} @@ -1881,6 +1894,8 @@ snapshots: dependencies: undici-types: 5.26.5 + '@types/picomatch@3.0.1': {} + '@types/punycode@2.1.4': {} '@types/retry@0.12.5': {} @@ -2475,7 +2490,9 @@ snapshots: dependencies: reusify: 1.0.4 - fdir@6.2.0: {} + fdir@6.2.0(picomatch@4.0.2): + optionalDependencies: + picomatch: 4.0.2 file-entry-cache@8.0.0: dependencies: @@ -2793,6 +2810,8 @@ snapshots: picomatch@2.3.1: {} + picomatch@4.0.2: {} + pirates@4.0.6: {} prebuild-install@7.1.2: