Skip to content

Commit f59a3d5

Browse files
committed
fix: 兼容 Surge 转 Loon 时参数带转义符和单引号的情况。
1 parent e7f36f2 commit f59a3d5

1 file changed

Lines changed: 57 additions & 14 deletions

File tree

Rewrite-Parser.beta.js

Lines changed: 57 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,7 @@ let skipBox = [] //skip-ip
257257
let realBox = [] //real-ip
258258
let hndelBox = [] //正则剔除的主机名
259259
let sgArg = [] //surge模块参数
260+
let loonSgArg = [] //转换为 Loon 时实际需要保留的参数
260261
let surgeRuleToggleArgs = new Map() //Surge 用行首 # 注释控制脚本启停的参数
261262
let argumentKeyRenameMap = new Map() //Surge 模板参数名 -> 脚本实际读取的 $argument key
262263

@@ -1110,6 +1111,7 @@ if (binaryInfo != null && binaryInfo.length > 0) {
11101111

11111112
if (isLooniOS) {
11121113
collectArgumentKeyRenameMap(jsBox)
1114+
loonSgArg = filterLoonArguments(sgArg, jsBox, hnBox)
11131115
}
11141116

11151117
//模块信息输出
@@ -1156,13 +1158,13 @@ if (binaryInfo != null && binaryInfo.length > 0) {
11561158
} //模块信息输出结束
11571159

11581160
//surge模块参数转[Argument]输出
1159-
if (isLooniOS && sgArg.length > 0) {
1160-
applySurgeArgumentsDesc(sgArg, modInfoObj['arguments-desc'])
1161-
for (let i = 0; i < sgArg.length; i++) {
1162-
let key = argumentKeyRenameMap.get(sgArg[i].key) || sgArg[i].key
1163-
let type = sgArg[i].type
1164-
let value = formatLoonArgumentValue(sgArg[i])
1165-
let tag = sgArg[i].tag
1161+
if (isLooniOS && loonSgArg.length > 0) {
1162+
applySurgeArgumentsDesc(loonSgArg, modInfoObj['arguments-desc'])
1163+
for (let i = 0; i < loonSgArg.length; i++) {
1164+
let key = argumentKeyRenameMap.get(loonSgArg[i].key) || loonSgArg[i].key
1165+
let type = loonSgArg[i].type
1166+
let value = formatLoonArgumentValue(loonSgArg[i])
1167+
let tag = loonSgArg[i].tag
11661168
loonArg.push(key + '=' + type + ',' + value + ',' + tag)
11671169
}
11681170
}
@@ -2105,22 +2107,32 @@ function isLoonArgumentContainer(str) {
21052107
return /^\s*\[[\s\S]*\]\s*$/.test(stripWrapQuote(str))
21062108
}
21072109

2110+
function unwrapJsonArgument(str, targetApp = 'loon-plugin') {
2111+
let value = normalizeTemplateValue(str, targetApp)
2112+
value = stripWrapQuote(value).trim()
2113+
const unescaped = value.replace(/\\"/g, '"').replace(/\\'/g, "'").replace(/\\\\/g, '\\').trim()
2114+
if (/^\s*\{[\s\S]*\}\s*$/.test(unescaped) && /:/.test(unescaped)) return unescaped
2115+
if (/^\s*\{[\s\S]*\}\s*$/.test(value) && /:/.test(value)) return value
2116+
return /^\s*\{[\s\S]*\}\s*$/.test(unescaped) && /:/.test(unescaped) ? unescaped : ''
2117+
}
2118+
21082119
function isJsonObjectArgument(str) {
2109-
str = stripWrapQuote(str)
2110-
return /^\s*\{[\s\S]*\}\s*$/.test(str) && /:/.test(str)
2120+
return !!unwrapJsonArgument(str)
21112121
}
21122122

21132123
function formatLoonJsonArgument(str, renameMap = argumentKeyRenameMap) {
2114-
const objectBody = normalizeTemplateValue(str, 'loon-plugin')
2115-
.replace(/"([^"]+)"\s*:/g, '$1:')
2116-
.replace(/:\s*"?\{([^{}]+)\}"?/g, ':$1')
2124+
const objectBody = unwrapJsonArgument(str, 'loon-plugin')
2125+
.replace(/["']([^"']+)["']\s*:/g, '$1:')
2126+
.replace(/:\s*["']?\{\{\{([^{}]+)\}\}\}["']?/g, ':$1')
2127+
.replace(/:\s*["']?\{\{([^{}]+)\}\}["']?/g, ':$1')
2128+
.replace(/:\s*["']?\{([^{}]+)\}["']?/g, ':$1')
21172129
.replace(/^\s*\{|\}\s*$/g, '')
21182130
return splitTopLevel(objectBody, ',')
21192131
.filter(Boolean)
21202132
.map(item => {
21212133
const [key, value] = splitFirstTopLevel(item, ':')
2122-
const scriptKey = stripWrapQuote(key)
2123-
const templateKey = stripWrapQuote(value)
2134+
const scriptKey = stripWrapQuote(key).replace(/^\\+|\\+$/g, '')
2135+
const templateKey = stripWrapQuote(value).replace(/^\{+|\}+$/g, '').replace(/^\\+|\\+$/g, '')
21242136
if (templateKey && scriptKey) renameMap.set(templateKey, scriptKey)
21252137
return `{${scriptKey}}`
21262138
})
@@ -2143,6 +2155,37 @@ function getTemplateKeys(str) {
21432155
].filter(Boolean)
21442156
}
21452157

2158+
function getArgumentDefaultValue(item) {
2159+
const value = `${item?.value ?? ''}`.trim()
2160+
return stripWrapQuote(splitTopLevel(value, ',')[0] || value).trim()
2161+
}
2162+
2163+
function collectUsedArgumentKeys(jsBox, hnBox = []) {
2164+
const keys = new Set()
2165+
for (let i = 0; i < jsBox.length; i++) {
2166+
;['jsarg', 'jsenable', 'cronexp'].forEach(field => {
2167+
getTemplateKeys(jsBox[i][field] || '').forEach(key => keys.add(key))
2168+
})
2169+
}
2170+
for (let i = 0; i < hnBox.length; i++) {
2171+
const key = getHnToggleKey(hnBox[i])
2172+
key && keys.add(key)
2173+
}
2174+
return keys
2175+
}
2176+
2177+
function filterLoonArguments(args, jsBox, hnBox = []) {
2178+
const usedKeys = collectUsedArgumentKeys(jsBox, hnBox)
2179+
return args.filter(item => {
2180+
const sourceKey = item.key
2181+
const targetKey = argumentKeyRenameMap.get(sourceKey) || sourceKey
2182+
const defaultValue = getArgumentDefaultValue(item)
2183+
if (!usedKeys.has(sourceKey) && !usedKeys.has(targetKey)) return false
2184+
if (defaultValue === '--' && sourceKey === targetKey) return false
2185+
return true
2186+
})
2187+
}
2188+
21462189
function getLoonArgumentKeys(str) {
21472190
str = stripWrapQuote(str)
21482191
if (!isLoonArgumentList(str)) return []

0 commit comments

Comments
 (0)