Skip to content

Commit df9e15e

Browse files
author
bestrui
committed
feat: ✨ 同步 2.21.69
1 parent 2d15caf commit df9e15e

21 files changed

Lines changed: 717 additions & 1466 deletions

File tree

package.json

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,9 @@
55
"scripts": {
66
"sync": "node scripts/sync.js",
77
"build": "node scripts/build.js",
8-
"build:parsers": "node scripts/build.js --parsers-only",
98
"node:dev": "nodemon -w src -w scripts -w package.json -w jsconfig.json --ext js,json --exec \"pnpm run build && node dist/minisubconvert.js\"",
10-
"worker:dev": "pnpm run build:parsers && wrangler dev .build/src/worker.js --config wrangler.jsonc --tsconfig .build/jsconfig.json --ip 0.0.0.0",
11-
"worker:deploy": "pnpm run build:parsers && wrangler deploy .build/src/worker.js --config wrangler.jsonc --tsconfig .build/jsconfig.json",
9+
"worker:dev": "wrangler dev src/worker.js --config wrangler.jsonc --tsconfig jsconfig.json --ip 0.0.0.0",
10+
"worker:deploy": "wrangler deploy src/worker.js --config wrangler.jsonc --tsconfig jsconfig.json",
1211
"worker:secret": "wrangler secret bulk .env.local",
1312
"lint": "eslint \"{src,scripts}/**/*.js\" --ignore-pattern \"src/core/proxy-utils/**\""
1413
},
@@ -30,7 +29,6 @@
3029
"globals": "^17.4.0",
3130
"jszip": "^3.10.1",
3231
"nodemon": "^3.1.11",
33-
"peggy": "^2.0.1",
3432
"typescript": "^5.9.3",
3533
"wrangler": "^4.71.0"
3634
}

scripts/build.js

Lines changed: 11 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -1,139 +1,18 @@
11
const esbuild = require('esbuild');
2-
const peggy = require('peggy');
32
const fs = require('node:fs');
43
const path = require('node:path');
54

