@@ -257,6 +257,7 @@ let skipBox = [] //skip-ip
257257let realBox = [ ] //real-ip
258258let hndelBox = [ ] //正则剔除的主机名
259259let sgArg = [ ] //surge模块参数
260+ let loonSgArg = [ ] //转换为 Loon 时实际需要保留的参数
260261let surgeRuleToggleArgs = new Map ( ) //Surge 用行首 # 注释控制脚本启停的参数
261262let 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+
21082119function isJsonObjectArgument ( str ) {
2109- str = stripWrapQuote ( str )
2110- return / ^ \s * \{ [ \s \S ] * \} \s * $ / . test ( str ) && / : / . test ( str )
2120+ return ! ! unwrapJsonArgument ( str )
21112121}
21122122
21132123function 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+
21462189function getLoonArgumentKeys ( str ) {
21472190 str = stripWrapQuote ( str )
21482191 if ( ! isLoonArgumentList ( str ) ) return [ ]
0 commit comments