6-
const CLI_FLAGS = new Set(process.argv.slice(2));
7-
const SHOULD_BUILD_BUNDLE = !CLI_FLAGS.has('--parsers-only');
8-
const PEGGY_IMPORT_SOURCE_RE =
9-
/(from\s+['"])\.\/peggy\/(?!generated\/)([^'"]+)(['"])/g;
10-
const HELP_TEXT = `Usage: node scripts/build.js [--parsers-only]
11-
12-
--parsers-only Only generate pre-compiled Peggy parsers.
13-
Without --parsers-only, build the Node bundle from .build/src/node.js.`;
14-
15-
if (CLI_FLAGS.has('--help')) {
16-
console.log(HELP_TEXT);
17-
process.exit(0);
18-
}
19-
20-
const PATHS = createPaths();
21-
22-
function createPaths() {
23-
const rootDir = path.resolve(__dirname, '..');
24-
const buildDir = path.join(rootDir, '.build');
25-
const buildSrcDir = path.join(buildDir, 'src');
26-
const buildParsersDir = path.join(buildSrcDir, 'core/proxy-utils/parsers');
27-
const buildPeggyDir = path.join(buildParsersDir, 'peggy');
28-
29-
return {
30-
rootDir,
31-
srcDir: path.join(rootDir, 'src'),
32-
rootTsconfigPath: path.join(rootDir, 'jsconfig.json'),
33-
buildDir,
34-
buildSrcDir,
35-
buildTsconfigPath: path.join(buildDir, 'jsconfig.json'),
36-
buildPeggyDir,
37-
buildGeneratedDir: path.join(buildPeggyDir, 'generated'),
38-
buildParsersIndexPath: path.join(buildParsersDir, 'index.js'),
39-
nodeEntryPath: path.join(buildSrcDir, 'node.js'),
40-
nodeOutputPath: path.join(rootDir, 'dist/minisubconvert.js'),
41-
};
42-
}
43-
44-
function ensureDir(dirPath) {
45-
fs.mkdirSync(dirPath, { recursive: true });
46-
}
47-
48-
function prepareBuildWorkspace() {
49-
fs.rmSync(PATHS.buildDir, { recursive: true, force: true });
50-
ensureDir(PATHS.buildDir);
51-
fs.cpSync(PATHS.srcDir, PATHS.buildSrcDir, { recursive: true });
52-
fs.copyFileSync(PATHS.rootTsconfigPath, PATHS.buildTsconfigPath);
53-
}
54-
55-
function getPeggyGrammarFiles() {
56-
const grammarFiles = fs
57-
.readdirSync(PATHS.buildPeggyDir)
58-
.filter((fileName) => fileName.endsWith('.peg'))
59-
.sort();
60-
61-
if (grammarFiles.length === 0) {
62-
throw new Error(`No .peg files found in ${PATHS.buildPeggyDir}`);
63-
}
64-
65-
return grammarFiles;
66-
}
67-
68-
function createParserModuleCode(pegFileName, parserSource) {
69-
return [
70-
`// Auto-generated from ${pegFileName} - DO NOT EDIT`,
71-
parserSource,
72-
'',
73-
'let cachedParser = null;',
74-
'export default function getParser() {',
75-
' if (!cachedParser) {',
76-
' cachedParser = peg$parse;',
77-
' cachedParser.parse = peg$parse;',
78-
' }',
79-
' return cachedParser;',
80-
'}',
81-
'',
82-
].join('\n');
83-
}
84-
85-
function compilePeggyParser(pegFileName) {
86-
const grammarPath = path.join(PATHS.buildPeggyDir, pegFileName);
87-
const outputPath = path.join(
88-
PATHS.buildGeneratedDir,
89-
`${path.parse(pegFileName).name}.js`,
90-
);
91-
const parserSource = peggy.generate(fs.readFileSync(grammarPath, 'utf-8'), {
92-
output: 'source',
93-
format: 'es',
94-
});
95-
96-
fs.writeFileSync(
97-
outputPath,
98-
createParserModuleCode(pegFileName, parserSource),
99-
'utf-8',
100-
);
101-
console.log(` Generated: ${path.relative(PATHS.rootDir, outputPath)}`);
102-
}
103-
104-
function compilePeggyParsers() {
105-
prepareBuildWorkspace();
106-
ensureDir(PATHS.buildGeneratedDir);
107-
108-
const grammarFiles = getPeggyGrammarFiles();
109-
110-
console.log('Pre-compiling Peggy grammars...');
111-
112-
for (const pegFileName of grammarFiles) {
113-
compilePeggyParser(pegFileName);
114-
}
115-
116-
rewriteParserIndexImports();
117-
console.log(`Generated ${grammarFiles.length} parser modules.`);
118-
}
119-
120-
function rewriteParserIndexImports() {
121-
const source = fs.readFileSync(PATHS.buildParsersIndexPath, 'utf-8');
122-
const rewritten = source.replace(
123-
PEGGY_IMPORT_SOURCE_RE,
124-
'$1./peggy/generated/$2$3',
125-
);
126-
127-
if (rewritten !== source) {
128-
fs.writeFileSync(PATHS.buildParsersIndexPath, rewritten, 'utf-8');
129-
console.log(
130-
` Rewired: ${path.relative(PATHS.rootDir, PATHS.buildParsersIndexPath)}`,
131-
);
132-
}
133-
}
5+
const rootDir = path.resolve(__dirname, '..');
6+
const PATHS = {
7+
rootDir,
8+
srcDir: path.join(rootDir, 'src'),
9+
tsconfigPath: path.join(rootDir, 'jsconfig.json'),
10+
nodeEntryPath: path.join(rootDir, 'src/node.js'),
11+
nodeOutputPath: path.join(rootDir, 'dist/minisubconvert.js'),
12+
};
13413

13514
async function buildNodeBundle() {
136-
ensureDir(path.dirname(PATHS.nodeOutputPath));
15+
fs.mkdirSync(path.dirname(PATHS.nodeOutputPath), { recursive: true });
13716

13817
await esbuild.build({
13918
entryPoints: [PATHS.nodeEntryPath],
@@ -147,7 +26,7 @@ async function buildNodeBundle() {
14726
banner: {
14827
js: '#!/usr/bin/env node',
14928
},
150-
tsconfig: PATHS.buildTsconfigPath,
29+
tsconfig: PATHS.tsconfigPath,
15130
logLevel: 'info',
15231
});
15332

@@ -158,12 +37,7 @@ async function buildNodeBundle() {
15837

15938
async function main() {
16039
try {
161-
compilePeggyParsers();
162-
163-
if (SHOULD_BUILD_BUNDLE) {
164-
await buildNodeBundle();
165-
}
166-
40+
await buildNodeBundle();
16741
console.log('Build complete.');
16842
} catch (error) {
16943
console.error('Build failed:', error);

src/core/proxy-utils/parsers/index.js

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -829,13 +829,38 @@ function URI_VLESS() {
829829
// mKCP 的伪装头部类型。当前可选值有 none / srtp / utp / wechat-video / dtls / wireguard。省略时默认值为 none,即不使用伪装头部,但不可以为空字符串。
830830
proxy.headerType = params.headerType || 'none';
831831
}
832-
833-
if (params.mode) {
834-
proxy._mode = params.mode;
835-
}
836832
if (params.extra) {
837833
proxy._extra = params.extra;
838834
}
835+
// 太麻烦了 暂时 extra 原封不动
836+
// 单独解析一下
837+
if (params.mode) {
838+
if (['xhttp'].includes(proxy.network)) {
839+
let extra = {};
840+
try {
841+
extra = proxy._extra ? JSON.parse(proxy._extra) : {};
842+
} catch (e) {
843+
$.error(
844+
`Failed to parse extra field as JSON: ${proxy._extra}`,
845+
);
846+
}
847+
if (extra.downloadSettings) {
848+
$.error(
849+
'It is too complex to convert the downloadSettings in extra into the Mihomo format, so it is not supported.',
850+
);
851+
}
852+
proxy[`${proxy.network}-opts`] = {
853+
'no-grpc-header': extra['noGRPCHeader'],
854+
'x-padding-bytes': extra['xPaddingBytes'],
855+
// 'sc-max-each-post-bytes': extra['scMaxEachPostBytes'],
856+
// 'sc-min-posts-interval-ms': extra['scMinPostsIntervalMs'],
857+
mode: params.mode,
858+
...proxy[`${proxy.network}-opts`],
859+
};
860+
} else {
861+
proxy._mode = params.mode;
862+
}
863+
}
839864
}
840865
if (params.encryption) {
841866
proxy.encryption = params.encryption;
@@ -1266,6 +1291,7 @@ function Clash_All() {
12661291
}
12671292
if (
12681293
![
1294+
'tailscale',
12691295
'trusttunnel',
12701296
'naive',
12711297
'anytls',
@@ -1656,10 +1682,16 @@ function Surge_Trojan() {
16561682
return { name, test, parse };
16571683
}
16581684

1685+
const LOON_ONLY_OPTIONS =
1686+
/(^|,)\s*(fast-open|over-tls|tls-name|ip-mode|tls-cert-sha256|tls-pubkey-sha256)\s*=/i;
1687+
16591688
function Surge_Http() {
16601689
const name = 'Surge HTTP Parser';
16611690
const test = (line) => {
1662-
return /^.*=\s*https?/.test(line.split(',')[0]);
1691+
return (
1692+
/^.*=\s*https?/.test(line.split(',')[0]) &&
1693+
!LOON_ONLY_OPTIONS.test(line)
1694+
);
16631695
};
16641696
const parse = (line) => getSurgeParser().parse(line);
16651697
return { name, test, parse };
@@ -1668,7 +1700,10 @@ function Surge_Http() {
16681700
function Surge_Socks5() {
16691701
const name = 'Surge Socks5 Parser';
16701702
const test = (line) => {
1671-
return /^.*=\s*socks5(-tls)?/.test(line.split(',')[0]);
1703+
return (
1704+
/^.*=\s*socks5(-tls)?/.test(line.split(',')[0]) &&
1705+
!LOON_ONLY_OPTIONS.test(line)
1706+
);
16721707
};
16731708
const parse = (line) => getSurgeParser().parse(line);
16741709
return { name, test, parse };

src/core/proxy-utils/parsers/peggy/loon.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import * as peggy from 'peggy';
1+
import peggy from 'peggy';
22
const grammars = String.raw`
33
// global initializer
44
{{

0 commit comments

Comments
 (0)