mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-10-30 07:45:13 +08:00
💐 Sync 2026-07-18 20:20:11
This commit is contained in:
1 parent
bc9ac87cd6
commit
ccd8763bcd
61 files changed
+6527
-2863
No files matched your search
@@ -6,7 +6,7 @@ include $(TOPDIR)/rules.mk
|
|||||||
|
|
||||||
PKG_NAME:=luci-app-daede
|
PKG_NAME:=luci-app-daede
|
||||||
PKG_VERSION:=1.14.7
|
PKG_VERSION:=1.14.7
|
||||||
PKG_RELEASE:=32
|
PKG_RELEASE:=33
|
||||||
PKG_MAINTAINER:=kenzok8
|
PKG_MAINTAINER:=kenzok8
|
||||||
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
|
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
|
||||||
|
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ function renderDaedSettings() {
|
|||||||
const err = (res.stderr || res.stdout || ('exit ' + res.code)).trim().split('\n')[0];
|
const err = (res.stderr || res.stdout || ('exit ' + res.code)).trim().split('\n')[0];
|
||||||
flash(_('Subscription update failed: %s').format(err), 'err', 9000);
|
flash(_('Subscription update failed: %s').format(err), 'err', 9000);
|
||||||
} else {
|
} else {
|
||||||
flash(_('Subscriptions updated'), 'ok');
|
flash(_('Subscriptions updated (daed restarted)'), 'ok');
|
||||||
}
|
}
|
||||||
}).catch(function(e) {
|
}).catch(function(e) {
|
||||||
flash(_('Subscription update failed: %s').format(e.message || e), 'err', 9000);
|
flash(_('Subscription update failed: %s').format(e.message || e), 'err', 9000);
|
||||||
|
|||||||
@@ -628,6 +628,9 @@ msgstr "更新失败:%s"
|
|||||||
msgid "Subscriptions updated (dae reloaded)"
|
msgid "Subscriptions updated (dae reloaded)"
|
||||||
msgstr "订阅已更新(dae 已重载)"
|
msgstr "订阅已更新(dae 已重载)"
|
||||||
|
|
||||||
|
msgid "Subscriptions updated (daed restarted)"
|
||||||
|
msgstr "订阅已更新,daed 已重启"
|
||||||
|
|
||||||
msgid "Section"
|
msgid "Section"
|
||||||
msgstr "区块"
|
msgstr "区块"
|
||||||
|
|
||||||
|
|||||||
@@ -628,6 +628,9 @@ msgstr "更新失败:%s"
|
|||||||
msgid "Subscriptions updated (dae reloaded)"
|
msgid "Subscriptions updated (dae reloaded)"
|
||||||
msgstr "订阅已更新(dae 已重载)"
|
msgstr "订阅已更新(dae 已重载)"
|
||||||
|
|
||||||
|
msgid "Subscriptions updated (daed restarted)"
|
||||||
|
msgstr "订阅已更新,daed 已重启"
|
||||||
|
|
||||||
msgid "Section"
|
msgid "Section"
|
||||||
msgstr "区块"
|
msgstr "区块"
|
||||||
|
|
||||||
|
|||||||
@@ -115,4 +115,16 @@ while IFS= read -r id || [ -n "$id" ]; do
|
|||||||
done < "$TMPDIR/ids"
|
done < "$TMPDIR/ids"
|
||||||
|
|
||||||
log "finished daed subscription update: ok=$ok fail=$fail total=$count"
|
log "finished daed subscription update: ok=$ok fail=$fail total=$count"
|
||||||
[ "$fail" -eq 0 ]
|
|
||||||
|
if [ "$fail" -ne 0 ]; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$count" -gt 0 ] && [ "$ok" -gt 0 ] && /bin/pidof daed >/dev/null 2>&1; then
|
||||||
|
log "restarting daed to apply updated subscriptions"
|
||||||
|
if ! /etc/init.d/daed restart >>"$LOG" 2>&1; then
|
||||||
|
fail 8 "daed restart failed after subscription update"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit 0
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
include $(TOPDIR)/rules.mk
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
PKG_NAME:=luci-app-openclash
|
PKG_NAME:=luci-app-openclash
|
||||||
PKG_VERSION:=0.47.116
|
PKG_VERSION:=0.47.133
|
||||||
PKG_RELEASE:=6
|
PKG_RELEASE:=7
|
||||||
PKG_MAINTAINER:=vernesong <https://github.com/vernesong/OpenClash>
|
PKG_MAINTAINER:=vernesong <https://github.com/vernesong/OpenClash>
|
||||||
|
|
||||||
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
|
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
|
||||||
|
|||||||
File diff suppressed because it is too large.
Load diff
@@ -13,7 +13,7 @@ m.reset = false
|
|||||||
m.submit = false
|
m.submit = false
|
||||||
|
|
||||||
m:section(SimpleSection).template = "openclash/status"
|
m:section(SimpleSection).template = "openclash/status"
|
||||||
if fs.uci_get_config("config", "oix_token") then
|
if fs.uci_get_config("config", "oix_token") and fs.uci_get_config("config", "oix_show_info_page") ~= "0" then
|
||||||
m:append(Template("openclash/oixcloud"))
|
m:append(Template("openclash/oixcloud"))
|
||||||
end
|
end
|
||||||
m:append(Template("openclash/myip"))
|
m:append(Template("openclash/myip"))
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ o:value("http://captive.apple.com/generate_204")
|
|||||||
o.default = "0"
|
o.default = "0"
|
||||||
|
|
||||||
o = s:taboption("settings", Value, "github_address_mod", translate("Github Address Modify"))
|
o = s:taboption("settings", Value, "github_address_mod", translate("Github Address Modify"))
|
||||||
o.description = translate("Modify The Github Address In The Config And OpenClash With Proxy(CDN) To Prevent File Download Faild. Format Reference:").." ".."<a href='javascript:void(0)' onclick='javascript:return winOpen(\"https://ghfast.top/\")'>https://ghfast.top/</a>"
|
o.description = translate("Modify The Github Address In The Config And OpenClash With Proxy(CDN) To Prevent File Download Failed. Format Reference:").." ".."<a href='javascript:void(0)' onclick='javascript:return winOpen(\"https://ghfast.top/\")'>https://ghfast.top/</a>"
|
||||||
o:value("0", translate("Disable"))
|
o:value("0", translate("Disable"))
|
||||||
o:value("https://fastly.jsdelivr.net/")
|
o:value("https://fastly.jsdelivr.net/")
|
||||||
o:value("https://testingcf.jsdelivr.net/")
|
o:value("https://testingcf.jsdelivr.net/")
|
||||||
@@ -215,6 +215,7 @@ function custom_fallback_filter.write(self, section, value)
|
|||||||
fs.writefile("/etc/openclash/custom/openclash_custom_fallback_filter.yaml", value)
|
fs.writefile("/etc/openclash/custom/openclash_custom_fallback_filter.yaml", value)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
if op_mode == "fake-ip" then
|
if op_mode == "fake-ip" then
|
||||||
@@ -247,6 +248,7 @@ function custom_fake_black.write(self, section, value)
|
|||||||
fs.writefile("/etc/openclash/custom/openclash_custom_fake_filter.list", value)
|
fs.writefile("/etc/openclash/custom/openclash_custom_fake_filter.list", value)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -271,6 +273,7 @@ function custom_domain_dns_policy.write(self, section, value)
|
|||||||
fs.writefile("/etc/openclash/custom/openclash_custom_domain_dns_policy.list", value)
|
fs.writefile("/etc/openclash/custom/openclash_custom_domain_dns_policy.list", value)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
o = s:taboption("dns", Flag, "custom_proxy_server_policy", translate("Proxy-Server-Nameserver-Policy"))
|
o = s:taboption("dns", Flag, "custom_proxy_server_policy", translate("Proxy-Server-Nameserver-Policy"))
|
||||||
@@ -294,6 +297,7 @@ function custom_proxy_server_dns_policy.write(self, section, value)
|
|||||||
fs.writefile("/etc/openclash/custom/openclash_custom_proxy_server_dns_policy.list", value)
|
fs.writefile("/etc/openclash/custom/openclash_custom_proxy_server_dns_policy.list", value)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
o = s:taboption("dns", Flag, "custom_host", translate("Hosts"))
|
o = s:taboption("dns", Flag, "custom_host", translate("Hosts"))
|
||||||
@@ -317,6 +321,7 @@ function custom_hosts.write(self, section, value)
|
|||||||
fs.writefile("/etc/openclash/custom/openclash_custom_hosts.list", value)
|
fs.writefile("/etc/openclash/custom/openclash_custom_hosts.list", value)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Meta
|
-- Meta
|
||||||
@@ -384,6 +389,7 @@ function sniffer_custom.write(self, section, value)
|
|||||||
fs.writefile("/etc/openclash/custom/openclash_custom_sniffer.yaml", value)
|
fs.writefile("/etc/openclash/custom/openclash_custom_sniffer.yaml", value)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Smart Settings
|
-- Smart Settings
|
||||||
@@ -476,6 +482,7 @@ function custom_rules.write(self, section, value)
|
|||||||
fs.writefile("/etc/openclash/custom/openclash_custom_rules.list", value)
|
fs.writefile("/etc/openclash/custom/openclash_custom_rules.list", value)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
custom_rules_2 = s:taboption("rules", Value, "custom_rules_2")
|
custom_rules_2 = s:taboption("rules", Value, "custom_rules_2")
|
||||||
@@ -496,6 +503,7 @@ function custom_rules_2.write(self, section, value)
|
|||||||
fs.writefile("/etc/openclash/custom/openclash_custom_rules_2.list", value)
|
fs.writefile("/etc/openclash/custom/openclash_custom_rules_2.list", value)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
-- [[ Edit Custom DNS ]] --
|
-- [[ Edit Custom DNS ]] --
|
||||||
|
|||||||
@@ -9,6 +9,14 @@ local HTTP = require "luci.http"
|
|||||||
local DISP = require "luci.dispatcher"
|
local DISP = require "luci.dispatcher"
|
||||||
local sid = arg[1]
|
local sid = arg[1]
|
||||||
local age_section
|
local age_section
|
||||||
|
local backend_version_status = [[
|
||||||
|
<div class="oc">
|
||||||
|
<div id="subconverter-version-status-cbi" class="subconverter-version-status" data-state="idle" hidden>
|
||||||
|
<span class="subconverter-version-label"></span>
|
||||||
|
<span class="subconverter-version-text"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
]]
|
||||||
|
|
||||||
font_red = [[<b style=color:red>]]
|
font_red = [[<b style=color:red>]]
|
||||||
font_off = [[</b>]]
|
font_off = [[</b>]]
|
||||||
@@ -67,6 +75,12 @@ o:value("clash.meta/1.19.20")
|
|||||||
o:value("Clash")
|
o:value("Clash")
|
||||||
o.rmempty = true
|
o.rmempty = true
|
||||||
|
|
||||||
|
---- Custom Headers
|
||||||
|
o = s:option(DynamicList, "sub_headers", translate("Custom Headers"))
|
||||||
|
o.description = font_red..bold_on..translate("Custom HTTP request headers, one per line, format: Header-Name: value")..bold_off..font_off
|
||||||
|
o.rmempty = true
|
||||||
|
o.placeholder = "x-hwid: my-device-id"
|
||||||
|
|
||||||
o = s:option(ListValue, "config_age_algo", translate("Age Key Type"))
|
o = s:option(ListValue, "config_age_algo", translate("Age Key Type"))
|
||||||
o.description = font_red..bold_on..translate("Age Encryption For Config, Click For More:")..bold_off..font_off.." ".."<a href='javascript:void(0)' onclick='javascript:return winOpen(\"https://wiki.metacubex.one/config/proxy-providers/?age-secret-key#age-secret-key\")'>"..translate("Age Encryption Introduce").."</a>"
|
o.description = font_red..bold_on..translate("Age Encryption For Config, Click For More:")..bold_off..font_off.." ".."<a href='javascript:void(0)' onclick='javascript:return winOpen(\"https://wiki.metacubex.one/config/proxy-providers/?age-secret-key#age-secret-key\")'>"..translate("Age Encryption Introduce").."</a>"
|
||||||
o:value("keygen", "x25519")
|
o:value("keygen", "x25519")
|
||||||
@@ -197,7 +211,7 @@ o.default = 0
|
|||||||
---- Convert Address
|
---- Convert Address
|
||||||
o = s:option(Value, "convert_address", translate("Convert Address"))
|
o = s:option(Value, "convert_address", translate("Convert Address"))
|
||||||
o.rmempty = true
|
o.rmempty = true
|
||||||
o.description = font_red..bold_on..translate("Note: There is A Risk of Privacy Leakage in Online Convert")..bold_off..font_off
|
o.description = backend_version_status..font_red..bold_on..translate("Note: There is A Risk of Privacy Leakage in Online Convert")..bold_off..font_off
|
||||||
o:depends("sub_convert", "1")
|
o:depends("sub_convert", "1")
|
||||||
o:value("https://api.asailor.org/sub", translate("api.asailor.org"))
|
o:value("https://api.asailor.org/sub", translate("api.asailor.org"))
|
||||||
o:value("https://api.wcc.best/sub", translate("api.wcc.best"))
|
o:value("https://api.wcc.best/sub", translate("api.wcc.best"))
|
||||||
@@ -331,4 +345,5 @@ o.write = function()
|
|||||||
end
|
end
|
||||||
|
|
||||||
m:append(Template("openclash/toolbar_show"))
|
m:append(Template("openclash/toolbar_show"))
|
||||||
|
m:append(Template("openclash/subconverter_version"))
|
||||||
return m
|
return m
|
||||||
@@ -350,7 +350,6 @@ local tab = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
s = m:section(Table, tab)
|
s = m:section(Table, tab)
|
||||||
s.description = align_mid..translate("Support syntax check, press").." "..font_green..bold_on.."F10"..bold_off..font_off.." "..translate("to control diff option, press").." "..font_green..bold_on.."F11"..bold_off..font_off.." "..translate("to enter full screen editing mode")..align_mid_off
|
|
||||||
s.anonymous = true
|
s.anonymous = true
|
||||||
s.addremove = false
|
s.addremove = false
|
||||||
|
|
||||||
@@ -361,6 +360,8 @@ local conf_name = fs.basename(conf)
|
|||||||
if not conf_name then conf_name = "config.yaml" end
|
if not conf_name then conf_name = "config.yaml" end
|
||||||
local sconf = "/etc/openclash/"..conf_name
|
local sconf = "/etc/openclash/"..conf_name
|
||||||
|
|
||||||
|
s.description = align_mid..translate("Current Config")..": "..font_green..bold_on..conf_name..bold_off..font_off..align_mid_off
|
||||||
|
|
||||||
sev = s:option(TextValue, "user")
|
sev = s:option(TextValue, "user")
|
||||||
---sev.description = align_mid..translate("Modify Your Config file:").." "..font_green..bold_on..conf_name..bold_off..font_off.." "..translate("Here, Except The Settings That Were Taken Over")..align_mid_off
|
---sev.description = align_mid..translate("Modify Your Config file:").." "..font_green..bold_on..conf_name..bold_off..font_off.." "..translate("Here, Except The Settings That Were Taken Over")..align_mid_off
|
||||||
sev.rows = 40
|
sev.rows = 40
|
||||||
@@ -421,7 +422,7 @@ o.write = function()
|
|||||||
HTTP.redirect(DISP.build_url("admin", "services", "openclash"))
|
HTTP.redirect(DISP.build_url("admin", "services", "openclash"))
|
||||||
end
|
end
|
||||||
|
|
||||||
m:append(Template("openclash/config_editor"))
|
m:append(Template("openclash/config_merge_editor"))
|
||||||
m:append(Template("openclash/config_upload"))
|
m:append(Template("openclash/config_upload"))
|
||||||
|
|
||||||
return ful , form , p , m
|
return ful , form , p , m
|
||||||
@@ -29,6 +29,7 @@ function o.write(self, section, value)
|
|||||||
fs.writefile(file_path, value)
|
fs.writefile(file_path, value)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function o.cfgvalue(self, section)
|
function o.cfgvalue(self, section)
|
||||||
|
|||||||
@@ -229,6 +229,7 @@ function custom_domain_dns.write(self, section, value)
|
|||||||
fs.writefile("/etc/openclash/custom/openclash_custom_domain_dns.list", value)
|
fs.writefile("/etc/openclash/custom/openclash_custom_domain_dns.list", value)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
---- Access Control
|
---- Access Control
|
||||||
@@ -488,7 +489,7 @@ o.default = 0
|
|||||||
o = s:taboption("traffic_control", Value, "common_ports", font_red..bold_on..translate("Common Ports Proxy Mode")..bold_off..font_off)
|
o = s:taboption("traffic_control", Value, "common_ports", font_red..bold_on..translate("Common Ports Proxy Mode")..bold_off..font_off)
|
||||||
o.description = translate("Only Common Ports, Prevent BT/P2P Passing")
|
o.description = translate("Only Common Ports, Prevent BT/P2P Passing")
|
||||||
o:value("0", translate("Disable"))
|
o:value("0", translate("Disable"))
|
||||||
o:value("21 22 23 53 80 123 143 194 443 465 587 853 993 995 998 2052 2053 2082 2083 2086 2095 2096 5222 5228 5229 5230 8080 8443 8880 8888 8889", translate("Default Common Ports"))
|
o:value("21 22 23 53 80 123 143 194 443 465 587 853 993 995 998 2052 2053 2082 2083 2086 2095 2096 2197 5222 5223 5228 5229 5230 8080 8443 8880 8888 8889", translate("Default Common Ports"))
|
||||||
o.default = 0
|
o.default = 0
|
||||||
o.placeholder = translate("443 or 21-443, Use Space to Separate")
|
o.placeholder = translate("443 or 21-443, Use Space to Separate")
|
||||||
o:depends("en_mode", "redir-host")
|
o:depends("en_mode", "redir-host")
|
||||||
@@ -538,6 +539,7 @@ function o.write(self, section, value)
|
|||||||
fs.writefile("/etc/openclash/custom/openclash_custom_localnetwork_ipv4.list", value)
|
fs.writefile("/etc/openclash/custom/openclash_custom_localnetwork_ipv4.list", value)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
o = s:taboption("traffic_control", Value, "chnroute_pass", translate("Chnroute Bypassed List"))
|
o = s:taboption("traffic_control", Value, "chnroute_pass", translate("Chnroute Bypassed List"))
|
||||||
@@ -559,6 +561,7 @@ function o.write(self, section, value)
|
|||||||
fs.writefile("/etc/openclash/custom/openclash_custom_chnroute_pass.list", value)
|
fs.writefile("/etc/openclash/custom/openclash_custom_chnroute_pass.list", value)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
--Stream Enhance
|
--Stream Enhance
|
||||||
@@ -1366,6 +1369,7 @@ function o.write(self, section, value)
|
|||||||
fs.writefile("/etc/openclash/custom/openclash_custom_localnetwork_ipv6.list", value)
|
fs.writefile("/etc/openclash/custom/openclash_custom_localnetwork_ipv6.list", value)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
o = s:taboption("ipv6", Value, "chnroute6_pass", translate("Chnroute6 Bypassed List"))
|
o = s:taboption("ipv6", Value, "chnroute6_pass", translate("Chnroute6 Bypassed List"))
|
||||||
@@ -1386,6 +1390,7 @@ function o.write(self, section, value)
|
|||||||
fs.writefile("/etc/openclash/custom/openclash_custom_chnroute6_pass.list", value)
|
fs.writefile("/etc/openclash/custom/openclash_custom_chnroute6_pass.list", value)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
---- version update
|
---- version update
|
||||||
@@ -1410,6 +1415,7 @@ function o.write(self, section, value)
|
|||||||
fs.writefile("/etc/openclash/custom/openclash_custom_firewall_rules.sh", value)
|
fs.writefile("/etc/openclash/custom/openclash_custom_firewall_rules.sh", value)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
---- debug
|
---- debug
|
||||||
@@ -1417,52 +1423,9 @@ o = s:taboption("debug", DummyValue, "", nil)
|
|||||||
o.template = "openclash/debug"
|
o.template = "openclash/debug"
|
||||||
|
|
||||||
---- oixcloud
|
---- oixcloud
|
||||||
o = s:taboption("oixcloud", Value, "oix_email")
|
oixcloud_panel = s:taboption("oixcloud", DummyValue, "", nil)
|
||||||
o.title = translate("Account Email Address")
|
oixcloud_panel.template = "openclash/oix_login"
|
||||||
o.rmempty = true
|
oixcloud_panel.rawhtml = true
|
||||||
|
|
||||||
o = s:taboption("oixcloud", Value, "oix_passwd")
|
|
||||||
o.title = translate("Account Password")
|
|
||||||
o.password = true
|
|
||||||
o.rmempty = true
|
|
||||||
|
|
||||||
if fs.uci_get_config("config", "oix_token") then
|
|
||||||
o = s:taboption("oixcloud", Flag, "oix_checkin")
|
|
||||||
o.title = translate("Checkin")
|
|
||||||
o.default = 0
|
|
||||||
o.rmempty = true
|
|
||||||
end
|
|
||||||
|
|
||||||
o = s:taboption("oixcloud", Value, "oix_checkin_interval")
|
|
||||||
o.title = translate("Checkin Interval (hour)")
|
|
||||||
o:depends("oix_checkin", "1")
|
|
||||||
o.default = "1"
|
|
||||||
o.rmempty = true
|
|
||||||
|
|
||||||
o = s:taboption("oixcloud", Value, "oix_checkin_multiple")
|
|
||||||
o.title = translate("Checkin Multiple")
|
|
||||||
o.datatype = "uinteger"
|
|
||||||
o.default = "1"
|
|
||||||
o:depends("oix_checkin", "1")
|
|
||||||
o.rmempty = true
|
|
||||||
o.description = font_green..bold_on..translate("Multiple Must Be a Positive Integer and No More Than 100")..bold_off..font_off
|
|
||||||
function o.validate(self, value)
|
|
||||||
if tonumber(value) < 1 then
|
|
||||||
return "1"
|
|
||||||
end
|
|
||||||
if tonumber(value) > 100 then
|
|
||||||
return "100"
|
|
||||||
end
|
|
||||||
return value
|
|
||||||
end
|
|
||||||
|
|
||||||
o = s:taboption("oixcloud", DummyValue, "oix_login", translate("Account Login"))
|
|
||||||
o.template = "openclash/oix_login"
|
|
||||||
if fs.uci_get_config("config", "oix_token") then
|
|
||||||
o.value = font_green..bold_on..translate("Account logged in")..bold_off..font_off
|
|
||||||
else
|
|
||||||
o.value = font_red..bold_on..translate("Account not logged in")..bold_off..font_off
|
|
||||||
end
|
|
||||||
|
|
||||||
local t = {
|
local t = {
|
||||||
{Commit, Apply}
|
{Commit, Apply}
|
||||||
|
|||||||
@@ -603,7 +603,19 @@ end
|
|||||||
--- Returns the installed version of luci-app-openclash.
|
--- Returns the installed version of luci-app-openclash.
|
||||||
-- Supports both opkg and apk package managers.
|
-- Supports both opkg and apk package managers.
|
||||||
-- @return String containing the version number, or "0" if not found
|
-- @return String containing the version number, or "0" if not found
|
||||||
|
-- NOTE: The module-level cache (_oc_version_cache) provides per-request
|
||||||
|
-- deduplication. In OpenWrt LuCI CGI mode each HTTP request spawns a new Lua
|
||||||
|
-- process, so cross-request caching is impossible.
|
||||||
|
-- Since require() returns the same module instance (package.loaded), the
|
||||||
|
-- first call caches the result and subsequent calls avoid redundant shell
|
||||||
|
-- commands. No time-based expiration is needed — the version is immutable
|
||||||
|
-- for the lifetime of a request.
|
||||||
|
local _oc_version_cache = nil
|
||||||
|
|
||||||
function oc_version()
|
function oc_version()
|
||||||
|
if _oc_version_cache ~= nil then
|
||||||
|
return _oc_version_cache
|
||||||
|
end
|
||||||
local v
|
local v
|
||||||
if pkg_type() == "opkg" then
|
if pkg_type() == "opkg" then
|
||||||
v = SYS.exec("rm -f /var/lock/opkg.lock && opkg status luci-app-openclash 2>/dev/null |grep '^Version:' |awk '{print $2}' |tr -d '\n'")
|
v = SYS.exec("rm -f /var/lock/opkg.lock && opkg status luci-app-openclash 2>/dev/null |grep '^Version:' |awk '{print $2}' |tr -d '\n'")
|
||||||
@@ -613,6 +625,7 @@ function oc_version()
|
|||||||
if v == "" then
|
if v == "" then
|
||||||
v = "0"
|
v = "0"
|
||||||
end
|
end
|
||||||
|
_oc_version_cache = v
|
||||||
return v
|
return v
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
<script type="text/javascript">//<![CDATA[
|
||||||
|
(function() {
|
||||||
|
if (window._ocCommonLoaded) return;
|
||||||
|
window._ocCommonLoaded = true;
|
||||||
|
|
||||||
|
window.levelTranslations = {
|
||||||
|
'info': '<%:Info%>',
|
||||||
|
'warning': '<%:Warning%>',
|
||||||
|
'error': '<%:Error%>',
|
||||||
|
'debug': '<%:Debug%>',
|
||||||
|
'tip': '<%:Tip%>',
|
||||||
|
'watchdog': '<%:Watchdog%>',
|
||||||
|
'fatal': '<%:Fatal%>'
|
||||||
|
};
|
||||||
|
window._ocArchOptionsHTML = '<option value="linux-386"><%:linux-386%></option>' +
|
||||||
|
'<option value="linux-amd64-v1"><%:linux-amd64-v1(x86-64)%></option>' +
|
||||||
|
'<option value="linux-amd64-v2"><%:linux-amd64-v2(x86-64)%></option>' +
|
||||||
|
'<option value="linux-amd64-v3"><%:linux-amd64-v3(x86-64)%></option>' +
|
||||||
|
'<option value="linux-armv5"><%:linux-armv5%></option>' +
|
||||||
|
'<option value="linux-armv6"><%:linux-armv6%></option>' +
|
||||||
|
'<option value="linux-armv7"><%:linux-armv7%></option>' +
|
||||||
|
'<option value="linux-arm64"><%:linux-arm64(armv8)%></option>' +
|
||||||
|
'<option value="linux-loong64-abi1"><%:linux-loong64-abi1%></option>' +
|
||||||
|
'<option value="linux-loong64-abi2"><%:linux-loong64-abi2%></option>' +
|
||||||
|
'<option value="linux-riscv64"><%:linux-riscv64%></option>' +
|
||||||
|
'<option value="linux-s390x"><%:linux-s390x%></option>' +
|
||||||
|
'<option value="linux-mips-hardfloat"><%:linux-mips-hardfloat%></option>' +
|
||||||
|
'<option value="linux-mips-softfloat"><%:linux-mips-softfloat%></option>' +
|
||||||
|
'<option value="linux-mips64"><%:linux-mips64%></option>' +
|
||||||
|
'<option value="linux-mips64le"><%:linux-mips64le%></option>' +
|
||||||
|
'<option value="linux-mipsle-softfloat"><%:linux-mipsle-softfloat%></option>' +
|
||||||
|
'<option value="linux-mipsle-hardfloat"><%:linux-mipsle-hardfloat%></option>' +
|
||||||
|
'<option value="0"><%:Not Set%></option>';
|
||||||
|
(function() {
|
||||||
|
function injectArchOptions() {
|
||||||
|
var selects = document.querySelectorAll('.oc-arch-select');
|
||||||
|
for (var i = 0; i < selects.length; i++) {
|
||||||
|
if (selects[i].getAttribute('data-oc-arch-injected')) continue;
|
||||||
|
selects[i].insertAdjacentHTML('afterbegin', window._ocArchOptionsHTML);
|
||||||
|
selects[i].setAttribute('data-oc-arch-injected', '1');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
injectArchOptions();
|
||||||
|
if (document.readyState === 'loading') {
|
||||||
|
document.addEventListener('DOMContentLoaded', injectArchOptions);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
})();
|
||||||
|
//]]></script>
|
||||||
@@ -12,40 +12,22 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="config-editor-actions">
|
<div class="config-editor-actions">
|
||||||
<button type="button" class="icon-btn" id="config-editor-layout" title="<%:Compare%>" style="display:none;">
|
<button type="button" class="icon-btn" id="config-editor-layout" title="<%:Compare%>" style="display:none;">
|
||||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
<svg width="14" height="14"><use href="#oc-icon-compare"/></svg>
|
||||||
<rect x="3" y="3" width="8" height="18" rx="2" stroke="currentColor" stroke-width="2" fill="none"/>
|
|
||||||
<rect x="13" y="3" width="8" height="18" rx="2" stroke="currentColor" stroke-width="2" fill="none"/>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
<button type="button" class="icon-btn" id="config-editor-download" title="<%:Download%>">
|
<button type="button" class="icon-btn" id="config-editor-download" title="<%:Download%>">
|
||||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
<svg width="14" height="14"><use href="#oc-icon-download"/></svg>
|
||||||
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
|
|
||||||
<polyline points="7,11 12,16 17,11"></polyline>
|
|
||||||
<line x1="12" y1="2" x2="12" y2="16"></line>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
<button type="button" class="icon-btn" id="config-editor-save" title="<%:Save%>">
|
<button type="button" class="icon-btn" id="config-editor-save" title="<%:Save%>">
|
||||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
<svg width="14" height="14"><use href="#oc-icon-save"/></svg>
|
||||||
<path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"></path>
|
|
||||||
<polyline points="17,21 17,13 7,13 7,21"></polyline>
|
|
||||||
<polyline points="7,3 7,8 15,8"></polyline>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
<button type="button" class="icon-btn" id="config-editor-close" title="<%:Close%>">
|
<button type="button" class="icon-btn" id="config-editor-close" title="<%:Close%>">
|
||||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
<svg width="14" height="14"><use href="#oc-icon-close"/></svg>
|
||||||
<line x1="18" y1="6" x2="6" y2="18"></line>
|
|
||||||
<line x1="6" y1="6" x2="18" y2="18"></line>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="overwrite-banner" class="overwrite-banner" style="display:none;">
|
<div id="overwrite-banner" class="overwrite-banner" style="display:none;">
|
||||||
<svg style="flex-shrink:0;" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="var(--error-color)" stroke-width="2">
|
<svg style="flex-shrink:0;" width="20" height="20"><use href="#oc-icon-alert-circle"/></svg>
|
||||||
<circle cx="12" cy="12" r="10" stroke="var(--error-color)" fill="rgba(255,80,80,0.12)"/>
|
|
||||||
<line x1="12" y1="5" x2="12" y2="13"/>
|
|
||||||
<circle cx="12" cy="16" r="0.5"/>
|
|
||||||
</svg>
|
|
||||||
<span>
|
<span>
|
||||||
<%:You are editing the overwrite script, please note that some settings may cause the abnormal, be careful with the modification!%>
|
<%:You are editing the overwrite script, please note that some settings may cause the abnormal, be careful with the modification!%>
|
||||||
</span>
|
</span>
|
||||||
@@ -72,10 +54,6 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="config-editor-content">
|
<div class="config-editor-content">
|
||||||
<div class="config-editor-loading" id="config-editor-loading">
|
|
||||||
<div class="loading-spinner"></div>
|
|
||||||
<span><%:Loading config file...%></span>
|
|
||||||
</div>
|
|
||||||
<textarea id="config-editor-textarea" style="display: none;"></textarea>
|
<textarea id="config-editor-textarea" style="display: none;"></textarea>
|
||||||
<div id="config-mergeview-container" style="display:none;width:100%;height:100%;"></div>
|
<div id="config-mergeview-container" style="display:none;width:100%;height:100%;"></div>
|
||||||
</div>
|
</div>
|
||||||
@@ -89,7 +67,7 @@
|
|||||||
<span id="config-editor-status-text"><%:Ready%></span>
|
<span id="config-editor-status-text"><%:Ready%></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="config-editor-help">
|
<div class="config-editor-help">
|
||||||
<span id="config-editor-help"><%:Press F11 for fullscreen, Esc to exit fullscreen, Ctrl+Mouse Wheel to zoom%></span>
|
<span id="config-editor-help"><%:Press%> <b style="color:var(--success-color)">F11</b> <%:for fullscreen,%> <b style="color:var(--success-color)">Esc</b> <%:to exit fullscreen,%> <b style="color:var(--success-color)">Ctrl + <%:Mouse Wheel%></b> <%:to zoom%></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="config-editor-resize-handle" id="config-editor-resize-handle"></div>
|
<div class="config-editor-resize-handle" id="config-editor-resize-handle"></div>
|
||||||
</div>
|
</div>
|
||||||
@@ -97,22 +75,26 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<script src="/luci-static/resources/openclash/js/common.js?v=<%=plugin_version%>"></script>
|
||||||
|
<script src="/luci-static/resources/openclash/js/oc-icons.js?v=<%=plugin_version%>"></script>
|
||||||
<script src="/luci-static/resources/openclash/js/cm6.min.js?v=<%=plugin_version%>"></script>
|
<script src="/luci-static/resources/openclash/js/cm6.min.js?v=<%=plugin_version%>"></script>
|
||||||
|
<%+openclash/common%>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
var levelTranslations = {
|
ocRegisterEditorHotkeys();
|
||||||
'info': '<%:Info%>',
|
|
||||||
'warning': '<%:Warning%>',
|
var _ocIcons = {
|
||||||
'error': '<%:Error%>',
|
SVG_COMPARE: '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="2" y="3" width="8" height="18" rx="2" stroke="currentColor" stroke-width="2" fill="none"/><rect x="14" y="3" width="8" height="18" rx="2" stroke="currentColor" stroke-width="2" fill="none"/></svg>',
|
||||||
'debug': '<%:Debug%>',
|
SVG_RESTORE: '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="18" height="18" rx="2" stroke="currentColor" stroke-width="2" fill="none"/></svg>'
|
||||||
'tip': '<%:Tip%>',
|
|
||||||
'watchdog': '<%:Watchdog%>',
|
|
||||||
'fatal': '<%:Fatal%>'
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Uses EditorView.updateListener instead of view.dispatch override.
|
||||||
|
// dispatch() can receive TransactionSpec objects which lack docChanged.
|
||||||
|
|
||||||
var ConfigEditor = {
|
var ConfigEditor = {
|
||||||
overlay: null,
|
overlay: null,
|
||||||
model: null,
|
model: null,
|
||||||
editorInstance: null,
|
editorInstance: null,
|
||||||
|
_currentEditorMode: null,
|
||||||
originalContent: '',
|
originalContent: '',
|
||||||
isModified: false,
|
isModified: false,
|
||||||
currentZoom: 100,
|
currentZoom: 100,
|
||||||
@@ -124,17 +106,7 @@ var ConfigEditor = {
|
|||||||
mergeViewActive: false,
|
mergeViewActive: false,
|
||||||
isFullscreen: false,
|
isFullscreen: false,
|
||||||
mergeShowDifferences: true,
|
mergeShowDifferences: true,
|
||||||
SVG_COMPARE: `
|
|
||||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
||||||
<rect x="3" y="3" width="8" height="18" rx="2" stroke="currentColor" stroke-width="2" fill="none"/>
|
|
||||||
<rect x="13" y="3" width="8" height="18" rx="2" stroke="currentColor" stroke-width="2" fill="none"/>
|
|
||||||
</svg>
|
|
||||||
`,
|
|
||||||
SVG_RESTORE: `
|
|
||||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
||||||
<rect x="3" y="3" width="18" height="18" rx="2" stroke="currentColor" stroke-width="2" fill="none"/>
|
|
||||||
</svg>
|
|
||||||
`,
|
|
||||||
overwriteFiles: [],
|
overwriteFiles: [],
|
||||||
overwriteSubInfo: {},
|
overwriteSubInfo: {},
|
||||||
overwriteCardBar: null,
|
overwriteCardBar: null,
|
||||||
@@ -179,22 +151,7 @@ var ConfigEditor = {
|
|||||||
document.addEventListener('keydown', function(e) {
|
document.addEventListener('keydown', function(e) {
|
||||||
if (!self.overlay.classList.contains('show')) return;
|
if (!self.overlay.classList.contains('show')) return;
|
||||||
|
|
||||||
if ((e.ctrlKey || e.metaKey) && (e.key === '=' || e.key === '+')) {
|
if (e.key === 'Escape' && self.isFullscreen) {
|
||||||
e.preventDefault();
|
|
||||||
self.zoomIn();
|
|
||||||
} else if ((e.ctrlKey || e.metaKey) && e.key === '-') {
|
|
||||||
e.preventDefault();
|
|
||||||
self.zoomOut();
|
|
||||||
} else if ((e.ctrlKey || e.metaKey) && e.key === '0') {
|
|
||||||
e.preventDefault();
|
|
||||||
self.resetZoom();
|
|
||||||
} else if (e.key === 'F11') {
|
|
||||||
e.preventDefault();
|
|
||||||
self.toggleFullscreen();
|
|
||||||
} else if (e.key === 'F10' && self.mergeViewActive) {
|
|
||||||
e.preventDefault();
|
|
||||||
self.toggleMergeDifferences();
|
|
||||||
} else if (e.key === 'Escape' && self.isFullscreen) {
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
self.toggleFullscreen(false);
|
self.toggleFullscreen(false);
|
||||||
} else if (e.key === 'Escape' && !self.isFullscreen) {
|
} else if (e.key === 'Escape' && !self.isFullscreen) {
|
||||||
@@ -240,11 +197,11 @@ var ConfigEditor = {
|
|||||||
self.showMergeView();
|
self.showMergeView();
|
||||||
self.currentViewMode = 'original';
|
self.currentViewMode = 'original';
|
||||||
layoutBtn.title = "<%:Restore%>";
|
layoutBtn.title = "<%:Restore%>";
|
||||||
layoutBtn.innerHTML = self.SVG_RESTORE;
|
layoutBtn.innerHTML = _ocIcons.SVG_RESTORE;
|
||||||
} else {
|
} else {
|
||||||
self.hideMergeView();
|
self.hideMergeView();
|
||||||
layoutBtn.title = "<%:Compare%>";
|
layoutBtn.title = "<%:Compare%>";
|
||||||
layoutBtn.innerHTML = self.SVG_COMPARE;
|
layoutBtn.innerHTML = _ocIcons.SVG_COMPARE;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -255,9 +212,6 @@ var ConfigEditor = {
|
|||||||
|
|
||||||
show: function(configFile) {
|
show: function(configFile) {
|
||||||
var self = this;
|
var self = this;
|
||||||
if (typeof isDarkBackground === 'function' && isDarkBackground(document.body)) {
|
|
||||||
document.documentElement.setAttribute('data-darkmode', 'true');
|
|
||||||
}
|
|
||||||
this.isOverwrite = false;
|
this.isOverwrite = false;
|
||||||
this.currentViewMode = 'original';
|
this.currentViewMode = 'original';
|
||||||
this.currentConfigFile = '';
|
this.currentConfigFile = '';
|
||||||
@@ -276,8 +230,7 @@ var ConfigEditor = {
|
|||||||
textarea.value = '';
|
textarea.value = '';
|
||||||
textarea.style.display = 'none';
|
textarea.style.display = 'none';
|
||||||
}
|
}
|
||||||
var loadingDiv = document.getElementById('config-editor-loading');
|
ocShowLoading(textarea.parentNode, '<%:Loading config file...%>');
|
||||||
if (loadingDiv) loadingDiv.style.display = 'flex';
|
|
||||||
var mergeview = document.getElementById('config-mergeview-container');
|
var mergeview = document.getElementById('config-mergeview-container');
|
||||||
if (mergeview) mergeview.style.display = 'none';
|
if (mergeview) mergeview.style.display = 'none';
|
||||||
|
|
||||||
@@ -335,8 +288,7 @@ var ConfigEditor = {
|
|||||||
textarea.value = '';
|
textarea.value = '';
|
||||||
textarea.style.display = 'none';
|
textarea.style.display = 'none';
|
||||||
}
|
}
|
||||||
var loadingDiv = document.getElementById('config-editor-loading');
|
ocShowLoading(textarea.parentNode, '<%:Loading config file...%>');
|
||||||
if (loadingDiv) loadingDiv.style.display = 'flex';
|
|
||||||
var mergeview = document.getElementById('config-mergeview-container');
|
var mergeview = document.getElementById('config-mergeview-container');
|
||||||
if (mergeview) mergeview.style.display = 'none';
|
if (mergeview) mergeview.style.display = 'none';
|
||||||
|
|
||||||
@@ -387,65 +339,37 @@ var ConfigEditor = {
|
|||||||
}
|
}
|
||||||
this.editorInstance = null;
|
this.editorInstance = null;
|
||||||
}
|
}
|
||||||
|
this._currentEditorMode = null;
|
||||||
var textarea = document.getElementById('config-editor-textarea');
|
var textarea = document.getElementById('config-editor-textarea');
|
||||||
if (textarea) textarea.style.display = '';
|
if (textarea) textarea.style.display = '';
|
||||||
},
|
},
|
||||||
|
|
||||||
toggleFullscreen: function(forceState) {
|
toggleFullscreen: function(forceState) {
|
||||||
var target = null;
|
|
||||||
if (this.mergeViewActive && this.editorInstance && this.editorInstance.dom) {
|
|
||||||
target = this.editorInstance.dom;
|
|
||||||
} else if (this.editorInstance && this.editorInstance.dom) {
|
|
||||||
target = this.editorInstance.dom;
|
|
||||||
}
|
|
||||||
if (!target) return;
|
|
||||||
|
|
||||||
var nextState = typeof forceState === 'boolean' ? forceState : !this.isFullscreen;
|
var nextState = typeof forceState === 'boolean' ? forceState : !this.isFullscreen;
|
||||||
this.isFullscreen = nextState;
|
this.isFullscreen = nextState;
|
||||||
|
window._ocFullscreenActive = nextState;
|
||||||
|
if (typeof CM6 !== 'undefined' && CM6.toggleFullscreen) {
|
||||||
if (nextState) {
|
if (nextState) {
|
||||||
target.classList.add('cm-fullscreen');
|
var dom = this.editorInstance;
|
||||||
target._fsOriginalParent = target.parentNode;
|
if (dom && dom.dom) dom = dom.dom;
|
||||||
if (target.parentNode !== document.body) document.body.appendChild(target);
|
if (dom && dom.classList) {
|
||||||
target.style.setProperty('position', 'fixed', 'important');
|
if (typeof _ocEnterFullscreen === 'function') _ocEnterFullscreen(dom);
|
||||||
target.style.setProperty('top', '0', 'important');
|
CM6.toggleFullscreen(dom);
|
||||||
target.style.setProperty('left', '0', 'important');
|
}
|
||||||
target.style.setProperty('right', '0', 'important');
|
|
||||||
target.style.setProperty('bottom', '0', 'important');
|
|
||||||
target.style.setProperty('width', '100vw', 'important');
|
|
||||||
target.style.setProperty('height', '100vh', 'important');
|
|
||||||
target.style.setProperty('z-index', '999999', 'important');
|
|
||||||
target.style.setProperty('background', 'var(--bg-light, #f5f5f5)', 'important');
|
|
||||||
} else {
|
} else {
|
||||||
target.classList.remove('cm-fullscreen');
|
var fsEl = document.getElementById('oc-fullscreen-active');
|
||||||
if (target._fsOriginalParent && target._fsOriginalParent !== document.body) {
|
if (fsEl) CM6.toggleFullscreen(fsEl);
|
||||||
target._fsOriginalParent.appendChild(target);
|
if (typeof _ocExitFullscreen === 'function') _ocExitFullscreen();
|
||||||
}
|
}
|
||||||
target._fsOriginalParent = null;
|
|
||||||
target.style.position = '';
|
|
||||||
target.style.top = '';
|
|
||||||
target.style.left = '';
|
|
||||||
target.style.right = '';
|
|
||||||
target.style.bottom = '';
|
|
||||||
target.style.width = '';
|
|
||||||
target.style.height = '';
|
|
||||||
target.style.zIndex = '';
|
|
||||||
target.style.background = '';
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
toggleMergeDifferences: function() {
|
|
||||||
if (!this.mergeViewActive || !this.editorInstance || !this.editorInstance.reconfigure) return;
|
|
||||||
this.mergeShowDifferences = !this.mergeShowDifferences;
|
|
||||||
this.editorInstance.reconfigure({ highlightChanges: this.mergeShowDifferences, gutter: this.mergeShowDifferences });
|
|
||||||
if (this.editorInstance.dom) {
|
|
||||||
this.editorInstance.dom.classList.toggle('oc-diff-hidden', !this.mergeShowDifferences);
|
|
||||||
}
|
}
|
||||||
|
ocUpdateTheme();
|
||||||
},
|
},
|
||||||
|
|
||||||
hide: function() {
|
hide: function() {
|
||||||
this.overlay.classList.remove('show');
|
this.overlay.classList.remove('show');
|
||||||
|
|
||||||
this._destroyEditor();
|
this._destroyEditor();
|
||||||
|
window._mergeViewInstance = null;
|
||||||
|
|
||||||
this.isModified = false;
|
this.isModified = false;
|
||||||
this.originalContent = '';
|
this.originalContent = '';
|
||||||
@@ -454,21 +378,22 @@ var ConfigEditor = {
|
|||||||
this.currentConfigFile = '';
|
this.currentConfigFile = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
var loadingDiv = document.getElementById('config-editor-loading');
|
|
||||||
var textarea = document.getElementById('config-editor-textarea');
|
var textarea = document.getElementById('config-editor-textarea');
|
||||||
var mergeview = document.getElementById('config-mergeview-container');
|
var mergeview = document.getElementById('config-mergeview-container');
|
||||||
var editor_help = document.getElementById('config-editor-help');
|
var editor_help = document.getElementById('config-editor-help');
|
||||||
var layoutBtn = document.getElementById('config-editor-layout');
|
var layoutBtn = document.getElementById('config-editor-layout');
|
||||||
|
|
||||||
if (loadingDiv) loadingDiv.style.display = 'flex';
|
if (textarea) {
|
||||||
if (textarea) textarea.style.display = 'none';
|
ocHideLoading(textarea.parentNode);
|
||||||
|
textarea.style.display = 'none';
|
||||||
|
}
|
||||||
if (mergeview) mergeview.style.display = 'none';
|
if (mergeview) mergeview.style.display = 'none';
|
||||||
if (layoutBtn) {
|
if (layoutBtn) {
|
||||||
layoutBtn.classList.remove('active');
|
layoutBtn.classList.remove('active');
|
||||||
layoutBtn.title = "<%:Compare%>";
|
layoutBtn.title = "<%:Compare%>";
|
||||||
layoutBtn.innerHTML = this.SVG_COMPARE;
|
layoutBtn.innerHTML = _ocIcons.SVG_COMPARE;
|
||||||
}
|
}
|
||||||
if (editor_help) editor_help.textContent = '<%:Press F11 for fullscreen, Esc to exit fullscreen, Ctrl+Mouse Wheel to zoom%>';
|
if (editor_help) editor_help.innerHTML = '<%:Press%> <b style="color:var(--success-color)">F11</b> <%:for fullscreen,%> <b style="color:var(--success-color)">Esc</b> <%:to exit fullscreen,%> <b style="color:var(--success-color)">Ctrl + <%:Mouse Wheel%></b> <%:to zoom%>';
|
||||||
},
|
},
|
||||||
|
|
||||||
formatDisplayName: function(fileName) {
|
formatDisplayName: function(fileName) {
|
||||||
@@ -522,11 +447,9 @@ var ConfigEditor = {
|
|||||||
loadConfigContent: function() {
|
loadConfigContent: function() {
|
||||||
var self = this;
|
var self = this;
|
||||||
var statusText = document.getElementById('config-editor-status-text');
|
var statusText = document.getElementById('config-editor-status-text');
|
||||||
var loadingDiv = document.getElementById('config-editor-loading');
|
|
||||||
var textarea = document.getElementById('config-editor-textarea');
|
var textarea = document.getElementById('config-editor-textarea');
|
||||||
var mergeview = document.getElementById('config-mergeview-container');
|
var mergeview = document.getElementById('config-mergeview-container');
|
||||||
if (mergeview) mergeview.style.display = 'none';
|
if (mergeview) mergeview.style.display = 'none';
|
||||||
if (textarea) textarea.style.display = 'block';
|
|
||||||
|
|
||||||
statusText.textContent = '<%:Loading...%>';
|
statusText.textContent = '<%:Loading...%>';
|
||||||
|
|
||||||
@@ -551,17 +474,30 @@ var ConfigEditor = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function renderEditor(content, mode, readOnly, lint) {
|
function renderEditor(content, mode, readOnly, lint) {
|
||||||
loadingDiv.style.display = 'none';
|
|
||||||
textarea.value = content;
|
textarea.value = content;
|
||||||
textarea.style.display = 'block';
|
|
||||||
|
var editorKey = mode + '|' + (readOnly ? 'r' : 'w') + '|' + (lint ? 'l' : 'n');
|
||||||
|
|
||||||
|
if (self.editorInstance && self._currentEditorMode === editorKey && !self.mergeViewActive) {
|
||||||
|
self.originalContent = content;
|
||||||
|
self.editorInstance.dispatch({
|
||||||
|
changes: { from: 0, to: self.editorInstance.state.doc.length, insert: content }
|
||||||
|
});
|
||||||
|
self.isModified = false;
|
||||||
|
self.updateSaveButtonState();
|
||||||
|
textarea.style.display = 'none';
|
||||||
|
ocHideLoading(textarea.parentNode);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (self.editorInstance) {
|
if (self.editorInstance) {
|
||||||
self._destroyEditor();
|
self._destroyEditor();
|
||||||
}
|
}
|
||||||
|
self._currentEditorMode = editorKey;
|
||||||
|
|
||||||
var exts = [];
|
var exts = [];
|
||||||
var isDark = (typeof isDarkBackground === 'function' && isDarkBackground(document.body));
|
var isDark = isDarkBackground(document.body);
|
||||||
var topSearch = (CM6 && typeof CM6.topSearchExtension === 'function') ? CM6.topSearchExtension() : null;
|
var topSearch = (CM6 && CM6.topSearchExtension) ? CM6.topSearchExtension() : null;
|
||||||
exts.push(CM6.themeExtension(isDark));
|
exts.push(CM6.themeExtension(isDark));
|
||||||
if (topSearch) exts.push(topSearch);
|
if (topSearch) exts.push(topSearch);
|
||||||
|
|
||||||
@@ -599,6 +535,15 @@ var ConfigEditor = {
|
|||||||
}}
|
}}
|
||||||
]));
|
]));
|
||||||
|
|
||||||
|
if (!readOnly) {
|
||||||
|
exts.push(CM6.EditorView.updateListener.of(function(update) {
|
||||||
|
if (update.docChanged) {
|
||||||
|
self.isModified = update.state.doc.toString() !== self.originalContent;
|
||||||
|
self.updateSaveButtonState();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
var parent = textarea.parentNode;
|
var parent = textarea.parentNode;
|
||||||
self.editorInstance = new CM6.EditorView({
|
self.editorInstance = new CM6.EditorView({
|
||||||
state: CM6.EditorState.create({
|
state: CM6.EditorState.create({
|
||||||
@@ -610,17 +555,9 @@ var ConfigEditor = {
|
|||||||
|
|
||||||
textarea.style.display = 'none';
|
textarea.style.display = 'none';
|
||||||
self.editorInstance.dom.style.height = '100%';
|
self.editorInstance.dom.style.height = '100%';
|
||||||
|
ocHideLoading(textarea.parentNode);
|
||||||
|
|
||||||
if (!readOnly) {
|
if (CM6.mirrorThemeScrollbar) CM6.mirrorThemeScrollbar();
|
||||||
var originalDispatch = self.editorInstance.dispatch;
|
|
||||||
self.editorInstance.dispatch = function(tr) {
|
|
||||||
originalDispatch.call(self.editorInstance, tr);
|
|
||||||
if (tr.docChanged) {
|
|
||||||
self.isModified = self.editorInstance.state.doc.toString() !== self.originalContent;
|
|
||||||
self.updateSaveButtonState();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.isOverwrite) {
|
if (!this.isOverwrite) {
|
||||||
@@ -656,12 +593,12 @@ var ConfigEditor = {
|
|||||||
}
|
}
|
||||||
self.updateModeTabs();
|
self.updateModeTabs();
|
||||||
} else {
|
} else {
|
||||||
loadingDiv.querySelector('span').textContent = '<%:Failed to load config file%>';
|
ocHideLoading(textarea.parentNode);
|
||||||
statusText.textContent = '<%:Load failed%>';
|
statusText.textContent = '<%:Load failed%>';
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(function(err) {
|
.catch(function(err) {
|
||||||
loadingDiv.querySelector('span').textContent = '<%:Failed to load config file%>';
|
ocHideLoading(textarea.parentNode);
|
||||||
statusText.textContent = '<%:Load failed%>';
|
statusText.textContent = '<%:Load failed%>';
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -671,17 +608,18 @@ var ConfigEditor = {
|
|||||||
if (this.isOverwrite) return;
|
if (this.isOverwrite) return;
|
||||||
var container = document.getElementById('config-mergeview-container');
|
var container = document.getElementById('config-mergeview-container');
|
||||||
var textarea = document.getElementById('config-editor-textarea');
|
var textarea = document.getElementById('config-editor-textarea');
|
||||||
var loadingDiv = document.getElementById('config-editor-loading');
|
|
||||||
var tabs = document.getElementById('config-mode-tabs');
|
var tabs = document.getElementById('config-mode-tabs');
|
||||||
var editor_help = document.getElementById('config-editor-help');
|
var editor_help = document.getElementById('config-editor-help');
|
||||||
var statusText = document.getElementById('config-editor-status-text');
|
var statusText = document.getElementById('config-editor-status-text');
|
||||||
|
|
||||||
if (tabs) tabs.style.display = 'none';
|
if (tabs) tabs.style.display = 'none';
|
||||||
if (textarea) textarea.style.display = 'none';
|
if (textarea) {
|
||||||
if (loadingDiv) loadingDiv.style.display = 'none';
|
textarea.style.display = 'none';
|
||||||
|
ocHideLoading(textarea.parentNode);
|
||||||
|
}
|
||||||
if (container) container.style.display = 'block';
|
if (container) container.style.display = 'block';
|
||||||
if (statusText) statusText.textContent = '<%:Loading...%>';
|
if (statusText) statusText.textContent = '<%:Loading...%>';
|
||||||
if (editor_help) editor_help.textContent = '<%:Press F10 to toggle differences, F11 for fullscreen, Esc to exit fullscreen, Ctrl+Mouse Wheel to zoom%>';
|
if (editor_help) editor_help.innerHTML = '<%:Press%> <b style="color:var(--success-color)">F10</b> <%:to toggle differences,%> <b style="color:var(--success-color)">F11</b> <%:for fullscreen,%> <b style="color:var(--success-color)">Esc</b> <%:to exit fullscreen,%> <b style="color:var(--success-color)">Ctrl + <%:Mouse Wheel%></b> <%:to zoom%>';
|
||||||
|
|
||||||
var getOriginal = function() {
|
var getOriginal = function() {
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
@@ -711,9 +649,9 @@ var ConfigEditor = {
|
|||||||
container.innerHTML = '';
|
container.innerHTML = '';
|
||||||
if (self.editorInstance) self._destroyEditor();
|
if (self.editorInstance) self._destroyEditor();
|
||||||
|
|
||||||
var isDark = (typeof isDarkBackground === 'function' && isDarkBackground(document.body));
|
var isDark = isDarkBackground(document.body);
|
||||||
var themeExt = CM6.themeExtension(isDark);
|
var themeExt = CM6.themeExtension(isDark);
|
||||||
var topSearch = (CM6 && typeof CM6.topSearchExtension === 'function') ? CM6.topSearchExtension() : null;
|
var topSearch = (CM6 && CM6.topSearchExtension) ? CM6.topSearchExtension() : null;
|
||||||
var extA = [CM6.baseExtensions(), themeExt, CM6.placeholderExtension('<%:Edit original config...%>'), CM6.yaml(), CM6.yamlLinter(), CM6.lintGutter(), CM6.autocompletion({ override: [CM6.mihomoCompletion] }), CM6.indentUnit.of(" "), CM6.indentMarkerExtension()];
|
var extA = [CM6.baseExtensions(), themeExt, CM6.placeholderExtension('<%:Edit original config...%>'), CM6.yaml(), CM6.yamlLinter(), CM6.lintGutter(), CM6.autocompletion({ override: [CM6.mihomoCompletion] }), CM6.indentUnit.of(" "), CM6.indentMarkerExtension()];
|
||||||
var extB = [CM6.baseExtensions(), themeExt, CM6.placeholderExtension('<%:Runtime config (read only)%>'), CM6.yaml(), CM6.indentUnit.of(" "), CM6.indentMarkerExtension(), CM6.EditorState.readOnly.of(true)];
|
var extB = [CM6.baseExtensions(), themeExt, CM6.placeholderExtension('<%:Runtime config (read only)%>'), CM6.yaml(), CM6.indentUnit.of(" "), CM6.indentMarkerExtension(), CM6.EditorState.readOnly.of(true)];
|
||||||
var mergeDefaults = CM6.mergeDefaultConfig || {};
|
var mergeDefaults = CM6.mergeDefaultConfig || {};
|
||||||
@@ -722,6 +660,13 @@ var ConfigEditor = {
|
|||||||
extB.push(topSearch);
|
extB.push(topSearch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extA.push(CM6.EditorView.updateListener.of(function(update) {
|
||||||
|
if (update.docChanged) {
|
||||||
|
self.isModified = update.state.doc.toString() !== self.originalContent;
|
||||||
|
self.updateSaveButtonState();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
self.editorInstance = new CM6.MergeView({
|
self.editorInstance = new CM6.MergeView({
|
||||||
a: {
|
a: {
|
||||||
doc: original,
|
doc: original,
|
||||||
@@ -733,25 +678,17 @@ var ConfigEditor = {
|
|||||||
},
|
},
|
||||||
parent: container,
|
parent: container,
|
||||||
diffConfig: mergeDefaults.diffConfig || { scanLimit: 5000 },
|
diffConfig: mergeDefaults.diffConfig || { scanLimit: 5000 },
|
||||||
gutter: typeof mergeDefaults.gutter === 'boolean' ? mergeDefaults.gutter : true,
|
gutter: mergeDefaults.gutter !== false,
|
||||||
revertControls: mergeDefaults.revertControls || 'b-to-a',
|
revertControls: mergeDefaults.revertControls || 'b-to-a',
|
||||||
highlightChanges: self.mergeShowDifferences,
|
highlightChanges: self.mergeShowDifferences,
|
||||||
collapseUnchanged: typeof mergeDefaults.collapseUnchanged !== 'undefined' ? mergeDefaults.collapseUnchanged : false
|
collapseUnchanged: mergeDefaults.collapseUnchanged || false
|
||||||
});
|
});
|
||||||
|
|
||||||
var leftView = self.editorInstance.a;
|
|
||||||
if (leftView) {
|
|
||||||
var origDispatchA = leftView.dispatch;
|
|
||||||
leftView.dispatch = function(tr) {
|
|
||||||
origDispatchA.call(leftView, tr);
|
|
||||||
if (tr.docChanged) {
|
|
||||||
self.isModified = leftView.state.doc.toString() !== self.originalContent;
|
|
||||||
self.updateSaveButtonState();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
self.mergeViewActive = true;
|
self.mergeViewActive = true;
|
||||||
|
window._mergeViewInstance = self.editorInstance;
|
||||||
|
|
||||||
|
if (CM6.mirrorThemeScrollbar) CM6.mirrorThemeScrollbar();
|
||||||
|
|
||||||
if (statusText) statusText.textContent = '<%:Compare mode: left(Original Config), right(Runtime Config)%>';
|
if (statusText) statusText.textContent = '<%:Compare mode: left(Original Config), right(Runtime Config)%>';
|
||||||
var layoutBtn = document.getElementById('config-editor-layout');
|
var layoutBtn = document.getElementById('config-editor-layout');
|
||||||
if (layoutBtn) layoutBtn.classList.add('active');
|
if (layoutBtn) layoutBtn.classList.add('active');
|
||||||
@@ -771,15 +708,16 @@ var ConfigEditor = {
|
|||||||
if (textarea) textarea.style.display = 'block';
|
if (textarea) textarea.style.display = 'block';
|
||||||
if (!this.isOverwrite && tabs) tabs.style.display = 'flex';
|
if (!this.isOverwrite && tabs) tabs.style.display = 'flex';
|
||||||
this.mergeViewActive = false;
|
this.mergeViewActive = false;
|
||||||
|
window._mergeViewInstance = null;
|
||||||
this.loadConfigContent();
|
this.loadConfigContent();
|
||||||
|
|
||||||
if (layoutBtn) {
|
if (layoutBtn) {
|
||||||
layoutBtn.classList.remove('active');
|
layoutBtn.classList.remove('active');
|
||||||
layoutBtn.title = "<%:Compare%>";
|
layoutBtn.title = "<%:Compare%>";
|
||||||
layoutBtn.innerHTML = this.SVG_COMPARE;
|
layoutBtn.innerHTML = _ocIcons.SVG_COMPARE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (editor_help) editor_help.textContent = '<%:Press F11 for fullscreen, Esc to exit fullscreen, Ctrl+Mouse Wheel to zoom%>';
|
if (editor_help) editor_help.innerHTML = '<%:Press%> <b style="color:var(--success-color)">F11</b> <%:for fullscreen,%> <b style="color:var(--success-color)">Esc</b> <%:to exit fullscreen,%> <b style="color:var(--success-color)">Ctrl + <%:Mouse Wheel%></b> <%:to zoom%>';
|
||||||
},
|
},
|
||||||
|
|
||||||
saveConfigContent: function() {
|
saveConfigContent: function() {
|
||||||
@@ -1871,6 +1809,73 @@ var ConfigEditor = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
addOverwriteParamRow: function(container, name, value) {
|
||||||
|
var row = document.createElement('div');
|
||||||
|
row.className = 'form-row overwrite-param-row';
|
||||||
|
row.style.cssText = 'align-items: center; gap: 6px; margin-bottom: 6px;';
|
||||||
|
|
||||||
|
var nameInput = document.createElement('input');
|
||||||
|
nameInput.type = 'text';
|
||||||
|
nameInput.className = 'form-input';
|
||||||
|
nameInput.placeholder = 'Key';
|
||||||
|
nameInput.value = name || '';
|
||||||
|
nameInput.style.cssText = 'flex: 1; height: 32px;';
|
||||||
|
|
||||||
|
var valueInput = document.createElement('input');
|
||||||
|
valueInput.type = 'text';
|
||||||
|
valueInput.className = 'form-input';
|
||||||
|
valueInput.placeholder = 'Value';
|
||||||
|
valueInput.value = value || '';
|
||||||
|
valueInput.style.cssText = 'flex: 1.5; height: 32px;';
|
||||||
|
|
||||||
|
var removeBtn = document.createElement('button');
|
||||||
|
removeBtn.type = 'button';
|
||||||
|
removeBtn.className = 'icon-btn';
|
||||||
|
removeBtn.title = '<%:Remove%>';
|
||||||
|
removeBtn.style.cssText = 'flex-shrink: 0;';
|
||||||
|
removeBtn.innerHTML = '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>';
|
||||||
|
removeBtn.addEventListener('click', function() {
|
||||||
|
row.parentNode.removeChild(row);
|
||||||
|
if (container.children.length === 0) {
|
||||||
|
container.style.display = 'none';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
row.appendChild(nameInput);
|
||||||
|
row.appendChild(valueInput);
|
||||||
|
row.appendChild(removeBtn);
|
||||||
|
container.appendChild(row);
|
||||||
|
container.style.display = 'block';
|
||||||
|
},
|
||||||
|
|
||||||
|
buildOverwriteParamRows: function(container, paramStr) {
|
||||||
|
if (!paramStr) return;
|
||||||
|
var pairs = paramStr.split(';');
|
||||||
|
for (var i = 0; i < pairs.length; i++) {
|
||||||
|
var pair = pairs[i].trim();
|
||||||
|
if (pair) {
|
||||||
|
var eqIdx = pair.indexOf('=');
|
||||||
|
var name = eqIdx > 0 ? pair.substring(0, eqIdx).trim() : pair;
|
||||||
|
var value = eqIdx > 0 ? pair.substring(eqIdx + 1).trim() : '';
|
||||||
|
this.addOverwriteParamRow(container, name, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
collectOverwriteParams: function(container) {
|
||||||
|
var rows = container.querySelectorAll('.overwrite-param-row');
|
||||||
|
var params = [];
|
||||||
|
for (var i = 0; i < rows.length; i++) {
|
||||||
|
var inputs = rows[i].querySelectorAll('input');
|
||||||
|
var name = inputs[0].value.trim();
|
||||||
|
var value = inputs[1].value.trim();
|
||||||
|
if (name) {
|
||||||
|
params.push(name + '=' + value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return params.join(';');
|
||||||
|
},
|
||||||
|
|
||||||
getOverwriteConfigSelection: function(root, dropdownId) {
|
getOverwriteConfigSelection: function(root, dropdownId) {
|
||||||
var dropdown = root.querySelector('#' + dropdownId);
|
var dropdown = root.querySelector('#' + dropdownId);
|
||||||
if (!dropdown) return [];
|
if (!dropdown) return [];
|
||||||
@@ -1994,7 +1999,9 @@ var ConfigEditor = {
|
|||||||
</div>
|
</div>
|
||||||
<div class="form-group" id="overwrite-subscribe-param-group" style="display:'block';">
|
<div class="form-group" id="overwrite-subscribe-param-group" style="display:'block';">
|
||||||
<label><%:Environment variable%>:</label>
|
<label><%:Environment variable%>:</label>
|
||||||
<input type="text" class="form-input" name="param" id="overwrite-subscribe-param" value="${sub.param||''}" placeholder="key1=value1;key2=value2">
|
<div class="form-help" style="margin-bottom: unset;"><%:Set environment variables for the overwrite script%></div>
|
||||||
|
<div id="overwrite-subscribe-param-container" style="display:none;"></div>
|
||||||
|
<button type="button" id="overwrite-subscribe-param-add" class="btn upload-btn" style="align-self: flex-start; margin-top: 4px; padding: 4px 12px; font-size: 13px; border: 1px solid var(--primary-color); border-radius: var(--radius-sm); cursor: pointer;">+ <%:Add Param%></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="upload-progress" id="overwrite-upload-progress" style="display:none;">
|
<div class="upload-progress" id="overwrite-upload-progress" style="display:none;">
|
||||||
<div class="progress-bar">
|
<div class="progress-bar">
|
||||||
@@ -2022,8 +2029,7 @@ var ConfigEditor = {
|
|||||||
|
|
||||||
var ocDiv = document.createElement('div');
|
var ocDiv = document.createElement('div');
|
||||||
ocDiv.className = 'oc';
|
ocDiv.className = 'oc';
|
||||||
var mainOc = document.querySelector('.oc[data-darkmode="true"]');
|
if (document.documentElement.getAttribute('data-darkmode') === 'true') {
|
||||||
if (mainOc) {
|
|
||||||
ocDiv.setAttribute('data-darkmode', 'true');
|
ocDiv.setAttribute('data-darkmode', 'true');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2175,6 +2181,14 @@ var ConfigEditor = {
|
|||||||
if (model.querySelector('#overwrite-subscribe-filename')) {
|
if (model.querySelector('#overwrite-subscribe-filename')) {
|
||||||
model.querySelector('#overwrite-subscribe-filename').addEventListener('input', validateAddOverwriteForm);
|
model.querySelector('#overwrite-subscribe-filename').addEventListener('input', validateAddOverwriteForm);
|
||||||
}
|
}
|
||||||
|
var paramContainer = model.querySelector('#overwrite-subscribe-param-container');
|
||||||
|
if (paramContainer) {
|
||||||
|
self.buildOverwriteParamRows(paramContainer, '');
|
||||||
|
model.querySelector('#overwrite-subscribe-param-add').addEventListener('click', function() {
|
||||||
|
self.addOverwriteParamRow(paramContainer, '', '');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (model.querySelector('#overwrite-subscribe-type')) {
|
if (model.querySelector('#overwrite-subscribe-type')) {
|
||||||
model.querySelector('#overwrite-subscribe-type').addEventListener('change', validateAddOverwriteForm);
|
model.querySelector('#overwrite-subscribe-type').addEventListener('change', validateAddOverwriteForm);
|
||||||
}
|
}
|
||||||
@@ -2247,7 +2261,7 @@ var ConfigEditor = {
|
|||||||
var update_days = form.querySelector('#overwrite-subscribe-update-days').value;
|
var update_days = form.querySelector('#overwrite-subscribe-update-days').value;
|
||||||
var update_hour = form.querySelector('#overwrite-subscribe-update-hour').value;
|
var update_hour = form.querySelector('#overwrite-subscribe-update-hour').value;
|
||||||
var type = form.querySelector('#overwrite-subscribe-type').value;
|
var type = form.querySelector('#overwrite-subscribe-type').value;
|
||||||
var param = form.querySelector('#overwrite-subscribe-param').value.trim();
|
var param = self.collectOverwriteParams(form.querySelector('#overwrite-subscribe-param-container'));
|
||||||
var selectedConfigPaths = self.getOverwriteConfigSelection(model, 'overwrite-subscribe-config-dropdown');
|
var selectedConfigPaths = self.getOverwriteConfigSelection(model, 'overwrite-subscribe-config-dropdown');
|
||||||
if (!filename) {
|
if (!filename) {
|
||||||
alert('<%:Please enter a filename%>');
|
alert('<%:Please enter a filename%>');
|
||||||
@@ -2329,8 +2343,7 @@ var ConfigEditor = {
|
|||||||
|
|
||||||
var ocDiv = document.createElement('div');
|
var ocDiv = document.createElement('div');
|
||||||
ocDiv.className = 'oc';
|
ocDiv.className = 'oc';
|
||||||
var mainOc = document.querySelector('.oc[data-darkmode="true"]');
|
if (document.documentElement.getAttribute('data-darkmode') === 'true') {
|
||||||
if (mainOc) {
|
|
||||||
ocDiv.setAttribute('data-darkmode', 'true');
|
ocDiv.setAttribute('data-darkmode', 'true');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2376,6 +2389,17 @@ var ConfigEditor = {
|
|||||||
|
|
||||||
this.bindOverwriteConfigDropdown(model.querySelector('#overwrite-subscribe-config-dropdown'));
|
this.bindOverwriteConfigDropdown(model.querySelector('#overwrite-subscribe-config-dropdown'));
|
||||||
|
|
||||||
|
var paramContainer = model.querySelector('#overwrite-subscribe-param-container');
|
||||||
|
if (paramContainer && sub && sub.param) {
|
||||||
|
self.buildOverwriteParamRows(paramContainer, sub.param);
|
||||||
|
}
|
||||||
|
var paramAddBtn = model.querySelector('#overwrite-subscribe-param-add');
|
||||||
|
if (paramAddBtn) {
|
||||||
|
paramAddBtn.addEventListener('click', function() {
|
||||||
|
self.addOverwriteParamRow(paramContainer, '', '');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
var typeSelect = model.querySelector('#overwrite-subscribe-type');
|
var typeSelect = model.querySelector('#overwrite-subscribe-type');
|
||||||
var urlGroup = model.querySelector('#overwrite-subscribe-url-group');
|
var urlGroup = model.querySelector('#overwrite-subscribe-url-group');
|
||||||
var updateGroup = model.querySelector('#overwrite-subscribe-update-group');
|
var updateGroup = model.querySelector('#overwrite-subscribe-update-group');
|
||||||
@@ -2435,7 +2459,7 @@ var ConfigEditor = {
|
|||||||
var newName = form.querySelector('#overwrite-subscribe-filename').value.trim();
|
var newName = form.querySelector('#overwrite-subscribe-filename').value.trim();
|
||||||
var type = form.querySelector('#overwrite-subscribe-type').value;
|
var type = form.querySelector('#overwrite-subscribe-type').value;
|
||||||
var url = form.querySelector('#overwrite-subscribe-url').value.trim();
|
var url = form.querySelector('#overwrite-subscribe-url').value.trim();
|
||||||
var param = form.querySelector('#overwrite-subscribe-param').value.trim();
|
var param = self.collectOverwriteParams(form.querySelector('#overwrite-subscribe-param-container'));
|
||||||
var selectedConfigPaths = self.getOverwriteConfigSelection(model, 'overwrite-subscribe-config-dropdown');
|
var selectedConfigPaths = self.getOverwriteConfigSelection(model, 'overwrite-subscribe-config-dropdown');
|
||||||
|
|
||||||
if (!newName) {
|
if (!newName) {
|
||||||
@@ -2465,6 +2489,7 @@ var ConfigEditor = {
|
|||||||
}
|
}
|
||||||
formData.delete('config');
|
formData.delete('config');
|
||||||
formData.append('config', selectedConfigPaths.join('\n'));
|
formData.append('config', selectedConfigPaths.join('\n'));
|
||||||
|
formData.append('param', param);
|
||||||
if (newName !== name) {
|
if (newName !== name) {
|
||||||
formData.append('old_filename', name);
|
formData.append('old_filename', name);
|
||||||
}
|
}
|
||||||
@@ -2538,7 +2563,7 @@ var ConfigEditor = {
|
|||||||
this.hideMergeView();
|
this.hideMergeView();
|
||||||
this.hide();
|
this.hide();
|
||||||
|
|
||||||
if (window.OverwriteSubscribeManager && typeof window.OverwriteSubscribeManager.load === 'function') {
|
if (window.OverwriteSubscribeManager && window.OverwriteSubscribeManager.load) {
|
||||||
window.OverwriteSubscribeManager.load(true);
|
window.OverwriteSubscribeManager.load(true);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
@@ -2548,39 +2573,21 @@ var ConfigEditor = {
|
|||||||
|
|
||||||
updateZoom: function(newZoom) {
|
updateZoom: function(newZoom) {
|
||||||
this.currentZoom = newZoom;
|
this.currentZoom = newZoom;
|
||||||
|
ocApplyZoom(this.editorInstance, newZoom);
|
||||||
if (this.editorInstance) {
|
|
||||||
var cmEl = null;
|
|
||||||
if (this.editorInstance.dom) cmEl = this.editorInstance.dom;
|
|
||||||
else if (this.editorInstance.a && this.editorInstance.a.dom) cmEl = this.editorInstance.a.dom;
|
|
||||||
|
|
||||||
if (cmEl) {
|
|
||||||
this.zoomLevels.forEach(function(level) {
|
|
||||||
cmEl.classList.remove('zoom-' + level);
|
|
||||||
});
|
|
||||||
if (this.currentZoom !== 100) {
|
|
||||||
cmEl.classList.add('zoom-' + this.currentZoom);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
zoomIn: function() {
|
zoomIn: function() {
|
||||||
var currentIndex = this.zoomLevels.indexOf(this.currentZoom);
|
var newZoom = ocZoomIn(this.currentZoom);
|
||||||
if (currentIndex < this.zoomLevels.length - 1) {
|
if (newZoom !== this.currentZoom) this.updateZoom(newZoom);
|
||||||
this.updateZoom(this.zoomLevels[currentIndex + 1]);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
zoomOut: function() {
|
zoomOut: function() {
|
||||||
var currentIndex = this.zoomLevels.indexOf(this.currentZoom);
|
var newZoom = ocZoomOut(this.currentZoom);
|
||||||
if (currentIndex > 0) {
|
if (newZoom !== this.currentZoom) this.updateZoom(newZoom);
|
||||||
this.updateZoom(this.zoomLevels[currentIndex - 1]);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
resetZoom: function() {
|
resetZoom: function() {
|
||||||
this.updateZoom(100);
|
this.updateZoom(ocResetZoom());
|
||||||
},
|
},
|
||||||
|
|
||||||
isPointOnTextContent: function(el, clientX, clientY) {
|
isPointOnTextContent: function(el, clientX, clientY) {
|
||||||
@@ -2846,6 +2853,5 @@ var ConfigEditor = {
|
|||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
ConfigEditor.init();
|
ConfigEditor.init();
|
||||||
if (typeof CM6 !== 'undefined' && CM6.startThemeObserver) CM6.startThemeObserver();
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
@@ -2,91 +2,33 @@
|
|||||||
local fs = require "luci.openclash"
|
local fs = require "luci.openclash"
|
||||||
local plugin_version = fs.oc_version()
|
local plugin_version = fs.oc_version()
|
||||||
%>
|
%>
|
||||||
|
<script src="/luci-static/resources/openclash/js/common.js?v=<%=plugin_version%>"></script>
|
||||||
<link rel="stylesheet" href="/luci-static/resources/openclash/css/oc.css?v=<%=plugin_version%>">
|
<link rel="stylesheet" href="/luci-static/resources/openclash/css/oc.css?v=<%=plugin_version%>">
|
||||||
<script src="/luci-static/resources/openclash/js/cm6.min.js?v=<%=plugin_version%>"></script>
|
<script src="/luci-static/resources/openclash/js/cm6.min.js?v=<%=plugin_version%>"></script>
|
||||||
<script src="/luci-static/resources/openclash/js/common.js?v=<%=plugin_version%>"></script>
|
<script src="/luci-static/resources/openclash/js/oc-icons.js?v=<%=plugin_version%>"></script>
|
||||||
|
|
||||||
<%-
|
<%-
|
||||||
local uci = require("luci.model.uci").cursor()
|
|
||||||
local fs = require "luci.openclash"
|
|
||||||
local conf = fs.uci_get_config("config", "config_path")
|
|
||||||
if not conf then conf = "/etc/openclash/config/config.yaml" end
|
|
||||||
local conf_name = fs.basename(conf)
|
|
||||||
if not conf_name then conf_name = "config.yaml" end
|
|
||||||
local sconf = "/etc/openclash/"..conf_name
|
|
||||||
local path_info = os.getenv("PATH_INFO") or ""
|
local path_info = os.getenv("PATH_INFO") or ""
|
||||||
local sid = path_info:match("(cfg[0-9a-f]+)") or ""
|
local sid = path_info:match("(cfg[0-9a-f]+)") or ""
|
||||||
-%>
|
-%>
|
||||||
|
|
||||||
<table id="my_editor_div" style="width: 100%; text-align: center; display: none;">
|
<%+openclash/common%>
|
||||||
<tr>
|
|
||||||
<td style="width: 50%; overflow: hidden;"><%:Modify Your Config file:%> <b style=color:green><%=conf_name%></b> <%:Here, Except The Settings That Were Taken Over%></td>
|
|
||||||
|
|
||||||
<%-
|
|
||||||
if fs.isfile(sconf) then
|
|
||||||
-%>
|
|
||||||
<td style="width: 50%; overflow: hidden;"><%:Config File Edited By OpenClash For Running%></td>
|
|
||||||
<%-
|
|
||||||
else
|
|
||||||
-%>
|
|
||||||
<td style="width: 50%; overflow: hidden;"><%:Default Config File With Correct Template%></td>
|
|
||||||
<%-
|
|
||||||
end
|
|
||||||
-%>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<script type="text/javascript">//<![CDATA[
|
<script type="text/javascript">//<![CDATA[
|
||||||
var levelTranslations = {
|
|
||||||
'info': '<%:Info%>',
|
|
||||||
'warning': '<%:Warning%>',
|
|
||||||
'error': '<%:Error%>',
|
|
||||||
'debug': '<%:Debug%>',
|
|
||||||
'tip': '<%:Tip%>',
|
|
||||||
'watchdog': '<%:Watchdog%>',
|
|
||||||
'fatal': '<%:Fatal%>'
|
|
||||||
};
|
|
||||||
|
|
||||||
var _mergeShowDifferences = true;
|
ocRegisterEditorHotkeys();
|
||||||
var _fullscreenActive = false;
|
|
||||||
|
|
||||||
if (!window._ocEditorHotkeysBound) {
|
// All editable editors use EditorView.updateListener (not view.dispatch)
|
||||||
document.addEventListener('keydown', function(e) {
|
// to sync content back to the hidden textarea. The dispatch override is
|
||||||
if (e.key === 'F11') {
|
// unreliable because CM6 can pass either a Transaction (with docChanged)
|
||||||
e.preventDefault();
|
// or a TransactionSpec (without docChanged) to dispatch().
|
||||||
if (_fullscreenActive) {
|
|
||||||
CM6.toggleFullscreen(document.getElementById('oc-fullscreen-active'));
|
|
||||||
_fullscreenActive = false;
|
|
||||||
} else {
|
|
||||||
var target = CM6.getActiveEditor();
|
|
||||||
_fullscreenActive = CM6.toggleFullscreen(target);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e.key === 'F10' && window._mergeViewInstance && window._mergeViewInstance.reconfigure) {
|
|
||||||
e.preventDefault();
|
|
||||||
_mergeShowDifferences = !_mergeShowDifferences;
|
|
||||||
window._mergeViewInstance.reconfigure({ highlightChanges: _mergeShowDifferences, gutter: _mergeShowDifferences });
|
|
||||||
if (window._mergeViewInstance.dom) {
|
|
||||||
window._mergeViewInstance.dom.classList.toggle('oc-diff-hidden', !_mergeShowDifferences);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e.key === 'Escape' && _fullscreenActive) {
|
|
||||||
e.preventDefault();
|
|
||||||
CM6.toggleFullscreen(document.getElementById('oc-fullscreen-active'));
|
|
||||||
_fullscreenActive = false;
|
|
||||||
}
|
|
||||||
}, true);
|
|
||||||
window._ocEditorHotkeysBound = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function editor(id, readOnly, wid, height) {
|
function editor(id, readOnly, wid, height) {
|
||||||
|
id.style.display = 'none';
|
||||||
|
id.parentNode.classList.add('oc');
|
||||||
|
ocShowLoading(id.parentNode, '<%:Loading...%>', height);
|
||||||
var isDark = isDarkBackground(document.body);
|
var isDark = isDarkBackground(document.body);
|
||||||
var exts = [CM6.baseExtensions(), CM6.themeExtension(isDark), CM6.placeholderExtension('<%:Enter YAML configuration...%>')];
|
var exts = [CM6.baseExtensions(), CM6.themeExtension(isDark), CM6.placeholderExtension('<%:Enter YAML configuration...%>')];
|
||||||
var topSearch = (CM6 && typeof CM6.topSearchExtension === 'function') ? CM6.topSearchExtension() : null;
|
var topSearch = (CM6 && CM6.topSearchExtension) ? CM6.topSearchExtension() : null;
|
||||||
if (topSearch) exts.push(topSearch);
|
if (topSearch) exts.push(topSearch);
|
||||||
exts.push(CM6.yaml());
|
exts.push(CM6.yaml());
|
||||||
exts.push(CM6.yamlLinter());
|
exts.push(CM6.yamlLinter());
|
||||||
@@ -96,79 +38,86 @@ function editor(id, readOnly, wid, height) {
|
|||||||
exts.push(CM6.indentMarkerExtension());
|
exts.push(CM6.indentMarkerExtension());
|
||||||
if (readOnly) exts.push(CM6.EditorState.readOnly.of(true));
|
if (readOnly) exts.push(CM6.EditorState.readOnly.of(true));
|
||||||
|
|
||||||
|
exts.push(CM6.EditorView.updateListener.of(function(update) {
|
||||||
|
if (update.docChanged) id.value = update.state.doc.toString();
|
||||||
|
}));
|
||||||
|
|
||||||
var view = new CM6.EditorView({
|
var view = new CM6.EditorView({
|
||||||
state: CM6.EditorState.create({ doc: id.value, extensions: exts })
|
state: CM6.EditorState.create({ doc: id.value, extensions: exts })
|
||||||
});
|
});
|
||||||
id.parentNode.insertBefore(view.dom, id.nextSibling);
|
id.parentNode.insertBefore(view.dom, id.nextSibling);
|
||||||
id.style.display = 'none';
|
ocHideLoading(id.parentNode);
|
||||||
id.parentNode.classList.add('oc');
|
ocUpdateTheme();
|
||||||
if (wid && height) {
|
if (wid && height) {
|
||||||
view.dom.style.width = wid;
|
view.dom.style.width = wid;
|
||||||
view.dom.style.height = height;
|
view.dom.style.height = height;
|
||||||
}
|
}
|
||||||
var origDispatch = view.dispatch;
|
|
||||||
view.dispatch = function(tr) {
|
|
||||||
origDispatch.call(view, tr);
|
|
||||||
if (tr.docChanged) id.value = view.state.doc.toString();
|
|
||||||
};
|
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
function shell_editor(id, readOnly, wid, height) {
|
function shell_editor(id, readOnly, wid, height) {
|
||||||
|
id.style.display = 'none';
|
||||||
|
id.parentNode.classList.add('oc');
|
||||||
|
ocShowLoading(id.parentNode, '<%:Loading...%>', height);
|
||||||
var isDark = isDarkBackground(document.body);
|
var isDark = isDarkBackground(document.body);
|
||||||
var exts = [CM6.baseExtensions(), CM6.themeExtension(isDark), CM6.placeholderExtension('<%:Enter shell script...%>')];
|
var exts = [CM6.baseExtensions(), CM6.themeExtension(isDark), CM6.placeholderExtension('<%:Enter shell script...%>')];
|
||||||
var topSearch = (CM6 && typeof CM6.topSearchExtension === 'function') ? CM6.topSearchExtension() : null;
|
var topSearch = (CM6 && CM6.topSearchExtension) ? CM6.topSearchExtension() : null;
|
||||||
if (topSearch) exts.push(topSearch);
|
if (topSearch) exts.push(topSearch);
|
||||||
exts.push(CM6.StreamLanguage.define(CM6.shell));
|
exts.push(CM6.StreamLanguage.define(CM6.shell));
|
||||||
if (readOnly) exts.push(CM6.EditorState.readOnly.of(true));
|
if (readOnly) exts.push(CM6.EditorState.readOnly.of(true));
|
||||||
|
|
||||||
|
exts.push(CM6.EditorView.updateListener.of(function(update) {
|
||||||
|
if (update.docChanged) id.value = update.state.doc.toString();
|
||||||
|
}));
|
||||||
|
|
||||||
var view = new CM6.EditorView({
|
var view = new CM6.EditorView({
|
||||||
state: CM6.EditorState.create({ doc: id.value, extensions: exts })
|
state: CM6.EditorState.create({ doc: id.value, extensions: exts })
|
||||||
});
|
});
|
||||||
id.parentNode.insertBefore(view.dom, id.nextSibling);
|
id.parentNode.insertBefore(view.dom, id.nextSibling);
|
||||||
id.style.display = 'none';
|
ocHideLoading(id.parentNode);
|
||||||
id.parentNode.classList.add('oc');
|
ocUpdateTheme();
|
||||||
if (wid && height) {
|
if (wid && height) {
|
||||||
view.dom.style.width = wid;
|
view.dom.style.width = wid;
|
||||||
view.dom.style.height = height;
|
view.dom.style.height = height;
|
||||||
}
|
}
|
||||||
var origDispatch = view.dispatch;
|
|
||||||
view.dispatch = function(tr) {
|
|
||||||
origDispatch.call(view, tr);
|
|
||||||
if (tr.docChanged) id.value = view.state.doc.toString();
|
|
||||||
};
|
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
function other_editor(id, readOnly, wid, height) {
|
function other_editor(id, readOnly, wid, height) {
|
||||||
|
id.style.display = 'none';
|
||||||
|
id.parentNode.classList.add('oc');
|
||||||
|
ocShowLoading(id.parentNode, '<%:Loading...%>', height);
|
||||||
var isDark = isDarkBackground(document.body);
|
var isDark = isDarkBackground(document.body);
|
||||||
var exts = [CM6.baseExtensions(), CM6.themeExtension(isDark), CM6.placeholderExtension('<%:Enter configuration...%>')];
|
var exts = [CM6.baseExtensions(), CM6.themeExtension(isDark), CM6.placeholderExtension('<%:Enter configuration...%>')];
|
||||||
var topSearch = (CM6 && typeof CM6.topSearchExtension === 'function') ? CM6.topSearchExtension() : null;
|
var topSearch = (CM6 && CM6.topSearchExtension) ? CM6.topSearchExtension() : null;
|
||||||
if (topSearch) exts.push(topSearch);
|
if (topSearch) exts.push(topSearch);
|
||||||
exts.push(CM6.StreamLanguage.define(CM6.properties));
|
exts.push(CM6.StreamLanguage.define(CM6.properties));
|
||||||
if (readOnly) exts.push(CM6.EditorState.readOnly.of(true));
|
if (readOnly) exts.push(CM6.EditorState.readOnly.of(true));
|
||||||
|
|
||||||
|
exts.push(CM6.EditorView.updateListener.of(function(update) {
|
||||||
|
if (update.docChanged) id.value = update.state.doc.toString();
|
||||||
|
}));
|
||||||
|
|
||||||
var view = new CM6.EditorView({
|
var view = new CM6.EditorView({
|
||||||
state: CM6.EditorState.create({ doc: id.value, extensions: exts })
|
state: CM6.EditorState.create({ doc: id.value, extensions: exts })
|
||||||
});
|
});
|
||||||
id.parentNode.insertBefore(view.dom, id.nextSibling);
|
id.parentNode.insertBefore(view.dom, id.nextSibling);
|
||||||
id.style.display = 'none';
|
ocHideLoading(id.parentNode);
|
||||||
id.parentNode.classList.add('oc');
|
ocUpdateTheme();
|
||||||
if (wid && height) {
|
if (wid && height) {
|
||||||
view.dom.style.width = wid;
|
view.dom.style.width = wid;
|
||||||
view.dom.style.height = height;
|
view.dom.style.height = height;
|
||||||
}
|
}
|
||||||
var origDispatch = view.dispatch;
|
|
||||||
view.dispatch = function(tr) {
|
|
||||||
origDispatch.call(view, tr);
|
|
||||||
if (tr.docChanged) id.value = view.state.doc.toString();
|
|
||||||
};
|
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
function log_editor(id, name, readOnly, wid, height) {
|
function log_editor(id, name, readOnly, wid, height) {
|
||||||
var exts = [CM6.lineNumbers(), CM6.EditorView.lineWrapping, CM6.EditorState.readOnly.of(true)];
|
id.style.display = 'none';
|
||||||
var topSearch = (CM6 && typeof CM6.topSearchExtension === 'function') ? CM6.topSearchExtension() : null;
|
id.parentNode.classList.add('oc');
|
||||||
|
ocShowLoading(id.parentNode, '<%:Loading...%>', height);
|
||||||
|
var isDark = isDarkBackground(document.body);
|
||||||
|
var exts = [CM6.lineNumbers(), CM6.EditorView.lineWrapping, CM6.EditorState.readOnly.of(true), CM6.themeExtension(isDark)];
|
||||||
|
var topSearch = (CM6 && CM6.topSearchExtension) ? CM6.topSearchExtension() : null;
|
||||||
if (topSearch) exts.push(topSearch);
|
if (topSearch) exts.push(topSearch);
|
||||||
exts.push(CM6.highlightActiveLine());
|
exts.push(CM6.highlightActiveLine());
|
||||||
exts.push(CM6.drawSelection());
|
exts.push(CM6.drawSelection());
|
||||||
@@ -181,12 +130,8 @@ function log_editor(id, name, readOnly, wid, height) {
|
|||||||
state: CM6.EditorState.create({ doc: id.value, extensions: exts })
|
state: CM6.EditorState.create({ doc: id.value, extensions: exts })
|
||||||
});
|
});
|
||||||
id.parentNode.insertBefore(view.dom, id.nextSibling);
|
id.parentNode.insertBefore(view.dom, id.nextSibling);
|
||||||
id.style.display = 'none';
|
ocHideLoading(id.parentNode);
|
||||||
id.parentNode.classList.add('oc');
|
ocUpdateTheme();
|
||||||
if (isDarkBackground(document.body)) {
|
|
||||||
id.parentNode.setAttribute('data-darkmode', 'true');
|
|
||||||
view.dom.setAttribute('data-darkmode', 'true');
|
|
||||||
}
|
|
||||||
window['editor_' + name] = view;
|
window['editor_' + name] = view;
|
||||||
if (wid && height) {
|
if (wid && height) {
|
||||||
view.dom.style.width = wid;
|
view.dom.style.width = wid;
|
||||||
@@ -211,14 +156,18 @@ function log_editor(id, name, readOnly, wid, height) {
|
|||||||
view.somethingSelected = function() { return !view.state.selection.main.empty; };
|
view.somethingSelected = function() { return !view.state.selection.main.empty; };
|
||||||
view.setSelection = function(f, t) { var lf = view.state.doc.line(f.line + 1), lt = view.state.doc.line(t.line + 1); view.dispatch({ selection: { anchor: lf.from + f.ch, head: lt.from + t.ch } }); };
|
view.setSelection = function(f, t) { var lf = view.state.doc.line(f.line + 1), lt = view.state.doc.line(t.line + 1); view.dispatch({ selection: { anchor: lf.from + f.ch, head: lt.from + t.ch } }); };
|
||||||
view.scrollIntoView = function(p, m) { if (p && p.line !== undefined) { var ln = view.state.doc.line(p.line + 1); view.dispatch({ selection: { anchor: ln.from + (p.ch || 0) }, scrollIntoView: true }); } else { view.dispatch({ selection: { anchor: view.state.selection.main.head }, scrollIntoView: true }); } };
|
view.scrollIntoView = function(p, m) { if (p && p.line !== undefined) { var ln = view.state.doc.line(p.line + 1); view.dispatch({ selection: { anchor: ln.from + (p.ch || 0) }, scrollIntoView: true }); } else { view.dispatch({ selection: { anchor: view.state.selection.main.head }, scrollIntoView: true }); } };
|
||||||
if (typeof isDarkBackground === 'function' && isDarkBackground(document.body)) {
|
if (view.state.doc.length > 0 && view.state.doc.lines >= 1) {
|
||||||
document.documentElement.setAttribute('data-darkmode', 'true');
|
var fl = view.state.doc.line(1);
|
||||||
|
view.dispatch({ selection: { anchor: fl.to } });
|
||||||
}
|
}
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
function markdown_editor(id, name, readOnly, wid, height) {
|
function markdown_editor(id, name, readOnly, wid, height) {
|
||||||
var isDark = (typeof isDarkBackground === 'function' && isDarkBackground(document.body));
|
id.style.display = 'none';
|
||||||
|
id.parentNode.classList.add('oc');
|
||||||
|
ocShowLoading(id.parentNode, '<%:Loading...%>', height);
|
||||||
|
var isDark = isDarkBackground(document.body);
|
||||||
var exts = [CM6.lineNumbers(), CM6.EditorView.lineWrapping, CM6.themeExtension(isDark), CM6.markdown()];
|
var exts = [CM6.lineNumbers(), CM6.EditorView.lineWrapping, CM6.themeExtension(isDark), CM6.markdown()];
|
||||||
if (readOnly) exts.push(CM6.EditorState.readOnly.of(true));
|
if (readOnly) exts.push(CM6.EditorState.readOnly.of(true));
|
||||||
|
|
||||||
@@ -226,8 +175,8 @@ function markdown_editor(id, name, readOnly, wid, height) {
|
|||||||
state: CM6.EditorState.create({ doc: id.value || '', extensions: exts })
|
state: CM6.EditorState.create({ doc: id.value || '', extensions: exts })
|
||||||
});
|
});
|
||||||
id.parentNode.insertBefore(view.dom, id.nextSibling);
|
id.parentNode.insertBefore(view.dom, id.nextSibling);
|
||||||
id.style.display = 'none';
|
ocHideLoading(id.parentNode);
|
||||||
id.parentNode.classList.add('oc');
|
ocUpdateTheme();
|
||||||
window['editor_' + name] = view;
|
window['editor_' + name] = view;
|
||||||
if (wid && height) {
|
if (wid && height) {
|
||||||
view.dom.style.width = wid;
|
view.dom.style.width = wid;
|
||||||
@@ -240,75 +189,11 @@ function markdown_editor(id, name, readOnly, wid, height) {
|
|||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
function merge_editor(id, id2, target, target2, readOnly, readOnly2, wid, height) {
|
var _cmWhenReady = window._cmWhenReady;
|
||||||
var descr = document.getElementById("my_editor_div");
|
|
||||||
target.parentNode.parentNode.parentNode.insertBefore(descr, target.parentNode.parentNode);
|
|
||||||
descr.style.display = "inline-table";
|
|
||||||
|
|
||||||
if (!id.value) {
|
|
||||||
editor(id, readOnly, wid, height);
|
|
||||||
editor(id2, readOnly2, wid, height);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
target2.parentNode.style.display = "none";
|
|
||||||
target.style.height = "700px";
|
|
||||||
target.classList.add('oc');
|
|
||||||
id.style.display = "none";
|
|
||||||
id2.style.display = "none";
|
|
||||||
|
|
||||||
var isDark = isDarkBackground(document.body);
|
|
||||||
if (isDark) target.setAttribute('data-darkmode', 'true');
|
|
||||||
var leftDoc = id.value || '';
|
|
||||||
var rightDoc = id2.value || '';
|
|
||||||
var topSearch = (CM6 && typeof CM6.topSearchExtension === 'function') ? CM6.topSearchExtension() : null;
|
|
||||||
var extA = [CM6.baseExtensions(), CM6.themeExtension(isDark), CM6.placeholderExtension('<%:Edit original config...%>'), CM6.yaml(), CM6.yamlLinter(), CM6.lintGutter(), CM6.autocompletion({ override: [CM6.mihomoCompletion] }), CM6.indentUnit.of(" "), CM6.indentMarkerExtension()];
|
|
||||||
var extB = [CM6.baseExtensions(), CM6.themeExtension(isDark), CM6.placeholderExtension('<%:Runtime config (read only)%>'), CM6.yaml(), CM6.indentUnit.of(" "), CM6.indentMarkerExtension(), CM6.EditorState.readOnly.of(true)];
|
|
||||||
var mergeDefaults = CM6.mergeDefaultConfig || {};
|
|
||||||
if (topSearch) {
|
|
||||||
extA.push(topSearch);
|
|
||||||
extB.push(topSearch);
|
|
||||||
}
|
|
||||||
|
|
||||||
var mv = new CM6.MergeView({
|
|
||||||
a: { doc: leftDoc, extensions: extA },
|
|
||||||
b: { doc: rightDoc, extensions: extB },
|
|
||||||
parent: target,
|
|
||||||
diffConfig: mergeDefaults.diffConfig || { scanLimit: 5000 },
|
|
||||||
gutter: typeof mergeDefaults.gutter === 'boolean' ? mergeDefaults.gutter : true,
|
|
||||||
revertControls: mergeDefaults.revertControls || 'b-to-a',
|
|
||||||
highlightChanges: _mergeShowDifferences,
|
|
||||||
collapseUnchanged: typeof mergeDefaults.collapseUnchanged !== 'undefined' ? mergeDefaults.collapseUnchanged : false
|
|
||||||
});
|
|
||||||
|
|
||||||
var origDispatchA = mv.a.dispatch;
|
|
||||||
mv.a.dispatch = function(tr) {
|
|
||||||
origDispatchA.call(mv.a, tr);
|
|
||||||
if (tr.docChanged) id.value = mv.a.state.doc.toString();
|
|
||||||
};
|
|
||||||
|
|
||||||
if (wid && height) {
|
|
||||||
mv.a.dom.style.width = wid;
|
|
||||||
mv.a.dom.style.height = height;
|
|
||||||
mv.b.dom.style.width = wid;
|
|
||||||
mv.b.dom.style.height = height;
|
|
||||||
}
|
|
||||||
|
|
||||||
window._mergeViewInstance = mv;
|
|
||||||
_mergeShowDifferences = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var _cmWhenReady = function(cb) { cb(); };
|
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
CM6.startThemeObserver();
|
|
||||||
if (typeof isDarkBackground === 'function' && isDarkBackground(document.body)) {
|
|
||||||
document.documentElement.setAttribute('data-darkmode', 'true');
|
|
||||||
}
|
|
||||||
var core_log = document.getElementById("core_log");
|
|
||||||
var oc_log = document.getElementById("cbid.openclash.config.clog");
|
var oc_log = document.getElementById("cbid.openclash.config.clog");
|
||||||
if (oc_log) { log_editor(oc_log, 'oc', true, '100%', '540px'); }
|
if (oc_log) { log_editor(oc_log, 'oc', true, '100%', '540px'); }
|
||||||
if (core_log) { log_editor(core_log, 'core', true, '100%', '540px'); }
|
|
||||||
|
|
||||||
var custom_cfg_value = document.getElementById("cbid.openclash.<%=sid%>.other_parameters");
|
var custom_cfg_value = document.getElementById("cbid.openclash.<%=sid%>.other_parameters");
|
||||||
if (custom_cfg_value) {
|
if (custom_cfg_value) {
|
||||||
@@ -320,24 +205,6 @@ if (custom_firewall) {
|
|||||||
shell_editor(custom_firewall, false, "100%", '300px');
|
shell_editor(custom_firewall, false, "100%", '300px');
|
||||||
}
|
}
|
||||||
|
|
||||||
var myEditor_use = document.getElementById("cbid.table.1.user");
|
|
||||||
var myEditor_def = document.getElementById("cbid.table.1.default");
|
|
||||||
|
|
||||||
if (myEditor_use && myEditor_def) {
|
|
||||||
var myEditor_div_use = document.getElementById("cbi-table-1-user");
|
|
||||||
var myEditor_div_def = document.getElementById("cbi-table-1-default");
|
|
||||||
|
|
||||||
myEditor_div_def.parentNode.parentNode.style.cssText = "text-align: left !important";
|
|
||||||
myEditor_div_def.parentNode.className = 'cbi-value';
|
|
||||||
myEditor_div_def.parentNode.style.display = "revert";
|
|
||||||
myEditor_div_def.parentNode.style.width = "100%";
|
|
||||||
|
|
||||||
myEditor_div_use.parentNode.className = 'cbi-value';
|
|
||||||
myEditor_div_use.parentNode.style.display = "revert";
|
|
||||||
myEditor_div_use.parentNode.style.width = "100%";
|
|
||||||
merge_editor(myEditor_use, myEditor_def, myEditor_div_use, myEditor_div_def, true, false, 'auto', '700px');
|
|
||||||
}
|
|
||||||
|
|
||||||
var myEditor_hosts = document.getElementById("cbid.openclash.config.custom_hosts");
|
var myEditor_hosts = document.getElementById("cbid.openclash.config.custom_hosts");
|
||||||
var myEditor_fall_fil = document.getElementById("cbid.openclash.config.custom_fallback_fil");
|
var myEditor_fall_fil = document.getElementById("cbid.openclash.config.custom_fallback_fil");
|
||||||
var myEditor_name_pol = document.getElementById("cbid.openclash.config.custom_domain_dns_core");
|
var myEditor_name_pol = document.getElementById("cbid.openclash.config.custom_domain_dns_core");
|
||||||
@@ -348,6 +215,10 @@ var myEditor_custom_domain_dns = document.getElementById("cbid.openclash.config.
|
|||||||
var myEditor_edit_file = document.getElementById("cbid.openclash.config.edit_file");
|
var myEditor_edit_file = document.getElementById("cbid.openclash.config.edit_file");
|
||||||
var myEditor_custom_sniffer = document.getElementById("cbid.openclash.config.sniffer_custom");
|
var myEditor_custom_sniffer = document.getElementById("cbid.openclash.config.sniffer_custom");
|
||||||
var myEditor_proxy_name_pol = document.getElementById("cbid.openclash.config.custom_proxy_server_dns_policy");
|
var myEditor_proxy_name_pol = document.getElementById("cbid.openclash.config.custom_proxy_server_dns_policy");
|
||||||
|
var myEditor_local_network_pass = document.getElementById("cbid.openclash.config.local_network_pass");
|
||||||
|
var myEditor_chnroute_pass = document.getElementById("cbid.openclash.config.chnroute_pass");
|
||||||
|
var myEditor_local_network6_pass = document.getElementById("cbid.openclash.config.local_network6_pass");
|
||||||
|
var myEditor_chnroute6_pass = document.getElementById("cbid.openclash.config.chnroute6_pass");
|
||||||
|
|
||||||
if (myEditor_hosts) { editor(myEditor_hosts, false, '100%', '300px'); }
|
if (myEditor_hosts) { editor(myEditor_hosts, false, '100%', '300px'); }
|
||||||
if (myEditor_edit_file) { editor(myEditor_edit_file, false, '100%', '700px'); }
|
if (myEditor_edit_file) { editor(myEditor_edit_file, false, '100%', '700px'); }
|
||||||
@@ -361,20 +232,11 @@ if (myEditor_name_cus_r1) {
|
|||||||
if (myEditor_fake_filter) { other_editor(myEditor_fake_filter, false, '100%', '300px'); }
|
if (myEditor_fake_filter) { other_editor(myEditor_fake_filter, false, '100%', '300px'); }
|
||||||
if (myEditor_custom_domain_dns) { other_editor(myEditor_custom_domain_dns, false, '100%', '300px'); }
|
if (myEditor_custom_domain_dns) { other_editor(myEditor_custom_domain_dns, false, '100%', '300px'); }
|
||||||
if (myEditor_custom_sniffer) { other_editor(myEditor_custom_sniffer, false, '100%', '300px'); }
|
if (myEditor_custom_sniffer) { other_editor(myEditor_custom_sniffer, false, '100%', '300px'); }
|
||||||
|
if (myEditor_local_network_pass) { other_editor(myEditor_local_network_pass, false, '600px', '300px'); }
|
||||||
|
if (myEditor_chnroute_pass) { other_editor(myEditor_chnroute_pass, false, '600px', '300px'); }
|
||||||
|
if (myEditor_local_network6_pass) { other_editor(myEditor_local_network6_pass, false, '600px', '300px'); }
|
||||||
|
if (myEditor_chnroute6_pass) { other_editor(myEditor_chnroute6_pass, false, '600px', '300px'); }
|
||||||
|
|
||||||
var proxy_mg = document.getElementById('cbi-table-1-proxy_mg');
|
|
||||||
var rule_mg = document.getElementById('cbi-table-1-rule_mg');
|
|
||||||
var Commit = document.getElementById('cbi-table-1-Commit');
|
|
||||||
var Apply = document.getElementById('cbi-table-1-Apply');
|
|
||||||
var Create = document.getElementById('cbi-table-1-Create');
|
|
||||||
|
|
||||||
if (proxy_mg) {
|
|
||||||
proxy_mg.style.textAlign = "center";
|
|
||||||
rule_mg.style.textAlign = "center";
|
|
||||||
Commit.style.textAlign = "center";
|
|
||||||
Apply.style.textAlign = "center";
|
|
||||||
Create.style.textAlign = "center";
|
|
||||||
}
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
//]]>
|
//]]>
|
||||||
|
|||||||
@@ -0,0 +1,472 @@
|
|||||||
|
<%
|
||||||
|
local fs = require "luci.openclash"
|
||||||
|
local plugin_version = fs.oc_version()
|
||||||
|
%>
|
||||||
|
<script src="/luci-static/resources/openclash/js/common.js?v=<%=plugin_version%>"></script>
|
||||||
|
<link rel="stylesheet" href="/luci-static/resources/openclash/css/oc.css?v=<%=plugin_version%>">
|
||||||
|
<script src="/luci-static/resources/openclash/js/cm6.min.js?v=<%=plugin_version%>"></script>
|
||||||
|
<script src="/luci-static/resources/openclash/js/oc-icons.js?v=<%=plugin_version%>"></script>
|
||||||
|
|
||||||
|
<div id="my_editor_div" style="display:flex;">
|
||||||
|
<div id="config-mode-tabs" style="display:flex;width:100%;">
|
||||||
|
<div class="mode-tabs">
|
||||||
|
<button type="button" class="mode-tab active" id="tab-original-config">
|
||||||
|
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" style="vertical-align:middle;margin-right:4px;">
|
||||||
|
<rect x="4" y="4" width="16" height="16" rx="2" stroke="currentColor" stroke-width="2" fill="none"/>
|
||||||
|
<line x1="8" y1="8" x2="16" y2="8" stroke="currentColor" stroke-width="2"/>
|
||||||
|
<line x1="8" y1="12" x2="16" y2="12" stroke="currentColor" stroke-width="2"/>
|
||||||
|
<line x1="8" y1="16" x2="12" y2="16" stroke="currentColor" stroke-width="2"/>
|
||||||
|
</svg>
|
||||||
|
<%:Original Config%>
|
||||||
|
</button>
|
||||||
|
<button type="button" class="mode-tab" id="tab-runtime-config">
|
||||||
|
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" style="vertical-align:middle;margin-right:4px;">
|
||||||
|
<polygon points="13 2 3 14 12 14 11 22 21 10 13 10 13 2" stroke="currentColor" stroke-width="2" fill="none"/>
|
||||||
|
</svg>
|
||||||
|
<%:Runtime Config%>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button type="button" class="oc-usage-help-float" id="oc-merge-toggle-btn" title="<%:Compare%>">
|
||||||
|
<svg width="24" height="24"><use href="#oc-icon-compare"/></svg>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<div id="oc-merge-help" style="display:none;">
|
||||||
|
<span id="oc-merge-help-normal"><%:Press%> <b style="color:var(--success-color)">F11</b> <%:for fullscreen,%> <b style="color:var(--success-color)">Esc</b> <%:to exit fullscreen,%> <b style="color:var(--success-color)">Ctrl + <%:Mouse Wheel%></b> <%:to zoom%></span>
|
||||||
|
<span id="oc-merge-help-merge" style="display:none;"><%:Press%> <b style="color:var(--success-color)">F10</b> <%:to toggle differences,%> <b style="color:var(--success-color)">F11</b> <%:for fullscreen,%> <b style="color:var(--success-color)">Esc</b> <%:to exit fullscreen,%> <b style="color:var(--success-color)">Ctrl + <%:Mouse Wheel%></b> <%:to zoom%></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script type="text/javascript">//<![CDATA[
|
||||||
|
ocRegisterEditorHotkeys();
|
||||||
|
|
||||||
|
var _ocIcons = {
|
||||||
|
SVG_COMPARE: '<svg width="18" height="18"><use href="#oc-icon-compare"/></svg>',
|
||||||
|
SVG_RESTORE: '<svg width="18" height="18"><use href="#oc-icon-restore"/></svg>'
|
||||||
|
};
|
||||||
|
|
||||||
|
// Uses EditorView.updateListener instead of view.dispatch override.
|
||||||
|
// dispatch() can receive TransactionSpec objects which lack docChanged.
|
||||||
|
|
||||||
|
function config_merge_editor(id, id2, target, target2, readOnly, readOnly2, wid, height) {
|
||||||
|
id.style.display = "none";
|
||||||
|
id2.style.display = "none";
|
||||||
|
|
||||||
|
var descr = document.getElementById("my_editor_div");
|
||||||
|
var cbiMap = target.closest('.cbi-map');
|
||||||
|
var sectionTable = cbiMap ? cbiMap.querySelector('.cbi-section') : null;
|
||||||
|
if (!cbiMap || !sectionTable) return;
|
||||||
|
|
||||||
|
cbiMap.classList.add('oc');
|
||||||
|
var wrapper = document.createElement('div');
|
||||||
|
wrapper.classList.add('cbi-section-card');
|
||||||
|
while (cbiMap.firstChild) {
|
||||||
|
wrapper.appendChild(cbiMap.firstChild);
|
||||||
|
}
|
||||||
|
cbiMap.appendChild(wrapper);
|
||||||
|
|
||||||
|
descr.style.display = "flex";
|
||||||
|
wrapper.insertBefore(descr, sectionTable);
|
||||||
|
|
||||||
|
var editorCell = target.parentNode;
|
||||||
|
editorCell.style.position = "relative";
|
||||||
|
editorCell.style.background = "var(--bg-gray)";
|
||||||
|
editorCell.style.borderRadius = 'var(--radius-md)';
|
||||||
|
editorCell.style.padding = '12px';
|
||||||
|
|
||||||
|
var toggleBtn = document.getElementById('oc-merge-toggle-btn');
|
||||||
|
if (toggleBtn) {
|
||||||
|
editorCell.appendChild(toggleBtn);
|
||||||
|
toggleBtn.style.display = 'flex';
|
||||||
|
toggleBtn.onclick = function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
_toggleMergeView();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
var helpEl = document.getElementById('oc-merge-help');
|
||||||
|
if (helpEl) {
|
||||||
|
helpEl.style.display = 'inline';
|
||||||
|
var footer = document.createElement('div');
|
||||||
|
footer.className = 'config-editor-footer';
|
||||||
|
footer.style.cssText = 'border-radius:var(--radius-sm);margin: 8px 0;';
|
||||||
|
var statusDiv = document.createElement('div');
|
||||||
|
statusDiv.className = 'config-editor-status';
|
||||||
|
var mergeModeLabel = document.createElement('span');
|
||||||
|
mergeModeLabel.id = 'oc-merge-mode-label';
|
||||||
|
mergeModeLabel.style.display = 'none';
|
||||||
|
mergeModeLabel.textContent = '<%:Compare mode: left(Original Config), right(Runtime Config)%>';
|
||||||
|
statusDiv.appendChild(mergeModeLabel);
|
||||||
|
var helpDiv = document.createElement('div');
|
||||||
|
helpDiv.className = 'config-editor-help';
|
||||||
|
helpDiv.appendChild(helpEl);
|
||||||
|
footer.appendChild(statusDiv);
|
||||||
|
footer.appendChild(helpDiv);
|
||||||
|
wrapper.insertBefore(footer, sectionTable.nextSibling);
|
||||||
|
_updateMergeHelpText(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
var sectionDescr = wrapper.querySelector('.cbi-section-descr');
|
||||||
|
if (sectionDescr) {
|
||||||
|
sectionDescr.classList.add('config-editor-header', 'config-editor-title');
|
||||||
|
sectionDescr.style.cssText = sectionDescr.style.cssText + ';display:flex !important;align-items:center;gap:6px;padding:10px 10px;min-height:50px;cursor:default;user-select:text;margin-bottom:unset;';
|
||||||
|
var text = sectionDescr.textContent.trim();
|
||||||
|
var idx = text.indexOf(':');
|
||||||
|
if (idx > 0) {
|
||||||
|
var label = text.substring(0, idx + 1);
|
||||||
|
var fname = text.substring(idx + 1).trim();
|
||||||
|
sectionDescr.innerHTML = '<span id="editTitle">' + label + '</span> ' +
|
||||||
|
'<span id="config-file-name" class="config-file-name">' + fname + '</span>';
|
||||||
|
}
|
||||||
|
wrapper.insertBefore(sectionDescr, descr);
|
||||||
|
}
|
||||||
|
|
||||||
|
target2.parentNode.style.display = "none";
|
||||||
|
target.parentNode.colSpan = 2;
|
||||||
|
target.style.height = "700px";
|
||||||
|
|
||||||
|
var useContent = id.value || '';
|
||||||
|
var defContent = id2.value || '';
|
||||||
|
var showUse = useContent !== '';
|
||||||
|
|
||||||
|
window._mergeEditorState = {
|
||||||
|
id: id,
|
||||||
|
id2: id2,
|
||||||
|
target: target,
|
||||||
|
target2: target2,
|
||||||
|
wid: wid,
|
||||||
|
height: height,
|
||||||
|
isMerge: false,
|
||||||
|
showUse: showUse,
|
||||||
|
useContent: useContent,
|
||||||
|
defContent: defContent,
|
||||||
|
instance: null,
|
||||||
|
_readOnlyComp: null,
|
||||||
|
_programmaticChange: false
|
||||||
|
};
|
||||||
|
|
||||||
|
_createSingleMergeEditor(showUse ? useContent : defContent, !showUse);
|
||||||
|
|
||||||
|
_updateMergeToggleBtn();
|
||||||
|
_updateMergeTabs(false);
|
||||||
|
|
||||||
|
var tabOriginal = document.getElementById('tab-original-config');
|
||||||
|
var tabRuntime = document.getElementById('tab-runtime-config');
|
||||||
|
|
||||||
|
if (tabOriginal) {
|
||||||
|
tabOriginal.onclick = function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
var state = window._mergeEditorState;
|
||||||
|
if (!state) return;
|
||||||
|
if (state.instance) {
|
||||||
|
if (state.isMerge && state.instance.a && state.instance.a.state) {
|
||||||
|
state.useContent = state.instance.a.state.doc.toString();
|
||||||
|
} else if (!state.isMerge && state.instance.state) {
|
||||||
|
var cur = state.instance.state.doc.toString();
|
||||||
|
if (state.showUse) state.useContent = cur;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (state.isMerge) {
|
||||||
|
state.showUse = true;
|
||||||
|
_createSingleMergeEditor(state.useContent, false);
|
||||||
|
document.getElementById('my_editor_div').style.display = 'flex';
|
||||||
|
} else if (!state.showUse) {
|
||||||
|
state.showUse = true;
|
||||||
|
_switchSingleTab(state.useContent, false);
|
||||||
|
}
|
||||||
|
_updateMergeToggleBtn();
|
||||||
|
_updateMergeTabs(false);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tabRuntime) {
|
||||||
|
tabRuntime.onclick = function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
var state = window._mergeEditorState;
|
||||||
|
if (!state) return;
|
||||||
|
if (state.instance) {
|
||||||
|
if (state.isMerge && state.instance.a && state.instance.a.state) {
|
||||||
|
state.useContent = state.instance.a.state.doc.toString();
|
||||||
|
} else if (!state.isMerge && state.instance.state) {
|
||||||
|
var cur = state.instance.state.doc.toString();
|
||||||
|
if (state.showUse) state.useContent = cur;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (state.isMerge) {
|
||||||
|
state.showUse = false;
|
||||||
|
_createSingleMergeEditor(state.defContent, true);
|
||||||
|
document.getElementById('my_editor_div').style.display = 'flex';
|
||||||
|
} else if (state.showUse) {
|
||||||
|
state.showUse = false;
|
||||||
|
_switchSingleTab(state.defContent, true);
|
||||||
|
}
|
||||||
|
_updateMergeToggleBtn();
|
||||||
|
_updateMergeTabs(false);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function _switchSingleTab(content, readOnly) {
|
||||||
|
var state = window._mergeEditorState;
|
||||||
|
if (!state || !state.instance || state.isMerge) return;
|
||||||
|
|
||||||
|
var view = state.instance;
|
||||||
|
state._programmaticChange = true;
|
||||||
|
view.dispatch({
|
||||||
|
changes: { from: 0, to: view.state.doc.length, insert: content }
|
||||||
|
});
|
||||||
|
if (state._readOnlyComp) {
|
||||||
|
view.dispatch({
|
||||||
|
effects: state._readOnlyComp.reconfigure(
|
||||||
|
readOnly ? CM6.EditorState.readOnly.of(true) : []
|
||||||
|
)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
state._programmaticChange = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _createSingleMergeEditor(content, readOnly) {
|
||||||
|
var state = window._mergeEditorState;
|
||||||
|
if (!state) return;
|
||||||
|
_destroyMergeInstance();
|
||||||
|
|
||||||
|
if (state.target) {
|
||||||
|
var orphans = state.target.querySelectorAll('.cm-editor, .cm-mergeView');
|
||||||
|
for (var i = 0; i < orphans.length; i++) { orphans[i].remove(); }
|
||||||
|
state.target.style.height = '700px';
|
||||||
|
if (state.target.parentNode) state.target.parentNode.colSpan = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
ocShowLoading(state.target, '<%:Loading...%>');
|
||||||
|
|
||||||
|
var isDark = isDarkBackground(document.body);
|
||||||
|
var exts = [CM6.baseExtensions(), CM6.themeExtension(isDark), CM6.placeholderExtension('<%:Enter YAML configuration...%>')];
|
||||||
|
var topSearch = (CM6 && CM6.topSearchExtension) ? CM6.topSearchExtension() : null;
|
||||||
|
if (topSearch) exts.push(topSearch);
|
||||||
|
exts.push(CM6.yaml());
|
||||||
|
exts.push(CM6.yamlLinter());
|
||||||
|
exts.push(CM6.lintGutter());
|
||||||
|
exts.push(CM6.autocompletion({ override: [CM6.mihomoCompletion] }));
|
||||||
|
exts.push(CM6.indentUnit.of(" "));
|
||||||
|
exts.push(CM6.indentMarkerExtension());
|
||||||
|
var readOnlyComp = new CM6.Compartment();
|
||||||
|
exts.push(readOnlyComp.of(readOnly ? CM6.EditorState.readOnly.of(true) : []));
|
||||||
|
state._readOnlyComp = readOnlyComp;
|
||||||
|
|
||||||
|
exts.push(CM6.EditorView.updateListener.of(function(update) {
|
||||||
|
if (update.docChanged && !state._programmaticChange) {
|
||||||
|
state.id.value = update.state.doc.toString();
|
||||||
|
state.useContent = update.state.doc.toString();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
var mergeStatus = document.querySelector('.config-editor-status');
|
||||||
|
if (mergeStatus) mergeStatus.style.display = 'none';
|
||||||
|
|
||||||
|
var view = new CM6.EditorView({
|
||||||
|
state: CM6.EditorState.create({ doc: content, extensions: exts }),
|
||||||
|
parent: state.target
|
||||||
|
});
|
||||||
|
var btn = document.getElementById('oc-merge-toggle-btn');
|
||||||
|
if (btn && view.dom) view.dom.appendChild(btn);
|
||||||
|
if (state.wid && state.height) {
|
||||||
|
view.dom.style.width = state.wid;
|
||||||
|
view.dom.style.height = state.height;
|
||||||
|
}
|
||||||
|
state.instance = view;
|
||||||
|
state.isMerge = false;
|
||||||
|
|
||||||
|
if (CM6.mirrorThemeScrollbar) CM6.mirrorThemeScrollbar();
|
||||||
|
|
||||||
|
ocHideLoading(state.target);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _renderMergeView() {
|
||||||
|
var state = window._mergeEditorState;
|
||||||
|
if (!state) return;
|
||||||
|
_destroyMergeInstance();
|
||||||
|
|
||||||
|
if (state.target) {
|
||||||
|
var orphans = state.target.querySelectorAll('.cm-editor');
|
||||||
|
for (var i = 0; i < orphans.length; i++) { orphans[i].remove(); }
|
||||||
|
state.target.style.height = '700px';
|
||||||
|
if (state.target.parentNode) state.target.parentNode.colSpan = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
ocShowLoading(state.target, '<%:Loading...%>');
|
||||||
|
|
||||||
|
var isDark = isDarkBackground(document.body);
|
||||||
|
var topSearch = (CM6 && CM6.topSearchExtension) ? CM6.topSearchExtension() : null;
|
||||||
|
var extA = [CM6.baseExtensions(), CM6.themeExtension(isDark), CM6.placeholderExtension('<%:Edit original config...%>'), CM6.yaml(), CM6.yamlLinter(), CM6.lintGutter(), CM6.autocompletion({ override: [CM6.mihomoCompletion] }), CM6.indentUnit.of(" "), CM6.indentMarkerExtension()];
|
||||||
|
var extB = [CM6.baseExtensions(), CM6.themeExtension(isDark), CM6.placeholderExtension('<%:Runtime config (read only)%>'), CM6.yaml(), CM6.indentUnit.of(" "), CM6.indentMarkerExtension(), CM6.EditorState.readOnly.of(true)];
|
||||||
|
var mergeDefaults = CM6.mergeDefaultConfig || {};
|
||||||
|
if (topSearch) {
|
||||||
|
extA.push(topSearch);
|
||||||
|
extB.push(topSearch);
|
||||||
|
}
|
||||||
|
|
||||||
|
extA.push(CM6.EditorView.updateListener.of(function(update) {
|
||||||
|
if (update.docChanged) {
|
||||||
|
state.id.value = update.state.doc.toString();
|
||||||
|
state.useContent = update.state.doc.toString();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
var mv = new CM6.MergeView({
|
||||||
|
a: { doc: state.useContent || '', extensions: extA },
|
||||||
|
b: { doc: state.defContent || '', extensions: extB },
|
||||||
|
parent: state.target,
|
||||||
|
diffConfig: mergeDefaults.diffConfig || { scanLimit: 5000 },
|
||||||
|
gutter: mergeDefaults.gutter !== false,
|
||||||
|
revertControls: mergeDefaults.revertControls || 'b-to-a',
|
||||||
|
highlightChanges: window._ocMergeShowDifferences,
|
||||||
|
collapseUnchanged: mergeDefaults.collapseUnchanged || false
|
||||||
|
});
|
||||||
|
|
||||||
|
if (state.wid && state.height) {
|
||||||
|
mv.a.dom.style.width = state.wid;
|
||||||
|
mv.a.dom.style.height = state.height;
|
||||||
|
mv.b.dom.style.width = state.wid;
|
||||||
|
mv.b.dom.style.height = state.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CM6.mirrorThemeScrollbar) CM6.mirrorThemeScrollbar();
|
||||||
|
|
||||||
|
var btn = document.getElementById('oc-merge-toggle-btn');
|
||||||
|
if (btn && mv.dom) mv.dom.appendChild(btn);
|
||||||
|
|
||||||
|
var mergeStatus = document.querySelector('.config-editor-status');
|
||||||
|
if (mergeStatus) mergeStatus.style.display = '';
|
||||||
|
var mergeLabel = document.getElementById('oc-merge-mode-label');
|
||||||
|
if (mergeLabel) mergeLabel.style.display = 'inline';
|
||||||
|
|
||||||
|
window._mergeViewInstance = mv;
|
||||||
|
window._ocMergeShowDifferences = true;
|
||||||
|
state.instance = mv;
|
||||||
|
state.isMerge = true;
|
||||||
|
|
||||||
|
ocHideLoading(state.target);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _destroyMergeInstance() {
|
||||||
|
var btn = document.getElementById('oc-merge-toggle-btn');
|
||||||
|
if (btn) {
|
||||||
|
var editorCell = window._mergeEditorState && window._mergeEditorState.target ? window._mergeEditorState.target.parentNode : null;
|
||||||
|
if (editorCell) editorCell.appendChild(btn);
|
||||||
|
}
|
||||||
|
var state = window._mergeEditorState;
|
||||||
|
if (state && state.instance) {
|
||||||
|
try {
|
||||||
|
if (state.instance.a && state.instance.a.destroy) {
|
||||||
|
state.instance.a.destroy();
|
||||||
|
if (state.instance.b && state.instance.b.destroy) state.instance.b.destroy();
|
||||||
|
} else if (state.instance.destroy) {
|
||||||
|
state.instance.destroy();
|
||||||
|
}
|
||||||
|
} catch(e) {}
|
||||||
|
state.instance = null;
|
||||||
|
}
|
||||||
|
window._mergeViewInstance = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _updateMergeHelpText(isMerge) {
|
||||||
|
var helpNormal = document.getElementById('oc-merge-help-normal');
|
||||||
|
var helpMerge = document.getElementById('oc-merge-help-merge');
|
||||||
|
if (helpNormal) helpNormal.style.display = isMerge ? 'none' : 'inline';
|
||||||
|
if (helpMerge) helpMerge.style.display = isMerge ? 'inline' : 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
function _toggleMergeView() {
|
||||||
|
var state = window._mergeEditorState;
|
||||||
|
if (!state) return;
|
||||||
|
|
||||||
|
if (state.instance) {
|
||||||
|
if (state.isMerge && state.instance.a && state.instance.a.state) {
|
||||||
|
state.useContent = state.instance.a.state.doc.toString();
|
||||||
|
} else if (!state.isMerge && state.instance.state) {
|
||||||
|
var cur = state.instance.state.doc.toString();
|
||||||
|
if (state.showUse) state.useContent = cur;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var wasFullscreen = window._ocFullscreenActive;
|
||||||
|
|
||||||
|
if (state.isMerge) {
|
||||||
|
state.showUse = true;
|
||||||
|
_createSingleMergeEditor(state.useContent, false);
|
||||||
|
document.getElementById('my_editor_div').style.display = 'flex';
|
||||||
|
} else {
|
||||||
|
_renderMergeView();
|
||||||
|
document.getElementById('my_editor_div').style.display = 'none';
|
||||||
|
}
|
||||||
|
_updateMergeToggleBtn();
|
||||||
|
_updateMergeTabs(state.isMerge);
|
||||||
|
_updateMergeHelpText(state.isMerge);
|
||||||
|
|
||||||
|
if (wasFullscreen && CM6 && CM6.toggleFullscreen) {
|
||||||
|
var target = state.instance && state.instance.dom ? state.instance.dom : null;
|
||||||
|
if (!target && CM6.getActiveEditor) target = CM6.getActiveEditor();
|
||||||
|
if (target) CM6.toggleFullscreen(target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function _updateMergeToggleBtn() {
|
||||||
|
var btn = document.getElementById('oc-merge-toggle-btn');
|
||||||
|
if (!btn) return;
|
||||||
|
var state = window._mergeEditorState;
|
||||||
|
if (state && state.isMerge) {
|
||||||
|
btn.title = '<%:Restore%>';
|
||||||
|
btn.innerHTML = _ocIcons.SVG_RESTORE;
|
||||||
|
} else {
|
||||||
|
btn.title = '<%:Compare%>';
|
||||||
|
btn.innerHTML = _ocIcons.SVG_COMPARE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function _updateMergeTabs(isMerge) {
|
||||||
|
var tabOriginal = document.getElementById('tab-original-config');
|
||||||
|
var tabRuntime = document.getElementById('tab-runtime-config');
|
||||||
|
if (!tabOriginal || !tabRuntime) return;
|
||||||
|
if (isMerge) {
|
||||||
|
tabOriginal.classList.remove('active');
|
||||||
|
tabRuntime.classList.remove('active');
|
||||||
|
} else {
|
||||||
|
var state = window._mergeEditorState;
|
||||||
|
if (state && state.showUse) {
|
||||||
|
tabOriginal.classList.add('active');
|
||||||
|
tabRuntime.classList.remove('active');
|
||||||
|
} else {
|
||||||
|
tabOriginal.classList.remove('active');
|
||||||
|
tabRuntime.classList.add('active');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var _cmWhenReady = window._cmWhenReady;
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
|
||||||
|
var myEditor_use = document.getElementById("cbid.table.1.user");
|
||||||
|
var myEditor_def = document.getElementById("cbid.table.1.default");
|
||||||
|
|
||||||
|
if (myEditor_use && myEditor_def) {
|
||||||
|
var myEditor_div_use = document.getElementById("cbi-table-1-user");
|
||||||
|
var myEditor_div_def = document.getElementById("cbi-table-1-default");
|
||||||
|
|
||||||
|
myEditor_div_def.parentNode.parentNode.style.cssText = "text-align: left !important";
|
||||||
|
myEditor_div_def.parentNode.className = 'cbi-value';
|
||||||
|
myEditor_div_def.parentNode.style.display = "revert";
|
||||||
|
myEditor_div_def.parentNode.style.width = "100%";
|
||||||
|
|
||||||
|
myEditor_div_use.parentNode.className = 'cbi-value';
|
||||||
|
myEditor_div_use.parentNode.style.display = "revert";
|
||||||
|
myEditor_div_use.parentNode.style.width = "100%";
|
||||||
|
|
||||||
|
config_merge_editor(myEditor_use, myEditor_def, myEditor_div_use, myEditor_div_def, true, false, 'auto', '700px');
|
||||||
|
ocUpdateTheme();
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
//]]>
|
||||||
|
</script>
|
||||||
@@ -1,4 +1,10 @@
|
|||||||
<div class="oc">
|
<div class="oc">
|
||||||
|
<%
|
||||||
|
local fs = require "luci.openclash"
|
||||||
|
local plugin_version = fs.oc_version()
|
||||||
|
%>
|
||||||
|
<script src="/luci-static/resources/openclash/js/oc-icons.js?v=<%=plugin_version%>"></script>
|
||||||
|
<script src="/luci-static/resources/openclash/js/subconverter-version.js?v=<%=plugin_version%>"></script>
|
||||||
<div class="config-upload-model-overlay" id="config-upload-overlay">
|
<div class="config-upload-model-overlay" id="config-upload-overlay">
|
||||||
<div class="config-upload-model" id="config-upload-model">
|
<div class="config-upload-model" id="config-upload-model">
|
||||||
<div class="config-upload-header">
|
<div class="config-upload-header">
|
||||||
@@ -7,10 +13,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="config-upload-actions">
|
<div class="config-upload-actions">
|
||||||
<button type="button" class="icon-btn" id="config-upload-close" title="<%:Close%>">
|
<button type="button" class="icon-btn" id="config-upload-close" title="<%:Close%>">
|
||||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
<svg width="14" height="14"><use href="#oc-icon-close"/></svg>
|
||||||
<line x1="18" y1="6" x2="6" y2="18"></line>
|
|
||||||
<line x1="6" y1="6" x2="18" y2="18"></line>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -18,20 +21,11 @@
|
|||||||
<div class="upload-mode-selector">
|
<div class="upload-mode-selector">
|
||||||
<div class="mode-tabs">
|
<div class="mode-tabs">
|
||||||
<button type="button" class="mode-tab active" id="upload-mode-file" data-mode="file">
|
<button type="button" class="mode-tab active" id="upload-mode-file" data-mode="file">
|
||||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
<svg width="16" height="16"><use href="#oc-icon-download"/></svg>
|
||||||
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
|
|
||||||
<polyline points="17,11 12,6 7,11"></polyline>
|
|
||||||
<line x1="12" y1="18" x2="12" y2="6"></line>
|
|
||||||
</svg>
|
|
||||||
<%:Upload File%>
|
<%:Upload File%>
|
||||||
</button>
|
</button>
|
||||||
<button type="button" class="mode-tab" id="upload-mode-subscribe" data-mode="subscribe">
|
<button type="button" class="mode-tab" id="upload-mode-subscribe" data-mode="subscribe">
|
||||||
<svg width="15" height="15" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg width="15" height="15"><use href="#oc-icon-link"/></svg>
|
||||||
<path d="M26.2401 16.373L17.1001 7.23303C14.4388 4.57168 10.0653 4.6303 7.33158 7.36397C4.59791 10.0976 4.53929 14.4712 7.20064 17.1325L15.1359 25.0678" stroke="currentColor" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"></path>
|
|
||||||
<path d="M32.9027 23.0031L40.838 30.9384C43.4994 33.5998 43.4407 37.9733 40.7071 40.707C37.9734 43.4407 33.5999 43.4993 30.9385 40.8379L21.7985 31.6979" stroke="currentColor" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"></path>
|
|
||||||
<path d="M26.1093 26.1416C28.843 23.4079 28.9016 19.0344 26.2403 16.373" stroke="currentColor" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"></path>
|
|
||||||
<path d="M21.7989 21.7984C19.0652 24.5321 19.0066 28.9056 21.6679 31.5669" stroke="currentColor" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"></path>
|
|
||||||
</svg>
|
|
||||||
<%:Subscribe Link%>
|
<%:Subscribe Link%>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -40,11 +34,7 @@
|
|||||||
<div class="upload-mode-content" id="mode-file-content">
|
<div class="upload-mode-content" id="mode-file-content">
|
||||||
<div class="upload-zone" id="upload-zone">
|
<div class="upload-zone" id="upload-zone">
|
||||||
<div class="upload-icon">
|
<div class="upload-icon">
|
||||||
<svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1">
|
<svg width="48" height="48"><use href="#oc-icon-download"/></svg>
|
||||||
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
|
|
||||||
<polyline points="17,11 12,6 7,11"></polyline>
|
|
||||||
<line x1="12" y1="18" x2="12" y2="6"></line>
|
|
||||||
</svg>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="upload-text">
|
<div class="upload-text">
|
||||||
<div class="upload-primary"><%:Click to select file or drag and drop%></div>
|
<div class="upload-primary"><%:Click to select file or drag and drop%></div>
|
||||||
@@ -87,6 +77,13 @@
|
|||||||
<input type="text" id="subscribe-ua-custom" placeholder="<%:Enter custom User-Agent%>" class="form-input" style="display: none; margin-top: 8px;" />
|
<input type="text" id="subscribe-ua-custom" placeholder="<%:Enter custom User-Agent%>" class="form-input" style="display: none; margin-top: 8px;" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label><%:Custom Headers%> (<%:Optional%>):</label>
|
||||||
|
<div class="form-help" style="margin-bottom: unset;"><%:Add custom HTTP headers to the subscription request%></div>
|
||||||
|
<div id="subscribe-headers-container" style="display:none;"></div>
|
||||||
|
<button type="button" id="subscribe-headers-add" class="btn upload-btn" style="align-self: flex-start; margin-top: 4px; padding: 4px 12px; font-size: 13px; border: 1px solid var(--primary-color); border-radius: var(--radius-sm); cursor: pointer;">+ <%:Add Header%></button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="form-checkbox">
|
<label class="form-checkbox">
|
||||||
<input type="checkbox" id="advanced-options-enable">
|
<input type="checkbox" id="advanced-options-enable">
|
||||||
@@ -117,6 +114,10 @@
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<input type="text" id="convert-address-custom" placeholder="<%:Enter custom convert address%>" class="form-input" style="display: none; margin-top: 8px;" />
|
<input type="text" id="convert-address-custom" placeholder="<%:Enter custom convert address%>" class="form-input" style="display: none; margin-top: 8px;" />
|
||||||
|
<div id="subconverter-version-status-upload" class="subconverter-version-status" data-state="idle" hidden>
|
||||||
|
<span class="subconverter-version-label"></span>
|
||||||
|
<span class="subconverter-version-text"></span>
|
||||||
|
</div>
|
||||||
<div class="form-help"><%:Note: There is A Risk of Privacy Leakage in Online Convert%></div>
|
<div class="form-help"><%:Note: There is A Risk of Privacy Leakage in Online Convert%></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -261,9 +262,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button type="button" id="age-generate-btn" class="icon-btn" style="margin-left:8px;" title="<%:Generate Age Key%>">
|
<button type="button" id="age-generate-btn" class="icon-btn" style="margin-left:8px;" title="<%:Generate Age Key%>">
|
||||||
<svg height="16" viewBox="0 0 16 16" width="16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg width="16" height="16"><use href="#oc-icon-key"/></svg>
|
||||||
<path d="M10.5 0a5.499 5.499 0 1 1-1.288 10.848l-.932.932a.749.749 0 0 1-.53.22H7v.75a.749.749 0 0 1-.22.53l-.5.5a.749.749 0 0 1-.53.22H5v.75a.749.749 0 0 1-.22.53l-.5.5a.749.749 0 0 1-.53.22h-2A1.75 1.75 0 0 1 0 14.25v-2c0-.199.079-.389.22-.53l4.932-4.932A5.5 5.5 0 0 1 10.5 0Zm-4 5.5c-.001.431.069.86.205 1.269a.75.75 0 0 1-.181.768L1.5 12.56v1.69c0 .138.112.25.25.25h1.69l.06-.06v-1.19a.75.75 0 0 1 .75-.75h1.19l.06-.06v-1.19a.75.75 0 0 1 .75-.75h1.19l1.023-1.025a.75.75 0 0 1 .768-.18A4 4 0 1 0 6.5 5.5ZM11 6a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z" fill="currentColor"/>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-help"><%:Age Encryption For Config, Click For More:%> <a href="javascript:void(0);" onclick="window.open('https://wiki.metacubex.one/config/proxy-providers/?age-secret-key#age-secret-key', '_blank');" class="help-link"> <%:Age Encryption Introduce%></a></div>
|
<div class="form-help"><%:Age Encryption For Config, Click For More:%> <a href="javascript:void(0);" onclick="window.open('https://wiki.metacubex.one/config/proxy-providers/?age-secret-key#age-secret-key', '_blank');" class="help-link"> <%:Age Encryption Introduce%></a></div>
|
||||||
@@ -274,9 +273,7 @@
|
|||||||
<div style="display:flex; align-items:center;">
|
<div style="display:flex; align-items:center;">
|
||||||
<input type="text" id="age-secret-input" class="form-input" style="flex:1;" />
|
<input type="text" id="age-secret-input" class="form-input" style="flex:1;" />
|
||||||
<button type="button" id="age-copy-secret" class="icon-btn" style="margin-left:8px;" title="<%:Copy%>">
|
<button type="button" id="age-copy-secret" class="icon-btn" style="margin-left:8px;" title="<%:Copy%>">
|
||||||
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
|
<svg width="24" height="24"><use href="#oc-icon-copy-bold"/></svg>
|
||||||
<path d="M16 1H4a2 2 0 00-2 2v12h2V3h12V1zM20 5H8a2 2 0 00-2 2v14a2 2 0 002 2h12a2 2 0 002-2V7a2 2 0 00-2-2zm0 16H8V7h12v14z" fill="currentColor"/>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -286,18 +283,10 @@
|
|||||||
<div style="display:flex; align-items:center;">
|
<div style="display:flex; align-items:center;">
|
||||||
<input type="text" id="age-public-input" class="form-input" style="flex:1;" />
|
<input type="text" id="age-public-input" class="form-input" style="flex:1;" />
|
||||||
<button type="button" id="age-copy-public" class="icon-btn" style="margin-left:8px;" title="<%:Copy%>">
|
<button type="button" id="age-copy-public" class="icon-btn" style="margin-left:8px;" title="<%:Copy%>">
|
||||||
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
|
<svg width="24" height="24"><use href="#oc-icon-copy-bold"/></svg>
|
||||||
<path d="M16 1H4a2 2 0 00-2 2v12h2V3h12V1zM20 5H8a2 2 0 00-2 2v14a2 2 0 002 2h12a2 2 0 002-2V7a2 2 0 00-2-2zm0 16H8V7h12v14z" fill="currentColor"/>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
<button type="button" id="age-calculate-public" class="icon-btn" style="margin-left:8px;" title="<%:Calculate Public Key%>">
|
<button type="button" id="age-calculate-public" class="icon-btn" style="margin-left:8px;" title="<%:Calculate Public Key%>">
|
||||||
<svg width="16" height="16" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg width="16" height="16"><use href="#oc-icon-calculator"/></svg>
|
||||||
<path d="M28 32.5H42" stroke="currentColor" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
|
||||||
<path d="M28 41.5H42" stroke="currentColor" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
|
||||||
<path d="M6 13H22" stroke="currentColor" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
|
||||||
<path d="M14 5L14 21" stroke="currentColor" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
|
||||||
<path d="M42 5L6 41" stroke="currentColor" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -334,7 +323,7 @@
|
|||||||
<div class="config-upload-header">
|
<div class="config-upload-header">
|
||||||
<div class="config-upload-title"><%:Set Subscription Info URL%></div>
|
<div class="config-upload-title"><%:Set Subscription Info URL%></div>
|
||||||
<button type="button" class="icon-btn" onclick="SubscriptionUrlSetter.hide()">
|
<button type="button" class="icon-btn" onclick="SubscriptionUrlSetter.hide()">
|
||||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>
|
<svg width="14" height="14"><use href="#oc-icon-close"/></svg>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="config-upload-content">
|
<div class="config-upload-content">
|
||||||
@@ -355,6 +344,80 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
var UrlValidator = {
|
||||||
|
_httpRe: /^https?:\/\/\S+$/i,
|
||||||
|
_anyProtocolRe: /^[a-zA-Z][a-zA-Z0-9+.-]*:\/\/\S+$/i,
|
||||||
|
|
||||||
|
// Extract individual URLs from input. Supports:
|
||||||
|
// - Newline-separated: url1\nurl2
|
||||||
|
// - | -separated: url1|url2 (| only when followed by protocol)
|
||||||
|
// - Comma-separated: node1,https://sub.com
|
||||||
|
// - URL-encoded comma: node1%2Chttps%3A%2F%2Fsub.com
|
||||||
|
// Correctly preserves | inside query parameters (e.g., ?lv=2|3|5|6.js).
|
||||||
|
extractUrls: function(input, allowNonHttp) {
|
||||||
|
if (!input) return [];
|
||||||
|
var protocolPat = allowNonHttp ? '[a-zA-Z][a-zA-Z0-9+.-]*://' : 'https?://';
|
||||||
|
var protocolRe = new RegExp(protocolPat, 'gi');
|
||||||
|
var urls = [];
|
||||||
|
|
||||||
|
function extractFrom(text) {
|
||||||
|
var positions = [];
|
||||||
|
var m;
|
||||||
|
protocolRe.lastIndex = 0;
|
||||||
|
while ((m = protocolRe.exec(text)) !== null) {
|
||||||
|
positions.push(m.index);
|
||||||
|
}
|
||||||
|
if (positions.length === 0) return false;
|
||||||
|
|
||||||
|
for (var i = 0; i < positions.length; i++) {
|
||||||
|
var start = positions[i];
|
||||||
|
var end = (i + 1 < positions.length) ? positions[i + 1] : text.length;
|
||||||
|
var raw = text.substring(start, end);
|
||||||
|
raw = raw.replace(/[\s|,]+$/, '').trim();
|
||||||
|
if (raw) urls.push(raw);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!extractFrom(input)) {
|
||||||
|
if (/%[23][aA]/i.test(input)) {
|
||||||
|
try {
|
||||||
|
var decoded = decodeURIComponent(input);
|
||||||
|
if (decoded !== input) extractFrom(decoded);
|
||||||
|
} catch(e) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return urls;
|
||||||
|
},
|
||||||
|
|
||||||
|
validateUrl: function(url, allowNonHttp) {
|
||||||
|
var urlPart = url.replace(/#name=.*$/, '');
|
||||||
|
if (!urlPart) return { valid: false, reason: '<%:Empty URL%>' };
|
||||||
|
|
||||||
|
var re = allowNonHttp ? this._anyProtocolRe : this._httpRe;
|
||||||
|
if (!re.test(urlPart)) {
|
||||||
|
if (!allowNonHttp && /^[a-zA-Z][a-zA-Z0-9+.-]*:\/\/\S/.test(urlPart)) {
|
||||||
|
return { valid: false, reason: '<%:Only HTTP/HTTPS URLs are supported%>' };
|
||||||
|
}
|
||||||
|
return { valid: false, reason: '<%:Invalid URL format%>' };
|
||||||
|
}
|
||||||
|
|
||||||
|
var hostMatch = urlPart.match(/^https?:\/\/([^\/\s?#]+)/i);
|
||||||
|
if (!hostMatch || hostMatch[1].length === 0) {
|
||||||
|
return { valid: false, reason: '<%:URL missing hostname%>' };
|
||||||
|
}
|
||||||
|
return { valid: true };
|
||||||
|
},
|
||||||
|
|
||||||
|
anyValid: function(urlList, allowNonHttp) {
|
||||||
|
for (var i = 0; i < urlList.length; i++) {
|
||||||
|
if (this.validateUrl(urlList[i], allowNonHttp).valid) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
var SubscriptionUrlSetter = {
|
var SubscriptionUrlSetter = {
|
||||||
filename: '',
|
filename: '',
|
||||||
onSuccess: '',
|
onSuccess: '',
|
||||||
@@ -415,6 +478,14 @@ var SubscriptionUrlSetter = {
|
|||||||
});
|
});
|
||||||
var newUrl = urlList.join('\n');
|
var newUrl = urlList.join('\n');
|
||||||
|
|
||||||
|
for (var i = 0; i < urlList.length; i++) {
|
||||||
|
var result = UrlValidator.validateUrl(urlList[i], false);
|
||||||
|
if (!result.valid) {
|
||||||
|
alert('<%:Invalid URL on line %> ' + (i + 1) + ':\n' + urlList[i] + '\n\n' + result.reason);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.hide();
|
this.hide();
|
||||||
|
|
||||||
XHR.get('<%=luci.dispatcher.build_url("admin", "services", "openclash", "set_subinfo_url")%>', {
|
XHR.get('<%=luci.dispatcher.build_url("admin", "services", "openclash", "set_subinfo_url")%>', {
|
||||||
@@ -473,7 +544,8 @@ var ConfigUploader = {
|
|||||||
isProcessing: false,
|
isProcessing: false,
|
||||||
currentMode: 'file',
|
currentMode: 'file',
|
||||||
onSuccess: '',
|
onSuccess: '',
|
||||||
_linkRe: /^(?:https?:\/\/\S+|[a-zA-Z]+:\/\/\S+|[^,\s]+,https?:\/\/\S+|[^%\s]+%2Chttps?%3A%2F%2F\S+)$/i,
|
subconverterVersionChecker: null,
|
||||||
|
_linkRe: null,
|
||||||
|
|
||||||
init: function() {
|
init: function() {
|
||||||
this.overlay = document.getElementById('config-upload-overlay');
|
this.overlay = document.getElementById('config-upload-overlay');
|
||||||
@@ -547,6 +619,25 @@ var ConfigUploader = {
|
|||||||
var advancedOptionsEnableFile = document.getElementById('advanced-options-enable-file');
|
var advancedOptionsEnableFile = document.getElementById('advanced-options-enable-file');
|
||||||
var advancedOptionsContainerFile = document.getElementById('advanced-options-container-file');
|
var advancedOptionsContainerFile = document.getElementById('advanced-options-container-file');
|
||||||
var ageFormNode = document.getElementById('age-encryption-group');
|
var ageFormNode = document.getElementById('age-encryption-group');
|
||||||
|
var subVersionStatus = document.getElementById('subconverter-version-status-upload');
|
||||||
|
|
||||||
|
if (window.OpenClashSubconverterVersion && subVersionStatus) {
|
||||||
|
this.subconverterVersionChecker = window.OpenClashSubconverterVersion.init({
|
||||||
|
select: convertAddressSelect,
|
||||||
|
customInput: convertAddressCustom,
|
||||||
|
enable: subConvertEnable,
|
||||||
|
status: subVersionStatus,
|
||||||
|
proxyURL: '<%=luci.dispatcher.build_url("admin", "services", "openclash", "subconverter_version")%>',
|
||||||
|
labels: {
|
||||||
|
checking: '<%:Checking backend version...%>',
|
||||||
|
versionPrefix: '<%:Backend Version%>',
|
||||||
|
empty: '<%:Please enter backend URL%>',
|
||||||
|
invalid: '<%:Invalid backend URL%>',
|
||||||
|
unrecognized: '<%:Backend version information not detected%>',
|
||||||
|
failed: '<%:Unable to detect backend version%>'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
subscribeUrlInput.addEventListener('input', function() {
|
subscribeUrlInput.addEventListener('input', function() {
|
||||||
self.autoFillConfigName();
|
self.autoFillConfigName();
|
||||||
@@ -595,11 +686,13 @@ var ConfigUploader = {
|
|||||||
|
|
||||||
subConvertEnable.addEventListener('change', function() {
|
subConvertEnable.addEventListener('change', function() {
|
||||||
subConvertOptions.style.display = this.checked ? 'block' : 'none';
|
subConvertOptions.style.display = this.checked ? 'block' : 'none';
|
||||||
|
self.updateSubconverterVersionStatus();
|
||||||
self.updateSubmitButton();
|
self.updateSubmitButton();
|
||||||
});
|
});
|
||||||
|
|
||||||
convertAddressSelect.addEventListener('change', function() {
|
convertAddressSelect.addEventListener('change', function() {
|
||||||
convertAddressCustom.style.display = this.value === 'custom' ? 'block' : 'none';
|
convertAddressCustom.style.display = this.value === 'custom' ? 'block' : 'none';
|
||||||
|
self.updateSubconverterVersionStatus();
|
||||||
});
|
});
|
||||||
|
|
||||||
templateSelect.addEventListener('change', function() {
|
templateSelect.addEventListener('change', function() {
|
||||||
@@ -640,7 +733,7 @@ var ConfigUploader = {
|
|||||||
ageCopyPublic.addEventListener('click', function() {
|
ageCopyPublic.addEventListener('click', function() {
|
||||||
var v = agePublicInput.value || '';
|
var v = agePublicInput.value || '';
|
||||||
if (v === '') { alert('<%:No public key%>'); return; }
|
if (v === '') { alert('<%:No public key%>'); return; }
|
||||||
copyToClipboard(v);
|
ocCopyToClipboard(v, ageCopyPublic);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -648,7 +741,7 @@ var ConfigUploader = {
|
|||||||
ageCopySecret.addEventListener('click', function() {
|
ageCopySecret.addEventListener('click', function() {
|
||||||
var v = ageSecretInput.value || '';
|
var v = ageSecretInput.value || '';
|
||||||
if (v === '') { alert('<%:No secret key%>'); return; }
|
if (v === '') { alert('<%:No secret key%>'); return; }
|
||||||
copyToClipboard(v);
|
ocCopyToClipboard(v, ageCopySecret);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -676,18 +769,9 @@ var ConfigUploader = {
|
|||||||
if (agePublicInput) agePublicInput.addEventListener('input', self.updateSubmitButton.bind(self));
|
if (agePublicInput) agePublicInput.addEventListener('input', self.updateSubmitButton.bind(self));
|
||||||
if (ageSecretInput) ageSecretInput.addEventListener('input', self.updateSubmitButton.bind(self));
|
if (ageSecretInput) ageSecretInput.addEventListener('input', self.updateSubmitButton.bind(self));
|
||||||
|
|
||||||
function copyToClipboard(text) {
|
document.getElementById('subscribe-headers-add').addEventListener('click', function() {
|
||||||
if (navigator && navigator.clipboard && navigator.clipboard.writeText) {
|
self.addHeaderRow('', '');
|
||||||
navigator.clipboard.writeText(text);
|
});
|
||||||
} else {
|
|
||||||
var ta = document.createElement('textarea');
|
|
||||||
ta.value = text;
|
|
||||||
document.body.appendChild(ta);
|
|
||||||
ta.select();
|
|
||||||
document.execCommand('copy');
|
|
||||||
document.body.removeChild(ta);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
document.getElementById('config-upload-submit').addEventListener('click', function() {
|
document.getElementById('config-upload-submit').addEventListener('click', function() {
|
||||||
if (self.currentMode === 'file') {
|
if (self.currentMode === 'file') {
|
||||||
@@ -793,6 +877,12 @@ var ConfigUploader = {
|
|||||||
this.reset();
|
this.reset();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
updateSubconverterVersionStatus: function() {
|
||||||
|
if (this.subconverterVersionChecker) {
|
||||||
|
this.subconverterVersionChecker.update();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
resetAdvancedOptions: function() {
|
resetAdvancedOptions: function() {
|
||||||
document.getElementById('sub-convert-enable').checked = false;
|
document.getElementById('sub-convert-enable').checked = false;
|
||||||
document.getElementById('sub-convert-options').style.display = 'none';
|
document.getElementById('sub-convert-options').style.display = 'none';
|
||||||
@@ -828,6 +918,7 @@ var ConfigUploader = {
|
|||||||
if (advFileEnable) advFileEnable.checked = false;
|
if (advFileEnable) advFileEnable.checked = false;
|
||||||
var advFileContainer = document.getElementById('advanced-options-container-file');
|
var advFileContainer = document.getElementById('advanced-options-container-file');
|
||||||
if (advFileContainer) advFileContainer.style.display = 'none';
|
if (advFileContainer) advFileContainer.style.display = 'none';
|
||||||
|
if (this.subconverterVersionChecker) this.subconverterVersionChecker.hide();
|
||||||
},
|
},
|
||||||
|
|
||||||
reset: function() {
|
reset: function() {
|
||||||
@@ -842,6 +933,9 @@ var ConfigUploader = {
|
|||||||
document.getElementById('subscribe-url-input').value = '';
|
document.getElementById('subscribe-url-input').value = '';
|
||||||
document.getElementById('subscribe-ua-input').value = 'clash-verge/v2.4.5';
|
document.getElementById('subscribe-ua-input').value = 'clash-verge/v2.4.5';
|
||||||
document.getElementById('subscribe-ua-custom').style.display = 'none';
|
document.getElementById('subscribe-ua-custom').style.display = 'none';
|
||||||
|
var hdrContainer = document.getElementById('subscribe-headers-container');
|
||||||
|
hdrContainer.innerHTML = '';
|
||||||
|
hdrContainer.style.display = 'none';
|
||||||
|
|
||||||
document.getElementById('advanced-options-enable').checked = false;
|
document.getElementById('advanced-options-enable').checked = false;
|
||||||
document.getElementById('advanced-options-container').style.display = 'none';
|
document.getElementById('advanced-options-container').style.display = 'none';
|
||||||
@@ -883,7 +977,22 @@ var ConfigUploader = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.sub_convert === '1' || data.convert_address || data.template || data.custom_template_url || data.emoji === 'true' || data.udp === 'true' || data.skip_cert_verify === 'true' || data.sort === 'true' || data.node_type === 'true' || data.rule_provider === 'true' || data.custom_params || data.keyword || data.ex_keyword || data.de_ex_keyword || data.config_age_secret || data.config_age_public || data.config_age_algo) {
|
if (data.sub_headers) {
|
||||||
|
var container = document.getElementById('subscribe-headers-container');
|
||||||
|
container.innerHTML = '';
|
||||||
|
var lines = data.sub_headers.split('\n');
|
||||||
|
for (var i = 0; i < lines.length; i++) {
|
||||||
|
var line = lines[i].trim();
|
||||||
|
if (line) {
|
||||||
|
var colonIdx = line.indexOf(':');
|
||||||
|
var name = colonIdx > 0 ? line.substring(0, colonIdx).trim() : line;
|
||||||
|
var value = colonIdx > 0 ? line.substring(colonIdx + 1).trim() : '';
|
||||||
|
ConfigUploader.addHeaderRow(name, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.sub_convert === '1' || data.convert_address || data.template || data.custom_template_url || data.emoji === 'true' || data.udp === 'true' || data.skip_cert_verify === 'true' || data.sort === 'true' || data.node_type === 'true' || data.rule_provider === 'true' || data.custom_params || data.keyword || data.ex_keyword || data.de_ex_keyword || data.sub_headers || data.config_age_secret || data.config_age_public || data.config_age_algo) {
|
||||||
document.getElementById('advanced-options-enable').checked = true;
|
document.getElementById('advanced-options-enable').checked = true;
|
||||||
document.getElementById('advanced-options-container').style.display = 'block';
|
document.getElementById('advanced-options-container').style.display = 'block';
|
||||||
|
|
||||||
@@ -963,6 +1072,8 @@ var ConfigUploader = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.updateSubconverterVersionStatus();
|
||||||
},
|
},
|
||||||
|
|
||||||
switchMode: function(mode) {
|
switchMode: function(mode) {
|
||||||
@@ -1085,23 +1196,12 @@ var ConfigUploader = {
|
|||||||
|
|
||||||
if (url && filename) {
|
if (url && filename) {
|
||||||
if (subConvert) {
|
if (subConvert) {
|
||||||
var linkPattern = this._linkRe;
|
var links = UrlValidator.extractUrls(url, true);
|
||||||
|
isValidFormat = UrlValidator.anyValid(links, true);
|
||||||
if (url.indexOf('\n') !== -1 || url.indexOf('|') !== -1) {
|
|
||||||
var links = url.split(/[\n|]/);
|
|
||||||
for (var i = 0; i < links.length; i++) {
|
|
||||||
var link = links[i].trim();
|
|
||||||
if (link && linkPattern.test(link)) {
|
|
||||||
isValidFormat = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
isValidFormat = linkPattern.test(url);
|
if (/^https?:\/\//.test(url) && url.indexOf('\n') === -1) {
|
||||||
}
|
var singleUrls = UrlValidator.extractUrls(url, false);
|
||||||
} else {
|
isValidFormat = singleUrls.length === 1 && UrlValidator.validateUrl(singleUrls[0], false).valid;
|
||||||
if (/^https?:\/\//.test(url) && url.indexOf('\n') === -1 && url.indexOf('|') === -1) {
|
|
||||||
isValidFormat = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (filename && (agePublic || ageSecret)) {
|
} else if (filename && (agePublic || ageSecret)) {
|
||||||
@@ -1252,6 +1352,7 @@ var ConfigUploader = {
|
|||||||
var keywords = '';
|
var keywords = '';
|
||||||
var excludeKeywords = '';
|
var excludeKeywords = '';
|
||||||
var excludeDefaults = [];
|
var excludeDefaults = [];
|
||||||
|
var customHeaders = ConfigUploader.collectHeaders();
|
||||||
|
|
||||||
if (advancedEnabled) {
|
if (advancedEnabled) {
|
||||||
convertAddress = document.getElementById('convert-address-input').value;
|
convertAddress = document.getElementById('convert-address-input').value;
|
||||||
@@ -1302,23 +1403,12 @@ var ConfigUploader = {
|
|||||||
var isValidFormat = false;
|
var isValidFormat = false;
|
||||||
|
|
||||||
if (subConvert) {
|
if (subConvert) {
|
||||||
var linkPattern = this._linkRe;
|
var links = UrlValidator.extractUrls(url, true);
|
||||||
|
isValidFormat = UrlValidator.anyValid(links, true);
|
||||||
if (url.indexOf('\n') !== -1 || url.indexOf('|') !== -1) {
|
|
||||||
var links = url.split(/[\n|]/);
|
|
||||||
for (var i = 0; i < links.length; i++) {
|
|
||||||
var link = links[i].trim();
|
|
||||||
if (link && linkPattern.test(link)) {
|
|
||||||
isValidFormat = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
isValidFormat = linkPattern.test(url);
|
if (/^https?:\/\//.test(url) && url.indexOf('\n') === -1) {
|
||||||
}
|
var singleUrls = UrlValidator.extractUrls(url, false);
|
||||||
} else {
|
isValidFormat = singleUrls.length === 1 && UrlValidator.validateUrl(singleUrls[0], false).valid;
|
||||||
if (/^https?:\/\//.test(url) && url.indexOf('\n') === -1 && url.indexOf('|') === -1) {
|
|
||||||
isValidFormat = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1376,7 +1466,8 @@ var ConfigUploader = {
|
|||||||
custom_params: customParams,
|
custom_params: customParams,
|
||||||
keyword: keywords,
|
keyword: keywords,
|
||||||
ex_keyword: excludeKeywords,
|
ex_keyword: excludeKeywords,
|
||||||
de_ex_keyword: excludeDefaults.join(' ')
|
de_ex_keyword: excludeDefaults.join(' '),
|
||||||
|
sub_headers: customHeaders
|
||||||
}, function(x, data) {
|
}, function(x, data) {
|
||||||
if (x && x.status == 200 && data.status === 'success') {
|
if (x && x.status == 200 && data.status === 'success') {
|
||||||
XHR.get('<%=luci.dispatcher.build_url("admin", "services", "openclash", "update_config")%>', {
|
XHR.get('<%=luci.dispatcher.build_url("admin", "services", "openclash", "update_config")%>', {
|
||||||
@@ -1458,6 +1549,60 @@ var ConfigUploader = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
addHeaderRow: function(name, value) {
|
||||||
|
var container = document.getElementById('subscribe-headers-container');
|
||||||
|
var row = document.createElement('div');
|
||||||
|
row.className = 'form-row header-row';
|
||||||
|
row.style.cssText = 'align-items: center; gap: 6px; margin-bottom: 6px;';
|
||||||
|
|
||||||
|
var nameInput = document.createElement('input');
|
||||||
|
nameInput.type = 'text';
|
||||||
|
nameInput.className = 'form-input';
|
||||||
|
nameInput.placeholder = 'Header-Name';
|
||||||
|
nameInput.value = name || '';
|
||||||
|
nameInput.style.cssText = 'flex: 1; height: 32px;';
|
||||||
|
|
||||||
|
var valueInput = document.createElement('input');
|
||||||
|
valueInput.type = 'text';
|
||||||
|
valueInput.className = 'form-input';
|
||||||
|
valueInput.placeholder = 'value';
|
||||||
|
valueInput.value = value || '';
|
||||||
|
valueInput.style.cssText = 'flex: 1.5; height: 32px;';
|
||||||
|
|
||||||
|
var removeBtn = document.createElement('button');
|
||||||
|
removeBtn.type = 'button';
|
||||||
|
removeBtn.className = 'icon-btn';
|
||||||
|
removeBtn.title = '<%:Remove%>';
|
||||||
|
removeBtn.style.cssText = 'flex-shrink: 0;';
|
||||||
|
removeBtn.innerHTML = '<svg width="14" height="14"><use href="#oc-icon-close"/></svg>';
|
||||||
|
removeBtn.addEventListener('click', function() {
|
||||||
|
row.parentNode.removeChild(row);
|
||||||
|
if (container.children.length === 0) {
|
||||||
|
container.style.display = 'none';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
row.appendChild(nameInput);
|
||||||
|
row.appendChild(valueInput);
|
||||||
|
row.appendChild(removeBtn);
|
||||||
|
container.appendChild(row);
|
||||||
|
container.style.display = 'block';
|
||||||
|
},
|
||||||
|
|
||||||
|
collectHeaders: function() {
|
||||||
|
var rows = document.querySelectorAll('#subscribe-headers-container .header-row');
|
||||||
|
var headers = [];
|
||||||
|
for (var i = 0; i < rows.length; i++) {
|
||||||
|
var inputs = rows[i].querySelectorAll('input');
|
||||||
|
var name = inputs[0].value.trim();
|
||||||
|
var value = inputs[1].value.trim();
|
||||||
|
if (name) {
|
||||||
|
headers.push(name + ': ' + (value || ''));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return headers.join('\n');
|
||||||
|
},
|
||||||
|
|
||||||
handleError: function(message) {
|
handleError: function(message) {
|
||||||
var statusText = document.getElementById('config-upload-status-text');
|
var statusText = document.getElementById('config-upload-status-text');
|
||||||
var progressText = document.getElementById('upload-progress-text');
|
var progressText = document.getElementById('upload-progress-text');
|
||||||
|
|||||||
@@ -131,6 +131,7 @@ local dns_host = "www.instagram.com"
|
|||||||
}
|
}
|
||||||
//]]></script>
|
//]]></script>
|
||||||
|
|
||||||
|
<div class="oc">
|
||||||
<form>
|
<form>
|
||||||
<fieldset class="diag-style">
|
<fieldset class="diag-style">
|
||||||
<div style="width:50%; float: left; text-align: center; white-space: nowrap;">
|
<div style="width:50%; float: left; text-align: center; white-space: nowrap;">
|
||||||
@@ -155,3 +156,4 @@ local dns_host = "www.instagram.com"
|
|||||||
<span id="dns-rc-output"></span>
|
<span id="dns-rc-output"></span>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
</div>
|
||||||
@@ -73,7 +73,7 @@
|
|||||||
immortalwrt.innerHTML = createAvatarHTML('https://avatars.githubusercontent.com/u/82308430?v=4', 'immortalwrt', 'immortalwrt', 'immortalwrt_rediret');
|
immortalwrt.innerHTML = createAvatarHTML('https://avatars.githubusercontent.com/u/82308430?v=4', 'immortalwrt', 'immortalwrt', 'immortalwrt_rediret');
|
||||||
lmc999.innerHTML = createAvatarHTML('https://avatars.githubusercontent.com/u/39726914?v=4', 'lmc999', 'lmc999', 'lmc999_rediret');
|
lmc999.innerHTML = createAvatarHTML('https://avatars.githubusercontent.com/u/39726914?v=4', 'lmc999', 'lmc999', 'lmc999_rediret');
|
||||||
MetaCubeX.innerHTML = createAvatarHTML('https://avatars.githubusercontent.com/u/84378451?v=4', 'MetaCubeX', 'MetaCubeX', 'MetaCubeX_rediret');
|
MetaCubeX.innerHTML = createAvatarHTML('https://avatars.githubusercontent.com/u/84378451?v=4', 'MetaCubeX', 'MetaCubeX', 'MetaCubeX_rediret');
|
||||||
oixcloud.innerHTML = createAvatarHTML('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAYAAAErdZjwAAAACXBIWXMAAAsTAAALEwEAmpwYAAAGsGlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDggNzkuMTY0MDM2LCAyMDE5LzA4LzEzLTAxOjA2OjU3ICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgMjEuMCAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDI2LTA2LTExVDAwOjU0OjU4KzA4OjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAyNi0wNi0xMVQyMzoyNjowNyswODowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAyNi0wNi0xMVQyMzoyNjowNyswODowMCIgZGM6Zm9ybWF0PSJpbWFnZS9wbmciIHBob3Rvc2hvcDpDb2xvck1vZGU9IjMiIHBob3Rvc2hvcDpJQ0NQcm9maWxlPSJzUkdCIElFQzYxOTY2LTIuMSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo0ZjA3Mjk4Yi03M2E1LTcxNDItODE2MS03ZTkyNDlmMGU0ODkiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OGM3YzA4NjMtYzdlOS0yYzQ1LTk1ODYtNDgxZjMxYzM0MmFjIiB4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ9InhtcC5kaWQ6OGM3YzA4NjMtYzdlOS0yYzQ1LTk1ODYtNDgxZjMxYzM0MmFjIj4gPHhtcE1NOkhpc3Rvcnk+IDxyZGY6U2VxPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0iY3JlYXRlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDo4YzdjMDg2My1jN2U5LTJjNDUtOTU4Ni00ODFmMzFjMzQyYWMiIHN0RXZ0OndoZW49IjIwMjYtMDYtMTFUMDA6NTQ6NTgrMDg6MDAiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCAyMS4wIChXaW5kb3dzKSIvPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0ic2F2ZWQiIHN0RXZ0Omluc3RhbmNlSUQ9InhtcC5paWQ6MTg5NzBjODctZDk2My1iMjRiLWJlNDEtOTkyMTE5MjhhNDIxIiBzdEV2dDp3aGVuPSIyMDI2LTA2LTExVDIzOjE0OjA5KzA4OjAwIiBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgMjEuMCAoV2luZG93cykiIHN0RXZ0OmNoYW5nZWQ9Ii8iLz4gPHJkZjpsaSBzdEV2dDphY3Rpb249InNhdmVkIiBzdEV2dDppbnN0YW5jZUlEPSJ4bXAuaWlkOjRmMDcyOThiLTczYTUtNzE0Mi04MTYxLTdlOTI0OWYwZTQ4OSIgc3RFdnQ6d2hlbj0iMjAyNi0wNi0xMVQyMzoyNjowNyswODowMCIgc3RFdnQ6c29mdHdhcmVBZ2VudD0iQWRvYmUgUGhvdG9zaG9wIDIxLjAgKFdpbmRvd3MpIiBzdEV2dDpjaGFuZ2VkPSIvIi8+IDwvcmRmOlNlcT4gPC94bXBNTTpIaXN0b3J5PiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PiagcG0AADMvSURBVHic7b15eFRFvv9fZ+k1ne7ORgJZiJCYgAiB4A2LgoiExFxQQGE0qHAFGUTmjtfx6zA+M+pzdWYckDs6A+IMaxBBARUN66i4BBwRAhIWQyAQCNl77z591qrfHwK/EDrpTm8nyanX85xHn3BO16eq3vU5tXxOFYEQQkBGSDkTxwZgA7ABIRuwYcMGx9ChQ0OzAAXJrFmzLAAAdP0KFiJYT0gQRMeMBFUAQVWBWq0Om/vutgFut1sSBOGm7J87d84ZrAHdroKORU8QBIAQBpt+90pg8+bN7o5/EwQBAvBztRAEASiK6p4F3VEsaKd6AABKSkriEELov//7v5vb//33v/+9GPBvBnrj4cOHbzGgM8NWrlzJhd2AtrY2tn0ir776qhshhBITE4XODAurAQghtHjxYicAABUWFrI3fqBD4idOnPB25zcDagWSJPkUV8cWcU1TAAAARFGEFEWRvu5pj99WQBAEoGkaEAQBDh8+fKO9V1RUsD4MhdefUalUJEmS4Ouvv+7SR/gtgc5cbse/m0wm0W63010944tu+YGZM2e6rv//lClTbsrZ9cQ7Mn36dJevv7e3rkskSYJmsxn97ne/c3T8t6VLlzrNZvMtz0AIodlsRr/97W+tYRFhJOndPSJsADagTxiA/QA2ABuADQjaAIQQuuOOO8BLL71kD8kCfz2WzgDtuuJPP/006/+JTn4nmIcGDRrEgRAGI+3pdhUghEBtba26/d/WrVvHBVsD3X4XkCR5Sze7mz9x8+915+a6ujp3x8QEQQjtZdad+gId6p2maYgQQlVVVc7rfzt06JDfrvhNvxnojQsXLmzraEBnhkXEgI6JPPjggyxCCA0ePJiVxYDO/v7uu+92qwoCbgUIIUDTNEAIAZ7nEU3TRDhaRECtgGVZiSAIIEkSgBACmqaJ5uZmrmNiDofjxnSZ1+sVA7Kgq+L55ptvbvJ4XVWJTqcTEULo2LFjfGfPdLsKOhZx+/8PdN7AX5V0WQX33ntvQDOgEyZMuDFbMnXqVEcgz9zAXxEtWbLE5xyAJEkwISEBvfTSS7eofsmSJTaz2YwghDCkKogGvbdHhA3ABvQZA2T3A3Ijew3IDS4AuQ2QG1wAchsgN7gA5DZAbmQpAL1ejwiCAO2vtLQ0IZQQkGCJakfo6tWrXFpamqare6LdL4uaAo4cOeLyl3mdTidFy57rRKUA/t//+3/WgoKC2K7uiY+PlzweTzcjj8KAv0mDUCkqKrpl7rDjdccddwiRtqMzIloA8fHxt8Q1dbyWLl1q6/jc5s2b68eNG4fWrFlzNZL2IRShAhBFEarVaugv8xUVFTcWdyCEUKvVdvqMKIpSJGwNewGwLCv6yzgAAF29evVG5j0ej99nZs+ebQ+3rQhFoAAOHjzYpewJgrjp/mPHjjH+Mt/xmXASkSYwYsQIt6+MJCcn8+3ve/vttxv8ZT4pKYnvLJ1wEFEnKIoidDgckOf5W0JaZ86c6fftkJeX161YzGAIuQAOHjzI0zR9w2iKotCOHTuYrp5JS0vzm/nFixffNOd/8OBBRqVS3dQstm/fHvQK+XVCKgC9Xi91lgGtVuvTa3f1zPVr06ZNbKDPJCYmhtREQhoL+FoibI+vf/MX0VtVVeUZNmxYTHeeCSELoXWFeZ6XNBrNLamrVCrE87xPqyCEwNczOp0OchyHOmYeAAAEQfCZjl6vl3ieD9Z8AACeFscTIrgA5DZAbnAByG2A3OACkNsAuVF8AeCOkNwGyA0uALkNkBtcAHIbIDe4AOQ2QG5wAchtgNzgApDbALnBBSC3AXKDC0BuA+RGlgJoamryPvDAA2xOTg647777+FOnToW2vBMKoSwsBsO2bdtuCYggCAKVl5cHvClTOInqjJDL5ZKMRmOnoXBut1uKiYmJaqhcVJvAAw880OU3ne+++641WrZcJ2oFUFNT46ioqOgyUrS+vt7nDk2RJGoF8B//8R8Gf/dMnz496gUQFSe4ceNGv5FgUTLlFiLuBCGEkKZp0l8y586dE7Ozs/teE5g/f77DX+YHDBggyJF5ACK8MGKxWITExESVv/saGxu5lJSULh1kpIioAsaNG+e3cOfOncvKlXkAQOQ8zw8//OAzWrTjJUnSTeF0drvdO2/ePOYXv/iFt6mpyR0p+64TsQIwGAx+A6D/+te/eto/c//9999SaDk5OawkSX43QwiWiBTAq6++esvOLx2vxMREof0mD8uXL+/0mRkzZnQZeRoKYS8AhmH8RoICAFBlZeWNUFie57t8hiTJcJt5g7AXwJw5c27ZcKrjlZqaelPw9IwZM/w+E8CWIEER9tegSqUCotj1PjYQQkRci3+9evUqk5aWpu/qfrVajTiO6zpeNkjC/hqUpK6/fFu4cKGLaBf8O3bsWL8doN/97ne2MJjmm3BL6p577un09afVaqEgCDdee59++qmrs3uvXzExMVIgW+IES9gLwGq1dvrhU0VFxU2h7SqVyu+HVV9++WVEZ4oi8hq0WCxSZmbmjY8iEhIS+CNHjtz0zn/hhRes/jKfmJgY8WLine truncated
|
oixcloud.innerHTML = createAvatarHTML('/luci-static/resources/openclash/img/oixcloud.png', 'oixCloud', 'oixcloud', 'oixcloud_rediret');
|
||||||
more.innerHTML = createMoreAvatarHTML('<%:More%>', 'more_rediret');
|
more.innerHTML = createMoreAvatarHTML('<%:More%>', 'more_rediret');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,12 @@
|
|||||||
<%+cbi/valueheader%>
|
<%+cbi/valueheader%>
|
||||||
|
<%
|
||||||
|
local fs = require "luci.openclash"
|
||||||
|
local plugin_version = fs.oc_version()
|
||||||
|
%>
|
||||||
|
<script src="/luci-static/resources/openclash/js/oc-icons.js?v=<%=plugin_version%>"></script>
|
||||||
|
<%+openclash/common%>
|
||||||
<body>
|
<body>
|
||||||
<div id="tab" class="cbi-section">
|
<div id="tab" class="cbi-section oc">
|
||||||
<div id="tab-header">
|
<div id="tab-header">
|
||||||
<ul class="cbi-tabmenu">
|
<ul class="cbi-tabmenu">
|
||||||
<li name="tab-header" class="cbi-tab"><a href="#"><%:OpenClash Log%></a></li>
|
<li name="tab-header" class="cbi-tab"><a href="#"><%:OpenClash Log%></a></li>
|
||||||
@@ -31,7 +37,7 @@
|
|||||||
<textarea id="debug_log" class="cbi-input-textarea" style="width: 100%;display:none" data-update="change" rows="32" cols="60" readonly="readonly" ></textarea>
|
<textarea id="debug_log" class="cbi-input-textarea" style="width: 100%;display:none" data-update="change" rows="32" cols="60" readonly="readonly" ></textarea>
|
||||||
<div id="debug-render-wrapper">
|
<div id="debug-render-wrapper">
|
||||||
<div id="debug-rendered"></div>
|
<div id="debug-rendered"></div>
|
||||||
<div class="oc-usage-help-float" id="debug-copy-source" onclick="copyDebugSource()" title="<%:Copy Debug%>"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg></div>
|
<div class="oc-usage-help-float" id="debug-copy-source" onclick="copyDebugSource()" title="<%:Copy Debug%>"><svg width="20" height="20"><use href="#oc-icon-copy"/></svg></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -45,7 +51,7 @@
|
|||||||
<input type="button" class="btn cbi-button cbi-button-apply" id="down_log_button" value="<%:Download Log%>" onclick=" return download_log() " />
|
<input type="button" class="btn cbi-button cbi-button-apply" id="down_log_button" value="<%:Download Log%>" onclick=" return download_log() " />
|
||||||
<span style="display:inline-flex; align-items:center; gap:4px;">
|
<span style="display:inline-flex; align-items:center; gap:4px;">
|
||||||
<input type="button" class="btn cbi-button cbi-button-apply" id="gen_debug_button" value="<%:Generate Logs%>" onclick="return gen_debug_logs()" />
|
<input type="button" class="btn cbi-button cbi-button-apply" id="gen_debug_button" value="<%:Generate Logs%>" onclick="return gen_debug_logs()" />
|
||||||
<span id="debug_loading" style="display:none; vertical-align:middle;"><img src="<%=resource%>/icons/loading.svg" onerror="this.onerror=null;this.src='<%=resource%>/icons/loading.gif'" alt="<%:Loading...%>" style="vertical-align:middle" /></span>
|
<span id="debug_loading" style="display:none; vertical-align:middle; line-height:1;"><img src="<%=resource%>/icons/loading.svg" onerror="this.onerror=null;this.src='<%=resource%>/icons/loading.gif'" alt="<%:Loading...%>" style="vertical-align:middle; height:1.6em; width:auto;" /></span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
@@ -68,6 +74,37 @@ var wsRetryDelay = 2000;
|
|||||||
var wsRetryTimer = null;
|
var wsRetryTimer = null;
|
||||||
var isPolling = false;
|
var isPolling = false;
|
||||||
var core_refresh = true;
|
var core_refresh = true;
|
||||||
|
var wsHasData = false;
|
||||||
|
var coreEditorInitialized = false;
|
||||||
|
var editor_core;
|
||||||
|
var coreLogAccumulator = '';
|
||||||
|
var pollInterval = 1000;
|
||||||
|
|
||||||
|
function accumulateCoreLog(linesArr) {
|
||||||
|
var reversed = linesArr.slice().reverse();
|
||||||
|
var batchStr = '';
|
||||||
|
for (var k = 0; k < reversed.length; k++) {
|
||||||
|
batchStr += reversed[k] + '\n';
|
||||||
|
}
|
||||||
|
if (coreLogAccumulator) {
|
||||||
|
var accFirstLineEnd = coreLogAccumulator.indexOf('\n');
|
||||||
|
var accFirstLine = accFirstLineEnd > 0 ? coreLogAccumulator.substring(0, accFirstLineEnd) : coreLogAccumulator;
|
||||||
|
var batchTrimmed = batchStr.slice(0, -1);
|
||||||
|
var batchLastLineStart = batchTrimmed.lastIndexOf('\n');
|
||||||
|
var batchLastLine = batchLastLineStart > 0 ? batchTrimmed.substring(batchLastLineStart + 1) : batchTrimmed;
|
||||||
|
if (accFirstLine === batchLastLine) {
|
||||||
|
batchStr = batchLastLineStart > 0 ? batchStr.substring(0, batchLastLineStart + 1) : '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
coreLogAccumulator = batchStr + coreLogAccumulator;
|
||||||
|
var accLines = coreLogAccumulator.split('\n');
|
||||||
|
if (accLines.length > 2000) {
|
||||||
|
accLines = accLines.slice(0, 1999);
|
||||||
|
accLines.push('...');
|
||||||
|
coreLogAccumulator = accLines.join('\n');
|
||||||
|
}
|
||||||
|
cl.value = coreLogAccumulator;
|
||||||
|
}
|
||||||
|
|
||||||
function setLogTab(log_level) {
|
function setLogTab(log_level) {
|
||||||
var radio = document.getElementsByName("radios");
|
var radio = document.getElementsByName("radios");
|
||||||
@@ -235,7 +272,7 @@ function p(s) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function getWebSocketConnectionInfo(callback) {
|
function getWebSocketConnectionInfo(callback) {
|
||||||
XHR.get('<%=luci.dispatcher.build_url("admin", "services", "openclash", "status")%>', null, function(x, status) {
|
XHR.get('<%=luci.dispatcher.build_url("admin", "services", "openclash", "conn_status")%>', null, function(x, status) {
|
||||||
if (x && x.status == 200 && status) {
|
if (x && x.status == 200 && status) {
|
||||||
callback(status);
|
callback(status);
|
||||||
} else {
|
} else {
|
||||||
@@ -268,6 +305,7 @@ function coreLogWebSocketStop() {
|
|||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
|
|
||||||
coreLogBuffer = [];
|
coreLogBuffer = [];
|
||||||
|
wsHasData = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function coreLogWebSocketRetry() {
|
function coreLogWebSocketRetry() {
|
||||||
@@ -307,6 +345,7 @@ function coreLogWebSocket() {
|
|||||||
coreWebSocket = new WebSocket(wsUrl);
|
coreWebSocket = new WebSocket(wsUrl);
|
||||||
coreWebSocket.onopen = function() {
|
coreWebSocket.onopen = function() {
|
||||||
coreLogBuffer = [];
|
coreLogBuffer = [];
|
||||||
|
wsHasData = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
coreWebSocket.onmessage = function(event) {
|
coreWebSocket.onmessage = function(event) {
|
||||||
@@ -314,6 +353,7 @@ function coreLogWebSocket() {
|
|||||||
try {
|
try {
|
||||||
var msgData = JSON.parse(event.data);
|
var msgData = JSON.parse(event.data);
|
||||||
if (msgData && msgData.payload) {
|
if (msgData && msgData.payload) {
|
||||||
|
wsHasData = true;
|
||||||
var now = new Date();
|
var now = new Date();
|
||||||
var timestamp = now.getFullYear() + "-" + p(now.getMonth() + 1) + "-" + p(now.getDate()) + " " +
|
var timestamp = now.getFullYear() + "-" + p(now.getMonth() + 1) + "-" + p(now.getDate()) + " " +
|
||||||
p(now.getHours()) + ":" + p(now.getMinutes()) + ":" + p(now.getSeconds());
|
p(now.getHours()) + ":" + p(now.getMinutes()) + ":" + p(now.getSeconds());
|
||||||
@@ -509,8 +549,9 @@ function smoothlyDisplayLogs(newLines, target, isEditor, currentContent, isActiv
|
|||||||
}
|
}
|
||||||
} else if (isAtTop) {
|
} else if (isAtTop) {
|
||||||
target.scrollTo(0, 0);
|
target.scrollTo(0, 0);
|
||||||
if (isFirstLoad) {
|
if (!cursorPos) {
|
||||||
target.setCursor({line: 0, ch: 0});
|
var firstLineLen = target.state.doc.line(1).length;
|
||||||
|
target.setCursor({line: 0, ch: firstLineLen});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -587,6 +628,13 @@ function smoothlyDisplayLogs(newLines, target, isEditor, currentContent, isActiv
|
|||||||
target.scrollIntoView({line: cursorPos.line, ch: cursorPos.ch}, 300);
|
target.scrollIntoView({line: cursorPos.line, ch: cursorPos.ch}, 300);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (isEditor && !cursorPos) {
|
||||||
|
var doc = target.state.doc;
|
||||||
|
if (doc.lines >= 1) {
|
||||||
|
var fl = doc.line(1);
|
||||||
|
target.dispatch({ selection: { anchor: fl.to } });
|
||||||
|
}
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -652,6 +700,13 @@ function smoothlyDisplayLogs(newLines, target, isEditor, currentContent, isActiv
|
|||||||
target.scrollIntoView({line: cursorPos.line, ch: cursorPos.ch}, 300);
|
target.scrollIntoView({line: cursorPos.line, ch: cursorPos.ch}, 300);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (isEditor && !cursorPos) {
|
||||||
|
var doc = target.state.doc;
|
||||||
|
if (doc.lines >= 1) {
|
||||||
|
var fl = doc.line(1);
|
||||||
|
target.dispatch({ selection: { anchor: fl.to } });
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -677,17 +732,16 @@ function poll_log(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (coreWebSocket && coreWebSocket.readyState == WebSocket.OPEN) {
|
if (coreWebSocket && coreWebSocket.readyState == WebSocket.OPEN) {
|
||||||
core_refresh = false;
|
core_refresh = !wsHasData;
|
||||||
if (coreLogBuffer.length > 0) {
|
if (coreLogBuffer.length > 0) {
|
||||||
bufferToProcess = coreLogBuffer;
|
bufferToProcess = coreLogBuffer;
|
||||||
coreLogBuffer = [];
|
coreLogBuffer = [];
|
||||||
core_logs = line_tolocal(bufferToProcess.join('\n'));
|
core_logs = line_tolocal(bufferToProcess.join('\n'));
|
||||||
if (editor_core) {
|
if (editor_core && activeTabId === 1) {
|
||||||
currentCoreContent = editor_core.getValue();
|
currentCoreContent = editor_core.getValue();
|
||||||
smoothlyDisplayLogs(core_logs, editor_core, true, currentCoreContent, activeTabId === 1);
|
smoothlyDisplayLogs(core_logs, editor_core, true, currentCoreContent, true);
|
||||||
} else if (cl) {
|
} else {
|
||||||
currentCoreContent = cl.innerHTML;
|
accumulateCoreLog(core_logs);
|
||||||
smoothlyDisplayLogs(core_logs, cl, false, currentCoreContent, activeTabId === 1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -695,7 +749,11 @@ function poll_log(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isPolling) {
|
if (isPolling) {
|
||||||
r = setTimeout("poll_log()", 1000);
|
r = setTimeout("poll_log()", pollInterval);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (activeTabId === 2) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -710,7 +768,7 @@ function poll_log(){
|
|||||||
if (status) {
|
if (status) {
|
||||||
if (!status.update) {
|
if (!status.update) {
|
||||||
isPolling = false;
|
isPolling = false;
|
||||||
r = setTimeout("poll_log()", 1000);
|
r = setTimeout("poll_log()", pollInterval);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -736,19 +794,18 @@ function poll_log(){
|
|||||||
core_logs = line_tolocal(status.core_log);
|
core_logs = line_tolocal(status.core_log);
|
||||||
|
|
||||||
if (core_logs.length > 0) {
|
if (core_logs.length > 0) {
|
||||||
if (editor_core) {
|
if (editor_core && activeTabId === 1) {
|
||||||
currentCoreContent = editor_core.getValue();
|
currentCoreContent = editor_core.getValue();
|
||||||
smoothlyDisplayLogs(core_logs, editor_core, true, currentCoreContent, activeTabId === 1);
|
smoothlyDisplayLogs(core_logs, editor_core, true, currentCoreContent, true);
|
||||||
} else if (cl) {
|
} else {
|
||||||
currentCoreContent = cl.innerHTML;
|
accumulateCoreLog(core_logs);
|
||||||
smoothlyDisplayLogs(core_logs, cl, false, currentCoreContent, activeTabId === 1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
isPolling = false;
|
isPolling = false;
|
||||||
r = setTimeout("poll_log()", 1000);
|
r = setTimeout("poll_log()", pollInterval);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -769,12 +826,34 @@ window.onload = function(){
|
|||||||
function handleTabSwitch(tab) {
|
function handleTabSwitch(tab) {
|
||||||
return function(e) {
|
return function(e) {
|
||||||
if (tab.className === 'cbi-tab') return;
|
if (tab.className === 'cbi-tab') return;
|
||||||
|
var prevTabId = -1;
|
||||||
for(var j=0; j<titles.length; j++){
|
for(var j=0; j<titles.length; j++){
|
||||||
|
if (titles[j].className === 'cbi-tab') prevTabId = j;
|
||||||
titles[j].className = 'cbi-tab-disabled';
|
titles[j].className = 'cbi-tab-disabled';
|
||||||
divs[j].classList.remove('active');
|
divs[j].classList.remove('active');
|
||||||
}
|
}
|
||||||
tab.className = 'cbi-tab';
|
tab.className = 'cbi-tab';
|
||||||
divs[tab.id].classList.add('active');
|
divs[tab.id].classList.add('active');
|
||||||
|
|
||||||
|
if (prevTabId == 1 && editor_core) {
|
||||||
|
coreLogAccumulator = editor_core.getValue();
|
||||||
|
cl.value = coreLogAccumulator;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tab.id == 1 && !coreEditorInitialized) {
|
||||||
|
coreEditorInitialized = true;
|
||||||
|
if (typeof log_editor === 'function' && cl) {
|
||||||
|
cl.value = coreLogAccumulator;
|
||||||
|
log_editor(cl, 'core', true, '100%', '540px');
|
||||||
|
}
|
||||||
|
} else if (tab.id == 1 && editor_core) {
|
||||||
|
editor_core.setValue(coreLogAccumulator);
|
||||||
|
editor_core.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
pollInterval = (tab.id == 1) ? 5000 : 1000;
|
||||||
|
clearTimeout(r);
|
||||||
|
poll_log();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -815,11 +894,10 @@ function renderDebugView() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var pres = rendered.querySelectorAll('pre');
|
var pres = rendered.querySelectorAll('pre');
|
||||||
|
var copyIcon = '<svg width="14" height="14"><use href="#oc-icon-copy"/></svg>';
|
||||||
for (var i = 0; i < pres.length; i++) {
|
for (var i = 0; i < pres.length; i++) {
|
||||||
(function(pre) {
|
(function(pre) {
|
||||||
if (pre.parentNode && pre.parentNode.classList.contains('pre-copy-wrap')) return;
|
if (pre.parentNode && pre.parentNode.classList.contains('pre-copy-wrap')) return;
|
||||||
var copyIcon = '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>';
|
|
||||||
var checkIcon = '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg>';
|
|
||||||
var btn = document.createElement('div');
|
var btn = document.createElement('div');
|
||||||
btn.className = 'pre-copy-btn';
|
btn.className = 'pre-copy-btn';
|
||||||
btn.title = '<%:Copy%>';
|
btn.title = '<%:Copy%>';
|
||||||
@@ -827,31 +905,7 @@ function renderDebugView() {
|
|||||||
btn.onclick = function(e) {
|
btn.onclick = function(e) {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
var text = pre.textContent || '';
|
var text = pre.textContent || '';
|
||||||
var done = function() {
|
ocCopyToClipboard(text, btn);
|
||||||
btn.innerHTML = checkIcon;
|
|
||||||
setTimeout(function() { btn.innerHTML = copyIcon; }, 1200);
|
|
||||||
};
|
|
||||||
if (navigator.clipboard && navigator.clipboard.writeText) {
|
|
||||||
navigator.clipboard.writeText(text).then(done).catch(function() {
|
|
||||||
var ta = document.createElement('textarea');
|
|
||||||
ta.value = text;
|
|
||||||
ta.style.position = 'fixed'; ta.style.left = '-9999px';
|
|
||||||
document.body.appendChild(ta);
|
|
||||||
ta.select();
|
|
||||||
document.execCommand('copy');
|
|
||||||
document.body.removeChild(ta);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
var ta = document.createElement('textarea');
|
|
||||||
ta.value = text;
|
|
||||||
ta.style.position = 'fixed'; ta.style.left = '-9999px';
|
|
||||||
document.body.appendChild(ta);
|
|
||||||
ta.select();
|
|
||||||
document.execCommand('copy');
|
|
||||||
document.body.removeChild(ta);
|
|
||||||
done();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
var wrap = document.createElement('div');
|
var wrap = document.createElement('div');
|
||||||
wrap.className = 'pre-copy-wrap';
|
wrap.className = 'pre-copy-wrap';
|
||||||
@@ -866,11 +920,7 @@ function renderDebugView() {
|
|||||||
if (dl.parentNode && dl.parentNode.className.indexOf('oc') < 0) {
|
if (dl.parentNode && dl.parentNode.className.indexOf('oc') < 0) {
|
||||||
dl.parentNode.classList.add('oc');
|
dl.parentNode.classList.add('oc');
|
||||||
}
|
}
|
||||||
if (typeof isDarkBackground === 'function' && isDarkBackground(document.body)) {
|
ocUpdateTheme();
|
||||||
dl.parentNode.setAttribute('data-darkmode', 'true');
|
|
||||||
} else {
|
|
||||||
dl.parentNode.removeAttribute('data-darkmode');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function copyDebugSource() {
|
function copyDebugSource() {
|
||||||
@@ -881,35 +931,7 @@ function copyDebugSource() {
|
|||||||
src = dl.value || '';
|
src = dl.value || '';
|
||||||
}
|
}
|
||||||
if (!src) return;
|
if (!src) return;
|
||||||
var done = function() {
|
ocCopyToClipboard(src, document.getElementById('debug-copy-source'));
|
||||||
var btn = document.getElementById('debug-copy-source');
|
|
||||||
if (btn) {
|
|
||||||
var orig = btn.innerHTML;
|
|
||||||
btn.innerHTML = '<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg>';
|
|
||||||
setTimeout(function() { btn.innerHTML = orig; }, 1500);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if (navigator.clipboard && navigator.clipboard.writeText) {
|
|
||||||
navigator.clipboard.writeText(src).then(done).catch(function() {
|
|
||||||
var ta = document.createElement('textarea');
|
|
||||||
ta.value = src;
|
|
||||||
ta.style.position = 'fixed'; ta.style.left = '-9999px';
|
|
||||||
document.body.appendChild(ta);
|
|
||||||
ta.select();
|
|
||||||
document.execCommand('copy');
|
|
||||||
document.body.removeChild(ta);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
var ta = document.createElement('textarea');
|
|
||||||
ta.value = src;
|
|
||||||
ta.style.position = 'fixed'; ta.style.left = '-9999px';
|
|
||||||
document.body.appendChild(ta);
|
|
||||||
ta.select();
|
|
||||||
document.execCommand('copy');
|
|
||||||
document.body.removeChild(ta);
|
|
||||||
done();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//]]>
|
//]]>
|
||||||
|
|||||||
@@ -3,21 +3,20 @@
|
|||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta http-equiv="x-dns-prefetch-control" content="on">
|
<meta http-equiv="x-dns-prefetch-control" content="on">
|
||||||
<link rel="dns-prefetch" href="//cdn.jsdelivr.net">
|
<link rel="dns-prefetch" href="//cdn.jsdelivr.net">
|
||||||
|
<%
|
||||||
|
local fs = require "luci.openclash"
|
||||||
|
local plugin_version = fs.oc_version()
|
||||||
|
%>
|
||||||
|
<script src="/luci-static/resources/openclash/js/oc-icons.js?v=<%=plugin_version%>"></script>
|
||||||
<link rel="dns-prefetch" href="//whois.pconline.com.cn">
|
<link rel="dns-prefetch" href="//whois.pconline.com.cn">
|
||||||
<link rel="dns-prefetch" href="//pubstatic.b0.upaiyun.com">
|
<link rel="dns-prefetch" href="//pubstatic.b0.upaiyun.com">
|
||||||
<link rel="dns-prefetch" href="//api.ip.sb">
|
<link rel="dns-prefetch" href="//api.ip.sb">
|
||||||
<link rel="dns-prefetch" href="//api.ipify.org">
|
<link rel="dns-prefetch" href="//api.ipify.org">
|
||||||
<link rel="dns-prefetch" href="//api.ttt.sh">
|
|
||||||
<link rel="dns-prefetch" href="//myip.ipip.net">
|
<link rel="dns-prefetch" href="//myip.ipip.net">
|
||||||
<link rel="dns-prefetch" href="//qqwry.api.skk.moe">
|
|
||||||
<link rel="dns-prefetch" href="//d.skk.moe">
|
|
||||||
<link rel="preconnect" href="https://pubstatic.b0.upaiyun.com">
|
<link rel="preconnect" href="https://pubstatic.b0.upaiyun.com">
|
||||||
<link rel="preconnect" href="https://whois.pconline.com.cn">
|
<link rel="preconnect" href="https://whois.pconline.com.cn">
|
||||||
<link rel="preconnect" href="https://api.ip.sb">
|
<link rel="preconnect" href="https://api.ip.sb">
|
||||||
<link rel="preconnect" href="https://api.ipify.org">
|
<link rel="preconnect" href="https://api.ipify.org">
|
||||||
<link rel="preconnect" href="https://api.ttt.sh">
|
|
||||||
<link rel="preconnect" href="https://qqwry.api.skk.moe">
|
|
||||||
<link rel="preconnect" href="https://d.skk.moe">
|
|
||||||
<link rel="preconnect" href="http://myip.ipip.net">
|
<link rel="preconnect" href="http://myip.ipip.net">
|
||||||
<meta name="referrer" content="no-referrer">
|
<meta name="referrer" content="no-referrer">
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no,minimal-ui">
|
<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no,minimal-ui">
|
||||||
@@ -97,10 +96,9 @@
|
|||||||
<path d="M12 28L12 8" stroke="#333" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
|
<path d="M12 28L12 8" stroke="#333" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<path d="M36 28V8" stroke="#333" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
|
<path d="M36 28V8" stroke="#333" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
</svg>
|
</svg>
|
||||||
<svg id="data-refresh-icon" class="myip-icon-btn" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" onclick="return refresh_myip(this)">
|
<svg id="data-refresh-icon" class="myip-icon-btn" width="20" height="20" onclick="return refresh_myip(this)">
|
||||||
<title><%:Refresh%></title>
|
<title><%:Refresh%></title>
|
||||||
<path d="M23 4v6h-6"></path>
|
<use href="#oc-icon-refresh"/>
|
||||||
<path d="M20.49 15a9 9 0 1 1-2.12-9.36L23 10"></path>
|
|
||||||
</svg>
|
</svg>
|
||||||
</span>
|
</span>
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -1,112 +1,629 @@
|
|||||||
<%+cbi/valueheader%>
|
<%-
|
||||||
|
local fs = require "luci.openclash"
|
||||||
|
local logged_in = fs.uci_get_config("config", "oix_token") and true or false
|
||||||
|
local checkin_enabled = fs.uci_get_config("config", "oix_checkin") == "1"
|
||||||
|
local checkin_interval = fs.uci_get_config("config", "oix_checkin_interval") or "1"
|
||||||
|
local checkin_multiple = fs.uci_get_config("config", "oix_checkin_multiple") or "1"
|
||||||
|
local oix_params = fs.uci_get_config("config", "oix_params") or ""
|
||||||
|
local oix_default_params = fs.uci_get_config("config", "oix_default_params") or ""
|
||||||
|
local oix_logo_src = "/luci-static/resources/openclash/img/oixcloud.png"
|
||||||
|
local function oix_logo_img(cls)
|
||||||
|
return '<img class="'..cls..'" src="'..oix_logo_src..'" loading="lazy" alt="oixCloud" title="oixCloud">'
|
||||||
|
end
|
||||||
|
-%>
|
||||||
|
<div class="oc">
|
||||||
|
<script src="/luci-static/resources/openclash/js/oc-icons.js?v=<%=plugin_version%>"></script>
|
||||||
|
<fieldset class="cbi-section oix-panel">
|
||||||
|
<div id="oix-msg-bar" class="oix-msg-bar"></div>
|
||||||
|
<div id="oix-login-section"<%= logged_in and ' style="display:none;"' or '' %>>
|
||||||
|
<div class="oix-login-box">
|
||||||
|
|
||||||
|
<%= oix_logo_img("oix-logo") %>
|
||||||
|
|
||||||
|
<div class="mode-tabs" style="margin-bottom:14px;" id="oix-tabs">
|
||||||
|
<button type="button" class="mode-tab active" id="oix-tab-account" onclick="OixCloud.switchTab('account')">
|
||||||
|
<svg class="oc-icon" width="13" height="13"><use href="#oc-icon-user"/></svg>
|
||||||
|
<%:Account Login%>
|
||||||
|
</button>
|
||||||
|
<button type="button" class="mode-tab" id="oix-tab-token" onclick="OixCloud.switchTab('token')">
|
||||||
|
<svg class="oc-icon" width="13" height="13"><use href="#oc-icon-key-oix"/></svg>
|
||||||
|
<%:Token Login%>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="oix-panel-account">
|
||||||
|
<div style="margin-bottom:10px;">
|
||||||
|
<input type="text" id="oix-email" class="oix-input oix-input-ok" placeholder="<%:Account Email Address%>" autocomplete="email" inputmode="email"
|
||||||
|
value="<%= fs.uci_get_config('config', 'oix_email') or '' %>">
|
||||||
|
<span id="oix-email-hint" class="oix-field-hint oix-field-help"></span>
|
||||||
|
</div>
|
||||||
|
<div style="margin-bottom:14px;">
|
||||||
|
<div style="position:relative;">
|
||||||
|
<input type="password" id="oix-passwd" class="oix-input oix-input-ok" placeholder="<%:Account Password%>" autocomplete="current-password"
|
||||||
|
style="padding-right:36px;"
|
||||||
|
value="<%= fs.uci_get_config('config', 'oix_passwd') or '' %>">
|
||||||
|
<button type="button" class="oix-pwd-toggle" onclick="OixCloud.togglePwd('oix-passwd')" style="position:absolute;right:5px;top:50%;transform:translateY(-50%);background:none;border:none;cursor:pointer;padding:3px;line-height:0;" title="<%:Show/Hide Password%>">
|
||||||
|
<svg class="oc-icon oix-eye-icon" width="15" height="15"><use href="#oc-icon-eye"/></svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<span id="oix-passwd-hint" class="oix-field-hint oix-field-help"></span>
|
||||||
|
</div>
|
||||||
|
<button type="button" class="oix-btn oix-btn-primary oix-btn-block" onclick="OixCloud.doLogin()">
|
||||||
|
<svg class="oc-icon" width="14" height="14"><use href="#oc-icon-login"/></svg>
|
||||||
|
<%:Login Account%>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<div style="text-align:center;margin-top:12px;">
|
||||||
|
<button type="button" class="oix-btn oix-btn-ghost oix-btn-block" onclick="OixCloud.openWebsite();return false;">
|
||||||
|
<svg class="oc-icon" width="14" height="14"><use href="#oc-icon-home"/></svg>
|
||||||
|
<%:oixCloud Website%>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="oix-panel-token" style="display:none;">
|
||||||
|
<div style="margin-bottom:14px;">
|
||||||
|
<div style="position:relative;">
|
||||||
|
<input type="password" id="oix-token" class="oix-input oix-input-ok" placeholder="<%:Enter your oixCloud token%>"
|
||||||
|
style="padding-right:36px;"
|
||||||
|
value="<%= fs.uci_get_config('config', 'oix_token') or '' %>">
|
||||||
|
<button type="button" class="oix-pwd-toggle" onclick="OixCloud.togglePwd('oix-token')" style="position:absolute;right:5px;top:50%;transform:translateY(-50%);background:none;border:none;cursor:pointer;padding:3px;line-height:0;" title="<%:Show/Hide Token%>">
|
||||||
|
<svg class="oc-icon oix-eye-icon" width="15" height="15"><use href="#oc-icon-eye"/></svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<span id="oix-token-hint" class="oix-field-hint oix-field-help"><%:Token login does not require email and password%></span>
|
||||||
|
</div>
|
||||||
|
<button type="button" class="oix-btn oix-btn-primary oix-btn-block" onclick="OixCloud.doLogin()">
|
||||||
|
<svg class="oc-icon" width="14" height="14"><use href="#oc-icon-login"/></svg>
|
||||||
|
<%:Login Account%>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<div style="text-align:center;margin-top:12px;">
|
||||||
|
<button type="button" class="oix-btn oix-btn-ghost oix-btn-block" onclick="OixCloud.openWebsite();return false;">
|
||||||
|
<svg class="oc-icon" width="12" height="12"><use href="#oc-icon-home"/></svg>
|
||||||
|
<%:oixCloud Website%>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="oix-footer">
|
||||||
|
<span>Powered by <a href="javascript:void(0);" onclick="OixCloud.openWebsite();return false;">oixcloud.com</a></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="oix-logged-section" style="display:<%= logged_in and 'block' or 'none' %>;">
|
||||||
|
<div class="oix-header">
|
||||||
|
<div class="oix-header-left">
|
||||||
|
<span class="oix-status-badge">
|
||||||
|
<svg class="oc-icon" width="14" height="14"><use href="#oc-icon-badge"/></svg>
|
||||||
|
<span id="oix-header-plan">--</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="oix-header-right">
|
||||||
|
<button type="button" class="oix-btn oix-btn-primary oix-btn-sm" onclick="OixCloud.doCheckin();return false;">
|
||||||
|
<svg class="oc-icon" width="12" height="12"><use href="#oc-icon-gift"/></svg>
|
||||||
|
<%:Checkin%>
|
||||||
|
</button>
|
||||||
|
<button type="button" class="oix-btn oix-btn-ghost-subtle oix-btn-sm" onclick="OixCloud.openWebsite();return false;">
|
||||||
|
<img src="<%= oix_logo_src %>" width="14" height="14" style="border-radius:50%;vertical-align:middle" alt="oixCloud">
|
||||||
|
<%:oixCloud Website%>
|
||||||
|
</button>
|
||||||
|
<button type="button" class="oix-btn oix-btn-danger oix-btn-sm" onclick="OixCloud.doLogout();return false;">
|
||||||
|
<svg class="oc-icon" width="12" height="12"><use href="#oc-icon-logout"/></svg>
|
||||||
|
<%:Logout Account%>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="oix-announce" id="oix-announce">
|
||||||
|
<div class="oix-announce-header">
|
||||||
|
<svg class="oc-icon" width="14" height="14"><use href="#oc-icon-bell"/></svg>
|
||||||
|
<%:Announcement%>
|
||||||
|
</div>
|
||||||
|
<div class="oix-announce-body oix-collapsed" id="oix-announce-body"></div>
|
||||||
|
<div class="oix-announce-arrow" id="oix-announce-arrow" style="display:none;" onclick="OixCloud.toggleAnnounce();return false;">
|
||||||
|
<svg class="oc-icon" width="18" height="18" style="color:var(--primary-color)"><use href="#oc-icon-chevron-oix"/></svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="oix-cards" id="oix-cards">
|
||||||
|
<div class="oix-card">
|
||||||
|
<div class="oix-card-label"><%:Plan Expiration Time%></div>
|
||||||
|
<div class="oix-card-value" id="oix-plantime">--</div>
|
||||||
|
</div>
|
||||||
|
<div class="oix-card">
|
||||||
|
<div class="oix-card-label"><%:Account Integral%></div>
|
||||||
|
<div class="oix-card-value" id="oix-integral">--</div>
|
||||||
|
</div>
|
||||||
|
<div class="oix-card">
|
||||||
|
<div class="oix-card-label"><%:Aff Balances%></div>
|
||||||
|
<div class="oix-card-value" id="oix-affmoney">--</div>
|
||||||
|
</div>
|
||||||
|
<div class="oix-card">
|
||||||
|
<div class="oix-card-label"><%:Account Balances%></div>
|
||||||
|
<div class="oix-card-value" id="oix-money">--</div>
|
||||||
|
</div>
|
||||||
|
<div class="oix-card">
|
||||||
|
<div class="oix-card-label"><%:Plan Traffic%></div>
|
||||||
|
<div class="oix-card-value" id="oix-traffic">--</div>
|
||||||
|
</div>
|
||||||
|
<div class="oix-card">
|
||||||
|
<div class="oix-card-label"><%:Plan Unused%></div>
|
||||||
|
<div class="oix-card-value" id="oix-unused">--</div>
|
||||||
|
</div>
|
||||||
|
<div class="oix-card">
|
||||||
|
<div class="oix-card-label"><%:Plan Used%></div>
|
||||||
|
<div class="oix-card-value" id="oix-used">--</div>
|
||||||
|
</div>
|
||||||
|
<div class="oix-card">
|
||||||
|
<div class="oix-card-label"><%:Today Used%></div>
|
||||||
|
<div class="oix-card-value" id="oix-today-used">--</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="oix-settings-grid oix-settings-grid-4">
|
||||||
|
<div class="oix-setting-card">
|
||||||
|
<div class="oix-toggle-row">
|
||||||
|
<span><%:Show on Overview%></span>
|
||||||
|
<label class="oix-toggle" title="<%:Show on Overview%>">
|
||||||
|
<input type="checkbox" id="oix-show-info-page" onchange="OixCloud.toggleInfoPage()" <%= fs.uci_get_config('config', 'oix_show_info_page') ~= '0' and 'checked' or '' %>>
|
||||||
|
<span class="oix-toggle-slider"></span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="oix-card-help">
|
||||||
|
<svg class="oc-icon" width="10" height="10"><use href="#oc-icon-help"/></svg>
|
||||||
|
<span><%:Display account info on the main page%></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="oix-setting-card">
|
||||||
|
<div class="oix-toggle-row">
|
||||||
|
<span><%:Auto Checkin%></span>
|
||||||
|
<label class="oix-toggle" title="<%:Auto Checkin%>">
|
||||||
|
<input type="checkbox" id="oix-checkin-enable" onchange="OixCloud.toggleCheckin()" <%= checkin_enabled and 'checked' or '' %>>
|
||||||
|
<span class="oix-toggle-slider"></span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="oix-card-help">
|
||||||
|
<svg class="oc-icon" width="10" height="10"><use href="#oc-icon-help"/></svg>
|
||||||
|
<span><%:Auto check-in for traffic rewards and penalties%></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="oix-setting-card">
|
||||||
|
<div class="oix-params-item">
|
||||||
|
<span><%:Checkin Interval%> (<%:Hours%>):</span>
|
||||||
|
<input type="text" id="oix-checkin-interval" size="3" value="<%= checkin_interval %>" onblur="OixCloud.saveCheckin()" class="oix-input-num oix-input-ok">
|
||||||
|
</div>
|
||||||
|
<div class="oix-card-help">
|
||||||
|
<svg class="oc-icon" width="10" height="10"><use href="#oc-icon-help"/></svg>
|
||||||
|
<span><%:Checkin interval must be between 1 and 720%></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="oix-setting-card">
|
||||||
|
<div class="oix-params-item">
|
||||||
|
<span><%:Checkin Multiple%>:</span>
|
||||||
|
<input type="text" id="oix-checkin-multiple" size="3" value="<%= checkin_multiple %>" onblur="OixCloud.saveCheckin()" oninput="OixCloud.validateMultiple(this)" class="oix-input-num oix-input-ok">
|
||||||
|
</div>
|
||||||
|
<div class="oix-card-help">
|
||||||
|
<svg class="oc-icon" width="10" height="10"><use href="#oc-icon-help"/></svg>
|
||||||
|
<span><%:Multiple Must Be a Positive Integer and No More Than 100%></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="oix-settings-grid">
|
||||||
|
<div class="oix-setting-card" style="grid-column: span 2;">
|
||||||
|
<div class="oix-params-item">
|
||||||
|
<span><%:Optional Parameters%>:</span>
|
||||||
|
<input type="text" id="oix-params" style="min-width:140px;" value="<%= oix_params %>" onblur="OixCloud.saveParams()" oninput="OixCloud.validateParams(this)" class="oix-input-num oix-input-ok" placeholder="&type=love&tfo=false&area=hk">
|
||||||
|
</div>
|
||||||
|
<div class="oix-card-help">
|
||||||
|
<svg class="oc-icon" width="12" height="12"><use href="#oc-icon-help"/></svg>
|
||||||
|
<span><%:For more information, please visit the%> <a href="https://docs.dler.io/black-hole/advanced/ding-yue-di-zhi-tuo-guan-di-zhi/untitled" target="_blank"><%:official documentation%></a></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="oix-footer">
|
||||||
|
<span>Powered by <a href="javascript:void(0);" onclick="OixCloud.openWebsite();return false;">oixcloud.com</a></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
</div>
|
||||||
|
|
||||||
<script type="text/javascript">//<![CDATA[
|
<script type="text/javascript">//<![CDATA[
|
||||||
function oix_login(btn,option)
|
var OIX_URLS = {
|
||||||
{
|
info: '<%=luci.dispatcher.build_url("admin", "services", "openclash", "oix_info")%>',
|
||||||
btn.disabled = true;
|
login: '<%=luci.dispatcher.build_url("admin", "services", "openclash", "oix_login")%>',
|
||||||
if (option == "oix_login") {
|
logout: '<%=luci.dispatcher.build_url("admin", "services", "openclash", "oix_logout")%>',
|
||||||
var s = document.getElementById(option+'-status');
|
save: '<%=luci.dispatcher.build_url("admin", "services", "openclash", "oix_login_info_save")%>',
|
||||||
var e = document.getElementsByName('cbid.openclash.config.oix_email');
|
checkin: '<%=luci.dispatcher.build_url("admin", "services", "openclash", "oix_checkin")%>',
|
||||||
var p = document.getElementsByName('cbid.openclash.config.oix_passwd');
|
params: '<%=luci.dispatcher.build_url("admin", "services", "openclash", "oix_params_sync")%>',
|
||||||
var c = document.getElementsByName('cbid.openclash.config.oix_checkin');
|
paramsGet: '<%=luci.dispatcher.build_url("admin", "services", "openclash", "oix_params_get")%>'
|
||||||
if (!e[0].value || !p[0].value) {
|
|
||||||
btn.disabled = false;
|
|
||||||
s.innerHTML ="<font color='red'><strong>"+"<%:Error Login Info%>"+"</strong></font>";
|
|
||||||
return false;
|
|
||||||
};
|
};
|
||||||
if (c[0] && c[0].checked) {
|
|
||||||
c = "1";
|
var OixCloud = {
|
||||||
var i = document.getElementsByName('cbid.openclash.config.oix_checkin_interval');
|
loggedIn: <%= logged_in and 'true' or 'false' %>,
|
||||||
var m = document.getElementsByName('cbid.openclash.config.oix_checkin_multiple');
|
_activeTab: 'account',
|
||||||
if (!i[0].value || !(/(^[1-9]\d*$)/.test(i[0].value))) { i = "1"} else {i = i[0].value};
|
_pollTimer: null,
|
||||||
if (!m[0].value || !(/(^[1-9]\d*$)/.test(m[0].value)))
|
_paramsRetry: 0,
|
||||||
{
|
_paramsMaxRetry: 30,
|
||||||
btn.disabled = false;
|
_paramsRetryTimer: null,
|
||||||
s.innerHTML ="<font color='red'><strong>"+"<%:Multiple Must Be a Positive Integer and No More Than 100%>"+"</strong></font>";
|
|
||||||
return false;
|
init: function() {
|
||||||
|
if (this.loggedIn) { this.loadAccountInfo(); this.startPolling(); this.fetchParams(); }
|
||||||
|
},
|
||||||
|
|
||||||
|
fetchParams: function() {
|
||||||
|
var input = document.getElementById('oix-params');
|
||||||
|
if (!input || input.value !== '') return;
|
||||||
|
var self = this;
|
||||||
|
XHR.get(OIX_URLS.paramsGet, null, function(x, status) {
|
||||||
|
if (x && x.status == 200 && status && status.params) {
|
||||||
|
input.value = status.params;
|
||||||
|
self._paramsRetry = 0;
|
||||||
|
if (status.default_params) {
|
||||||
|
XHR.get(OIX_URLS.save, {default_params: status.default_params}, function() {});
|
||||||
}
|
}
|
||||||
else if (m[0].value < 1)
|
} else {
|
||||||
{
|
if (self._paramsRetry < self._paramsMaxRetry) {
|
||||||
btn.disabled = false;
|
self._paramsRetry++;
|
||||||
s.innerHTML ="<font color='red'><strong>"+"<%:Multiple Must Be a Positive Integer and No More Than 100%>"+"</strong></font>";
|
self._paramsRetryTimer = setTimeout(function() { self.fetchParams(); }, 5000);
|
||||||
return false;
|
} else {
|
||||||
|
var cached = '<%= oix_default_params %>';
|
||||||
|
if (cached) { input.value = cached; input.placeholder = cached; }
|
||||||
}
|
}
|
||||||
else if (m[0].value > 100)
|
|
||||||
{
|
|
||||||
btn.disabled = false;
|
|
||||||
s.innerHTML ="<font color='red'><strong>"+"<%:Multiple Must Be a Positive Integer and No More Than 100%>"+"</strong></font>";
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
else {
|
});
|
||||||
m = m[0].value;
|
},
|
||||||
|
|
||||||
|
switchTab: function(tab) {
|
||||||
|
this._activeTab = tab;
|
||||||
|
document.getElementById('oix-tab-account').classList.toggle('active', tab === 'account');
|
||||||
|
document.getElementById('oix-tab-token').classList.toggle('active', tab === 'token');
|
||||||
|
document.getElementById('oix-panel-account').style.display = tab === 'account' ? 'block' : 'none';
|
||||||
|
document.getElementById('oix-panel-token').style.display = tab === 'token' ? 'block' : 'none';
|
||||||
|
OixMsg.clearAll();
|
||||||
|
},
|
||||||
|
|
||||||
|
doLogin: function() {
|
||||||
|
OixMsg.clearAll();
|
||||||
|
var isToken = this._activeTab === 'token', data = {};
|
||||||
|
if (isToken) {
|
||||||
|
var token = document.getElementById('oix-token').value.trim();
|
||||||
|
if (!token) { OixMsg.field('oix-token', '<%:Please enter a valid token%>'); return; }
|
||||||
|
data.token = token;
|
||||||
|
} else {
|
||||||
|
var email = document.getElementById('oix-email').value.trim();
|
||||||
|
var passwd = document.getElementById('oix-passwd').value.trim();
|
||||||
|
if (!email) { OixMsg.field('oix-email', '<%:Please enter email address%>'); return; }
|
||||||
|
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) { OixMsg.field('oix-email', '<%:Please enter a valid email address%>'); return; }
|
||||||
|
if (!passwd) { OixMsg.field('oix-passwd', '<%:Please enter password%>'); return; }
|
||||||
|
data.email = email; data.passwd = passwd;
|
||||||
|
}
|
||||||
|
data.checkin = document.getElementById('oix-checkin-enable').checked ? '1' : '0'; data.interval = document.getElementById('oix-checkin-interval').value || '1'; data.multiple = document.getElementById('oix-checkin-multiple').value || '1';
|
||||||
|
var self = this, btns = document.querySelectorAll('#oix-login-section .oix-btn-primary');
|
||||||
|
btns.forEach(function(b){ b._origHTML = b.innerHTML; b.disabled = true; var svg = b.querySelector('svg'); b.innerHTML = (svg ? svg.outerHTML : '') + ' <%:Login...%>'; });
|
||||||
|
XHR.get(OIX_URLS.save, data, function(x, status) {
|
||||||
|
if (!x || x.status != 200) { OixMsg.show('<%:Network request failed, please check your connection and try again%>', 'error'); btns.forEach(function(b){b.disabled=false;b.innerHTML=b._origHTML;}); return; }
|
||||||
|
|
||||||
|
var onLoginSuccess = function() {
|
||||||
|
var info = '<%:oixCloud Login Successful%>' + ', <%:Note: oixCloud need a specific core installed, OpenClash will auto download, After the core start, an oixCloud nodes provider will be added, which you can customize as needed%>';
|
||||||
|
OixMsg.show(info, 'success', 20000);
|
||||||
|
self.loggedIn = true; self.showLoggedIn(); self.loadAccountInfo(); self.startPolling();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (isToken) {
|
||||||
|
XHR.get(OIX_URLS.login, {token: data.token}, function(x2, s2) {
|
||||||
|
btns.forEach(function(b){ b.disabled = false; b.innerHTML = b._origHTML; });
|
||||||
|
if (x2 && x2.status == 200 && s2.result == 200) {
|
||||||
|
onLoginSuccess();
|
||||||
|
} else {
|
||||||
|
var msg = (s2 && s2.result) ? s2.result : '<%:oixCloud Login Failed%>';
|
||||||
|
OixMsg.show('<%:oixCloud Login Failed:%> ' + msg, 'error');
|
||||||
}
|
}
|
||||||
else {
|
});
|
||||||
c = "0";
|
} else {
|
||||||
var i = "1";
|
XHR.get(OIX_URLS.login, null, function(x2, s2) {
|
||||||
var m = "1";
|
btns.forEach(function(b){ b.disabled = false; b.innerHTML = b._origHTML; });
|
||||||
};
|
if (x2 && x2.status == 200 && s2.result == 200) {
|
||||||
btn.value = '<%:Login...%>';
|
onLoginSuccess();
|
||||||
XHR.get('<%=luci.dispatcher.build_url("admin", "services", "openclash", "oix_login_info_save")%>', {email: e[0].value, passwd : p[0].value, checkin: c, interval: i, multiple: m}, function(x, status) {
|
} else {
|
||||||
if (x && x.status == 200) {
|
var msg = (s2 && s2.result) ? s2.result : '<%:oixCloud Login Failed%>';
|
||||||
XHR.get('<%=luci.dispatcher.build_url("admin", "services", "openclash", "oix_login")%>', null, function(x, status) {
|
OixMsg.show('<%:oixCloud Login Failed:%> ' + msg, 'error');
|
||||||
if (s)
|
|
||||||
{
|
|
||||||
if (x && x.status == 200 && status.result == 200) {
|
|
||||||
s.innerHTML ="<font color='green'><strong>"+"<%:oixCloud Login Successful%>"+"</strong></font>";
|
|
||||||
alert("<%:Note: oixCloud need a specific core installed, OpenClash will auto download%>\n\n<%:After the core start, an oixCloud nodes provider will be added, which you can customize as needed%>");
|
|
||||||
window.location.href='<%="settings?tab.openclash.config=oixcloud"%>';
|
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
s.innerHTML ="<font color='red'><strong>"+"<%:oixCloud Login Faild%>"+"</strong></font>";
|
|
||||||
if (status.result) {
|
|
||||||
alert("<%:oixCloud Login Faild%>: " + status.result)
|
|
||||||
}
|
|
||||||
window.location.href='<%="settings?tab.openclash.config=oixcloud"%>';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
btn.disabled = false;
|
|
||||||
btn.value = '<%:Login Account%>';
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
},
|
||||||
|
|
||||||
if (option == "oix_logout") {
|
doLogout: function() {
|
||||||
var s = document.getElementById('oix_login-status');
|
var self = this;
|
||||||
btn.value = '<%:Logout...%>';
|
var btn = document.querySelector('#oix-logged-section .oix-btn-danger');
|
||||||
XHR.get('<%=luci.dispatcher.build_url("admin", "services", "openclash", "oix_logout")%>', null, function(x, status) {
|
if (btn) { btn._origHTML = btn.innerHTML; btn.disabled = true; var svg = btn.querySelector('svg'); btn.innerHTML = (svg ? svg.outerHTML : '') + ' <%:Logout...%>'; }
|
||||||
if (s)
|
XHR.get(OIX_URLS.logout, null, function(x, status) {
|
||||||
{
|
if (btn) { btn.disabled = false; btn.innerHTML = btn._origHTML; }
|
||||||
if (x && x.status == 200 && status.result == 200) {
|
if (x && x.status == 200 && status.result == 200) {
|
||||||
s.innerHTML ="<font color='green'><strong>"+"<%:oixCloud Logout Successful%>"+"</strong></font>";
|
OixMsg.show('<%:oixCloud Logout Successful%>', 'success', 2000);
|
||||||
window.location.href='<%="settings?tab.openclash.config=oixcloud"%>';
|
self.loggedIn = false; self.stopPolling(); self.showLoggedOut();
|
||||||
}
|
} else {
|
||||||
else {
|
var msg = (status && status.result) ? status.result : '<%:oixCloud Logout Failed%>';
|
||||||
s.innerHTML ="<font color='red'><strong>"+"<%:oixCloud Logout Faild%>"+"</strong></font>";
|
OixMsg.show('<%:oixCloud Logout Failed:%> ' + msg, 'error');
|
||||||
if (status.result) {
|
|
||||||
alert("<%:oixCloud Logout Faild%>: " + status.result)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
btn.disabled = false;
|
|
||||||
btn.value = '<%:Logout Account%>';
|
|
||||||
}
|
|
||||||
);
|
|
||||||
};
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
function web_oix(btn)
|
showLoggedIn: function() {
|
||||||
{
|
document.getElementById('oix-login-section').style.display = 'none';
|
||||||
btn.disabled = true;
|
document.getElementById('oix-logged-section').style.display = 'block';
|
||||||
url='http://bit.ly/oixcloud-register';
|
},
|
||||||
window.open(url);
|
|
||||||
btn.disabled = false;
|
showLoggedOut: function() {
|
||||||
return false;
|
document.getElementById('oix-login-section').style.display = 'block';
|
||||||
|
document.getElementById('oix-logged-section').style.display = 'none';
|
||||||
|
this.stopParamsRetry();
|
||||||
|
this.switchTab('account');
|
||||||
|
},
|
||||||
|
|
||||||
|
clearForm: function() {
|
||||||
|
document.getElementById('oix-email').value = '';
|
||||||
|
document.getElementById('oix-passwd').value = '';
|
||||||
|
document.getElementById('oix-token').value = '';
|
||||||
|
document.getElementById('oix-checkin-enable').checked = false;
|
||||||
|
document.getElementById('oix-checkin-interval').value = '1';
|
||||||
|
document.getElementById('oix-checkin-multiple').value = '1';
|
||||||
|
document.getElementById('oix-params').value = '';
|
||||||
|
},
|
||||||
|
|
||||||
|
loadAccountInfo: function() {
|
||||||
|
var self = this;
|
||||||
|
XHR.get(OIX_URLS.info, null, function(x, status) {
|
||||||
|
if (x && x.status == 200 && status.result && typeof status.result === 'object') {
|
||||||
|
self.renderAccountInfo(status.result);
|
||||||
|
self.renderAnnouncement(status.result);
|
||||||
|
} else {
|
||||||
|
var cards = document.getElementById('oix-cards');
|
||||||
|
if (cards) cards.style.display = 'none';
|
||||||
|
var ann = document.getElementById('oix-announce');
|
||||||
|
if (ann) ann.style.display = 'none';
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
renderAnnouncement: function(result) {
|
||||||
|
if (result.announcement && result.announcement.content) {
|
||||||
|
var el = document.getElementById('oix-announce');
|
||||||
|
var body = document.getElementById('oix-announce-body');
|
||||||
|
var arrow = document.getElementById('oix-announce-arrow');
|
||||||
|
if (el && body) {
|
||||||
|
el.style.display = 'block';
|
||||||
|
body.innerHTML = '<strong>' + (result.announcement.date || '') + ': </strong>' + result.announcement.content;
|
||||||
|
body.classList.remove('oix-collapsed');
|
||||||
|
var ref = document.getElementById('oix-cards');
|
||||||
|
var measureContent = function() {
|
||||||
|
if (!ref || ref.offsetWidth === 0) return;
|
||||||
|
var cs = getComputedStyle(body);
|
||||||
|
var fontSize = parseFloat(cs.fontSize) || 12;
|
||||||
|
var maxH = fontSize * 5.6;
|
||||||
|
var measure = document.createElement('div');
|
||||||
|
measure.style.font = cs.font;
|
||||||
|
measure.style.lineHeight = cs.lineHeight;
|
||||||
|
measure.style.wordBreak = cs.wordBreak;
|
||||||
|
measure.style.width = ref.offsetWidth + 'px';
|
||||||
|
measure.style.position = 'absolute';
|
||||||
|
measure.style.visibility = 'hidden';
|
||||||
|
measure.innerHTML = (result.announcement.date || '') + ': ' + result.announcement.content;
|
||||||
|
ref.parentElement.appendChild(measure);
|
||||||
|
var fullH = measure.scrollHeight;
|
||||||
|
ref.parentElement.removeChild(measure);
|
||||||
|
if (fullH > maxH + 4) {
|
||||||
|
body.classList.add('oix-collapsed');
|
||||||
|
if (arrow) arrow.style.display = 'flex';
|
||||||
|
} else {
|
||||||
|
if (arrow) arrow.style.display = 'none';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (ref && ref.offsetWidth > 0) {
|
||||||
|
measureContent();
|
||||||
|
} else {
|
||||||
|
var tabContainer = document.getElementById('tab.openclash.config.oixcloud');
|
||||||
|
var observer = new MutationObserver(function() {
|
||||||
|
if (ref && ref.offsetWidth > 0) {
|
||||||
|
observer.disconnect();
|
||||||
|
measureContent();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
observer.observe(tabContainer, { attributes: true, attributeFilter: ['style', 'class'] });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var el2 = document.getElementById('oix-announce');
|
||||||
|
if (el2) el2.style.display = 'none';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
renderAccountInfo: function(d) {
|
||||||
|
document.getElementById('oix-header-plan').textContent = d.plan || '--';
|
||||||
|
document.getElementById('oix-affmoney').textContent = d.aff_money || '--';
|
||||||
|
document.getElementById('oix-plantime').textContent = d.plan_time || '--';
|
||||||
|
document.getElementById('oix-money').textContent = d.money || '--';
|
||||||
|
document.getElementById('oix-integral').textContent = d.integral || '--';
|
||||||
|
document.getElementById('oix-traffic').textContent = d.traffic || '--';
|
||||||
|
document.getElementById('oix-used').textContent = d.used || '--';
|
||||||
|
document.getElementById('oix-unused').textContent = d.unused || '--';
|
||||||
|
document.getElementById('oix-today-used').textContent = d.today_used || '--';
|
||||||
|
},
|
||||||
|
|
||||||
|
toggleInfoPage: function() {
|
||||||
|
var on = document.getElementById('oix-show-info-page').checked;
|
||||||
|
XHR.get(OIX_URLS.save, {show_info_page: on?'1':'0'}, function(x, status) {
|
||||||
|
if (x && x.status == 200) { OixMsg.show('<%:Setting saved%>', 'success', 2000); }
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
startPolling: function() { this.stopPolling(); var s=this; this._pollTimer=setInterval(function(){s.loadAccountInfo();},1800000); },
|
||||||
|
stopPolling: function() { if(this._pollTimer){clearInterval(this._pollTimer);this._pollTimer=null;} },
|
||||||
|
stopParamsRetry: function() { if(this._paramsRetryTimer){clearTimeout(this._paramsRetryTimer);this._paramsRetryTimer=null;} this._paramsRetry = 0; },
|
||||||
|
|
||||||
|
doCheckin: function() {
|
||||||
|
var self = this;
|
||||||
|
var btn = document.querySelector('#oix-logged-section .oix-btn-primary');
|
||||||
|
if (btn) { btn._origHTML = btn.innerHTML; btn.disabled = true; var svg = btn.querySelector('svg'); btn.innerHTML = (svg ? svg.outerHTML : '') + ' <%:Checkin...%>'; }
|
||||||
|
XHR.get(OIX_URLS.checkin, null, function(x, status) {
|
||||||
|
if (btn) { btn.disabled = false; btn.innerHTML = btn._origHTML; }
|
||||||
|
if (x && x.status == 200 && status.result && status.result.ret == 200) {
|
||||||
|
OixMsg.show('<%:oixCloud Checkin Successful, Result:%> ' + (status.result.data && status.result.data.checkin || ''), 'success', 4000);
|
||||||
|
self.loadAccountInfo();
|
||||||
|
} else {
|
||||||
|
var msg = (status.result && status.result.msg) ? status.result.msg : '<%:oixCloud Checkin Failed! Please Check And Try Again...%>';
|
||||||
|
OixMsg.show('<%:Checkin Failed:%> ' + msg, 'error');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
toggleCheckin: function() {
|
||||||
|
var on = document.getElementById('oix-checkin-enable').checked;
|
||||||
|
XHR.get(OIX_URLS.save, {checkin: on?'1':'0'}, function(x, status) {
|
||||||
|
if (x && x.status == 200) { OixMsg.show('<%:Setting saved%>', 'success', 2000); }
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
saveCheckin: function() {
|
||||||
|
OixMsg.clearAll();
|
||||||
|
var on = document.getElementById('oix-checkin-enable').checked;
|
||||||
|
var interval = parseInt(document.getElementById('oix-checkin-interval').value, 10);
|
||||||
|
var multiple = parseInt(document.getElementById('oix-checkin-multiple').value, 10);
|
||||||
|
var valid = true;
|
||||||
|
if (isNaN(interval) || interval < 1 || interval > 720) { OixMsg.field('oix-checkin-interval', '<%:Checkin interval must be between 1 and 720%>'); OixMsg.show('<%:Checkin interval must be between 1 and 720%>', 'error'); valid = false; }
|
||||||
|
if (isNaN(multiple) || multiple < 1 || multiple > 100) { OixMsg.field('oix-checkin-multiple', '<%:Multiple Must Be a Positive Integer and No More Than 100%>'); OixMsg.show('<%:Multiple Must Be a Positive Integer and No More Than 100%>', 'error'); valid = false; }
|
||||||
|
if (!valid) return;
|
||||||
|
XHR.get(OIX_URLS.save, {checkin: on?'1':'0', interval: String(isNaN(interval)?1:interval), multiple: String(isNaN(multiple)?1:multiple)}, function(x, status) {
|
||||||
|
if (x && x.status == 200) { OixMsg.show('<%:Checkin settings saved%>', 'success', 4000); }
|
||||||
|
else { OixMsg.show('<%:Failed to save checkin settings, please try again%>', 'error'); }
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
saveParams: function() {
|
||||||
|
OixMsg.clearAll();
|
||||||
|
var params = document.getElementById('oix-params').value.trim();
|
||||||
|
if (params !== '' && !params.match(/^&[a-zA-Z][a-zA-Z0-9-]*(=[^&\s]*)?(&[a-zA-Z][a-zA-Z0-9-]*(=[^&\s]*)?)*$/)) {
|
||||||
|
OixMsg.field('oix-params', '<%:Invalid params format, must start with & and use key=value pairs%>');
|
||||||
|
OixMsg.show('<%:Invalid params format%>', 'error');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (params.length > 8192) {
|
||||||
|
OixMsg.field('oix-params', '<%:Params too long, max 8192 characters%>');
|
||||||
|
OixMsg.show('<%:Params too long%>', 'error');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
XHR.get(OIX_URLS.params, {params: params}, function(x, status) {
|
||||||
|
if (x && x.status == 200) { OixMsg.show('<%:Optional parameters saved%>', 'success', 4000); }
|
||||||
|
else { OixMsg.show('<%:Failed to save optional parameters, please try again%>', 'error'); }
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
validateParams: function(inp) {
|
||||||
|
if (!inp) return;
|
||||||
|
var v = inp.value.trim();
|
||||||
|
if (v === '') { OixMsg.field('oix-params', ''); return; }
|
||||||
|
if (!v.startsWith('&')) {
|
||||||
|
OixMsg.field('oix-params', '<%:Must start with &%>');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (/\s/.test(v)) {
|
||||||
|
OixMsg.field('oix-params', '<%:Params must not contain spaces%>');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (v.length > 8192) {
|
||||||
|
OixMsg.field('oix-params', '<%:Params too long, max 8192 characters%>');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!v.match(/^&[a-zA-Z][a-zA-Z0-9-]*(=[^&\s]*)?(&[a-zA-Z][a-zA-Z0-9-]*(=[^&\s]*)?)*$/)) {
|
||||||
|
OixMsg.field('oix-params', '<%:Invalid params format, must start with & and use key=value pairs%>');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
OixMsg.field('oix-params', '');
|
||||||
|
},
|
||||||
|
|
||||||
|
validateMultiple: function(inp) {
|
||||||
|
if (!inp) return;
|
||||||
|
var v = inp.value.trim();
|
||||||
|
if (v === '') { OixMsg.field('oix-checkin-multiple', ''); return; }
|
||||||
|
var n = parseInt(v, 10);
|
||||||
|
if (isNaN(n) || n < 1 || n > 100 || String(n) !== v) {
|
||||||
|
OixMsg.field('oix-checkin-multiple', '<%:Multiple Must Be a Positive Integer and No More Than 100%>');
|
||||||
|
OixMsg.show('<%:Multiple Must Be a Positive Integer and No More Than 100%>', 'error');
|
||||||
|
} else {
|
||||||
|
OixMsg.field('oix-checkin-multiple', '');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
togglePwd: function(id) {
|
||||||
|
var inp = document.getElementById(id);
|
||||||
|
if (!inp) return;
|
||||||
|
var isPwd = inp.type === 'password';
|
||||||
|
inp.type = isPwd ? 'text' : 'password';
|
||||||
|
var icon = inp.parentNode.querySelector('svg');
|
||||||
|
if (icon) {
|
||||||
|
icon.innerHTML = isPwd
|
||||||
|
? '<use href="#oc-icon-eye-off"/>'
|
||||||
|
: '<use href="#oc-icon-eye"/>';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
toggleAnnounce: function() {
|
||||||
|
var body = document.getElementById('oix-announce-body');
|
||||||
|
var arrow = document.getElementById('oix-announce-arrow');
|
||||||
|
if (!body) return;
|
||||||
|
if (body.classList.contains('oix-collapsed')) {
|
||||||
|
body.classList.remove('oix-collapsed');
|
||||||
|
if (arrow) arrow.style.transform = 'rotate(180deg)';
|
||||||
|
} else {
|
||||||
|
body.classList.add('oix-collapsed');
|
||||||
|
if (arrow) arrow.style.transform = 'rotate(0deg)';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
openWebsite: function() {
|
||||||
|
window.open('http://bit.ly/oixcloud-register');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var OixMsg = {
|
||||||
|
_timer: null,
|
||||||
|
show: function(msg, level, timeout) {
|
||||||
|
var bar = document.getElementById('oix-msg-bar');
|
||||||
|
var icons = {
|
||||||
|
success: '<svg width="15" height="15"><use href="#oc-icon-success"/></svg>',
|
||||||
|
error: '<svg width="15" height="15"><use href="#oc-icon-error"/></svg>',
|
||||||
|
info: '<svg width="15" height="15"><use href="#oc-icon-info"/></svg>'
|
||||||
|
};
|
||||||
|
bar.style.display = 'flex'; bar.innerHTML = (icons[level] || icons.info) + '<span>' + msg + '</span>';
|
||||||
|
bar.className = 'oix-msg-bar oix-msg-' + (level || 'info');
|
||||||
|
clearTimeout(this._timer);
|
||||||
|
var t = (timeout !== undefined) ? timeout : (level === 'error' ? 6000 : 3000);
|
||||||
|
if (t > 0) { var s=this; this._timer=setTimeout(function(){s.hide();},t); }
|
||||||
|
},
|
||||||
|
hide: function() { document.getElementById('oix-msg-bar').style.display = 'none'; },
|
||||||
|
field: function(id, msg) {
|
||||||
|
var hint = document.getElementById(id + '-hint'), inp = document.getElementById(id);
|
||||||
|
if (hint) { hint.textContent = msg || ''; hint.className = msg ? 'oix-field-hint oix-field-error' : 'oix-field-hint oix-field-help'; }
|
||||||
|
if (inp) {
|
||||||
|
var isNum = id === 'oix-checkin-interval' || id === 'oix-checkin-multiple' || id === 'oix-params';
|
||||||
|
var base = isNum ? 'oix-input-num' : 'oix-input';
|
||||||
|
inp.className = msg ? (base + ' oix-input-err') : (base + ' oix-input-ok');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
clearAll: function() {
|
||||||
|
this.hide();
|
||||||
|
['oix-email','oix-passwd','oix-token'].forEach(function(id) {
|
||||||
|
var hint = document.getElementById(id + '-hint'), inp = document.getElementById(id);
|
||||||
|
if (hint) { hint.textContent = ''; hint.className = 'oix-field-hint oix-field-help'; }
|
||||||
|
if (inp) { inp.className = 'oix-input oix-input-ok'; }
|
||||||
|
});
|
||||||
|
['oix-checkin-interval','oix-checkin-multiple'].forEach(function(id) {
|
||||||
|
var hint = document.getElementById(id + '-hint'), inp = document.getElementById(id);
|
||||||
|
if (hint) { hint.textContent = ''; hint.className = 'oix-field-hint oix-field-help'; }
|
||||||
|
if (inp) { inp.className = 'oix-input-num oix-input-ok'; }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', function() { OixCloud.init(); });
|
||||||
//]]></script>
|
//]]></script>
|
||||||
<input type="button" class="btn cbi-button cbi-button-apply" value="<%:Login Account%>" onclick="return oix_login(this,'oix_login')" />
|
|
||||||
<input type="button" class="btn cbi-button cbi-button-remove" value="<%:Logout Account%>" onclick="return oix_login(this,'oix_logout')" />
|
|
||||||
<input type="button" class="btn cbi-button cbi-button-reset" value="<%:Official Website%>" onclick="return web_oix(this)" />
|
|
||||||
<span id="<%=self.option%>-status"><%=self.value%></span>
|
|
||||||
<%+cbi/valuefooter%>
|
|
||||||
@@ -3,6 +3,11 @@
|
|||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no,minimal-ui">
|
<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no,minimal-ui">
|
||||||
|
<%
|
||||||
|
local fs = require "luci.openclash"
|
||||||
|
local plugin_version = fs.oc_version()
|
||||||
|
%>
|
||||||
|
<script src="/luci-static/resources/openclash/js/oc-icons.js?v=<%=plugin_version%>"></script>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
@@ -15,7 +20,7 @@
|
|||||||
<div id="additional" class="additional">
|
<div id="additional" class="additional">
|
||||||
<div class="user-card">
|
<div class="user-card">
|
||||||
<div class="img">
|
<div class="img">
|
||||||
<img id="oix_logo" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAYAAAErdZjwAAAACXBIWXMAAAsTAAALEwEAmpwYAAAGsGlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDggNzkuMTY0MDM2LCAyMDE5LzA4LzEzLTAxOjA2OjU3ICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgMjEuMCAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDI2LTA2LTExVDAwOjU0OjU4KzA4OjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAyNi0wNi0xMVQyMzoyNjowNyswODowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAyNi0wNi0xMVQyMzoyNjowNyswODowMCIgZGM6Zm9ybWF0PSJpbWFnZS9wbmciIHBob3Rvc2hvcDpDb2xvck1vZGU9IjMiIHBob3Rvc2hvcDpJQ0NQcm9maWxlPSJzUkdCIElFQzYxOTY2LTIuMSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo0ZjA3Mjk4Yi03M2E1LTcxNDItODE2MS03ZTkyNDlmMGU0ODkiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OGM3YzA4NjMtYzdlOS0yYzQ1LTk1ODYtNDgxZjMxYzM0MmFjIiB4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ9InhtcC5kaWQ6OGM3YzA4NjMtYzdlOS0yYzQ1LTk1ODYtNDgxZjMxYzM0MmFjIj4gPHhtcE1NOkhpc3Rvcnk+IDxyZGY6U2VxPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0iY3JlYXRlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDo4YzdjMDg2My1jN2U5LTJjNDUtOTU4Ni00ODFmMzFjMzQyYWMiIHN0RXZ0OndoZW49IjIwMjYtMDYtMTFUMDA6NTQ6NTgrMDg6MDAiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCAyMS4wIChXaW5kb3dzKSIvPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0ic2F2ZWQiIHN0RXZ0Omluc3RhbmNlSUQ9InhtcC5paWQ6MTg5NzBjODctZDk2My1iMjRiLWJlNDEtOTkyMTE5MjhhNDIxIiBzdEV2dDp3aGVuPSIyMDI2LTA2LTExVDIzOjE0OjA5KzA4OjAwIiBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgMjEuMCAoV2luZG93cykiIHN0RXZ0OmNoYW5nZWQ9Ii8iLz4gPHJkZjpsaSBzdEV2dDphY3Rpb249InNhdmVkIiBzdEV2dDppbnN0YW5jZUlEPSJ4bXAuaWlkOjRmMDcyOThiLTczYTUtNzE0Mi04MTYxLTdlOTI0OWYwZTQ4OSIgc3RFdnQ6d2hlbj0iMjAyNi0wNi0xMVQyMzoyNjowNyswODowMCIgc3RFdnQ6c29mdHdhcmVBZ2VudD0iQWRvYmUgUGhvdG9zaG9wIDIxLjAgKFdpbmRvd3MpIiBzdEV2dDpjaGFuZ2VkPSIvIi8+IDwvcmRmOlNlcT4gPC94bXBNTTpIaXN0b3J5PiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PiagcG0AADMvSURBVHic7b15eFRFvv9fZ+k1ne7ORgJZiJCYgAiB4A2LgoiExFxQQGE0qHAFGUTmjtfx6zA+M+pzdWYckDs6A+IMaxBBARUN66i4BBwRAhIWQyAQCNl77z591qrfHwK/EDrpTm8nyanX85xHn3BO16eq3vU5tXxOFYEQQkBGSDkTxwZgA7ABIRuwYcMGx9ChQ0OzAAXJrFmzLAAAdP0KFiJYT0gQRMeMBFUAQVWBWq0Om/vutgFut1sSBOGm7J87d84ZrAHdroKORU8QBIAQBpt+90pg8+bN7o5/EwQBAvBztRAEASiK6p4F3VEsaKd6AABKSkriEELov//7v5vb//33v/+9GPBvBnrj4cOHbzGgM8NWrlzJhd2AtrY2tn0ir776qhshhBITE4XODAurAQghtHjxYicAABUWFrI3fqBD4idOnPB25zcDagWSJPkUV8cWcU1TAAAARFGEFEWRvu5pj99WQBAEoGkaEAQBDh8+fKO9V1RUsD4MhdefUalUJEmS4Ouvv+7SR/gtgc5cbse/m0wm0W63010944tu+YGZM2e6rv//lClTbsrZ9cQ7Mn36dJevv7e3rkskSYJmsxn97ne/c3T8t6VLlzrNZvMtz0AIodlsRr/97W+tYRFhJOndPSJsADagTxiA/QA2ABuADQjaAIQQuuOOO8BLL71kD8kCfz2WzgDtuuJPP/006/+JTn4nmIcGDRrEgRAGI+3pdhUghEBtba26/d/WrVvHBVsD3X4XkCR5Sze7mz9x8+915+a6ujp3x8QEQQjtZdad+gId6p2maYgQQlVVVc7rfzt06JDfrvhNvxnojQsXLmzraEBnhkXEgI6JPPjggyxCCA0ePJiVxYDO/v7uu+92qwoCbgUIIUDTNEAIAZ7nEU3TRDhaRECtgGVZiSAIIEkSgBACmqaJ5uZmrmNiDofjxnSZ1+sVA7Kgq+L55ptvbvJ4XVWJTqcTEULo2LFjfGfPdLsKOhZx+/8PdN7AX5V0WQX33ntvQDOgEyZMuDFbMnXqVEcgz9zAXxEtWbLE5xyAJEkwISEBvfTSS7eofsmSJTaz2YwghDCkKogGvbdHhA3ABvQZA2T3A3Ijew3IDS4AuQ2QG1wAchsgN7gA5DZAbmQpAL1ejwiCAO2vtLQ0IZQQkGCJakfo6tWrXFpamqare6LdL4uaAo4cOeLyl3mdTidFy57rRKUA/t//+3/WgoKC2K7uiY+PlzweTzcjj8KAv0mDUCkqKrpl7rDjdccddwiRtqMzIloA8fHxt8Q1dbyWLl1q6/jc5s2b68eNG4fWrFlzNZL2IRShAhBFEarVaugv8xUVFTcWdyCEUKvVdvqMKIpSJGwNewGwLCv6yzgAAF29evVG5j0ej99nZs+ebQ+3rQhFoAAOHjzYpewJgrjp/mPHjjH+Mt/xmXASkSYwYsQIt6+MJCcn8+3ve/vttxv8ZT4pKYnvLJ1wEFEnKIoidDgckOf5W0JaZ86c6fftkJeX161YzGAIuQAOHjzI0zR9w2iKotCOHTuYrp5JS0vzm/nFixffNOd/8OBBRqVS3dQstm/fHvQK+XVCKgC9Xi91lgGtVuvTa3f1zPVr06ZNbKDPJCYmhtREQhoL+FoibI+vf/MX0VtVVeUZNmxYTHeeCSELoXWFeZ6XNBrNLamrVCrE87xPqyCEwNczOp0OchyHOmYeAAAEQfCZjl6vl3ieD9Z8AACeFscTIrgA5DZAbnAByG2A3OACkNsAuVF8AeCOkNwGyA0uALkNkBtcAHIbIDe4AOQ2QG5wAchtgNzgApDbALnBBSC3AXKDC0BuA+RGlgJoamryPvDAA2xOTg647777+FOnToW2vBMKoSwsBsO2bdtuCYggCAKVl5cHvClTOInqjJDL5ZKMRmOnoXBut1uKiYmJaqhcVJvAAw880OU3ne+++641WrZcJ2oFUFNT46ioqOgyUrS+vt7nDk2RJGoF8B//8R8Gf/dMnz496gUQFSe4ceNGv5FgUTLlFiLuBCGEkKZp0l8y586dE7Ozs/teE5g/f77DX+YHDBggyJF5ACK8MGKxWITExESVv/saGxu5lJSULh1kpIioAsaNG+e3cOfOncvKlXkAQOQ8zw8//OAzWrTjJUnSTeF0drvdO2/ePOYXv/iFt6mpyR0p+64TsQIwGAx+A6D/+te/eto/c//9999SaDk5OawkSX43QwiWiBTAq6++esvOLx2vxMREof0mD8uXL+/0mRkzZnQZeRoKYS8AhmH8RoICAFBlZeWNUFie57t8hiTJcJt5g7AXwJw5c27ZcKrjlZqaelPw9IwZM/w+E8CWIEER9tegSqUCotj1PjYQQkRci3+9evUqk5aWpu/qfrVajTiO6zpeNkjC/hqUpK6/fFu4cKGLaBf8O3bsWL8doN/97ne2MJjmm3BL6p577un09afVaqEgCDdee59++qmrs3uvXzExMVIgW+IES9gLwGq1dvrhU0VFxU2h7SqVyu+HVV9++WVEZ4oi8hq0WCxSZmbmjY8iEhIS+CNHjtz0zn/hhRes/jKfmLine truncated
|
<img id="oix_logo" src="/luci-static/resources/openclash/img/oixcloud.png" loading="lazy" title="oixCloud" alt="oixCloud" onerror="return imgerrorfuns(this,this.src)" onclick="return show_more()" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="more-info" id="more_info">
|
<div class="more-info" id="more_info">
|
||||||
@@ -30,9 +35,7 @@
|
|||||||
<div class="oix-announcement" id="oix-announcement" style="display: none;">
|
<div class="oix-announcement" id="oix-announcement" style="display: none;">
|
||||||
<div id="oix-announcement-banner" class="oix-announcement-banner">
|
<div id="oix-announcement-banner" class="oix-announcement-banner">
|
||||||
<div class="oix-megaphone-container">
|
<div class="oix-megaphone-container">
|
||||||
<svg id="oix-megaphone" xmlns="http://www.w3.org/2000/svg" width="15" height="15" fill="currentColor" viewBox="0 0 256 256">
|
<svg id="oix-megaphone" width="15" height="15"><use href="#oc-icon-megaphone"/></svg>
|
||||||
<path d="M228.54,86.66l-176.06-54A16,16,0,0,0,32,48V192a16,16,0,0,0,16,16,16,16,0,0,0,4.52-.65L136,181.73V192a16,16,0,0,0,16,16h32a16,16,0,0,0,16-16v-29.9l28.54-8.75A16.09,16.09,0,0,0,240,138V102A16.09,16.09,0,0,0,228.54,86.66ZM136,165,48,192V48l88,27Zm48,27H152V176.82L184,167Zm40-54-.11,0L152,160.08V79.92l71.89,22,.11,0v36Z"></path>
|
|
||||||
</svg>
|
|
||||||
</div>
|
</div>
|
||||||
<div id="oix-announcement-content" class="oix-announcement-content"></div>
|
<div id="oix-announcement-content" class="oix-announcement-content"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -13,23 +13,28 @@ function act_manual_unlock_test_<%=stream_id_name%>(btn, type)
|
|||||||
if (manual_<%=stream_id_name%>_type_legend && manual_<%=stream_id_name%>_type_output)
|
if (manual_<%=stream_id_name%>_type_legend && manual_<%=stream_id_name%>_type_output)
|
||||||
{
|
{
|
||||||
manual_<%=stream_id_name%>_type_output.innerHTML =
|
manual_<%=stream_id_name%>_type_output.innerHTML =
|
||||||
'<img src="<%=resource%>/icons/loading.gif" alt="<%:Loading%>" style="vertical-align:middle" /> ' +
|
'<img src="<%=resource%>/icons/loading.svg" onerror="this.onerror=null;this.src=\'<%=resource%>/icons/loading.gif\'" alt="<%:Loading...%>" style="vertical-align:middle" /> ' +
|
||||||
'<%:Waiting for command to complete...%>';
|
'<%:Waiting for command to complete...%>';
|
||||||
|
|
||||||
|
manual_<%=stream_id_name%>_type_legend.textContent = '<%:Collecting data...%>';
|
||||||
manual_<%=stream_id_name%>_type_legend.parentNode.style.display = 'block';
|
manual_<%=stream_id_name%>_type_legend.parentNode.style.display = 'block';
|
||||||
manual_<%=stream_id_name%>_type_legend.style.display = 'inline';
|
manual_<%=stream_id_name%>_type_legend.style.display = 'block';
|
||||||
};
|
};
|
||||||
|
|
||||||
XHR.get('<%=luci.dispatcher.build_url("admin", "services", "openclash", "manual_stream_unlock_test")%>', {type: type}, function(x, status) {
|
XHR.get('<%=luci.dispatcher.build_url("admin", "services", "openclash", "manual_stream_unlock_test")%>', {type: type}, function(x, status) {
|
||||||
if (x && x.status == 200 && x.responseText != "")
|
if (x && x.status == 200 && x.responseText != "")
|
||||||
{
|
{
|
||||||
manual_<%=stream_id_name%>_type_legend.style.display = 'none';
|
manual_<%=stream_id_name%>_type_legend.textContent = '<%:Unlock Test Result%>';
|
||||||
manual_<%=stream_id_name%>_type_output.innerHTML = '<textarea id="manual_<%=stream_id_name%>_type_output" class="cbi-input-textarea" style="width: 100%;display:inline" data-update="change" rows="10" cols="50" readonly="readonly" >'+x.responseText+'</textarea>';
|
manual_<%=stream_id_name%>_type_output.innerHTML = '';
|
||||||
log_editor(document.getElementById("manual_<%=stream_id_name%>_type_output"), 'manual_stream_unlock_test', 'true', manual_<%=stream_id_name%>_type_output.offsetWidth, '250px');
|
var ta = document.createElement('textarea');
|
||||||
|
ta.value = x.responseText;
|
||||||
|
manual_<%=stream_id_name%>_type_output.appendChild(ta);
|
||||||
|
_cmWhenReady(function() {
|
||||||
|
log_editor(ta, 'manual_stream_unlock_test', 'true', '600px', '250px');
|
||||||
|
});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
manual_<%=stream_id_name%>_type_legend.style.display = 'none';
|
|
||||||
manual_<%=stream_id_name%>_type_output.innerHTML = '<span class="error"><%:Something Wrong While Testing...%></span>';
|
manual_<%=stream_id_name%>_type_output.innerHTML = '<span class="error"><%:Something Wrong While Testing...%></span>';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -46,23 +51,28 @@ function act_all_proxies_test_<%=stream_id_name%>(btn, type)
|
|||||||
if (all_<%=stream_id_name%>_legend && all_<%=stream_id_name%>_output)
|
if (all_<%=stream_id_name%>_legend && all_<%=stream_id_name%>_output)
|
||||||
{
|
{
|
||||||
all_<%=stream_id_name%>_output.innerHTML =
|
all_<%=stream_id_name%>_output.innerHTML =
|
||||||
'<img src="<%=resource%>/icons/loading.gif" alt="<%:Loading%>" style="vertical-align:middle" /> ' +
|
'<img src="<%=resource%>/icons/loading.svg" onerror="this.onerror=null;this.src=\'<%=resource%>/icons/loading.gif\'" alt="<%:Loading...%>" style="vertical-align:middle" /> ' +
|
||||||
'<%:Waiting for command to complete...%>';
|
'<%:Waiting for command to complete...%>';
|
||||||
|
|
||||||
|
all_<%=stream_id_name%>_legend.textContent = '<%:Collecting data...%>';
|
||||||
all_<%=stream_id_name%>_legend.parentNode.style.display = 'block';
|
all_<%=stream_id_name%>_legend.parentNode.style.display = 'block';
|
||||||
all_<%=stream_id_name%>_legend.style.display = 'inline';
|
all_<%=stream_id_name%>_legend.style.display = 'block';
|
||||||
};
|
};
|
||||||
|
|
||||||
XHR.get('<%=luci.dispatcher.build_url("admin", "services", "openclash", "all_proxies_stream_test")%>', {type: type}, function(x, status) {
|
XHR.get('<%=luci.dispatcher.build_url("admin", "services", "openclash", "all_proxies_stream_test")%>', {type: type}, function(x, status) {
|
||||||
if (x && x.status == 200 && x.responseText != "")
|
if (x && x.status == 200 && x.responseText != "")
|
||||||
{
|
{
|
||||||
all_<%=stream_id_name%>_legend.style.display = 'none';
|
all_<%=stream_id_name%>_legend.textContent = '<%:All Proxies Test Result%>';
|
||||||
all_<%=stream_id_name%>_output.innerHTML = '<textarea id="all_<%=stream_id_name%>_output" class="cbi-input-textarea" style="width: 100%;display:inline" data-update="change" rows="10" cols="50" readonly="readonly" >'+x.responseText+'</textarea>';
|
all_<%=stream_id_name%>_output.innerHTML = '';
|
||||||
log_editor(document.getElementById("all_<%=stream_id_name%>_output"), 'all_proxies_stream_test', true, all_<%=stream_id_name%>_output.offsetWidth, '250px');
|
var ta = document.createElement('textarea');
|
||||||
|
ta.value = x.responseText;
|
||||||
|
all_<%=stream_id_name%>_output.appendChild(ta);
|
||||||
|
_cmWhenReady(function() {
|
||||||
|
log_editor(ta, 'all_proxies_stream_test', true, '600px', '250px');
|
||||||
|
});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
all_<%=stream_id_name%>_legend.style.display = 'none';
|
|
||||||
all_<%=stream_id_name%>_output.innerHTML = '<span class="error"><%:Something Wrong While Testing...%></span>';
|
all_<%=stream_id_name%>_output.innerHTML = '<span class="error"><%:Something Wrong While Testing...%></span>';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -72,17 +82,16 @@ function act_all_proxies_test_<%=stream_id_name%>(btn, type)
|
|||||||
|
|
||||||
//]]></script>
|
//]]></script>
|
||||||
|
|
||||||
|
|
||||||
<input type="button" class="btn cbi-button cbi-input-reload" value="<%:Unlock Test(Select)%>" onclick="return act_manual_unlock_test_<%=stream_id_name%>(this, '<%=self.value%>')" />
|
<input type="button" class="btn cbi-button cbi-input-reload" value="<%:Unlock Test(Select)%>" onclick="return act_manual_unlock_test_<%=stream_id_name%>(this, '<%=self.value%>')" />
|
||||||
<input type="button" class="btn cbi-button cbi-input-reload" value="<%:All Proxies Test%>" onclick="return act_all_proxies_test_<%=stream_id_name%>(this, '<%=self.value%>')" />
|
<input type="button" class="btn cbi-button cbi-input-reload" value="<%:All Proxies Test%>" onclick="return act_all_proxies_test_<%=stream_id_name%>(this, '<%=self.value%>')" />
|
||||||
<fieldset style="display: none;margin: 0 auto;">
|
<div class="oc">
|
||||||
<legend id="manual-<%=stream_id_name%>-test-state"><%:Collecting data...%></legend>
|
<div class="diag-style" style="display:none">
|
||||||
<br />
|
<div id="manual-<%=stream_id_name%>-test-state" class="diag-legend"><%:Collecting data...%></div>
|
||||||
<span id="manual-<%=stream_id_name%>-test-output"></span>
|
<div id="manual-<%=stream_id_name%>-test-output"></div>
|
||||||
</fieldset>
|
</div>
|
||||||
<fieldset style="display: none;margin: 0 auto;">
|
<div class="diag-style" style="display:none">
|
||||||
<legend id="all-<%=stream_id_name%>-test-state"><%:Collecting data...%></legend>
|
<div id="all-<%=stream_id_name%>-test-state" class="diag-legend"><%:Collecting data...%></div>
|
||||||
<br />
|
<div id="all-<%=stream_id_name%>-test-output"></div>
|
||||||
<span id="all-<%=stream_id_name%>-test-output"></span>
|
</div>
|
||||||
</fieldset>
|
</div>
|
||||||
<%+cbi/valuefooter%>
|
<%+cbi/valuefooter%>
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
<%+openclash/common%>
|
||||||
|
<script src="/luci-static/resources/openclash/js/oc-icons.js?v=<%=plugin_version%>"></script>
|
||||||
<body>
|
<body>
|
||||||
<div class="oc">
|
<div class="oc">
|
||||||
<div id="selectPopup" class="select-popup hidden">
|
<div id="selectPopup" class="select-popup hidden">
|
||||||
@@ -7,10 +9,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="config-editor-actions">
|
<div class="config-editor-actions">
|
||||||
<button type="button" class="icon-btn close-btn" onclick="closeSelectPopup()" title="<%:Close%>">
|
<button type="button" class="icon-btn close-btn" onclick="closeSelectPopup()" title="<%:Close%>">
|
||||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
<svg width="14" height="14"><use href="#oc-icon-close"/></svg>
|
||||||
<line x1="18" y1="6" x2="6" y2="18"></line>
|
|
||||||
<line x1="6" y1="6" x2="18" y2="18"></line>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -18,26 +17,7 @@
|
|||||||
<div class="config-grid">
|
<div class="config-grid">
|
||||||
<div class="config-item">
|
<div class="config-item">
|
||||||
<div class="config-label"><%:Compiled Version%></div>
|
<div class="config-label"><%:Compiled Version%></div>
|
||||||
<select class="select-class" id="CORE_VERSION_CDN">
|
<select class="select-class oc-arch-select" id="CORE_VERSION_CDN">
|
||||||
<option value="linux-386"><%:linux-386%></option>
|
|
||||||
<option value="linux-amd64-v1"><%:linux-amd64-v1(x86-64)%></option>
|
|
||||||
<option value="linux-amd64-v2"><%:linux-amd64-v2(x86-64)%></option>
|
|
||||||
<option value="linux-amd64-v3"><%:linux-amd64-v3(x86-64)%></option>
|
|
||||||
<option value="linux-armv5"><%:linux-armv5%></option>
|
|
||||||
<option value="linux-armv6"><%:linux-armv6%></option>
|
|
||||||
<option value="linux-armv7"><%:linux-armv7%></option>
|
|
||||||
<option value="linux-arm64"><%:linux-arm64(armv8)%></option>
|
|
||||||
<option value="linux-loong64-abi1"><%:linux-loong64-abi1%></option>
|
|
||||||
<option value="linux-loong64-abi2"><%:linux-loong64-abi2%></option>
|
|
||||||
<option value="linux-riscv64"><%:linux-riscv64%></option>
|
|
||||||
<option value="linux-s390x"><%:linux-s390x%></option>
|
|
||||||
<option value="linux-mips-hardfloat"><%:linux-mips-hardfloat%></option>
|
|
||||||
<option value="linux-mips-softfloat"><%:linux-mips-softfloat%></option>
|
|
||||||
<option value="linux-mips64"><%:linux-mips64%></option>
|
|
||||||
<option value="linux-mips64le"><%:linux-mips64le%></option>
|
|
||||||
<option value="linux-mipsle-softfloat"><%:linux-mipsle-softfloat%></option>
|
|
||||||
<option value="linux-mipsle-hardfloat"><%:linux-mipsle-hardfloat%></option>
|
|
||||||
<option value="0"><%:Not Set%></option>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -53,11 +33,7 @@
|
|||||||
<div class="config-label">
|
<div class="config-label">
|
||||||
<%:Smart Core%>
|
<%:Smart Core%>
|
||||||
<a href="javascript:void(0);" onclick="window.open('https://github.com/vernesong/mihomo/releases', '_blank');" class="help-link" title="<%:View core infos that support smart group%>">
|
<a href="javascript:void(0);" onclick="window.open('https://github.com/vernesong/mihomo/releases', '_blank');" class="help-link" title="<%:View core infos that support smart group%>">
|
||||||
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
<svg width="12" height="12"><use href="#oc-icon-help"/></svg>
|
||||||
<circle cx="12" cy="12" r="10"></circle>
|
|
||||||
<path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"></path>
|
|
||||||
<line x1="12" y1="17" x2="12.01" y2="17"></line>
|
|
||||||
</svg>
|
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<select class="select-class" id="SMART_ENABLE_CDN">
|
<select class="select-class" id="SMART_ENABLE_CDN">
|
||||||
@@ -84,9 +60,7 @@
|
|||||||
<div class="select-option" data-value="custom">
|
<div class="select-option" data-value="custom">
|
||||||
<span><%:Custom Your CDN URL%></span>
|
<span><%:Custom Your CDN URL%></span>
|
||||||
<span style="display: flex; align-items: center; height: 100%;">
|
<span style="display: flex; align-items: center; height: 100%;">
|
||||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor" stroke="none" style="display: block;">
|
<svg width="18" height="18" style="display: block;"><use href="#oc-icon-chevron-down"/></svg>
|
||||||
<polygon points="6,9 18,9 12,15"/>
|
|
||||||
</svg>
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<input type="text" id="customOptionInput" class="custom-option-input" value="https://ghfast.top/" placeholder="<%:Type CDN URL, Format Like%> https://ghfast.top/" style="display: none;">
|
<input type="text" id="customOptionInput" class="custom-option-input" value="https://ghfast.top/" placeholder="<%:Type CDN URL, Format Like%> https://ghfast.top/" style="display: none;">
|
||||||
@@ -102,29 +76,6 @@
|
|||||||
var release_branch_cdn = document.getElementById('RELEASE_BRANCH_CDN');
|
var release_branch_cdn = document.getElementById('RELEASE_BRANCH_CDN');
|
||||||
var smart_enable_cdn = document.getElementById('SMART_ENABLE_CDN');
|
var smart_enable_cdn = document.getElementById('SMART_ENABLE_CDN');
|
||||||
|
|
||||||
function initDarkMode() {
|
|
||||||
var ocContainers = document.querySelectorAll('.oc');
|
|
||||||
if (!ocContainers.length) return;
|
|
||||||
|
|
||||||
var shouldUseDark = isDarkBackground(document.body);
|
|
||||||
|
|
||||||
ocContainers.forEach(function(ocContainer) {
|
|
||||||
if (shouldUseDark) {
|
|
||||||
ocContainer.setAttribute('data-darkmode', 'true');
|
|
||||||
document.documentElement.setAttribute('data-darkmode', 'true');
|
|
||||||
} else {
|
|
||||||
ocContainer.removeAttribute('data-darkmode');
|
|
||||||
document.documentElement.removeAttribute('data-darkmode');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (document.readyState === 'loading') {
|
|
||||||
document.addEventListener('DOMContentLoaded', initDarkMode);
|
|
||||||
} else {
|
|
||||||
initDarkMode();
|
|
||||||
}
|
|
||||||
|
|
||||||
function get_update_info() {
|
function get_update_info() {
|
||||||
XHR.get('<%=luci.dispatcher.build_url("admin", "services", "openclash", "update_info")%>', null, function(x, status) {
|
XHR.get('<%=luci.dispatcher.build_url("admin", "services", "openclash", "update_info")%>', null, function(x, status) {
|
||||||
if ( x && x.status == 200 ) {
|
if ( x && x.status == 200 ) {
|
||||||
|
|||||||
File diff suppressed because it is too large.
Load diff
@@ -1,4 +1,9 @@
|
|||||||
<%+cbi/valueheader%>
|
<%+cbi/valueheader%>
|
||||||
|
<%
|
||||||
|
local fs = require "luci.openclash"
|
||||||
|
local plugin_version = fs.oc_version()
|
||||||
|
%>
|
||||||
|
<script src="/luci-static/resources/openclash/js/oc-icons.js?v=<%=plugin_version%>"></script>
|
||||||
<%
|
<%
|
||||||
local fs = require "luci.openclash"
|
local fs = require "luci.openclash"
|
||||||
local val = self:cfgvalue(section)
|
local val = self:cfgvalue(section)
|
||||||
@@ -6,27 +11,16 @@
|
|||||||
local idname = math.random(1000)..(string.match(filename, "[%w_]+") or "")
|
local idname = math.random(1000)..(string.match(filename, "[%w_]+") or "")
|
||||||
%>
|
%>
|
||||||
|
|
||||||
<div class="sub_div">
|
<div class="sub_div oc">
|
||||||
<span id='<%=idname%>' class="sub_tab"></span>
|
<span id='<%=idname%>' class="sub_tab"></span>
|
||||||
<button type="button" class="sub_setting" title='<%:Refresh%>' alt='<%:Refresh%>' onclick='return sub_info_refresh_<%=idname%>(true)'>
|
<button type="button" class="sub_setting" title='<%:Refresh%>' alt='<%:Refresh%>' onclick='return sub_info_refresh_<%=idname%>(true)'>
|
||||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
<svg viewBox="0 0 24 24"><use href="#oc-icon-refresh"/></svg>
|
||||||
<path d="M23 4v6h-6"></path>
|
|
||||||
<path d="M20.49 15a9 9 0 1 1-2.12-9.36L23 10"></path>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
<button type="button" class="sub_setting" title='<%:Specify URL%>' alt='<%:Specify URL%>' onclick='return setUrlConfig_<%=idname%>()'>
|
<button type="button" class="sub_setting" title='<%:Specify URL%>' alt='<%:Specify URL%>' onclick='return setUrlConfig_<%=idname%>()'>
|
||||||
<svg viewBox="0 0 48 48" fill="none" stroke="currentColor" stroke-width="4">
|
<svg viewBox="0 0 48 48"><use href="#oc-icon-chat"/></svg>
|
||||||
<path d="M4 6H44V36H29L24 41L19 36H4V6Z"/>
|
|
||||||
<path d="M23 21H25.0025" />
|
|
||||||
<path d="M33.001 21H34.9999"/>
|
|
||||||
<path d="M13.001 21H14.9999"/>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
<button type="button" class="sub_setting" title='<%:Edit Subscription%>' alt='<%:Edit Subscription%>' onclick='return uploadConfig_<%=idname%>()'>
|
<button type="button" class="sub_setting" title='<%:Edit Subscription%>' alt='<%:Edit Subscription%>' onclick='return uploadConfig_<%=idname%>()'>
|
||||||
<svg width="14" height="14" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg width="14" height="14"><use href="#oc-icon-settings"/></svg>
|
||||||
<path d="M18.2838 43.1713C14.9327 42.1736 11.9498 40.3213 9.58787 37.867C10.469 36.8227 11 35.4734 11 34.0001C11 30.6864 8.31371 28.0001 5 28.0001C4.79955 28.0001 4.60139 28.01 4.40599 28.0292C4.13979 26.7277 4 25.3803 4 24.0001C4 21.9095 4.32077 19.8938 4.91579 17.9995C4.94381 17.9999 4.97188 18.0001 5 18.0001C8.31371 18.0001 11 15.3138 11 12.0001C11 11.0488 10.7786 10.1493 10.3846 9.35011C12.6975 7.1995 15.5205 5.59002 18.6521 4.72314C19.6444 6.66819 21.6667 8.00013 24 8.00013C26.3333 8.00013 28.3556 6.66819 29.3479 4.72314C32.4795 5.59002 35.3025 7.1995 37.6154 9.35011C37.2214 10.1493 37 11.0488 37 12.0001C37 15.3138 39.6863 18.0001 43 18.0001C43.0281 18.0001 43.0562 17.9999 43.0842 17.9995C43.6792 19.8938 44 21.9095 44 24.0001C44 25.3803 43.8602 26.7277 43.594 28.0292C43.3986 28.01 43.2005 28.0001 43 28.0001C39.6863 28.0001 37 30.6864 37 34.0001C37 35.4734 37.531 36.8227 38.4121 37.867C36.0502 40.3213 33.0673 42.1736 29.7162 43.1713C28.9428 40.752 26.676 39.0001 24 39.0001C21.324 39.0001 19.0572 40.752 18.2838 43.1713Z" fill="none" stroke="currentColor" stroke-width="4" stroke-linejoin="round"/>
|
|
||||||
<path d="M24 31C27.866 31 31 27.866 31 24C31 20.134 27.866 17 24 17C20.134 17 17 20.134 17 24C17 27.866 20.134 31 24 31Z" fill="none" stroke="currentColor" stroke-width="4" stroke-linejoin="round"/>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -36,45 +30,18 @@ var retry_<%=idname%> = 0;
|
|||||||
var s_<%=idname%>;
|
var s_<%=idname%>;
|
||||||
sub_info_refresh_<%=idname%>(false);
|
sub_info_refresh_<%=idname%>(false);
|
||||||
|
|
||||||
setTimeout(function(){
|
|
||||||
initDarkMode();
|
|
||||||
}, 200);
|
|
||||||
|
|
||||||
function initDarkMode() {
|
|
||||||
if (typeof isDarkBackground === 'undefined') {
|
|
||||||
setTimeout(function() {
|
|
||||||
initDarkMode();
|
|
||||||
}, 100);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isDarkBackground(document.body)) {
|
|
||||||
document.documentElement.setAttribute('data-darkmode', 'true');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function progressbar_<%=idname%>(v, m, pc, np, f, t, tr) {
|
function progressbar_<%=idname%>(v, m, pc, np, f, t, tr) {
|
||||||
var screenWidth = window.innerWidth || document.documentElement.clientWidth;
|
var screenWidth = window.innerWidth || document.documentElement.clientWidth;
|
||||||
var fontSize = '12px';
|
var fontSize = '12px';
|
||||||
var minWidth = '200px';
|
|
||||||
var topPosition = tr == "null" ? '6px' : '2px';
|
|
||||||
|
|
||||||
if (screenWidth <= 320) {
|
if (screenWidth <= 320) {
|
||||||
fontSize = '8px';
|
fontSize = '8px';
|
||||||
minWidth = '140px';
|
|
||||||
topPosition = tr == "null" ? '8px' : '4px';
|
|
||||||
} else if (screenWidth <= 480) {
|
} else if (screenWidth <= 480) {
|
||||||
fontSize = '9px';
|
fontSize = '9px';
|
||||||
minWidth = '160px';
|
|
||||||
topPosition = tr == "null" ? '7px' : '3px';
|
|
||||||
} else if (screenWidth <= 768) {
|
} else if (screenWidth <= 768) {
|
||||||
fontSize = '10px';
|
fontSize = '10px';
|
||||||
minWidth = '180px';
|
|
||||||
topPosition = tr == "null" ? '6px' : '3px';
|
|
||||||
} else if (screenWidth <= 1024) {
|
} else if (screenWidth <= 1024) {
|
||||||
fontSize = '11px';
|
fontSize = '11px';
|
||||||
minWidth = '200px';
|
|
||||||
topPosition = tr == "null" ? '6px' : '2px';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build title for native tooltip (format: "v / m (pc%)\nt (Remaining tr days)")
|
// Build title for native tooltip (format: "v / m (pc%)\nt (Remaining tr days)")
|
||||||
@@ -84,7 +51,7 @@ function progressbar_<%=idname%>(v, m, pc, np, f, t, tr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return String.format(
|
return String.format(
|
||||||
'<div class="progress_bar_bg" title="' + titleText + '" style="position:relative; border-radius: 6px; min-width: %s; display: flex; align-items: center;">' +
|
'<div class="progress_bar_bg" title="' + titleText + '" style="position:relative; border-radius: 6px; display: flex; align-items: center;">' +
|
||||||
(pc >= 50 ? '<div class="progress_bar_high" style="width:%d%%; height:34px; border-radius: 6px">' :
|
(pc >= 50 ? '<div class="progress_bar_high" style="width:%d%%; height:34px; border-radius: 6px">' :
|
||||||
(pc < 50 && pc >= 20 ? '<div class="progress_bar_medium" style="width:%d%%; height:34px; border-radius: 6px">' :
|
(pc < 50 && pc >= 20 ? '<div class="progress_bar_medium" style="width:%d%%; height:34px; border-radius: 6px">' :
|
||||||
'<div class="progress_bar_low" style="width:%d%%; height:34px; border-radius: 6px">')) +
|
'<div class="progress_bar_low" style="width:%d%%; height:34px; border-radius: 6px">')) +
|
||||||
@@ -95,7 +62,7 @@ function progressbar_<%=idname%>(v, m, pc, np, f, t, tr) {
|
|||||||
'</div>' +
|
'</div>' +
|
||||||
'</div>' +
|
'</div>' +
|
||||||
'</div>',
|
'</div>',
|
||||||
minWidth, pc, fontSize, v, m, pc, t, tr
|
pc, fontSize, v, m, pc, t, tr
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -267,7 +234,7 @@ function sub_info_refresh_<%=idname%>(force) {
|
|||||||
|
|
||||||
if (!needsErrorHandling) {
|
if (!needsErrorHandling) {
|
||||||
retry_<%=idname%> = 0;
|
retry_<%=idname%> = 0;
|
||||||
localStorage.setItem("sub_info_<%=filename%>", JSON.stringify(status));
|
(window.requestIdleCallback || function(cb) { setTimeout(cb, 1); })(function() { localStorage.setItem("sub_info_<%=filename%>", JSON.stringify(status)); });
|
||||||
dispaly_progressbar('<%=idname%>', status);
|
dispaly_progressbar('<%=idname%>', status);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -281,7 +248,7 @@ function sub_info_refresh_<%=idname%>(force) {
|
|||||||
retry_<%=idname%> = 0;
|
retry_<%=idname%> = 0;
|
||||||
dispaly_progressbar('<%=idname%>', status);
|
dispaly_progressbar('<%=idname%>', status);
|
||||||
if (status && status.providers) {
|
if (status && status.providers) {
|
||||||
localStorage.setItem("sub_info_<%=filename%>", JSON.stringify(status));
|
(window.requestIdleCallback || function(cb) { setTimeout(cb, 1); })(function() { localStorage.setItem("sub_info_<%=filename%>", JSON.stringify(status)); });
|
||||||
}
|
}
|
||||||
s_<%=idname%> = setTimeout("sub_info_refresh_<%=idname%>(false)", 60000*15);
|
s_<%=idname%> = setTimeout("sub_info_refresh_<%=idname%>(false)", 60000*15);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
<%
|
||||||
|
local fs = require "luci.openclash"
|
||||||
|
local plugin_version = fs.oc_version()
|
||||||
|
%>
|
||||||
|
<div class="oc-subconverter-version-loader" hidden></div>
|
||||||
|
<script src="/luci-static/resources/openclash/js/subconverter-version.js?v=<%=plugin_version%>"></script>
|
||||||
|
<script type="text/javascript">//<![CDATA[
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
var attempts = 0;
|
||||||
|
|
||||||
|
function initSubconverterVersionStatus() {
|
||||||
|
var selectSelector = 'div[id$=".convert_address"].cbi-dropdown, select[name$=".convert_address"], input[name$=".convert_address"]';
|
||||||
|
var select = document.querySelector(selectSelector);
|
||||||
|
var status = document.getElementById('subconverter-version-status-cbi');
|
||||||
|
|
||||||
|
if (!window.OpenClashSubconverterVersion || !select || !status) {
|
||||||
|
if (attempts++ < 50) window.setTimeout(initSubconverterVersionStatus, 100);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
window.OpenClashSubconverterVersion.init({
|
||||||
|
select: selectSelector,
|
||||||
|
enable: document.querySelector('input[type="checkbox"][name$=".sub_convert"]'),
|
||||||
|
status: status,
|
||||||
|
watchRoot: status.closest ? status.closest('.cbi-value') : null,
|
||||||
|
watchDocument: true,
|
||||||
|
proxyURL: '<%=luci.dispatcher.build_url("admin", "services", "openclash", "subconverter_version")%>',
|
||||||
|
labels: {
|
||||||
|
checking: '<%:Checking backend version...%>',
|
||||||
|
versionPrefix: '<%:Backend Version%>',
|
||||||
|
empty: '<%:Please enter backend URL%>',
|
||||||
|
invalid: '<%:Invalid backend URL%>',
|
||||||
|
unrecognized: '<%:Backend version information not detected%>',
|
||||||
|
failed: '<%:Unable to detect backend version%>'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
initSubconverterVersionStatus();
|
||||||
|
});
|
||||||
|
//]]></script>
|
||||||
@@ -192,55 +192,55 @@ local sectiontype = "_"..self.config.."_"..string.match(self.sectiontype, "[%w_]
|
|||||||
width: 225px;
|
width: 225px;
|
||||||
}
|
}
|
||||||
|
|
||||||
:root[data-darkmode="true"] #tab-header-<%=self.config%>-<%=self.sectiontype%>{
|
html[data-darkmode="true"] .oc #tab-header-<%=self.config%>-<%=self.sectiontype%>{
|
||||||
background: #374151;
|
background: #374151;
|
||||||
border-bottom: 1px solid #374151;
|
border-bottom: 1px solid #374151;
|
||||||
}
|
}
|
||||||
|
|
||||||
:root[data-darkmode="true"] #tab-header-<%=self.config%>-<%=self.sectiontype%> ul{
|
html[data-darkmode="true"] .oc #tab-header-<%=self.config%>-<%=self.sectiontype%> ul{
|
||||||
background: #374151;
|
background: #374151;
|
||||||
}
|
}
|
||||||
|
|
||||||
:root[data-darkmode="true"] #tab-header-<%=self.config%>-<%=self.sectiontype%> ul li{
|
html[data-darkmode="true"] .oc #tab-header-<%=self.config%>-<%=self.sectiontype%> ul li{
|
||||||
background: #1f2937;
|
background: #1f2937;
|
||||||
color: #a1a1aa;
|
color: #a1a1aa;
|
||||||
border-color: #374151;
|
border-color: #374151;
|
||||||
}
|
}
|
||||||
|
|
||||||
:root[data-darkmode="true"] #tab-header-<%=self.config%>-<%=self.sectiontype%> ul li.cbi-tab{
|
html[data-darkmode="true"] .oc #tab-header-<%=self.config%>-<%=self.sectiontype%> ul li.cbi-tab{
|
||||||
background: #2563eb;
|
background: #2563eb;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
:root[data-darkmode="true"] #tab-header-<%=self.config%>-<%=self.sectiontype%> ul li.cbi-tab a{
|
html[data-darkmode="true"] .oc #tab-header-<%=self.config%>-<%=self.sectiontype%> ul li.cbi-tab a{
|
||||||
color: #fff !important;
|
color: #fff !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
:root[data-darkmode="true"] #tab-header-<%=self.config%>-<%=self.sectiontype%> ul li.cbi-tab-disabled{
|
html[data-darkmode="true"] .oc #tab-header-<%=self.config%>-<%=self.sectiontype%> ul li.cbi-tab-disabled{
|
||||||
color: #1f2937;
|
color: #1f2937;
|
||||||
background: #1f2937;
|
background: #1f2937;
|
||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
}
|
}
|
||||||
|
|
||||||
:root[data-darkmode="true"] #tab-header-<%=self.config%>-<%=self.sectiontype%> ul li.cbi-tab-disabled a{
|
html[data-darkmode="true"] .oc #tab-header-<%=self.config%>-<%=self.sectiontype%> ul li.cbi-tab-disabled a{
|
||||||
color: #fff !important;
|
color: #fff !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
:root[data-darkmode="true"] #tab-header-<%=self.config%>-<%=self.sectiontype%> ul li:not(.cbi-tab):hover,
|
html[data-darkmode="true"] .oc #tab-header-<%=self.config%>-<%=self.sectiontype%> ul li:not(.cbi-tab):hover,
|
||||||
:root[data-darkmode="true"] #tab-header-<%=self.config%>-<%=self.sectiontype%> ul li:not(.cbi-tab):focus{
|
html[data-darkmode="true"] .oc #tab-header-<%=self.config%>-<%=self.sectiontype%> ul li:not(.cbi-tab):focus{
|
||||||
color: #3b82f6;
|
color: #3b82f6;
|
||||||
border-color: #3b82f6;
|
border-color: #3b82f6;
|
||||||
background: #22304a;
|
background: #22304a;
|
||||||
}
|
}
|
||||||
|
|
||||||
:root[data-darkmode="true"] #tab-header-<%=self.config%>-<%=self.sectiontype%> ul li:not(.cbi-tab):hover a,
|
html[data-darkmode="true"] .oc #tab-header-<%=self.config%>-<%=self.sectiontype%> ul li:not(.cbi-tab):hover a,
|
||||||
:root[data-darkmode="true"] #tab-header-<%=self.config%>-<%=self.sectiontype%> ul li:not(.cbi-tab):focus a{
|
html[data-darkmode="true"] .oc #tab-header-<%=self.config%>-<%=self.sectiontype%> ul li:not(.cbi-tab):focus a{
|
||||||
color: #60a5fa !important;
|
color: #60a5fa !important;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<!-- tblsection -->
|
<!-- tblsection -->
|
||||||
<fieldset class="cbi-section" id="cbi-<%=self.config%>-<%=self.sectiontype%>">
|
<fieldset class="cbi-section oc" id="cbi-<%=self.config%>-<%=self.sectiontype%>">
|
||||||
<%- if self.title and #self.title > 0 then -%>
|
<%- if self.title and #self.title > 0 then -%>
|
||||||
<h3><%=self.title%></h3>
|
<h3><%=self.title%></h3>
|
||||||
<%- end -%>
|
<%- end -%>
|
||||||
@@ -475,9 +475,6 @@ local sectiontype = "_"..self.config.."_"..string.match(self.sectiontype, "[%w_]
|
|||||||
};
|
};
|
||||||
|
|
||||||
function onload<%=sectiontype%>() {
|
function onload<%=sectiontype%>() {
|
||||||
if (isDarkBackground(document.body)) {
|
|
||||||
document.documentElement.setAttribute('data-darkmode', 'true');
|
|
||||||
};
|
|
||||||
|
|
||||||
if(titles<%=sectiontype%>.length != divs<%=sectiontype%>.length) return;
|
if(titles<%=sectiontype%>.length != divs<%=sectiontype%>.length) return;
|
||||||
|
|
||||||
|
|||||||
@@ -3,12 +3,13 @@
|
|||||||
local plugin_version = fs.oc_version()
|
local plugin_version = fs.oc_version()
|
||||||
%>
|
%>
|
||||||
<head>
|
<head>
|
||||||
|
<script src="/luci-static/resources/openclash/js/common.js?v=<%=plugin_version%>"></script>
|
||||||
<link rel="stylesheet" href="/luci-static/resources/openclash/css/oc.css?v=<%=plugin_version%>">
|
<link rel="stylesheet" href="/luci-static/resources/openclash/css/oc.css?v=<%=plugin_version%>">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<li id="tool_label" class="tool_label">
|
<li id="tool_label" class="tool_label">
|
||||||
<span class="tool_label_span">
|
<span class="tool_label_span">
|
||||||
<%:Current Config File%>:
|
<%:Current Config%>:
|
||||||
<select class="tool_label_select" id="cfg_name">
|
<select class="tool_label_select" id="cfg_name">
|
||||||
</select>
|
</select>
|
||||||
<input type="button" class="btn cbi-button cbi-button-apply" value="<%:SwiTch%>" onclick="return switch_config(this)" />
|
<input type="button" class="btn cbi-button cbi-button-apply" value="<%:SwiTch%>" onclick="return switch_config(this)" />
|
||||||
@@ -16,45 +17,13 @@
|
|||||||
</span>
|
</span>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<script src="/luci-static/resources/openclash/js/common.js?v=<%=plugin_version%>"></script>
|
|
||||||
<script type="text/javascript">//<![CDATA[
|
<script type="text/javascript">//<![CDATA[
|
||||||
|
|
||||||
var config_name = document.getElementById('cfg_name');
|
var config_name = document.getElementById('cfg_name');
|
||||||
var tool_label = document.getElementById('tool_label');
|
var tool_label = document.getElementById('tool_label');
|
||||||
var Commit = document.getElementById('cbi-table-1-Commit');
|
|
||||||
var Apply = document.getElementById('cbi-table-1-Apply');
|
|
||||||
var Back = document.getElementById('cbi-table-1-Back');
|
|
||||||
var Load_Config = document.getElementById('cbi-table-1-Load_Config');
|
|
||||||
var Delete_Unused_Servers = document.getElementById('cbi-table-1-Delete_Unused_Servers');
|
|
||||||
var Delete_Servers = document.getElementById('cbi-table-1-Delete_Servers');
|
|
||||||
var Delete_Proxy_Provider = document.getElementById('cbi-table-1-Delete_Proxy_Provider');
|
|
||||||
var Delete_Groups = document.getElementById('cbi-table-1-Delete_Groups');
|
|
||||||
var rule_mg = document.getElementById('cbi-table-1-rule_mg');
|
|
||||||
var pro_mg = document.getElementById('cbi-table-1-pro_mg');
|
|
||||||
|
|
||||||
setTimeout("get_header()",100);
|
setTimeout("get_header()",100);
|
||||||
|
|
||||||
if (Commit) {
|
|
||||||
Commit.style.textAlign="center";
|
|
||||||
}
|
|
||||||
if (Apply) {
|
|
||||||
Apply.style.textAlign="center";
|
|
||||||
}
|
|
||||||
if (Back) {
|
|
||||||
Back.style.textAlign="center";
|
|
||||||
}
|
|
||||||
if (Load_Config) {
|
|
||||||
Load_Config.style.textAlign="center";
|
|
||||||
Delete_Unused_Servers.style.textAlign="center";
|
|
||||||
Delete_Servers.style.textAlign="center";
|
|
||||||
Delete_Proxy_Provider.style.textAlign="center";
|
|
||||||
Delete_Groups.style.textAlign="center";
|
|
||||||
}
|
|
||||||
if (rule_mg) {
|
|
||||||
rule_mg.style.textAlign="center";
|
|
||||||
pro_mg.style.textAlign="center";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tool_label.style.display != "none") {
|
if (tool_label.style.display != "none") {
|
||||||
XHR.get('<%=luci.dispatcher.build_url("admin", "services", "openclash", "config_name")%>', null, function(x, status) {
|
XHR.get('<%=luci.dispatcher.build_url("admin", "services", "openclash", "config_name")%>', null, function(x, status) {
|
||||||
if (x && x.status == 200 && status.config_name != "") {
|
if (x && x.status == 200 && status.config_name != "") {
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
|
<%
|
||||||
|
local fs = require "luci.openclash"
|
||||||
|
local plugin_version = fs.oc_version()
|
||||||
|
%>
|
||||||
|
<script src="/luci-static/resources/openclash/js/oc-icons.js?v=<%=plugin_version%>"></script>
|
||||||
<fieldset class="cbi-section">
|
<fieldset class="cbi-section">
|
||||||
<table width="100%">
|
<table width="100%">
|
||||||
<tr>
|
<tr>
|
||||||
@@ -10,26 +15,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td width="16.6%" align="right"><%:Compiled Version%></td>
|
<td width="16.6%" align="right"><%:Compiled Version%></td>
|
||||||
<td width="16.6%" align="left">
|
<td width="16.6%" align="left">
|
||||||
<select class="cbi-input-select" name="CORE_VERSION" id="CORE_VERSION">
|
<select class="cbi-input-select oc-arch-select" name="CORE_VERSION" id="CORE_VERSION">
|
||||||
<option value="linux-386"><%:linux-386%></option>
|
|
||||||
<option value="linux-amd64-v1"><%:linux-amd64-v1(x86-64)%></option>
|
|
||||||
<option value="linux-amd64-v2"><%:linux-amd64-v2(x86-64)%></option>
|
|
||||||
<option value="linux-amd64-v3"><%:linux-amd64-v3(x86-64)%></option>
|
|
||||||
<option value="linux-armv5"><%:linux-armv5%></option>
|
|
||||||
<option value="linux-armv6"><%:linux-armv6%></option>
|
|
||||||
<option value="linux-armv7"><%:linux-armv7%></option>
|
|
||||||
<option value="linux-arm64"><%:linux-arm64(armv8)%></option>
|
|
||||||
<option value="linux-loong64-abi1"><%:linux-loong64-abi1%></option>
|
|
||||||
<option value="linux-loong64-abi2"><%:linux-loong64-abi2%></option>
|
|
||||||
<option value="linux-riscv64"><%:linux-riscv64%></option>
|
|
||||||
<option value="linux-s390x"><%:linux-s390x%></option>
|
|
||||||
<option value="linux-mips-hardfloat"><%:linux-mips-hardfloat%></option>
|
|
||||||
<option value="linux-mips-softfloat"><%:linux-mips-softfloat%></option>
|
|
||||||
<option value="linux-mips64"><%:linux-mips64%></option>
|
|
||||||
<option value="linux-mips64le"><%:linux-mips64le%></option>
|
|
||||||
<option value="linux-mipsle-softfloat"><%:linux-mipsle-softfloat%></option>
|
|
||||||
<option value="linux-mipsle-hardfloat"><%:linux-mipsle-hardfloat%></option>
|
|
||||||
<option value="0"><%:Not Set%></option>
|
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
<td width="16.6%" align="right"><%:Release Branch%></td>
|
<td width="16.6%" align="right"><%:Release Branch%></td>
|
||||||
@@ -41,11 +27,7 @@
|
|||||||
</td>
|
</td>
|
||||||
<td width="16.6%" align="right"><%:Smart Core%>
|
<td width="16.6%" align="right"><%:Smart Core%>
|
||||||
<a href="javascript:void(0);" onclick="window.open('https://github.com/vernesong/mihomo/releases', '_blank');" style="color: #0066cc; text-decoration: none;" title="<%:View core infos that support smart group%>">
|
<a href="javascript:void(0);" onclick="window.open('https://github.com/vernesong/mihomo/releases', '_blank');" style="color: #0066cc; text-decoration: none;" title="<%:View core infos that support smart group%>">
|
||||||
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
<svg width="12" height="12"><use href="#oc-icon-help"/></svg>
|
||||||
<circle cx="12" cy="12" r="10"></circle>
|
|
||||||
<path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"></path>
|
|
||||||
<line x1="12" y1="17" x2="12.01" y2="17"></line>
|
|
||||||
</svg>
|
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td width="16.6%" align="left">
|
<td width="16.6%" align="left">
|
||||||
@@ -125,6 +107,7 @@
|
|||||||
</table>
|
</table>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
|
<%+openclash/common%>
|
||||||
<script type="text/javascript">//<![CDATA[
|
<script type="text/javascript">//<![CDATA[
|
||||||
var core_version = document.getElementById('CORE_VERSION');
|
var core_version = document.getElementById('CORE_VERSION');
|
||||||
var checktime = document.getElementById('CHECKTIME');
|
var checktime = document.getElementById('CHECKTIME');
|
||||||
@@ -326,7 +309,12 @@
|
|||||||
XHR.get('<%=luci.dispatcher.build_url("admin", "services", "openclash", "update_ma")%>', status.corever, function(x, status) {
|
XHR.get('<%=luci.dispatcher.build_url("admin", "services", "openclash", "update_ma")%>', status.corever, function(x, status) {
|
||||||
if ( x && x.status == 200 ) {
|
if ( x && x.status == 200 ) {
|
||||||
if ( status.corever != "0" ) {
|
if ( status.corever != "0" ) {
|
||||||
if (type == "Meta") {
|
if (status.oix_core) {
|
||||||
|
if (status.corelv && status.corelv != "" && status.corelv != "loading...") {
|
||||||
|
url4='https://github.com/vernesong/mihomo-oix/releases/download/Pre-Alpha/mihomo-'+status.corever+'-'+status.corelv+'.gz';
|
||||||
|
window.location.href=url4;
|
||||||
|
}
|
||||||
|
} else if (type == "Meta") {
|
||||||
if (s == "1") {
|
if (s == "1") {
|
||||||
url4='https://raw.githubusercontent.com/vernesong/OpenClash/core/'+r+'/smart/clash-'+status.corever+'.tar.gz';
|
url4='https://raw.githubusercontent.com/vernesong/OpenClash/core/'+r+'/smart/clash-'+status.corever+'.tar.gz';
|
||||||
window.location.href=url4;
|
window.location.href=url4;
|
||||||
|
|||||||
@@ -8,10 +8,21 @@
|
|||||||
<script type="text/javascript">//<![CDATA[
|
<script type="text/javascript">//<![CDATA[
|
||||||
function act_update_config_<%=idname%>(btn)
|
function act_update_config_<%=idname%>(btn)
|
||||||
{
|
{
|
||||||
|
var originalValue = btn.value;
|
||||||
btn.disabled = true;
|
btn.disabled = true;
|
||||||
btn.value = '<%:UpDate%>';
|
btn.value = '<%:Updating Config...%>';
|
||||||
XHR.get('<%=luci.dispatcher.build_url("admin", "services", "openclash","update_config")%>',{filename: "<%=filename%>"}, function(x,status){});
|
|
||||||
|
XHR.get('<%=luci.dispatcher.build_url("admin", "services", "openclash","update_config")%>',{filename: "<%=filename%>"}, function(x,status){
|
||||||
|
if (x && x.status == 200 && status && status.status === 'success') {
|
||||||
|
btn.value = '<%:Update Successful%>';
|
||||||
|
} else {
|
||||||
|
btn.value = '<%:Update Failed%>';
|
||||||
|
}
|
||||||
|
setTimeout(function() {
|
||||||
|
btn.value = originalValue;
|
||||||
btn.disabled = false;
|
btn.disabled = false;
|
||||||
|
}, 2000);
|
||||||
|
});
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ msgid "OpenClash"
|
|||||||
msgstr "OpenClash"
|
msgstr "OpenClash"
|
||||||
|
|
||||||
msgid "A Mihomo(Clash) Client For OpenWrt"
|
msgid "A Mihomo(Clash) Client For OpenWrt"
|
||||||
msgstr "Un cliente Mihomo(Clash) para OpenWrt compatible con Shadowsocks(R), Vmess, Trojan, Snell y otros protocolos, que permite el enrutamiento flexible por reglas."
|
msgstr "Cliente Mihomo(Clash) para OpenWrt"
|
||||||
|
|
||||||
msgid "Error"
|
msgid "Error"
|
||||||
msgstr "Error"
|
msgstr "Error"
|
||||||
@@ -147,10 +147,10 @@ msgid "fake-ip(tun mode)"
|
|||||||
msgstr "Fake-IP (TUN)"
|
msgstr "Fake-IP (TUN)"
|
||||||
|
|
||||||
msgid "redir-host-mix(tun mix mode)"
|
msgid "redir-host-mix(tun mix mode)"
|
||||||
msgstr "Modo Redir-Host (TUN mixto) [UDP-TUN, TCP-reenvío]"
|
msgstr "Redir-Host (TUN mixto)"
|
||||||
|
|
||||||
msgid "fake-ip-mix(tun mix mode)"
|
msgid "fake-ip-mix(tun mix mode)"
|
||||||
msgstr "Modo Fake-IP (TUN mixto) [UDP-TUN, TCP-reenvío]"
|
msgstr "Fake-IP (TUN mixto)"
|
||||||
|
|
||||||
msgid "Select Mode For OpenClash Work, Try Flush DNS Cache If Network Error"
|
msgid "Select Mode For OpenClash Work, Try Flush DNS Cache If Network Error"
|
||||||
msgstr "Selecciona el modo de funcionamiento de OpenClash. Si hay errores de red, intenta vaciar la caché DNS."
|
msgstr "Selecciona el modo de funcionamiento de OpenClash. Si hay errores de red, intenta vaciar la caché DNS."
|
||||||
@@ -165,7 +165,7 @@ msgid "Rule Proxy Mode"
|
|||||||
msgstr "Rule (proxy por reglas)"
|
msgstr "Rule (proxy por reglas)"
|
||||||
|
|
||||||
msgid "Global Proxy Mode"
|
msgid "Global Proxy Mode"
|
||||||
msgstr "Global (proxy total – requiere elegir nodo en el panel de control)"
|
msgstr "Global (proxy total)"
|
||||||
|
|
||||||
msgid "Direct Proxy Mode"
|
msgid "Direct Proxy Mode"
|
||||||
msgstr "Direct (conexión directa total)"
|
msgstr "Direct (conexión directa total)"
|
||||||
@@ -222,7 +222,7 @@ msgid "Redirect Local DNS Setting"
|
|||||||
msgstr "Redirección del DNS local"
|
msgstr "Redirección del DNS local"
|
||||||
|
|
||||||
msgid "Set Local DNS Redirect"
|
msgid "Set Local DNS Redirect"
|
||||||
msgstr "Configura la redirección del DNS local; se recomienda Dnsmasq para mejor compatibilidad"
|
msgstr "Configurar redirección del DNS local"
|
||||||
|
|
||||||
msgid "Dnsmasq Redirect"
|
msgid "Dnsmasq Redirect"
|
||||||
msgstr "Redirección mediante Dnsmasq"
|
msgstr "Redirección mediante Dnsmasq"
|
||||||
@@ -264,13 +264,13 @@ msgid "Domain Names In The List Use The Custom DNS Server, But Still Return Fake
|
|||||||
msgstr "Un dominio por línea; usarán el DNS indicado pero seguirán devolviendo direcciones Fake-IP"
|
msgstr "Un dominio por línea; usarán el DNS indicado pero seguirán devolviendo direcciones Fake-IP"
|
||||||
|
|
||||||
msgid "Set OpenClash Upstream DNS Resolve Server"
|
msgid "Set OpenClash Upstream DNS Resolve Server"
|
||||||
msgstr "Activar para sobrescribir la configuración DNS del archivo; configura los servidores abajo"
|
msgstr "Activar DNS upstream personalizado"
|
||||||
|
|
||||||
msgid "DNS Server Group"
|
msgid "DNS Server Group"
|
||||||
msgstr "Grupo de servidores DNS"
|
msgstr "Grupo de servidores DNS"
|
||||||
|
|
||||||
msgid "NameServer Group Must Be Set"
|
msgid "NameServer Group Must Be Set"
|
||||||
msgstr "Debe configurarse al menos un NameServer"
|
msgstr "NameServer requerido"
|
||||||
|
|
||||||
msgid "DNS Server Address"
|
msgid "DNS Server Address"
|
||||||
msgstr "Dirección del servidor"
|
msgstr "Dirección del servidor"
|
||||||
@@ -294,7 +294,7 @@ msgid "Proxy IPv6 Traffic"
|
|||||||
msgstr "Proxy para tráfico IPv6"
|
msgstr "Proxy para tráfico IPv6"
|
||||||
|
|
||||||
msgid "The Gateway and DNS of The Connected Device Must be The Router IP, Disable IPv6 DHCP To Avoid Abnormal Connection If You Do Not Use"
|
msgid "The Gateway and DNS of The Connected Device Must be The Router IP, Disable IPv6 DHCP To Avoid Abnormal Connection If You Do Not Use"
|
||||||
msgstr "El dispositivo debe usar como puerta de enlace y DNS la IP del router. Si no usas IPv6, desactiva su DHCP para evitar fallos."
|
msgstr "El GW y DNS del dispositivo deben ser la IP del router. Si no usas IPv6, desactiva su DHCP."
|
||||||
|
|
||||||
msgid "IPv6 DNS Resolve"
|
msgid "IPv6 DNS Resolve"
|
||||||
msgstr "Permitir resolución DNS IPv6"
|
msgstr "Permitir resolución DNS IPv6"
|
||||||
@@ -454,7 +454,7 @@ msgid "Set Authentication of SOCKS5/HTTP(S)"
|
|||||||
msgstr "Configurar autenticación para SOCKS5/HTTP(S)"
|
msgstr "Configurar autenticación para SOCKS5/HTTP(S)"
|
||||||
|
|
||||||
msgid "Not Null"
|
msgid "Not Null"
|
||||||
msgstr "No puede estar vacío"
|
msgstr "Requerido"
|
||||||
|
|
||||||
msgid "Server Subscription Address"
|
msgid "Server Subscription Address"
|
||||||
msgstr "Dirección de suscripción de configuración"
|
msgstr "Dirección de suscripción de configuración"
|
||||||
@@ -463,7 +463,7 @@ msgid "Auto Update Server subscription"
|
|||||||
msgstr "Actualizar suscripción automáticamente"
|
msgstr "Actualizar suscripción automáticamente"
|
||||||
|
|
||||||
msgid "Modify Your Config file:"
|
msgid "Modify Your Config file:"
|
||||||
msgstr "Puedes modificar tu archivo de configuración:"
|
msgstr "Modificar archivo de configuración:"
|
||||||
|
|
||||||
msgid "Here, Except The Settings That Were Taken Over"
|
msgid "Here, Except The Settings That Were Taken Over"
|
||||||
msgstr " (solo para parámetros que no estén gestionados por OpenClash)"
|
msgstr " (solo para parámetros que no estén gestionados por OpenClash)"
|
||||||
@@ -589,10 +589,10 @@ msgid "IP To CIDR:"
|
|||||||
msgstr "Conversor IP a CIDR:"
|
msgstr "Conversor IP a CIDR:"
|
||||||
|
|
||||||
msgid "Custom Hosts Here, You May Need to Turn off The Rebinding Protection Option of Dnsmasq When Hosts Has Set a Reserved Address, For More Go:"
|
msgid "Custom Hosts Here, You May Need to Turn off The Rebinding Protection Option of Dnsmasq When Hosts Has Set a Reserved Address, For More Go:"
|
||||||
msgstr "Configura Hosts personalizados aquí. Si usas direcciones reservadas, debes desactivar la protección de re-binding de Dnsmasq. Más información en:"
|
msgstr "Hosts personalizados. Si usas direcciones reservadas, desactiva el anti-rebinding de Dnsmasq. Más info:"
|
||||||
|
|
||||||
msgid "Set Custom Rules"
|
msgid "Set Custom Rules"
|
||||||
msgstr "Establecer reglas personalizadas (requiere activar la opción en Ajustes de reglas)"
|
msgstr "Reglas personalizadas"
|
||||||
|
|
||||||
msgid "Version Update"
|
msgid "Version Update"
|
||||||
msgstr "Actualización de versión"
|
msgstr "Actualización de versión"
|
||||||
@@ -631,7 +631,7 @@ msgid "Update OpenClash"
|
|||||||
msgstr "Actualizar OpenClash"
|
msgstr "Actualizar OpenClash"
|
||||||
|
|
||||||
msgid "Only For IPK Install Type Or Not Release Memory"
|
msgid "Only For IPK Install Type Or Not Release Memory"
|
||||||
msgstr "Solo se puede actualizar si se instaló mediante IPK; las versiones compiladas en el sistema no liberarán espacio tras actualizar."
|
msgstr "Solo para instalación IPK; en squashfs no se libera espacio"
|
||||||
|
|
||||||
msgid "Servers Manage"
|
msgid "Servers Manage"
|
||||||
msgstr "Gestionar servidores"
|
msgstr "Gestionar servidores"
|
||||||
@@ -814,7 +814,7 @@ msgid "Other Group (Support Regex)"
|
|||||||
msgstr "Incluir otros grupos (soporta expresiones regulares; sin duplicados)"
|
msgstr "Incluir otros grupos (soporta expresiones regulares; sin duplicados)"
|
||||||
|
|
||||||
msgid "The Added Proxy Groups Must Exist Except 'DIRECT' & 'REJECT' & 'REJECT-DROP' & 'PASS' & 'GLOBAL'"
|
msgid "The Added Proxy Groups Must Exist Except 'DIRECT' & 'REJECT' & 'REJECT-DROP' & 'PASS' & 'GLOBAL'"
|
||||||
msgstr "Nota: excepto 'DIRECT', 'REJECT', 'REJECT-DROP', 'PASS' y 'GLOBAL', los demás grupos deben existir antes de añadirlos."
|
msgstr "Excepto 'DIRECT', 'REJECT', 'REJECT-DROP', 'PASS' y 'GLOBAL', los demás grupos deben existir."
|
||||||
|
|
||||||
msgid "The Added Proxy Provider Must Exist"
|
msgid "The Added Proxy Provider Must Exist"
|
||||||
msgstr "El proveedor de proxy debe existir antes de añadirlo"
|
msgstr "El proveedor de proxy debe existir antes de añadirlo"
|
||||||
@@ -861,6 +861,18 @@ msgstr "Tamaño"
|
|||||||
msgid "Remove"
|
msgid "Remove"
|
||||||
msgstr "Eliminar"
|
msgstr "Eliminar"
|
||||||
|
|
||||||
|
msgid "Add Header"
|
||||||
|
msgstr "Añadir cabecera"
|
||||||
|
|
||||||
|
msgid "Add Param"
|
||||||
|
msgstr "Añadir parámetro"
|
||||||
|
|
||||||
|
msgid "Add custom HTTP headers to the subscription request"
|
||||||
|
msgstr "Añadir cabeceras HTTP personalizadas a la solicitud de suscripción"
|
||||||
|
|
||||||
|
msgid "Set environment variables for the overwrite script"
|
||||||
|
msgstr "Establecer variables de entorno para el script de sobrescritura"
|
||||||
|
|
||||||
msgid "(Enable or Disable Subscribe)"
|
msgid "(Enable or Disable Subscribe)"
|
||||||
msgstr "(Habilitar o deshabilitar suscripción)"
|
msgstr "(Habilitar o deshabilitar suscripción)"
|
||||||
|
|
||||||
@@ -940,10 +952,10 @@ msgid "Disable QUIC"
|
|||||||
msgstr "Deshabilitar QUIC"
|
msgstr "Deshabilitar QUIC"
|
||||||
|
|
||||||
msgid "Prevent YouTube and Others To Use QUIC Transmission"
|
msgid "Prevent YouTube and Others To Use QUIC Transmission"
|
||||||
msgstr "Evita que YouTube y otros usen QUIC, lo que puede mejorar la velocidad"
|
msgstr "Evita que YouTube y otros usen QUIC"
|
||||||
|
|
||||||
msgid "REJECT UDP Traffic(Not Include bypassed regions via China IP Route setting) On Port 443"
|
msgid "REJECT UDP Traffic(Not Include bypassed regions via China IP Route setting) On Port 443"
|
||||||
msgstr "Rechazar tráfico UDP en puerto 443 (excepto regiones omitidas). Evita QUIC según la ruta configurada."
|
msgstr "Rechazar UDP en puerto 443 (excepto regiones omitidas)"
|
||||||
|
|
||||||
msgid "Operation Mode"
|
msgid "Operation Mode"
|
||||||
msgstr "Modo de operación"
|
msgstr "Modo de operación"
|
||||||
@@ -1030,7 +1042,7 @@ msgid "Delete All File"
|
|||||||
msgstr "Eliminar todos los archivos"
|
msgstr "Eliminar todos los archivos"
|
||||||
|
|
||||||
msgid "SS/SSR/Vmess or Other Link And Subscription Address is Supported When Online Subscription Conversion is Enabled, Multiple Links Should be One Per Line or Separated By |"
|
msgid "SS/SSR/Vmess or Other Link And Subscription Address is Supported When Online Subscription Conversion is Enabled, Multiple Links Should be One Per Line or Separated By |"
|
||||||
msgstr "Si está activada la conversión de suscripción en línea, se admiten enlaces SS/SSR/Vmess y direcciones de suscripción. Coloca cada enlace en una línea o sepáralos con |"
|
msgstr "Con conversión online activa, se admiten enlaces SS/SSR/Vmess y suscripciones. Uno por línea o separados con |"
|
||||||
|
|
||||||
msgid "URI and subscription address is supported when online subscription conversion enabled, multiple links should be one per line or separated by"
|
msgid "URI and subscription address is supported when online subscription conversion enabled, multiple links should be one per line or separated by"
|
||||||
msgstr "Si la conversión está activada, se aceptan URIs y direcciones de suscripción. Varios enlaces: uno por línea o separados por el delimitador."
|
msgstr "Si la conversión está activada, se aceptan URIs y direcciones de suscripción. Varios enlaces: uno por línea o separados por el delimitador."
|
||||||
@@ -1210,25 +1222,25 @@ msgid "Save Nodes Selection Failed"
|
|||||||
msgstr "Error al guardar la selección de nodos"
|
msgstr "Error al guardar la selección de nodos"
|
||||||
|
|
||||||
msgid "after started, please wait patiently until the connection is normal"
|
msgid "after started, please wait patiently until the connection is normal"
|
||||||
msgstr "Una vez iniciado OpenClash, espera hasta que las pruebas de acceso sean normales."
|
msgstr "Tras iniciar, espera a que la conexión se normalice."
|
||||||
|
|
||||||
msgid "You can modify the profile on the profile page (for content that is not taken over)"
|
msgid "You can modify the profile on the profile page (for content that is not taken over)"
|
||||||
msgstr "Puedes modificar el archivo de configuración en la página correspondiente (solo parámetros no gestionados por OpenClash)."
|
msgstr "Modifica el perfil en su página (contenido no gestionado por OpenClash)."
|
||||||
|
|
||||||
msgid "do not write configuration files? Try to create one click on the server page"
|
msgid "do not write configuration files? Try to create one click on the server page"
|
||||||
msgstr "¿no sabes crear archivos de configuración? Usa la función de generación con un clic en la página de servidores."
|
msgstr "¿Sin archivo de configuración? Créalo con un clic en la página de servidores."
|
||||||
|
|
||||||
msgid "some website are abnormal? Try switching modes or using third-party rules"
|
msgid "some website are abnormal? Try switching modes or using third-party rules"
|
||||||
msgstr "Si algunas webs funcionan mal, prueba a cambiar de modo o usar reglas de terceros."
|
msgstr "¿Webs con problemas? Cambia de modo o usa reglas de terceros."
|
||||||
|
|
||||||
msgid "using the fake IP mode can get a faster access experience"
|
msgid "using the fake IP mode can get a faster access experience"
|
||||||
msgstr "El modo Fake-IP suele ofrecer mejor velocidad."
|
msgstr "El modo Fake-IP suele ofrecer mejor velocidad."
|
||||||
|
|
||||||
msgid "the nameserver group must have at least one server set when using custom DNS"
|
msgid "the nameserver group must have at least one server set when using custom DNS"
|
||||||
msgstr "Al usar DNS personalizados, el grupo NameServer debe tener al menos un servidor configurado."
|
msgstr "Con DNS personalizado, NameServer requiere al menos un servidor."
|
||||||
|
|
||||||
msgid "if you don not use IPv6, please turn off the DHCP service of IPv6, otherwise the connection will be abnormal"
|
msgid "if you don not use IPv6, please turn off the DHCP service of IPv6, otherwise the connection will be abnormal"
|
||||||
msgstr "Si no usas IPv6, desactiva su DHCP para evitar problemas de conexión."
|
msgstr "Si no usas IPv6, desactiva su DHCP."
|
||||||
|
|
||||||
msgid "you can update the version in the settings page"
|
msgid "you can update the version in the settings page"
|
||||||
msgstr "Puedes actualizar el plugin desde la página de ajustes."
|
msgstr "Puedes actualizar el plugin desde la página de ajustes."
|
||||||
@@ -1237,7 +1249,7 @@ msgid "Note: if the update fails, you can manually download and upload"
|
|||||||
msgstr "Nota: si la actualización falla, puedes descargar y subir el archivo manualmente."
|
msgstr "Nota: si la actualización falla, puedes descargar y subir el archivo manualmente."
|
||||||
|
|
||||||
msgid "Note: the client may not support update, because the firmware with squashfs format will not release flash space after updating"
|
msgid "Note: the client may not support update, because the firmware with squashfs format will not release flash space after updating"
|
||||||
msgstr "Nota: el cliente puede no actualizarse en firmwares squashfs, ya que no liberan espacio tras actualizar."
|
msgstr "Nota: en squashfs la actualización puede no liberar espacio flash."
|
||||||
|
|
||||||
msgid "Compiled Version"
|
msgid "Compiled Version"
|
||||||
msgstr "Versión compilada"
|
msgstr "Versión compilada"
|
||||||
@@ -1299,14 +1311,23 @@ msgstr "Restauración completada."
|
|||||||
msgid "Restore failed!"
|
msgid "Restore failed!"
|
||||||
msgstr "Error al restaurar la configuración."
|
msgstr "Error al restaurar la configuración."
|
||||||
|
|
||||||
msgid "Support syntax check, press"
|
msgid "Press"
|
||||||
msgstr "Admite comprobación de sintaxis; pulsa"
|
msgstr "Pulsa"
|
||||||
|
|
||||||
msgid "to control diff option, press"
|
msgid "for fullscreen,"
|
||||||
msgstr "para cambiar la vista de diferencia; pulsa"
|
msgstr "para pantalla completa,"
|
||||||
|
|
||||||
msgid "to enter full screen editing mode"
|
msgid "to exit fullscreen,"
|
||||||
msgstr "para entrar en modo de edición a pantalla completa"
|
msgstr "para salir,"
|
||||||
|
|
||||||
|
msgid "to zoom"
|
||||||
|
msgstr "zoom"
|
||||||
|
|
||||||
|
msgid "Mouse Wheel"
|
||||||
|
msgstr "Rueda del ratón"
|
||||||
|
|
||||||
|
msgid "to toggle differences,"
|
||||||
|
msgstr "para mostrar diferencias,"
|
||||||
|
|
||||||
msgid "Switch page to Fake-IP mode"
|
msgid "Switch page to Fake-IP mode"
|
||||||
msgstr "Cambiar página a modo Fake-IP"
|
msgstr "Cambiar página a modo Fake-IP"
|
||||||
@@ -1681,7 +1702,7 @@ msgid "Update Successful!"
|
|||||||
msgstr "Actualizado correctamente."
|
msgstr "Actualizado correctamente."
|
||||||
|
|
||||||
msgid "No Change, Do Nothing..."
|
msgid "No Change, Do Nothing..."
|
||||||
msgstr "Sin cambios, no hacer nada..."
|
msgstr "Sin cambios, omitido..."
|
||||||
|
|
||||||
msgid "Update Error, Please Try Again Later..."
|
msgid "Update Error, Please Try Again Later..."
|
||||||
msgstr "Error al actualizar; inténtalo más tarde..."
|
msgstr "Error al actualizar; inténtalo más tarde..."
|
||||||
@@ -1894,7 +1915,7 @@ msgid "Download Successful!"
|
|||||||
msgstr "Descarga completada."
|
msgstr "Descarga completada."
|
||||||
|
|
||||||
msgid "Switch To The New Proxy When The Delay Difference Between Old and The Fastest Currently is Greater Than This Value"
|
msgid "Switch To The New Proxy When The Delay Difference Between Old and The Fastest Currently is Greater Than This Value"
|
||||||
msgstr "Cambiar al nuevo proxy solo si la diferencia de latencia es mayor que este valor."
|
msgstr "Cambiar de proxy si la diferencia de latencia supera este valor."
|
||||||
|
|
||||||
msgid "URL-Test Group Tolerance"
|
msgid "URL-Test Group Tolerance"
|
||||||
msgstr "Tolerancia del grupo URL-Test"
|
msgstr "Tolerancia del grupo URL-Test"
|
||||||
@@ -1909,13 +1930,13 @@ msgid "Introduction to proxy-provider usage:"
|
|||||||
msgstr "Introducción al uso de proveedores de proxy:"
|
msgstr "Introducción al uso de proveedores de proxy:"
|
||||||
|
|
||||||
msgid "Subconverter external configuration (subscription conversion template) Description: https://github.com/tindy2013/subconverter#external-configuration-file"
|
msgid "Subconverter external configuration (subscription conversion template) Description: https://github.com/tindy2013/subconverter#external-configuration-file"
|
||||||
msgstr "Descripción del archivo de configuración externa para subconverter: https://github.com/tindy2013/subconverter#external-configuration-file"
|
msgstr "Plantilla externa subconverter: https://github.com/tindy2013/subconverter#external-configuration-file"
|
||||||
|
|
||||||
msgid "If you need to customize the external configuration file (subscription conversion template), please write it according to the instructions, upload it to the accessible location of the external network, and fill in the address correctly when using it"
|
msgid "If you need to customize the external configuration file (subscription conversion template), please write it according to the instructions, upload it to the accessible location of the external network, and fill in the address correctly when using it"
|
||||||
msgstr "Para crear una plantilla personalizada, edítala siguiendo las instrucciones, súbela a una URL accesible y usa esa dirección."
|
msgstr "Crea tu plantilla según las instrucciones, súbela a una URL pública y usa esa dirección."
|
||||||
|
|
||||||
msgid "If you have a recommended external configuration file (subscription conversion template), you can modify by following The file format of /usr/share/openclash/res/sub_ini.list and pr"
|
msgid "If you have a recommended external configuration file (subscription conversion template), you can modify by following The file format of /usr/share/openclash/res/sub_ini.list and pr"
|
||||||
msgstr "Si quieres aportar una plantilla recomendada, modifícala siguiendo el formato de /usr/share/openclash/res/sub_ini.list y envía un PR."
|
msgstr "Para contribuir, sigue el formato de /usr/share/openclash/res/sub_ini.list y envía un PR."
|
||||||
|
|
||||||
msgid "Note: To restore the default configuration, try accessing:"
|
msgid "Note: To restore the default configuration, try accessing:"
|
||||||
msgstr "Nota: para restaurar la configuración por defecto, accede a:"
|
msgstr "Nota: para restaurar la configuración por defecto, accede a:"
|
||||||
@@ -2004,8 +2025,8 @@ msgstr "¡Cambio realizado con éxito!"
|
|||||||
msgid "switching failed!"
|
msgid "switching failed!"
|
||||||
msgstr "¡El cambio ha fallado!"
|
msgstr "¡El cambio ha fallado!"
|
||||||
|
|
||||||
msgid "Current Config File"
|
msgid "Current Config"
|
||||||
msgstr "Archivo de configuración actual"
|
msgstr "Configuración actual"
|
||||||
|
|
||||||
msgid "Up"
|
msgid "Up"
|
||||||
msgstr "Subida"
|
msgstr "Subida"
|
||||||
@@ -2262,8 +2283,8 @@ msgstr "Sugerencia: si el dispositivo no tiene WLAN, desactiva la opción de pue
|
|||||||
msgid "Github Address Modify"
|
msgid "Github Address Modify"
|
||||||
msgstr "Modificar dirección de Github"
|
msgstr "Modificar dirección de Github"
|
||||||
|
|
||||||
msgid "Modify The Github Address In The Config And OpenClash With Proxy(CDN) To Prevent File Download Faild. Format Reference:"
|
msgid "Modify The Github Address In The Config And OpenClash With Proxy(CDN) To Prevent File Download Failed. Format Reference:"
|
||||||
msgstr "Permite reemplazar las direcciones de Github en OpenClash y en la configuración utilizando un proxy/CDN para evitar fallos de descarga. Formato de referencia:"
|
msgstr "Reemplaza las URLs de Github con un proxy/CDN para evitar fallos de descarga. Formato:"
|
||||||
|
|
||||||
msgid "File Edit"
|
msgid "File Edit"
|
||||||
msgstr "Edición de archivos"
|
msgstr "Edición de archivos"
|
||||||
@@ -2275,7 +2296,7 @@ msgid "Create File"
|
|||||||
msgstr "Crear archivo"
|
msgstr "Crear archivo"
|
||||||
|
|
||||||
msgid "You are editing the overwrite script, please note that some settings may cause the abnormal, be careful with the modification!"
|
msgid "You are editing the overwrite script, please note that some settings may cause the abnormal, be careful with the modification!"
|
||||||
msgstr "Estás editando el script de sobrescritura; algunos cambios pueden causar fallos. Modifica con precaución."
|
msgstr "Editando script de sobrescritura. ¡Ciertos cambios pueden causar fallos, precaución!"
|
||||||
|
|
||||||
msgid "Paste the name of the new file (including the extension) here:"
|
msgid "Paste the name of the new file (including the extension) here:"
|
||||||
msgstr "Introduce aquí el nombre del nuevo archivo (con extensión):"
|
msgstr "Introduce aquí el nombre del nuevo archivo (con extensión):"
|
||||||
@@ -2331,11 +2352,20 @@ msgstr "Parámetros personalizados"
|
|||||||
msgid "eg: \"rename=match@replace\" , \"rename=\\s+([2-9])[xX]@ (HIGH:$1)\""
|
msgid "eg: \"rename=match@replace\" , \"rename=\\s+([2-9])[xX]@ (HIGH:$1)\""
|
||||||
msgstr "Ejemplo: \"rename=match@replace\" , \"rename=\\s+([2-9])[xX]@ (ALTO:$1)\""
|
msgstr "Ejemplo: \"rename=match@replace\" , \"rename=\\s+([2-9])[xX]@ (ALTO:$1)\""
|
||||||
|
|
||||||
|
msgid "Custom Headers"
|
||||||
|
msgstr "Cabeceras personalizadas"
|
||||||
|
|
||||||
|
msgid "Custom HTTP request headers, one per line, format: Header-Name: value"
|
||||||
|
msgstr "Cabeceras HTTP personalizadas, una por línea, formato: Nombre-Cabecera: valor"
|
||||||
|
|
||||||
|
msgid "eg: x-hwid: device-001, one header per line, format: Name: value"
|
||||||
|
msgstr "Ej: x-hwid: device-001, una cabecera por línea, formato: Nombre: valor"
|
||||||
|
|
||||||
msgid "Use Rule Provider"
|
msgid "Use Rule Provider"
|
||||||
msgstr "Usar proveedor de reglas"
|
msgstr "Usar proveedor de reglas"
|
||||||
|
|
||||||
msgid "Note: Please Make Sure Backend Service Supports This Feature"
|
msgid "Note: Please Make Sure Backend Service Supports This Feature"
|
||||||
msgstr "Nota: asegúrate de que tu backend admite esta función, de lo contrario podría fallar el inicio del núcleo."
|
msgstr "Nota: asegúrate de que tu backend soporte esta función."
|
||||||
|
|
||||||
msgid "Rename"
|
msgid "Rename"
|
||||||
msgstr "Renombrar"
|
msgstr "Renombrar"
|
||||||
@@ -2355,6 +2385,12 @@ msgstr "Prueba de desbloqueo (selección)"
|
|||||||
msgid "All Proxies Test"
|
msgid "All Proxies Test"
|
||||||
msgstr "Probar todos los nodos"
|
msgstr "Probar todos los nodos"
|
||||||
|
|
||||||
|
msgid "Unlock Test Result"
|
||||||
|
msgstr "Resultado de la prueba de desbloqueo"
|
||||||
|
|
||||||
|
msgid "All Proxies Test Result"
|
||||||
|
msgstr "Resultado de la prueba de todos los nodos"
|
||||||
|
|
||||||
msgid "Something Wrong While Testing..."
|
msgid "Something Wrong While Testing..."
|
||||||
msgstr "Algo ha fallado durante la prueba..."
|
msgstr "Algo ha fallado durante la prueba..."
|
||||||
|
|
||||||
@@ -2377,7 +2413,7 @@ msgid "Rule Mode"
|
|||||||
msgstr "Modo de regla"
|
msgstr "Modo de regla"
|
||||||
|
|
||||||
msgid "ALL Functions In Stream Enhance Tag Will Not Work After Disable"
|
msgid "ALL Functions In Stream Enhance Tag Will Not Work After Disable"
|
||||||
msgstr "Si se desactiva, todas las funciones del apartado «mejora de streaming» dejarán de estar disponibles."
|
msgstr "Al desactivar, todas las funciones de «mejora de streaming» se deshabilitan."
|
||||||
|
|
||||||
msgid "Set Router Self Proxy Rule Failed,"
|
msgid "Set Router Self Proxy Rule Failed,"
|
||||||
msgstr "Fallo al configurar la regla de proxy del router,"
|
msgstr "Fallo al configurar la regla de proxy del router,"
|
||||||
@@ -2440,13 +2476,13 @@ msgid "Update GeoIP Dat"
|
|||||||
msgstr "Actualizar GeoIP Dat"
|
msgstr "Actualizar GeoIP Dat"
|
||||||
|
|
||||||
msgid "Note: It is not recommended to enable IPv6 and related services for routing. Most of the network connection problems reported so far are related to it"
|
msgid "Note: It is not recommended to enable IPv6 and related services for routing. Most of the network connection problems reported so far are related to it"
|
||||||
msgstr "Nota: no se recomienda activar IPv6 ni sus servicios en el router; la mayoría de problemas reportados están relacionados con ello."
|
msgstr "Nota: no se recomienda activar IPv6 en el router; la mayoría de fallos reportados vienen de ahí."
|
||||||
|
|
||||||
msgid "Note: Turning on secure DNS in the browser will cause abnormal shunting, please be careful to turn it off"
|
msgid "Note: Turning on secure DNS in the browser will cause abnormal shunting, please be careful to turn it off"
|
||||||
msgstr "Nota: activar DNS seguro en el navegador puede causar problemas de enrutamiento; se recomienda desactivarlo."
|
msgstr "Nota: el DNS seguro del navegador puede causar fallos; desactívalo."
|
||||||
|
|
||||||
msgid "Note: Some software will modify the device HOSTS, which will cause abnormal shunt, please pay attention to check"
|
msgid "Note: Some software will modify the device HOSTS, which will cause abnormal shunt, please pay attention to check"
|
||||||
msgstr "Nota: algunos programas modifican el archivo HOSTS del dispositivo y causan problemas de enrutamiento. Revisa si es necesario."
|
msgstr "Nota: algunos programas modifican los HOSTS y causan fallos. Revísalo."
|
||||||
|
|
||||||
msgid "Note: The default proxy routes local traffic, BT, PT download, etc., please use Redir-Host mode as much as possible and pay attention to traffic avoidance"
|
msgid "Note: The default proxy routes local traffic, BT, PT download, etc., please use Redir-Host mode as much as possible and pay attention to traffic avoidance"
|
||||||
msgstr "Nota: el proxy por defecto procesa tráfico local, BT, PT, etc.; usa Redir-Host siempre que sea posible."
|
msgstr "Nota: el proxy por defecto procesa tráfico local, BT, PT, etc.; usa Redir-Host siempre que sea posible."
|
||||||
@@ -2569,7 +2605,7 @@ msgid "Close Old Connections"
|
|||||||
msgstr "Cerrar conexiones antiguas"
|
msgstr "Cerrar conexiones antiguas"
|
||||||
|
|
||||||
msgid "Automatically Close Old Connections When New Unlock Node Selected"
|
msgid "Automatically Close Old Connections When New Unlock Node Selected"
|
||||||
msgstr "Cierra automáticamente las conexiones del grupo al seleccionar un nuevo nodo de desbloqueo"
|
msgstr "Cerrar conexiones antiguas al cambiar de nodo"
|
||||||
|
|
||||||
msgid "Append Default DNS"
|
msgid "Append Default DNS"
|
||||||
msgstr "Añadir DNS predeterminado"
|
msgstr "Añadir DNS predeterminado"
|
||||||
@@ -2641,7 +2677,7 @@ msgid "Core Start Failed, Please Check The Log Infos!"
|
|||||||
msgstr "Fallo al iniciar el núcleo. Revisa el registro de núcleo."
|
msgstr "Fallo al iniciar el núcleo. Revisa el registro de núcleo."
|
||||||
|
|
||||||
msgid "Core Initial Configuration Timeout, Please Check The Log Infos!"
|
msgid "Core Initial Configuration Timeout, Please Check The Log Infos!"
|
||||||
msgstr "Tiempo de espera agotado en la configuración inicial del núcleo, ¡consulta la información del registro!"
|
msgstr "Timeout en configuración inicial del núcleo. ¡Revisa el log!"
|
||||||
|
|
||||||
msgid "Forced Sniff Pure IP Connections"
|
msgid "Forced Sniff Pure IP Connections"
|
||||||
msgstr "Forzar sniffing de conexiones IP puras"
|
msgstr "Forzar sniffing de conexiones IP puras"
|
||||||
@@ -2668,7 +2704,7 @@ msgid "1. Before modifying the configuration file, please click the button below
|
|||||||
msgstr "1. Antes de editar el archivo de configuración, pulsa el botón inferior para cargarlo."
|
msgstr "1. Antes de editar el archivo de configuración, pulsa el botón inferior para cargarlo."
|
||||||
|
|
||||||
msgid "2. Proxy-providers address can be directly filled in the subscription link"
|
msgid "2. Proxy-providers address can be directly filled in the subscription link"
|
||||||
msgstr "2. La dirección de un proveedor de proxy puede ser directamente un enlace de suscripción."
|
msgstr "2. La URL de un proxy-provider puede ser un enlace de suscripción."
|
||||||
|
|
||||||
msgid "Edit URL-Test URL Failed,"
|
msgid "Edit URL-Test URL Failed,"
|
||||||
msgstr "Fallo al modificar la URL de URL-Test,"
|
msgstr "Fallo al modificar la URL de URL-Test,"
|
||||||
@@ -2800,10 +2836,10 @@ msgid "IPv6 Proxy Mode is Mix..."
|
|||||||
msgstr "El modo proxy IPv6 es Mixto..."
|
msgstr "El modo proxy IPv6 es Mixto..."
|
||||||
|
|
||||||
msgid "Can't Settting Only Intranet Allowed Function, Get IPv4 WAN Interfaces error, Please Verify The Firewall's WAN Zone Name is wan, Ignore This IF The Device Does not Have a WAN Interfaces..."
|
msgid "Can't Settting Only Intranet Allowed Function, Get IPv4 WAN Interfaces error, Please Verify The Firewall's WAN Zone Name is wan, Ignore This IF The Device Does not Have a WAN Interfaces..."
|
||||||
msgstr "Fallo al activar la función «solo intranet». No se pudo obtener la interfaz WAN IPv4. Comprueba que la zona WAN en el cortafuegos se llama «wan». Si el dispositivo no tiene interfaz WAN, ignora este aviso."
|
msgstr "Fallo en «solo intranet»: no se detectó WAN IPv4. Verifica que la zona WAN del firewall se llame «wan». Ignora si no hay WAN."
|
||||||
|
|
||||||
msgid "Can't Settting Only Intranet Allowed Function, Get IPv6 WAN Interfaces error, Please Verify The Firewall's WAN Zone Name is wan, Ignore This IF The Device Does not Have a WAN Interfaces..."
|
msgid "Can't Settting Only Intranet Allowed Function, Get IPv6 WAN Interfaces error, Please Verify The Firewall's WAN Zone Name is wan, Ignore This IF The Device Does not Have a WAN Interfaces..."
|
||||||
msgstr "Fallo al activar la función «solo intranet». No se pudo obtener la interfaz WAN IPv6. Comprueba que la zona WAN en el cortafuegos se llama «wan». Si el dispositivo no tiene interfaz WAN, ignora este aviso."
|
msgstr "Fallo en «solo intranet»: no se detectó WAN IPv6. Verifica que la zona WAN del firewall se llame «wan». Ignora si no hay WAN."
|
||||||
|
|
||||||
msgid "Config File Download Successful, Test If There is Any Errors..."
|
msgid "Config File Download Successful, Test If There is Any Errors..."
|
||||||
msgstr "Archivo de configuración descargado correctamente. Probando si hay errores..."
|
msgstr "Archivo de configuración descargado correctamente. Probando si hay errores..."
|
||||||
@@ -2832,6 +2868,21 @@ msgstr "Edita aquí tus parámetros adicionales"
|
|||||||
msgid "Config Not Found, Switch Config File to"
|
msgid "Config Not Found, Switch Config File to"
|
||||||
msgstr "No se encontró el archivo de configuración; cambiando al archivo de configuración"
|
msgstr "No se encontró el archivo de configuración; cambiando al archivo de configuración"
|
||||||
|
|
||||||
|
msgid "Empty URL"
|
||||||
|
msgstr "URL vacía"
|
||||||
|
|
||||||
|
msgid "Only HTTP/HTTPS URLs are supported"
|
||||||
|
msgstr "Solo se admiten URL HTTP/HTTPS"
|
||||||
|
|
||||||
|
msgid "Invalid URL format"
|
||||||
|
msgstr "Formato de URL no válido"
|
||||||
|
|
||||||
|
msgid "URL missing hostname"
|
||||||
|
msgstr "La URL no tiene nombre de host"
|
||||||
|
|
||||||
|
msgid "Invalid URL on line"
|
||||||
|
msgstr "URL no válida"
|
||||||
|
|
||||||
msgid "Enable Unified Delay"
|
msgid "Enable Unified Delay"
|
||||||
msgstr "Activar cálculo unificado de latencia"
|
msgstr "Activar cálculo unificado de latencia"
|
||||||
|
|
||||||
@@ -2866,7 +2917,7 @@ msgid "Respect Rules"
|
|||||||
msgstr "Respetar reglas"
|
msgstr "Respetar reglas"
|
||||||
|
|
||||||
msgid "Whether or not The Connection to the DNS Server Follow the Rules in Config"
|
msgid "Whether or not The Connection to the DNS Server Follow the Rules in Config"
|
||||||
msgstr "Indica si la conexión al servidor DNS debe seguir las reglas establecidas en la configuración."
|
msgstr "La conexión al DNS sigue las reglas de la configuración."
|
||||||
|
|
||||||
msgid "To Use in Fake-IP Mode, Please Switch The Dns Redirect Mode To Firewall Forwarding"
|
msgid "To Use in Fake-IP Mode, Please Switch The Dns Redirect Mode To Firewall Forwarding"
|
||||||
msgstr "Para usar esta función en modo Fake-IP, cambia el redireccionamiento DNS a reenvío por firewall."
|
msgstr "Para usar esta función en modo Fake-IP, cambia el redireccionamiento DNS a reenvío por firewall."
|
||||||
@@ -2887,7 +2938,7 @@ msgid "Type CDN URL, Format Like"
|
|||||||
msgstr "Introduce la URL del CDN, con formato tipo"
|
msgstr "Introduce la URL del CDN, con formato tipo"
|
||||||
|
|
||||||
msgid "Please enter a valid URL!"
|
msgid "Please enter a valid URL!"
|
||||||
msgstr "Por favor, introduce una URL válida."
|
msgstr "¡Introduce una URL válida!"
|
||||||
|
|
||||||
msgid "WAN Interface Name"
|
msgid "WAN Interface Name"
|
||||||
msgstr "Nombre de la interfaz WAN"
|
msgstr "Nombre de la interfaz WAN"
|
||||||
@@ -2905,10 +2956,10 @@ msgid "For More Useful Meta Core Functions Go Wiki"
|
|||||||
msgstr "Consulta el Wiki para más funciones del núcleo Meta"
|
msgstr "Consulta el Wiki para más funciones del núcleo Meta"
|
||||||
|
|
||||||
msgid "Because Need Ensure Bypassing IP Option Work, Deleted The Fake-IP-Filter Rule"
|
msgid "Because Need Ensure Bypassing IP Option Work, Deleted The Fake-IP-Filter Rule"
|
||||||
msgstr "Para garantizar que la omisión IP funcione, se ha eliminado la regla de Fake-IP-Filter."
|
msgstr "Omisión IP: regla Fake-IP-Filter eliminada."
|
||||||
|
|
||||||
msgid "Because Need Ensure Bypassing IP Option Work, Added The Fake-IP-Filter Rule"
|
msgid "Because Need Ensure Bypassing IP Option Work, Added The Fake-IP-Filter Rule"
|
||||||
msgstr "Para garantizar que la omisión IP funcione, se ha añadido la regla de Fake-IP-Filter."
|
msgstr "Omisión IP: regla Fake-IP-Filter añadida."
|
||||||
|
|
||||||
msgid "Fake-IP is not returned if the matching succeeds when blacklist mode or Fake-IP is returned if the matching succeeds when whitelist mode"
|
msgid "Fake-IP is not returned if the matching succeeds when blacklist mode or Fake-IP is returned if the matching succeeds when whitelist mode"
|
||||||
msgstr "En modo lista negra: si coincide, no se devuelve Fake-IP. En modo lista blanca: solo si coincide se devuelve Fake-IP."
|
msgstr "En modo lista negra: si coincide, no se devuelve Fake-IP. En modo lista blanca: solo si coincide se devuelve Fake-IP."
|
||||||
@@ -2947,13 +2998,13 @@ msgid "Override the ECS Subnet Address"
|
|||||||
msgstr "Sobrescribir la subred ECS en consultas DNS"
|
msgstr "Sobrescribir la subred ECS en consultas DNS"
|
||||||
|
|
||||||
msgid "Need Proxy-server-nameserver Option Must Be Setted, Auto Set to"
|
msgid "Need Proxy-server-nameserver Option Must Be Setted, Auto Set to"
|
||||||
msgstr "necesidad proxy-server-nameserver debe estar configurado. Se ajustará automáticamente a"
|
msgstr "proxy-server-nameserver requerido; auto-ajustado a"
|
||||||
|
|
||||||
msgid "Nameserver Option Maybe All Setted The Proxy Option, Auto Set Proxy-server-nameserver Option to"
|
msgid "Nameserver Option Maybe All Setted The Proxy Option, Auto Set Proxy-server-nameserver Option to"
|
||||||
msgstr "Los servidores nameserver podrían estar todos usando proxy. Se ajustará automáticamente proxy-server-nameserver a"
|
msgstr "Nameservers en modo proxy; ajustando proxy-server-nameserver a"
|
||||||
|
|
||||||
msgid "Proxy-server-nameserver Option Maybe All Setted The Proxy Option, Auto Set Proxy-server-nameserver Option to"
|
msgid "Proxy-server-nameserver Option Maybe All Setted The Proxy Option, Auto Set Proxy-server-nameserver Option to"
|
||||||
msgstr "Proxy-server-nameserver podría estar completamente en modo proxy. Se añadirá configuración automáticamente."
|
msgstr "Proxy-server-nameserver en modo proxy; configurando automáticamente."
|
||||||
|
|
||||||
msgid "For Avoiding Proxies Server Resolve Loop..."
|
msgid "For Avoiding Proxies Server Resolve Loop..."
|
||||||
msgstr "Para evitar bucles de resolución en servidores proxy..."
|
msgstr "Para evitar bucles de resolución en servidores proxy..."
|
||||||
@@ -3178,7 +3229,7 @@ msgid "Proxy service not available, please try again later"
|
|||||||
msgstr "Servicio proxy no disponible, inténtalo de nuevo más tarde"
|
msgstr "Servicio proxy no disponible, inténtalo de nuevo más tarde"
|
||||||
|
|
||||||
msgid "No authentication configured, please be aware of the risk of information leakage!"
|
msgid "No authentication configured, please be aware of the risk of information leakage!"
|
||||||
msgstr "No hay autenticación configurada. Ten en cuenta el riesgo de fuga de información."
|
msgstr "¡Sin autenticación, riesgo de fuga de datos!"
|
||||||
|
|
||||||
msgid "Other"
|
msgid "Other"
|
||||||
msgstr "Otros"
|
msgstr "Otros"
|
||||||
@@ -3238,7 +3289,7 @@ msgid "Config Name"
|
|||||||
msgstr "Nombre de configuración"
|
msgstr "Nombre de configuración"
|
||||||
|
|
||||||
msgid "Enter config name (without extension)"
|
msgid "Enter config name (without extension)"
|
||||||
msgstr "Introduzca el nombre de configuración (sin extensión)"
|
msgstr "Introduce el nombre de configuración (sin extensión)"
|
||||||
|
|
||||||
msgid "Processing..."
|
msgid "Processing..."
|
||||||
msgstr "Procesando..."
|
msgstr "Procesando..."
|
||||||
@@ -3360,12 +3411,6 @@ msgstr "Cargando archivo de configuración..."
|
|||||||
msgid "Ready"
|
msgid "Ready"
|
||||||
msgstr "Listo"
|
msgstr "Listo"
|
||||||
|
|
||||||
msgid "Press F11 for fullscreen, Esc to exit fullscreen, Ctrl+Mouse Wheel to zoom"
|
|
||||||
msgstr "Pulsa F11 para pantalla completa, Esc para salir, Ctrl + rueda del ratón para zoom"
|
|
||||||
|
|
||||||
msgid "Press F10 to toggle differences, F11 for fullscreen, Esc to exit fullscreen, Ctrl+Mouse Wheel to zoom"
|
|
||||||
msgstr "Pulsa F10 para mostrar diferencias, F11 para pantalla completa, Esc para salir, Ctrl + rueda del ratón para zoom"
|
|
||||||
|
|
||||||
msgid "Compare mode: left(Original Config), right(Runtime Config)"
|
msgid "Compare mode: left(Original Config), right(Runtime Config)"
|
||||||
msgstr "Modo comparación: izquierda (configuración original), derecha (configuración en ejecución)"
|
msgstr "Modo comparación: izquierda (configuración original), derecha (configuración en ejecución)"
|
||||||
|
|
||||||
@@ -3810,9 +3855,6 @@ msgstr "Deshabilitar reutilización de la conexión"
|
|||||||
msgid "Write file failed:"
|
msgid "Write file failed:"
|
||||||
msgstr "Fallo al escribir el archivo:"
|
msgstr "Fallo al escribir el archivo:"
|
||||||
|
|
||||||
msgid "Fix short-id values type failed:"
|
|
||||||
msgstr "Fallo al modificar el tipo de valores short-id:"
|
|
||||||
|
|
||||||
msgid "Interface"
|
msgid "Interface"
|
||||||
msgstr "Interfaz"
|
msgstr "Interfaz"
|
||||||
|
|
||||||
@@ -3829,13 +3871,13 @@ msgid "Load YAML Override Block"
|
|||||||
msgstr "Cargar bloque de sobrescritura YAML"
|
msgstr "Cargar bloque de sobrescritura YAML"
|
||||||
|
|
||||||
msgid "Enter YAML configuration..."
|
msgid "Enter YAML configuration..."
|
||||||
msgstr "Ingrese configuración YAML..."
|
msgstr "Introduce configuración YAML..."
|
||||||
|
|
||||||
msgid "Enter shell script..."
|
msgid "Enter shell script..."
|
||||||
msgstr "Ingrese script de shell..."
|
msgstr "Introduce script de shell..."
|
||||||
|
|
||||||
msgid "Enter configuration..."
|
msgid "Enter configuration..."
|
||||||
msgstr "Ingrese configuración..."
|
msgstr "Introduce configuración..."
|
||||||
|
|
||||||
msgid "Edit original config..."
|
msgid "Edit original config..."
|
||||||
msgstr "Editar configuración original..."
|
msgstr "Editar configuración original..."
|
||||||
@@ -3849,9 +3891,6 @@ msgstr "Formato de sobrescritura YAML no válido, omitido..."
|
|||||||
msgid "Parse YAML Override failed:"
|
msgid "Parse YAML Override failed:"
|
||||||
msgstr "Error al analizar bloque de sobrescritura YAML:"
|
msgstr "Error al analizar bloque de sobrescritura YAML:"
|
||||||
|
|
||||||
msgid "YAML overwrite failed:"
|
|
||||||
msgstr "Error en la sobrescritura YAML:"
|
|
||||||
|
|
||||||
msgid "files selected"
|
msgid "files selected"
|
||||||
msgstr "archivos seleccionados"
|
msgstr "archivos seleccionados"
|
||||||
|
|
||||||
@@ -3876,16 +3915,25 @@ msgstr "Fallo en intento de descifrado con una clave encontrada:"
|
|||||||
msgid "Encrypt attempt failed:"
|
msgid "Encrypt attempt failed:"
|
||||||
msgstr "Fallo en intento de cifrado:"
|
msgstr "Fallo en intento de cifrado:"
|
||||||
|
|
||||||
msgid "Official Website"
|
msgid "oixCloud Website"
|
||||||
msgstr "Sitio web oficial"
|
msgstr "Sitio web oficial"
|
||||||
|
|
||||||
msgid "Login..."
|
msgid "Login..."
|
||||||
msgstr "Iniciando sesión..."
|
msgstr "Iniciando sesión..."
|
||||||
|
|
||||||
|
msgid "Logout..."
|
||||||
|
msgstr "Cerrando sesión..."
|
||||||
|
|
||||||
|
msgid "Checkin..."
|
||||||
|
msgstr "Registrando..."
|
||||||
|
|
||||||
msgid "oixCloud Login Successful"
|
msgid "oixCloud Login Successful"
|
||||||
msgstr "Inicio de sesión en oixCloud exitoso"
|
msgstr "Inicio de sesión en oixCloud exitoso"
|
||||||
|
|
||||||
msgid "oixCloud Login Faild"
|
msgid "Note: oixCloud need a specific core installed, OpenClash will auto download, After the core start, an oixCloud nodes provider will be added, which you can customize as needed"
|
||||||
|
msgstr "Nota: oixCloud requiere un núcleo específico. OpenClash lo descargará y añadirá un proveedor de nodos personalizable."
|
||||||
|
|
||||||
|
msgid "oixCloud Login Failed"
|
||||||
msgstr "Fallo al iniciar sesión en oixCloud"
|
msgstr "Fallo al iniciar sesión en oixCloud"
|
||||||
|
|
||||||
msgid "Login Account"
|
msgid "Login Account"
|
||||||
@@ -3894,7 +3942,7 @@ msgstr "Iniciar sesión en la cuenta"
|
|||||||
msgid "oixCloud Logout Successful"
|
msgid "oixCloud Logout Successful"
|
||||||
msgstr "Cierre de sesión en oixCloud exitoso"
|
msgstr "Cierre de sesión en oixCloud exitoso"
|
||||||
|
|
||||||
msgid "oixCloud Logout Faild"
|
msgid "oixCloud Logout Failed"
|
||||||
msgstr "Fallo al cerrar sesión en oixCloud"
|
msgstr "Fallo al cerrar sesión en oixCloud"
|
||||||
|
|
||||||
msgid "Logout Account"
|
msgid "Logout Account"
|
||||||
@@ -3903,18 +3951,6 @@ msgstr "Cerrar sesión en la cuenta"
|
|||||||
msgid "Account Login"
|
msgid "Account Login"
|
||||||
msgstr "Inicio de sesión de cuenta"
|
msgstr "Inicio de sesión de cuenta"
|
||||||
|
|
||||||
msgid "Account logged in"
|
|
||||||
msgstr "Cuenta iniciada"
|
|
||||||
|
|
||||||
msgid "Account not logged in"
|
|
||||||
msgstr "Cuenta no iniciada"
|
|
||||||
|
|
||||||
msgid "Logout..."
|
|
||||||
msgstr "Cerrando sesión..."
|
|
||||||
|
|
||||||
msgid "Error Login Info"
|
|
||||||
msgstr "Información de inicio de sesión incorrecta"
|
|
||||||
|
|
||||||
msgid "Simple & trustworthy"
|
msgid "Simple & trustworthy"
|
||||||
msgstr "Simple y confiable"
|
msgstr "Simple y confiable"
|
||||||
|
|
||||||
@@ -3957,17 +3993,14 @@ msgstr "Tráfico restante"
|
|||||||
msgid "Plan Traffic"
|
msgid "Plan Traffic"
|
||||||
msgstr "Tráfico del plan"
|
msgstr "Tráfico del plan"
|
||||||
|
|
||||||
msgid "Checkin"
|
|
||||||
msgstr "Probar suerte"
|
|
||||||
|
|
||||||
msgid "oixCloud Account Login Failed! Please Check And Try Again..."
|
msgid "oixCloud Account Login Failed! Please Check And Try Again..."
|
||||||
msgstr "¡Fallo al iniciar sesión en oixCloud! Verifique los datos e intente de nuevo..."
|
msgstr "¡Fallo al iniciar sesión en oixCloud! Verifica los datos e inténtalo de nuevo."
|
||||||
|
|
||||||
msgid "oixCloud Account Login Failed, The Error Info is"
|
msgid "oixCloud Account Login Failed, The Error Info is"
|
||||||
msgstr "Fallo al iniciar sesión en oixCloud, el error es"
|
msgstr "Fallo al iniciar sesión en oixCloud, el error es"
|
||||||
|
|
||||||
msgid "oixCloud Checkin Failed! Please Check And Try Again..."
|
msgid "oixCloud Checkin Failed! Please Check And Try Again..."
|
||||||
msgstr "¡Fallo al registrar asistencia en oixCloud! Intente de nuevo más tarde..."
|
msgstr "¡Fallo al registrar en oixCloud! Inténtalo de nuevo más tarde."
|
||||||
|
|
||||||
msgid "Account Email Address"
|
msgid "Account Email Address"
|
||||||
msgstr "Correo electrónico de la cuenta"
|
msgstr "Correo electrónico de la cuenta"
|
||||||
@@ -3975,14 +4008,41 @@ msgstr "Correo electrónico de la cuenta"
|
|||||||
msgid "Account Password"
|
msgid "Account Password"
|
||||||
msgstr "Contraseña de la cuenta"
|
msgstr "Contraseña de la cuenta"
|
||||||
|
|
||||||
msgid "Checkin Interval (hour)"
|
|
||||||
msgstr "Intervalo de registro (horas)"
|
|
||||||
|
|
||||||
msgid "Checkin Multiple"
|
msgid "Checkin Multiple"
|
||||||
msgstr "Multiplicador de registro"
|
msgstr "Multiplicador de registro"
|
||||||
|
|
||||||
msgid "Multiple Must Be a Positive Integer and No More Than 100"
|
msgid "Optional Parameters"
|
||||||
msgstr "El multiplicador debe ser un número entero positivo no mayor a 100"
|
msgstr "Parámetros opcionales"
|
||||||
|
|
||||||
|
msgid "Optional parameters saved"
|
||||||
|
msgstr "Parámetros opcionales guardados"
|
||||||
|
|
||||||
|
msgid "Failed to save optional parameters, please try again"
|
||||||
|
msgstr "Error al guardar parámetros opcionales, inténtelo de nuevo"
|
||||||
|
|
||||||
|
msgid "For more information, please visit the"
|
||||||
|
msgstr "Para más información, visite la"
|
||||||
|
|
||||||
|
msgid "official documentation"
|
||||||
|
msgstr "documentación oficial"
|
||||||
|
|
||||||
|
msgid "Must start with &"
|
||||||
|
msgstr "Debe comenzar con &"
|
||||||
|
|
||||||
|
msgid "Params must not contain spaces"
|
||||||
|
msgstr "Los parámetros no deben contener espacios"
|
||||||
|
|
||||||
|
msgid "Params too long, max 8192 characters"
|
||||||
|
msgstr "Parámetros demasiado largos, máximo 8192 caracteres"
|
||||||
|
|
||||||
|
msgid "Invalid params format"
|
||||||
|
msgstr "Formato de parámetros no válido"
|
||||||
|
|
||||||
|
msgid "Invalid params format, must start with & and use key=value pairs"
|
||||||
|
msgstr "Formato de parámetros no válido, debe comenzar con & y usar pares clave=valor"
|
||||||
|
|
||||||
|
msgid "Params too long"
|
||||||
|
msgstr "Parámetros demasiado largos"
|
||||||
|
|
||||||
msgid "Usage Help"
|
msgid "Usage Help"
|
||||||
msgstr "Ayuda de uso"
|
msgstr "Ayuda de uso"
|
||||||
@@ -3990,29 +4050,44 @@ msgstr "Ayuda de uso"
|
|||||||
msgid "Copy the following text to any AI (ChatGPT, DeepSeek, etc.) to get usage help for OpenClash:"
|
msgid "Copy the following text to any AI (ChatGPT, DeepSeek, etc.) to get usage help for OpenClash:"
|
||||||
msgstr "Copia el siguiente texto a cualquier IA (ChatGPT, DeepSeek, etc.) para obtener ayuda de uso de OpenClash:"
|
msgstr "Copia el siguiente texto a cualquier IA (ChatGPT, DeepSeek, etc.) para obtener ayuda de uso de OpenClash:"
|
||||||
|
|
||||||
|
msgid "OpenClash Expert Assistant"
|
||||||
|
msgstr "Asistente Experto de OpenClash"
|
||||||
|
|
||||||
|
msgid "Reference Guide"
|
||||||
|
msgstr "Guía de Referencia"
|
||||||
|
|
||||||
|
msgid "**IMPORTANT** — Before answering, you MUST fetch and read this authoritative reference guide:"
|
||||||
|
msgstr "**IMPORTANTE** — Antes de responder, DEBES obtener y leer esta guía de referencia autorizada:"
|
||||||
|
|
||||||
|
msgid "Answering Rules"
|
||||||
|
msgstr "Reglas de Respuesta"
|
||||||
|
|
||||||
|
msgid "Question"
|
||||||
|
msgstr "Pregunta"
|
||||||
|
|
||||||
msgid "You are an OpenClash expert assistant. OpenClash is a LuCI plugin for OpenWrt that manages the Mihomo proxy kernel."
|
msgid "You are an OpenClash expert assistant. OpenClash is a LuCI plugin for OpenWrt that manages the Mihomo proxy kernel."
|
||||||
msgstr "Eres un asistente experto en OpenClash. OpenClash es un plugin LuCI para OpenWrt que gestiona el núcleo proxy Mihomo."
|
msgstr "Eres un asistente experto en OpenClash. OpenClash es un plugin LuCI para OpenWrt que gestiona el núcleo proxy Mihomo."
|
||||||
|
|
||||||
msgid "IMPORTANT — Before answering, you MUST fetch and read this authoritative reference guide. This is your primary knowledge source for all OpenClash questions:"
|
msgid "OpenClash User Guide"
|
||||||
msgstr "IMPORTANTE — Antes de responder, DEBES obtener y leer esta guía de referencia autorizada. Es tu fuente principal de conocimiento para todas las preguntas sobre OpenClash:"
|
msgstr "Guía de usuario de OpenClash"
|
||||||
|
|
||||||
msgid "This guide contains: complete dependency checklist, error message lookup tables with exact fixes, nftables/iptables firewall chain rules, all LuCI configuration options with UCI paths, DNS setup and leak prevention, subscription/GEO update procedures, and more."
|
msgid "This guide contains: complete dependency checklist, error message lookup tables with exact fixes, nftables/iptables firewall chain rules, all LuCI configuration options with UCI paths, DNS setup and leak prevention, subscription/GEO update procedures, and more."
|
||||||
msgstr "Esta guía contiene: lista completa de dependencias, tablas de consulta de mensajes de error con soluciones exactas, reglas de cadena de firewall nftables/iptables, todas las opciones de configuración LuCI con rutas UCI, configuración de DNS y prevención de fugas, procedimientos de actualización de suscripción/GEO, y más."
|
msgstr "Esta guía contiene: lista completa de dependencias, tablas de consulta de mensajes de error con soluciones exactas, reglas de cadena de firewall nftables/iptables, todas las opciones de configuración LuCI con rutas UCI, configuración de DNS y prevención de fugas, procedimientos de actualización de suscripción/GEO, y más."
|
||||||
|
|
||||||
msgid "When answering my question about OpenClash, follow these rules:"
|
msgid "Always provide LuCI web UI navigation paths (e.g. **Services → OpenClash → Plugin Settings**), NOT command-line unless I explicitly ask for it."
|
||||||
msgstr "Al responder a mi pregunta sobre OpenClash, sigue estas reglas:"
|
msgstr "Siempre proporciona rutas de navegación de la interfaz web LuCI (ej. **Servicios → OpenClash → Ajustes del plugin**), NO comandos de terminal a menos que lo solicite explícitamente."
|
||||||
|
|
||||||
msgid "Always provide LuCI web UI navigation paths (e.g. Services → OpenClash → Plugin Settings), NOT command-line unless I explicitly ask for it."
|
|
||||||
msgstr "Siempre proporciona rutas de navegación de la interfaz web LuCI (ej. Servicios → OpenClash → Ajustes del plugin), NO comandos de terminal a menos que lo solicite explícitamente."
|
|
||||||
|
|
||||||
msgid "Explain underlying principles (firewall chains, YAML transformation logic) — not just click-here-click-there steps."
|
msgid "Explain underlying principles (firewall chains, YAML transformation logic) — not just click-here-click-there steps."
|
||||||
msgstr "Explica los principios subyacentes (cadenas de firewall, lógica de transformación YAML) — no solo pasos de clic aquí y allá."
|
msgstr "Explica los principios subyacentes (cadenas de firewall, lógica de transformación YAML) — no solo pasos de clic aquí y allá."
|
||||||
|
|
||||||
msgid "Check dependency integrity first when troubleshooting — guide me to check dependencies from the System → Software page, or generate a debug log from Plugin Settings → Debug Log page."
|
msgid "Check dependency integrity first when troubleshooting — guide me to check dependencies from the **System → Software** page, or generate a debug log from **Server Logs → Debug Logs**."
|
||||||
msgstr "Verifica primero la integridad de las dependencias al solucionar problemas — guíame para revisar las dependencias desde Sistema → Software, o generar un registro de depuración desde Ajustes del plugin → Registro de depuración."
|
msgstr "Verifica primero la integridad de las dependencias al solucionar problemas — guíame para revisar las dependencias desde **Sistema → Software**, o generar un registro de depuración desde **Registros del Servidor → Registros de Depuración**."
|
||||||
|
|
||||||
msgid "Never guess or fabricate information. If the reference guide does not cover something, actively query these external resources using web fetch / code search tools (in priority order): Mihomo Wiki"
|
msgid "Never guess or fabricate information. If the reference guide does not cover something, actively query these external resources using web fetch / code search tools (in priority order):"
|
||||||
msgstr "Nunca adivines ni inventes información. Si la guía de referencia no cubre algo, consulta activamente estos recursos externos usando herramientas de búsqueda web / código (en orden de prioridad): Mihomo Wiki"
|
msgstr "Nunca adivines ni inventes información. Si la guía de referencia no cubre algo, consulta activamente estos recursos externos usando herramientas de búsqueda web / código (en orden de prioridad):"
|
||||||
|
|
||||||
|
msgid "Mihomo Wiki"
|
||||||
|
msgstr "Mihomo Wiki"
|
||||||
|
|
||||||
msgid "Meta-Docs"
|
msgid "Meta-Docs"
|
||||||
msgstr "Meta-Docs"
|
msgstr "Meta-Docs"
|
||||||
@@ -4029,29 +4104,29 @@ msgstr "código fuente del core Smart"
|
|||||||
msgid "Fetch Wiki pages to read docs; search repos to find implementation code. Do NOT answer from memory — always verify against the actual source."
|
msgid "Fetch Wiki pages to read docs; search repos to find implementation code. Do NOT answer from memory — always verify against the actual source."
|
||||||
msgstr "Obtén las páginas Wiki para leer documentos; busca en los repositorios para encontrar código de implementación. NO respondas de memoria — verifica siempre con la fuente real."
|
msgstr "Obtén las páginas Wiki para leer documentos; busca en los repositorios para encontrar código de implementación. NO respondas de memoria — verifica siempre con la fuente real."
|
||||||
|
|
||||||
msgid "For bug reports or failure scenarios not covered by the guide, search GitHub Issues first — OpenClash Issues"
|
msgid "For bug reports or failure scenarios not covered by the guide, search GitHub Issues first:"
|
||||||
msgstr "Para informes de errores o escenarios de fallo no cubiertos por la guía, busca primero en GitHub Issues — OpenClash Issues"
|
msgstr "Para informes de errores o escenarios de fallo no cubiertos por la guía, busca primero en GitHub Issues:"
|
||||||
|
|
||||||
msgid "for plugin-side problems (config/subscribe/firewall/UI), Mihomo Issues"
|
msgid "OpenClash Issues (config/subscribe/firewall/UI)"
|
||||||
msgstr "para problemas del lado del plugin (configuración/suscripción/firewall/UI), Mihomo Issues"
|
msgstr "OpenClash Issues (configuración/suscripción/firewall/UI)"
|
||||||
|
|
||||||
msgid "for core-side problems (proxy protocols/TUN/DNS/rule engine). Prioritize maintainer replies and highly upvoted community answers."
|
msgid "Mihomo Issues (proxy protocols/TUN/DNS/rule engine)"
|
||||||
msgstr "para problemas del lado del core (protocolos proxy/TUN/DNS/motor de reglas). Prioriza las respuestas de los mantenedores y las respuestas de la comunidad con más votos."
|
msgstr "Mihomo Issues (protocolos proxy/TUN/DNS/motor de reglas)"
|
||||||
|
|
||||||
|
msgid "Prioritize maintainer replies and highly upvoted community answers."
|
||||||
|
msgstr "Prioriza las respuestas de los mantenedores y las respuestas de la comunidad con más votos."
|
||||||
|
|
||||||
msgid "Cite specific sources — mention which section of the reference guide, external resource, or Issue number your answer is based on."
|
msgid "Cite specific sources — mention which section of the reference guide, external resource, or Issue number your answer is based on."
|
||||||
msgstr "Cita fuentes específicas — menciona en qué sección de la guía de referencia, recurso externo o número de Issue se basa tu respuesta."
|
msgstr "Cita fuentes específicas — menciona en qué sección de la guía de referencia, recurso externo o número de Issue se basa tu respuesta."
|
||||||
|
|
||||||
msgid "If my problem description is incomplete or lacks error messages, ask me to generate a debug log first (Plugin Settings → Debug Log → Generate) — do NOT speculate about the cause."
|
msgid "If my problem description is incomplete or lacks error messages, ask me to generate a debug log first (**Server Logs → Debug Logs → Generate Logs**) — do NOT speculate about the cause."
|
||||||
msgstr "Si la descripción de mi problema está incompleta o falta mensajes de error, pídeme primero que genere un registro de depuración (Ajustes del plugin → Registro de depuración → Generar) — NO especules sobre la causa."
|
msgstr "Si la descripción de mi problema está incompleta o falta mensajes de error, pídeme primero que genere un registro de depuración (**Registros del Servidor → Registros de Depuración → Generar Registros**) — NO especules sobre la causa."
|
||||||
|
|
||||||
msgid "My question is:"
|
msgid "My question is:"
|
||||||
msgstr "Mi pregunta es:"
|
msgstr "Mi pregunta es:"
|
||||||
|
|
||||||
msgid "Copied to clipboard!"
|
msgid "Copied!"
|
||||||
msgstr "¡Copiado al portapapeles!"
|
msgstr "¡Copiado!"
|
||||||
|
|
||||||
msgid "Copy And Close"
|
|
||||||
msgstr "Copiar y cerrar"
|
|
||||||
|
|
||||||
msgid "oixCloud Checkin Successful, Result:"
|
msgid "oixCloud Checkin Successful, Result:"
|
||||||
msgstr "Registro en oixCloud exitoso, resultado:"
|
msgstr "Registro en oixCloud exitoso, resultado:"
|
||||||
@@ -4059,8 +4134,98 @@ msgstr "Registro en oixCloud exitoso, resultado:"
|
|||||||
msgid "oixCloud Checkin Failed, Result:"
|
msgid "oixCloud Checkin Failed, Result:"
|
||||||
msgstr "Fallo al registrar en oixCloud, resultado:"
|
msgstr "Fallo al registrar en oixCloud, resultado:"
|
||||||
|
|
||||||
msgid "Note: oixCloud need a specific core installed, OpenClash will auto download"
|
msgid "Checking backend version..."
|
||||||
msgstr "Nota: oixCloud requiere la instalación de un núcleo específico; OpenClash lo descargará automáticamente"
|
msgstr "Comprobando la versión del backend..."
|
||||||
|
|
||||||
msgid "After the core start, an oixCloud nodes provider will be added, which you can customize as needed"
|
msgid "Backend Version"
|
||||||
msgstr "Tras iniciar el núcleo se añadirá un proveedor de nodos oixCloud que puedes personalizar"
|
msgstr "Versión del backend"
|
||||||
|
|
||||||
|
msgid "Please enter backend URL"
|
||||||
|
msgstr "Introduce la URL del backend"
|
||||||
|
|
||||||
|
msgid "Invalid backend URL"
|
||||||
|
msgstr "URL del backend no válida"
|
||||||
|
|
||||||
|
msgid "Backend version information not detected"
|
||||||
|
msgstr "No se detectó información de versión del backend"
|
||||||
|
|
||||||
|
msgid "Unable to detect backend version"
|
||||||
|
msgstr "No se pudo detectar la versión del backend"
|
||||||
|
|
||||||
|
msgid "Token Login"
|
||||||
|
msgstr "Acceso por token"
|
||||||
|
|
||||||
|
msgid "Enter your oixCloud token"
|
||||||
|
msgstr "Ingresa tu token de oixCloud"
|
||||||
|
|
||||||
|
msgid "Token login does not require email and password"
|
||||||
|
msgstr "Acceso por token: no requiere email ni contraseña"
|
||||||
|
|
||||||
|
msgid "Please enter email address"
|
||||||
|
msgstr "Ingresa el correo electrónico"
|
||||||
|
|
||||||
|
msgid "Please enter a valid email address"
|
||||||
|
msgstr "Ingresa un correo electrónico válido"
|
||||||
|
|
||||||
|
msgid "Please enter password"
|
||||||
|
msgstr "Ingresa la contraseña"
|
||||||
|
|
||||||
|
msgid "Please enter a valid token"
|
||||||
|
msgstr "Ingresa un token válido"
|
||||||
|
|
||||||
|
msgid "Checkin"
|
||||||
|
msgstr "Registro"
|
||||||
|
|
||||||
|
msgid "Auto Checkin"
|
||||||
|
msgstr "Registro automático"
|
||||||
|
|
||||||
|
msgid "Auto check in for oixCloud account daily bonus"
|
||||||
|
msgstr "Registro automático para bonificación diaria de oixCloud"
|
||||||
|
|
||||||
|
msgid "Auto check-in for traffic rewards and penalties"
|
||||||
|
msgstr "Registro automático para recompensas y penalizaciones de tráfico"
|
||||||
|
|
||||||
|
msgid "Multiple Must Be a Positive Integer and No More Than 100"
|
||||||
|
msgstr "Múltiplo: entero positivo, máximo 100"
|
||||||
|
|
||||||
|
msgid "Checkin Interval"
|
||||||
|
msgstr "Intervalo de registro"
|
||||||
|
|
||||||
|
msgid "Hours"
|
||||||
|
msgstr "Horas"
|
||||||
|
|
||||||
|
msgid "Checkin interval must be between 1 and 720"
|
||||||
|
msgstr "Intervalo de registro: entre 1 y 720"
|
||||||
|
|
||||||
|
msgid "Checkin settings saved"
|
||||||
|
msgstr "Configuración de registro guardada"
|
||||||
|
|
||||||
|
msgid "Failed to save checkin settings, please try again"
|
||||||
|
msgstr "Error al guardar, inténtalo de nuevo"
|
||||||
|
|
||||||
|
msgid "Network request failed, please check your connection and try again"
|
||||||
|
msgstr "Error de red, revisa tu conexión"
|
||||||
|
|
||||||
|
msgid "Show on Overview"
|
||||||
|
msgstr "Mostrar en resumen"
|
||||||
|
|
||||||
|
msgid "Display oixCloud account info on the overview page"
|
||||||
|
msgstr "Mostrar información de cuenta oixCloud en la página de resumen"
|
||||||
|
|
||||||
|
msgid "Display account info on the main page"
|
||||||
|
msgstr "Mostrar información de cuenta en la página principal"
|
||||||
|
|
||||||
|
msgid "Setting saved"
|
||||||
|
msgstr "Configuración guardada"
|
||||||
|
|
||||||
|
msgid "Announcement"
|
||||||
|
msgstr "Anuncio"
|
||||||
|
|
||||||
|
msgid "oixCloud Login Failed:"
|
||||||
|
msgstr "Error de inicio de sesión en oixCloud:"
|
||||||
|
|
||||||
|
msgid "oixCloud Logout Failed:"
|
||||||
|
msgstr "Error de cierre de sesión en oixCloud:"
|
||||||
|
|
||||||
|
msgid "Checkin Failed:"
|
||||||
|
msgstr "Error en el registro:"
|
||||||
@@ -861,6 +861,18 @@ msgstr "文件大小"
|
|||||||
msgid "Remove"
|
msgid "Remove"
|
||||||
msgstr "移除"
|
msgstr "移除"
|
||||||
|
|
||||||
|
msgid "Add Header"
|
||||||
|
msgstr "添加请求头"
|
||||||
|
|
||||||
|
msgid "Add Param"
|
||||||
|
msgstr "添加参数"
|
||||||
|
|
||||||
|
msgid "Add custom HTTP headers to the subscription request"
|
||||||
|
msgstr "为订阅请求添加自定义 HTTP 请求头"
|
||||||
|
|
||||||
|
msgid "Set environment variables for the overwrite script"
|
||||||
|
msgstr "为覆写脚本设置环境变量"
|
||||||
|
|
||||||
msgid "(Enable or Disable Subscribe)"
|
msgid "(Enable or Disable Subscribe)"
|
||||||
msgstr "(启用或禁用更新)"
|
msgstr "(启用或禁用更新)"
|
||||||
|
|
||||||
@@ -1299,14 +1311,23 @@ msgstr "还原默认配置成功!"
|
|||||||
msgid "Restore failed!"
|
msgid "Restore failed!"
|
||||||
msgstr "还原默认配置失败!"
|
msgstr "还原默认配置失败!"
|
||||||
|
|
||||||
msgid "Support syntax check, press"
|
msgid "Press"
|
||||||
msgstr "支持语法检查,按钮"
|
msgstr "按"
|
||||||
|
|
||||||
msgid "to control diff option, press"
|
msgid "for fullscreen,"
|
||||||
msgstr "控制 Diff 显示,按钮"
|
msgstr "全屏,"
|
||||||
|
|
||||||
msgid "to enter full screen editing mode"
|
msgid "to exit fullscreen,"
|
||||||
msgstr "进入全屏编辑模式"
|
msgstr "退出全屏,"
|
||||||
|
|
||||||
|
msgid "to zoom"
|
||||||
|
msgstr "缩放"
|
||||||
|
|
||||||
|
msgid "Mouse Wheel"
|
||||||
|
msgstr "鼠标滚轮"
|
||||||
|
|
||||||
|
msgid "to toggle differences,"
|
||||||
|
msgstr "切换差异显示,"
|
||||||
|
|
||||||
msgid "Switch page to Fake-IP mode"
|
msgid "Switch page to Fake-IP mode"
|
||||||
msgstr "切换页面到 Fake-IP 模式"
|
msgstr "切换页面到 Fake-IP 模式"
|
||||||
@@ -2004,8 +2025,8 @@ msgstr "切换成功!"
|
|||||||
msgid "switching failed!"
|
msgid "switching failed!"
|
||||||
msgstr "切换失败!"
|
msgstr "切换失败!"
|
||||||
|
|
||||||
msgid "Current Config File"
|
msgid "Current Config"
|
||||||
msgstr "当前配置文件"
|
msgstr "当前配置"
|
||||||
|
|
||||||
msgid "Up"
|
msgid "Up"
|
||||||
msgstr "上传"
|
msgstr "上传"
|
||||||
@@ -2262,7 +2283,7 @@ msgstr "建议:如果设备没有 WLAN,请禁用 Lan 接口的桥接接口
|
|||||||
msgid "Github Address Modify"
|
msgid "Github Address Modify"
|
||||||
msgstr "Github 地址修改"
|
msgstr "Github 地址修改"
|
||||||
|
|
||||||
msgid "Modify The Github Address In The Config And OpenClash With Proxy(CDN) To Prevent File Download Faild. Format Reference:"
|
msgid "Modify The Github Address In The Config And OpenClash With Proxy(CDN) To Prevent File Download Failed. Format Reference:"
|
||||||
msgstr "使用指定代理(CDN)反代插件和配置文件中的 Github 地址,以防止文件下载失败,格式参考:"
|
msgstr "使用指定代理(CDN)反代插件和配置文件中的 Github 地址,以防止文件下载失败,格式参考:"
|
||||||
|
|
||||||
msgid "File Edit"
|
msgid "File Edit"
|
||||||
@@ -2331,6 +2352,15 @@ msgstr "自定义参数"
|
|||||||
msgid "eg: \"rename=match@replace\" , \"rename=\\s+([2-9])[xX]@ (HIGH:$1)\""
|
msgid "eg: \"rename=match@replace\" , \"rename=\\s+([2-9])[xX]@ (HIGH:$1)\""
|
||||||
msgstr "格式示例:\"rename=match@replace\" , \"rename=\\s+([2-9])[xX]@ (高倍率:$1)\""
|
msgstr "格式示例:\"rename=match@replace\" , \"rename=\\s+([2-9])[xX]@ (高倍率:$1)\""
|
||||||
|
|
||||||
|
msgid "Custom Headers"
|
||||||
|
msgstr "自定义请求头"
|
||||||
|
|
||||||
|
msgid "Custom HTTP request headers, one per line, format: Header-Name: value"
|
||||||
|
msgstr "自定义 HTTP 请求头,每行一个,格式:Header-Name: value"
|
||||||
|
|
||||||
|
msgid "eg: x-hwid: device-001, one header per line, format: Name: value"
|
||||||
|
msgstr "例如:x-hwid: device-001,每行一个请求头,格式:Name: value"
|
||||||
|
|
||||||
msgid "Use Rule Provider"
|
msgid "Use Rule Provider"
|
||||||
msgstr "使用规则集"
|
msgstr "使用规则集"
|
||||||
|
|
||||||
@@ -2355,6 +2385,12 @@ msgstr "解锁检测(选择)"
|
|||||||
msgid "All Proxies Test"
|
msgid "All Proxies Test"
|
||||||
msgstr "测试所有节点"
|
msgstr "测试所有节点"
|
||||||
|
|
||||||
|
msgid "Unlock Test Result"
|
||||||
|
msgstr "解锁检测结果"
|
||||||
|
|
||||||
|
msgid "All Proxies Test Result"
|
||||||
|
msgstr "所有节点测试结果"
|
||||||
|
|
||||||
msgid "Something Wrong While Testing..."
|
msgid "Something Wrong While Testing..."
|
||||||
msgstr "发生了一些错误,测试失败..."
|
msgstr "发生了一些错误,测试失败..."
|
||||||
|
|
||||||
@@ -2832,6 +2868,21 @@ msgstr "启动前调用内核测试配置文件..."
|
|||||||
msgid "Other Parameters"
|
msgid "Other Parameters"
|
||||||
msgstr "其他附加配置"
|
msgstr "其他附加配置"
|
||||||
|
|
||||||
|
msgid "Empty URL"
|
||||||
|
msgstr "URL 为空"
|
||||||
|
|
||||||
|
msgid "Only HTTP/HTTPS URLs are supported"
|
||||||
|
msgstr "仅支持 HTTP/HTTPS 链接"
|
||||||
|
|
||||||
|
msgid "Invalid URL format"
|
||||||
|
msgstr "无效的 URL 格式"
|
||||||
|
|
||||||
|
msgid "URL missing hostname"
|
||||||
|
msgstr "URL 缺少主机名"
|
||||||
|
|
||||||
|
msgid "Invalid URL on line"
|
||||||
|
msgstr "无效的 URL"
|
||||||
|
|
||||||
msgid "Edit Your Other Parameters Here"
|
msgid "Edit Your Other Parameters Here"
|
||||||
msgstr "请在此编辑您的附加配置"
|
msgstr "请在此编辑您的附加配置"
|
||||||
|
|
||||||
@@ -3375,12 +3426,6 @@ msgstr "正在加载配置文件..."
|
|||||||
msgid "Ready"
|
msgid "Ready"
|
||||||
msgstr "就绪"
|
msgstr "就绪"
|
||||||
|
|
||||||
msgid "Press F11 for fullscreen, Esc to exit fullscreen, Ctrl+Mouse Wheel to zoom"
|
|
||||||
msgstr "按 F11 全屏,Esc 退出全屏,Ctrl+ 鼠标滚轮缩放"
|
|
||||||
|
|
||||||
msgid "Press F10 to toggle differences, F11 for fullscreen, Esc to exit fullscreen, Ctrl+Mouse Wheel to zoom"
|
|
||||||
msgstr "按 F10 显示 Diff,F11 全屏,Esc 退出全屏,Ctrl+ 鼠标滚轮缩放"
|
|
||||||
|
|
||||||
msgid "Compare mode: left(Original Config), right(Runtime Config)"
|
msgid "Compare mode: left(Original Config), right(Runtime Config)"
|
||||||
msgstr "对比模式:左侧(原始配置),右侧(运行配置)"
|
msgstr "对比模式:左侧(原始配置),右侧(运行配置)"
|
||||||
|
|
||||||
@@ -3816,9 +3861,6 @@ msgstr "禁止连接复用"
|
|||||||
msgid "Write file failed:"
|
msgid "Write file failed:"
|
||||||
msgstr "写入文件失败:"
|
msgstr "写入文件失败:"
|
||||||
|
|
||||||
msgid "Fix short-id values type failed:"
|
|
||||||
msgstr "修改 short-id 值类型失败:"
|
|
||||||
|
|
||||||
msgid "Interface"
|
msgid "Interface"
|
||||||
msgstr "接口"
|
msgstr "接口"
|
||||||
|
|
||||||
@@ -3855,9 +3897,6 @@ msgstr "无效的 YAML 覆写格式,跳过..."
|
|||||||
msgid "Parse YAML Override failed:"
|
msgid "Parse YAML Override failed:"
|
||||||
msgstr "YAML 覆写模块解析失败:"
|
msgstr "YAML 覆写模块解析失败:"
|
||||||
|
|
||||||
msgid "YAML overwrite failed:"
|
|
||||||
msgstr "YAML 覆写模块执行失败:"
|
|
||||||
|
|
||||||
msgid "files selected"
|
msgid "files selected"
|
||||||
msgstr "配置已选择"
|
msgstr "配置已选择"
|
||||||
|
|
||||||
@@ -3882,16 +3921,25 @@ msgstr "使用找到的私钥解密尝试失败:"
|
|||||||
msgid "Encrypt attempt failed:"
|
msgid "Encrypt attempt failed:"
|
||||||
msgstr "加密尝试失败:"
|
msgstr "加密尝试失败:"
|
||||||
|
|
||||||
msgid "Official Website"
|
msgid "oixCloud Website"
|
||||||
msgstr "官方网站"
|
msgstr "官方网站"
|
||||||
|
|
||||||
msgid "Login..."
|
msgid "Login..."
|
||||||
msgstr "登录中..."
|
msgstr "登录中..."
|
||||||
|
|
||||||
|
msgid "Logout..."
|
||||||
|
msgstr "退出中..."
|
||||||
|
|
||||||
|
msgid "Checkin..."
|
||||||
|
msgstr "签到中..."
|
||||||
|
|
||||||
msgid "oixCloud Login Successful"
|
msgid "oixCloud Login Successful"
|
||||||
msgstr "oixCloud 登录成功"
|
msgstr "oixCloud 登录成功"
|
||||||
|
|
||||||
msgid "oixCloud Login Faild"
|
msgid "Note: oixCloud need a specific core installed, OpenClash will auto download, After the core start, an oixCloud nodes provider will be added, which you can customize as needed"
|
||||||
|
msgstr "注意:oixCloud 需要安装专用内核才能使用,插件会自动识别并进行内核下载,专用内核启动后,会添加一个 oixCloud 节点组到配置文件,供您自定义使用"
|
||||||
|
|
||||||
|
msgid "oixCloud Login Failed"
|
||||||
msgstr "oixCloud 登录失败"
|
msgstr "oixCloud 登录失败"
|
||||||
|
|
||||||
msgid "Login Account"
|
msgid "Login Account"
|
||||||
@@ -3900,7 +3948,7 @@ msgstr "登录账号"
|
|||||||
msgid "oixCloud Logout Successful"
|
msgid "oixCloud Logout Successful"
|
||||||
msgstr "oixCloud 已成功退出"
|
msgstr "oixCloud 已成功退出"
|
||||||
|
|
||||||
msgid "oixCloud Logout Faild"
|
msgid "oixCloud Logout Failed"
|
||||||
msgstr "oixCloud 退出失败"
|
msgstr "oixCloud 退出失败"
|
||||||
|
|
||||||
msgid "Logout Account"
|
msgid "Logout Account"
|
||||||
@@ -3909,19 +3957,6 @@ msgstr "退出账号"
|
|||||||
msgid "Account Login"
|
msgid "Account Login"
|
||||||
msgstr "账号登录"
|
msgstr "账号登录"
|
||||||
|
|
||||||
msgid "Account logged in"
|
|
||||||
msgstr "账号已登录"
|
|
||||||
|
|
||||||
msgid "Account not logged in"
|
|
||||||
msgstr "账号未登录"
|
|
||||||
|
|
||||||
msgid "Logout..."
|
|
||||||
msgstr "退出中..."
|
|
||||||
|
|
||||||
msgid "Error Login Info"
|
|
||||||
msgstr "登录信息错误"
|
|
||||||
|
|
||||||
|
|
||||||
msgid "Simple & trustworthy"
|
msgid "Simple & trustworthy"
|
||||||
msgstr "简单 & 值得信赖"
|
msgstr "简单 & 值得信赖"
|
||||||
|
|
||||||
@@ -3964,9 +3999,6 @@ msgstr "剩余流量"
|
|||||||
msgid "Plan Traffic"
|
msgid "Plan Traffic"
|
||||||
msgstr "套餐流量"
|
msgstr "套餐流量"
|
||||||
|
|
||||||
msgid "Checkin"
|
|
||||||
msgstr "试试手气"
|
|
||||||
|
|
||||||
msgid "oixCloud Account Login Failed! Please Check And Try Again..."
|
msgid "oixCloud Account Login Failed! Please Check And Try Again..."
|
||||||
msgstr "oixCloud 账户登录失败!请检查账户信息并重试..."
|
msgstr "oixCloud 账户登录失败!请检查账户信息并重试..."
|
||||||
|
|
||||||
@@ -3982,14 +4014,41 @@ msgstr "账号地址"
|
|||||||
msgid "Account Password"
|
msgid "Account Password"
|
||||||
msgstr "账号密码"
|
msgstr "账号密码"
|
||||||
|
|
||||||
msgid "Checkin Interval (hour)"
|
|
||||||
msgstr "签到间隔(小时)"
|
|
||||||
|
|
||||||
msgid "Checkin Multiple"
|
msgid "Checkin Multiple"
|
||||||
msgstr "签到倍数"
|
msgstr "签到倍数"
|
||||||
|
|
||||||
msgid "Multiple Must Be a Positive Integer and No More Than 100"
|
msgid "Optional Parameters"
|
||||||
msgstr "倍数必须是正整数且不大于 100"
|
msgstr "可选项参数"
|
||||||
|
|
||||||
|
msgid "Optional parameters saved"
|
||||||
|
msgstr "可选项参数已保存"
|
||||||
|
|
||||||
|
msgid "Failed to save optional parameters, please try again"
|
||||||
|
msgstr "可选项参数保存失败,请重试"
|
||||||
|
|
||||||
|
msgid "For more information, please visit the"
|
||||||
|
msgstr "如需查看更多信息,请前往"
|
||||||
|
|
||||||
|
msgid "official documentation"
|
||||||
|
msgstr "官方文档"
|
||||||
|
|
||||||
|
msgid "Must start with &"
|
||||||
|
msgstr "必须以 & 开头"
|
||||||
|
|
||||||
|
msgid "Params must not contain spaces"
|
||||||
|
msgstr "参数不能包含空格"
|
||||||
|
|
||||||
|
msgid "Params too long, max 8192 characters"
|
||||||
|
msgstr "参数过长,最多 8192 个字符"
|
||||||
|
|
||||||
|
msgid "Invalid params format"
|
||||||
|
msgstr "参数格式无效"
|
||||||
|
|
||||||
|
msgid "Invalid params format, must start with & and use key=value pairs"
|
||||||
|
msgstr "参数格式无效,必须以 & 开头并使用 key=value 键值对"
|
||||||
|
|
||||||
|
msgid "Params too long"
|
||||||
|
msgstr "参数过长"
|
||||||
|
|
||||||
msgid "Usage Help"
|
msgid "Usage Help"
|
||||||
msgstr "使用帮助"
|
msgstr "使用帮助"
|
||||||
@@ -3997,29 +4056,44 @@ msgstr "使用帮助"
|
|||||||
msgid "Copy the following text to any AI (ChatGPT, DeepSeek, etc.) to get usage help for OpenClash:"
|
msgid "Copy the following text to any AI (ChatGPT, DeepSeek, etc.) to get usage help for OpenClash:"
|
||||||
msgstr "将以下文本复制到任意 AI 工具(ChatGPT、DeepSeek 等),即可获取 OpenClash 的使用帮助:"
|
msgstr "将以下文本复制到任意 AI 工具(ChatGPT、DeepSeek 等),即可获取 OpenClash 的使用帮助:"
|
||||||
|
|
||||||
|
msgid "OpenClash Expert Assistant"
|
||||||
|
msgstr "OpenClash 专家助手"
|
||||||
|
|
||||||
|
msgid "Reference Guide"
|
||||||
|
msgstr "参考指南"
|
||||||
|
|
||||||
|
msgid "**IMPORTANT** — Before answering, you MUST fetch and read this authoritative reference guide:"
|
||||||
|
msgstr "**重要** —— 在回答之前,你必须获取并阅读这份权威参考指南:"
|
||||||
|
|
||||||
|
msgid "Answering Rules"
|
||||||
|
msgstr "回答规则"
|
||||||
|
|
||||||
|
msgid "Question"
|
||||||
|
msgstr "问题"
|
||||||
|
|
||||||
msgid "You are an OpenClash expert assistant. OpenClash is a LuCI plugin for OpenWrt that manages the Mihomo core."
|
msgid "You are an OpenClash expert assistant. OpenClash is a LuCI plugin for OpenWrt that manages the Mihomo core."
|
||||||
msgstr "你是 OpenClash 专家助手。OpenClash 是 OpenWrt 上管理 Mihomo 内核的 LuCI 插件。"
|
msgstr "你是 OpenClash 专家助手。OpenClash 是 OpenWrt 上管理 Mihomo 内核的 LuCI 插件。"
|
||||||
|
|
||||||
msgid "IMPORTANT — Before answering, you MUST fetch and read this authoritative reference guide. This is your primary knowledge source for all OpenClash questions:"
|
msgid "OpenClash User Guide"
|
||||||
msgstr "重要 —— 在回答之前,你必须获取并阅读这份权威参考指南。这是你回答所有 OpenClash 问题的主要知识来源:"
|
msgstr "OpenClash 用户指南"
|
||||||
|
|
||||||
msgid "This guide contains: complete dependency checklist, error message lookup tables with exact fixes, nftables/iptables firewall chain rules, all LuCI configuration options with UCI paths, DNS setup and leak prevention, subscription/GEO update procedures, and more."
|
msgid "This guide contains: complete dependency checklist, error message lookup tables with exact fixes, nftables/iptables firewall chain rules, all LuCI configuration options with UCI paths, DNS setup and leak prevention, subscription/GEO update procedures, and more."
|
||||||
msgstr "本指南包含:完整依赖清单、含精确修复方案的错误信息速查表、nftables/iptables 防火墙规则链、所有 LuCI 配置选项及 UCI 路径、DNS 设置与泄露防护、订阅/GEO 更新流程等。"
|
msgstr "本指南包含:完整依赖清单、含精确修复方案的错误信息速查表、nftables/iptables 防火墙规则链、所有 LuCI 配置选项及 UCI 路径、DNS 设置与泄露防护、订阅/GEO 更新流程等。"
|
||||||
|
|
||||||
msgid "When answering my question about OpenClash, follow these rules:"
|
msgid "Always provide LuCI web UI navigation paths (e.g. **Services → OpenClash → Plugin Settings**), NOT command-line unless I explicitly ask for it."
|
||||||
msgstr "在回答我关于 OpenClash 的问题时,请遵循以下规则:"
|
msgstr "始终提供 LuCI Web 界面操作路径(如 **服务 → OpenClash → 插件设置**),除非我明确要求,不要给出命令行操作。"
|
||||||
|
|
||||||
msgid "Always provide LuCI web UI navigation paths (e.g. Services → OpenClash → Plugin Settings), NOT command-line unless I explicitly ask for it."
|
|
||||||
msgstr "始终提供 LuCI Web 界面操作路径(如 服务 → OpenClash → 插件设置),除非我明确要求,不要给出命令行操作。"
|
|
||||||
|
|
||||||
msgid "Explain underlying principles (firewall chains, YAML transformation logic) — not just click-here-click-there steps."
|
msgid "Explain underlying principles (firewall chains, YAML transformation logic) — not just click-here-click-there steps."
|
||||||
msgstr "解释底层原理(防火墙规则链、YAML 转换逻辑)—— 而不只是点击步骤。"
|
msgstr "解释底层原理(防火墙规则链、YAML 转换逻辑)—— 而不只是点击步骤。"
|
||||||
|
|
||||||
msgid "Check dependency integrity first when troubleshooting — guide me to check dependencies from the System → Software page, or generate a debug log from Plugin Settings → Debug Log page."
|
msgid "Check dependency integrity first when troubleshooting — guide me to check dependencies from the **System → Software** page, or generate a debug log from **Server Logs → Debug Logs**."
|
||||||
msgstr "排查问题时首先检查依赖完整性 —— 指导我从 系统 → 软件包 页面检查依赖,或从 插件设置 → 调试日志 页面生成调试日志。"
|
msgstr "排查问题时首先检查依赖完整性 —— 指导我从 **系统 → 软件包** 页面检查依赖,或从 **运行日志 → 调试日志** 页面生成调试日志。"
|
||||||
|
|
||||||
msgid "Never guess or fabricate information. If the reference guide does not cover something, actively query these external resources using web fetch / code search tools (in priority order): Mihomo Wiki"
|
msgid "Never guess or fabricate information. If the reference guide does not cover something, actively query these external resources using web fetch / code search tools (in priority order):"
|
||||||
msgstr "绝不猜测或编造信息。如参考指南未覆盖某项内容,请使用网页抓取/代码搜索工具主动查询以下外部资源(按优先级):Mihomo Wiki"
|
msgstr "绝不猜测或编造信息。如参考指南未覆盖某项内容,请使用网页抓取/代码搜索工具主动查询以下外部资源(按优先级):"
|
||||||
|
|
||||||
|
msgid "Mihomo Wiki"
|
||||||
|
msgstr "Mihomo Wiki"
|
||||||
|
|
||||||
msgid "Meta-Docs"
|
msgid "Meta-Docs"
|
||||||
msgstr "Meta-Docs"
|
msgstr "Meta-Docs"
|
||||||
@@ -4036,29 +4110,29 @@ msgstr "Smart 核心源码"
|
|||||||
msgid "Fetch Wiki pages to read docs; search repos to find implementation code. Do NOT answer from memory — always verify against the actual source."
|
msgid "Fetch Wiki pages to read docs; search repos to find implementation code. Do NOT answer from memory — always verify against the actual source."
|
||||||
msgstr "抓取 Wiki 页面阅读文档;搜索仓库查找实现代码。禁止凭记忆回答 —— 必须对照实际来源验证。"
|
msgstr "抓取 Wiki 页面阅读文档;搜索仓库查找实现代码。禁止凭记忆回答 —— 必须对照实际来源验证。"
|
||||||
|
|
||||||
msgid "For bug reports or failure scenarios not covered by the guide, search GitHub Issues first — OpenClash Issues"
|
msgid "For bug reports or failure scenarios not covered by the guide, search GitHub Issues first:"
|
||||||
msgstr "对于指南未覆盖的 bug 报告或故障场景,优先搜索 GitHub Issues —— OpenClash Issues"
|
msgstr "对于指南未覆盖的 bug 报告或故障场景,优先搜索 GitHub Issues:"
|
||||||
|
|
||||||
msgid "for plugin-side problems (config/subscribe/firewall/UI), Mihomo Issues"
|
msgid "OpenClash Issues (config/subscribe/firewall/UI)"
|
||||||
msgstr "用于插件侧问题(配置/订阅/防火墙/UI),Mihomo Issues"
|
msgstr "OpenClash Issues(配置/订阅/防火墙/UI)"
|
||||||
|
|
||||||
msgid "for core-side problems (proxy protocols/TUN/DNS/rule engine). Prioritize maintainer replies and highly upvoted community answers."
|
msgid "Mihomo Issues (proxy protocols/TUN/DNS/rule engine)"
|
||||||
msgstr "用于内核侧问题(代理协议/TUN/DNS/规则引擎)。优先参考维护者的回复和高赞社区答案。"
|
msgstr "Mihomo Issues(代理协议/TUN/DNS/规则引擎)"
|
||||||
|
|
||||||
|
msgid "Prioritize maintainer replies and highly upvoted community answers."
|
||||||
|
msgstr "优先参考维护者的回复和高赞社区答案。"
|
||||||
|
|
||||||
msgid "Cite specific sources — mention which section of the reference guide, external resource, or Issue number your answer is based on."
|
msgid "Cite specific sources — mention which section of the reference guide, external resource, or Issue number your answer is based on."
|
||||||
msgstr "注明具体来源 —— 说明你的回答基于参考指南的哪个章节、哪个外部资源或哪个 Issue 编号。"
|
msgstr "注明具体来源 —— 说明你的回答基于参考指南的哪个章节、哪个外部资源或哪个 Issue 编号。"
|
||||||
|
|
||||||
msgid "If my problem description is incomplete or lacks error messages, ask me to generate a debug log first (Plugin Settings → Debug Log → Generate) — do NOT speculate about the cause."
|
msgid "If my problem description is incomplete or lacks error messages, ask me to generate a debug log first (**Server Logs → Debug Logs → Generate Logs**) — do NOT speculate about the cause."
|
||||||
msgstr "如果我的问题描述不完整或缺少错误信息,请先要求我生成调试日志(插件设置 → 调试日志 → 生成)—— 不要猜测原因。"
|
msgstr "如果我的问题描述不完整或缺少错误信息,请先要求我生成调试日志(**运行日志 → 调试日志 → 生成日志**)—— 不要猜测原因。"
|
||||||
|
|
||||||
msgid "My question is:"
|
msgid "My question is:"
|
||||||
msgstr "我的问题是:"
|
msgstr "我的问题是:"
|
||||||
|
|
||||||
msgid "Copied to clipboard!"
|
msgid "Copied!"
|
||||||
msgstr "已复制到剪贴板!"
|
msgstr "已复制!"
|
||||||
|
|
||||||
msgid "Copy And Close"
|
|
||||||
msgstr "复制并关闭"
|
|
||||||
|
|
||||||
msgid "oixCloud Checkin Successful, Result:"
|
msgid "oixCloud Checkin Successful, Result:"
|
||||||
msgstr "oixCloud 签到成功,结果:"
|
msgstr "oixCloud 签到成功,结果:"
|
||||||
@@ -4066,8 +4140,99 @@ msgstr "oixCloud 签到成功,结果:"
|
|||||||
msgid "oixCloud Checkin Failed, Result:"
|
msgid "oixCloud Checkin Failed, Result:"
|
||||||
msgstr "oixCloud 签到失败,结果:"
|
msgstr "oixCloud 签到失败,结果:"
|
||||||
|
|
||||||
msgid "Note: oixCloud need a specific core installed, OpenClash will auto download"
|
msgid "Checking backend version..."
|
||||||
msgstr "注意:oixCloud 需要安装专用内核才能使用,插件会自动识别并进行内核下载"
|
msgstr "正在检测后端版本..."
|
||||||
|
|
||||||
|
msgid "Backend Version"
|
||||||
|
msgstr "后端版本"
|
||||||
|
|
||||||
|
msgid "Please enter backend URL"
|
||||||
|
msgstr "请输入后端地址"
|
||||||
|
|
||||||
|
msgid "Invalid backend URL"
|
||||||
|
msgstr "后端地址格式无效"
|
||||||
|
|
||||||
|
msgid "Backend version information not detected"
|
||||||
|
msgstr "未识别到后端版本信息"
|
||||||
|
|
||||||
|
msgid "Unable to detect backend version"
|
||||||
|
msgstr "无法检测后端版本"
|
||||||
|
|
||||||
|
msgid "Token Login"
|
||||||
|
msgstr "Token 登录"
|
||||||
|
|
||||||
|
msgid "Enter your oixCloud token"
|
||||||
|
msgstr "输入您的 oixCloud Token"
|
||||||
|
|
||||||
|
msgid "Token login does not require email and password"
|
||||||
|
msgstr "Token 登录无需填写邮箱和密码"
|
||||||
|
|
||||||
|
msgid "Please enter email address"
|
||||||
|
msgstr "请输入邮箱地址"
|
||||||
|
|
||||||
|
msgid "Please enter a valid email address"
|
||||||
|
msgstr "请输入有效的邮箱地址"
|
||||||
|
|
||||||
|
msgid "Please enter password"
|
||||||
|
msgstr "请输入密码"
|
||||||
|
|
||||||
|
msgid "Please enter a valid token"
|
||||||
|
msgstr "请输入有效的 Token"
|
||||||
|
|
||||||
|
msgid "Checkin"
|
||||||
|
msgstr "试试手气"
|
||||||
|
|
||||||
|
msgid "Auto Checkin"
|
||||||
|
msgstr "自动签到"
|
||||||
|
|
||||||
|
msgid "Auto check in for oixCloud account daily bonus"
|
||||||
|
msgstr "自动签到来获取 oixCloud 每日奖励"
|
||||||
|
|
||||||
|
msgid "Auto check-in for traffic rewards and penalties"
|
||||||
|
msgstr "自动签到来获取流量奖励(惩罚)"
|
||||||
|
|
||||||
|
msgid "Multiple Must Be a Positive Integer and No More Than 100"
|
||||||
|
msgstr "倍数必须是正整数且不大于 100"
|
||||||
|
|
||||||
|
msgid "Checkin Interval"
|
||||||
|
msgstr "签到间隔"
|
||||||
|
|
||||||
|
msgid "Hours"
|
||||||
|
msgstr "小时"
|
||||||
|
|
||||||
|
msgid "Checkin interval must be between 1 and 720"
|
||||||
|
msgstr "签到间隔必须为 1 到 720 小时之间的整数"
|
||||||
|
|
||||||
|
msgid "Checkin settings saved"
|
||||||
|
msgstr "签到设置已保存"
|
||||||
|
|
||||||
|
msgid "Failed to save checkin settings, please try again"
|
||||||
|
msgstr "签到设置保存失败,请重试"
|
||||||
|
|
||||||
|
msgid "Network request failed, please check your connection and try again"
|
||||||
|
msgstr "网络请求失败,请检查网络连接后重试"
|
||||||
|
|
||||||
|
msgid "Show on Overview"
|
||||||
|
msgstr "主页显示"
|
||||||
|
|
||||||
|
msgid "Display oixCloud account info on the overview page"
|
||||||
|
msgstr "在概览页面显示 oixCloud 账户信息"
|
||||||
|
|
||||||
|
msgid "Display account info on the main page"
|
||||||
|
msgstr "在主页显示账户信息"
|
||||||
|
|
||||||
|
msgid "Setting saved"
|
||||||
|
msgstr "设置已保存"
|
||||||
|
|
||||||
|
msgid "Announcement"
|
||||||
|
msgstr "公告"
|
||||||
|
|
||||||
|
msgid "oixCloud Login Failed:"
|
||||||
|
msgstr "oixCloud 登录失败:"
|
||||||
|
|
||||||
|
msgid "oixCloud Logout Failed:"
|
||||||
|
msgstr "oixCloud 退出失败:"
|
||||||
|
|
||||||
|
msgid "Checkin Failed:"
|
||||||
|
msgstr "签到失败:"
|
||||||
|
|
||||||
msgid "After the core start, an oixCloud nodes provider will be added, which you can customize as needed"
|
|
||||||
msgstr "专用内核启动后,会添加一个 oixCloud 节点组到配置文件,供您自定义使用"
|
|
||||||
@@ -213,6 +213,8 @@ change_dnsmasq() {
|
|||||||
uci -q set dhcp.@dnsmasq[0].cachesize=0
|
uci -q set dhcp.@dnsmasq[0].cachesize=0
|
||||||
uci -q set openclash.config.cachesize_dns=1
|
uci -q set openclash.config.cachesize_dns=1
|
||||||
else
|
else
|
||||||
|
# Remove residual Dnsmasq redirect left
|
||||||
|
uci -q del_list dhcp.@dnsmasq[0].server="127.0.0.1#$dns_port"
|
||||||
uci -q set openclash.config.redirect_dns=0
|
uci -q set openclash.config.redirect_dns=0
|
||||||
uci -q set openclash.config.cachesize_dns=0
|
uci -q set openclash.config.cachesize_dns=0
|
||||||
fi
|
fi
|
||||||
@@ -573,7 +575,7 @@ do_run_file()
|
|||||||
|
|
||||||
ln -s "$meta_core_path" /etc/openclash/clash
|
ln -s "$meta_core_path" /etc/openclash/clash
|
||||||
|
|
||||||
if [ -n "$OIX_TOKEN" ]; then
|
if [ -n "$OIX_TOKEN" ] || [ "$core_type" == "Oix" ]; then
|
||||||
core_type="Oix"
|
core_type="Oix"
|
||||||
elif [ "$smart_enable" -eq 1 ] || [ "$core_type" == "Smart" ]; then
|
elif [ "$smart_enable" -eq 1 ] || [ "$core_type" == "Smart" ]; then
|
||||||
core_type="Smart"
|
core_type="Smart"
|
||||||
@@ -586,7 +588,7 @@ do_run_file()
|
|||||||
chown root:root "$CLASH"
|
chown root:root "$CLASH"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
[ ! -f "$CLASH" ] || { [ "$core_type" = "Smart" ] && [ -z "$($CLASH -v | grep 'smart')" ]; } || { [ "$core_type" = "Oix" ] && [ -z "$($CLASH -v | grep 'oix')" ]; } && {
|
[ ! -f "$CLASH" ] || { [ "$core_type" = "Smart" ] && [ -z "$($CLASH -v | grep 'smart')" ] && [ -z "$($CLASH -v | grep 'oix')" ]; } || { [ "$core_type" = "Oix" ] && [ -z "$($CLASH -v | grep 'oix')" ]; } && {
|
||||||
LOG_TIP "【$core_type】Core is not Detected installed, Ready to Download..."
|
LOG_TIP "【$core_type】Core is not Detected installed, Ready to Download..."
|
||||||
rm -rf "/tmp/clash_last_version"
|
rm -rf "/tmp/clash_last_version"
|
||||||
/usr/share/openclash/openclash_core.sh "$core_type"
|
/usr/share/openclash/openclash_core.sh "$core_type"
|
||||||
@@ -823,6 +825,7 @@ start_run_core()
|
|||||||
procd_set_param env SAFE_PATHS=/usr/share/openclash:/etc/ssl
|
procd_set_param env SAFE_PATHS=/usr/share/openclash:/etc/ssl
|
||||||
procd_append_param env CLASH_AGE_SECRET_KEY="$SECRET_KEY"
|
procd_append_param env CLASH_AGE_SECRET_KEY="$SECRET_KEY"
|
||||||
procd_append_param env OIX_TOKEN="$OIX_TOKEN"
|
procd_append_param env OIX_TOKEN="$OIX_TOKEN"
|
||||||
|
procd_append_param env OIX_PARAMS="$OIX_PARAMS"
|
||||||
procd_set_param command /bin/sh -c "$CLASH -d $CLASH_CONFIG -f \"$CONFIG_FILE\" >> $LOG_FILE 2>&1"
|
procd_set_param command /bin/sh -c "$CLASH -d $CLASH_CONFIG -f \"$CONFIG_FILE\" >> $LOG_FILE 2>&1"
|
||||||
procd_set_param user "root"
|
procd_set_param user "root"
|
||||||
procd_set_param group "nogroup"
|
procd_set_param group "nogroup"
|
||||||
@@ -925,6 +928,21 @@ ipv6_suffix_to_nft_format()
|
|||||||
echo "& ${suffix} == ${addr}"
|
echo "& ${suffix} == ${addr}"
|
||||||
} 2>/dev/null
|
} 2>/dev/null
|
||||||
|
|
||||||
|
fw4_has_dns_hijack_rule()
|
||||||
|
{
|
||||||
|
local chain="$1"
|
||||||
|
local family="$2"
|
||||||
|
|
||||||
|
case "$family" in
|
||||||
|
ipv6)
|
||||||
|
nft list chain inet fw4 "$chain" 2>/dev/null |grep 'OpenClash DNS Hijack' |grep -Eq 'meta nfproto[[:space:]]+\{?ipv6\}?|meta nfproto[[:space:]]+ipv6|ip6 nexthdr'
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
nft list chain inet fw4 "$chain" 2>/dev/null |grep 'OpenClash DNS Hijack' |grep -Evq 'meta nfproto[[:space:]]+\{?ipv6\}?|meta nfproto[[:space:]]+ipv6|ip6 nexthdr'
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
firewall_lan_ac_traffic()
|
firewall_lan_ac_traffic()
|
||||||
{
|
{
|
||||||
local src_port sport_rule dscp_rule sport_ipt dscp_ipt src_ip src_ip_v6 proto target target_ enabled family dscp rule output_rule comment
|
local src_port sport_rule dscp_rule sport_ipt dscp_ipt src_ip src_ip_v6 proto target target_ enabled family dscp rule output_rule comment
|
||||||
@@ -1153,7 +1171,7 @@ EOF
|
|||||||
#common ports
|
#common ports
|
||||||
if [ -n "$common_ports" ] && [ "$common_ports" != "0" ]; then
|
if [ -n "$common_ports" ] && [ "$common_ports" != "0" ]; then
|
||||||
if [ "$common_ports" = "1" ]; then
|
if [ "$common_ports" = "1" ]; then
|
||||||
common_port="21 22 23 53 80 123 143 194 443 465 587 853 993 995 998 2052 2053 2082 2083 2086 2095 2096 5222 5228 5229 5230 8080 8443 8880 8888 8889"
|
common_port="21 22 23 53 80 123 143 194 443 465 587 853 993 995 998 2052 2053 2082 2083 2086 2095 2096 2197 5222 5223 5228 5229 5230 8080 8443 8880 8888 8889"
|
||||||
else
|
else
|
||||||
common_port=$common_ports
|
common_port=$common_ports
|
||||||
fi
|
fi
|
||||||
@@ -1327,7 +1345,7 @@ if [ -n "$FW4" ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$enable_redirect_dns" -eq 1 ]; then
|
if [ "$enable_redirect_dns" -eq 1 ]; then
|
||||||
if [ -z "$(nft list chain inet fw4 dstnat |grep 'OpenClash DNS Hijack')" ]; then
|
if ! fw4_has_dns_hijack_rule dstnat ipv4; then
|
||||||
if [ "$lan_ac_mode" != "1" ]; then
|
if [ "$lan_ac_mode" != "1" ]; then
|
||||||
ACBLACKDNSFILTER=""
|
ACBLACKDNSFILTER=""
|
||||||
if [ "$lan_ac_mode" = "0" ]; then
|
if [ "$lan_ac_mode" = "0" ]; then
|
||||||
@@ -1338,18 +1356,19 @@ if [ -n "$FW4" ]; then
|
|||||||
ACBLACKDNSFILTER="$ACBLACKDNSFILTER ether saddr != @lan_ac_black_macs"
|
ACBLACKDNSFILTER="$ACBLACKDNSFILTER ether saddr != @lan_ac_black_macs"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
nft insert rule inet fw4 dstnat position 0 meta l4proto {tcp,udp} th dport 53 ${ACBLACKDNSFILTER} counter redirect to "$DNSPORT" comment \"OpenClash DNS Hijack\"
|
nft insert rule inet fw4 dstnat position 0 meta nfproto {ipv4} meta l4proto {tcp,udp} th dport 53 ${ACBLACKDNSFILTER} counter redirect to "$DNSPORT" comment \"OpenClash DNS Hijack\"
|
||||||
else
|
else
|
||||||
nft insert rule inet fw4 dstnat position 0 meta l4proto {tcp,udp} th dport 53 ip saddr @lan_ac_white_ips counter redirect to "$DNSPORT" comment \"OpenClash DNS Hijack\"
|
nft insert rule inet fw4 dstnat position 0 meta nfproto {ipv4} meta l4proto {tcp,udp} th dport 53 ip saddr @lan_ac_white_ips counter redirect to "$DNSPORT" comment \"OpenClash DNS Hijack\"
|
||||||
nft insert rule inet fw4 dstnat position 0 meta l4proto {tcp,udp} th dport 53 ether saddr @lan_ac_white_macs counter redirect to "$DNSPORT" comment \"OpenClash DNS Hijack\"
|
nft insert rule inet fw4 dstnat position 0 meta nfproto {ipv4} meta l4proto {tcp,udp} th dport 53 ether saddr @lan_ac_white_macs counter redirect to "$DNSPORT" comment \"OpenClash DNS Hijack\"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
if [ "$router_self_proxy" = 1 ]; then
|
if [ "$router_self_proxy" = 1 ]; then
|
||||||
nft 'add chain inet fw4 nat_output { type nat hook output priority -1; }'
|
nft 'add chain inet fw4 nat_output { type nat hook output priority -1; }'
|
||||||
nft insert rule inet fw4 nat_output position 0 skgid != 65534 meta l4proto {tcp,udp} th dport 53 ip daddr {127.0.0.1} counter redirect to "$DNSPORT" comment \"OpenClash DNS Hijack\"
|
nft insert rule inet fw4 nat_output position 0 skgid != 65534 meta nfproto {ipv4} meta l4proto {tcp,udp} th dport 53 ip daddr {127.0.0.1} counter redirect to "$DNSPORT" comment \"OpenClash DNS Hijack\"
|
||||||
fi
|
fi
|
||||||
elif [ "$enable_redirect_dns" -eq 2 ]; then
|
elif [ "$enable_redirect_dns" -eq 2 ]; then
|
||||||
nft 'add chain inet fw4 openclash_dns_redirect'
|
nft 'add chain inet fw4 openclash_dns_redirect'
|
||||||
|
nft 'flush chain inet fw4 openclash_dns_redirect'
|
||||||
if [ "$lan_ac_mode" != "1" ]; then
|
if [ "$lan_ac_mode" != "1" ]; then
|
||||||
ACBLACKDNSFILTER=""
|
ACBLACKDNSFILTER=""
|
||||||
if [ "$lan_ac_mode" = "0" ]; then
|
if [ "$lan_ac_mode" = "0" ]; then
|
||||||
@@ -1360,15 +1379,15 @@ if [ -n "$FW4" ]; then
|
|||||||
ACBLACKDNSFILTER="$ACBLACKDNSFILTER ether saddr != @lan_ac_black_macs"
|
ACBLACKDNSFILTER="$ACBLACKDNSFILTER ether saddr != @lan_ac_black_macs"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
nft add rule inet fw4 openclash_dns_redirect meta l4proto {tcp,udp} th dport 53 ${ACBLACKDNSFILTER} counter redirect to "$dns_port" comment \"OpenClash DNS Hijack\"
|
nft add rule inet fw4 openclash_dns_redirect meta nfproto {ipv4} meta l4proto {tcp,udp} th dport 53 ${ACBLACKDNSFILTER} counter redirect to "$dns_port" comment \"OpenClash DNS Hijack\"
|
||||||
else
|
else
|
||||||
nft add rule inet fw4 openclash_dns_redirect meta l4proto {tcp,udp} th dport 53 ip saddr @lan_ac_white_ips counter redirect to "$dns_port" comment \"OpenClash DNS Hijack\"
|
nft add rule inet fw4 openclash_dns_redirect meta nfproto {ipv4} meta l4proto {tcp,udp} th dport 53 ip saddr @lan_ac_white_ips counter redirect to "$dns_port" comment \"OpenClash DNS Hijack\"
|
||||||
nft add rule inet fw4 openclash_dns_redirect meta l4proto {tcp,udp} th dport 53 ether saddr @lan_ac_white_macs counter redirect to "$dns_port" comment \"OpenClash DNS Hijack\"
|
nft add rule inet fw4 openclash_dns_redirect meta nfproto {ipv4} meta l4proto {tcp,udp} th dport 53 ether saddr @lan_ac_white_macs counter redirect to "$dns_port" comment \"OpenClash DNS Hijack\"
|
||||||
fi
|
fi
|
||||||
nft 'insert rule inet fw4 dstnat position 0 meta l4proto {tcp,udp} th dport 53 counter jump openclash_dns_redirect'
|
nft 'insert rule inet fw4 dstnat position 0 meta nfproto {ipv4} meta l4proto {tcp,udp} th dport 53 counter jump openclash_dns_redirect'
|
||||||
if [ "$router_self_proxy" = 1 ]; then
|
if [ "$router_self_proxy" = 1 ]; then
|
||||||
nft 'add chain inet fw4 nat_output { type nat hook output priority -1; }'
|
nft 'add chain inet fw4 nat_output { type nat hook output priority -1; }'
|
||||||
nft insert rule inet fw4 nat_output position 0 meta l4proto {tcp,udp} th dport 53 ip daddr {127.0.0.1} meta skgid != 65534 counter redirect to "$dns_port" comment \"OpenClash DNS Hijack\"
|
nft insert rule inet fw4 nat_output position 0 meta nfproto {ipv4} meta l4proto {tcp,udp} th dport 53 ip daddr {127.0.0.1} meta skgid != 65534 counter redirect to "$dns_port" comment \"OpenClash DNS Hijack\"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -1378,17 +1397,17 @@ if [ -n "$FW4" ]; then
|
|||||||
nft 'flush chain inet fw4 openclash'
|
nft 'flush chain inet fw4 openclash'
|
||||||
nft 'add rule inet fw4 openclash ip daddr @localnetwork counter return'
|
nft 'add rule inet fw4 openclash ip daddr @localnetwork counter return'
|
||||||
nft 'add rule inet fw4 openclash ct direction reply counter return'
|
nft 'add rule inet fw4 openclash ct direction reply counter return'
|
||||||
nft add rule inet fw4 openclash ip protocol tcp ip daddr { "$fakeip_range" } counter redirect to "$proxy_port"
|
|
||||||
nft 'add rule inet fw4 openclash ip daddr @wan_ac_black_ips counter return'
|
|
||||||
nft 'add rule inet fw4 openclash th dport @wan_ac_black_ports counter return'
|
|
||||||
nft 'add rule inet fw4 openclash ip saddr @lan_ac_black_ips counter return'
|
|
||||||
nft 'add rule inet fw4 openclash ether saddr @lan_ac_black_macs counter return'
|
|
||||||
if [ "$lan_ac_mode" = "1" ] && [ -n "$(uci_get_config "lan_ac_white_ips")" ] && [ -n "$(uci_get_config "lan_ac_white_macs")" ]; then
|
if [ "$lan_ac_mode" = "1" ] && [ -n "$(uci_get_config "lan_ac_white_ips")" ] && [ -n "$(uci_get_config "lan_ac_white_macs")" ]; then
|
||||||
nft 'add rule inet fw4 openclash ether saddr != @lan_ac_white_macs ip saddr != @lan_ac_white_ips counter return'
|
nft 'add rule inet fw4 openclash ether saddr != @lan_ac_white_macs ip saddr != @lan_ac_white_ips counter return'
|
||||||
else
|
else
|
||||||
nft 'add rule inet fw4 openclash ether saddr != @lan_ac_white_macs counter return'
|
nft 'add rule inet fw4 openclash ether saddr != @lan_ac_white_macs counter return'
|
||||||
nft 'add rule inet fw4 openclash ip saddr != @lan_ac_white_ips counter return'
|
nft 'add rule inet fw4 openclash ip saddr != @lan_ac_white_ips counter return'
|
||||||
fi
|
fi
|
||||||
|
nft 'add rule inet fw4 openclash ip saddr @lan_ac_black_ips counter return'
|
||||||
|
nft 'add rule inet fw4 openclash ether saddr @lan_ac_black_macs counter return'
|
||||||
|
nft add rule inet fw4 openclash ip protocol tcp ip daddr { "$fakeip_range" } counter redirect to "$proxy_port"
|
||||||
|
nft 'add rule inet fw4 openclash ip daddr @wan_ac_black_ips counter return'
|
||||||
|
nft 'add rule inet fw4 openclash th dport @wan_ac_black_ports counter return'
|
||||||
|
|
||||||
if [ "$en_mode" = "redir-host" ]; then
|
if [ "$en_mode" = "redir-host" ]; then
|
||||||
nft 'add rule inet fw4 openclash th dport != @common_ports counter return'
|
nft 'add rule inet fw4 openclash th dport != @common_ports counter return'
|
||||||
@@ -1495,6 +1514,11 @@ if [ -n "$FW4" ]; then
|
|||||||
nft 'add rule inet fw4 mangle_output meta nfproto {ipv4} ip protocol udp counter jump openclash_mangle_output'
|
nft 'add rule inet fw4 mangle_output meta nfproto {ipv4} ip protocol udp counter jump openclash_mangle_output'
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Accept TPROXY traffic in input chain (needed when zone input policy is REJECT)
|
||||||
|
if [ -z "$(nft list chain inet fw4 input 2>/dev/null | grep 'OpenClash TPROXY Accept')" ]; then
|
||||||
|
nft insert rule inet fw4 input position 0 meta mark "$PROXY_FWMARK" accept comment \"OpenClash TPROXY Accept\"
|
||||||
|
fi
|
||||||
|
|
||||||
#quic
|
#quic
|
||||||
if [ "$disable_udp_quic" -eq 1 ]; then
|
if [ "$disable_udp_quic" -eq 1 ]; then
|
||||||
if [ "$china_ip_route" = "2" ]; then
|
if [ "$china_ip_route" = "2" ]; then
|
||||||
@@ -1507,11 +1531,6 @@ if [ -n "$FW4" ]; then
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Accept TPROXY traffic in input chain (needed when zone input policy is REJECT)
|
|
||||||
if [ -z "$(nft list chain inet fw4 input 2>/dev/null | grep 'OpenClash TPROXY Accept')" ]; then
|
|
||||||
nft insert rule inet fw4 input position 0 meta mark "$PROXY_FWMARK" accept comment \"OpenClash TPROXY Accept\"
|
|
||||||
fi
|
|
||||||
|
|
||||||
#router self proxy tcp
|
#router self proxy tcp
|
||||||
if [ "$router_self_proxy" = "1" ] || ([ "$enable_redirect_dns" != "2" ] && [ "$en_mode" = "fake-ip" ]); then
|
if [ "$router_self_proxy" = "1" ] || ([ "$enable_redirect_dns" != "2" ] && [ "$en_mode" = "fake-ip" ]); then
|
||||||
nft 'add chain inet fw4 openclash_output'
|
nft 'add chain inet fw4 openclash_output'
|
||||||
@@ -1597,6 +1616,14 @@ if [ -n "$FW4" ]; then
|
|||||||
nft 'add rule inet fw4 openclash_mangle meta l4proto {tcp,udp} iifname utun counter return'
|
nft 'add rule inet fw4 openclash_mangle meta l4proto {tcp,udp} iifname utun counter return'
|
||||||
nft 'add rule inet fw4 openclash_mangle ip daddr @localnetwork counter return'
|
nft 'add rule inet fw4 openclash_mangle ip daddr @localnetwork counter return'
|
||||||
nft 'add rule inet fw4 openclash_mangle ct direction reply counter return'
|
nft 'add rule inet fw4 openclash_mangle ct direction reply counter return'
|
||||||
|
if [ "$lan_ac_mode" = "1" ] && [ -n "$(uci_get_config "lan_ac_white_ips")" ] && [ -n "$(uci_get_config "lan_ac_white_macs")" ]; then
|
||||||
|
nft 'add rule inet fw4 openclash_mangle ether saddr != @lan_ac_white_macs ip saddr != @lan_ac_white_ips counter return'
|
||||||
|
else
|
||||||
|
nft 'add rule inet fw4 openclash_mangle ether saddr != @lan_ac_white_macs counter return'
|
||||||
|
nft 'add rule inet fw4 openclash_mangle ip saddr != @lan_ac_white_ips counter return'
|
||||||
|
fi
|
||||||
|
nft 'add rule inet fw4 openclash_mangle ip saddr @lan_ac_black_ips counter return'
|
||||||
|
nft 'add rule inet fw4 openclash_mangle ether saddr @lan_ac_black_macs counter return'
|
||||||
if [ "$en_mode_tun" -eq 1 ]; then
|
if [ "$en_mode_tun" -eq 1 ]; then
|
||||||
nft add rule inet fw4 openclash_mangle meta l4proto {tcp,udp} ip daddr { "$fakeip_range" } mark set "$PROXY_FWMARK" counter
|
nft add rule inet fw4 openclash_mangle meta l4proto {tcp,udp} ip daddr { "$fakeip_range" } mark set "$PROXY_FWMARK" counter
|
||||||
else
|
else
|
||||||
@@ -1604,14 +1631,6 @@ if [ -n "$FW4" ]; then
|
|||||||
fi
|
fi
|
||||||
nft 'add rule inet fw4 openclash_mangle ip daddr @wan_ac_black_ips counter return'
|
nft 'add rule inet fw4 openclash_mangle ip daddr @wan_ac_black_ips counter return'
|
||||||
nft 'add rule inet fw4 openclash_mangle th dport @wan_ac_black_ports counter return'
|
nft 'add rule inet fw4 openclash_mangle th dport @wan_ac_black_ports counter return'
|
||||||
nft 'add rule inet fw4 openclash_mangle ip saddr @lan_ac_black_ips counter return'
|
|
||||||
nft 'add rule inet fw4 openclash_mangle ether saddr @lan_ac_black_macs counter return'
|
|
||||||
if [ "$lan_ac_mode" = "1" ] && [ -n "$(uci_get_config "lan_ac_white_ips")" ] && [ -n "$(uci_get_config "lan_ac_white_macs")" ]; then
|
|
||||||
nft 'add rule inet fw4 openclash_mangle ether saddr != @lan_ac_white_macs ip saddr != @lan_ac_white_ips counter return'
|
|
||||||
else
|
|
||||||
nft 'add rule inet fw4 openclash_mangle ether saddr != @lan_ac_white_macs counter return'
|
|
||||||
nft 'add rule inet fw4 openclash_mangle ip saddr != @lan_ac_white_ips counter return'
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$en_mode" = "redir-host" ]; then
|
if [ "$en_mode" = "redir-host" ]; then
|
||||||
nft 'add rule inet fw4 openclash_mangle th dport != @common_ports counter return'
|
nft 'add rule inet fw4 openclash_mangle th dport != @common_ports counter return'
|
||||||
@@ -1649,10 +1668,10 @@ if [ -n "$FW4" ]; then
|
|||||||
if [ "$disable_udp_quic" -eq 1 ]; then
|
if [ "$disable_udp_quic" -eq 1 ]; then
|
||||||
if [ "$china_ip_route" = "2" ]; then
|
if [ "$china_ip_route" = "2" ]; then
|
||||||
nft insert rule inet fw4 input position 0 udp dport 443 ip daddr @china_ip_route counter reject comment \"OpenClash QUIC REJECT\"
|
nft insert rule inet fw4 input position 0 udp dport 443 ip daddr @china_ip_route counter reject comment \"OpenClash QUIC REJECT\"
|
||||||
nft insert rule inet fw4 forward position 0 udp dport 443 ip daddr @china_ip_route counter reject comment \"OpenClash QUIC REJECT\"
|
nft insert rule inet fw4 forward position 0 oifname utun udp dport 443 ip daddr @china_ip_route counter reject comment \"OpenClash QUIC REJECT\"
|
||||||
else
|
else
|
||||||
nft insert rule inet fw4 input position 0 udp dport 443 ip daddr != @china_ip_route counter reject comment \"OpenClash QUIC REJECT\"
|
nft insert rule inet fw4 input position 0 udp dport 443 ip daddr != @china_ip_route counter reject comment \"OpenClash QUIC REJECT\"
|
||||||
nft insert rule inet fw4 forward position 0 udp dport 443 ip daddr != @china_ip_route counter reject comment \"OpenClash QUIC REJECT\"
|
nft insert rule inet fw4 forward position 0 oifname utun udp dport 443 ip daddr != @china_ip_route counter reject comment \"OpenClash QUIC REJECT\"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
@@ -1689,7 +1708,7 @@ if [ -n "$FW4" ]; then
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z "$(nft list chain inet fw4 dstnat |grep 'OpenClash DNS Hijack')" ]; then
|
if ! fw4_has_dns_hijack_rule dstnat ipv6; then
|
||||||
if [ "$enable_redirect_dns" -eq 1 ]; then
|
if [ "$enable_redirect_dns" -eq 1 ]; then
|
||||||
if [ "$lan_ac_mode" != "1" ]; then
|
if [ "$lan_ac_mode" != "1" ]; then
|
||||||
ACBLACKDNSFILTER=""
|
ACBLACKDNSFILTER=""
|
||||||
@@ -1756,19 +1775,19 @@ if [ -n "$FW4" ]; then
|
|||||||
#tcp
|
#tcp
|
||||||
nft 'add chain inet fw4 openclash_v6'
|
nft 'add chain inet fw4 openclash_v6'
|
||||||
nft 'flush chain inet fw4 openclash_v6'
|
nft 'flush chain inet fw4 openclash_v6'
|
||||||
nft add rule inet fw4 openclash_v6 ip6 nexthdr {tcp} ip6 daddr { "$fakeip_range6" } counter redirect to "$proxy_port"
|
|
||||||
nft 'add rule inet fw4 openclash_v6 ip6 daddr @localnetwork6 counter return'
|
nft 'add rule inet fw4 openclash_v6 ip6 daddr @localnetwork6 counter return'
|
||||||
nft 'add rule inet fw4 openclash_v6 ct direction reply counter return'
|
nft 'add rule inet fw4 openclash_v6 ct direction reply counter return'
|
||||||
nft 'add rule inet fw4 openclash_v6 ip6 daddr @wan_ac_black_ipv6s counter return'
|
|
||||||
nft 'add rule inet fw4 openclash_v6 th dport @wan_ac_black_ports counter return'
|
|
||||||
nft 'add rule inet fw4 openclash_v6 ip6 saddr @lan_ac_black_ipv6s counter return'
|
|
||||||
nft 'add rule inet fw4 openclash_v6 ether saddr @lan_ac_black_macs counter return'
|
|
||||||
if [ "$lan_ac_mode" = "1" ] && [ -n "$(uci_get_config "lan_ac_white_ips")" ] && [ -n "$(uci_get_config "lan_ac_white_macs")" ]; then
|
if [ "$lan_ac_mode" = "1" ] && [ -n "$(uci_get_config "lan_ac_white_ips")" ] && [ -n "$(uci_get_config "lan_ac_white_macs")" ]; then
|
||||||
nft 'add rule inet fw4 openclash_v6 ether saddr != @lan_ac_white_macs ip6 saddr != @lan_ac_white_ipv6s counter return'
|
nft 'add rule inet fw4 openclash_v6 ether saddr != @lan_ac_white_macs ip6 saddr != @lan_ac_white_ipv6s counter return'
|
||||||
else
|
else
|
||||||
nft 'add rule inet fw4 openclash_v6 ether saddr != @lan_ac_white_macs counter return'
|
nft 'add rule inet fw4 openclash_v6 ether saddr != @lan_ac_white_macs counter return'
|
||||||
nft 'add rule inet fw4 openclash_v6 ip6 saddr != @lan_ac_white_ipv6s counter return'
|
nft 'add rule inet fw4 openclash_v6 ip6 saddr != @lan_ac_white_ipv6s counter return'
|
||||||
fi
|
fi
|
||||||
|
nft 'add rule inet fw4 openclash_v6 ip6 saddr @lan_ac_black_ipv6s counter return'
|
||||||
|
nft 'add rule inet fw4 openclash_v6 ether saddr @lan_ac_black_macs counter return'
|
||||||
|
nft add rule inet fw4 openclash_v6 ip6 nexthdr {tcp} ip6 daddr { "$fakeip_range6" } counter redirect to "$proxy_port"
|
||||||
|
nft 'add rule inet fw4 openclash_v6 ip6 daddr @wan_ac_black_ipv6s counter return'
|
||||||
|
nft 'add rule inet fw4 openclash_v6 th dport @wan_ac_black_ports counter return'
|
||||||
|
|
||||||
if [ "$en_mode" = "redir-host" ]; then
|
if [ "$en_mode" = "redir-host" ]; then
|
||||||
nft 'add rule inet fw4 openclash_v6 th dport != @common_ports counter return'
|
nft 'add rule inet fw4 openclash_v6 th dport != @common_ports counter return'
|
||||||
@@ -1793,6 +1812,14 @@ if [ -n "$FW4" ]; then
|
|||||||
nft 'flush chain inet fw4 openclash_mangle_v6'
|
nft 'flush chain inet fw4 openclash_mangle_v6'
|
||||||
nft 'add rule inet fw4 openclash_mangle_v6 ip6 daddr @localnetwork6 counter return'
|
nft 'add rule inet fw4 openclash_mangle_v6 ip6 daddr @localnetwork6 counter return'
|
||||||
nft 'add rule inet fw4 openclash_mangle_v6 ct direction reply counter return'
|
nft 'add rule inet fw4 openclash_mangle_v6 ct direction reply counter return'
|
||||||
|
if [ "$lan_ac_mode" = "1" ] && [ -n "$(uci_get_config "lan_ac_white_ips")" ] && [ -n "$(uci_get_config "lan_ac_white_macs")" ]; then
|
||||||
|
nft 'add rule inet fw4 openclash_mangle_v6 ether saddr != @lan_ac_white_macs ip6 saddr != @lan_ac_white_ipv6s counter return'
|
||||||
|
else
|
||||||
|
nft 'add rule inet fw4 openclash_mangle_v6 ether saddr != @lan_ac_white_macs counter return'
|
||||||
|
nft 'add rule inet fw4 openclash_mangle_v6 ip6 saddr != @lan_ac_white_ipv6s counter return'
|
||||||
|
fi
|
||||||
|
nft 'add rule inet fw4 openclash_mangle_v6 ip6 saddr @lan_ac_black_ipv6s counter return'
|
||||||
|
nft 'add rule inet fw4 openclash_mangle_v6 ether saddr @lan_ac_black_macs counter return'
|
||||||
if [ "$ipv6_mode" -ne 1 ] && [ "$ipv6_mode" -ne 3 ]; then
|
if [ "$ipv6_mode" -ne 1 ] && [ "$ipv6_mode" -ne 3 ]; then
|
||||||
if [ "$ipv6_mode" -eq 0 ]; then
|
if [ "$ipv6_mode" -eq 0 ]; then
|
||||||
nft add rule inet fw4 openclash_mangle_v6 ip6 nexthdr {tcp} ip6 daddr { "$fakeip_range6" } mark set "$PROXY_FWMARK" tproxy ip6 to :"$tproxy_port" counter accept
|
nft add rule inet fw4 openclash_mangle_v6 ip6 nexthdr {tcp} ip6 daddr { "$fakeip_range6" } mark set "$PROXY_FWMARK" tproxy ip6 to :"$tproxy_port" counter accept
|
||||||
@@ -1814,15 +1841,6 @@ if [ -n "$FW4" ]; then
|
|||||||
nft 'add rule inet fw4 openclash_mangle_v6 th dport != @common_ports counter return'
|
nft 'add rule inet fw4 openclash_mangle_v6 th dport != @common_ports counter return'
|
||||||
fi
|
fi
|
||||||
|
|
||||||
nft 'add rule inet fw4 openclash_mangle_v6 ip6 saddr @lan_ac_black_ipv6s counter return'
|
|
||||||
nft 'add rule inet fw4 openclash_mangle_v6 ether saddr @lan_ac_black_macs counter return'
|
|
||||||
if [ "$lan_ac_mode" = "1" ] && [ -n "$(uci_get_config "lan_ac_white_ips")" ] && [ -n "$(uci_get_config "lan_ac_white_macs")" ]; then
|
|
||||||
nft 'add rule inet fw4 openclash_mangle_v6 ether saddr != @lan_ac_white_macs ip6 saddr != @lan_ac_white_ipv6s counter return'
|
|
||||||
else
|
|
||||||
nft 'add rule inet fw4 openclash_mangle_v6 ether saddr != @lan_ac_white_macs counter return'
|
|
||||||
nft 'add rule inet fw4 openclash_mangle_v6 ip6 saddr != @lan_ac_white_ipv6s counter return'
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$china_ip6_route" != "0" ]; then
|
if [ "$china_ip6_route" != "0" ]; then
|
||||||
if [ "$china_ip6_route" = "1" ]; then
|
if [ "$china_ip6_route" = "1" ]; then
|
||||||
rule="ip6 daddr @china_ip6_route"
|
rule="ip6 daddr @china_ip6_route"
|
||||||
@@ -1842,29 +1860,17 @@ if [ -n "$FW4" ]; then
|
|||||||
#tcp Tproxy && TUN
|
#tcp Tproxy && TUN
|
||||||
if [ "$ipv6_mode" -ne 1 ] && [ "$ipv6_mode" -ne 3 ]; then
|
if [ "$ipv6_mode" -ne 1 ] && [ "$ipv6_mode" -ne 3 ]; then
|
||||||
if [ "$ipv6_mode" -eq 0 ]; then
|
if [ "$ipv6_mode" -eq 0 ]; then
|
||||||
if [ "$en_mode" = "fake-ip" ]; then
|
|
||||||
nft insert rule inet fw4 openclash_mangle_v6 position 0 ip6 nexthdr {tcp} ip6 daddr { "$fakeip_range6" } mark set "$PROXY_FWMARK" tproxy ip6 to :"$tproxy_port" counter accept
|
|
||||||
fi
|
|
||||||
nft add rule inet fw4 openclash_mangle_v6 ip6 nexthdr {tcp} mark set "$PROXY_FWMARK" tproxy ip6 to :"$tproxy_port" counter accept comment \"OpenClash TCP Tproxy\"
|
nft add rule inet fw4 openclash_mangle_v6 ip6 nexthdr {tcp} mark set "$PROXY_FWMARK" tproxy ip6 to :"$tproxy_port" counter accept comment \"OpenClash TCP Tproxy\"
|
||||||
else
|
else
|
||||||
if [ "$en_mode" = "fake-ip" ]; then
|
|
||||||
nft insert rule inet fw4 openclash_mangle_v6 position 0 ip6 nexthdr {tcp} ip6 daddr { "$fakeip_range6" } mark set "$PROXY_FWMARK" counter
|
|
||||||
fi
|
|
||||||
nft add rule inet fw4 openclash_mangle_v6 ip6 nexthdr {tcp} mark set "$PROXY_FWMARK" counter
|
nft add rule inet fw4 openclash_mangle_v6 ip6 nexthdr {tcp} mark set "$PROXY_FWMARK" counter
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
#udp
|
#udp
|
||||||
if [ "$ipv6_mode" -eq 2 ] || [ "$ipv6_mode" -eq 3 ]; then
|
if [ "$ipv6_mode" -eq 2 ] || [ "$ipv6_mode" -eq 3 ]; then
|
||||||
if [ "$en_mode" = "fake-ip" ]; then
|
|
||||||
nft insert rule inet fw4 openclash_mangle_v6 position 0 ip6 nexthdr {udp} ip6 daddr { "$fakeip_range6" } mark set "$PROXY_FWMARK" counter
|
|
||||||
fi
|
|
||||||
nft add rule inet fw4 openclash_mangle_v6 ip6 nexthdr {udp} mark set "$PROXY_FWMARK" counter
|
nft add rule inet fw4 openclash_mangle_v6 ip6 nexthdr {udp} mark set "$PROXY_FWMARK" counter
|
||||||
else
|
else
|
||||||
if [ "$enable_v6_udp_proxy" -eq 1 ]; then
|
if [ "$enable_v6_udp_proxy" -eq 1 ]; then
|
||||||
if [ "$en_mode" = "fake-ip" ]; then
|
|
||||||
nft insert rule inet fw4 openclash_mangle_v6 position 0 ip6 nexthdr {udp} ip6 daddr { "$fakeip_range6" } mark set "$PROXY_FWMARK" tproxy ip6 to :"$tproxy_port" counter accept
|
|
||||||
fi
|
|
||||||
nft add rule inet fw4 openclash_mangle_v6 ip6 nexthdr {udp} mark set "$PROXY_FWMARK" tproxy ip6 to :"$tproxy_port" counter accept comment \"OpenClash UDP Tproxy\"
|
nft add rule inet fw4 openclash_mangle_v6 ip6 nexthdr {udp} mark set "$PROXY_FWMARK" tproxy ip6 to :"$tproxy_port" counter accept comment \"OpenClash UDP Tproxy\"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
@@ -2509,10 +2515,10 @@ if [ -z "$FW4" ]; then
|
|||||||
if [ "$disable_udp_quic" -eq 1 ]; then
|
if [ "$disable_udp_quic" -eq 1 ]; then
|
||||||
if [ "$china_ip_route" = "2" ]; then
|
if [ "$china_ip_route" = "2" ]; then
|
||||||
iptables -I INPUT -p udp --dport 443 -m comment --comment "OpenClash QUIC REJECT" -m set --match-set china_ip_route dst -j REJECT
|
iptables -I INPUT -p udp --dport 443 -m comment --comment "OpenClash QUIC REJECT" -m set --match-set china_ip_route dst -j REJECT
|
||||||
iptables -I FORWARD -p udp --dport 443 -m comment --comment "OpenClash QUIC REJECT" -m set --match-set china_ip_route dst -j REJECT
|
iptables -I FORWARD -p udp --dport 443 -o utun -m comment --comment "OpenClash QUIC REJECT" -m set --match-set china_ip_route dst -j REJECT
|
||||||
else
|
else
|
||||||
iptables -I INPUT -p udp --dport 443 -m comment --comment "OpenClash QUIC REJECT" -m set ! --match-set china_ip_route dst -j REJECT
|
iptables -I INPUT -p udp --dport 443 -m comment --comment "OpenClash QUIC REJECT" -m set ! --match-set china_ip_route dst -j REJECT
|
||||||
iptables -I FORWARD -p udp --dport 443 -m comment --comment "OpenClash QUIC REJECT" -m set ! --match-set china_ip_route dst -j REJECT
|
iptables -I FORWARD -p udp --dport 443 -o utun -m comment --comment "OpenClash QUIC REJECT" -m set ! --match-set china_ip_route dst -j REJECT
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
@@ -3142,6 +3148,8 @@ EOF
|
|||||||
LGBM_CUSTOM_URL:string \
|
LGBM_CUSTOM_URL:string \
|
||||||
LGBM_UPDATE_INTERVAL:int \
|
LGBM_UPDATE_INTERVAL:int \
|
||||||
MIXED_PORT:int \
|
MIXED_PORT:int \
|
||||||
|
OIX_TOKEN:string \
|
||||||
|
OIX_PARAMS:string \
|
||||||
PROXY_MODE:string \
|
PROXY_MODE:string \
|
||||||
PROXY_PORT:int \
|
PROXY_PORT:int \
|
||||||
ROUTER_SELF_PROXY:int_bool \
|
ROUTER_SELF_PROXY:int_bool \
|
||||||
@@ -3435,6 +3443,7 @@ EOF
|
|||||||
if [ -f "/tmp/yaml_openclash_ruby_parts/$OPENCLASH_OVERWRITE_SID" ]; then
|
if [ -f "/tmp/yaml_openclash_ruby_parts/$OPENCLASH_OVERWRITE_SID" ]; then
|
||||||
ruby_code=$(cat "/tmp/yaml_openclash_ruby_parts/$OPENCLASH_OVERWRITE_SID")
|
ruby_code=$(cat "/tmp/yaml_openclash_ruby_parts/$OPENCLASH_OVERWRITE_SID")
|
||||||
ruby -ryaml -rYAML -I "/usr/share/openclash" -E UTF-8 -e "
|
ruby -ryaml -rYAML -I "/usr/share/openclash" -E UTF-8 -e "
|
||||||
|
begin
|
||||||
Value = YAML.load_file('$CONFIG_FILE')
|
Value = YAML.load_file('$CONFIG_FILE')
|
||||||
threads = []
|
threads = []
|
||||||
$ruby_code
|
$ruby_code
|
||||||
@@ -3442,6 +3451,9 @@ if [ -f "/tmp/yaml_openclash_ruby_parts/$OPENCLASH_OVERWRITE_SID" ]; then
|
|||||||
File.open('$CONFIG_FILE', 'w') do |f|
|
File.open('$CONFIG_FILE', 'w') do |f|
|
||||||
YAML.dump(Value, f)
|
YAML.dump(Value, f)
|
||||||
end
|
end
|
||||||
|
rescue Exception => e
|
||||||
|
YAML.LOG_ERROR('Set Custom Overwrite Script Failed,【%s】' % [e.message])
|
||||||
|
end
|
||||||
" >> $LOG_FILE 2>&1
|
" >> $LOG_FILE 2>&1
|
||||||
fi
|
fi
|
||||||
EOF
|
EOF
|
||||||
@@ -3480,6 +3492,7 @@ get_config()
|
|||||||
CFG_NO_EXT_NAME="${CFG_NAME%.*}"
|
CFG_NO_EXT_NAME="${CFG_NAME%.*}"
|
||||||
SECRET_KEY=$(uci_get_age_secret_keys "$CFG_NO_EXT_NAME")
|
SECRET_KEY=$(uci_get_age_secret_keys "$CFG_NO_EXT_NAME")
|
||||||
OIX_TOKEN=$(uci_get_config "oix_token")
|
OIX_TOKEN=$(uci_get_config "oix_token")
|
||||||
|
OIX_PARAMS=$(uci_get_config "oix_params")
|
||||||
enable=$(uci_get_config "enable")
|
enable=$(uci_get_config "enable")
|
||||||
enable_custom_clash_rules=$(uci_get_config "enable_custom_clash_rules")
|
enable_custom_clash_rules=$(uci_get_config "enable_custom_clash_rules")
|
||||||
da_password=$(uci_get_config "dashboard_password")
|
da_password=$(uci_get_config "dashboard_password")
|
||||||
@@ -3640,6 +3653,7 @@ start_service()
|
|||||||
if [ -f "$yaml_file" ]; then
|
if [ -f "$yaml_file" ]; then
|
||||||
(
|
(
|
||||||
ruby -ryaml -rYAML -I "/usr/share/openclash" -E UTF-8 -e "
|
ruby -ryaml -rYAML -I "/usr/share/openclash" -E UTF-8 -e "
|
||||||
|
begin
|
||||||
Value = YAML.load_file('$yaml_file');
|
Value = YAML.load_file('$yaml_file');
|
||||||
threads = []
|
threads = []
|
||||||
$ruby_code
|
$ruby_code
|
||||||
@@ -3647,6 +3661,9 @@ start_service()
|
|||||||
File.open('$yaml_file', 'w') do |f|
|
File.open('$yaml_file', 'w') do |f|
|
||||||
YAML.dump(Value, f)
|
YAML.dump(Value, f)
|
||||||
end
|
end
|
||||||
|
rescue Exception => e
|
||||||
|
YAML.LOG_ERROR('Set Custom Overwrite Script Failed,【%s】' % [e.message])
|
||||||
|
end
|
||||||
" >> $LOG_FILE 2>&1
|
" >> $LOG_FILE 2>&1
|
||||||
)
|
)
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -54,7 +54,7 @@
|
|||||||
# INTRANET_ALLOWED (仅允许内网访问, 0: 禁用, 1: 启用)
|
# INTRANET_ALLOWED (仅允许内网访问, 0: 禁用, 1: 启用)
|
||||||
# INTRANET_ALLOWED_WAN_NAME (仅允许内网时 WAN 接口列表名称)
|
# INTRANET_ALLOWED_WAN_NAME (仅允许内网时 WAN 接口列表名称)
|
||||||
# BYPASS_GATEWAY_COMPATIBLE (旁路网关兼容模式, 0: 禁用, 1: 启用)
|
# BYPASS_GATEWAY_COMPATIBLE (旁路网关兼容模式, 0: 禁用, 1: 启用)
|
||||||
# COMMON_PORTS (绕过常用端口的端口列表, 0: 禁用 or "21 22 23 53 80 123 143 194 443 465 587 853 993 995 998 2052 2053 2082 2083 2086 2095 2096 5222 5228 5229 5230 8080 8443 8880 8888 8889")
|
# COMMON_PORTS (绕过常用端口的端口列表, 0: 禁用 or "21 22 23 53 80 123 143 194 443 465 587 853 993 995 998 2052 2053 2082 2083 2086 2095 2096 2197 5222 5223 5228 5229 5230 8080 8443 8880 8888 8889")
|
||||||
|
|
||||||
# --- 分流相关 ---
|
# --- 分流相关 ---
|
||||||
# CHINA_IP_ROUTE (IPv4 绕过 IP 模式, 0: 禁用, 1: 绕过大陆, 2: 回国)
|
# CHINA_IP_ROUTE (IPv4 绕过 IP 模式, 0: 禁用, 1: 绕过大陆, 2: 回国)
|
||||||
|
|||||||
@@ -29,22 +29,19 @@ module YAML
|
|||||||
secret = kwargs.delete(:secret)
|
secret = kwargs.delete(:secret)
|
||||||
end
|
end
|
||||||
|
|
||||||
if secret && secret.to_s.strip != "" && yaml_content.include?("BEGIN AGE ENCRYPTED FILE")
|
if yaml_content.include?("BEGIN AGE ENCRYPTED FILE")
|
||||||
begin
|
if secret && secret.to_s.strip != ""
|
||||||
decrypted = decrypt_content_with_secret(secret.to_s, yaml_content)
|
decrypted = decrypt_content_with_secret(secret.to_s, yaml_content)
|
||||||
if decrypted && !decrypted.empty? && !decrypted.include?("BEGIN AGE ENCRYPTED FILE")
|
if decrypted && !decrypted.empty? && !decrypted.include?("BEGIN AGE ENCRYPTED FILE")
|
||||||
processed = fix_short_id_quotes(decrypted)
|
processed = fix_short_id_quotes(decrypted)
|
||||||
return load(processed, *args, **kwargs)
|
return load(processed, *args, **kwargs)
|
||||||
else
|
else
|
||||||
LOG_WARN("【%s】Decrypted content empty or still encrypted" % [filename])
|
raise "Decrypted content empty or still encrypted: [#{filename}]"
|
||||||
end
|
|
||||||
rescue => e
|
|
||||||
LOG_WARN("Decrypt attempt failed:【%s】" % [e.message])
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if (secret.nil? || secret.to_s.strip == "") && yaml_content.include?("BEGIN AGE ENCRYPTED FILE")
|
|
||||||
keys = find_age_keys_for_filename(filename)
|
keys = find_age_keys_for_filename(filename)
|
||||||
|
last_error = nil
|
||||||
(keys[:secrets] || []).each do |sec|
|
(keys[:secrets] || []).each do |sec|
|
||||||
begin
|
begin
|
||||||
decrypted = decrypt_content_with_secret(sec, yaml_content)
|
decrypted = decrypt_content_with_secret(sec, yaml_content)
|
||||||
@@ -53,13 +50,12 @@ module YAML
|
|||||||
return load(processed, *args, **kwargs)
|
return load(processed, *args, **kwargs)
|
||||||
end
|
end
|
||||||
rescue => e
|
rescue => e
|
||||||
LOG_WARN("Decrypt attempt failed for a found secret:【%s】" % [e.message])
|
last_error = e.message
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if yaml_content.include?("BEGIN AGE ENCRYPTED FILE")
|
detail = last_error ? "#{last_error}" : ""
|
||||||
raise "Encrypted file: decryption failed for %s" % [filename]
|
raise "Encrypted file: decryption failed for [#{filename}]: [#{detail}]"
|
||||||
end
|
end
|
||||||
|
|
||||||
processed_content = fix_short_id_quotes(yaml_content)
|
processed_content = fix_short_id_quotes(yaml_content)
|
||||||
@@ -67,7 +63,6 @@ module YAML
|
|||||||
end
|
end
|
||||||
|
|
||||||
def self.dump(obj, io = nil, **options)
|
def self.dump(obj, io = nil, **options)
|
||||||
begin
|
|
||||||
yaml_content = original_dump(obj, **options)
|
yaml_content = original_dump(obj, **options)
|
||||||
processed = fix_short_id_quotes(yaml_content)
|
processed = fix_short_id_quotes(yaml_content)
|
||||||
public_key = nil
|
public_key = nil
|
||||||
@@ -105,7 +100,10 @@ module YAML
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
rescue => e
|
rescue => e
|
||||||
LOG_WARN("Encrypt attempt failed:【%s】" % [e.message])
|
if io.respond_to?(:write)
|
||||||
|
io.write(processed)
|
||||||
|
end
|
||||||
|
raise
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -117,16 +115,13 @@ module YAML
|
|||||||
else
|
else
|
||||||
processed
|
processed
|
||||||
end
|
end
|
||||||
rescue => e
|
|
||||||
LOG_ERROR("Write file failed:【%s】" % [e.message])
|
|
||||||
nil
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.popen_stream(cmd, input, chunk_size: 64 * 1024)
|
def self.popen_stream(cmd, input, chunk_size: 64 * 1024)
|
||||||
output = String.new
|
output = String.new
|
||||||
IO.popen(cmd, 'r+', err: [:child, :out]) do |io|
|
IO.popen(cmd, 'r+', err: [:child, :out]) do |io|
|
||||||
io.binmode
|
io.binmode
|
||||||
|
writer_error = nil
|
||||||
writer = Thread.new do
|
writer = Thread.new do
|
||||||
begin
|
begin
|
||||||
input.bytesize.times do |i|
|
input.bytesize.times do |i|
|
||||||
@@ -136,6 +131,9 @@ module YAML
|
|||||||
end
|
end
|
||||||
io.close_write
|
io.close_write
|
||||||
rescue Errno::EPIPE
|
rescue Errno::EPIPE
|
||||||
|
# child exited before reading all input, not an error
|
||||||
|
rescue => e
|
||||||
|
writer_error = e
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -143,6 +141,7 @@ module YAML
|
|||||||
output << chunk
|
output << chunk
|
||||||
end
|
end
|
||||||
writer.join
|
writer.join
|
||||||
|
raise writer_error if writer_error
|
||||||
end
|
end
|
||||||
[output, $?]
|
[output, $?]
|
||||||
end
|
end
|
||||||
@@ -157,7 +156,6 @@ module YAML
|
|||||||
end
|
end
|
||||||
|
|
||||||
def self.find_age_keys_for_filename(filename)
|
def self.find_age_keys_for_filename(filename)
|
||||||
begin
|
|
||||||
basename = File.basename(filename)
|
basename = File.basename(filename)
|
||||||
basename_no_ext = File.basename(filename, File.extname(filename))
|
basename_no_ext = File.basename(filename, File.extname(filename))
|
||||||
publics = []
|
publics = []
|
||||||
@@ -175,25 +173,42 @@ module YAML
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
{ publics: publics, secrets: secrets }
|
{ publics: publics, secrets: secrets }
|
||||||
rescue => e
|
|
||||||
{ publics: [], secrets: [] }
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.decrypt_content_with_secret(secret, content)
|
def self.decrypt_content_with_secret(secret, content)
|
||||||
|
# Clear injection-detection env vars to prevent OIX GuardStartup from
|
||||||
|
# killing the child process (e.g. LD_PRELOAD set by opkg upgrade)
|
||||||
cmd = ['/etc/openclash/core/clash_meta', 'age', 'decrypt', secret, '-', '-']
|
cmd = ['/etc/openclash/core/clash_meta', 'age', 'decrypt', secret, '-', '-']
|
||||||
|
old_ld_preload = ENV.delete('LD_PRELOAD')
|
||||||
|
old_ld_audit = ENV.delete('LD_AUDIT')
|
||||||
|
old_dyld = ENV.delete('DYLD_INSERT_LIBRARIES')
|
||||||
|
begin
|
||||||
out, status = popen_stream(cmd, content)
|
out, status = popen_stream(cmd, content)
|
||||||
status.success? ? out : nil
|
status.success? ? out : raise("age decrypt failed: #{out.to_s.strip}")
|
||||||
rescue => e
|
rescue => e
|
||||||
nil
|
raise "age decrypt failed: #{e.message.strip}"
|
||||||
|
ensure
|
||||||
|
ENV['LD_PRELOAD'] = old_ld_preload if old_ld_preload
|
||||||
|
ENV['LD_AUDIT'] = old_ld_audit if old_ld_audit
|
||||||
|
ENV['DYLD_INSERT_LIBRARIES'] = old_dyld if old_dyld
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.encrypt_content_with_public(public, content)
|
def self.encrypt_content_with_public(public, content)
|
||||||
cmd = ['/etc/openclash/core/clash_meta', 'age', 'encrypt', public, '-', '-']
|
cmd = ['/etc/openclash/core/clash_meta', 'age', 'encrypt', public, '-', '-']
|
||||||
|
old_ld_preload = ENV.delete('LD_PRELOAD')
|
||||||
|
old_ld_audit = ENV.delete('LD_AUDIT')
|
||||||
|
old_dyld = ENV.delete('DYLD_INSERT_LIBRARIES')
|
||||||
|
begin
|
||||||
out, status = popen_stream(cmd, content)
|
out, status = popen_stream(cmd, content)
|
||||||
status.success? ? out : nil
|
status.success? ? out : raise("age encrypt failed: #{out.to_s.strip}")
|
||||||
rescue => e
|
rescue => e
|
||||||
nil
|
raise "age encrypt failed: #{e.message.strip}"
|
||||||
|
ensure
|
||||||
|
ENV['LD_PRELOAD'] = old_ld_preload if old_ld_preload
|
||||||
|
ENV['LD_AUDIT'] = old_ld_audit if old_ld_audit
|
||||||
|
ENV['DYLD_INSERT_LIBRARIES'] = old_dyld if old_dyld
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
@@ -279,8 +294,7 @@ module YAML
|
|||||||
yaml_content
|
yaml_content
|
||||||
end
|
end
|
||||||
rescue => e
|
rescue => e
|
||||||
LOG_ERROR("Fix short-id values type failed:【%s】" % [e.message])
|
raise "fix short-id values type failed: #{e.message}"
|
||||||
yaml_content
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -314,8 +328,7 @@ module YAML
|
|||||||
override
|
override
|
||||||
end
|
end
|
||||||
rescue => e
|
rescue => e
|
||||||
LOG_ERROR("YAML overwrite failed:【key: %s, operation: %s, error: %s】" % [current_key, current_operation, e.message])
|
raise "key: [#{current_key}] - operation: [#{current_operation}], error: [#{e.message}]"
|
||||||
base
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -385,8 +398,7 @@ module YAML
|
|||||||
target == condition
|
target == condition
|
||||||
end
|
end
|
||||||
rescue => e
|
rescue => e
|
||||||
LOG_ERROR("YAML overwrite failed:【(match value) => target: %s, condition: %s, error: %s】" % [target, condition, e.message])
|
raise "[match value] target: [#{target}] - condition: [#{condition}], error: [#{e.message}]"
|
||||||
false
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -602,8 +614,7 @@ module YAML
|
|||||||
collection
|
collection
|
||||||
end
|
end
|
||||||
rescue => e
|
rescue => e
|
||||||
LOG_ERROR("YAML overwrite failed:【(batch update) => update_spec: %s, error: %s】" % [update_spec, e.message])
|
raise "[batch update] update_spec: [#{update_spec}], error: [#{e.message}]"
|
||||||
collection
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -26,10 +26,11 @@ fi
|
|||||||
|
|
||||||
if [ "$CORE_TYPE" = "Oix" ] || [ -n "$OIX_TOKEN" ]; then
|
if [ "$CORE_TYPE" = "Oix" ] || [ -n "$OIX_TOKEN" ]; then
|
||||||
OIX_VERSION_URL="https://github.com/vernesong/mihomo-oix/releases/download/Pre-Alpha/version.txt"
|
OIX_VERSION_URL="https://github.com/vernesong/mihomo-oix/releases/download/Pre-Alpha/version.txt"
|
||||||
|
OIX_VERSION_P_URL="https://dl.dler.io/mihomo-oix/version.txt?tag=Pre-Alpha"
|
||||||
if [ "$github_address_mod" != "0" ] && [ "$github_address_mod" != "https://cdn.jsdelivr.net/" ] && [ "$github_address_mod" != "https://fastly.jsdelivr.net/" ] && [ "$github_address_mod" != "https://testingcf.jsdelivr.net/" ]; then
|
if [ "$github_address_mod" != "0" ] && [ "$github_address_mod" != "https://cdn.jsdelivr.net/" ] && [ "$github_address_mod" != "https://fastly.jsdelivr.net/" ] && [ "$github_address_mod" != "https://testingcf.jsdelivr.net/" ]; then
|
||||||
DOWNLOAD_URL="${github_address_mod}${OIX_VERSION_URL}"
|
DOWNLOAD_URL="${github_address_mod}${OIX_VERSION_URL}"
|
||||||
else
|
else
|
||||||
DOWNLOAD_URL="$OIX_VERSION_URL"
|
DOWNLOAD_URL="$OIX_VERSION_P_URL"
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
if [ "$github_address_mod" != "0" ]; then
|
if [ "$github_address_mod" != "0" ]; then
|
||||||
|
|||||||
@@ -70,6 +70,9 @@ config_test()
|
|||||||
config_download()
|
config_download()
|
||||||
{
|
{
|
||||||
LOG_TIP "Config File【$name】Downloading User-Agent【$sub_ua】..."
|
LOG_TIP "Config File【$name】Downloading User-Agent【$sub_ua】..."
|
||||||
|
if [ -n "$sub_headers" ]; then
|
||||||
|
LOG_TIP "Config File【$name】Custom Headers【$(echo "$sub_headers" | tr '\n' ',' | sed 's/,$//')】..."
|
||||||
|
fi
|
||||||
if [ -n "$subscribe_url_param" ] && [ -n "$c_address" ]; then
|
if [ -n "$subscribe_url_param" ] && [ -n "$c_address" ]; then
|
||||||
LOG_INFO "Config File【$name】Downloading URL【$c_address$subscribe_url_param】..."
|
LOG_INFO "Config File【$name】Downloading URL【$c_address$subscribe_url_param】..."
|
||||||
DOWNLOAD_URL="${c_address}${subscribe_url_param}"
|
DOWNLOAD_URL="${c_address}${subscribe_url_param}"
|
||||||
@@ -79,7 +82,7 @@ if [ -z "$DOWNLOAD_URL" ]; then
|
|||||||
DOWNLOAD_URL="${subscribe_url}"
|
DOWNLOAD_URL="${subscribe_url}"
|
||||||
fi
|
fi
|
||||||
DOWNLOAD_PARAM="$sub_ua"
|
DOWNLOAD_PARAM="$sub_ua"
|
||||||
DOWNLOAD_FILE_CURL "$DOWNLOAD_URL" "$CFG_FILE" "$CONFIG_FILE" "$DOWNLOAD_PARAM" "$SECRET_KEY"
|
DOWNLOAD_FILE_CURL "$DOWNLOAD_URL" "$CFG_FILE" "$CONFIG_FILE" "$DOWNLOAD_PARAM" "$SECRET_KEY" "$sub_headers"
|
||||||
DOWNLOAD_RESULT=$?
|
DOWNLOAD_RESULT=$?
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,7 +151,11 @@ config_cus_up()
|
|||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
YAML.LOG_ERROR('Filter Proxies Failed,【' + e.message + '】');
|
YAML.LOG_ERROR('Filter Proxies Failed,【' + e.message + '】');
|
||||||
ensure
|
ensure
|
||||||
|
begin
|
||||||
File.open('$CFG_FILE','w') {|f| YAML.dump(Value, f)};
|
File.open('$CFG_FILE','w') {|f| YAML.dump(Value, f)};
|
||||||
|
rescue Exception => e
|
||||||
|
YAML.LOG_ERROR('Write file failed:【%s】' % [e.message])
|
||||||
|
end
|
||||||
end" 2>/dev/null >> $LOG_FILE
|
end" 2>/dev/null >> $LOG_FILE
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
@@ -219,7 +226,7 @@ config_download_direct()
|
|||||||
sed -i '/^ \{0,\}enhanced-mode:/d' "$CFG_FILE" >/dev/null 2>&1
|
sed -i '/^ \{0,\}enhanced-mode:/d' "$CFG_FILE" >/dev/null 2>&1
|
||||||
config_test
|
config_test
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
LOG_ERROR "Config File Tested Faild, Please Check The Log Infos!"
|
LOG_ERROR "Config File Tested Failed, Please Check The Log Infos!"
|
||||||
change_dns
|
change_dns
|
||||||
config_error
|
config_error
|
||||||
return
|
return
|
||||||
@@ -314,9 +321,19 @@ convert_custom_param()
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
build_sub_headers()
|
||||||
|
{
|
||||||
|
if [ -z "$sub_headers" ]; then
|
||||||
|
sub_headers="$1"
|
||||||
|
else
|
||||||
|
sub_headers="$sub_headers
|
||||||
|
$1"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
sub_info_get()
|
sub_info_get()
|
||||||
{
|
{
|
||||||
local section="$1" subscribe_url template_path subscribe_url_param template_path_encode key_match_param key_ex_match_param c_address de_ex_keyword sub_ua append_custom_params SECRET_KEY DOWNLOAD_URL DOWNLOAD_PARAM
|
local section="$1" subscribe_url template_path subscribe_url_param template_path_encode key_match_param key_ex_match_param c_address de_ex_keyword sub_ua sub_headers append_custom_params SECRET_KEY DOWNLOAD_URL DOWNLOAD_PARAM
|
||||||
config_get_bool "enabled" "$section" "enabled" "1"
|
config_get_bool "enabled" "$section" "enabled" "1"
|
||||||
config_get "name" "$section" "name" "config"
|
config_get "name" "$section" "name" "config"
|
||||||
config_get "sub_convert" "$section" "sub_convert" ""
|
config_get "sub_convert" "$section" "sub_convert" ""
|
||||||
@@ -334,6 +351,7 @@ sub_info_get()
|
|||||||
config_get "custom_template_url" "$section" "custom_template_url" ""
|
config_get "custom_template_url" "$section" "custom_template_url" ""
|
||||||
config_get "de_ex_keyword" "$section" "de_ex_keyword" ""
|
config_get "de_ex_keyword" "$section" "de_ex_keyword" ""
|
||||||
config_get "sub_ua" "$section" "sub_ua" "clash-verge/v2.4.5"
|
config_get "sub_ua" "$section" "sub_ua" "clash-verge/v2.4.5"
|
||||||
|
config_list_foreach "$section" "sub_headers" build_sub_headers
|
||||||
SECRET_KEY=$(uci_get_age_secret_keys "$name")
|
SECRET_KEY=$(uci_get_age_secret_keys "$name")
|
||||||
|
|
||||||
CONFIG_FILE="/etc/openclash/config/$name.yaml"
|
CONFIG_FILE="/etc/openclash/config/$name.yaml"
|
||||||
@@ -419,7 +437,7 @@ sub_info_get()
|
|||||||
sed -i -E 's/protocol-param: ([^,'"'"'"''}( *#)\n\r]+)/protocol-param: "\1"/g' "$CFG_FILE" 2>/dev/null
|
sed -i -E 's/protocol-param: ([^,'"'"'"''}( *#)\n\r]+)/protocol-param: "\1"/g' "$CFG_FILE" 2>/dev/null
|
||||||
config_test
|
config_test
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
LOG_ERROR "Config File Tested Faild, Please Check The Log Infos!"
|
LOG_ERROR "Config File Tested Failed, Please Check The Log Infos!"
|
||||||
LOG_ERROR "Config File【$name】Subscribed Failed, Trying to Download Without Agent..."
|
LOG_ERROR "Config File【$name】Subscribed Failed, Trying to Download Without Agent..."
|
||||||
config_download_direct
|
config_download_direct
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -63,9 +63,9 @@ else
|
|||||||
mkdir -p /tmp/etc/openclash/core
|
mkdir -p /tmp/etc/openclash/core
|
||||||
fi
|
fi
|
||||||
|
|
||||||
CORE_CV=$($meta_core_path -v 2>/dev/null |awk -F ' ' '{print $3}' |head -1)
|
|
||||||
TMP_FILE="/tmp/clash_meta"
|
|
||||||
TARGET_CORE_PATH="$meta_core_path"
|
TARGET_CORE_PATH="$meta_core_path"
|
||||||
|
CORE_CV=$($TARGET_CORE_PATH -v 2>/dev/null |awk -F ' ' '{print $3}' |head -1)
|
||||||
|
TMP_FILE="${TARGET_CORE_PATH}.new.$$"
|
||||||
|
|
||||||
if [ "$CORE_TYPE" = "Oix" ]; then
|
if [ "$CORE_TYPE" = "Oix" ]; then
|
||||||
CORE_URL_PATH=""
|
CORE_URL_PATH=""
|
||||||
@@ -88,10 +88,11 @@ if [ "$CORE_CV" != "$CORE_LV" ] || [ -z "$CORE_CV" ]; then
|
|||||||
LOG_TIP "【$CORE_TYPE】Core Downloading, Please Try to Download and Upload Manually If Fails"
|
LOG_TIP "【$CORE_TYPE】Core Downloading, Please Try to Download and Upload Manually If Fails"
|
||||||
if [ "$CORE_TYPE" = "Oix" ]; then
|
if [ "$CORE_TYPE" = "Oix" ]; then
|
||||||
OIX_CORE_URL="https://github.com/vernesong/mihomo-oix/releases/download/Pre-Alpha/mihomo-${CPU_MODEL}-${CORE_LV}.gz"
|
OIX_CORE_URL="https://github.com/vernesong/mihomo-oix/releases/download/Pre-Alpha/mihomo-${CPU_MODEL}-${CORE_LV}.gz"
|
||||||
|
OIX_CORE_P_URL="https://dl.dler.io/mihomo-oix/mihomo-${CPU_MODEL}-${CORE_LV}.gz?tag=Pre-Alpha"
|
||||||
if [ "$github_address_mod" != "0" ] && [ "$github_address_mod" != "https://cdn.jsdelivr.net/" ] && [ "$github_address_mod" != "https://fastly.jsdelivr.net/" ] && [ "$github_address_mod" != "https://testingcf.jsdelivr.net/" ]; then
|
if [ "$github_address_mod" != "0" ] && [ "$github_address_mod" != "https://cdn.jsdelivr.net/" ] && [ "$github_address_mod" != "https://fastly.jsdelivr.net/" ] && [ "$github_address_mod" != "https://testingcf.jsdelivr.net/" ]; then
|
||||||
DOWNLOAD_URL="${github_address_mod}${OIX_CORE_URL}"
|
DOWNLOAD_URL="${github_address_mod}${OIX_CORE_URL}"
|
||||||
else
|
else
|
||||||
DOWNLOAD_URL="$OIX_CORE_URL"
|
DOWNLOAD_URL="$OIX_CORE_P_URL"
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
if [ "$github_address_mod" != "0" ]; then
|
if [ "$github_address_mod" != "0" ]; then
|
||||||
@@ -149,7 +150,7 @@ if [ "$CORE_CV" != "$CORE_LV" ] || [ -z "$CORE_CV" ]; then
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
mv "$TMP_FILE" "$TARGET_CORE_PATH" >/dev/null 2>&1
|
mv -f "$TMP_FILE" "$TARGET_CORE_PATH" >/dev/null 2>&1
|
||||||
|
|
||||||
if [ "$?" == "0" ]; then
|
if [ "$?" == "0" ]; then
|
||||||
LOG_TIP "【"$CORE_TYPE"】Core Update Successful!"
|
LOG_TIP "【"$CORE_TYPE"】Core Update Successful!"
|
||||||
|
|||||||
@@ -2,6 +2,22 @@
|
|||||||
. /usr/share/openclash/log.sh
|
. /usr/share/openclash/log.sh
|
||||||
. /usr/share/openclash/openclash_etag.sh
|
. /usr/share/openclash/openclash_etag.sh
|
||||||
|
|
||||||
|
DOWNLOAD_FAILURE_OUTPUT() {
|
||||||
|
failure_exit_code="$1"
|
||||||
|
failure_http_code="$2"
|
||||||
|
failure_output="$3"
|
||||||
|
|
||||||
|
if [ -n "$failure_output" ]; then
|
||||||
|
printf '%s' "$failure_output"
|
||||||
|
elif [ -n "$failure_http_code" ] && [ "$failure_http_code" != "000" ]; then
|
||||||
|
printf 'HTTP status %s' "$failure_http_code"
|
||||||
|
elif [ -n "$failure_exit_code" ]; then
|
||||||
|
printf 'curl exit code %s' "$failure_exit_code"
|
||||||
|
else
|
||||||
|
printf 'unknown error'
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
DOWNLOAD_FILE_CURL() {
|
DOWNLOAD_FILE_CURL() {
|
||||||
[ -z "$1" ] || [ -z "$2" ] && return 1
|
[ -z "$1" ] || [ -z "$2" ] && return 1
|
||||||
DOWNLOAD_URL=$1
|
DOWNLOAD_URL=$1
|
||||||
@@ -9,6 +25,7 @@ DOWNLOAD_FILE_CURL() {
|
|||||||
FILE_PATH=$3
|
FILE_PATH=$3
|
||||||
DOWNLOAD_UA=$4
|
DOWNLOAD_UA=$4
|
||||||
SECRET_KEY=$5
|
SECRET_KEY=$5
|
||||||
|
CUSTOM_HEADERS=$6
|
||||||
[ -z "$DOWNLOAD_UA" ] && DOWNLOAD_UA="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36"
|
[ -z "$DOWNLOAD_UA" ] && DOWNLOAD_UA="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36"
|
||||||
HEADER_TMP="/tmp/openclash_curl_header_$$"
|
HEADER_TMP="/tmp/openclash_curl_header_$$"
|
||||||
DOWNLOAD_TMP="${DOWNLOAD_PATH}.download.$$"
|
DOWNLOAD_TMP="${DOWNLOAD_PATH}.download.$$"
|
||||||
@@ -25,6 +42,15 @@ DOWNLOAD_FILE_CURL() {
|
|||||||
|
|
||||||
rm -f "$HEADER_TMP" "$DOWNLOAD_TMP"
|
rm -f "$HEADER_TMP" "$DOWNLOAD_TMP"
|
||||||
|
|
||||||
|
set --
|
||||||
|
if [ -n "$CUSTOM_HEADERS" ]; then
|
||||||
|
while IFS= read -r hdr; do
|
||||||
|
[ -n "$hdr" ] && set -- "$@" -H "$hdr"
|
||||||
|
done <<EOF
|
||||||
|
$CUSTOM_HEADERS
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
|
||||||
if [ "$SHOW_DOWNLOAD_PROGRESS" = "1" ] || [ "$SHOW_DOWNLOAD_PROGRESS" = "true" ]; then
|
if [ "$SHOW_DOWNLOAD_PROGRESS" = "1" ] || [ "$SHOW_DOWNLOAD_PROGRESS" = "true" ]; then
|
||||||
TEMP_LOG="/tmp/curl_log_$$"
|
TEMP_LOG="/tmp/curl_log_$$"
|
||||||
|
|
||||||
@@ -37,23 +63,27 @@ DOWNLOAD_FILE_CURL() {
|
|||||||
-H "User-Agent: ${DOWNLOAD_UA}" \
|
-H "User-Agent: ${DOWNLOAD_UA}" \
|
||||||
-H "X-Age-Public-Key: ${SECRET_KEY}" \
|
-H "X-Age-Public-Key: ${SECRET_KEY}" \
|
||||||
-H "$ETAG_HEADER" \
|
-H "$ETAG_HEADER" \
|
||||||
|
"$@" \
|
||||||
"$DOWNLOAD_URL" -o "$DOWNLOAD_TMP" 2>"$TEMP_LOG"
|
"$DOWNLOAD_URL" -o "$DOWNLOAD_TMP" 2>"$TEMP_LOG"
|
||||||
elif [ -n "$SECRET_KEY" ]; then
|
elif [ -n "$SECRET_KEY" ]; then
|
||||||
curl -# -L --connect-timeout 30 -m 180 --speed-time 30 --speed-limit 1 --retry 2 \
|
curl -# -L --connect-timeout 30 -m 180 --speed-time 30 --speed-limit 1 --retry 2 \
|
||||||
-D "$HEADER_TMP" \
|
-D "$HEADER_TMP" \
|
||||||
-H "User-Agent: ${DOWNLOAD_UA}" \
|
-H "User-Agent: ${DOWNLOAD_UA}" \
|
||||||
-H "X-Age-Public-Key: ${SECRET_KEY}" \
|
-H "X-Age-Public-Key: ${SECRET_KEY}" \
|
||||||
|
"$@" \
|
||||||
"$DOWNLOAD_URL" -o "$DOWNLOAD_TMP" 2>"$TEMP_LOG"
|
"$DOWNLOAD_URL" -o "$DOWNLOAD_TMP" 2>"$TEMP_LOG"
|
||||||
elif [ -n "$ETAG_HEADER" ]; then
|
elif [ -n "$ETAG_HEADER" ]; then
|
||||||
curl -# -L --connect-timeout 30 -m 180 --speed-time 30 --speed-limit 1 --retry 2 \
|
curl -# -L --connect-timeout 30 -m 180 --speed-time 30 --speed-limit 1 --retry 2 \
|
||||||
-D "$HEADER_TMP" \
|
-D "$HEADER_TMP" \
|
||||||
-H "User-Agent: ${DOWNLOAD_UA}" \
|
-H "User-Agent: ${DOWNLOAD_UA}" \
|
||||||
-H "$ETAG_HEADER" \
|
-H "$ETAG_HEADER" \
|
||||||
|
"$@" \
|
||||||
"$DOWNLOAD_URL" -o "$DOWNLOAD_TMP" 2>"$TEMP_LOG"
|
"$DOWNLOAD_URL" -o "$DOWNLOAD_TMP" 2>"$TEMP_LOG"
|
||||||
else
|
else
|
||||||
curl -# -L --connect-timeout 30 -m 180 --speed-time 30 --speed-limit 1 --retry 2 \
|
curl -# -L --connect-timeout 30 -m 180 --speed-time 30 --speed-limit 1 --retry 2 \
|
||||||
-D "$HEADER_TMP" \
|
-D "$HEADER_TMP" \
|
||||||
-H "User-Agent: ${DOWNLOAD_UA}" \
|
-H "User-Agent: ${DOWNLOAD_UA}" \
|
||||||
|
"$@" \
|
||||||
"$DOWNLOAD_URL" -o "$DOWNLOAD_TMP" 2>"$TEMP_LOG"
|
"$DOWNLOAD_URL" -o "$DOWNLOAD_TMP" 2>"$TEMP_LOG"
|
||||||
fi
|
fi
|
||||||
echo $? > "${TEMP_LOG}.exit"
|
echo $? > "${TEMP_LOG}.exit"
|
||||||
@@ -99,7 +129,8 @@ DOWNLOAD_FILE_CURL() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$EXIR_CODE" -ne 0 ] || [ "$HTTP_CODE" != "200" ]; then
|
if [ "$EXIR_CODE" -ne 0 ] || [ "$HTTP_CODE" != "200" ]; then
|
||||||
LOG_OUT "【$DOWNLOAD_PATH】Download Failed:【$OUTPUT】"
|
OUTPUT=$(DOWNLOAD_FAILURE_OUTPUT "$EXIR_CODE" "$HTTP_CODE" "${OUTPUT:-}")
|
||||||
|
LOG_OUT "【${DOWNLOAD_PATH}】Download Failed:【${OUTPUT}】"
|
||||||
rm -f "$HEADER_TMP" "$DOWNLOAD_TMP"
|
rm -f "$HEADER_TMP" "$DOWNLOAD_TMP"
|
||||||
SLOG_CLEAN
|
SLOG_CLEAN
|
||||||
return 1
|
return 1
|
||||||
@@ -116,23 +147,28 @@ DOWNLOAD_FILE_CURL() {
|
|||||||
-H "User-Agent: ${DOWNLOAD_UA}" \
|
-H "User-Agent: ${DOWNLOAD_UA}" \
|
||||||
-H "X-Age-Public-Key: ${SECRET_KEY}" \
|
-H "X-Age-Public-Key: ${SECRET_KEY}" \
|
||||||
-H "$ETAG_HEADER" \
|
-H "$ETAG_HEADER" \
|
||||||
|
"$@" \
|
||||||
"$DOWNLOAD_URL" -o "$DOWNLOAD_TMP" 2>&1)
|
"$DOWNLOAD_URL" -o "$DOWNLOAD_TMP" 2>&1)
|
||||||
elif [ -n "$SECRET_KEY" ]; then
|
elif [ -n "$SECRET_KEY" ]; then
|
||||||
CURL_OUTPUT=$(curl -w "\n%{http_code}" -SsL --connect-timeout 30 -m 180 --speed-time 30 --speed-limit 1 --retry 2 \
|
CURL_OUTPUT=$(curl -w "\n%{http_code}" -SsL --connect-timeout 30 -m 180 --speed-time 30 --speed-limit 1 --retry 2 \
|
||||||
-D "$HEADER_TMP" \
|
-D "$HEADER_TMP" \
|
||||||
-H "User-Agent: ${DOWNLOAD_UA}" \
|
-H "User-Agent: ${DOWNLOAD_UA}" \
|
||||||
-H "X-Age-Public-Key: ${SECRET_KEY}" \
|
-H "X-Age-Public-Key: ${SECRET_KEY}" \
|
||||||
|
"$@" \
|
||||||
"$DOWNLOAD_URL" -o "$DOWNLOAD_TMP" 2>&1)
|
"$DOWNLOAD_URL" -o "$DOWNLOAD_TMP" 2>&1)
|
||||||
elif [ -n "$ETAG_HEADER" ]; then
|
elif [ -n "$ETAG_HEADER" ]; then
|
||||||
CURL_OUTPUT=$(curl -w "\n%{http_code}" -SsL --connect-timeout 30 -m 180 --speed-time 30 --speed-limit 1 --retry 2 \
|
CURL_OUTPUT=$(curl -w "\n%{http_code}" -SsL --connect-timeout 30 -m 180 --speed-time 30 --speed-limit 1 --retry 2 \
|
||||||
-D "$HEADER_TMP" \
|
-D "$HEADER_TMP" \
|
||||||
-H "User-Agent: ${DOWNLOAD_UA}" \
|
-H "User-Agent: ${DOWNLOAD_UA}" \
|
||||||
-H "$ETAG_HEADER" \
|
-H "$ETAG_HEADER" \
|
||||||
|
"$@" \
|
||||||
"$DOWNLOAD_URL" -o "$DOWNLOAD_TMP" 2>&1)
|
"$DOWNLOAD_URL" -o "$DOWNLOAD_TMP" 2>&1)
|
||||||
else
|
else
|
||||||
CURL_OUTPUT=$(curl -w "\n%{http_code}" -SsL --connect-timeout 30 -m 180 --speed-time 30 --speed-limit 1 --retry 2 \
|
CURL_OUTPUT=$(curl -w "\n%{http_code}" -SsL --connect-timeout 30 -m 180 --speed-time 30 --speed-limit 1 --retry 2 \
|
||||||
-D "$HEADER_TMP" \
|
-D "$HEADER_TMP" \
|
||||||
-H "User-Agent: ${DOWNLOAD_UA}" "$DOWNLOAD_URL" -o "$DOWNLOAD_TMP" 2>&1)
|
-H "User-Agent: ${DOWNLOAD_UA}" \
|
||||||
|
"$@" \
|
||||||
|
"$DOWNLOAD_URL" -o "$DOWNLOAD_TMP" 2>&1)
|
||||||
fi
|
fi
|
||||||
EXIR_CODE=$?
|
EXIR_CODE=$?
|
||||||
HTTP_CODE=$(echo "$CURL_OUTPUT" | tail -n1)
|
HTTP_CODE=$(echo "$CURL_OUTPUT" | tail -n1)
|
||||||
@@ -149,7 +185,8 @@ DOWNLOAD_FILE_CURL() {
|
|||||||
|
|
||||||
if [ "$EXIR_CODE" -ne 0 ] || [ "$HTTP_CODE" != "200" ]; then
|
if [ "$EXIR_CODE" -ne 0 ] || [ "$HTTP_CODE" != "200" ]; then
|
||||||
OUTPUT=$(echo "$CURL_OUTPUT" | sed '$d' | grep -a 'curl:' | tail -n 1)
|
OUTPUT=$(echo "$CURL_OUTPUT" | sed '$d' | grep -a 'curl:' | tail -n 1)
|
||||||
LOG_OUT "【$DOWNLOAD_PATH】Download Failed:【$OUTPUT】"
|
OUTPUT=$(DOWNLOAD_FAILURE_OUTPUT "$EXIR_CODE" "$HTTP_CODE" "$OUTPUT")
|
||||||
|
LOG_OUT "【${DOWNLOAD_PATH}】Download Failed:【${OUTPUT}】"
|
||||||
rm -f "$HEADER_TMP" "$DOWNLOAD_TMP"
|
rm -f "$HEADER_TMP" "$DOWNLOAD_TMP"
|
||||||
SLOG_CLEAN
|
SLOG_CLEAN
|
||||||
return 1
|
return 1
|
||||||
@@ -157,7 +194,7 @@ DOWNLOAD_FILE_CURL() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if ! mv -f "$DOWNLOAD_TMP" "$DOWNLOAD_PATH"; then
|
if ! mv -f "$DOWNLOAD_TMP" "$DOWNLOAD_PATH"; then
|
||||||
LOG_OUT "【$DOWNLOAD_PATH】Download Failed:【Unable to save download file】"
|
LOG_OUT "【${DOWNLOAD_PATH}】Download Failed:【Unable to save download file】"
|
||||||
rm -f "$HEADER_TMP" "$DOWNLOAD_TMP"
|
rm -f "$HEADER_TMP" "$DOWNLOAD_TMP"
|
||||||
SLOG_CLEAN
|
SLOG_CLEAN
|
||||||
return 1
|
return 1
|
||||||
|
|||||||
@@ -418,6 +418,25 @@ cat >> "$DEBUG_LOG" <<-EOF
|
|||||||
\`\`\`
|
\`\`\`
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
if [ -n "$(command -v fw4)" ]; then
|
||||||
|
cat >> "$DEBUG_LOG" <<-EOF
|
||||||
|
|
||||||
|
## NFTABLES 防火墙设置
|
||||||
|
|
||||||
|
\`\`\`bash
|
||||||
|
# nft list chain inet fw4 (all chains)
|
||||||
|
EOF
|
||||||
|
for nft in "input" "forward" "dstnat" "srcnat" "nat_output" "mangle_prerouting" "mangle_output"; do
|
||||||
|
nft list chain inet fw4 "$nft" >> "$DEBUG_LOG" 2>/dev/null && echo "" >> "$DEBUG_LOG"
|
||||||
|
done >/dev/null 2>&1
|
||||||
|
for nft in "openclash" "openclash_mangle" "openclash_mangle_output" "openclash_output" "openclash_post" "openclash_wan_input" "openclash_dns_hijack" "openclash_dns_redirect" "openclash_v6" "openclash_mangle_v6" "openclash_mangle_output_v6" "openclash_output_v6" "openclash_post_v6" "openclash_wan6_input"; do
|
||||||
|
nft list chain inet fw4 "$nft" >> "$DEBUG_LOG" 2>/dev/null && echo "" >> "$DEBUG_LOG"
|
||||||
|
done >/dev/null 2>&1
|
||||||
|
echo "" >> "$DEBUG_LOG"
|
||||||
|
cat >> "$DEBUG_LOG" <<-EOF
|
||||||
|
\`\`\`
|
||||||
|
EOF
|
||||||
|
else
|
||||||
cat >> "$DEBUG_LOG" <<-EOF
|
cat >> "$DEBUG_LOG" <<-EOF
|
||||||
|
|
||||||
## IPTABLES 防火墙设置
|
## IPTABLES 防火墙设置
|
||||||
@@ -482,39 +501,63 @@ echo "" >> "$DEBUG_LOG"
|
|||||||
cat >> "$DEBUG_LOG" <<-EOF
|
cat >> "$DEBUG_LOG" <<-EOF
|
||||||
\`\`\`
|
\`\`\`
|
||||||
EOF
|
EOF
|
||||||
|
fi
|
||||||
|
|
||||||
if [ -n "$(command -v fw4)" ]; then
|
if [ -n "$(command -v fw4)" ]; then
|
||||||
cat >> "$DEBUG_LOG" <<-EOF
|
cat >> "$DEBUG_LOG" <<-EOF
|
||||||
|
|
||||||
## NFTABLES 防火墙设置
|
## NFT Sets 状态
|
||||||
|
|
||||||
\`\`\`bash
|
\`\`\`bash
|
||||||
# nft list chain inet fw4 (all chains)
|
# nft list sets inet fw4
|
||||||
EOF
|
EOF
|
||||||
for nft in "input" "forward" "dstnat" "srcnat" "nat_output" "mangle_prerouting" "mangle_output"; do
|
nft list sets inet fw4 2>/dev/null | sed -n '/^table inet fw4 {/,/^}/p' | awk '
|
||||||
nft list chain inet fw4 "$nft" >> "$DEBUG_LOG" 2>/dev/null
|
/elements = \{/ { in_el=1; el=0; trunc=0; indent=""; elem_indent=$0; sub(/[^[:space:]].*/, "", elem_indent); print; if (/[[:space:]]+\}[[:space:]]*$/) in_el=0; next }
|
||||||
done >/dev/null 2>&1
|
in_el && /\}/ { in_el=0; if (trunc) { print indent "..."; print elem_indent "}" } else print; next }
|
||||||
for nft in "openclash" "openclash_mangle" "openclash_mangle_output" "openclash_output" "openclash_post" "openclash_wan_input" "openclash_dns_hijack" "openclash_dns_redirect" "openclash_v6" "openclash_mangle_v6" "openclash_mangle_output_v6" "openclash_output_v6" "openclash_post_v6" "openclash_wan6_input"; do
|
in_el {
|
||||||
nft list chain inet fw4 "$nft" >> "$DEBUG_LOG" 2>/dev/null
|
if (!indent) { match($0, /^[[:space:]]*/); indent = substr($0, 1, RLENGTH) }
|
||||||
done >/dev/null 2>&1
|
n = split($0, a, ","); el += n
|
||||||
|
if (el > 10 && !trunc) { trunc=1; next }
|
||||||
|
if (trunc) next
|
||||||
|
print
|
||||||
|
}
|
||||||
|
!in_el {
|
||||||
|
print
|
||||||
|
if (/^[[:space:]]+\}$/) print ""
|
||||||
|
}
|
||||||
|
' >> "$DEBUG_LOG"
|
||||||
echo "" >> "$DEBUG_LOG"
|
echo "" >> "$DEBUG_LOG"
|
||||||
cat >> "$DEBUG_LOG" <<-EOF
|
cat >> "$DEBUG_LOG" <<-EOF
|
||||||
\`\`\`
|
\`\`\`
|
||||||
EOF
|
EOF
|
||||||
fi
|
else
|
||||||
|
|
||||||
cat >> "$DEBUG_LOG" <<-EOF
|
cat >> "$DEBUG_LOG" <<-EOF
|
||||||
|
|
||||||
## IPSET状态
|
## IPSET状态
|
||||||
|
|
||||||
\`\`\`bash
|
\`\`\`bash
|
||||||
# ipset list -t
|
# ipset list
|
||||||
EOF
|
EOF
|
||||||
ipset list -t >> "$DEBUG_LOG"
|
for set in $(ipset list -n 2>/dev/null); do
|
||||||
|
ipset list "$set" 2>/dev/null | awk -v max=10 '
|
||||||
|
/^Members:/ { in_members=1; count=0; print; next }
|
||||||
|
in_members {
|
||||||
|
if (/^[[:space:]]*[^[:space:]]/) {
|
||||||
|
count++
|
||||||
|
if (count <= max) { print; next }
|
||||||
|
else if (count == max+1) { print "..."; next }
|
||||||
|
else { next }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ print }
|
||||||
|
'
|
||||||
|
echo ""
|
||||||
|
done >> "$DEBUG_LOG" 2>/dev/null
|
||||||
echo "" >> "$DEBUG_LOG"
|
echo "" >> "$DEBUG_LOG"
|
||||||
cat >> "$DEBUG_LOG" <<-EOF
|
cat >> "$DEBUG_LOG" <<-EOF
|
||||||
\`\`\`
|
\`\`\`
|
||||||
EOF
|
EOF
|
||||||
|
fi
|
||||||
|
|
||||||
cat >> "$DEBUG_LOG" <<-EOF
|
cat >> "$DEBUG_LOG" <<-EOF
|
||||||
|
|
||||||
@@ -631,7 +674,14 @@ cat >> "$DEBUG_LOG" <<-EOF
|
|||||||
|
|
||||||
## DNS 解析文件
|
## DNS 解析文件
|
||||||
|
|
||||||
### **Dnsmasq 当前默认 resolv 文件:** \`$dnsmasq_default_resolvfile\`
|
### **Dnsmasq 当前默认 resolv 文件**
|
||||||
|
|
||||||
|
\`\`\`bash
|
||||||
|
EOF
|
||||||
|
echo $dnsmasq_default_resolvfile >> "$DEBUG_LOG"
|
||||||
|
echo "" >> "$DEBUG_LOG"
|
||||||
|
cat >> "$DEBUG_LOG" <<-EOF
|
||||||
|
\`\`\`
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
if [ -s "/tmp/resolv.conf.auto" ]; then
|
if [ -s "/tmp/resolv.conf.auto" ]; then
|
||||||
|
|||||||
@@ -14,6 +14,55 @@
|
|||||||
rm -rf "/tmp/lock/openclash_dashboard.lock" 2>/dev/null
|
rm -rf "/tmp/lock/openclash_dashboard.lock" 2>/dev/null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
validate_dashboard_dir() {
|
||||||
|
local dashboard_dir="$1"
|
||||||
|
local index_file="${dashboard_dir%/}/index.html"
|
||||||
|
local ref=""
|
||||||
|
local asset=""
|
||||||
|
local script_found=0
|
||||||
|
|
||||||
|
[ -s "$index_file" ] || return 1
|
||||||
|
|
||||||
|
while IFS= read -r ref; do
|
||||||
|
[ -n "$ref" ] || continue
|
||||||
|
ref="${ref%%#*}"
|
||||||
|
ref="${ref%%\?*}"
|
||||||
|
ref="${ref#./}"
|
||||||
|
|
||||||
|
case "$ref" in
|
||||||
|
""|http://*|https://*|//*|/*|data:*|mailto:*) continue ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
case "$ref" in
|
||||||
|
*.js|*.css)
|
||||||
|
asset="${dashboard_dir%/}/$ref"
|
||||||
|
[ -s "$asset" ] || return 1
|
||||||
|
[ "${ref##*.}" = "js" ] && script_found=1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done <<-EOF
|
||||||
|
$(grep -oE "(src|href)[[:space:]]*=[[:space:]]*['\"][^'\"]+['\"]" "$index_file" 2>/dev/null | sed "s/^[^=]*=[[:space:]]*['\"]//;s/['\"]$//")
|
||||||
|
EOF
|
||||||
|
|
||||||
|
[ "$script_found" -eq 1 ]
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup_dashboard_tmp() {
|
||||||
|
rm -rf "$DASH_FILE_DIR" "$DASH_FILE_TMP" "$NEW_FILE_DIR" "$OLD_FILE_DIR" >/dev/null 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
restore_old_dashboard() {
|
||||||
|
rm -rf "$TARGET_FILE_DIR" >/dev/null 2>&1
|
||||||
|
[ -d "$OLD_FILE_DIR" ] && mv "$OLD_FILE_DIR" "$TARGET_FILE_DIR" >/dev/null 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
log_unzip_error() {
|
||||||
|
LOG_OUT "Control Panel【$DASH_NAME - $DASH_TYPE】Unzip Error!" && SLOG_CLEAN
|
||||||
|
cleanup_dashboard_tmp
|
||||||
|
del_lock
|
||||||
|
exit 2
|
||||||
|
}
|
||||||
|
|
||||||
set_lock
|
set_lock
|
||||||
|
|
||||||
DASH_NAME="$1"
|
DASH_NAME="$1"
|
||||||
@@ -23,7 +72,6 @@
|
|||||||
github_address_mod=$(uci_get_config "github_address_mod" || echo 0)
|
github_address_mod=$(uci_get_config "github_address_mod" || echo 0)
|
||||||
if [ "$DASH_NAME" == "Dashboard" ]; then
|
if [ "$DASH_NAME" == "Dashboard" ]; then
|
||||||
UNPACK_FILE_DIR="/usr/share/openclash/ui/dashboard/"
|
UNPACK_FILE_DIR="/usr/share/openclash/ui/dashboard/"
|
||||||
BACKUP_FILE_DIR="/usr/share/openclash/ui/dashboard_backup/"
|
|
||||||
if [ "$DASH_TYPE" == "Official" ]; then
|
if [ "$DASH_TYPE" == "Official" ]; then
|
||||||
DOWNLOAD_PATH="https://codeload.github.com/ayanamist/clash-dashboard/zip/refs/heads/gh-pages"
|
DOWNLOAD_PATH="https://codeload.github.com/ayanamist/clash-dashboard/zip/refs/heads/gh-pages"
|
||||||
FILE_PATH_INCLUDE="clash-dashboard-gh-pages"
|
FILE_PATH_INCLUDE="clash-dashboard-gh-pages"
|
||||||
@@ -33,7 +81,6 @@
|
|||||||
fi
|
fi
|
||||||
elif [ "$DASH_NAME" == "Yacd" ]; then
|
elif [ "$DASH_NAME" == "Yacd" ]; then
|
||||||
UNPACK_FILE_DIR="/usr/share/openclash/ui/yacd/"
|
UNPACK_FILE_DIR="/usr/share/openclash/ui/yacd/"
|
||||||
BACKUP_FILE_DIR="/usr/share/openclash/ui/yacd_backup/"
|
|
||||||
if [ "$DASH_TYPE" == "Official" ]; then
|
if [ "$DASH_TYPE" == "Official" ]; then
|
||||||
DOWNLOAD_PATH="https://codeload.github.com/haishanh/yacd/zip/refs/heads/gh-pages"
|
DOWNLOAD_PATH="https://codeload.github.com/haishanh/yacd/zip/refs/heads/gh-pages"
|
||||||
FILE_PATH_INCLUDE="yacd-gh-pages"
|
FILE_PATH_INCLUDE="yacd-gh-pages"
|
||||||
@@ -43,15 +90,17 @@
|
|||||||
fi
|
fi
|
||||||
elif [ "$DASH_NAME" == "Zashboard" ]; then
|
elif [ "$DASH_NAME" == "Zashboard" ]; then
|
||||||
UNPACK_FILE_DIR="/usr/share/openclash/ui/zashboard/"
|
UNPACK_FILE_DIR="/usr/share/openclash/ui/zashboard/"
|
||||||
BACKUP_FILE_DIR="/usr/share/openclash/ui/zashboard_backup/"
|
|
||||||
DOWNLOAD_PATH="https://codeload.github.com/Zephyruso/zashboard/zip/refs/heads/gh-pages-cdn-fonts"
|
DOWNLOAD_PATH="https://codeload.github.com/Zephyruso/zashboard/zip/refs/heads/gh-pages-cdn-fonts"
|
||||||
FILE_PATH_INCLUDE="zashboard-gh-pages-cdn-fonts"
|
FILE_PATH_INCLUDE="zashboard-gh-pages-cdn-fonts"
|
||||||
else
|
else
|
||||||
UNPACK_FILE_DIR="/usr/share/openclash/ui/metacubexd/"
|
UNPACK_FILE_DIR="/usr/share/openclash/ui/metacubexd/"
|
||||||
BACKUP_FILE_DIR="/usr/share/openclash/ui/metacubexd_backup/"
|
|
||||||
DOWNLOAD_PATH="https://codeload.github.com/MetaCubeX/metacubexd/zip/refs/heads/gh-pages"
|
DOWNLOAD_PATH="https://codeload.github.com/MetaCubeX/metacubexd/zip/refs/heads/gh-pages"
|
||||||
FILE_PATH_INCLUDE="metacubexd-gh-pages"
|
FILE_PATH_INCLUDE="metacubexd-gh-pages"
|
||||||
fi
|
fi
|
||||||
|
TARGET_FILE_DIR="${UNPACK_FILE_DIR%/}"
|
||||||
|
TARGET_PARENT_DIR="$(dirname "$TARGET_FILE_DIR")"
|
||||||
|
NEW_FILE_DIR="${TARGET_PARENT_DIR}/.openclash_dashboard_new.$$"
|
||||||
|
OLD_FILE_DIR="${TARGET_PARENT_DIR}/.openclash_dashboard_old.$$"
|
||||||
|
|
||||||
DOWNLOAD_FILE_CURL "$DOWNLOAD_PATH" "$DASH_FILE_DIR" "$UNPACK_FILE_DIR"
|
DOWNLOAD_FILE_CURL "$DOWNLOAD_PATH" "$DASH_FILE_DIR" "$UNPACK_FILE_DIR"
|
||||||
DOWNLOAD_RESULT=$?
|
DOWNLOAD_RESULT=$?
|
||||||
@@ -59,44 +108,43 @@
|
|||||||
if [ "$DOWNLOAD_RESULT" -eq 0 ] && [ -s "$DASH_FILE_DIR" ]; then
|
if [ "$DOWNLOAD_RESULT" -eq 0 ] && [ -s "$DASH_FILE_DIR" ]; then
|
||||||
unzip -qt "$DASH_FILE_DIR" >/dev/null 2>&1
|
unzip -qt "$DASH_FILE_DIR" >/dev/null 2>&1
|
||||||
if [ "$?" -eq "0" ]; then
|
if [ "$?" -eq "0" ]; then
|
||||||
cp -rf "$UNPACK_FILE_DIR". "$BACKUP_FILE_DIR" >/dev/null 2>&1
|
rm -rf "$DASH_FILE_TMP" "$NEW_FILE_DIR" "$OLD_FILE_DIR" >/dev/null 2>&1
|
||||||
rm -rf "$UNPACK_FILE_DIR" >/dev/null 2>&1
|
|
||||||
unzip -q "$DASH_FILE_DIR" -d "$DASH_FILE_TMP" >/dev/null 2>&1
|
unzip -q "$DASH_FILE_DIR" -d "$DASH_FILE_TMP" >/dev/null 2>&1
|
||||||
if [ "$?" -eq "0" ] && [ -d "$DASH_FILE_TMP$FILE_PATH_INCLUDE" ]; then
|
if [ "$?" -eq "0" ] && [ -d "$DASH_FILE_TMP$FILE_PATH_INCLUDE" ]; then
|
||||||
cp -rf "$DASH_FILE_TMP$FILE_PATH_INCLUDE"/. "$UNPACK_FILE_DIR" >/dev/null 2>&1
|
mkdir -p "$NEW_FILE_DIR" >/dev/null 2>&1 || log_unzip_error
|
||||||
rm -rf "$DASH_FILE_DIR" >/dev/null 2>&1
|
cp -rf "$DASH_FILE_TMP$FILE_PATH_INCLUDE"/. "$NEW_FILE_DIR" >/dev/null 2>&1 || log_unzip_error
|
||||||
rm -rf "$BACKUP_FILE_DIR" >/dev/null 2>&1
|
validate_dashboard_dir "$NEW_FILE_DIR" || log_unzip_error
|
||||||
rm -rf "$DASH_FILE_TMP" >/dev/null 2>&1
|
|
||||||
|
mkdir -p "$TARGET_PARENT_DIR" >/dev/null 2>&1 || log_unzip_error
|
||||||
|
if [ -d "$TARGET_FILE_DIR" ]; then
|
||||||
|
mv "$TARGET_FILE_DIR" "$OLD_FILE_DIR" >/dev/null 2>&1 || log_unzip_error
|
||||||
|
fi
|
||||||
|
if mv "$NEW_FILE_DIR" "$TARGET_FILE_DIR" >/dev/null 2>&1 && validate_dashboard_dir "$TARGET_FILE_DIR"; then
|
||||||
|
cleanup_dashboard_tmp
|
||||||
LOG_OUT "Control Panel【$DASH_NAME - $DASH_TYPE】Download Successful!" && SLOG_CLEAN
|
LOG_OUT "Control Panel【$DASH_NAME - $DASH_TYPE】Download Successful!" && SLOG_CLEAN
|
||||||
del_lock
|
del_lock
|
||||||
exit 0
|
exit 0
|
||||||
else
|
else
|
||||||
LOG_OUT "Control Panel【$DASH_NAME - $DASH_TYPE】Unzip Error!" && SLOG_CLEAN
|
restore_old_dashboard
|
||||||
cp -rf "$BACKUP_FILE_DIR". "$UNPACK_FILE_DIR" >/dev/null 2>&1
|
log_unzip_error
|
||||||
rm -rf "$DASH_FILE_DIR" >/dev/null 2>&1
|
|
||||||
rm -rf "$BACKUP_FILE_DIR" >/dev/null 2>&1
|
|
||||||
rm -rf "$DASH_FILE_TMP" >/dev/null 2>&1
|
|
||||||
del_lock
|
|
||||||
exit 2
|
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
LOG_OUT "Control Panel【$DASH_NAME - $DASH_TYPE】Unzip Error!" && SLOG_CLEAN
|
log_unzip_error
|
||||||
cp -rf "$BACKUP_FILE_DIR". "$UNPACK_FILE_DIR" >/dev/null 2>&1
|
fi
|
||||||
rm -rf "$DASH_FILE_DIR" >/dev/null 2>&1
|
else
|
||||||
rm -rf "$BACKUP_FILE_DIR" >/dev/null 2>&1
|
log_unzip_error
|
||||||
rm -rf "$DASH_FILE_TMP" >/dev/null 2>&1
|
|
||||||
del_lock
|
|
||||||
exit 2
|
|
||||||
fi
|
fi
|
||||||
elif [ "$DOWNLOAD_RESULT" -eq 2 ]; then
|
elif [ "$DOWNLOAD_RESULT" -eq 2 ]; then
|
||||||
|
if validate_dashboard_dir "$UNPACK_FILE_DIR"; then
|
||||||
|
cleanup_dashboard_tmp
|
||||||
LOG_OUT "Control Panel【$DASH_NAME - $DASH_TYPE】Download Successful!" && SLOG_CLEAN
|
LOG_OUT "Control Panel【$DASH_NAME - $DASH_TYPE】Download Successful!" && SLOG_CLEAN
|
||||||
del_lock
|
del_lock
|
||||||
exit 0
|
exit 0
|
||||||
else
|
else
|
||||||
cp -rf "$BACKUP_FILE_DIR". "$UNPACK_FILE_DIR" >/dev/null 2>&1
|
log_unzip_error
|
||||||
rm -rf "$BACKUP_FILE_DIR" >/dev/null 2>&1
|
fi
|
||||||
rm -rf "$DASH_FILE_DIR" >/dev/null 2>&1
|
else
|
||||||
rm -rf "$DASH_FILE_TMP" >/dev/null 2>&1
|
cleanup_dashboard_tmp
|
||||||
LOG_OUT "Control Panel【$DASH_NAME - $DASH_TYPE】Download Error!" && SLOG_CLEAN
|
LOG_OUT "Control Panel【$DASH_NAME - $DASH_TYPE】Download Error!" && SLOG_CLEAN
|
||||||
del_lock
|
del_lock
|
||||||
exit 1
|
exit 1
|
||||||
|
|||||||
@@ -53,23 +53,23 @@ function unlock_auto_select()
|
|||||||
local only_original = "only support homemade!"
|
local only_original = "only support homemade!"
|
||||||
local no_unlock = "not support unlock!"
|
local no_unlock = "not support unlock!"
|
||||||
local select_success = "unlock node auto selected successfully, the current selected is"
|
local select_success = "unlock node auto selected successfully, the current selected is"
|
||||||
local select_faild = "unlock node auto selected failed, no node available, rolled back to the"
|
local select_failed = "unlock node auto selected failed, no node available, rolled back to the"
|
||||||
local test_faild = "unlock test faild!"
|
local test_failed = "unlock test failed!"
|
||||||
local test_start = "Start auto select unlock proxy..."
|
local test_start = "Start auto select unlock proxy..."
|
||||||
local original_no_select = "only support homemade! the type of group is not select, auto select could not work!"
|
local original_no_select = "only support homemade! the type of group is not select, auto select could not work!"
|
||||||
local no_unlock_no_select = "not support unlock! the type of group is not select, auto select could not work!"
|
local no_unlock_no_select = "not support unlock! the type of group is not select, auto select could not work!"
|
||||||
local faild_no_select = "unlock test faild! the type of group is not select, auto select could not work!"
|
local failed_no_select = "unlock test failed! the type of group is not select, auto select could not work!"
|
||||||
local original_test_start = "only support homemade! start auto select unlock proxy..."
|
local original_test_start = "only support homemade! start auto select unlock proxy..."
|
||||||
local no_unlock_test_start = "not support unlock! start auto select unlock proxy..."
|
local no_unlock_test_start = "not support unlock! start auto select unlock proxy..."
|
||||||
local faild_test_start = "unlock test faild! start auto select unlock proxy..."
|
local failed_test_start = "unlock test failed! start auto select unlock proxy..."
|
||||||
local area_i18 = ", area:"
|
local area_i18 = ", area:"
|
||||||
local select_faild_other_region = "unlock node auto selected failed, no node match the regex, rolled back to other full support node"
|
local select_failed_other_region = "unlock node auto selected failed, no node match the regex, rolled back to other full support node"
|
||||||
local other_region_unlock_test = ", but not match the regex!"
|
local other_region_unlock_test = ", but not match the regex!"
|
||||||
local other_region_unlock_no_select = ", but not match the regex! the type of group is not select, auto select could not work!"
|
local other_region_unlock_no_select = ", but not match the regex! the type of group is not select, auto select could not work!"
|
||||||
local other_region_unlock_test_start = ", but not match the regex! start auto select unlock proxy..."
|
local other_region_unlock_test_start = ", but not match the regex! start auto select unlock proxy..."
|
||||||
local select_all_full_support = "unlock node test finished, rolled back to the full support node"
|
local select_all_full_support = "unlock node test finished, rolled back to the full support node"
|
||||||
local select_all_other_region = "unlock node test finished, no node match the regex, rolled back to other full support node"
|
local select_all_other_region = "unlock node test finished, no node match the regex, rolled back to other full support node"
|
||||||
local select_all_faild = "unlock node test finished, no node available, rolled back to the"
|
local select_all_failed = "unlock node test finished, no node available, rolled back to the"
|
||||||
local no_nodes_filter = "no nodes name match the regex!"
|
local no_nodes_filter = "no nodes name match the regex!"
|
||||||
local select_success_no_old_region = "unlock node auto selected successfully, no node match the old region, rolled back to other full support node"
|
local select_success_no_old_region = "unlock node auto selected successfully, no node match the old region, rolled back to other full support node"
|
||||||
local no_old_region_unlock_test = "full support but not match the old region!"
|
local no_old_region_unlock_test = "full support but not match the old region!"
|
||||||
@@ -222,9 +222,9 @@ function unlock_auto_select()
|
|||||||
delete_cache(type, get_group_now(info, value.now))
|
delete_cache(type, get_group_now(info, value.now))
|
||||||
else
|
else
|
||||||
if not all_test then
|
if not all_test then
|
||||||
print(now..faild_test_start)
|
print(now..failed_test_start)
|
||||||
else
|
else
|
||||||
print(now..test_faild)
|
print(now..test_failed)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -351,7 +351,7 @@ function unlock_auto_select()
|
|||||||
end
|
end
|
||||||
delete_cache(type, proxy)
|
delete_cache(type, proxy)
|
||||||
else
|
else
|
||||||
print(now..test_faild)
|
print(now..test_failed)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
break
|
break
|
||||||
@@ -429,7 +429,7 @@ function unlock_auto_select()
|
|||||||
end
|
end
|
||||||
delete_cache(type, value.all[i])
|
delete_cache(type, value.all[i])
|
||||||
else
|
else
|
||||||
print(now..faild_no_select)
|
print(now..failed_no_select)
|
||||||
end
|
end
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
@@ -482,15 +482,15 @@ function unlock_auto_select()
|
|||||||
end
|
end
|
||||||
elseif #other_region_unlock > 0 then
|
elseif #other_region_unlock > 0 then
|
||||||
if not all_test then
|
if not all_test then
|
||||||
print(os.date("%Y-%m-%d %H:%M:%S").." [Info] "..gorup_i18.."【"..value.name.."】"..select_faild_other_region..group_now)
|
print(os.date("%Y-%m-%d %H:%M:%S").." [Info] "..gorup_i18.."【"..value.name.."】"..select_failed_other_region..group_now)
|
||||||
else
|
else
|
||||||
print(os.date("%Y-%m-%d %H:%M:%S").." [Info] "..gorup_i18.."【"..value.name.."】"..select_all_other_region..group_now)
|
print(os.date("%Y-%m-%d %H:%M:%S").." [Info] "..gorup_i18.."【"..value.name.."】"..select_all_other_region..group_now)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
if not all_test then
|
if not all_test then
|
||||||
print(os.date("%Y-%m-%d %H:%M:%S").." [Info] "..gorup_i18.."【"..value.name.."】"..select_faild..group_now)
|
print(os.date("%Y-%m-%d %H:%M:%S").." [Info] "..gorup_i18.."【"..value.name.."】"..select_failed..group_now)
|
||||||
else
|
else
|
||||||
print(os.date("%Y-%m-%d %H:%M:%S").." [Info] "..gorup_i18.."【"..value.name.."】"..select_all_faild..group_now)
|
print(os.date("%Y-%m-%d %H:%M:%S").." [Info] "..gorup_i18.."【"..value.name.."】"..select_all_failed..group_now)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
close_connections()
|
close_connections()
|
||||||
@@ -503,7 +503,7 @@ function unlock_auto_select()
|
|||||||
else
|
else
|
||||||
group_now = value.name.." ➟ "..proxy_default
|
group_now = value.name.." ➟ "..proxy_default
|
||||||
end
|
end
|
||||||
print(os.date("%Y-%m-%d %H:%M:%S").." [Info] "..gorup_i18.."【"..value.name.."】"..select_faild.."【"..group_now.."】")
|
print(os.date("%Y-%m-%d %H:%M:%S").." [Info] "..gorup_i18.."【"..value.name.."】"..select_failed.."【"..group_now.."】")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
elseif #nodes_filter(get_group_now(info, value.name), info) ~= 0 then
|
elseif #nodes_filter(get_group_now(info, value.name), info) ~= 0 then
|
||||||
@@ -542,7 +542,7 @@ function unlock_auto_select()
|
|||||||
print(now..no_unlock_no_select)
|
print(now..no_unlock_no_select)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
print(now..faild_no_select)
|
print(now..failed_no_select)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ if [ -n "$OP_CV" ] && [ -n "$OP_LV" ] && version_compare "$OP_CV" "$OP_LV" && [
|
|||||||
update_retry=$((update_retry + 1))
|
update_retry=$((update_retry + 1))
|
||||||
run_with_timeout 30 apk update >/dev/null 2>&1
|
run_with_timeout 30 apk update >/dev/null 2>&1
|
||||||
apk_ret=$?
|
apk_ret=$?
|
||||||
rm -f /lib/apk/db/lock /tmp/apk.lock
|
rm -f /lib/apk/db/lock
|
||||||
if [ $apk_ret -eq 0 ]; then
|
if [ $apk_ret -eq 0 ]; then
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -54,12 +54,12 @@ begin
|
|||||||
provider_config = YAML.load_file(path, secret: provider['age-secret-key']) rescue nil
|
provider_config = YAML.load_file(path, secret: provider['age-secret-key']) rescue nil
|
||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
YAML.LOG_WARN('Set Proxies Address Skip: Failed【' + path + ': ' + e.message+'】')
|
YAML.LOG_WARN('Set Proxies Address Skip: Failed【' + path + ': ' + e.message+'】')
|
||||||
continue
|
next
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
if file_is_age_encrypted
|
if file_is_age_encrypted
|
||||||
if name == 'oixCloud'
|
if name == 'oixCloud'
|
||||||
YAML.LOG_TIP('Set Proxies Address Skip: Bypass【oixCloud】')
|
YAML.LOG('Set Proxies Address Skip: Bypass【oixCloud】')
|
||||||
else
|
else
|
||||||
YAML.LOG_WARN('Set Proxies Address Skip: Failed【' + path + '】File is AGE encrypted but no secret key provided')
|
YAML.LOG_WARN('Set Proxies Address Skip: Failed【' + path + '】File is AGE encrypted but no secret key provided')
|
||||||
end
|
end
|
||||||
@@ -73,7 +73,7 @@ begin
|
|||||||
servers_to_process.push(p['server']) if p.key?('server')
|
servers_to_process.push(p['server']) if p.key?('server')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
rescue Psych::SyntaxError, ArgumentError
|
rescue StandardError
|
||||||
if not provider.key?('age-secret-key') or provider['age-secret-key'].to_s.empty?
|
if not provider.key?('age-secret-key') or provider['age-secret-key'].to_s.empty?
|
||||||
if file_is_age_encrypted
|
if file_is_age_encrypted
|
||||||
YAML.LOG_WARN('Failed to parse config file with Lua helper【' + path + '】File is AGE encrypted, cannot parse with Lua')
|
YAML.LOG_WARN('Failed to parse config file with Lua helper【' + path + '】File is AGE encrypted, cannot parse with Lua')
|
||||||
@@ -313,7 +313,7 @@ fi
|
|||||||
if [ -f "$upnp_lease_file" ]; then
|
if [ -f "$upnp_lease_file" ]; then
|
||||||
#del
|
#del
|
||||||
if [ -n "$FW4" ]; then
|
if [ -n "$FW4" ]; then
|
||||||
for i in `$(nft list chain inet fw4 openclash_upnp |grep "return")`
|
nft list chain inet fw4 openclash_upnp 2>/dev/null |grep "return" |while read -r i
|
||||||
do
|
do
|
||||||
upnp_ip=$(echo "$i" |awk -F 'ip saddr ' '{print $2}' |awk '{print $1}')
|
upnp_ip=$(echo "$i" |awk -F 'ip saddr ' '{print $2}' |awk '{print $1}')
|
||||||
upnp_dp=$(echo "$i" |awk -F 'sport ' '{print $2}' |awk '{print $1}')
|
upnp_dp=$(echo "$i" |awk -F 'sport ' '{print $2}' |awk '{print $1}')
|
||||||
@@ -326,7 +326,7 @@ fi
|
|||||||
fi
|
fi
|
||||||
done >/dev/null 2>&1
|
done >/dev/null 2>&1
|
||||||
else
|
else
|
||||||
for i in `$(iptables -t mangle -nL openclash_upnp |grep "RETURN")`
|
iptables -t mangle -nL openclash_upnp 2>/dev/null |grep "RETURN" |while read -r i
|
||||||
do
|
do
|
||||||
upnp_ip=$(echo "$i" |awk '{print $4}')
|
upnp_ip=$(echo "$i" |awk '{print $4}')
|
||||||
upnp_dp=$(echo "$i" |awk -F 'spt:' '{print $2}')
|
upnp_dp=$(echo "$i" |awk -F 'spt:' '{print $2}')
|
||||||
@@ -339,7 +339,7 @@ fi
|
|||||||
done >/dev/null 2>&1
|
done >/dev/null 2>&1
|
||||||
fi
|
fi
|
||||||
#add
|
#add
|
||||||
if [ -s "$upnp_lease_file" ] && [ -n "$(iptables --line-numbers -t nat -xnvL openclash_upnp 2>/dev/null)"] || [ -n "$(nft list chain inet fw4 openclash_upnp 2>/dev/null)"]; then
|
if [ -s "$upnp_lease_file" ] && { { [ -z "$FW4" ] && [ -n "$(iptables --line-numbers -t mangle -xnvL openclash_upnp 2>/dev/null)" ]; } || { [ -n "$FW4" ] && [ -n "$(nft list chain inet fw4 openclash_upnp 2>/dev/null)" ]; }; }; then
|
||||||
cat "$upnp_lease_file" |while read -r line
|
cat "$upnp_lease_file" |while read -r line
|
||||||
do
|
do
|
||||||
if [ -n "$line" ]; then
|
if [ -n "$line" ]; then
|
||||||
@@ -408,59 +408,59 @@ fi
|
|||||||
if [ "$STREAM_AUTO_SELECT" -ne 0 ]; then
|
if [ "$STREAM_AUTO_SELECT" -ne 0 ]; then
|
||||||
if [ "$(expr "$STREAM_AUTO_SELECT" % "$stream_auto_select_interval")" -eq 0 ] || [ "$STREAM_AUTO_SELECT" -eq 1 ]; then
|
if [ "$(expr "$STREAM_AUTO_SELECT" % "$stream_auto_select_interval")" -eq 0 ] || [ "$STREAM_AUTO_SELECT" -eq 1 ]; then
|
||||||
if [ "$stream_auto_select_netflix" -eq 1 ]; then
|
if [ "$stream_auto_select_netflix" -eq 1 ]; then
|
||||||
LOG_TIP "【Netflix】Start Auto Select Unlock Proxy..."
|
LOG_INFO "【Netflix】Start Auto Select Unlock Proxy..."
|
||||||
/usr/share/openclash/openclash_streaming_unlock.lua "Netflix" >> $LOG_FILE
|
/usr/share/openclash/openclash_streaming_unlock.lua "Netflix" >> $LOG_FILE
|
||||||
fi
|
fi
|
||||||
if [ "$stream_auto_select_disney" -eq 1 ]; then
|
if [ "$stream_auto_select_disney" -eq 1 ]; then
|
||||||
LOG_TIP "【Disney Plus】Start Auto Select Unlock Proxy..."
|
LOG_INFO "【Disney Plus】Start Auto Select Unlock Proxy..."
|
||||||
/usr/share/openclash/openclash_streaming_unlock.lua "Disney Plus" >> $LOG_FILE
|
/usr/share/openclash/openclash_streaming_unlock.lua "Disney Plus" >> $LOG_FILE
|
||||||
fi
|
fi
|
||||||
if [ "$stream_auto_select_google_not_cn" -eq 1 ]; then
|
if [ "$stream_auto_select_google_not_cn" -eq 1 ]; then
|
||||||
LOG_TIP "【Google Not CN】Start Auto Select Unlock Proxy..."
|
LOG_INFO "【Google Not CN】Start Auto Select Unlock Proxy..."
|
||||||
/usr/share/openclash/openclash_streaming_unlock.lua "Google" >> $LOG_FILE
|
/usr/share/openclash/openclash_streaming_unlock.lua "Google" >> $LOG_FILE
|
||||||
fi
|
fi
|
||||||
if [ "$stream_auto_select_ytb" -eq 1 ]; then
|
if [ "$stream_auto_select_ytb" -eq 1 ]; then
|
||||||
LOG_TIP "【YouTube Premium】Start Auto Select Unlock Proxy..."
|
LOG_INFO "【YouTube Premium】Start Auto Select Unlock Proxy..."
|
||||||
/usr/share/openclash/openclash_streaming_unlock.lua "YouTube Premium" >> $LOG_FILE
|
/usr/share/openclash/openclash_streaming_unlock.lua "YouTube Premium" >> $LOG_FILE
|
||||||
fi
|
fi
|
||||||
if [ "$stream_auto_select_prime_video" -eq 1 ]; then
|
if [ "$stream_auto_select_prime_video" -eq 1 ]; then
|
||||||
LOG_TIP "【Amazon Prime Video】Start Auto Select Unlock Proxy..."
|
LOG_INFO "【Amazon Prime Video】Start Auto Select Unlock Proxy..."
|
||||||
/usr/share/openclash/openclash_streaming_unlock.lua "Amazon Prime Video" >> $LOG_FILE
|
/usr/share/openclash/openclash_streaming_unlock.lua "Amazon Prime Video" >> $LOG_FILE
|
||||||
fi
|
fi
|
||||||
if [ "$stream_auto_select_hbo_max" -eq 1 ]; then
|
if [ "$stream_auto_select_hbo_max" -eq 1 ]; then
|
||||||
LOG_TIP "【HBO Max】Start Auto Select Unlock Proxy..."
|
LOG_INFO "【HBO Max】Start Auto Select Unlock Proxy..."
|
||||||
/usr/share/openclash/openclash_streaming_unlock.lua "HBO Max" >> $LOG_FILE
|
/usr/share/openclash/openclash_streaming_unlock.lua "HBO Max" >> $LOG_FILE
|
||||||
fi
|
fi
|
||||||
if [ "$stream_auto_select_tvb_anywhere" -eq 1 ]; then
|
if [ "$stream_auto_select_tvb_anywhere" -eq 1 ]; then
|
||||||
LOG_TIP "【TVB Anywhere+】Start Auto Select Unlock Proxy..."
|
LOG_INFO "【TVB Anywhere+】Start Auto Select Unlock Proxy..."
|
||||||
/usr/share/openclash/openclash_streaming_unlock.lua "TVB Anywhere+" >> $LOG_FILE
|
/usr/share/openclash/openclash_streaming_unlock.lua "TVB Anywhere+" >> $LOG_FILE
|
||||||
fi
|
fi
|
||||||
if [ "$stream_auto_select_dazn" -eq 1 ]; then
|
if [ "$stream_auto_select_dazn" -eq 1 ]; then
|
||||||
LOG_TIP "【DAZN】Start Auto Select Unlock Proxy..."
|
LOG_INFO "【DAZN】Start Auto Select Unlock Proxy..."
|
||||||
/usr/share/openclash/openclash_streaming_unlock.lua "DAZN" >> $LOG_FILE
|
/usr/share/openclash/openclash_streaming_unlock.lua "DAZN" >> $LOG_FILE
|
||||||
fi
|
fi
|
||||||
if [ "$stream_auto_select_paramount_plus" -eq 1 ]; then
|
if [ "$stream_auto_select_paramount_plus" -eq 1 ]; then
|
||||||
LOG_TIP "【Paramount Plus】Start Auto Select Unlock Proxy..."
|
LOG_INFO "【Paramount Plus】Start Auto Select Unlock Proxy..."
|
||||||
/usr/share/openclash/openclash_streaming_unlock.lua "Paramount Plus" >> $LOG_FILE
|
/usr/share/openclash/openclash_streaming_unlock.lua "Paramount Plus" >> $LOG_FILE
|
||||||
fi
|
fi
|
||||||
if [ "$stream_auto_select_discovery_plus" -eq 1 ]; then
|
if [ "$stream_auto_select_discovery_plus" -eq 1 ]; then
|
||||||
LOG_TIP "【Discovery Plus】Start Auto Select Unlock Proxy..."
|
LOG_INFO "【Discovery Plus】Start Auto Select Unlock Proxy..."
|
||||||
/usr/share/openclash/openclash_streaming_unlock.lua "Discovery Plus" >> $LOG_FILE
|
/usr/share/openclash/openclash_streaming_unlock.lua "Discovery Plus" >> $LOG_FILE
|
||||||
fi
|
fi
|
||||||
if [ "$stream_auto_select_bilibili" -eq 1 ]; then
|
if [ "$stream_auto_select_bilibili" -eq 1 ]; then
|
||||||
LOG_TIP "【Bilibili】Start Auto Select Unlock Proxy..."
|
LOG_INFO "【Bilibili】Start Auto Select Unlock Proxy..."
|
||||||
/usr/share/openclash/openclash_streaming_unlock.lua "Bilibili" >> $LOG_FILE
|
/usr/share/openclash/openclash_streaming_unlock.lua "Bilibili" >> $LOG_FILE
|
||||||
fi
|
fi
|
||||||
if [ "$stream_auto_select_openai" -eq 1 ]; then
|
if [ "$stream_auto_select_openai" -eq 1 ]; then
|
||||||
LOG_TIP "【OpenAI】Start Auto Select Unlock Proxy..."
|
LOG_INFO "【OpenAI】Start Auto Select Unlock Proxy..."
|
||||||
/usr/share/openclash/openclash_streaming_unlock.lua "OpenAI" >> $LOG_FILE
|
/usr/share/openclash/openclash_streaming_unlock.lua "OpenAI" >> $LOG_FILE
|
||||||
fi
|
fi
|
||||||
if [ "$stream_auto_select_claude" -eq 1 ]; then
|
if [ "$stream_auto_select_claude" -eq 1 ]; then
|
||||||
LOG_TIP "【Claude】Start Auto Select Unlock Proxy..."
|
LOG_INFO "【Claude】Start Auto Select Unlock Proxy..."
|
||||||
/usr/share/openclash/openclash_streaming_unlock.lua "Claude" >> $LOG_FILE
|
/usr/share/openclash/openclash_streaming_unlock.lua "Claude" >> $LOG_FILE
|
||||||
fi
|
fi
|
||||||
if [ "$stream_auto_select_gemini" -eq 1 ]; then
|
if [ "$stream_auto_select_gemini" -eq 1 ]; then
|
||||||
LOG_TIP "【Gemini】Start Auto Select Unlock Proxy..."
|
LOG_INFO "【Gemini】Start Auto Select Unlock Proxy..."
|
||||||
/usr/share/openclash/openclash_streaming_unlock.lua "Gemini" >> $LOG_FILE
|
/usr/share/openclash/openclash_streaming_unlock.lua "Gemini" >> $LOG_FILE
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -810,6 +810,10 @@ begin
|
|||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
YAML.LOG_ERROR('Config File Overwrite Failed,【%s】' % [e.message])
|
YAML.LOG_ERROR('Config File Overwrite Failed,【%s】' % [e.message])
|
||||||
ensure
|
ensure
|
||||||
|
begin
|
||||||
File.open(config_file, 'w') { |f| YAML.dump(Value, f) }
|
File.open(config_file, 'w') { |f| YAML.dump(Value, f) }
|
||||||
|
rescue Exception => e
|
||||||
|
YAML.LOG_ERROR('Write file failed:【%s】' % [e.message])
|
||||||
|
end
|
||||||
end
|
end
|
||||||
" 2>/dev/null >> $LOG_FILE
|
" 2>/dev/null >> $LOG_FILE
|
||||||
@@ -424,7 +424,11 @@ yml_other_set()
|
|||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
YAML.LOG_ERROR('Config File Overwrite Failed,【%s】' % [e.message])
|
YAML.LOG_ERROR('Config File Overwrite Failed,【%s】' % [e.message])
|
||||||
ensure
|
ensure
|
||||||
|
begin
|
||||||
File.open('$2','w') {|f| YAML.dump(Value, f)};
|
File.open('$2','w') {|f| YAML.dump(Value, f)};
|
||||||
|
rescue Exception => e
|
||||||
|
YAML.LOG_ERROR('Write file failed:【%s】' % [e.message])
|
||||||
|
end
|
||||||
end" 2>/dev/null >> $LOG_FILE
|
end" 2>/dev/null >> $LOG_FILE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large.
Load diff
File renamed without changes.
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
+112
-112
@@ -1,43 +1,43 @@
|
|||||||
var CM6=(()=>{var _k=Object.create;var es=Object.defineProperty;var Zk=Object.getOwnPropertyDescriptor;var Dk=Object.getOwnPropertyNames;var Ik=Object.getPrototypeOf,Bk=Object.prototype.hasOwnProperty;var Nk=(t,e,i)=>e in t?es(t,e,{enumerable:!0,configurable:!0,writable:!0,value:i}):t[e]=i;var jk=(t,e)=>()=>{try{return e||t((e={exports:{}}).exports,e),e.exports}catch(i){throw e=0,i}},zk=(t,e)=>{for(var i in e)es(t,i,{get:e[i],enumerable:!0})},gg=(t,e,i,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of Dk(e))!Bk.call(t,r)&&r!==i&&es(t,r,{get:()=>e[r],enumerable:!(n=Zk(e,r))||n.enumerable});return t};var Yk=(t,e,i)=>(i=t!=null?_k(Ik(t)):{},gg(e||!t||!t.__esModule?es(i,"default",{value:t,enumerable:!0}):i,t)),qk=t=>gg(es({},"__esModule",{value:!0}),t);var J=(t,e,i)=>Nk(t,typeof e!="symbol"?e+"":e,i);var xk=jk((CZ,Sk)=>{function ak(t){return t instanceof Map?t.clear=t.delete=t.set=function(){throw new Error("map is read-only")}:t instanceof Set&&(t.add=t.clear=t.delete=function(){throw new Error("set is read-only")}),Object.freeze(t),Object.getOwnPropertyNames(t).forEach(e=>{let i=t[e],n=typeof i;(n==="object"||n==="function")&&!Object.isFrozen(i)&&ak(i)}),t}var sc=class{constructor(e){e.data===void 0&&(e.data={}),this.data=e.data,this.isMatchIgnored=!1}ignoreMatch(){this.isMatchIgnored=!0}};function ck(t){return t.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function on(t,...e){let i=Object.create(null);for(let n in t)i[n]=t[n];return e.forEach(function(n){for(let r in n)i[r]=n[r]}),i}var yL="</span>",ik=t=>!!t.scope,SL=(t,{prefix:e})=>{if(t.startsWith("language:"))return t.replace("language:","language-");if(t.includes(".")){let i=t.split(".");return[`${e}${i.shift()}`,...i.map((n,r)=>`${n}${"_".repeat(r+1)}`)].join(" ")}return`${e}${t}`},tg=class{constructor(e,i){this.buffer="",this.classPrefix=i.classPrefix,e.walk(this)}addText(e){this.buffer+=ck(e)}openNode(e){if(!ik(e))return;let i=SL(e.scope,{prefix:this.classPrefix});this.span(i)}closeNode(e){ik(e)&&(this.buffer+=yL)}value(){return this.buffer}span(e){this.buffer+=`<span class="${e}">`}},nk=(t={})=>{let e={children:[]};return Object.assign(e,t),e},ig=class t{constructor(){this.rootNode=nk(),this.stack=[this.rootNode]}get top(){return this.stack[this.stack.length-1]}get root(){return this.rootNode}add(e){this.top.children.push(e)}openNode(e){let i=nk({scope:e});this.add(i),this.stack.push(i)}closeNode(){if(this.stack.length>1)return this.stack.pop()}closeAllNodes(){for(;this.closeNode(););}toJSON(){return JSON.stringify(this.rootNode,null,4)}walk(e){return this.constructor._walk(e,this.rootNode)}static _walk(e,i){return typeof i=="string"?e.addText(i):i.children&&(e.openNode(i),i.children.forEach(n=>this._walk(e,n)),e.closeNode(i)),e}static _collapse(e){typeof e!="string"&&e.children&&(e.children.every(i=>typeof i=="string")?e.children=[e.children.join("")]:e.children.forEach(i=>{t._collapse(i)}))}},ng=class extends ig{constructor(e){super(),this.options=e}addText(e){e!==""&&this.add(e)}startScope(e){this.openNode(e)}endScope(){this.closeNode()}__addSublanguage(e,i){let n=e.root;i&&(n.scope=`language:${i}`),this.add(n)}toHTML(){return new tg(this,this.options).value()}finalize(){return this.closeAllNodes(),!0}};function vo(t){return t?typeof t=="string"?t:t.source:null}function hk(t){return Kn("(?=",t,")")}function xL(t){return Kn("(?:",t,")*")}function kL(t){return Kn("(?:",t,")?")}function Kn(...t){return t.map(i=>vo(i)).join("")}function wL(t){let e=t[t.length-1];return typeof e=="object"&&e.constructor===Object?(t.splice(t.length-1,1),e):{}}function sg(...t){return"("+(wL(t).capture?"":"?:")+t.map(n=>vo(n)).join("|")+")"}function fk(t){return new RegExp(t.toString()+"|").exec("").length-1}function vL(t,e){let i=t&&t.exec(e);return i&&i.index===0}var QL=/\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./;function og(t,{joinWith:e}){let i=0;return t.map(n=>{i+=1;let r=i,s=vo(n),o="";for(;s.length>0;){let l=QL.exec(s);if(!l){o+=s;break}o+=s.substring(0,l.index),s=s.substring(l.index+l[0].length),l[0][0]==="\\"&&l[1]?o+="\\"+String(Number(l[1])+r):(o+=l[0],l[0]==="("&&i++)}return o}).map(n=>`(${n})`).join(e)}var PL=/\b\B/,uk="[a-zA-Z]\\w*",lg="[a-zA-Z_]\\w*",dk="\\b\\d+(\\.\\d+)?",pk="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",gk="\\b(0b[01]+)",$L="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",TL=(t={})=>{let e=/^#![ ]*\//;return t.binary&&(t.begin=Kn(e,/.*\b/,t.binary,/\b.*/)),on({scope:"meta",begin:e,end:/$/,relevance:0,"on:begin":(i,n)=>{i.index!==0&&n.ignoreMatch()}},t)},Qo={begin:"\\\\[\\s\\S]",relevance:0},CL={scope:"string",begin:"'",end:"'",illegal:"\\n",contains:[Qo]},AL={scope:"string",begin:'"',end:'"',illegal:"\\n",contains:[Qo]},RL={begin:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|suLine truncated
|
var CM6=(()=>{var Dk=Object.create;var es=Object.defineProperty;var Ik=Object.getOwnPropertyDescriptor;var Bk=Object.getOwnPropertyNames;var Nk=Object.getPrototypeOf,jk=Object.prototype.hasOwnProperty;var zk=(t,e,i)=>e in t?es(t,e,{enumerable:!0,configurable:!0,writable:!0,value:i}):t[e]=i;var Yk=(t,e)=>()=>{try{return e||t((e={exports:{}}).exports,e),e.exports}catch(i){throw e=0,i}},qk=(t,e)=>{for(var i in e)es(t,i,{get:e[i],enumerable:!0})},bg=(t,e,i,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of Bk(e))!jk.call(t,r)&&r!==i&&es(t,r,{get:()=>e[r],enumerable:!(n=Ik(e,r))||n.enumerable});return t};var Wk=(t,e,i)=>(i=t!=null?Dk(Nk(t)):{},bg(e||!t||!t.__esModule?es(i,"default",{value:t,enumerable:!0}):i,t)),Vk=t=>bg(es({},"__esModule",{value:!0}),t);var K=(t,e,i)=>zk(t,typeof e!="symbol"?e+"":e,i);var Qk=Yk((CZ,vk)=>{function uk(t){return t instanceof Map?t.clear=t.delete=t.set=function(){throw new Error("map is read-only")}:t instanceof Set&&(t.add=t.clear=t.delete=function(){throw new Error("set is read-only")}),Object.freeze(t),Object.getOwnPropertyNames(t).forEach(e=>{let i=t[e],n=typeof i;(n==="object"||n==="function")&&!Object.isFrozen(i)&&uk(i)}),t}var ac=class{constructor(e){e.data===void 0&&(e.data={}),this.data=e.data,this.isMatchIgnored=!1}ignoreMatch(){this.isMatchIgnored=!0}};function dk(t){return t.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function on(t,...e){let i=Object.create(null);for(let n in t)i[n]=t[n];return e.forEach(function(n){for(let r in n)i[r]=n[r]}),i}var xL="</span>",ok=t=>!!t.scope,kL=(t,{prefix:e})=>{if(t.startsWith("language:"))return t.replace("language:","language-");if(t.includes(".")){let i=t.split(".");return[`${e}${i.shift()}`,...i.map((n,r)=>`${n}${"_".repeat(r+1)}`)].join(" ")}return`${e}${t}`},rg=class{constructor(e,i){this.buffer="",this.classPrefix=i.classPrefix,e.walk(this)}addText(e){this.buffer+=dk(e)}openNode(e){if(!ok(e))return;let i=kL(e.scope,{prefix:this.classPrefix});this.span(i)}closeNode(e){ok(e)&&(this.buffer+=xL)}value(){return this.buffer}span(e){this.buffer+=`<span class="${e}">`}},lk=(t={})=>{let e={children:[]};return Object.assign(e,t),e},sg=class t{constructor(){this.rootNode=lk(),this.stack=[this.rootNode]}get top(){return this.stack[this.stack.length-1]}get root(){return this.rootNode}add(e){this.top.children.push(e)}openNode(e){let i=lk({scope:e});this.add(i),this.stack.push(i)}closeNode(){if(this.stack.length>1)return this.stack.pop()}closeAllNodes(){for(;this.closeNode(););}toJSON(){return JSON.stringify(this.rootNode,null,4)}walk(e){return this.constructor._walk(e,this.rootNode)}static _walk(e,i){return typeof i=="string"?e.addText(i):i.children&&(e.openNode(i),i.children.forEach(n=>this._walk(e,n)),e.closeNode(i)),e}static _collapse(e){typeof e!="string"&&e.children&&(e.children.every(i=>typeof i=="string")?e.children=[e.children.join("")]:e.children.forEach(i=>{t._collapse(i)}))}},og=class extends sg{constructor(e){super(),this.options=e}addText(e){e!==""&&this.add(e)}startScope(e){this.openNode(e)}endScope(){this.closeNode()}__addSublanguage(e,i){let n=e.root;i&&(n.scope=`language:${i}`),this.add(n)}toHTML(){return new rg(this,this.options).value()}finalize(){return this.closeAllNodes(),!0}};function Qo(t){return t?typeof t=="string"?t:t.source:null}function pk(t){return Hn("(?=",t,")")}function wL(t){return Hn("(?:",t,")*")}function vL(t){return Hn("(?:",t,")?")}function Hn(...t){return t.map(i=>Qo(i)).join("")}function QL(t){let e=t[t.length-1];return typeof e=="object"&&e.constructor===Object?(t.splice(t.length-1,1),e):{}}function ag(...t){return"("+(QL(t).capture?"":"?:")+t.map(n=>Qo(n)).join("|")+")"}function gk(t){return new RegExp(t.toString()+"|").exec("").length-1}function PL(t,e){let i=t&&t.exec(e);return i&&i.index===0}var $L=/\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./;function cg(t,{joinWith:e}){let i=0;return t.map(n=>{i+=1;let r=i,s=Qo(n),o="";for(;s.length>0;){let l=$L.exec(s);if(!l){o+=s;break}o+=s.substring(0,l.index),s=s.substring(l.index+l[0].length),l[0][0]==="\\"&&l[1]?o+="\\"+String(Number(l[1])+r):(o+=l[0],l[0]==="("&&i++)}return o}).map(n=>`(${n})`).join(e)}var TL=/\b\B/,Ok="[a-zA-Z]\\w*",hg="[a-zA-Z_]\\w*",mk="\\b\\d+(\\.\\d+)?",bk="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",yk="\\b(0b[01]+)",CL="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",AL=(t={})=>{let e=/^#![ ]*\//;return t.binary&&(t.begin=Hn(e,/.*\b/,t.binary,/\b.*/)),on({scope:"meta",begin:e,end:/$/,relevance:0,"on:begin":(i,n)=>{i.index!==0&&n.ignoreMatch()}},t)},Po={begin:"\\\\[\\s\\S]",relevance:0},RL={scope:"string",begin:"'",end:"'",illegal:"\\n",contains:[Po]},EL={scope:"string",begin:'"',end:'"',illegal:"\\n",contains:[Po]},ML={begin:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|suLine truncated
|
||||||
https://github.com/highlightjs/highlight.js/issues/2277`),K=P,V=X),W===void 0&&(W=!0);let le={code:V,language:K};B("before:highlight",le);let ie=le.result?le.result:f(le.language,le.code,W);return ie.code=le.code,B("after:highlight",ie),ie}function f(P,X,W,V){let K=Object.create(null);function le(D,Y){return D.keywords[Y]}function ie(){if(!H.keywords){Ye.addText(Qe);return}let D=0;H.keywordPatternRe.lastIndex=0;let Y=H.keywordPatternRe.exec(Qe),ee="";for(;Y;){ee+=Qe.substring(D,Y.index);let ye=ti.case_insensitive?Y[0].toLowerCase():Y[0],Fe=le(H,ye);if(Fe){let[bi,Lk]=Fe;if(Ye.addText(ee),ee="",K[ye]=(K[ye]||0)+1,K[ye]<=lX&&($o+=Lk),bi.startsWith("_"))ee+=Y[0];else{let Xk=ti.classNameAliases[bi]||bi;Ae(Y[0],Xk)}}else ee+=Y[0];D=H.keywordPatternRe.lastIndex,Y=H.keywordPatternRe.exec(Qe)}ee+=Qe.substring(D),Ye.addText(ee)}function me(){if(Qe==="")return;let D=null;if(typeof H.subLanguage=="string"){if(!e[H.subLanguage]){Ye.addText(Qe);return}D=f(H.subLanguage,Qe,!0,pg[H.subLanguage]),pg[H.subLanguage]=D._top}else D=d(Qe,H.subLanguage.length?H.subLanguage:null);H.relevance>0&&($o+=D.relevance),Ye.__addSublanguage(D._emitter,D.language)}function be(){H.subLanguage!=null?me():ie(),Qe=""}function Ae(D,Y){D!==""&&(Ye.startScope(Y),Ye.addText(D),Ye.endScope())}function Ct(D,Y){let ee=1,ye=Y.length-1;for(;ee<=ye;){if(!D._emit[ee]){ee++;continue}let Fe=ti.classNameAliases[D[ee]]||D[ee],bi=Y[ee];Fe?Ae(bi,Fe):(Qe=bi,ie(),Qe=""),ee++}}function Mi(D,Y){return D.scope&&typeof D.scope=="string"&&Ye.openNode(ti.classNameAliases[D.scope]||D.scope),D.beginScope&&(D.beginScope._wrap?(Ae(Qe,ti.classNameAliases[D.beginScope._wrap]||D.beginScope._wrap),Qe=""):D.beginScope._multi&&(Ct(D.beginScope,Y),Qe="")),H=Object.create(D,{parent:{value:H}}),H}function ug(D,Y,ee){let ye=vL(D.endRe,ee);if(ye){if(D["on:end"]){let Fe=new sc(D);D["on:end"](Y,Fe),Fe.isMatchIgnored&&(ye=!1)}if(ye){for(;D.endsParent&&D.parent;)D=D.parent;return D}}if(D.endsWithParent)return ug(D.parent,Y,ee)}function Ck(D){return H.matcher.regexIndex===0?(Qe+=D[0],1):(dc=!0,0)}function Ak(D){let Y=D[0],ee=D.rule,ye=new sc(ee),Fe=[ee.__beforeBegin,ee["on:begin"]];for(let bi of Fe)if(bi&&(bi(D,ye),ye.isMatchIgnored))return Ck(Y);return ee.skip?Qe+=Y:(ee.excludeBegin&&(Qe+=Y),be(),!ee.returnBegin&&!ee.excludeBegin&&(Qe=Y)),Mi(ee,D),ee.returnBegin?0:Y.length}function Rk(D){let Y=D[0],ee=X.substring(D.index),ye=ug(H,D,ee);if(!ye)return lk;let Fe=H;H.endScope&&H.endScope._wrap?(be(),Ae(Y,H.endScope._wrap)):H.endScope&&H.endScope._multi?(be(),Ct(H.endScope,D)):Fe.skip?Qe+=Y:(Fe.returnEnd||Fe.excludeEnd||(Qe+=Y),be(),Fe.excludeEnd&&(Qe=Y));do H.scope&&Ye.closeNode(),!H.skip&&!H.subLanguage&&($o+=H.relevance),H=H.parent;while(H!==ye.parent);return ye.starts&&Mi(ye.starts,D),Fe.returnEnd?0:Y.length}function Ek(){let D=[];for(let Y=H;Y!==ti;Y=Y.parent)Y.scope&&D.unshift(Y.scope);D.forEach(Y=>Ye.openNode(Y))}let Po={};function dg(D,Y){let ee=Y&&Y[0];if(Qe+=D,ee==null)return be(),0;if(Po.type==="begin"&&Y.type==="end"&&Po.index===Y.index&&ee===""){if(Qe+=X.slice(Y.index,Y.index+1),!r){let ye=new Error(`0 width match regex (${P})`);throw ye.languageName=P,ye.badRule=Po.rule,ye}return 1}if(Po=Y,Y.type==="begin")return Ak(Y);if(Y.type==="illegal"&&!W){let ye=new Error('Illegal lexeme "'+ee+'" for mode "'+(H.scope||"<unnamed>")+'"');throw ye.mode=H,ye}else if(Y.type==="end"){let ye=Rk(Y);if(ye!==lk)return ye}if(Y.type==="illegal"&&ee==="")return Qe+=`
|
https://github.com/highlightjs/highlight.js/issues/2277`),te=P,Y=D),V===void 0&&(V=!0);let re={code:Y,language:te};E("before:highlight",re);let J=re.result?re.result:f(re.language,re.code,V);return J.code=re.code,E("after:highlight",J),J}function f(P,D,V,Y){let te=Object.create(null);function re(B,q){return B.keywords[q]}function J(){if(!H.keywords){Ye.addText(Pe);return}let B=0;H.keywordPatternRe.lastIndex=0;let q=H.keywordPatternRe.exec(Pe),ee="";for(;q;){ee+=Pe.substring(B,q.index);let Se=ii.case_insensitive?q[0].toLowerCase():q[0],He=re(H,Se);if(He){let[yi,_k]=He;if(Ye.addText(ee),ee="",te[Se]=(te[Se]||0)+1,te[Se]<=cX&&(Ao+=_k),yi.startsWith("_"))ee+=q[0];else{let Zk=ii.classNameAliases[yi]||yi;xe(q[0],Zk)}}else ee+=q[0];B=H.keywordPatternRe.lastIndex,q=H.keywordPatternRe.exec(Pe)}ee+=Pe.substring(B),Ye.addText(ee)}function ye(){if(Pe==="")return;let B=null;if(typeof H.subLanguage=="string"){if(!e[H.subLanguage]){Ye.addText(Pe);return}B=f(H.subLanguage,Pe,!0,mg[H.subLanguage]),mg[H.subLanguage]=B._top}else B=d(Pe,H.subLanguage.length?H.subLanguage:null);H.relevance>0&&(Ao+=B.relevance),Ye.__addSublanguage(B._emitter,B.language)}function ce(){H.subLanguage!=null?ye():J(),Pe=""}function xe(B,q){B!==""&&(Ye.startScope(q),Ye.addText(B),Ye.endScope())}function dt(B,q){let ee=1,Se=q.length-1;for(;ee<=Se;){if(!B._emit[ee]){ee++;continue}let He=ii.classNameAliases[B[ee]]||B[ee],yi=q[ee];He?xe(yi,He):(Pe=yi,J(),Pe=""),ee++}}function Nt(B,q){return B.scope&&typeof B.scope=="string"&&Ye.openNode(ii.classNameAliases[B.scope]||B.scope),B.beginScope&&(B.beginScope._wrap?(xe(Pe,ii.classNameAliases[B.beginScope._wrap]||B.beginScope._wrap),Pe=""):B.beginScope._multi&&(dt(B.beginScope,q),Pe="")),H=Object.create(B,{parent:{value:H}}),H}function Jr(B,q,ee){let Se=PL(B.endRe,ee);if(Se){if(B["on:end"]){let He=new ac(B);B["on:end"](q,He),He.isMatchIgnored&&(Se=!1)}if(Se){for(;B.endsParent&&B.parent;)B=B.parent;return B}}if(B.endsWithParent)return Jr(B.parent,q,ee)}function To(B){return H.matcher.regexIndex===0?(Pe+=B[0],1):(Oc=!0,0)}function Ek(B){let q=B[0],ee=B.rule,Se=new ac(ee),He=[ee.__beforeBegin,ee["on:begin"]];for(let yi of He)if(yi&&(yi(B,Se),Se.isMatchIgnored))return To(q);return ee.skip?Pe+=q:(ee.excludeBegin&&(Pe+=q),ce(),!ee.returnBegin&&!ee.excludeBegin&&(Pe=q)),Nt(ee,B),ee.returnBegin?0:q.length}function Mk(B){let q=B[0],ee=D.substring(B.index),Se=Jr(H,B,ee);if(!Se)return fk;let He=H;H.endScope&&H.endScope._wrap?(ce(),xe(q,H.endScope._wrap)):H.endScope&&H.endScope._multi?(ce(),dt(H.endScope,B)):He.skip?Pe+=q:(He.returnEnd||He.excludeEnd||(Pe+=q),ce(),He.excludeEnd&&(Pe=q));do H.scope&&Ye.closeNode(),!H.skip&&!H.subLanguage&&(Ao+=H.relevance),H=H.parent;while(H!==Se.parent);return Se.starts&&Nt(Se.starts,B),He.returnEnd?0:q.length}function Lk(){let B=[];for(let q=H;q!==ii;q=q.parent)q.scope&&B.unshift(q.scope);B.forEach(q=>Ye.openNode(q))}let Co={};function Og(B,q){let ee=q&&q[0];if(Pe+=B,ee==null)return ce(),0;if(Co.type==="begin"&&q.type==="end"&&Co.index===q.index&&ee===""){if(Pe+=D.slice(q.index,q.index+1),!r){let Se=new Error(`0 width match regex (${P})`);throw Se.languageName=P,Se.badRule=Co.rule,Se}return 1}if(Co=q,q.type==="begin")return Ek(q);if(q.type==="illegal"&&!V){let Se=new Error('Illegal lexeme "'+ee+'" for mode "'+(H.scope||"<unnamed>")+'"');throw Se.mode=H,Se}else if(q.type==="end"){let Se=Mk(q);if(Se!==fk)return Se}if(q.type==="illegal"&&ee==="")return Pe+=`
|
||||||
`,1;if(uc>1e5&&uc>Y.index*3)throw new Error("potential infinite loop, way more iterations than matches");return Qe+=ee,ee.length}let ti=L(P);if(!ti)throw Hn(s.replace("{}",P)),new Error('Unknown language: "'+P+'"');let Mk=rX(ti),fc="",H=V||Mk,pg={},Ye=new l.__emitter(l);Ek();let Qe="",$o=0,ln=0,uc=0,dc=!1;try{if(ti.__emitTokens)ti.__emitTokens(X,Ye);else{for(H.matcher.considerAll();;){uc++,dc?dc=!1:H.matcher.considerAll(),H.matcher.lastIndex=ln;let D=H.matcher.exec(X);if(!D)break;let Y=X.substring(ln,D.index),ee=dg(Y,D);ln=D.index+ee}dg(X.substring(ln))}return Ye.finalize(),fc=Ye.toHTML(),{language:P,value:fc,relevance:$o,illegal:!1,_emitter:Ye,_top:H}}catch(D){if(D.message&&D.message.includes("Illegal"))return{language:P,value:eg(X),illegal:!0,relevance:0,_illegalBy:{message:D.message,index:ln,context:X.slice(ln-100,ln+100),mode:D.mode,resultSoFar:fc},_emitter:Ye};if(r)return{language:P,value:eg(X),illegal:!1,relevance:0,errorRaised:D,_emitter:Ye,_top:H};throw D}}function u(P){let X={value:eg(P),illegal:!1,relevance:0,_top:o,_emitter:new l.__emitter(l)};return X._emitter.addText(P),X}function d(P,X){X=X||l.languages||Object.keys(e);let W=u(P),V=X.filter(L).filter(z).map(be=>f(be,P,!1));V.unshift(W);let K=V.sort((be,Ae)=>{if(be.relevance!==Ae.relevance)return Ae.relevance-be.relevance;if(be.language&&Ae.language){if(L(be.language).supersetOf===Ae.language)return 1;if(L(Ae.language).supersetOf===be.language)return-1}return 0}),[le,ie]=K,me=le;return me.secondBest=ie,me}function p(P,X,W){let V=X&&i[X]||W;P.classList.add("hljs"),P.classList.add(`language-${V}`)}function g(P){let X=null,W=h(P);if(a(W))return;if(B("before:highlightElement",{el:P,language:W}),P.dataset.highlighted){console.log("Element previously highlighted. To highlight again, first unset `dataset.highlighted`.",P);return}if(P.children.length>0&&(l.ignoreUnescapedHTML||(console.warn("One of your code blocks includes unescaped HTML. This is a potentially serious security risk."),console.warn("https://github.com/highlightjs/highlight.js/wiki/security"),console.warn("The element with unescaped HTML:"),console.warn(P)),l.throwUnescapedHTML))throw new rg("One of your code blocks includes unescaped HTML.",P.innerHTML);X=P;let V=X.textContent,K=W?c(V,{language:W,ignoreIllegals:!0}):d(V);P.innerHTML=K.value,P.dataset.highlighted="yes",p(P,W,K.language),P.result={language:K.language,re:K.relevance,relevance:K.relevance},K.secondBest&&(P.secondBest={language:K.secondBest.language,relevance:K.secondBest.relevance}),B("after:highlightElement",{el:P,result:K,text:V})}function m(P){l=ok(l,P)}let b=()=>{Q(),Kr("10.6.0","initHighlighting() deprecated. Use highlightAll() now.")};function y(){Q(),Kr("10.6.0","initHighlightingOnLoad() deprecated. Use highlightAll() now.")}let x=!1;function Q(){function P(){Q()}if(document.readyState==="loading"){x||window.addEventListener("DOMContentLoaded",P,!1),x=!0;return}document.querySelectorAll(l.cssSelector).forEach(g)}function S(P,X){let W=null;try{W=X(t)}catch(V){if(Hn("Language definition for '{}' could not be registered.".replace("{}",P)),r)Hn(V);else throw V;W=o}W.name||(W.name=P),e[P]=W,W.rawDefinition=X.bind(null,t),W.aliases&&I(W.aliases,{languageName:P})}function k(P){delete e[P];for(let X of Object.keys(i))i[X]===P&&delete i[X]}function w(){return Object.keys(e)}function L(P){return P=(P||"").toLowerCase(),e[P]||e[i[P]]}function I(P,{languageName:X}){typeof P=="string"&&(P=[P]),P.forEach(W=>{i[W.toLowerCase()]=X})}function z(P){let X=L(P);return X&&!X.disableAutodetect}function _(P){P["before:highlightBlock"]&&!P["before:highlightElement"]&&(P["before:highlightElement"]=X=>{P["before:highlightBlock"](Object.assign({block:X.el},X))}),P["after:highlightBlock"]&&!P["after:highlightElement"]&&(P["after:highlightElement"]=X=>{P["after:highlightBlock"](Object.assign({block:X.el},X))})}function $(P){_(P),n.push(P)}function N(P){let X=n.indexOf(P);X!==-1&&n.splice(X,1)}function B(P,X){let W=P;n.forEach(function(V){V[W]&&V[W](X)})}function U(P){return Kr("10.7.0","highlightBlock will be removed entirely in v12.0"),Kr("10.7.0","Please use highlightElement now."),g(P)}Object.assign(t,{highlight:c,highlightAuto:d,highlightAll:Q,highlightElement:g,highlightBlock:U,configure:m,initHighlighting:b,initHighlightingOnLoad:y,registerLanguage:S,unregisterLanguage:k,listLanguages:w,getLanguage:L,registerAliases:I,autoDetection:z,inherit:ok,addPlugin:$,removePlugin:N}),t.debugMode=function(){r=!1},t.safeMode=function(){r=!0},t.versionString=oX,t.regex={concat:Kn,lookahead:hk,either:sg,optional:kL,anyNumberOfTimes:xL};for(let P in rc)typeof rc[P]=="object"&&ak(rc[P]);return Object.assign(t,rc),t},Jr=yk({});Jr.newInstance=()=>yk({});Sk.exports=Jr;Jr.HighlightJS=Jr;Jr.default=Jr});var EX={};zk(EX,{Compartment:()=>ii,EditorState:()=>ce,EditorView:()=>T,HighlightStyle:()=>Wt,MergeView:()=>Fa,StreamLanguage:()=>Xs,autocompletion:()=>Wb,baseExtensions:()=>mX,bracketMatching:()=>Tf,closeBrackets:()=>Qu,closeBracketsKeymap:()=>Pu,crosshairC
Line truncated
|
`,1;if(gc>1e5&&gc>q.index*3)throw new Error("potential infinite loop, way more iterations than matches");return Pe+=ee,ee.length}let ii=C(P);if(!ii)throw Fn(s.replace("{}",P)),new Error('Unknown language: "'+P+'"');let Xk=oX(ii),pc="",H=Y||Xk,mg={},Ye=new l.__emitter(l);Lk();let Pe="",Ao=0,ln=0,gc=0,Oc=!1;try{if(ii.__emitTokens)ii.__emitTokens(D,Ye);else{for(H.matcher.considerAll();;){gc++,Oc?Oc=!1:H.matcher.considerAll(),H.matcher.lastIndex=ln;let B=H.matcher.exec(D);if(!B)break;let q=D.substring(ln,B.index),ee=Og(q,B);ln=B.index+ee}Og(D.substring(ln))}return Ye.finalize(),pc=Ye.toHTML(),{language:P,value:pc,relevance:Ao,illegal:!1,_emitter:Ye,_top:H}}catch(B){if(B.message&&B.message.includes("Illegal"))return{language:P,value:ng(D),illegal:!0,relevance:0,_illegalBy:{message:B.message,index:ln,context:D.slice(ln-100,ln+100),mode:B.mode,resultSoFar:pc},_emitter:Ye};if(r)return{language:P,value:ng(D),illegal:!1,relevance:0,errorRaised:B,_emitter:Ye,_top:H};throw B}}function u(P){let D={value:ng(P),illegal:!1,relevance:0,_top:o,_emitter:new l.__emitter(l)};return D._emitter.addText(P),D}function d(P,D){D=D||l.languages||Object.keys(e);let V=u(P),Y=D.filter(C).filter(N).map(ce=>f(ce,P,!1));Y.unshift(V);let te=Y.sort((ce,xe)=>{if(ce.relevance!==xe.relevance)return xe.relevance-ce.relevance;if(ce.language&&xe.language){if(C(ce.language).supersetOf===xe.language)return 1;if(C(xe.language).supersetOf===ce.language)return-1}return 0}),[re,J]=te,ye=re;return ye.secondBest=J,ye}function p(P,D,V){let Y=D&&i[D]||V;P.classList.add("hljs"),P.classList.add(`language-${Y}`)}function g(P){let D=null,V=h(P);if(a(V))return;if(E("before:highlightElement",{el:P,language:V}),P.dataset.highlighted){console.log("Element previously highlighted. To highlight again, first unset `dataset.highlighted`.",P);return}if(P.children.length>0&&(l.ignoreUnescapedHTML||(console.warn("One of your code blocks includes unescaped HTML. This is a potentially serious security risk."),console.warn("https://github.com/highlightjs/highlight.js/wiki/security"),console.warn("The element with unescaped HTML:"),console.warn(P)),l.throwUnescapedHTML))throw new lg("One of your code blocks includes unescaped HTML.",P.innerHTML);D=P;let Y=D.textContent,te=V?c(Y,{language:V,ignoreIllegals:!0}):d(Y);P.innerHTML=te.value,P.dataset.highlighted="yes",p(P,V,te.language),P.result={language:te.language,re:te.relevance,relevance:te.relevance},te.secondBest&&(P.secondBest={language:te.secondBest.language,relevance:te.secondBest.relevance}),E("after:highlightElement",{el:P,result:te,text:Y})}function m(P){l=hk(l,P)}let b=()=>{v(),Hr("10.6.0","initHighlighting() deprecated. Use highlightAll() now.")};function y(){v(),Hr("10.6.0","initHighlightingOnLoad() deprecated. Use highlightAll() now.")}let S=!1;function v(){function P(){v()}if(document.readyState==="loading"){S||window.addEventListener("DOMContentLoaded",P,!1),S=!0;return}document.querySelectorAll(l.cssSelector).forEach(g)}function x(P,D){let V=null;try{V=D(t)}catch(Y){if(Fn("Language definition for '{}' could not be registered.".replace("{}",P)),r)Fn(Y);else throw Y;V=o}V.name||(V.name=P),e[P]=V,V.rawDefinition=D.bind(null,t),V.aliases&&_(V.aliases,{languageName:P})}function w(P){delete e[P];for(let D of Object.keys(i))i[D]===P&&delete i[D]}function k(){return Object.keys(e)}function C(P){return P=(P||"").toLowerCase(),e[P]||e[i[P]]}function _(P,{languageName:D}){typeof P=="string"&&(P=[P]),P.forEach(V=>{i[V.toLowerCase()]=D})}function N(P){let D=C(P);return D&&!D.disableAutodetect}function R(P){P["before:highlightBlock"]&&!P["before:highlightElement"]&&(P["before:highlightElement"]=D=>{P["before:highlightBlock"](Object.assign({block:D.el},D))}),P["after:highlightBlock"]&&!P["after:highlightElement"]&&(P["after:highlightElement"]=D=>{P["after:highlightBlock"](Object.assign({block:D.el},D))})}function $(P){R(P),n.push(P)}function j(P){let D=n.indexOf(P);D!==-1&&n.splice(D,1)}function E(P,D){let V=P;n.forEach(function(Y){Y[V]&&Y[V](D)})}function U(P){return Hr("10.7.0","highlightBlock will be removed entirely in v12.0"),Hr("10.7.0","Please use highlightElement now."),g(P)}Object.assign(t,{highlight:c,highlightAuto:d,highlightAll:v,highlightElement:g,highlightBlock:U,configure:m,initHighlighting:b,initHighlightingOnLoad:y,registerLanguage:x,unregisterLanguage:w,listLanguages:k,getLanguage:C,registerAliases:_,autoDetection:N,inherit:hk,addPlugin:$,removePlugin:j}),t.debugMode=function(){r=!1},t.safeMode=function(){r=!0},t.versionString=aX,t.regex={concat:Hn,lookahead:pk,either:ag,optional:vL,anyNumberOfTimes:wL};for(let P in lc)typeof lc[P]=="object"&&uk(lc[P]);return Object.assign(t,lc),t},Kr=wk({});Kr.newInstance=()=>wk({});vk.exports=Kr;Kr.HighlightJS=Kr;Kr.default=Kr});var EX={};qk(EX,{Compartment:()=>ni,EditorState:()=>he,EditorView:()=>T,HighlightStyle:()=>Vt,MergeView:()=>Ja,StreamLanguage:()=>_s,autocompletion:()=>Fb,baseExtensions:()=>yX,bracketMatching:()=>Rf,closeBrackets:()=>Tu,closeBracketsKeymap:()=>Cu,
Line truncated
|
||||||
`){[e,i]=nr(this,e,i);let r="";for(let s=0,o=0;s<=i&&o<this.text.length;o++){let l=this.text[o],a=s+l.length;s>e&&o&&(r+=n),e<a&&i>s&&(r+=l.slice(Math.max(0,e-s),i-s)),s=a+1}return r}flatten(e){for(let i of this.text)e.push(i)}scanIdentical(){return 0}static split(e,i){let n=[],r=-1;for(let s of e)n.push(s),r+=s.length+1,n.length==32&&(i.push(new t(n,r)),n=[],r=-1);return r>-1&&i.push(new t(n,r)),i}},er=class t extends te{constructor(e,i){super(),this.children=e,this.length=i,this.lines=0;for(let n of e)this.lines+=n.lines}lineInner(e,i,n,r){for(let s=0;;s++){let o=this.children[s],l=r+o.length,a=n+o.lines-1;if((i?a:l)>=e)return o.lineInner(e,i,n,r);r=l+1,n=a+1}}decompose(e,i,n,r){for(let s=0,o=0;o<=i&&s<this.children.length;s++){let l=this.children[s],a=o+l.length;if(e<=a&&i>=o){let h=r&((o<=e?1:0)|(a>=i?2:0));o>=e&&a<=i&&!h?n.push(l):l.decompose(e-o,i-o,n,h)}o=a+1}}replace(e,i,n){if([e,i]=nr(this,e,i),n.lines<this.lines)for(let r=0,s=0;r<this.children.length;r++){let o=this.children[r],l=s+o.length;if(e>=s&&i<=l){let a=o.replace(e-s,i-s,n),h=this.lines-o.lines+a.lines;if(a.lines<h>>4&&a.lines>h>>6){let c=this.children.slice();return c[r]=a,new t(c,this.length-(i-e)+n.length)}return super.replace(s,l,a)}s=l+1}return super.replace(e,i,n)}sliceString(e,i=this.length,n=`
|
`){[e,i]=ir(this,e,i);let r="";for(let s=0,o=0;s<=i&&o<this.text.length;o++){let l=this.text[o],a=s+l.length;s>e&&o&&(r+=n),e<a&&i>s&&(r+=l.slice(Math.max(0,e-s),i-s)),s=a+1}return r}flatten(e){for(let i of this.text)e.push(i)}scanIdentical(){return 0}static split(e,i){let n=[],r=-1;for(let s of e)n.push(s),r+=s.length+1,n.length==32&&(i.push(new t(n,r)),n=[],r=-1);return r>-1&&i.push(new t(n,r)),i}},Jn=class t extends ie{constructor(e,i){super(),this.children=e,this.length=i,this.lines=0;for(let n of e)this.lines+=n.lines}lineInner(e,i,n,r){for(let s=0;;s++){let o=this.children[s],l=r+o.length,a=n+o.lines-1;if((i?a:l)>=e)return o.lineInner(e,i,n,r);r=l+1,n=a+1}}decompose(e,i,n,r){for(let s=0,o=0;o<=i&&s<this.children.length;s++){let l=this.children[s],a=o+l.length;if(e<=a&&i>=o){let h=r&((o<=e?1:0)|(a>=i?2:0));o>=e&&a<=i&&!h?n.push(l):l.decompose(e-o,i-o,n,h)}o=a+1}}replace(e,i,n){if([e,i]=ir(this,e,i),n.lines<this.lines)for(let r=0,s=0;r<this.children.length;r++){let o=this.children[r],l=s+o.length;if(e>=s&&i<=l){let a=o.replace(e-s,i-s,n),h=this.lines-o.lines+a.lines;if(a.lines<h>>4&&a.lines>h>>6){let c=this.children.slice();return c[r]=a,new t(c,this.length-(i-e)+n.length)}return super.replace(s,l,a)}s=l+1}return super.replace(e,i,n)}sliceString(e,i=this.length,n=`
|
||||||
`){[e,i]=nr(this,e,i);let r="";for(let s=0,o=0;s<this.children.length&&o<=i;s++){let l=this.children[s],a=o+l.length;o>e&&s&&(r+=n),e<a&&i>o&&(r+=l.sliceString(e-o,i-o,n)),o=a+1}return r}flatten(e){for(let i of this.children)i.flatten(e)}scanIdentical(e,i){if(!(e instanceof t))return 0;let n=0,[r,s,o,l]=i>0?[0,0,this.children.length,e.children.length]:[this.children.length-1,e.children.length-1,-1,-1];for(;;r+=i,s+=i){if(r==o||s==l)return n;let a=this.children[r],h=e.children[s];if(a!=h)return n+a.scanIdentical(h,i);n+=a.length+1}}static from(e,i=e.reduce((n,r)=>n+r.length+1,-1)){let n=0;for(let d of e)n+=d.lines;if(n<32){let d=[];for(let p of e)p.flatten(d);return new kt(d,i)}let r=Math.max(32,n>>5),s=r<<1,o=r>>1,l=[],a=0,h=-1,c=[];function f(d){let p;if(d.lines>s&&d instanceof t)for(let g of d.children)f(g);else d.lines>o&&(a>o||!a)?(u(),l.push(d)):d instanceof kt&&a&&(p=c[c.length-1])instanceof kt&&d.lines+p.lines<=32?(a+=d.lines,h+=d.length+1,c[c.length-1]=new kt(p.text.concat(d.text),p.length+1+d.length)):(a+d.lines>r&&u(),a+=d.lines,h+=d.length+1,c.push(d))}function u(){a!=0&&(l.push(c.length==1?c[0]:t.from(c,h)),h=-1,a=c.length=0)}for(let d of e)f(d);return u(),l.length==1?l[0]:new t(l,i)}};te.empty=new kt([""],0);function Gk(t){let e=-1;for(let i of t)e+=i.length+1;return e}function Ao(t,e,i=0,n=1e9){for(let r=0,s=0,o=!0;s<t.length&&r<=n;s++){let l=t[s],a=r+l.length;a>=i&&(a>n&&(l=l.slice(0,n-r)),r<i&&(l=l.slice(i-r)),o?(e[e.length-1]+=l,o=!1):e.push(l)),r=a+1}return e}function vg(t,e,i){return Ao(t,[""],e,i)}var hn=class{constructor(e,i=1){this.dir=i,this.done=!1,this.lineBreak=!1,this.value="",this.nodes=[e],this.offsets=[i>0?1:(e instanceof kt?e.text.length:e.children.length)<<1]}nextInner(e,i){for(this.done=this.lineBreak=!1;;){let n=this.nodes.length-1,r=this.nodes[n],s=this.offsets[n],o=s>>1,l=r instanceof kt?r.text.length:r.children.length;if(o==(i>0?l:0)){if(n==0)return this.done=!0,this.value="",this;i>0&&this.offsets[n-1]++,this.nodes.pop(),this.offsets.pop()}else if((s&1)==(i>0?0:1)){if(this.offsets[n]+=i,e==0)return this.lineBreak=!0,this.value=`
|
`){[e,i]=ir(this,e,i);let r="";for(let s=0,o=0;s<this.children.length&&o<=i;s++){let l=this.children[s],a=o+l.length;o>e&&s&&(r+=n),e<a&&i>o&&(r+=l.sliceString(e-o,i-o,n)),o=a+1}return r}flatten(e){for(let i of this.children)i.flatten(e)}scanIdentical(e,i){if(!(e instanceof t))return 0;let n=0,[r,s,o,l]=i>0?[0,0,this.children.length,e.children.length]:[this.children.length-1,e.children.length-1,-1,-1];for(;;r+=i,s+=i){if(r==o||s==l)return n;let a=this.children[r],h=e.children[s];if(a!=h)return n+a.scanIdentical(h,i);n+=a.length+1}}static from(e,i=e.reduce((n,r)=>n+r.length+1,-1)){let n=0;for(let d of e)n+=d.lines;if(n<32){let d=[];for(let p of e)p.flatten(d);return new wt(d,i)}let r=Math.max(32,n>>5),s=r<<1,o=r>>1,l=[],a=0,h=-1,c=[];function f(d){let p;if(d.lines>s&&d instanceof t)for(let g of d.children)f(g);else d.lines>o&&(a>o||!a)?(u(),l.push(d)):d instanceof wt&&a&&(p=c[c.length-1])instanceof wt&&d.lines+p.lines<=32?(a+=d.lines,h+=d.length+1,c[c.length-1]=new wt(p.text.concat(d.text),p.length+1+d.length)):(a+d.lines>r&&u(),a+=d.lines,h+=d.length+1,c.push(d))}function u(){a!=0&&(l.push(c.length==1?c[0]:t.from(c,h)),h=-1,a=c.length=0)}for(let d of e)f(d);return u(),l.length==1?l[0]:new t(l,i)}};ie.empty=new wt([""],0);function Fk(t){let e=-1;for(let i of t)e+=i.length+1;return e}function Mo(t,e,i=0,n=1e9){for(let r=0,s=0,o=!0;s<t.length&&r<=n;s++){let l=t[s],a=r+l.length;a>=i&&(a>n&&(l=l.slice(0,n-r)),r<i&&(l=l.slice(i-r)),o?(e[e.length-1]+=l,o=!1):e.push(l)),r=a+1}return e}function $g(t,e,i){return Mo(t,[""],e,i)}var hn=class{constructor(e,i=1){this.dir=i,this.done=!1,this.lineBreak=!1,this.value="",this.nodes=[e],this.offsets=[i>0?1:(e instanceof wt?e.text.length:e.children.length)<<1]}nextInner(e,i){for(this.done=this.lineBreak=!1;;){let n=this.nodes.length-1,r=this.nodes[n],s=this.offsets[n],o=s>>1,l=r instanceof wt?r.text.length:r.children.length;if(o==(i>0?l:0)){if(n==0)return this.done=!0,this.value="",this;i>0&&this.offsets[n-1]++,this.nodes.pop(),this.offsets.pop()}else if((s&1)==(i>0?0:1)){if(this.offsets[n]+=i,e==0)return this.lineBreak=!0,this.value=`
|
||||||
`,this;e--}else if(r instanceof kt){let a=r.text[o+(i<0?-1:0)];if(this.offsets[n]+=i,a.length>Math.max(0,e))return this.value=e==0?a:i>0?a.slice(e):a.slice(0,a.length-e),this;e-=a.length}else{let a=r.children[o+(i<0?-1:0)];e>a.length?(e-=a.length,this.offsets[n]+=i):(i<0&&this.offsets[n]--,this.nodes.push(a),this.offsets.push(i>0?1:(a instanceof kt?a.text.length:a.children.length)<<1))}}}next(e=0){return e<0&&(this.nextInner(-e,-this.dir),e=this.value.length),this.nextInner(e,this.dir)}},Ro=class{constructor(e,i,n){this.value="",this.done=!1,this.cursor=new hn(e,i>n?-1:1),this.pos=i>n?e.length:0,this.from=Math.min(i,n),this.to=Math.max(i,n)}nextInner(e,i){if(i<0?this.pos<=this.from:this.pos>=this.to)return this.value="",this.done=!0,this;e+=Math.max(0,i<0?this.pos-this.to:this.from-this.pos);let n=i<0?this.pos-this.from:this.to-this.pos;e>n&&(e=n),n-=e;let{value:r}=this.cursor.next(e);return this.pos+=(r.length+e)*i,this.value=r.length<=n?r:i<0?r.slice(r.length-n):r.slice(0,n),this.done=!this.value,this}next(e=0){return e<0?e=Math.max(e,this.from-this.pos):e>0&&(e=Math.min(e,this.to-this.pos)),this.nextInner(e,this.cursor.dir)}get lineBreak(){return this.cursor.lineBreak&&this.value!=""}},Eo=class{constructor(e){this.inner=e,this.afterBreak=!0,this.value="",this.done=!1}next(e=0){let{done:i,lineBreak:n,value:r}=this.inner.next(e);return i&&this.afterBreak?(this.value="",this.afterBreak=!1):i?(this.done=!0,this.value=""):n?this.afterBreak?this.value="":(this.afterBreak=!0,this.next()):(this.value=r,this.afterBreak=!1),this}get lineBreak(){return!1}};typeof Symbol!="undefined"&&(te.prototype[Symbol.iterator]=function(){return this.iter()},hn.prototype[Symbol.iterator]=Ro.prototype[Symbol.iterator]=Eo.prototype[Symbol.iterator]=function(){return this});var mc=class{constructor(e,i,n,r){this.from=e,this.to=i,this.number=n,this.text=r}get length(){return this.to-this.from}};function nr(t,e,i){return e=Math.max(0,Math.min(t.length,e)),[e,Math.max(e,Math.min(t.length,i))]}function Xe(t,e,i=!0,n=!0){return Sg(t,e,i,n)}function Uk(t){return t>=56320&&t<57344}function Fk(t){return t>=55296&&t<56320}function We(t,e){let i=t.charCodeAt(e);if(!Fk(i)||e+1==t.length)return i;let n=t.charCodeAt(e+1);return Uk(n)?(i-55296<<10)+(n-56320)+65536:i}function os(t){return t<=65535?String.fromCharCode(t):(t-=65536,String.fromCharCode((t>>10)+55296,(t&1023)+56320))}function wt(t){return t<65536?1:2}var bc=/\r\n?|\n/,De=(function(t){return t[t.Simple=0]="Simple",t[t.TrackDel=1]="TrackDel",t[t.TrackBefore=2]="TrackBefore",t[t.TrackAfter=3]="TrackAfter",t})(De||(De={})),yi=class t{constructor(e){this.sections=e}get length(){let e=0;for(let i=0;i<this.sections.length;i+=2)e+=this.sections[i];return e}get newLength(){let e=0;for(let i=0;i<this.sections.length;i+=2){let n=this.sections[i+1];e+=n<0?this.sections[i]:n}return e}get empty(){return this.sections.length==0||this.sections.length==2&&this.sections[1]<0}iterGaps(e){for(let i=0,n=0,r=0;i<this.sections.length;){let s=this.sections[i++],o=this.sections[i++];o<0?(e(n,r,s),r+=s):r+=o,n+=s}}iterChangedRanges(e,i=!1){yc(this,e,i)}get invertedDesc(){let e=[];for(let i=0;i<this.sections.length;){let n=this.sections[i++],r=this.sections[i++];r<0?e.push(n,r):e.push(r,n)}return new t(e)}composeDesc(e){return this.empty?e:e.empty?this:Ag(this,e)}mapDesc(e,i=!1){return e.empty?this:Sc(this,e,i)}mapPos(e,i=-1,n=De.Simple){let r=0,s=0;for(let o=0;o<this.sections.length;){let l=this.sections[o++],a=this.sections[o++],h=r+l;if(a<0){if(h>e)return s+(e-r);s+=l}else{if(n!=De.Simple&&h>=e&&(n==De.TrackDel&&r<e&&h>e||n==De.TrackBefore&&r<e||n==De.TrackAfter&&h>e))return null;if(h>e||h==e&&i<0&&!l)return e==r||i<0?s:s+a;s+=a}r=h}if(e>r)throw new RangeError(`Position ${e} is out of range for changeset of length ${r}`);return s}touchesRange(e,i=e){for(let n=0,r=0;n<this.sections.length&&r<=i;){let s=this.sections[n++],o=this.sections[n++],l=r+s;if(o>=0&&r<=i&&l>=e)return r<e&&l>i?"cover":!0;r=l}return!1}toString(){let e="";for(let i=0;i<this.sections.length;){let n=this.sections[i++],r=this.sections[i++];e+=(e?" ":"")+n+(r>=0?":"+r:"")}return e}toJSON(){return this.sections}static fromJSON(e){if(!Array.isArray(e)||e.length%2||e.some(i=>typeof i!="number"))throw new RangeError("Invalid JSON representation of ChangeDesc");return new t(e)}static create(e){return new t(e)}},qe=class t extends yi{constructor(e,i){super(e),this.inserted=i}apply(e){if(this.length!=e.length)throw new RangeError("Applying change set to a document with the wrong length");return yc(this,(i,n,r,s,o)=>e=e.replace(r,r+(n-i),o),!1),e}mapDesc(e,i=!1){return Sc(this,e,i,!0)}invert(e){let i=this.sections.slice(),n=[];for(let r=0,s=0;r<i.length;r+=2){let o=i[r],l=i[r+1];if(l>=0){i[r]=l,i[r+1]=o;let a=r>>1;for(;n.length<a;)n.push(te.empty);n.push(o?e.slice(s,s+o):te.empty)}s+=o}return new t(i,n)}compose(e){return this.empty?e:e.empty?this:Ag(this,e,!0)}map(e,i=!1){return e.empty?this:Sc(this,e,i,!0)}iterChanges(e,i=!1){yc(this,e,i)}get desc
Line truncated
|
`,this;e--}else if(r instanceof wt){let a=r.text[o+(i<0?-1:0)];if(this.offsets[n]+=i,a.length>Math.max(0,e))return this.value=e==0?a:i>0?a.slice(e):a.slice(0,a.length-e),this;e-=a.length}else{let a=r.children[o+(i<0?-1:0)];e>a.length?(e-=a.length,this.offsets[n]+=i):(i<0&&this.offsets[n]--,this.nodes.push(a),this.offsets.push(i>0?1:(a instanceof wt?a.text.length:a.children.length)<<1))}}}next(e=0){return e<0&&(this.nextInner(-e,-this.dir),e=this.value.length),this.nextInner(e,this.dir)}},Lo=class{constructor(e,i,n){this.value="",this.done=!1,this.cursor=new hn(e,i>n?-1:1),this.pos=i>n?e.length:0,this.from=Math.min(i,n),this.to=Math.max(i,n)}nextInner(e,i){if(i<0?this.pos<=this.from:this.pos>=this.to)return this.value="",this.done=!0,this;e+=Math.max(0,i<0?this.pos-this.to:this.from-this.pos);let n=i<0?this.pos-this.from:this.to-this.pos;e>n&&(e=n),n-=e;let{value:r}=this.cursor.next(e);return this.pos+=(r.length+e)*i,this.value=r.length<=n?r:i<0?r.slice(r.length-n):r.slice(0,n),this.done=!this.value,this}next(e=0){return e<0?e=Math.max(e,this.from-this.pos):e>0&&(e=Math.min(e,this.to-this.pos)),this.nextInner(e,this.cursor.dir)}get lineBreak(){return this.cursor.lineBreak&&this.value!=""}},Xo=class{constructor(e){this.inner=e,this.afterBreak=!0,this.value="",this.done=!1}next(e=0){let{done:i,lineBreak:n,value:r}=this.inner.next(e);return i&&this.afterBreak?(this.value="",this.afterBreak=!1):i?(this.done=!0,this.value=""):n?this.afterBreak?this.value="":(this.afterBreak=!0,this.next()):(this.value=r,this.afterBreak=!1),this}get lineBreak(){return!1}};typeof Symbol!="undefined"&&(ie.prototype[Symbol.iterator]=function(){return this.iter()},hn.prototype[Symbol.iterator]=Lo.prototype[Symbol.iterator]=Xo.prototype[Symbol.iterator]=function(){return this});var Sc=class{constructor(e,i,n,r){this.from=e,this.to=i,this.number=n,this.text=r}get length(){return this.to-this.from}};function ir(t,e,i){return e=Math.max(0,Math.min(t.length,e)),[e,Math.max(e,Math.min(t.length,i))]}function Xe(t,e,i=!0,n=!0){return wg(t,e,i,n)}function Hk(t){return t>=56320&&t<57344}function Kk(t){return t>=55296&&t<56320}function We(t,e){let i=t.charCodeAt(e);if(!Kk(i)||e+1==t.length)return i;let n=t.charCodeAt(e+1);return Hk(n)?(i-55296<<10)+(n-56320)+65536:i}function os(t){return t<=65535?String.fromCharCode(t):(t-=65536,String.fromCharCode((t>>10)+55296,(t&1023)+56320))}function vt(t){return t<65536?1:2}var xc=/\r\n?|\n/,De=(function(t){return t[t.Simple=0]="Simple",t[t.TrackDel=1]="TrackDel",t[t.TrackBefore=2]="TrackBefore",t[t.TrackAfter=3]="TrackAfter",t})(De||(De={})),Si=class t{constructor(e){this.sections=e}get length(){let e=0;for(let i=0;i<this.sections.length;i+=2)e+=this.sections[i];return e}get newLength(){let e=0;for(let i=0;i<this.sections.length;i+=2){let n=this.sections[i+1];e+=n<0?this.sections[i]:n}return e}get empty(){return this.sections.length==0||this.sections.length==2&&this.sections[1]<0}iterGaps(e){for(let i=0,n=0,r=0;i<this.sections.length;){let s=this.sections[i++],o=this.sections[i++];o<0?(e(n,r,s),r+=s):r+=o,n+=s}}iterChangedRanges(e,i=!1){kc(this,e,i)}get invertedDesc(){let e=[];for(let i=0;i<this.sections.length;){let n=this.sections[i++],r=this.sections[i++];r<0?e.push(n,r):e.push(r,n)}return new t(e)}composeDesc(e){return this.empty?e:e.empty?this:Mg(this,e)}mapDesc(e,i=!1){return e.empty?this:wc(this,e,i)}mapPos(e,i=-1,n=De.Simple){let r=0,s=0;for(let o=0;o<this.sections.length;){let l=this.sections[o++],a=this.sections[o++],h=r+l;if(a<0){if(h>e)return s+(e-r);s+=l}else{if(n!=De.Simple&&h>=e&&(n==De.TrackDel&&r<e&&h>e||n==De.TrackBefore&&r<e||n==De.TrackAfter&&h>e))return null;if(h>e||h==e&&i<0&&!l)return e==r||i<0?s:s+a;s+=a}r=h}if(e>r)throw new RangeError(`Position ${e} is out of range for changeset of length ${r}`);return s}touchesRange(e,i=e){for(let n=0,r=0;n<this.sections.length&&r<=i;){let s=this.sections[n++],o=this.sections[n++],l=r+s;if(o>=0&&r<=i&&l>=e)return r<e&&l>i?"cover":!0;r=l}return!1}toString(){let e="";for(let i=0;i<this.sections.length;){let n=this.sections[i++],r=this.sections[i++];e+=(e?" ":"")+n+(r>=0?":"+r:"")}return e}toJSON(){return this.sections}static fromJSON(e){if(!Array.isArray(e)||e.length%2||e.some(i=>typeof i!="number"))throw new RangeError("Invalid JSON representation of ChangeDesc");return new t(e)}static create(e){return new t(e)}},qe=class t extends Si{constructor(e,i){super(e),this.inserted=i}apply(e){if(this.length!=e.length)throw new RangeError("Applying change set to a document with the wrong length");return kc(this,(i,n,r,s,o)=>e=e.replace(r,r+(n-i),o),!1),e}mapDesc(e,i=!1){return wc(this,e,i,!0)}invert(e){let i=this.sections.slice(),n=[];for(let r=0,s=0;r<i.length;r+=2){let o=i[r],l=i[r+1];if(l>=0){i[r]=l,i[r+1]=o;let a=r>>1;for(;n.length<a;)n.push(ie.empty);n.push(o?e.slice(s,s+o):ie.empty)}s+=o}return new t(i,n)}compose(e){return this.empty?e:e.empty?this:Mg(this,e,!0)}map(e,i=!1){return e.empty?this:wc(this,e,i,!0)}iterChanges(e,i=!1){kc(this,e,i)}get desc
Line truncated
|
||||||
`}get readOnly(){return this.facet(Zg)}phrase(e,...i){for(let n of this.facet(t.phrases))if(Object.prototype.hasOwnProperty.call(n,e)){e=n[e];break}return i.length&&(e=e.replace(/\$(\$|\d*)/g,(n,r)=>{if(r=="$")return"$";let s=+(r||1);return!s||s>i.length?n:i[s-1]})),e}languageDataAt(e,i,n=-1){let r=[];for(let s of this.facet(Eg))for(let o of s(this,i,n))Object.prototype.hasOwnProperty.call(o,e)&&r.push(o[e]);return r}charCategorizer(e){return sw(this.languageDataAt("wordChars",e).join(""))}wordAt(e){let{text:i,from:n,length:r}=this.doc.lineAt(e),s=this.charCategorizer(e),o=e-n,l=e-n;for(;o>0;){let a=Xe(i,o,!1);if(s(i.slice(a,o))!=xe.Word)break;o=a}for(;l<r;){let a=Xe(i,l);if(s(i.slice(l,a))!=xe.Word)break;l=a}return o==l?null:v.range(o+n,l+n)}};ce.allowMultipleSelections=kc;ce.tabSize=R.define({combine:t=>t.length?t[0]:4});ce.lineSeparator=Mg;ce.readOnly=Zg;ce.phrases=R.define({compare(t,e){let i=Object.keys(t),n=Object.keys(e);return i.length==n.length&&i.every(r=>t[r]==e[r])}});ce.languageData=Eg;ce.changeFilter=Lg;ce.transactionFilter=Xg;ce.transactionExtender=_g;ii.reconfigure=q.define();function Ge(t,e,i={}){let n={};for(let r of t)for(let s of Object.keys(r)){let o=r[s],l=n[s];if(l===void 0)n[s]=o;else if(!(l===o||o===void 0))if(Object.hasOwnProperty.call(i,s))n[s]=i[s](l,o);else throw new Error("Config merge conflict for field "+s)}for(let r in e)n[r]===void 0&&(n[r]=e[r]);return n}var Nt=class{eq(e){return this==e}range(e,i=e){return rs.create(e,i,this)}};Nt.prototype.startSide=Nt.prototype.endSide=0;Nt.prototype.point=!1;Nt.prototype.mapMode=De.TrackDel;var rs=class t{constructor(e,i,n){this.from=e,this.to=i,this.value=n}static create(e,i,n){return new t(e,i,n)}};function $c(t,e){return t.from-e.from||t.value.startSide-e.value.startSide}var Tc=class t{constructor(e,i,n,r){this.from=e,this.to=i,this.value=n,this.maxPoint=r}get length(){return this.to[this.to.length-1]}findIndex(e,i,n,r=0){let s=n?this.to:this.from;for(let o=r,l=s.length;;){if(o==l)return o;let a=o+l>>1,h=s[a]-e||(n?this.value[a].endSide:this.value[a].startSide)-i;if(a==o)return h>=0?o:l;h>=0?l=a:o=a+1}}between(e,i,n,r){for(let s=this.findIndex(i,-1e9,!0),o=this.findIndex(n,1e9,!1,s);s<o;s++)if(r(this.from[s]+e,this.to[s]+e,this.value[s])===!1)return!1}map(e,i){let n=[],r=[],s=[],o=-1,l=-1;for(let a=0;a<this.value.length;a++){let h=this.value[a],c=this.from[a]+e,f=this.to[a]+e,u,d;if(c==f){let p=i.mapPos(c,h.startSide,h.mapMode);if(p==null||(u=d=p,h.startSide!=h.endSide&&(d=i.mapPos(c,h.endSide),d<u)))continue}else if(u=i.mapPos(c,h.startSide),d=i.mapPos(f,h.endSide),u>d||u==d&&h.startSide>0&&h.endSide<=0)continue;(d-u||h.endSide-h.startSide)<0||(o<0&&(o=u),h.point&&(l=Math.max(l,d-u)),n.push(h),r.push(u-o),s.push(d-o))}return{mapped:n.length?new t(r,s,n,l):null,pos:o}}},re=class t{constructor(e,i,n,r){this.chunkPos=e,this.chunk=i,this.nextLayer=n,this.maxPoint=r}static create(e,i,n,r){return new t(e,i,n,r)}get length(){let e=this.chunk.length-1;return e<0?0:Math.max(this.chunkEnd(e),this.nextLayer.length)}get size(){if(this.isEmpty)return 0;let e=this.nextLayer.size;for(let i of this.chunk)e+=i.value.length;return e}chunkEnd(e){return this.chunkPos[e]+this.chunk[e].length}update(e){let{add:i=[],sort:n=!1,filterFrom:r=0,filterTo:s=this.length}=e,o=e.filter;if(i.length==0&&!o)return this;if(n&&(i=i.slice().sort($c)),this.isEmpty)return i.length?t.of(i):this;let l=new _o(this,null,-1).goto(0),a=0,h=[],c=new Ee;for(;l.value||a<i.length;)if(a<i.length&&(l.from-i[a].from||l.startSide-i[a].value.startSide)>=0){let f=i[a++];c.addInner(f.from,f.to,f.value)||h.push(f)}else l.rangeIndex==1&&l.chunkIndex<this.chunk.length&&(a==i.length||this.chunkEnd(l.chunkIndex)<i[a].from)&&(!o||r>this.chunkEnd(l.chunkIndex)||s<this.chunkPos[l.chunkIndex])&&c.addChunk(this.chunkPos[l.chunkIndex],this.chunk[l.chunkIndex])?l.nextChunk():((!o||r>l.to||s<l.from||o(l.from,l.to,l.value))&&(c.addInner(l.from,l.to,l.value)||h.push(rs.create(l.from,l.to,l.value))),l.next());return c.finishInner(this.nextLayer.isEmpty&&!h.length?t.empty:this.nextLayer.update({add:h,filter:o,filterFrom:r,filterTo:s}))}map(e){if(e.empty||this.isEmpty)return this;let i=[],n=[],r=-1;for(let o=0;o<this.chunk.length;o++){let l=this.chunkPos[o],a=this.chunk[o],h=e.touchesRange(l,l+a.length);if(h===!1)r=Math.max(r,a.maxPoint),i.push(a),n.push(e.mapPos(l));else if(h===!0){let{mapped:c,pos:f}=a.map(l,e);c&&(r=Math.max(r,c.maxPoint),i.push(c),n.push(f))}}let s=this.nextLayer.map(e);return i.length==0?s:new t(n,i,s||t.empty,r)}between(e,i,n){if(!this.isEmpty){for(let r=0;r<this.chunk.length;r++){let s=this.chunkPos[r],o=this.chunk[r];if(i>=s&&e<=s+o.length&&o.between(s,e-s,i-s,n)===!1)return}this.nextLayer.between(e,i,n)}}iter(e=0){return ss.from([this]).goto(e)}get isEmpty(){return this.nextLayer==this}static iter(e,i=0){return ss.from(e).goto(i)}static compare(e,i,n,r,s=-1){let o=e.filter(f=>f.maxPoint>0||!f.isEmpty&&f.maxPoint>=s),l=i.filter(f=>f.maxPoint>0||!f.isEmpty&&f.maxPoint>=s),a=$g(o,l
Line truncated
|
`}get readOnly(){return this.facet(Bg)}phrase(e,...i){for(let n of this.facet(t.phrases))if(Object.prototype.hasOwnProperty.call(n,e)){e=n[e];break}return i.length&&(e=e.replace(/\$(\$|\d*)/g,(n,r)=>{if(r=="$")return"$";let s=+(r||1);return!s||s>i.length?n:i[s-1]})),e}languageDataAt(e,i,n=-1){let r=[];for(let s of this.facet(Xg))for(let o of s(this,i,n))Object.prototype.hasOwnProperty.call(o,e)&&r.push(o[e]);return r}charCategorizer(e){return lw(this.languageDataAt("wordChars",e).join(""))}wordAt(e){let{text:i,from:n,length:r}=this.doc.lineAt(e),s=this.charCategorizer(e),o=e-n,l=e-n;for(;o>0;){let a=Xe(i,o,!1);if(s(i.slice(a,o))!=ke.Word)break;o=a}for(;l<r;){let a=Xe(i,l);if(s(i.slice(l,a))!=ke.Word)break;l=a}return o==l?null:Q.range(o+n,l+n)}};he.allowMultipleSelections=Qc;he.tabSize=L.define({combine:t=>t.length?t[0]:4});he.lineSeparator=_g;he.readOnly=Bg;he.phrases=L.define({compare(t,e){let i=Object.keys(t),n=Object.keys(e);return i.length==n.length&&i.every(r=>t[r]==e[r])}});he.languageData=Xg;he.changeFilter=Zg;he.transactionFilter=Dg;he.transactionExtender=Ig;ni.reconfigure=W.define();function Ge(t,e,i={}){let n={};for(let r of t)for(let s of Object.keys(r)){let o=r[s],l=n[s];if(l===void 0)n[s]=o;else if(!(l===o||o===void 0))if(Object.hasOwnProperty.call(i,s))n[s]=i[s](l,o);else throw new Error("Config merge conflict for field "+s)}for(let r in e)n[r]===void 0&&(n[r]=e[r]);return n}var jt=class{eq(e){return this==e}range(e,i=e){return rs.create(e,i,this)}};jt.prototype.startSide=jt.prototype.endSide=0;jt.prototype.point=!1;jt.prototype.mapMode=De.TrackDel;var rs=class t{constructor(e,i,n){this.from=e,this.to=i,this.value=n}static create(e,i,n){return new t(e,i,n)}};function Ac(t,e){return t.from-e.from||t.value.startSide-e.value.startSide}var Rc=class t{constructor(e,i,n,r){this.from=e,this.to=i,this.value=n,this.maxPoint=r}get length(){return this.to[this.to.length-1]}findIndex(e,i,n,r=0){let s=n?this.to:this.from;for(let o=r,l=s.length;;){if(o==l)return o;let a=o+l>>1,h=s[a]-e||(n?this.value[a].endSide:this.value[a].startSide)-i;if(a==o)return h>=0?o:l;h>=0?l=a:o=a+1}}between(e,i,n,r){for(let s=this.findIndex(i,-1e9,!0),o=this.findIndex(n,1e9,!1,s);s<o;s++)if(r(this.from[s]+e,this.to[s]+e,this.value[s])===!1)return!1}map(e,i){let n=[],r=[],s=[],o=-1,l=-1;for(let a=0;a<this.value.length;a++){let h=this.value[a],c=this.from[a]+e,f=this.to[a]+e,u,d;if(c==f){let p=i.mapPos(c,h.startSide,h.mapMode);if(p==null||(u=d=p,h.startSide!=h.endSide&&(d=i.mapPos(c,h.endSide),d<u)))continue}else if(u=i.mapPos(c,h.startSide),d=i.mapPos(f,h.endSide),u>d||u==d&&h.startSide>0&&h.endSide<=0)continue;(d-u||h.endSide-h.startSide)<0||(o<0&&(o=u),h.point&&(l=Math.max(l,d-u)),n.push(h),r.push(u-o),s.push(d-o))}return{mapped:n.length?new t(r,s,n,l):null,pos:o}}},se=class t{constructor(e,i,n,r){this.chunkPos=e,this.chunk=i,this.nextLayer=n,this.maxPoint=r}static create(e,i,n,r){return new t(e,i,n,r)}get length(){let e=this.chunk.length-1;return e<0?0:Math.max(this.chunkEnd(e),this.nextLayer.length)}get size(){if(this.isEmpty)return 0;let e=this.nextLayer.size;for(let i of this.chunk)e+=i.value.length;return e}chunkEnd(e){return this.chunkPos[e]+this.chunk[e].length}update(e){let{add:i=[],sort:n=!1,filterFrom:r=0,filterTo:s=this.length}=e,o=e.filter;if(i.length==0&&!o)return this;if(n&&(i=i.slice().sort(Ac)),this.isEmpty)return i.length?t.of(i):this;let l=new Io(this,null,-1).goto(0),a=0,h=[],c=new Ee;for(;l.value||a<i.length;)if(a<i.length&&(l.from-i[a].from||l.startSide-i[a].value.startSide)>=0){let f=i[a++];c.addInner(f.from,f.to,f.value)||h.push(f)}else l.rangeIndex==1&&l.chunkIndex<this.chunk.length&&(a==i.length||this.chunkEnd(l.chunkIndex)<i[a].from)&&(!o||r>this.chunkEnd(l.chunkIndex)||s<this.chunkPos[l.chunkIndex])&&c.addChunk(this.chunkPos[l.chunkIndex],this.chunk[l.chunkIndex])?l.nextChunk():((!o||r>l.to||s<l.from||o(l.from,l.to,l.value))&&(c.addInner(l.from,l.to,l.value)||h.push(rs.create(l.from,l.to,l.value))),l.next());return c.finishInner(this.nextLayer.isEmpty&&!h.length?t.empty:this.nextLayer.update({add:h,filter:o,filterFrom:r,filterTo:s}))}map(e){if(e.empty||this.isEmpty)return this;let i=[],n=[],r=-1;for(let o=0;o<this.chunk.length;o++){let l=this.chunkPos[o],a=this.chunk[o],h=e.touchesRange(l,l+a.length);if(h===!1)r=Math.max(r,a.maxPoint),i.push(a),n.push(e.mapPos(l));else if(h===!0){let{mapped:c,pos:f}=a.map(l,e);c&&(r=Math.max(r,c.maxPoint),i.push(c),n.push(f))}}let s=this.nextLayer.map(e);return i.length==0?s:new t(n,i,s||t.empty,r)}between(e,i,n){if(!this.isEmpty){for(let r=0;r<this.chunk.length;r++){let s=this.chunkPos[r],o=this.chunk[r];if(i>=s&&e<=s+o.length&&o.between(s,e-s,i-s,n)===!1)return}this.nextLayer.between(e,i,n)}}iter(e=0){return ss.from([this]).goto(e)}get isEmpty(){return this.nextLayer==this}static iter(e,i=0){return ss.from(e).goto(i)}static compare(e,i,n,r,s=-1){let o=e.filter(f=>f.maxPoint>0||!f.isEmpty&&f.maxPoint>=s),l=i.filter(f=>f.maxPoint>0||!f.isEmpty&&f.maxPoint>=s),a=Ag(o,l
Line truncated
|
||||||
`)}static newName(){let e=Ng[Bg]||1;return Ng[Bg]=e+1,"\u037C"+e.toString(36)}static mount(e,i,n){let r=e[Ec],s=n&&n.nonce;r?s&&r.setNonce(s):r=new Mc(e,s),r.mount(Array.isArray(i)?i:[i],e)}},jg=new Map,Mc=class{constructor(e,i){let n=e.ownerDocument||e,r=n.defaultView;if(!e.head&&e.adoptedStyleSheets&&r.CSSStyleSheet){let s=jg.get(n);if(s)return e[Ec]=s;this.sheet=new r.CSSStyleSheet,jg.set(n,this)}else this.styleTag=n.createElement("style"),i&&this.styleTag.setAttribute("nonce",i);this.modules=[],e[Ec]=this}mount(e,i){let n=this.sheet,r=0,s=0;for(let o=0;o<e.length;o++){let l=e[o],a=this.modules.indexOf(l);if(a<s&&a>-1&&(this.modules.splice(a,1),s--,a=-1),a==-1){if(this.modules.splice(s++,0,l),n)for(let h=0;h<l.rules.length;h++)n.insertRule(l.rules[h],r++)}else{for(;s<a;)r+=this.modules[s++].rules.length;r+=l.rules.length,s++}}if(n)i.adoptedStyleSheets.indexOf(this.sheet)<0&&(i.adoptedStyleSheets=[this.sheet,...i.adoptedStyleSheets]);else{let o="";for(let a=0;a<this.modules.length;a++)o+=this.modules[a].getRules()+`
|
`)}static newName(){let e=Yg[zg]||1;return Yg[zg]=e+1,"\u037C"+e.toString(36)}static mount(e,i,n){let r=e[Xc],s=n&&n.nonce;r?s&&r.setNonce(s):r=new _c(e,s),r.mount(Array.isArray(i)?i:[i],e)}},qg=new Map,_c=class{constructor(e,i){let n=e.ownerDocument||e,r=n.defaultView;if(!e.head&&e.adoptedStyleSheets&&r.CSSStyleSheet){let s=qg.get(n);if(s)return e[Xc]=s;this.sheet=new r.CSSStyleSheet,qg.set(n,this)}else this.styleTag=n.createElement("style"),i&&this.styleTag.setAttribute("nonce",i);this.modules=[],e[Xc]=this}mount(e,i){let n=this.sheet,r=0,s=0;for(let o=0;o<e.length;o++){let l=e[o],a=this.modules.indexOf(l);if(a<s&&a>-1&&(this.modules.splice(a,1),s--,a=-1),a==-1){if(this.modules.splice(s++,0,l),n)for(let h=0;h<l.rules.length;h++)n.insertRule(l.rules[h],r++)}else{for(;s<a;)r+=this.modules[s++].rules.length;r+=l.rules.length,s++}}if(n)i.adoptedStyleSheets.indexOf(this.sheet)<0&&(i.adoptedStyleSheets=[this.sheet,...i.adoptedStyleSheets]);else{let o="";for(let a=0;a<this.modules.length;a++)o+=this.modules[a].getRules()+`
|
||||||
`;this.styleTag.textContent=o;let l=i.head||i;this.styleTag.parentNode!=l&&l.insertBefore(this.styleTag,l.firstChild)}}setNonce(e){this.styleTag&&this.styleTag.getAttribute("nonce")!=e&&this.styleTag.setAttribute("nonce",e)}};var Si={8:"Backspace",9:"Tab",10:"Enter",12:"NumLock",13:"Enter",16:"Shift",17:"Control",18:"Alt",20:"CapsLock",27:"Escape",32:" ",33:"PageUp",34:"PageDown",35:"End",36:"Home",37:"ArrowLeft",38:"ArrowUp",39:"ArrowRight",40:"ArrowDown",44:"PrintScreen",45:"Insert",46:"Delete",59:";",61:"=",91:"Meta",92:"Meta",106:"*",107:"+",108:",",109:"-",110:".",111:"/",144:"NumLock",145:"ScrollLock",160:"Shift",161:"Shift",162:"Control",163:"Control",164:"Alt",165:"Alt",173:"-",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'"},rr={48:")",49:"!",50:"@",51:"#",52:"$",53:"%",54:"^",55:"&",56:"*",57:"(",59:":",61:"+",173:"_",186:":",187:"+",188:"<",189:"_",190:">",191:"?",192:"~",219:"{",220:"|",221:"}",222:'"'},lw=typeof navigator!="undefined"&&/Mac/.test(navigator.platform),aw=typeof navigator!="undefined"&&/MSIE \d|Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(navigator.userAgent);for(_e=0;_e<10;_e++)Si[48+_e]=Si[96+_e]=String(_e);var _e;for(_e=1;_e<=24;_e++)Si[_e+111]="F"+_e;var _e;for(_e=65;_e<=90;_e++)Si[_e]=String.fromCharCode(_e+32),rr[_e]=String.fromCharCode(_e);var _e;for(Do in Si)rr.hasOwnProperty(Do)||(rr[Do]=Si[Do]);var Do;function zg(t){var e=lw&&t.metaKey&&t.shiftKey&&!t.ctrlKey&&!t.altKey||aw&&t.shiftKey&&t.key&&t.key.length==1||t.key=="Unidentified",i=!e&&t.key||(t.shiftKey?rr:Si)[t.keyCode]||t.key||"Unidentified";return i=="Esc"&&(i="Escape"),i=="Del"&&(i="Delete"),i=="Left"&&(i="ArrowLeft"),i=="Up"&&(i="ArrowUp"),i=="Right"&&(i="ArrowRight"),i=="Down"&&(i="ArrowDown"),i}function ge(){var t=arguments[0];typeof t=="string"&&(t=document.createElement(t));var e=1,i=arguments[1];if(i&&typeof i=="object"&&i.nodeType==null&&!Array.isArray(i)){for(var n in i)if(Object.prototype.hasOwnProperty.call(i,n)){var r=i[n];typeof r=="string"?t.setAttribute(n,r):r!=null&&(t[n]=r)}e++}for(;e<arguments.length;e++)Yg(t,arguments[e]);return t}function Yg(t,e){if(typeof e=="string")t.appendChild(document.createTextNode(e));else if(e!=null)if(e.nodeType!=null)t.appendChild(e);else if(Array.isArray(e))for(var i=0;i<e.length;i++)Yg(t,e[i]);else throw new RangeError("Unsupported child node: "+e)}var st=typeof navigator!="undefined"?navigator:{userAgent:"",vendor:"",platform:""},Nc=typeof document!="undefined"?document:{documentElement:{style:{}}},jc=/Edge\/(\d+)/.exec(st.userAgent),MO=/MSIE \d/.test(st.userAgent),zc=/Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(st.userAgent),Ol=!!(MO||zc||jc),qg=!Ol&&/gecko\/(\d+)/i.test(st.userAgent),Lc=!Ol&&/Chrome\/(\d+)/.exec(st.userAgent),Wg="webkitFontSmoothing"in Nc.documentElement.style,Yc=!Ol&&/Apple Computer/.test(st.vendor),Vg=Yc&&(/Mobile\/\w+/.test(st.userAgent)||st.maxTouchPoints>2),Z={mac:Vg||/Mac/.test(st.platform),windows:/Win/.test(st.platform),linux:/Linux|X11/.test(st.platform),ie:Ol,ie_version:MO?Nc.documentMode||6:zc?+zc[1]:jc?+jc[1]:0,gecko:qg,gecko_version:qg?+(/Firefox\/(\d+)/.exec(st.userAgent)||[0,0])[1]:0,chrome:!!Lc,chrome_version:Lc?+Lc[1]:0,ios:Vg,android:/Android\b/.test(st.userAgent),webkit:Wg,webkit_version:Wg?+(/\bAppleWebKit\/(\d+)/.exec(st.userAgent)||[0,0])[1]:0,safari:Yc,safari_version:Yc?+(/\bVersion\/(\d+(\.\d+)?)/.exec(st.userAgent)||[0,0])[1]:0,tabSize:Nc.documentElement.style.tabSize!=null?"tab-size":"-moz-tab-size"};function ys(t){let e;return t.nodeType==11?e=t.getSelection?t:t.ownerDocument:e=t,e.getSelection()}function qc(t,e){return e?t==e||t.contains(e.nodeType!=1?e.parentNode:e):!1}function Uo(t,e){if(!e.anchorNode)return!1;try{return qc(t,e.anchorNode)}catch{return!1}}function hr(t){return t.nodeType==3?gn(t,0,t.nodeValue.length).getClientRects():t.nodeType==1?t.getClientRects():[]}function fs(t,e,i,n){return i?Gg(t,e,i,n,-1)||Gg(t,e,i,n,1):!1}function pn(t){for(var e=0;;e++)if(t=t.previousSibling,!t)return e}function tl(t){return t.nodeType==1&&/^(DIV|P|LI|UL|OL|BLOCKQUOTE|DD|DT|H\d|SECTION|PRE)$/.test(t.nodeName)}function Gg(t,e,i,n,r){for(;;){if(t==i&&e==n)return!0;if(e==(r<0?0:li(t))){if(t.nodeName=="DIV")return!1;let s=t.parentNode;if(!s||s.nodeType!=1)return!1;e=pn(t)+(r<0?0:1),t=s}else if(t.nodeType==1){if(t=t.childNodes[e+(r<0?-1:0)],t.nodeType==1&&t.contentEditable=="false")return!1;e=r<0?li(t):0}else return!1}}function li(t){return t.nodeType==3?t.nodeValue.length:t.childNodes.length}function $s(t,e){let i=e?t.left:t.right;return{left:i,right:i,top:t.top,bottom:t.bottom}}function cw(t){let e=t.visualViewport;return e?{left:0,right:e.width,top:0,bottom:e.height}:{left:0,right:t.innerWidth,top:0,bottom:t.innerHeight}}function LO(t,e){let i=e.width/t.offsetWidth,n=e.height/t.offsetHeight;return(i>.995&&i<1.005||!isFinite(i)||Math.abs(e.width-t.offsetWidth)<1)&&(i=1),(n>.995&&n<1.005||!isFinite(n)||Math.abs(e.height-t.offsetHeight)<1)&&(n=1),{scaleX:i,scaleY:n}}function hw(t,e,i,n,r,Line truncated
|
`;this.styleTag.textContent=o;let l=i.head||i;this.styleTag.parentNode!=l&&l.insertBefore(this.styleTag,l.firstChild)}}setNonce(e){this.styleTag&&this.styleTag.getAttribute("nonce")!=e&&this.styleTag.setAttribute("nonce",e)}};var xi={8:"Backspace",9:"Tab",10:"Enter",12:"NumLock",13:"Enter",16:"Shift",17:"Control",18:"Alt",20:"CapsLock",27:"Escape",32:" ",33:"PageUp",34:"PageDown",35:"End",36:"Home",37:"ArrowLeft",38:"ArrowUp",39:"ArrowRight",40:"ArrowDown",44:"PrintScreen",45:"Insert",46:"Delete",59:";",61:"=",91:"Meta",92:"Meta",106:"*",107:"+",108:",",109:"-",110:".",111:"/",144:"NumLock",145:"ScrollLock",160:"Shift",161:"Shift",162:"Control",163:"Control",164:"Alt",165:"Alt",173:"-",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'"},nr={48:")",49:"!",50:"@",51:"#",52:"$",53:"%",54:"^",55:"&",56:"*",57:"(",59:":",61:"+",173:"_",186:":",187:"+",188:"<",189:"_",190:">",191:"?",192:"~",219:"{",220:"|",221:"}",222:'"'},cw=typeof navigator!="undefined"&&/Mac/.test(navigator.platform),hw=typeof navigator!="undefined"&&/MSIE \d|Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(navigator.userAgent);for(_e=0;_e<10;_e++)xi[48+_e]=xi[96+_e]=String(_e);var _e;for(_e=1;_e<=24;_e++)xi[_e+111]="F"+_e;var _e;for(_e=65;_e<=90;_e++)xi[_e]=String.fromCharCode(_e+32),nr[_e]=String.fromCharCode(_e);var _e;for(No in xi)nr.hasOwnProperty(No)||(nr[No]=xi[No]);var No;function Wg(t){var e=cw&&t.metaKey&&t.shiftKey&&!t.ctrlKey&&!t.altKey||hw&&t.shiftKey&&t.key&&t.key.length==1||t.key=="Unidentified",i=!e&&t.key||(t.shiftKey?nr:xi)[t.keyCode]||t.key||"Unidentified";return i=="Esc"&&(i="Escape"),i=="Del"&&(i="Delete"),i=="Left"&&(i="ArrowLeft"),i=="Up"&&(i="ArrowUp"),i=="Right"&&(i="ArrowRight"),i=="Down"&&(i="ArrowDown"),i}function Oe(){var t=arguments[0];typeof t=="string"&&(t=document.createElement(t));var e=1,i=arguments[1];if(i&&typeof i=="object"&&i.nodeType==null&&!Array.isArray(i)){for(var n in i)if(Object.prototype.hasOwnProperty.call(i,n)){var r=i[n];typeof r=="string"?t.setAttribute(n,r):r!=null&&(t[n]=r)}e++}for(;e<arguments.length;e++)Vg(t,arguments[e]);return t}function Vg(t,e){if(typeof e=="string")t.appendChild(document.createTextNode(e));else if(e!=null)if(e.nodeType!=null)t.appendChild(e);else if(Array.isArray(e))for(var i=0;i<e.length;i++)Vg(t,e[i]);else throw new RangeError("Unsupported child node: "+e)}var st=typeof navigator!="undefined"?navigator:{userAgent:"",vendor:"",platform:""},Yc=typeof document!="undefined"?document:{documentElement:{style:{}}},qc=/Edge\/(\d+)/.exec(st.userAgent),_O=/MSIE \d/.test(st.userAgent),Wc=/Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(st.userAgent),yl=!!(_O||Wc||qc),Gg=!yl&&/gecko\/(\d+)/i.test(st.userAgent),Zc=!yl&&/Chrome\/(\d+)/.exec(st.userAgent),Ug="webkitFontSmoothing"in Yc.documentElement.style,Vc=!yl&&/Apple Computer/.test(st.vendor),Fg=Vc&&(/Mobile\/\w+/.test(st.userAgent)||st.maxTouchPoints>2),I={mac:Fg||/Mac/.test(st.platform),windows:/Win/.test(st.platform),linux:/Linux|X11/.test(st.platform),ie:yl,ie_version:_O?Yc.documentMode||6:Wc?+Wc[1]:qc?+qc[1]:0,gecko:Gg,gecko_version:Gg?+(/Firefox\/(\d+)/.exec(st.userAgent)||[0,0])[1]:0,chrome:!!Zc,chrome_version:Zc?+Zc[1]:0,ios:Fg,android:/Android\b/.test(st.userAgent),webkit:Ug,webkit_version:Ug?+(/\bAppleWebKit\/(\d+)/.exec(st.userAgent)||[0,0])[1]:0,safari:Vc,safari_version:Vc?+(/\bVersion\/(\d+(\.\d+)?)/.exec(st.userAgent)||[0,0])[1]:0,tabSize:Yc.documentElement.style.tabSize!=null?"tab-size":"-moz-tab-size"};function ys(t){let e;return t.nodeType==11?e=t.getSelection?t:t.ownerDocument:e=t,e.getSelection()}function Gc(t,e){return e?t==e||t.contains(e.nodeType!=1?e.parentNode:e):!1}function Ko(t,e){if(!e.anchorNode)return!1;try{return Gc(t,e.anchorNode)}catch{return!1}}function cr(t){return t.nodeType==3?gn(t,0,t.nodeValue.length).getClientRects():t.nodeType==1?t.getClientRects():[]}function fs(t,e,i,n){return i?Hg(t,e,i,n,-1)||Hg(t,e,i,n,1):!1}function pn(t){for(var e=0;;e++)if(t=t.previousSibling,!t)return e}function rl(t){return t.nodeType==1&&/^(DIV|P|LI|UL|OL|BLOCKQUOTE|DD|DT|H\d|SECTION|PRE)$/.test(t.nodeName)}function Hg(t,e,i,n,r){for(;;){if(t==i&&e==n)return!0;if(e==(r<0?0:ai(t))){if(t.nodeName=="DIV")return!1;let s=t.parentNode;if(!s||s.nodeType!=1)return!1;e=pn(t)+(r<0?0:1),t=s}else if(t.nodeType==1){if(t=t.childNodes[e+(r<0?-1:0)],t.nodeType==1&&t.contentEditable=="false")return!1;e=r<0?ai(t):0}else return!1}}function ai(t){return t.nodeType==3?t.nodeValue.length:t.childNodes.length}function $s(t,e){let i=e?t.left:t.right;return{left:i,right:i,top:t.top,bottom:t.bottom}}function fw(t){let e=t.visualViewport;return e?{left:0,right:e.width,top:0,bottom:e.height}:{left:0,right:t.innerWidth,top:0,bottom:t.innerHeight}}function ZO(t,e){let i=e.width/t.offsetWidth,n=e.height/t.offsetHeight;return(i>.995&&i<1.005||!isFinite(i)||Math.abs(e.width-t.offsetWidth)<1)&&(i=1),(n>.995&&n<1.005||!isFinite(n)||Math.abs(e.height-t.offsetHeight)<1)&&(n=1),{scaleX:i,scaleY:n}}function uw(t,e,i,n,r,Line truncated
|
||||||
`,r=t.state.doc.line(r.number+(i?1:-1)),s=t.bidiSpans(r),h=t.visualLineSide(r,!i)}if(a){if(!a(c))return l}else{if(!n)return h;a=n(c)}l=h}}function zw(t,e,i){let n=t.state.charCategorizer(e),r=n(i);return s=>{let o=n(s);return r==xe.Space&&(r=o),r==o}}function Yw(t,e,i,n){let r=e.head,s=i?1:-1;if(r==(i?t.state.doc.length:0))return v.cursor(r,e.assoc);let o=e.goalColumn,l,a=t.contentDOM.getBoundingClientRect(),h=t.coordsAtPos(r,e.assoc||-1),c=t.documentTop;if(h)o==null&&(o=h.left-a.left),l=s<0?h.top:h.bottom;else{let d=t.viewState.lineBlockAt(r);o==null&&(o=Math.min(a.right-a.left,t.defaultCharacterWidth*(r-d.from))),l=(s<0?d.top:d.bottom)+c}let f=a.left+o,u=n!=null?n:t.viewState.heightOracle.textHeight>>1;for(let d=0;;d+=10){let p=l+(u+d)*s,g=um(t,{x:f,y:p},!1,s);if(p<a.top||p>a.bottom||(s<0?g<r:g>r)){let m=t.docView.coordsForChar(g),b=!m||p<m.top?-1:1;return v.cursor(g,b,void 0,o)}}}function gs(t,e,i){for(;;){let n=0;for(let r of t)r.between(e-1,e+1,(s,o,l)=>{if(e>s&&e<o){let a=n||i||(e-s<o-e?-1:1);e=a<0?s:o,n=a}});if(!n)return e}}function pm(t,e){let i=null;for(let n=0;n<e.ranges.length;n++){let r=e.ranges[n],s=null;if(r.empty){let o=gs(t,r.from,0);o!=r.from&&(s=v.cursor(o,-1))}else{let o=gs(t,r.from,-1),l=gs(t,r.to,1);(o!=r.from||l!=r.to)&&(s=v.range(r.from==r.anchor?o:l,r.from==r.head?o:l))}s&&(i||(i=e.ranges.slice()),i[n]=s)}return i?v.create(i,e.mainIndex):e}function _c(t,e,i){let n=gs(t.state.facet(Ts).map(r=>r(t)),i.from,e.head>i.from?-1:1);return n==i.from?i:v.cursor(n,n<i.from?1:-1)}var as="\uFFFF",th=class{constructor(e,i){this.points=e,this.text="",this.lineSeparator=i.facet(ce.lineSeparator)}append(e){this.text+=e}lineBreak(){this.text+=as}readRange(e,i){if(!e)return this;let n=e.parentNode;for(let r=e;;){this.findPointBefore(n,r);let s=this.text.length;this.readNode(r);let o=r.nextSibling;if(o==i)break;let l=ve.get(r),a=ve.get(o);(l&&a?l.breakAfter:(l?l.breakAfter:tl(r))||tl(o)&&(r.nodeName!="BR"||r.cmIgnore)&&this.text.length>s)&&!Ww(o,i)&&this.lineBreak(),r=o}return this.findPointBefore(n,i),this}readTextNode(e){let i=e.nodeValue;for(let n of this.points)n.node==e&&(n.pos=this.text.length+Math.min(n.offset,i.length));for(let n=0,r=this.lineSeparator?null:/\r\n?|\n/g;;){let s=-1,o=1,l;if(this.lineSeparator?(s=i.indexOf(this.lineSeparator,n),o=this.lineSeparator.length):(l=r.exec(i))&&(s=l.index,o=l[0].length),this.append(i.slice(n,s<0?i.length:s)),s<0)break;if(this.lineBreak(),o>1)for(let a of this.points)a.node==e&&a.pos>this.text.length&&(a.pos-=o-1);n=s+o}}readNode(e){if(e.cmIgnore)return;let i=ve.get(e),n=i&&i.overrideDOMText;if(n!=null){this.findPointInside(e,n.length);for(let r=n.iter();!r.next().done;)r.lineBreak?this.lineBreak():this.append(r.value)}else e.nodeType==3?this.readTextNode(e):e.nodeName=="BR"?e.nextSibling&&this.lineBreak():e.nodeType==1&&this.readRange(e.firstChild,null)}findPointBefore(e,i){for(let n of this.points)n.node==e&&e.childNodes[n.offset]==i&&(n.pos=this.text.length)}findPointInside(e,i){for(let n of this.points)(e.nodeType==3?n.node==e:e.contains(n.node))&&(n.pos=this.text.length+(qw(e,n.node,n.offset)?i:0))}};function qw(t,e,i){for(;;){if(!e||i<li(e))return!1;if(e==t)return!0;i=pn(e)+1,e=e.parentNode}}function Ww(t,e){let i;for(;!(t==e||!t);t=t.nextSibling){let n=ve.get(t);if(!(n!=null&&n.isWidget||t.cmIgnore))return!1;n&&(i||(i=[])).push(n)}if(i)for(let n of i){let r=n.overrideDOMText;if(r!=null&&r.length)return!1}return!0}var ol=class{constructor(e,i){this.node=e,this.offset=i,this.pos=-1}},ih=class{constructor(e,i,n,r){this.typeOver=r,this.bounds=null,this.text="",this.domChanged=i>-1;let{impreciseHead:s,impreciseAnchor:o}=e.docView;if(e.state.readOnly&&i>-1)this.newSel=null;else if(i>-1&&(this.bounds=e.docView.domBoundsAround(i,n,0))){let l=s||o?[]:Gw(e),a=new th(l,e.state);a.readRange(this.bounds.startDOM,this.bounds.endDOM),this.text=a.text,this.newSel=Uw(l,this.bounds.from)}else{let l=e.observer.selectionRange,a=s&&s.node==l.focusNode&&s.offset==l.focusOffset||!qc(e.contentDOM,l.focusNode)?e.state.selection.main.head:e.docView.posFromDOM(l.focusNode,l.focusOffset),h=o&&o.node==l.anchorNode&&o.offset==l.anchorOffset||!qc(e.contentDOM,l.anchorNode)?e.state.selection.main.anchor:e.docView.posFromDOM(l.anchorNode,l.anchorOffset),c=e.viewport;if((Z.ios||Z.chrome)&&e.state.selection.main.empty&&a!=h&&(c.from>0||c.to<e.state.doc.length)){let f=Math.min(a,h),u=Math.max(a,h),d=c.from-f,p=c.to-u;(d==0||d==1||f==0)&&(p==0||p==-1||u==e.state.doc.length)&&(a=0,h=e.state.doc.length)}e.inputState.composing>-1&&e.state.selection.ranges.length>1?this.newSel=e.state.selection.replaceRange(v.range(h,a)):this.newSel=v.single(h,a)}}};function gm(t,e){let i,{newSel:n}=e,r=t.state.selection.main,s=t.inputState.lastKeyTime>Date.now()-100?t.inputState.lastKeyCode:-1;if(e.bounds){let{from:o,to:l}=e.bounds,a=r.from,h=null;(s===8||Z.android&&e.text.length<l-o)&&(a=r.to,h="end");let c=Om(t.state.doc.sliceString(o,l,as),e.text,a-o,h);c&&(Z.chrome&&s==13&&c.toB==c.from+2&&e.text.sl
Line truncated
|
`,r=t.state.doc.line(r.number+(i?1:-1)),s=t.bidiSpans(r),h=t.visualLineSide(r,!i)}if(a){if(!a(c))return l}else{if(!n)return h;a=n(c)}l=h}}function qw(t,e,i){let n=t.state.charCategorizer(e),r=n(i);return s=>{let o=n(s);return r==ke.Space&&(r=o),r==o}}function Ww(t,e,i,n){let r=e.head,s=i?1:-1;if(r==(i?t.state.doc.length:0))return Q.cursor(r,e.assoc);let o=e.goalColumn,l,a=t.contentDOM.getBoundingClientRect(),h=t.coordsAtPos(r,e.assoc||-1),c=t.documentTop;if(h)o==null&&(o=h.left-a.left),l=s<0?h.top:h.bottom;else{let d=t.viewState.lineBlockAt(r);o==null&&(o=Math.min(a.right-a.left,t.defaultCharacterWidth*(r-d.from))),l=(s<0?d.top:d.bottom)+c}let f=a.left+o,u=n!=null?n:t.viewState.heightOracle.textHeight>>1;for(let d=0;;d+=10){let p=l+(u+d)*s,g=gm(t,{x:f,y:p},!1,s);if(p<a.top||p>a.bottom||(s<0?g<r:g>r)){let m=t.docView.coordsForChar(g),b=!m||p<m.top?-1:1;return Q.cursor(g,b,void 0,o)}}}function gs(t,e,i){for(;;){let n=0;for(let r of t)r.between(e-1,e+1,(s,o,l)=>{if(e>s&&e<o){let a=n||i||(e-s<o-e?-1:1);e=a<0?s:o,n=a}});if(!n)return e}}function mm(t,e){let i=null;for(let n=0;n<e.ranges.length;n++){let r=e.ranges[n],s=null;if(r.empty){let o=gs(t,r.from,0);o!=r.from&&(s=Q.cursor(o,-1))}else{let o=gs(t,r.from,-1),l=gs(t,r.to,1);(o!=r.from||l!=r.to)&&(s=Q.range(r.from==r.anchor?o:l,r.from==r.head?o:l))}s&&(i||(i=e.ranges.slice()),i[n]=s)}return i?Q.create(i,e.mainIndex):e}function Ic(t,e,i){let n=gs(t.state.facet(Ts).map(r=>r(t)),i.from,e.head>i.from?-1:1);return n==i.from?i:Q.cursor(n,n<i.from?1:-1)}var as="\uFFFF",rh=class{constructor(e,i){this.points=e,this.text="",this.lineSeparator=i.facet(he.lineSeparator)}append(e){this.text+=e}lineBreak(){this.text+=as}readRange(e,i){if(!e)return this;let n=e.parentNode;for(let r=e;;){this.findPointBefore(n,r);let s=this.text.length;this.readNode(r);let o=r.nextSibling;if(o==i)break;let l=Qe.get(r),a=Qe.get(o);(l&&a?l.breakAfter:(l?l.breakAfter:rl(r))||rl(o)&&(r.nodeName!="BR"||r.cmIgnore)&&this.text.length>s)&&!Gw(o,i)&&this.lineBreak(),r=o}return this.findPointBefore(n,i),this}readTextNode(e){let i=e.nodeValue;for(let n of this.points)n.node==e&&(n.pos=this.text.length+Math.min(n.offset,i.length));for(let n=0,r=this.lineSeparator?null:/\r\n?|\n/g;;){let s=-1,o=1,l;if(this.lineSeparator?(s=i.indexOf(this.lineSeparator,n),o=this.lineSeparator.length):(l=r.exec(i))&&(s=l.index,o=l[0].length),this.append(i.slice(n,s<0?i.length:s)),s<0)break;if(this.lineBreak(),o>1)for(let a of this.points)a.node==e&&a.pos>this.text.length&&(a.pos-=o-1);n=s+o}}readNode(e){if(e.cmIgnore)return;let i=Qe.get(e),n=i&&i.overrideDOMText;if(n!=null){this.findPointInside(e,n.length);for(let r=n.iter();!r.next().done;)r.lineBreak?this.lineBreak():this.append(r.value)}else e.nodeType==3?this.readTextNode(e):e.nodeName=="BR"?e.nextSibling&&this.lineBreak():e.nodeType==1&&this.readRange(e.firstChild,null)}findPointBefore(e,i){for(let n of this.points)n.node==e&&e.childNodes[n.offset]==i&&(n.pos=this.text.length)}findPointInside(e,i){for(let n of this.points)(e.nodeType==3?n.node==e:e.contains(n.node))&&(n.pos=this.text.length+(Vw(e,n.node,n.offset)?i:0))}};function Vw(t,e,i){for(;;){if(!e||i<ai(e))return!1;if(e==t)return!0;i=pn(e)+1,e=e.parentNode}}function Gw(t,e){let i;for(;!(t==e||!t);t=t.nextSibling){let n=Qe.get(t);if(!(n!=null&&n.isWidget||t.cmIgnore))return!1;n&&(i||(i=[])).push(n)}if(i)for(let n of i){let r=n.overrideDOMText;if(r!=null&&r.length)return!1}return!0}var cl=class{constructor(e,i){this.node=e,this.offset=i,this.pos=-1}},sh=class{constructor(e,i,n,r){this.typeOver=r,this.bounds=null,this.text="",this.domChanged=i>-1;let{impreciseHead:s,impreciseAnchor:o}=e.docView;if(e.state.readOnly&&i>-1)this.newSel=null;else if(i>-1&&(this.bounds=e.docView.domBoundsAround(i,n,0))){let l=s||o?[]:Fw(e),a=new rh(l,e.state);a.readRange(this.bounds.startDOM,this.bounds.endDOM),this.text=a.text,this.newSel=Hw(l,this.bounds.from)}else{let l=e.observer.selectionRange,a=s&&s.node==l.focusNode&&s.offset==l.focusOffset||!Gc(e.contentDOM,l.focusNode)?e.state.selection.main.head:e.docView.posFromDOM(l.focusNode,l.focusOffset),h=o&&o.node==l.anchorNode&&o.offset==l.anchorOffset||!Gc(e.contentDOM,l.anchorNode)?e.state.selection.main.anchor:e.docView.posFromDOM(l.anchorNode,l.anchorOffset),c=e.viewport;if((I.ios||I.chrome)&&e.state.selection.main.empty&&a!=h&&(c.from>0||c.to<e.state.doc.length)){let f=Math.min(a,h),u=Math.max(a,h),d=c.from-f,p=c.to-u;(d==0||d==1||f==0)&&(p==0||p==-1||u==e.state.doc.length)&&(a=0,h=e.state.doc.length)}e.inputState.composing>-1&&e.state.selection.ranges.length>1?this.newSel=e.state.selection.replaceRange(Q.range(h,a)):this.newSel=Q.single(h,a)}}};function bm(t,e){let i,{newSel:n}=e,r=t.state.selection.main,s=t.inputState.lastKeyTime>Date.now()-100?t.inputState.lastKeyCode:-1;if(e.bounds){let{from:o,to:l}=e.bounds,a=r.from,h=null;(s===8||I.android&&e.text.length<l-o)&&(a=r.to,h="end");let c=ym(t.state.doc.sliceString(o,l,as),e.text,a-o,h);c&&(I.chrome&&s==13&&c.toB==c.from+2&&e.text.sl
Line truncated
|
||||||
`&&t.lineWrapping&&(n&&(n=v.single(n.main.anchor-1,n.main.head-1)),i={from:r.from,to:r.to,insert:te.of([" "])}),i)return _h(t,i,n,s);if(n&&!n.main.eq(r)){let o=!1,l="select";return t.inputState.lastSelectionTime>Date.now()-50&&(t.inputState.lastSelectionOrigin=="select"&&(o=!0),l=t.inputState.lastSelectionOrigin,l=="select.pointer"&&(n=pm(t.state.facet(Ts).map(a=>a(t)),n))),t.dispatch({selection:n,scrollIntoView:o,userEvent:l}),!0}else return!1}function _h(t,e,i,n=-1){if(Z.ios&&t.inputState.flushIOSKey(e))return!0;let r=t.state.selection.main;if(Z.android&&(e.to==r.to&&(e.from==r.from||e.from==r.from-1&&t.state.sliceDoc(e.from,r.from)==" ")&&e.insert.length==1&&e.insert.lines==2&&cr(t.contentDOM,"Enter",13)||(e.from==r.from-1&&e.to==r.to&&e.insert.length==0||n==8&&e.insert.length<e.to-e.from&&e.to>r.head)&&cr(t.contentDOM,"Backspace",8)||e.from==r.from&&e.to==r.to+1&&e.insert.length==0&&cr(t.contentDOM,"Delete",46)))return!0;let s=e.insert.toString();t.inputState.composing>=0&&t.inputState.composing++;let o,l=()=>o||(o=Vw(t,e,i));return t.state.facet(tm).some(a=>a(t,e.from,e.to,s,l))||t.dispatch(l()),!0}function Vw(t,e,i){let n,r=t.state,s=r.selection.main,o=-1;if(e.from==e.to&&e.from<s.from||e.from>s.to){let a=e.from<s.from?-1:1,h=a<0?s.from:s.to,c=gs(r.facet(Ts).map(f=>f(t)),h,a);e.from==c&&(o=c)}if(o>-1)n={changes:e,selection:v.cursor(e.from+e.insert.length,-1)};else if(e.from>=s.from&&e.to<=s.to&&e.to-e.from>=(s.to-s.from)/3&&(!i||i.main.empty&&i.main.from==e.from+e.insert.length)&&t.inputState.composing<0){let a=s.from<e.from?r.sliceDoc(s.from,e.from):"",h=s.to>e.to?r.sliceDoc(e.to,s.to):"";n=r.replaceSelection(t.state.toText(a+e.insert.sliceString(0,void 0,t.state.lineBreak)+h))}else{let a=r.changes(e),h=i&&i.main.to<=a.newLength?i.main:void 0;if(r.selection.ranges.length>1&&(t.inputState.composing>=0||t.inputState.compositionPendingChange)&&e.to<=s.to+10&&e.to>=s.to-10){let c=t.state.sliceDoc(e.from,e.to),f,u=i&&fm(t,i.main.head);if(u){let p=e.insert.length-(e.to-e.from);f={from:u.from,to:u.to-p}}else f=t.state.doc.lineAt(s.head);let d=s.to-e.to;n=r.changeByRange(p=>{if(p.from==s.from&&p.to==s.to)return{changes:a,range:h||p.map(a)};let g=p.to-d,m=g-c.length;if(t.state.sliceDoc(m,g)!=c||g>=f.from&&m<=f.to)return{range:p};let b=r.changes({from:m,to:g,insert:e.insert}),y=p.to-s.to;return{changes:b,range:h?v.range(Math.max(0,h.anchor+y),Math.max(0,h.head+y)):p.map(b)}})}else n={changes:a,selection:h&&r.selection.replaceRange(h)}}let l="input.type";return(t.composing||t.inputState.compositionPendingChange&&t.inputState.compositionEndedAt>Date.now()-50)&&(t.inputState.compositionPendingChange=!1,l+=".compose",t.inputState.compositionFirstChange&&(l+=".start",t.inputState.compositionFirstChange=!1)),r.update(n,{userEvent:l,scrollIntoView:!0})}function Om(t,e,i,n){let r=Math.min(t.length,e.length),s=0;for(;s<r&&t.charCodeAt(s)==e.charCodeAt(s);)s++;if(s==r&&t.length==e.length)return null;let o=t.length,l=e.length;for(;o>0&&l>0&&t.charCodeAt(o-1)==e.charCodeAt(l-1);)o--,l--;if(n=="end"){let a=Math.max(0,s-Math.min(o,l));i-=o+a-s}if(o<s&&t.length<e.length){let a=i<=s&&i>=o?s-i:0;s-=a,l=s+(l-o),o=s}else if(l<s){let a=i<=s&&i>=l?s-i:0;s-=a,o=s+(o-l),l=s}return{from:s,toA:o,toB:l}}function Gw(t){let e=[];if(t.root.activeElement!=t.contentDOM)return e;let{anchorNode:i,anchorOffset:n,focusNode:r,focusOffset:s}=t.observer.selectionRange;return i&&(e.push(new ol(i,n)),(r!=i||s!=n)&&e.push(new ol(r,s))),e}function Uw(t,e){if(t.length==0)return null;let i=t[0].pos,n=t.length==2?t[1].pos:i;return i>-1&&n>-1?v.single(i+e,n+e):null}var nh=class{setSelectionOrigin(e){this.lastSelectionOrigin=e,this.lastSelectionTime=Date.now()}constructor(e){this.view=e,this.lastKeyCode=0,this.lastKeyTime=0,this.lastTouchTime=0,this.lastFocusTime=0,this.lastScrollTop=0,this.lastScrollLeft=0,this.pendingIOSKey=void 0,this.tabFocusMode=-1,this.lastSelectionOrigin=null,this.lastSelectionTime=0,this.lastContextMenu=0,this.scrollHandlers=[],this.handlers=Object.create(null),this.composing=-1,this.compositionFirstChange=null,this.compositionEndedAt=0,this.compositionPendingKey=!1,this.compositionPendingChange=!1,this.insertingText="",this.insertingTextAt=0,this.mouseSelection=null,this.draggedContent=null,this.handleEvent=this.handleEvent.bind(this),this.notifiedFocused=e.hasFocus,Z.safari&&e.contentDOM.addEventListener("input",()=>null),Z.gecko&&hv(e.contentDOM.ownerDocument)}handleEvent(e){!iv(this.view,e)||this.ignoreDuringComposition(e)||e.type=="keydown"&&this.keydown(e)||(this.view.updateState!=0?Promise.resolve().then(()=>this.runHandlers(e.type,e)):this.runHandlers(e.type,e))}runHandlers(e,i){let n=this.handlers[e];if(n){for(let r of n.observers)r(this.view,i);for(let r of n.handlers){if(i.defaultPrevented)break;if(r(this.view,i)){i.preventDefault();break}}}}ensureHandlers(e){let i=Fw(e),n=this.handlers,r=this.view.contentDOM;for(let s in i)if(s!="scroll"){let o=!i[s].handlers.length,l=n[s];l&&o!=!l.handlers.length&&(r.removeEventListe
Line truncated
|
`&&t.lineWrapping&&(n&&(n=Q.single(n.main.anchor-1,n.main.head-1)),i={from:r.from,to:r.to,insert:ie.of([" "])}),i)return Ih(t,i,n,s);if(n&&!n.main.eq(r)){let o=!1,l="select";return t.inputState.lastSelectionTime>Date.now()-50&&(t.inputState.lastSelectionOrigin=="select"&&(o=!0),l=t.inputState.lastSelectionOrigin,l=="select.pointer"&&(n=mm(t.state.facet(Ts).map(a=>a(t)),n))),t.dispatch({selection:n,scrollIntoView:o,userEvent:l}),!0}else return!1}function Ih(t,e,i,n=-1){if(I.ios&&t.inputState.flushIOSKey(e))return!0;let r=t.state.selection.main;if(I.android&&(e.to==r.to&&(e.from==r.from||e.from==r.from-1&&t.state.sliceDoc(e.from,r.from)==" ")&&e.insert.length==1&&e.insert.lines==2&&ar(t.contentDOM,"Enter",13)||(e.from==r.from-1&&e.to==r.to&&e.insert.length==0||n==8&&e.insert.length<e.to-e.from&&e.to>r.head)&&ar(t.contentDOM,"Backspace",8)||e.from==r.from&&e.to==r.to+1&&e.insert.length==0&&ar(t.contentDOM,"Delete",46)))return!0;let s=e.insert.toString();t.inputState.composing>=0&&t.inputState.composing++;let o,l=()=>o||(o=Uw(t,e,i));return t.state.facet(rm).some(a=>a(t,e.from,e.to,s,l))||t.dispatch(l()),!0}function Uw(t,e,i){let n,r=t.state,s=r.selection.main,o=-1;if(e.from==e.to&&e.from<s.from||e.from>s.to){let a=e.from<s.from?-1:1,h=a<0?s.from:s.to,c=gs(r.facet(Ts).map(f=>f(t)),h,a);e.from==c&&(o=c)}if(o>-1)n={changes:e,selection:Q.cursor(e.from+e.insert.length,-1)};else if(e.from>=s.from&&e.to<=s.to&&e.to-e.from>=(s.to-s.from)/3&&(!i||i.main.empty&&i.main.from==e.from+e.insert.length)&&t.inputState.composing<0){let a=s.from<e.from?r.sliceDoc(s.from,e.from):"",h=s.to>e.to?r.sliceDoc(e.to,s.to):"";n=r.replaceSelection(t.state.toText(a+e.insert.sliceString(0,void 0,t.state.lineBreak)+h))}else{let a=r.changes(e),h=i&&i.main.to<=a.newLength?i.main:void 0;if(r.selection.ranges.length>1&&(t.inputState.composing>=0||t.inputState.compositionPendingChange)&&e.to<=s.to+10&&e.to>=s.to-10){let c=t.state.sliceDoc(e.from,e.to),f,u=i&&pm(t,i.main.head);if(u){let p=e.insert.length-(e.to-e.from);f={from:u.from,to:u.to-p}}else f=t.state.doc.lineAt(s.head);let d=s.to-e.to;n=r.changeByRange(p=>{if(p.from==s.from&&p.to==s.to)return{changes:a,range:h||p.map(a)};let g=p.to-d,m=g-c.length;if(t.state.sliceDoc(m,g)!=c||g>=f.from&&m<=f.to)return{range:p};let b=r.changes({from:m,to:g,insert:e.insert}),y=p.to-s.to;return{changes:b,range:h?Q.range(Math.max(0,h.anchor+y),Math.max(0,h.head+y)):p.map(b)}})}else n={changes:a,selection:h&&r.selection.replaceRange(h)}}let l="input.type";return(t.composing||t.inputState.compositionPendingChange&&t.inputState.compositionEndedAt>Date.now()-50)&&(t.inputState.compositionPendingChange=!1,l+=".compose",t.inputState.compositionFirstChange&&(l+=".start",t.inputState.compositionFirstChange=!1)),r.update(n,{userEvent:l,scrollIntoView:!0})}function ym(t,e,i,n){let r=Math.min(t.length,e.length),s=0;for(;s<r&&t.charCodeAt(s)==e.charCodeAt(s);)s++;if(s==r&&t.length==e.length)return null;let o=t.length,l=e.length;for(;o>0&&l>0&&t.charCodeAt(o-1)==e.charCodeAt(l-1);)o--,l--;if(n=="end"){let a=Math.max(0,s-Math.min(o,l));i-=o+a-s}if(o<s&&t.length<e.length){let a=i<=s&&i>=o?s-i:0;s-=a,l=s+(l-o),o=s}else if(l<s){let a=i<=s&&i>=l?s-i:0;s-=a,o=s+(o-l),l=s}return{from:s,toA:o,toB:l}}function Fw(t){let e=[];if(t.root.activeElement!=t.contentDOM)return e;let{anchorNode:i,anchorOffset:n,focusNode:r,focusOffset:s}=t.observer.selectionRange;return i&&(e.push(new cl(i,n)),(r!=i||s!=n)&&e.push(new cl(r,s))),e}function Hw(t,e){if(t.length==0)return null;let i=t[0].pos,n=t.length==2?t[1].pos:i;return i>-1&&n>-1?Q.single(i+e,n+e):null}var oh=class{setSelectionOrigin(e){this.lastSelectionOrigin=e,this.lastSelectionTime=Date.now()}constructor(e){this.view=e,this.lastKeyCode=0,this.lastKeyTime=0,this.lastTouchTime=0,this.lastFocusTime=0,this.lastScrollTop=0,this.lastScrollLeft=0,this.pendingIOSKey=void 0,this.tabFocusMode=-1,this.lastSelectionOrigin=null,this.lastSelectionTime=0,this.lastContextMenu=0,this.scrollHandlers=[],this.handlers=Object.create(null),this.composing=-1,this.compositionFirstChange=null,this.compositionEndedAt=0,this.compositionPendingKey=!1,this.compositionPendingChange=!1,this.insertingText="",this.insertingTextAt=0,this.mouseSelection=null,this.draggedContent=null,this.handleEvent=this.handleEvent.bind(this),this.notifiedFocused=e.hasFocus,I.safari&&e.contentDOM.addEventListener("input",()=>null),I.gecko&&uv(e.contentDOM.ownerDocument)}handleEvent(e){!rv(this.view,e)||this.ignoreDuringComposition(e)||e.type=="keydown"&&this.keydown(e)||(this.view.updateState!=0?Promise.resolve().then(()=>this.runHandlers(e.type,e)):this.runHandlers(e.type,e))}runHandlers(e,i){let n=this.handlers[e];if(n){for(let r of n.observers)r(this.view,i);for(let r of n.handlers){if(i.defaultPrevented)break;if(r(this.view,i)){i.preventDefault();break}}}}ensureHandlers(e){let i=Kw(e),n=this.handlers,r=this.view.contentDOM;for(let s in i)if(s!="scroll"){let o=!i[s].handlers.length,l=n[s];l&&o!=!l.handlers.length&&(r.removeEventListe
Line truncated
|
||||||
`))};if((Z.mac||Z.android)&&f.from==o-1&&/^\. ?$/.test(n.text)&&e.contentDOM.getAttribute("autocorrect")=="off"&&(f={from:l,to:a,insert:te.of([n.text.replace("."," ")])}),this.pendingContextChange=f,!e.state.readOnly){let u=this.to-this.from+(f.to-f.from+f.insert.length);_h(e,f,v.single(this.toEditorPos(n.selectionStart,u),this.toEditorPos(n.selectionEnd,u)))}this.pendingContextChange&&(this.revertPending(e.state),this.setSelection(e.state)),f.from<f.to&&!f.insert.length&&e.inputState.composing>=0&&!/[\\p{Alphabetic}\\p{Number}_]/.test(i.text.slice(Math.max(0,n.updateRangeStart-1),Math.min(i.text.length,n.updateRangeStart+1)))&&this.handlers.compositionend(n)},this.handlers.characterboundsupdate=n=>{let r=[],s=null;for(let o=this.toEditorPos(n.rangeStart),l=this.toEditorPos(n.rangeEnd);o<l;o++){let a=e.coordsForChar(o);s=a&&new DOMRect(a.left,a.top,a.right-a.left,a.bottom-a.top)||s||new DOMRect,r.push(s)}i.updateCharacterBounds(n.rangeStart,r)},this.handlers.textformatupdate=n=>{let r=[];for(let s of n.getTextFormats()){let o=s.underlineStyle,l=s.underlineThickness;if(!/none/i.test(o)&&!/none/i.test(l)){let a=this.toEditorPos(s.rangeStart),h=this.toEditorPos(s.rangeEnd);if(a<h){let c=`text-decoration: underline ${/^[a-z]/.test(o)?o+" ":o=="Dashed"?"dashed ":o=="Squiggle"?"wavy ":""}${/thin/i.test(l)?1:2}px`;r.push(E.mark({attributes:{style:c}}).range(a,h))}}}e.dispatch({effects:om.of(E.set(r))})},this.handlers.compositionstart=()=>{e.inputState.composing<0&&(e.inputState.composing=0,e.inputState.compositionFirstChange=!0)},this.handlers.compositionend=()=>{if(e.inputState.composing=-1,e.inputState.compositionFirstChange=null,this.composing){let{drifted:n}=this.composing;this.composing=null,n&&this.reset(e.state)}};for(let n in this.handlers)i.addEventListener(n,this.handlers[n]);this.measureReq={read:n=>{this.editContext.updateControlBounds(n.contentDOM.getBoundingClientRect());let r=ys(n.root);r&&r.rangeCount&&this.editContext.updateSelectionBounds(r.getRangeAt(0).getBoundingClientRect())}}}applyEdits(e){let i=0,n=!1,r=this.pendingContextChange;return e.changes.iterChanges((s,o,l,a,h)=>{if(n)return;let c=h.length-(o-s);if(r&&o>=r.to)if(r.from==s&&r.to==o&&r.insert.eq(h)){r=this.pendingContextChange=null,i+=c,this.to+=c;return}else r=null,this.revertPending(e.state);if(s+=i,o+=i,o<=this.from)this.from+=c,this.to+=c;else if(s<this.to){if(s<this.from||o>this.to||this.to-this.from+h.length>3e4){n=!0;return}this.editContext.updateText(this.toContextPos(s),this.toContextPos(o),h.toString()),this.to+=c}i+=c}),r&&!n&&this.revertPending(e.state),!n}update(e){let i=this.pendingContextChange,n=e.startState.selection.main;this.composing&&(this.composing.drifted||!e.changes.touchesRange(n.from,n.to)&&e.transactions.some(r=>!r.isUserEvent("input.type")&&r.changes.touchesRange(this.from,this.to)))?(this.composing.drifted=!0,this.composing.editorBase=e.changes.mapPos(this.composing.editorBase)):!this.applyEdits(e)||!this.rangeIsValid(e.state)?(this.pendingContextChange=null,this.reset(e.state)):(e.docChanged||e.selectionSet||i)&&this.setSelection(e.state),(e.geometryChanged||e.docChanged||e.selectionSet)&&e.view.requestMeasure(this.measureReq)}resetRange(e){let{head:i}=e.selection.main;this.from=Math.max(0,i-1e4),this.to=Math.min(e.doc.length,i+1e4)}reset(e){this.resetRange(e),this.editContext.updateText(0,this.editContext.text.length,e.doc.sliceString(this.from,this.to)),this.setSelection(e)}revertPending(e){let i=this.pendingContextChange;this.pendingContextChange=null,this.editContext.updateText(this.toContextPos(i.from),this.toContextPos(i.from+i.insert.length),e.doc.sliceString(i.from,i.to))}setSelection(e){let{main:i}=e.selection,n=this.toContextPos(Math.max(this.from,Math.min(this.to,i.anchor))),r=this.toContextPos(i.head);(this.editContext.selectionStart!=n||this.editContext.selectionEnd!=r)&&this.editContext.updateSelection(n,r)}rangeIsValid(e){let{head:i}=e.selection.main;return!(this.from>0&&i-this.from<500||this.to<e.doc.length&&this.to-i<500||this.to-this.from>1e4*3)}toEditorPos(e,i=this.to-this.from){e=Math.min(e,i);let n=this.composing;return n&&n.drifted?n.editorBase+(e-n.contextBase):e+this.from}toContextPos(e){let i=this.composing;return i&&i.drifted?i.contextBase+(e-i.editorBase):e-this.from}destroy(){for(let e in this.handlers)this.editContext.removeEventListener(e,this.handlers[e])}},T=class t{get state(){return this.viewState.state}get viewport(){return this.viewState.viewport}get visibleRanges(){return this.viewState.visibleRanges}get inView(){return this.viewState.inView}get composing(){return!!this.inputState&&this.inputState.composing>0}get compositionStarted(){return!!this.inputState&&this.inputState.composing>=0}get root(){return this._root}get win(){return this.dom.ownerDocument.defaultView||window}constructor(e={}){var i;this.plugins=[],this.pluginMap=new Map,this.editorAttrs={},this.contentAttrs={},this.bidiCache=[],this.destroyed=!1,this.updateState=2,this.measureScheduled=-1,this.measureR
Line truncated
|
`))};if((I.mac||I.android)&&f.from==o-1&&/^\. ?$/.test(n.text)&&e.contentDOM.getAttribute("autocorrect")=="off"&&(f={from:l,to:a,insert:ie.of([n.text.replace("."," ")])}),this.pendingContextChange=f,!e.state.readOnly){let u=this.to-this.from+(f.to-f.from+f.insert.length);Ih(e,f,Q.single(this.toEditorPos(n.selectionStart,u),this.toEditorPos(n.selectionEnd,u)))}this.pendingContextChange&&(this.revertPending(e.state),this.setSelection(e.state)),f.from<f.to&&!f.insert.length&&e.inputState.composing>=0&&!/[\\p{Alphabetic}\\p{Number}_]/.test(i.text.slice(Math.max(0,n.updateRangeStart-1),Math.min(i.text.length,n.updateRangeStart+1)))&&this.handlers.compositionend(n)},this.handlers.characterboundsupdate=n=>{let r=[],s=null;for(let o=this.toEditorPos(n.rangeStart),l=this.toEditorPos(n.rangeEnd);o<l;o++){let a=e.coordsForChar(o);s=a&&new DOMRect(a.left,a.top,a.right-a.left,a.bottom-a.top)||s||new DOMRect,r.push(s)}i.updateCharacterBounds(n.rangeStart,r)},this.handlers.textformatupdate=n=>{let r=[];for(let s of n.getTextFormats()){let o=s.underlineStyle,l=s.underlineThickness;if(!/none/i.test(o)&&!/none/i.test(l)){let a=this.toEditorPos(s.rangeStart),h=this.toEditorPos(s.rangeEnd);if(a<h){let c=`text-decoration: underline ${/^[a-z]/.test(o)?o+" ":o=="Dashed"?"dashed ":o=="Squiggle"?"wavy ":""}${/thin/i.test(l)?1:2}px`;r.push(X.mark({attributes:{style:c}}).range(a,h))}}}e.dispatch({effects:cm.of(X.set(r))})},this.handlers.compositionstart=()=>{e.inputState.composing<0&&(e.inputState.composing=0,e.inputState.compositionFirstChange=!0)},this.handlers.compositionend=()=>{if(e.inputState.composing=-1,e.inputState.compositionFirstChange=null,this.composing){let{drifted:n}=this.composing;this.composing=null,n&&this.reset(e.state)}};for(let n in this.handlers)i.addEventListener(n,this.handlers[n]);this.measureReq={read:n=>{this.editContext.updateControlBounds(n.contentDOM.getBoundingClientRect());let r=ys(n.root);r&&r.rangeCount&&this.editContext.updateSelectionBounds(r.getRangeAt(0).getBoundingClientRect())}}}applyEdits(e){let i=0,n=!1,r=this.pendingContextChange;return e.changes.iterChanges((s,o,l,a,h)=>{if(n)return;let c=h.length-(o-s);if(r&&o>=r.to)if(r.from==s&&r.to==o&&r.insert.eq(h)){r=this.pendingContextChange=null,i+=c,this.to+=c;return}else r=null,this.revertPending(e.state);if(s+=i,o+=i,o<=this.from)this.from+=c,this.to+=c;else if(s<this.to){if(s<this.from||o>this.to||this.to-this.from+h.length>3e4){n=!0;return}this.editContext.updateText(this.toContextPos(s),this.toContextPos(o),h.toString()),this.to+=c}i+=c}),r&&!n&&this.revertPending(e.state),!n}update(e){let i=this.pendingContextChange,n=e.startState.selection.main;this.composing&&(this.composing.drifted||!e.changes.touchesRange(n.from,n.to)&&e.transactions.some(r=>!r.isUserEvent("input.type")&&r.changes.touchesRange(this.from,this.to)))?(this.composing.drifted=!0,this.composing.editorBase=e.changes.mapPos(this.composing.editorBase)):!this.applyEdits(e)||!this.rangeIsValid(e.state)?(this.pendingContextChange=null,this.reset(e.state)):(e.docChanged||e.selectionSet||i)&&this.setSelection(e.state),(e.geometryChanged||e.docChanged||e.selectionSet)&&e.view.requestMeasure(this.measureReq)}resetRange(e){let{head:i}=e.selection.main;this.from=Math.max(0,i-1e4),this.to=Math.min(e.doc.length,i+1e4)}reset(e){this.resetRange(e),this.editContext.updateText(0,this.editContext.text.length,e.doc.sliceString(this.from,this.to)),this.setSelection(e)}revertPending(e){let i=this.pendingContextChange;this.pendingContextChange=null,this.editContext.updateText(this.toContextPos(i.from),this.toContextPos(i.from+i.insert.length),e.doc.sliceString(i.from,i.to))}setSelection(e){let{main:i}=e.selection,n=this.toContextPos(Math.max(this.from,Math.min(this.to,i.anchor))),r=this.toContextPos(i.head);(this.editContext.selectionStart!=n||this.editContext.selectionEnd!=r)&&this.editContext.updateSelection(n,r)}rangeIsValid(e){let{head:i}=e.selection.main;return!(this.from>0&&i-this.from<500||this.to<e.doc.length&&this.to-i<500||this.to-this.from>1e4*3)}toEditorPos(e,i=this.to-this.from){e=Math.min(e,i);let n=this.composing;return n&&n.drifted?n.editorBase+(e-n.contextBase):e+this.from}toContextPos(e){let i=this.composing;return i&&i.drifted?i.contextBase+(e-i.editorBase):e-this.from}destroy(){for(let e in this.handlers)this.editContext.removeEventListener(e,this.handlers[e])}},T=class t{get state(){return this.viewState.state}get viewport(){return this.viewState.viewport}get visibleRanges(){return this.viewState.visibleRanges}get inView(){return this.viewState.inView}get composing(){return!!this.inputState&&this.inputState.composing>0}get compositionStarted(){return!!this.inputState&&this.inputState.composing>=0}get root(){return this._root}get win(){return this.dom.ownerDocument.defaultView||window}constructor(e={}){var i;this.plugins=[],this.pluginMap=new Map,this.editorAttrs={},this.contentAttrs={},this.bidiCache=[],this.destroyed=!1,this.updateState=2,this.measureScheduled=-1,this.measureR
Line truncated
|
||||||
-\x7F-\x9F\xAD\u061C\u200B\u200E\u200F\u2028\u2029\u202D\u202E\u2066\u2067\u2069\uFEFF\uFFF9-\uFFFC]`,xh),Xv={0:"null",7:"bell",8:"backspace",10:"newline",11:"vertical tab",13:"carriage return",27:"escape",8203:"zero width space",8204:"zero width non-joiner",8205:"zero width joiner",8206:"left-to-right mark",8207:"right-to-left mark",8232:"line separator",8237:"left-to-right override",8238:"right-to-left override",8294:"left-to-right isolate",8295:"right-to-left isolate",8297:"pop directional isolate",8233:"paragraph separator",65279:"zero width no-break space",65532:"object replacement"},Dc=null;function _v(){var t;if(Dc==null&&typeof document!="undefined"&&document.body){let e=document.body.style;Dc=((t=e.tabSize)!==null&&t!==void 0?t:e.MozTabSize)!=null}return Dc||!1}var Jo=R.define({combine(t){let e=Ge(t,{render:null,specialChars:Lv,addSpecialChars:null});return(e.replaceTabs=!_v())&&(e.specialChars=new RegExp(" |"+e.specialChars.source,xh)),e.addSpecialChars&&(e.specialChars=new RegExp(e.specialChars.source+"|"+e.addSpecialChars.source,xh)),e}});function Ih(t={}){return[Jo.of(t),Zv()]}var QO=null;function Zv(){return QO||(QO=Se.fromClass(class{constructor(t){this.view=t,this.decorations=E.none,this.decorationCache=Object.create(null),this.decorator=this.makeDecorator(t.state.facet(Jo)),this.decorations=this.decorator.createDeco(t)}makeDecorator(t){return new Sh({regexp:t.specialChars,decoration:(e,i,n)=>{let{doc:r}=i.state,s=We(e[0],0);if(s==9){let o=r.lineAt(n),l=i.state.tabSize,a=rt(o.text,l,n-o.from);return E.replace({widget:new wh((l-a%l)*this.view.defaultCharacterWidth/this.view.scaleX)})}return this.decorationCache[s]||(this.decorationCache[s]=E.replace({widget:new kh(t,s)}))},boundary:t.replaceTabs?void 0:/[^]/})}update(t){let e=t.state.facet(Jo);t.startState.facet(Jo)!=e?(this.decorator=this.makeDecorator(e),this.decorations=this.decorator.createDeco(t.view)):this.decorations=this.decorator.updateDeco(t,this.decorations)}},{decorations:t=>t.decorations}))}var Dv="\u2022";function Iv(t){return t>=32?Dv:t==10?"\u2424":String.fromCharCode(9216+t)}var kh=class extends Be{constructor(e,i){super(),this.options=e,this.code=i}eq(e){return e.code==this.code}toDOM(e){let i=Iv(this.code),n=e.state.phrase("Control character")+" "+(Xv[this.code]||"0x"+this.code.toString(16)),r=this.options.render&&this.options.render(this.code,n,i);if(r)return r;let s=document.createElement("span");return s.textContent=i,s.title=n,s.setAttribute("aria-label",n),s.className="cm-specialChar",s}ignoreEvent(){return!1}},wh=class extends Be{constructor(e){super(),this.width=e}eq(e){return e.width==this.width}toDOM(){let e=document.createElement("span");return e.textContent=" ",e.className="cm-tab",e.style.width=this.width+"px",e}ignoreEvent(){return!1}};function Bh(){return Nv}var Bv=E.line({class:"cm-activeLine"}),Nv=Se.fromClass(class{constructor(t){this.decorations=this.getDeco(t)}update(t){(t.docChanged||t.selectionSet)&&(this.decorations=this.getDeco(t.view))}getDeco(t){let e=-1,i=[];for(let n of t.state.selection.ranges){let r=t.lineBlockAt(n.head);r.from>e&&(i.push(Bv.range(r.from)),e=r.from)}return E.set(i)}},{decorations:t=>t.decorations}),vh=class extends Be{constructor(e){super(),this.content=e}toDOM(e){let i=document.createElement("span");return i.className="cm-placeholder",i.style.pointerEvents="none",i.appendChild(typeof this.content=="string"?document.createTextNode(this.content):typeof this.content=="function"?this.content(e):this.content.cloneNode(!0)),i.setAttribute("aria-hidden","true"),i}coordsAt(e){let i=e.firstChild?hr(e.firstChild):[];if(!i.length)return null;let n=window.getComputedStyle(e.parentNode),r=$s(i[0],n.direction!="rtl"),s=parseInt(n.lineHeight);return r.bottom-r.top>s*1.5?{left:r.left,right:r.right,top:r.top,bottom:r.top+s}:r}ignoreEvent(){return!1}};function Xm(t){let e=Se.fromClass(class{constructor(i){this.view=i,this.placeholder=t?E.set([E.widget({widget:new vh(t),side:1}).range(0)]):E.none}get decorations(){return this.view.state.doc.length?E.none:this.placeholder}},{decorations:i=>i.decorations});return typeof t=="string"?[e,T.contentAttributes.of({"aria-placeholder":t})]:e}var Qh=2e3;function jv(t,e,i){let n=Math.min(e.line,i.line),r=Math.max(e.line,i.line),s=[];if(e.off>Qh||i.off>Qh||e.col<0||i.col<0){let o=Math.min(e.off,i.off),l=Math.max(e.off,i.off);for(let a=n;a<=r;a++){let h=t.doc.line(a);h.length<=l&&s.push(v.range(h.from+o,h.to+l))}}else{let o=Math.min(e.col,i.col),l=Math.max(e.col,i.col);for(let a=n;a<=r;a++){let h=t.doc.line(a),c=Zo(h.text,o,t.tabSize,!0);if(c<0)s.push(v.cursor(h.to));else{let f=Zo(h.text,l,t.tabSize);s.push(v.range(h.from+c,h.from+f))}}}return s}function zv(t,e){let i=t.coordsAtPos(t.viewport.from);return i?Math.round(Math.abs((i.left-e)/t.defaultCharacterWidth)):-1}function PO(t,e){let i=t.posAtCoords({x:e.clientX,y:e.clientY},!1),n=t.state.doc.lineAt(i),r=i-n.from,s=r>Qh?-1:r==n.length?zv(t,e.clientX):rt(n.text,t.state.tabSize,i-n.from);return{line:n.numbe
Line truncated
|
-\x7F-\x9F\xAD\u061C\u200B\u200E\u200F\u2028\u2029\u202D\u202E\u2066\u2067\u2069\uFEFF\uFFF9-\uFFFC]`,vh),Zv={0:"null",7:"bell",8:"backspace",10:"newline",11:"vertical tab",13:"carriage return",27:"escape",8203:"zero width space",8204:"zero width non-joiner",8205:"zero width joiner",8206:"left-to-right mark",8207:"right-to-left mark",8232:"line separator",8237:"left-to-right override",8238:"right-to-left override",8294:"left-to-right isolate",8295:"right-to-left isolate",8297:"pop directional isolate",8233:"paragraph separator",65279:"zero width no-break space",65532:"object replacement"},Nc=null;function Dv(){var t;if(Nc==null&&typeof document!="undefined"&&document.body){let e=document.body.style;Nc=((t=e.tabSize)!==null&&t!==void 0?t:e.MozTabSize)!=null}return Nc||!1}var il=L.define({combine(t){let e=Ge(t,{render:null,specialChars:_v,addSpecialChars:null});return(e.replaceTabs=!Dv())&&(e.specialChars=new RegExp(" |"+e.specialChars.source,vh)),e.addSpecialChars&&(e.specialChars=new RegExp(e.specialChars.source+"|"+e.addSpecialChars.source,vh)),e}});function jh(t={}){return[il.of(t),Iv()]}var TO=null;function Iv(){return TO||(TO=me.fromClass(class{constructor(t){this.view=t,this.decorations=X.none,this.decorationCache=Object.create(null),this.decorator=this.makeDecorator(t.state.facet(il)),this.decorations=this.decorator.createDeco(t)}makeDecorator(t){return new wh({regexp:t.specialChars,decoration:(e,i,n)=>{let{doc:r}=i.state,s=We(e[0],0);if(s==9){let o=r.lineAt(n),l=i.state.tabSize,a=rt(o.text,l,n-o.from);return X.replace({widget:new Ph((l-a%l)*this.view.defaultCharacterWidth/this.view.scaleX)})}return this.decorationCache[s]||(this.decorationCache[s]=X.replace({widget:new Qh(t,s)}))},boundary:t.replaceTabs?void 0:/[^]/})}update(t){let e=t.state.facet(il);t.startState.facet(il)!=e?(this.decorator=this.makeDecorator(e),this.decorations=this.decorator.createDeco(t.view)):this.decorations=this.decorator.updateDeco(t,this.decorations)}},{decorations:t=>t.decorations}))}var Bv="\u2022";function Nv(t){return t>=32?Bv:t==10?"\u2424":String.fromCharCode(9216+t)}var Qh=class extends Be{constructor(e,i){super(),this.options=e,this.code=i}eq(e){return e.code==this.code}toDOM(e){let i=Nv(this.code),n=e.state.phrase("Control character")+" "+(Zv[this.code]||"0x"+this.code.toString(16)),r=this.options.render&&this.options.render(this.code,n,i);if(r)return r;let s=document.createElement("span");return s.textContent=i,s.title=n,s.setAttribute("aria-label",n),s.className="cm-specialChar",s}ignoreEvent(){return!1}},Ph=class extends Be{constructor(e){super(),this.width=e}eq(e){return e.width==this.width}toDOM(){let e=document.createElement("span");return e.textContent=" ",e.className="cm-tab",e.style.width=this.width+"px",e}ignoreEvent(){return!1}};function zh(){return zv}var jv=X.line({class:"cm-activeLine"}),zv=me.fromClass(class{constructor(t){this.decorations=this.getDeco(t)}update(t){(t.docChanged||t.selectionSet)&&(this.decorations=this.getDeco(t.view))}getDeco(t){let e=-1,i=[];for(let n of t.state.selection.ranges){let r=t.lineBlockAt(n.head);r.from>e&&(i.push(jv.range(r.from)),e=r.from)}return X.set(i)}},{decorations:t=>t.decorations}),$h=class extends Be{constructor(e){super(),this.content=e}toDOM(e){let i=document.createElement("span");return i.className="cm-placeholder",i.style.pointerEvents="none",i.appendChild(typeof this.content=="string"?document.createTextNode(this.content):typeof this.content=="function"?this.content(e):this.content.cloneNode(!0)),i.setAttribute("aria-hidden","true"),i}coordsAt(e){let i=e.firstChild?cr(e.firstChild):[];if(!i.length)return null;let n=window.getComputedStyle(e.parentNode),r=$s(i[0],n.direction!="rtl"),s=parseInt(n.lineHeight);return r.bottom-r.top>s*1.5?{left:r.left,right:r.right,top:r.top,bottom:r.top+s}:r}ignoreEvent(){return!1}};function Dm(t){let e=me.fromClass(class{constructor(i){this.view=i,this.placeholder=t?X.set([X.widget({widget:new $h(t),side:1}).range(0)]):X.none}get decorations(){return this.view.state.doc.length?X.none:this.placeholder}},{decorations:i=>i.decorations});return typeof t=="string"?[e,T.contentAttributes.of({"aria-placeholder":t})]:e}var Th=2e3;function Yv(t,e,i){let n=Math.min(e.line,i.line),r=Math.max(e.line,i.line),s=[];if(e.off>Th||i.off>Th||e.col<0||i.col<0){let o=Math.min(e.off,i.off),l=Math.max(e.off,i.off);for(let a=n;a<=r;a++){let h=t.doc.line(a);h.length<=l&&s.push(Q.range(h.from+o,h.to+l))}}else{let o=Math.min(e.col,i.col),l=Math.max(e.col,i.col);for(let a=n;a<=r;a++){let h=t.doc.line(a),c=Bo(h.text,o,t.tabSize,!0);if(c<0)s.push(Q.cursor(h.to));else{let f=Bo(h.text,l,t.tabSize);s.push(Q.range(h.from+c,h.from+f))}}}return s}function qv(t,e){let i=t.coordsAtPos(t.viewport.from);return i?Math.round(Math.abs((i.left-e)/t.defaultCharacterWidth)):-1}function CO(t,e){let i=t.posAtCoords({x:e.clientX,y:e.clientY},!1),n=t.state.doc.lineAt(i),r=i-n.from,s=r>Th?-1:r==n.length?qv(t,e.clientX):rt(n.text,t.state.tabSize,i-n.from);return{line:n.numbe
Line truncated
|
||||||
`&&(i="");else{let n=i.indexOf(`
|
`&&(i="");else{let n=i.indexOf(`
|
||||||
`);n>-1&&(i=i.slice(0,n))}return e+i.length<=this.to?i:i.slice(0,this.to-e)}nextLine(){let e=this.parsedPos,i=this.lineAfter(e),n=e+i.length;for(let r=this.rangeIndex;;){let s=this.ranges[r].to;if(s>=n||(i=i.slice(0,s-(n-i.length)),r++,r==this.ranges.length))break;let o=this.ranges[r].from,l=this.lineAfter(o);i+=l,n=o+l.length}return{line:i,end:n}}skipGapsTo(e,i,n){for(;;){let r=this.ranges[this.rangeIndex].to,s=e+i;if(n>0?r>s:r>=s)break;let o=this.ranges[++this.rangeIndex].from;i+=o-r}return i}moveRangeIndex(){for(;this.ranges[this.rangeIndex].to<this.parsedPos;)this.rangeIndex++}emitToken(e,i,n,r){let s=4;if(this.ranges.length>1){r=this.skipGapsTo(i,r,1),i+=r;let l=this.chunk.length;r=this.skipGapsTo(n,r,-1),n+=r,s+=this.chunk.length-l}let o=this.chunk.length-4;return this.lang.streamParser.mergeTokens&&s==4&&o>=0&&this.chunk[o]==e&&this.chunk[o+2]==i?this.chunk[o+2]=n:this.chunk.push(e,i,n,s),r}parseLine(e){let{line:i,end:n}=this.nextLine(),r=0,{streamParser:s}=this.lang,o=new Tl(i,e?e.state.tabSize:4,e?qt(e.state):2);if(o.eol())s.blankLine(this.state,o.indentUnit);else for(;!o.eol();){let l=S0(s.token,o,this.state);if(l&&(r=this.emitToken(this.lang.tokenTable.resolve(l),this.parsedPos+o.start,this.parsedPos+o.pos,r)),o.start>1e4)break}this.parsedPos=n,this.moveRangeIndex(),this.parsedPos<this.to&&this.parsedPos++}finishChunk(){let e=fe.build({buffer:this.chunk,start:this.chunkStart,length:this.parsedPos-this.chunkStart,nodeSet:JQ,topID:0,maxBufferLength:2048,reused:this.chunkReused});e=new fe(e.type,e.children,e.positions,e.length,[[this.lang.stateAfter,this.lang.streamParser.copyState(this.state)]]),this.chunks.push(e),this.chunkPos.push(this.chunkStart-this.ranges[0].from),this.chunk=[],this.chunkReused=void 0,this.chunkStart=this.parsedPos}finish(){return new fe(this.lang.topNode,this.chunks,this.chunkPos,this.parsedPos-this.ranges[0].from).balance()}};function S0(t,e,i){e.start=e.pos;for(let n=0;n<10;n++){let r=t(e,i);if(e.pos>e.start)return r}throw new Error("Stream parser failed to advance stream.")}var Rf=Object.create(null),_s=[Ne.none],JQ=new Or(_s),n0=[],r0=Object.create(null),x0=Object.create(null);for(let[t,e]of[["variable","variableName"],["variable-2","variableName.special"],["string-2","string.special"],["def","variableName.definition"],["tag","tagName"],["attribute","attributeName"],["type","typeName"],["builtin","variableName.standard"],["qualifier","modifier"],["error","invalid"],["header","heading"],["property","propertyName"]])x0[t]=k0(Rf,e);var Cl=class{constructor(e){this.extra=e,this.table=Object.assign(Object.create(null),x0)}resolve(e){return e?this.table[e]||(this.table[e]=k0(this.extra,e)):0}},eP=new Cl(Rf);function pf(t,e){n0.indexOf(t)>-1||(n0.push(t),console.warn(e))}function k0(t,e){let i=[];for(let l of e.split(" ")){let a=[];for(let h of l.split(".")){let c=t[h]||O[h];c?typeof c=="function"?a.length?a=a.map(c):pf(h,`Modifier ${h} used at start of tag`):a.length?pf(h,`Tag ${h} used as modifier`):a=Array.isArray(c)?c:[c]:pf(h,`Unknown highlighting tag ${h}`)}for(let h of a)i.push(h)}if(!i.length)return 0;let n=e.replace(/ /g,"_"),r=n+" "+i.map(l=>l.id),s=r0[r];if(s)return s.id;let o=r0[r]=Ne.define({id:_s.length,name:n,props:[at({[n]:i})]});return _s.push(o),o.id}function tP(t,e){let i=Ne.define({id:_s.length,name:"Document",props:[vi.add(()=>t),Et.add(()=>n=>e.getIndent(n))],top:!0});return _s.push(i),i}var u_={rtl:E.mark({class:"cm-iso",inclusive:!0,attributes:{dir:"rtl"},bidiIsolate:ke.RTL}),ltr:E.mark({class:"cm-iso",inclusive:!0,attributes:{dir:"ltr"},bidiIsolate:ke.LTR}),auto:E.mark({class:"cm-iso",inclusive:!0,attributes:{dir:"auto"},bidiIsolate:null})};var Zf=t=>{let{state:e}=t,i=e.doc.lineAt(e.selection.main.from),n=If(t.state,i.from);return n.line?iP(t):n.block?rP(t):!1};function Df(t,e){return({state:i,dispatch:n})=>{if(i.readOnly)return!1;let r=t(e,i);return r?(n(i.update(r)),!0):!1}}var iP=Df(lP,0);var nP=Df(R0,0);var rP=Df((t,e)=>R0(t,e,oP(e)),0);function If(t,e){let i=t.languageDataAt("commentTokens",e);return i.length?i[0]:{}}var Is=50;function sP(t,{open:e,close:i},n,r){let s=t.sliceDoc(n-Is,n),o=t.sliceDoc(r,r+Is),l=/\s*$/.exec(s)[0].length,a=/^\s*/.exec(o)[0].length,h=s.length-l;if(s.slice(h-e.length,h)==e&&o.slice(a,a+i.length)==i)return{open:{pos:n-l,margin:l&&1},close:{pos:r+a,margin:a&&1}};let c,f;r-n<=2*Is?c=f=t.sliceDoc(n,r):(c=t.sliceDoc(n,n+Is),f=t.sliceDoc(r-Is,r));let u=/^\s*/.exec(c)[0].length,d=/\s*$/.exec(f)[0].length,p=f.length-d-i.length;return c.slice(u,u+e.length)==e&&f.slice(p,p+i.length)==i?{open:{pos:n+u+e.length,margin:/\s/.test(c.charAt(u+e.length))?1:0},close:{pos:r-d-i.length,margin:/\s/.test(f.charAt(p-1))?1:0}}:null}function oP(t){let e=[];for(let i of t.selection.ranges){let n=t.doc.lineAt(i.from),r=i.to<=n.to?n:t.doc.lineAt(i.to);r.from>n.from&&r.from==i.to&&(r=i.to==n.to+1?n:t.doc.lineAt(i.to-1));let s=e.length-1;s>=0&&e[s].to>n.from?e[s].to=r.to:e.push({from:n.from+/^\s*/.exec(n.text)[0].length,to:r.to})}return e}function R
Line truncated
|
`);n>-1&&(i=i.slice(0,n))}return e+i.length<=this.to?i:i.slice(0,this.to-e)}nextLine(){let e=this.parsedPos,i=this.lineAfter(e),n=e+i.length;for(let r=this.rangeIndex;;){let s=this.ranges[r].to;if(s>=n||(i=i.slice(0,s-(n-i.length)),r++,r==this.ranges.length))break;let o=this.ranges[r].from,l=this.lineAfter(o);i+=l,n=o+l.length}return{line:i,end:n}}skipGapsTo(e,i,n){for(;;){let r=this.ranges[this.rangeIndex].to,s=e+i;if(n>0?r>s:r>=s)break;let o=this.ranges[++this.rangeIndex].from;i+=o-r}return i}moveRangeIndex(){for(;this.ranges[this.rangeIndex].to<this.parsedPos;)this.rangeIndex++}emitToken(e,i,n,r){let s=4;if(this.ranges.length>1){r=this.skipGapsTo(i,r,1),i+=r;let l=this.chunk.length;r=this.skipGapsTo(n,r,-1),n+=r,s+=this.chunk.length-l}let o=this.chunk.length-4;return this.lang.streamParser.mergeTokens&&s==4&&o>=0&&this.chunk[o]==e&&this.chunk[o+2]==i?this.chunk[o+2]=n:this.chunk.push(e,i,n,s),r}parseLine(e){let{line:i,end:n}=this.nextLine(),r=0,{streamParser:s}=this.lang,o=new Rl(i,e?e.state.tabSize:4,e?Wt(e.state):2);if(o.eol())s.blankLine(this.state,o.indentUnit);else for(;!o.eol();){let l=v0(s.token,o,this.state);if(l&&(r=this.emitToken(this.lang.tokenTable.resolve(l),this.parsedPos+o.start,this.parsedPos+o.pos,r)),o.start>1e4)break}this.parsedPos=n,this.moveRangeIndex(),this.parsedPos<this.to&&this.parsedPos++}finishChunk(){let e=ue.build({buffer:this.chunk,start:this.chunkStart,length:this.parsedPos-this.chunkStart,nodeSet:tP,topID:0,maxBufferLength:2048,reused:this.chunkReused});e=new ue(e.type,e.children,e.positions,e.length,[[this.lang.stateAfter,this.lang.streamParser.copyState(this.state)]]),this.chunks.push(e),this.chunkPos.push(this.chunkStart-this.ranges[0].from),this.chunk=[],this.chunkReused=void 0,this.chunkStart=this.parsedPos}finish(){return new ue(this.lang.topNode,this.chunks,this.chunkPos,this.parsedPos-this.ranges[0].from).balance()}};function v0(t,e,i){e.start=e.pos;for(let n=0;n<10;n++){let r=t(e,i);if(e.pos>e.start)return r}throw new Error("Stream parser failed to advance stream.")}var Lf=Object.create(null),Zs=[Ne.none],tP=new gr(Zs),o0=[],l0=Object.create(null),Q0=Object.create(null);for(let[t,e]of[["variable","variableName"],["variable-2","variableName.special"],["string-2","string.special"],["def","variableName.definition"],["tag","tagName"],["attribute","attributeName"],["type","typeName"],["builtin","variableName.standard"],["qualifier","modifier"],["error","invalid"],["header","heading"],["property","propertyName"]])Q0[t]=P0(Lf,e);var El=class{constructor(e){this.extra=e,this.table=Object.assign(Object.create(null),Q0)}resolve(e){return e?this.table[e]||(this.table[e]=P0(this.extra,e)):0}},iP=new El(Lf);function mf(t,e){o0.indexOf(t)>-1||(o0.push(t),console.warn(e))}function P0(t,e){let i=[];for(let l of e.split(" ")){let a=[];for(let h of l.split(".")){let c=t[h]||O[h];c?typeof c=="function"?a.length?a=a.map(c):mf(h,`Modifier ${h} used at start of tag`):a.length?mf(h,`Tag ${h} used as modifier`):a=Array.isArray(c)?c:[c]:mf(h,`Unknown highlighting tag ${h}`)}for(let h of a)i.push(h)}if(!i.length)return 0;let n=e.replace(/ /g,"_"),r=n+" "+i.map(l=>l.id),s=l0[r];if(s)return s.id;let o=l0[r]=Ne.define({id:Zs.length,name:n,props:[at({[n]:i})]});return Zs.push(o),o.id}function nP(t,e){let i=Ne.define({id:Zs.length,name:"Document",props:[Qi.add(()=>t),Et.add(()=>n=>e.getIndent(n))],top:!0});return Zs.push(i),i}var u_={rtl:X.mark({class:"cm-iso",inclusive:!0,attributes:{dir:"rtl"},bidiIsolate:we.RTL}),ltr:X.mark({class:"cm-iso",inclusive:!0,attributes:{dir:"ltr"},bidiIsolate:we.LTR}),auto:X.mark({class:"cm-iso",inclusive:!0,attributes:{dir:"auto"},bidiIsolate:null})};var Bf=t=>{let{state:e}=t,i=e.doc.lineAt(e.selection.main.from),n=jf(t.state,i.from);return n.line?rP(t):n.block?oP(t):!1};function Nf(t,e){return({state:i,dispatch:n})=>{if(i.readOnly)return!1;let r=t(e,i);return r?(n(i.update(r)),!0):!1}}var rP=Nf(cP,0);var sP=Nf(X0,0);var oP=Nf((t,e)=>X0(t,e,aP(e)),0);function jf(t,e){let i=t.languageDataAt("commentTokens",e);return i.length?i[0]:{}}var Bs=50;function lP(t,{open:e,close:i},n,r){let s=t.sliceDoc(n-Bs,n),o=t.sliceDoc(r,r+Bs),l=/\s*$/.exec(s)[0].length,a=/^\s*/.exec(o)[0].length,h=s.length-l;if(s.slice(h-e.length,h)==e&&o.slice(a,a+i.length)==i)return{open:{pos:n-l,margin:l&&1},close:{pos:r+a,margin:a&&1}};let c,f;r-n<=2*Bs?c=f=t.sliceDoc(n,r):(c=t.sliceDoc(n,n+Bs),f=t.sliceDoc(r-Bs,r));let u=/^\s*/.exec(c)[0].length,d=/\s*$/.exec(f)[0].length,p=f.length-d-i.length;return c.slice(u,u+e.length)==e&&f.slice(p,p+i.length)==i?{open:{pos:n+u+e.length,margin:/\s/.test(c.charAt(u+e.length))?1:0},close:{pos:r-d-i.length,margin:/\s/.test(f.charAt(p-1))?1:0}}:null}function aP(t){let e=[];for(let i of t.selection.ranges){let n=t.doc.lineAt(i.from),r=i.to<=n.to?n:t.doc.lineAt(i.to);r.from>n.from&&r.from==i.to&&(r=i.to==n.to+1?n:t.doc.lineAt(i.to-1));let s=e.length-1;s>=0&&e[s].to>n.from?e[s].to=r.to:e.push({from:n.from+/^\s*/.exec(n.text)[0].length,to:r.to})}return e}function X
Line truncated
|
||||||
`+i.scrub(),s=this.advance(r);return s>-1&&s<r.length?this.complete(e,n,s):!1}finish(e,i){return(this.stage==2||this.stage==3)&&Ks(i.content,this.pos)==i.content.length?this.complete(e,i,i.content.length):!1}complete(e,i,n){return e.addLeafElement(i,se(C.LinkReference,this.start,this.start+n,this.elts)),!0}nextStage(e){return e?(this.pos=e.to-this.start,this.elts.push(e),this.stage++,!0):(e===!1&&(this.stage=-1),!1)}advance(e){for(;;){if(this.stage==-1)return-1;if(this.stage==0){if(!this.nextStage(Ay(e,this.pos,this.start,!0)))return-1;if(e.charCodeAt(this.pos)!=58)return this.stage=-1;this.elts.push(se(C.LinkMark,this.pos+this.start,this.pos+this.start+1)),this.pos++}else if(this.stage==1){if(!this.nextStage(Ty(e,Ks(e,this.pos),this.start)))return-1}else if(this.stage==2){let i=Ks(e,this.pos),n=0;if(i>this.pos){let r=Cy(e,i,this.start);if(r){let s=Du(e,r.to-this.start);s>0&&(this.nextStage(r),n=s)}}return n||(n=Du(e,this.pos)),n>0&&n<e.length?n:-1}else return Du(e,this.pos)}}};function Du(t,e){for(;e<t.length;e++){let i=t.charCodeAt(e);if(i==10)break;if(!Dt(i))return-1}return e}var qu=class{nextLine(e,i,n){let r=i.depth<e.stack.length?-1:yy(i),s=i.next;if(r<0)return!1;let o=se(C.HeaderMark,e.lineStart+i.pos,e.lineStart+r);return e.nextLine(),e.addLeafElement(n,se(s==61?C.SetextHeading1:C.SetextHeading2,n.start,e.prevLineEnd(),[...e.parser.parseInline(n.content,n.start),o])),!0}finish(){return!1}},wy={LinkReference(t,e){return e.content.charCodeAt(0)==91?new Yu(e):null},SetextHeading(){return new qu}},LT=[(t,e)=>by(e)>=0,(t,e)=>gy(e)>=0,(t,e)=>Oy(e)>=0,(t,e)=>Ku(e,t,!0)>=0,(t,e)=>Ju(e,t,!0)>=0,(t,e)=>Hu(e,t,!0)>=0,(t,e)=>ky(e,t,!0)>=0],XT={text:"",end:0},Wu=class{constructor(e,i,n,r){this.parser=e,this.input=i,this.ranges=r,this.line=new Nu,this.atEnd=!1,this.reusePlaceholders=new Map,this.stoppedAt=null,this.rangeI=0,this.to=r[r.length-1].to,this.lineStart=this.absoluteLineStart=this.absoluteLineEnd=r[0].from,this.block=ia.create(C.Document,0,this.lineStart,0,0),this.stack=[this.block],this.fragments=n.length?new Uu(n,i):null,this.readLine()}get parsedPos(){return this.absoluteLineStart}advance(){if(this.stoppedAt!=null&&this.absoluteLineStart>this.stoppedAt)return this.finish();let{line:e}=this;for(;;){for(let n=0;;){let r=e.depth<this.stack.length?this.stack[this.stack.length-1]:null;for(;n<e.markers.length&&(!r||e.markers[n].from<r.end);){let s=e.markers[n++];this.addNode(s.type,s.from,s.to)}if(!r)break;this.finishContext()}if(e.pos<e.text.length)break;if(!this.nextLine())return this.finish()}if(this.fragments&&this.reuseFragment(e.basePos))return null;e:for(;;){for(let n of this.parser.blockParsers)if(n){let r=n(this,e);if(r!=!1){if(r==!0)return null;e.forward();continue e}}break}let i=new Bu(this.lineStart+e.pos,e.text.slice(e.pos));for(let n of this.parser.leafBlockParsers)if(n){let r=n(this,i);r&&i.parsers.push(r)}e:for(;this.nextLine()&&e.pos!=e.text.length;){if(e.indent<e.baseIndent+4){for(let n of this.parser.endLeafBlock)if(n(this,e,i))break e}for(let n of i.parsers)if(n.nextLine(this,e,i))return null;i.content+=`
|
`+i.scrub(),s=this.advance(r);return s>-1&&s<r.length?this.complete(e,n,s):!1}finish(e,i){return(this.stage==2||this.stage==3)&&Js(i.content,this.pos)==i.content.length?this.complete(e,i,i.content.length):!1}complete(e,i,n){return e.addLeafElement(i,oe(A.LinkReference,this.start,this.start+n,this.elts)),!0}nextStage(e){return e?(this.pos=e.to-this.start,this.elts.push(e),this.stage++,!0):(e===!1&&(this.stage=-1),!1)}advance(e){for(;;){if(this.stage==-1)return-1;if(this.stage==0){if(!this.nextStage(Ly(e,this.pos,this.start,!0)))return-1;if(e.charCodeAt(this.pos)!=58)return this.stage=-1;this.elts.push(oe(A.LinkMark,this.pos+this.start,this.pos+this.start+1)),this.pos++}else if(this.stage==1){if(!this.nextStage(Ey(e,Js(e,this.pos),this.start)))return-1}else if(this.stage==2){let i=Js(e,this.pos),n=0;if(i>this.pos){let r=My(e,i,this.start);if(r){let s=Nu(e,r.to-this.start);s>0&&(this.nextStage(r),n=s)}}return n||(n=Nu(e,this.pos)),n>0&&n<e.length?n:-1}else return Nu(e,this.pos)}}};function Nu(t,e){for(;e<t.length;e++){let i=t.charCodeAt(e);if(i==10)break;if(!Dt(i))return-1}return e}var Gu=class{nextLine(e,i,n){let r=i.depth<e.stack.length?-1:wy(i),s=i.next;if(r<0)return!1;let o=oe(A.HeaderMark,e.lineStart+i.pos,e.lineStart+r);return e.nextLine(),e.addLeafElement(n,oe(s==61?A.SetextHeading1:A.SetextHeading2,n.start,e.prevLineEnd(),[...e.parser.parseInline(n.content,n.start),o])),!0}finish(){return!1}},$y={LinkReference(t,e){return e.content.charCodeAt(0)==91?new Vu(e):null},SetextHeading(){return new Gu}},_T=[(t,e)=>ky(e)>=0,(t,e)=>yy(e)>=0,(t,e)=>Sy(e)>=0,(t,e)=>td(e,t,!0)>=0,(t,e)=>id(e,t,!0)>=0,(t,e)=>ed(e,t,!0)>=0,(t,e)=>Py(e,t,!0)>=0],ZT={text:"",end:0},Uu=class{constructor(e,i,n,r){this.parser=e,this.input=i,this.ranges=r,this.line=new Yu,this.atEnd=!1,this.reusePlaceholders=new Map,this.stoppedAt=null,this.rangeI=0,this.to=r[r.length-1].to,this.lineStart=this.absoluteLineStart=this.absoluteLineEnd=r[0].from,this.block=sa.create(A.Document,0,this.lineStart,0,0),this.stack=[this.block],this.fragments=n.length?new Ku(n,i):null,this.readLine()}get parsedPos(){return this.absoluteLineStart}advance(){if(this.stoppedAt!=null&&this.absoluteLineStart>this.stoppedAt)return this.finish();let{line:e}=this;for(;;){for(let n=0;;){let r=e.depth<this.stack.length?this.stack[this.stack.length-1]:null;for(;n<e.markers.length&&(!r||e.markers[n].from<r.end);){let s=e.markers[n++];this.addNode(s.type,s.from,s.to)}if(!r)break;this.finishContext()}if(e.pos<e.text.length)break;if(!this.nextLine())return this.finish()}if(this.fragments&&this.reuseFragment(e.basePos))return null;e:for(;;){for(let n of this.parser.blockParsers)if(n){let r=n(this,e);if(r!=!1){if(r==!0)return null;e.forward();continue e}}break}let i=new zu(this.lineStart+e.pos,e.text.slice(e.pos));for(let n of this.parser.leafBlockParsers)if(n){let r=n(this,i);r&&i.parsers.push(r)}e:for(;this.nextLine()&&e.pos!=e.text.length;){if(e.indent<e.baseIndent+4){for(let n of this.parser.endLeafBlock)if(n(this,e,i))break e}for(let n of i.parsers)if(n.nextLine(this,e,i))return null;i.content+=`
|
||||||
`+e.scrub();for(let n of e.markers)i.marks.push(n)}return this.finishLeaf(i),null}stopAt(e){if(this.stoppedAt!=null&&this.stoppedAt<e)throw new RangeError("Can't move stoppedAt forward");this.stoppedAt=e}reuseFragment(e){if(!this.fragments.moveTo(this.absoluteLineStart+e,this.absoluteLineStart)||!this.fragments.matches(this.block.hash))return!1;let i=this.fragments.takeNodes(this);return i?(this.absoluteLineStart+=i,this.lineStart=Ry(this.absoluteLineStart,this.ranges),this.moveRangeI(),this.absoluteLineStart<this.to?(this.lineStart++,this.absoluteLineStart++,this.readLine()):(this.atEnd=!0,this.readLine()),!0):!1}get depth(){return this.stack.length}parentType(e=this.depth-1){return this.parser.nodeSet.types[this.stack[e].type]}nextLine(){return this.lineStart+=this.line.text.length,this.absoluteLineEnd>=this.to?(this.absoluteLineStart=this.absoluteLineEnd,this.atEnd=!0,this.readLine(),!1):(this.lineStart++,this.absoluteLineStart=this.absoluteLineEnd+1,this.moveRangeI(),this.readLine(),!0)}peekLine(){return this.scanLine(this.absoluteLineEnd+1).text}moveRangeI(){for(;this.rangeI<this.ranges.length-1&&this.absoluteLineStart>=this.ranges[this.rangeI].to;)this.rangeI++,this.absoluteLineStart=Math.max(this.absoluteLineStart,this.ranges[this.rangeI].from)}scanLine(e){let i=XT;if(i.end=e,e>=this.to)i.text="";else if(i.text=this.lineChunkAt(e),i.end+=i.text.length,this.ranges.length>1){let n=this.absoluteLineStart,r=this.rangeI;for(;this.ranges[r].to<i.end;){r++;let s=this.ranges[r].from,o=this.lineChunkAt(s);i.end=s+o.length,i.text=i.text.slice(0,this.ranges[r-1].to-n)+o,n=i.end-i.text.length}}return i}readLine(){let{line:e}=this,{text:i,end:n}=this.scanLine(this.absoluteLineStart);for(this.absoluteLineEnd=n,e.reset(i);e.depth<this.stack.length;e.depth++){let r=this.stack[e.depth],s=this.parser.skipContextMarkup[r.type];if(!s)throw new Error("Unhandled block context "+C[r.type]);let o=this.line.markers.length;if(!s(r,this,e)){this.line.markers.length>o&&(r.end=this.line.markers[this.line.markers.length-1].to),e.forward();break}e.forward()}}lineChunkAt(e){let i=this.input.chunk(e),n;if(this.input.lineChunks)n=i==`
|
`+e.scrub();for(let n of e.markers)i.marks.push(n)}return this.finishLeaf(i),null}stopAt(e){if(this.stoppedAt!=null&&this.stoppedAt<e)throw new RangeError("Can't move stoppedAt forward");this.stoppedAt=e}reuseFragment(e){if(!this.fragments.moveTo(this.absoluteLineStart+e,this.absoluteLineStart)||!this.fragments.matches(this.block.hash))return!1;let i=this.fragments.takeNodes(this);return i?(this.absoluteLineStart+=i,this.lineStart=Xy(this.absoluteLineStart,this.ranges),this.moveRangeI(),this.absoluteLineStart<this.to?(this.lineStart++,this.absoluteLineStart++,this.readLine()):(this.atEnd=!0,this.readLine()),!0):!1}get depth(){return this.stack.length}parentType(e=this.depth-1){return this.parser.nodeSet.types[this.stack[e].type]}nextLine(){return this.lineStart+=this.line.text.length,this.absoluteLineEnd>=this.to?(this.absoluteLineStart=this.absoluteLineEnd,this.atEnd=!0,this.readLine(),!1):(this.lineStart++,this.absoluteLineStart=this.absoluteLineEnd+1,this.moveRangeI(),this.readLine(),!0)}peekLine(){return this.scanLine(this.absoluteLineEnd+1).text}moveRangeI(){for(;this.rangeI<this.ranges.length-1&&this.absoluteLineStart>=this.ranges[this.rangeI].to;)this.rangeI++,this.absoluteLineStart=Math.max(this.absoluteLineStart,this.ranges[this.rangeI].from)}scanLine(e){let i=ZT;if(i.end=e,e>=this.to)i.text="";else if(i.text=this.lineChunkAt(e),i.end+=i.text.length,this.ranges.length>1){let n=this.absoluteLineStart,r=this.rangeI;for(;this.ranges[r].to<i.end;){r++;let s=this.ranges[r].from,o=this.lineChunkAt(s);i.end=s+o.length,i.text=i.text.slice(0,this.ranges[r-1].to-n)+o,n=i.end-i.text.length}}return i}readLine(){let{line:e}=this,{text:i,end:n}=this.scanLine(this.absoluteLineStart);for(this.absoluteLineEnd=n,e.reset(i);e.depth<this.stack.length;e.depth++){let r=this.stack[e.depth],s=this.parser.skipContextMarkup[r.type];if(!s)throw new Error("Unhandled block context "+A[r.type]);let o=this.line.markers.length;if(!s(r,this,e)){this.line.markers.length>o&&(r.end=this.line.markers[this.line.markers.length-1].to),e.forward();break}e.forward()}}lineChunkAt(e){let i=this.input.chunk(e),n;if(this.input.lineChunks)n=i==`
|
||||||
`?"":i;else{let r=i.indexOf(`
|
`?"":i;else{let r=i.indexOf(`
|
||||||
`);n=r<0?i:i.slice(0,r)}return e+n.length>this.to?n.slice(0,this.to-e):n}prevLineEnd(){return this.atEnd?this.lineStart:this.lineStart-1}startContext(e,i,n=0){this.block=ia.create(e,n,this.lineStart+i,this.block.hash,this.lineStart+this.line.text.length),this.stack.push(this.block)}startComposite(e,i,n=0){this.startContext(this.parser.getNodeType(e),i,n)}addNode(e,i,n){typeof e=="number"&&(e=new Me(this.parser.nodeSet.types[e],Er,Er,(n!=null?n:this.prevLineEnd())-i)),this.block.addChild(e,i-this.block.from)}addElement(e){this.block.addChild(e.toTree(this.parser.nodeSet),e.from-this.block.from)}addLeafElement(e,i){this.addNode(this.buffer.writeElements(Gu(i.children,e.marks),-i.from).finish(i.type,i.to-i.from),i.from)}finishContext(){let e=this.stack.pop(),i=this.stack[this.stack.length-1];i.addChild(e.toTree(this.parser.nodeSet),e.from-i.from),this.block=i}finish(){for(;this.stack.length>1;)this.finishContext();return this.addGaps(this.block.toTree(this.parser.nodeSet,this.lineStart))}addGaps(e){return this.ranges.length>1?vy(this.ranges,0,e.topNode,this.ranges[0].from,this.reusePlaceholders):e}finishLeaf(e){for(let n of e.parsers)if(n.finish(this,e))return;let i=Gu(this.parser.parseInline(e.content,e.start),e.marks);this.addNode(this.buffer.writeElements(i,-e.start).finish(C.Paragraph,e.content.length),e.start)}elt(e,i,n,r){return typeof e=="string"?se(this.parser.getNodeType(e),i,n,r):new ra(e,i)}get buffer(){return new na(this.parser.nodeSet)}};function vy(t,e,i,n,r){let s=t[e].to,o=[],l=[],a=i.from+n;function h(c,f){for(;f?c>=s:c>s;){let u=t[e+1].from-s;n+=u,c+=u,e++,s=t[e].to}}for(let c=i.firstChild;c;c=c.nextSibling){h(c.from+n,!0);let f=c.from+n,u,d=r.get(c.tree);d?u=d:c.to+n>s?(u=vy(t,e,c,n,r),h(c.to+n,!1)):u=c.toTree(),o.push(u),l.push(f-a)}return h(i.to+n,!1),new Me(i.type,o,l,i.to+n-a,i.tree?i.tree.propValues:void 0)}var eo=class t extends Hl{constructor(e,i,n,r,s,o,l,a,h){super(),this.nodeSet=e,this.blockParsers=i,this.leafBlockParsers=n,this.blockNames=r,this.endLeafBlock=s,this.skipContextMarkup=o,this.inlineParsers=l,this.inlineNames=a,this.wrappers=h,this.nodeTypes=Object.create(null);for(let c of e.types)this.nodeTypes[c.name]=c.id}createParse(e,i,n){let r=new Wu(this,e,i,n);for(let s of this.wrappers)r=s(r,e,i,n);return r}configure(e){let i=Vu(e);if(!i)return this;let{nodeSet:n,skipContextMarkup:r}=this,s=this.blockParsers.slice(),o=this.leafBlockParsers.slice(),l=this.blockNames.slice(),a=this.inlineParsers.slice(),h=this.inlineNames.slice(),c=this.endLeafBlock.slice(),f=this.wrappers;if(Hs(i.defineNodes)){r=Object.assign({},r);let u=n.types.slice(),d;for(let p of i.defineNodes){let{name:g,block:m,composite:b,style:y}=typeof p=="string"?{name:p}:p;if(u.some(S=>S.name==g))continue;b&&(r[u.length]=(S,k,w)=>b(k,w,S.value));let x=u.length,Q=b?["Block","BlockContext"]:m?x>=C.ATXHeading1&&x<=C.SetextHeading2?["Block","LeafBlock","Heading"]:["Block","LeafBlock"]:void 0;u.push(tt.define({id:x,name:g,props:Q&&[[ue.group,Q]]})),y&&(d||(d={}),Array.isArray(y)||y instanceof Pe?d[g]=y:Object.assign(d,y))}n=new Gs(u),d&&(n=n.extend(at(d)))}if(Hs(i.props)&&(n=n.extend(...i.props)),Hs(i.remove))for(let u of i.remove){let d=this.blockNames.indexOf(u),p=this.inlineNames.indexOf(u);d>-1&&(s[d]=o[d]=void 0),p>-1&&(a[p]=void 0)}if(Hs(i.parseBlock))for(let u of i.parseBlock){let d=l.indexOf(u.name);if(d>-1)s[d]=u.parse,o[d]=u.leaf;else{let p=u.before?ta(l,u.before):u.after?ta(l,u.after)+1:l.length-1;s.splice(p,0,u.parse),o.splice(p,0,u.leaf),l.splice(p,0,u.name)}u.endLeaf&&c.push(u.endLeaf)}if(Hs(i.parseInline))for(let u of i.parseInline){let d=h.indexOf(u.name);if(d>-1)a[d]=u.parse;else{let p=u.before?ta(h,u.before):u.after?ta(h,u.after)+1:h.length-1;a.splice(p,0,u.parse),h.splice(p,0,u.name)}}return i.wrap&&(f=f.concat(i.wrap)),new t(n,s,o,l,c,r,a,h,f)}getNodeType(e){let i=this.nodeTypes[e];if(i==null)throw new RangeError(`Unknown node type '${e}'`);return i}parseInline(e,i){let n=new io(this,e,i);e:for(let r=i;r<n.end;){let s=n.char(r);for(let o of this.inlineParsers)if(o){let l=o(n,s,r);if(l>=0){r=l;continue e}}r++}return n.resolveMarkers(0)}};function Hs(t){return t!=null&&t.length>0}function Vu(t){if(!Array.isArray(t))return t;if(t.length==0)return null;let e=Vu(t[0]);if(t.length==1)return e;let i=Vu(t.slice(1));if(!i||!e)return e||i;let n=(o,l)=>(o||Er).concat(l||Er),r=e.wrap,s=i.wrap;return{props:n(e.props,i.props),defineNodes:n(e.defineNodes,i.defineNodes),parseBlock:n(e.parseBlock,i.parseBlock),parseInline:n(e.parseInline,i.parseInline),remove:n(e.remove,i.remove),wrap:r?s?(o,l,a,h)=>r(s(o,l,a,h),l,a,h):r:s}}function ta(t,e){let i=t.indexOf(e);if(i<0)throw new RangeError(`Position specified relative to unknown parser ${e}`);return i}var Qy=[tt.none];for(let t=1,e;e=C[t];t++)Qy[t]=tt.define({id:t,name:e,props:t>=C.Escape?[]:[[ue.group,t in py?["Block","BlockContext"]:["Block","LeafBlock"]]],top:e=="Document"});var Er=[],na=class{constructor(e){this.nodeSet=e,this.content=[],this.nodes=[]}write(e,i,n,
Line truncated
|
`);n=r<0?i:i.slice(0,r)}return e+n.length>this.to?n.slice(0,this.to-e):n}prevLineEnd(){return this.atEnd?this.lineStart:this.lineStart-1}startContext(e,i,n=0){this.block=sa.create(e,n,this.lineStart+i,this.block.hash,this.lineStart+this.line.text.length),this.stack.push(this.block)}startComposite(e,i,n=0){this.startContext(this.parser.getNodeType(e),i,n)}addNode(e,i,n){typeof e=="number"&&(e=new Me(this.parser.nodeSet.types[e],Rr,Rr,(n!=null?n:this.prevLineEnd())-i)),this.block.addChild(e,i-this.block.from)}addElement(e){this.block.addChild(e.toTree(this.parser.nodeSet),e.from-this.block.from)}addLeafElement(e,i){this.addNode(this.buffer.writeElements(Hu(i.children,e.marks),-i.from).finish(i.type,i.to-i.from),i.from)}finishContext(){let e=this.stack.pop(),i=this.stack[this.stack.length-1];i.addChild(e.toTree(this.parser.nodeSet),e.from-i.from),this.block=i}finish(){for(;this.stack.length>1;)this.finishContext();return this.addGaps(this.block.toTree(this.parser.nodeSet,this.lineStart))}addGaps(e){return this.ranges.length>1?Ty(this.ranges,0,e.topNode,this.ranges[0].from,this.reusePlaceholders):e}finishLeaf(e){for(let n of e.parsers)if(n.finish(this,e))return;let i=Hu(this.parser.parseInline(e.content,e.start),e.marks);this.addNode(this.buffer.writeElements(i,-e.start).finish(A.Paragraph,e.content.length),e.start)}elt(e,i,n,r){return typeof e=="string"?oe(this.parser.getNodeType(e),i,n,r):new la(e,i)}get buffer(){return new oa(this.parser.nodeSet)}};function Ty(t,e,i,n,r){let s=t[e].to,o=[],l=[],a=i.from+n;function h(c,f){for(;f?c>=s:c>s;){let u=t[e+1].from-s;n+=u,c+=u,e++,s=t[e].to}}for(let c=i.firstChild;c;c=c.nextSibling){h(c.from+n,!0);let f=c.from+n,u,d=r.get(c.tree);d?u=d:c.to+n>s?(u=Ty(t,e,c,n,r),h(c.to+n,!1)):u=c.toTree(),o.push(u),l.push(f-a)}return h(i.to+n,!1),new Me(i.type,o,l,i.to+n-a,i.tree?i.tree.propValues:void 0)}var to=class t extends ea{constructor(e,i,n,r,s,o,l,a,h){super(),this.nodeSet=e,this.blockParsers=i,this.leafBlockParsers=n,this.blockNames=r,this.endLeafBlock=s,this.skipContextMarkup=o,this.inlineParsers=l,this.inlineNames=a,this.wrappers=h,this.nodeTypes=Object.create(null);for(let c of e.types)this.nodeTypes[c.name]=c.id}createParse(e,i,n){let r=new Uu(this,e,i,n);for(let s of this.wrappers)r=s(r,e,i,n);return r}configure(e){let i=Fu(e);if(!i)return this;let{nodeSet:n,skipContextMarkup:r}=this,s=this.blockParsers.slice(),o=this.leafBlockParsers.slice(),l=this.blockNames.slice(),a=this.inlineParsers.slice(),h=this.inlineNames.slice(),c=this.endLeafBlock.slice(),f=this.wrappers;if(Ks(i.defineNodes)){r=Object.assign({},r);let u=n.types.slice(),d;for(let p of i.defineNodes){let{name:g,block:m,composite:b,style:y}=typeof p=="string"?{name:p}:p;if(u.some(x=>x.name==g))continue;b&&(r[u.length]=(x,w,k)=>b(w,k,x.value));let S=u.length,v=b?["Block","BlockContext"]:m?S>=A.ATXHeading1&&S<=A.SetextHeading2?["Block","LeafBlock","Heading"]:["Block","LeafBlock"]:void 0;u.push(tt.define({id:S,name:g,props:v&&[[de.group,v]]})),y&&(d||(d={}),Array.isArray(y)||y instanceof $e?d[g]=y:Object.assign(d,y))}n=new Us(u),d&&(n=n.extend(at(d)))}if(Ks(i.props)&&(n=n.extend(...i.props)),Ks(i.remove))for(let u of i.remove){let d=this.blockNames.indexOf(u),p=this.inlineNames.indexOf(u);d>-1&&(s[d]=o[d]=void 0),p>-1&&(a[p]=void 0)}if(Ks(i.parseBlock))for(let u of i.parseBlock){let d=l.indexOf(u.name);if(d>-1)s[d]=u.parse,o[d]=u.leaf;else{let p=u.before?ra(l,u.before):u.after?ra(l,u.after)+1:l.length-1;s.splice(p,0,u.parse),o.splice(p,0,u.leaf),l.splice(p,0,u.name)}u.endLeaf&&c.push(u.endLeaf)}if(Ks(i.parseInline))for(let u of i.parseInline){let d=h.indexOf(u.name);if(d>-1)a[d]=u.parse;else{let p=u.before?ra(h,u.before):u.after?ra(h,u.after)+1:h.length-1;a.splice(p,0,u.parse),h.splice(p,0,u.name)}}return i.wrap&&(f=f.concat(i.wrap)),new t(n,s,o,l,c,r,a,h,f)}getNodeType(e){let i=this.nodeTypes[e];if(i==null)throw new RangeError(`Unknown node type '${e}'`);return i}parseInline(e,i){let n=new no(this,e,i);e:for(let r=i;r<n.end;){let s=n.char(r);for(let o of this.inlineParsers)if(o){let l=o(n,s,r);if(l>=0){r=l;continue e}}r++}return n.resolveMarkers(0)}};function Ks(t){return t!=null&&t.length>0}function Fu(t){if(!Array.isArray(t))return t;if(t.length==0)return null;let e=Fu(t[0]);if(t.length==1)return e;let i=Fu(t.slice(1));if(!i||!e)return e||i;let n=(o,l)=>(o||Rr).concat(l||Rr),r=e.wrap,s=i.wrap;return{props:n(e.props,i.props),defineNodes:n(e.defineNodes,i.defineNodes),parseBlock:n(e.parseBlock,i.parseBlock),parseInline:n(e.parseInline,i.parseInline),remove:n(e.remove,i.remove),wrap:r?s?(o,l,a,h)=>r(s(o,l,a,h),l,a,h):r:s}}function ra(t,e){let i=t.indexOf(e);if(i<0)throw new RangeError(`Position specified relative to unknown parser ${e}`);return i}var Cy=[tt.none];for(let t=1,e;e=A[t];t++)Cy[t]=tt.define({id:t,name:e,props:t>=A.Escape?[]:[[de.group,t in by?["Block","BlockContext"]:["Block","LeafBlock"]]],top:e=="Document"});var Rr=[],oa=class{constructor(e){this.nodeSet=e,this.content=[],this.nodes=[]}write(e,i,n,
Line truncated
|
||||||
`;)s--;this.fragmentEnd=s?s-1:0}let n=this.cursor;n||(n=this.cursor=this.fragment.tree.cursor(),n.firstChild());let r=e+this.fragment.offset;for(;n.to<=r;)if(!n.parent())return!1;for(;;){if(n.from>=r)return this.fragment.from<=i;if(!n.childAfter(r))return!1}}matches(e){let i=this.cursor.tree;return i&&i.prop(ue.contextHash)==e}takeNodes(e){let i=this.cursor,n=this.fragment.offset,r=this.fragmentEnd-(this.fragment.openEnd?1:0),s=e.absoluteLineStart,o=s,l=e.block.children.length,a=o,h=l;for(;;){if(i.to-n>r){if(i.type.isAnonymous&&i.firstChild())continue;break}let c=Ry(i.from-n,e.ranges);if(i.to-n<=e.ranges[e.rangeI].to)e.addNode(i.tree,c);else{let f=new Me(e.parser.nodeSet.types[C.Paragraph],[],[],0,e.block.hashProp);e.reusePlaceholders.set(f,i.tree),e.addNode(f,c)}if(i.type.is("Block")&&(ZT.indexOf(i.type.id)<0?(o=i.to-n,l=e.block.children.length):(o=a,l=h),a=i.to-n,h=e.block.children.length),!i.nextSibling())break}for(;e.block.children.length>l;)e.block.children.pop(),e.block.positions.pop();return o-s}};function Ry(t,e){let i=t;for(let n=1;n<e.length;n++){let r=e[n-1].to,s=e[n].from;r<t&&(i-=s-r)}return i}var DT=at({"Blockquote/...":O.quote,HorizontalRule:O.contentSeparator,"ATXHeading1/... SetextHeading1/...":O.heading1,"ATXHeading2/... SetextHeading2/...":O.heading2,"ATXHeading3/...":O.heading3,"ATXHeading4/...":O.heading4,"ATXHeading5/...":O.heading5,"ATXHeading6/...":O.heading6,"Comment CommentBlock":O.comment,Escape:O.escape,Entity:O.character,"Emphasis/...":O.emphasis,"StrongEmphasis/...":O.strong,"Link/... Image/...":O.link,"OrderedList/... BulletList/...":O.list,"BlockQuote/...":O.quote,"InlineCode CodeText":O.monospace,"URL Autolink":O.url,"HeaderMark HardBreak QuoteMark ListMark LinkMark EmphasisMark CodeMark":O.processingInstruction,"CodeInfo LinkLabel":O.labelName,LinkTitle:O.string,Paragraph:O.content}),Ey=new eo(new Gs(Qy).extend(DT),Object.keys(ea).map(t=>ea[t]),Object.keys(ea).map(t=>wy[t]),Object.keys(ea),LT,py,Object.keys(Iu).map(t=>Iu[t]),Object.keys(Iu),[]);function IT(t,e,i){let n=[];for(let r=t.firstChild,s=e;;r=r.nextSibling){let o=r?r.from:i;if(o>s&&n.push({from:s,to:o}),!r)break;s=r.to}return n}function My(t){let{codeParser:e,htmlParser:i}=t;return{wrap:iy((r,s)=>{let o=r.type.id;if(e&&(o==C.CodeBlock||o==C.FencedCode)){let l="";if(o==C.FencedCode){let h=r.node.getChild(C.CodeInfo);h&&(l=s.read(h.from,h.to))}let a=e(l);if(a)return{parser:a,overlay:h=>h.type.id==C.CodeText,bracketed:o==C.FencedCode}}else if(i&&(o==C.HTMLBlock||o==C.HTMLTag||o==C.CommentBlock))return{parser:i,overlay:IT(r.node,r.from,r.to)};return null})}}var BT={resolve:"Strikethrough",mark:"StrikethroughMark"},NT={defineNodes:[{name:"Strikethrough",style:{"Strikethrough/...":O.strikethrough}},{name:"StrikethroughMark",style:O.processingInstruction}],parseInline:[{name:"Strikethrough",parse(t,e,i){if(e!=126||t.char(i+1)!=126||t.char(i+2)==126)return-1;let n=t.slice(i-1,i),r=t.slice(i+2,i+3),s=/\s|^$/.test(n),o=/\s|^$/.test(r),l=to.test(n),a=to.test(r);return t.addDelimiter(BT,i,i+2,!o&&(!a||s||l),!s&&(!l||o||a))},after:"Emphasis"}]};function Js(t,e,i=0,n,r=0){let s=0,o=!0,l=-1,a=-1,h=!1,c=()=>{n.push(t.elt("TableCell",r+l,r+a,t.parser.parseInline(e.slice(l,a),r+l)))};for(let f=i;f<e.length;f++){let u=e.charCodeAt(f);u==124&&!h?((!o||l>-1)&&s++,o=!1,n&&(l>-1&&c(),n.push(t.elt("TableDelimiter",f+r,f+r+1))),l=a=-1):(h||u!=32&&u!=9)&&(l<0&&(l=f),a=f+1),h=!h&&u==92}return l>-1&&(s++,n&&c()),s}function ly(t,e){for(let i=e;i<t.length;i++){let n=t.charCodeAt(i);if(n==124)return!0;n==92&&i++}return!1}var Ly=/^\|?(\s*:?-+:?\s*\|)+(\s*:?-+:?\s*)?$/,oa=class{constructor(){this.rows=null}nextLine(e,i,n){if(this.rows==null){this.rows=!1;let r;if((i.next==45||i.next==58||i.next==124)&&Ly.test(r=i.text.slice(i.pos))){let s=[];Js(e,n.content,0,s,n.start)==Js(e,r,0)&&(this.rows=[e.elt("TableHeader",n.start,n.start+n.content.length,s),e.elt("TableDelimiter",e.lineStart+i.pos,e.lineStart+i.text.length)])}}else if(this.rows){let r=[];Js(e,i.text,i.pos,r,e.lineStart),this.rows.push(e.elt("TableRow",e.lineStart+i.pos,e.lineStart+i.text.length,r))}return!1}finish(e,i){return this.rows?(e.addLeafElement(i,e.elt("Table",i.start,i.start+i.content.length,this.rows)),!0):!1}},jT={defineNodes:[{name:"Table",block:!0},{name:"TableHeader",style:{"TableHeader/...":O.heading}},"TableRow",{name:"TableCell",style:O.content},{name:"TableDelimiter",style:O.processingInstruction}],parseBlock:[{name:"Table",leaf(t,e){return ly(e.content,0)?new oa:null},endLeaf(t,e,i){if(i.parsers.some(r=>r instanceof oa)||!ly(e.text,e.basePos))return!1;let n=t.peekLine();return Ly.test(n)&&Js(t,e.text,e.basePos)==Js(t,n,e.basePos)},before:"SetextHeading"}]},Fu=class{nextLine(){return!1}finish(e,i){return e.addLeafElement(i,e.elt("Task",i.start,i.start+i.content.length,[e.elt("TaskMarker",i.start,i.start+3),...e.parser.parseInline(i.content.slice(3),i.start+3)])),!0}},zT={defineNodes:[{name:"Task",block:!0,style:O.list},{name:"TaskMarker",style:O.atom}],parseBlock:[{name:
Line truncated
|
`;)s--;this.fragmentEnd=s?s-1:0}let n=this.cursor;n||(n=this.cursor=this.fragment.tree.cursor(),n.firstChild());let r=e+this.fragment.offset;for(;n.to<=r;)if(!n.parent())return!1;for(;;){if(n.from>=r)return this.fragment.from<=i;if(!n.childAfter(r))return!1}}matches(e){let i=this.cursor.tree;return i&&i.prop(de.contextHash)==e}takeNodes(e){let i=this.cursor,n=this.fragment.offset,r=this.fragmentEnd-(this.fragment.openEnd?1:0),s=e.absoluteLineStart,o=s,l=e.block.children.length,a=o,h=l;for(;;){if(i.to-n>r){if(i.type.isAnonymous&&i.firstChild())continue;break}let c=Xy(i.from-n,e.ranges);if(i.to-n<=e.ranges[e.rangeI].to)e.addNode(i.tree,c);else{let f=new Me(e.parser.nodeSet.types[A.Paragraph],[],[],0,e.block.hashProp);e.reusePlaceholders.set(f,i.tree),e.addNode(f,c)}if(i.type.is("Block")&&(IT.indexOf(i.type.id)<0?(o=i.to-n,l=e.block.children.length):(o=a,l=h),a=i.to-n,h=e.block.children.length),!i.nextSibling())break}for(;e.block.children.length>l;)e.block.children.pop(),e.block.positions.pop();return o-s}};function Xy(t,e){let i=t;for(let n=1;n<e.length;n++){let r=e[n-1].to,s=e[n].from;r<t&&(i-=s-r)}return i}var BT=at({"Blockquote/...":O.quote,HorizontalRule:O.contentSeparator,"ATXHeading1/... SetextHeading1/...":O.heading1,"ATXHeading2/... SetextHeading2/...":O.heading2,"ATXHeading3/...":O.heading3,"ATXHeading4/...":O.heading4,"ATXHeading5/...":O.heading5,"ATXHeading6/...":O.heading6,"Comment CommentBlock":O.comment,Escape:O.escape,Entity:O.character,"Emphasis/...":O.emphasis,"StrongEmphasis/...":O.strong,"Link/... Image/...":O.link,"OrderedList/... BulletList/...":O.list,"BlockQuote/...":O.quote,"InlineCode CodeText":O.monospace,"URL Autolink":O.url,"HeaderMark HardBreak QuoteMark ListMark LinkMark EmphasisMark CodeMark":O.processingInstruction,"CodeInfo LinkLabel":O.labelName,LinkTitle:O.string,Paragraph:O.content}),_y=new to(new Us(Cy).extend(BT),Object.keys(na).map(t=>na[t]),Object.keys(na).map(t=>$y[t]),Object.keys(na),_T,by,Object.keys(ju).map(t=>ju[t]),Object.keys(ju),[]);function NT(t,e,i){let n=[];for(let r=t.firstChild,s=e;;r=r.nextSibling){let o=r?r.from:i;if(o>s&&n.push({from:s,to:o}),!r)break;s=r.to}return n}function Zy(t){let{codeParser:e,htmlParser:i}=t;return{wrap:oy((r,s)=>{let o=r.type.id;if(e&&(o==A.CodeBlock||o==A.FencedCode)){let l="";if(o==A.FencedCode){let h=r.node.getChild(A.CodeInfo);h&&(l=s.read(h.from,h.to))}let a=e(l);if(a)return{parser:a,overlay:h=>h.type.id==A.CodeText,bracketed:o==A.FencedCode}}else if(i&&(o==A.HTMLBlock||o==A.HTMLTag||o==A.CommentBlock))return{parser:i,overlay:NT(r.node,r.from,r.to)};return null})}}var jT={resolve:"Strikethrough",mark:"StrikethroughMark"},zT={defineNodes:[{name:"Strikethrough",style:{"Strikethrough/...":O.strikethrough}},{name:"StrikethroughMark",style:O.processingInstruction}],parseInline:[{name:"Strikethrough",parse(t,e,i){if(e!=126||t.char(i+1)!=126||t.char(i+2)==126)return-1;let n=t.slice(i-1,i),r=t.slice(i+2,i+3),s=/\s|^$/.test(n),o=/\s|^$/.test(r),l=io.test(n),a=io.test(r);return t.addDelimiter(jT,i,i+2,!o&&(!a||s||l),!s&&(!l||o||a))},after:"Emphasis"}]};function eo(t,e,i=0,n,r=0){let s=0,o=!0,l=-1,a=-1,h=!1,c=()=>{n.push(t.elt("TableCell",r+l,r+a,t.parser.parseInline(e.slice(l,a),r+l)))};for(let f=i;f<e.length;f++){let u=e.charCodeAt(f);u==124&&!h?((!o||l>-1)&&s++,o=!1,n&&(l>-1&&c(),n.push(t.elt("TableDelimiter",f+r,f+r+1))),l=a=-1):(h||u!=32&&u!=9)&&(l<0&&(l=f),a=f+1),h=!h&&u==92}return l>-1&&(s++,n&&c()),s}function fy(t,e){for(let i=e;i<t.length;i++){let n=t.charCodeAt(i);if(n==124)return!0;n==92&&i++}return!1}var Dy=/^\|?(\s*:?-+:?\s*\|)+(\s*:?-+:?\s*)?$/,ca=class{constructor(){this.rows=null}nextLine(e,i,n){if(this.rows==null){this.rows=!1;let r;if((i.next==45||i.next==58||i.next==124)&&Dy.test(r=i.text.slice(i.pos))){let s=[];eo(e,n.content,0,s,n.start)==eo(e,r,0)&&(this.rows=[e.elt("TableHeader",n.start,n.start+n.content.length,s),e.elt("TableDelimiter",e.lineStart+i.pos,e.lineStart+i.text.length)])}}else if(this.rows){let r=[];eo(e,i.text,i.pos,r,e.lineStart),this.rows.push(e.elt("TableRow",e.lineStart+i.pos,e.lineStart+i.text.length,r))}return!1}finish(e,i){return this.rows?(e.addLeafElement(i,e.elt("Table",i.start,i.start+i.content.length,this.rows)),!0):!1}},YT={defineNodes:[{name:"Table",block:!0},{name:"TableHeader",style:{"TableHeader/...":O.heading}},"TableRow",{name:"TableCell",style:O.content},{name:"TableDelimiter",style:O.processingInstruction}],parseBlock:[{name:"Table",leaf(t,e){return fy(e.content,0)?new ca:null},endLeaf(t,e,i){if(i.parsers.some(r=>r instanceof ca)||!fy(e.text,e.basePos))return!1;let n=t.peekLine();return Dy.test(n)&&eo(t,e.text,e.basePos)==eo(t,n,e.basePos)},before:"SetextHeading"}]},Ju=class{nextLine(){return!1}finish(e,i){return e.addLeafElement(i,e.elt("Task",i.start,i.start+i.content.length,[e.elt("TaskMarker",i.start,i.start+3),...e.parser.parseInline(i.content.slice(3),i.start+3)])),!0}},qT={defineNodes:[{name:"Task",block:!0,style:O.list},{name:"TaskMarker",style:O.atom}],parseBlock:[{name:
Line truncated
|
||||||
\${}
|
\${}
|
||||||
} catch (\${error}) {
|
} catch (\${error}) {
|
||||||
\${}
|
\${}
|
||||||
}`,{label:"try",detail:"/ catch block",type:"keyword"}),A("if (${}) {\n ${}\n}",{label:"if",detail:"block",type:"keyword"}),A(`if (\${}) {
|
}`,{label:"try",detail:"/ catch block",type:"keyword"}),M("if (${}) {\n ${}\n}",{label:"if",detail:"block",type:"keyword"}),M(`if (\${}) {
|
||||||
\${}
|
\${}
|
||||||
} else {
|
} else {
|
||||||
\${}
|
\${}
|
||||||
}`,{label:"if",detail:"/ else block",type:"keyword"}),A(`class \${name} {
|
}`,{label:"if",detail:"/ else block",type:"keyword"}),M(`class \${name} {
|
||||||
constructor(\${params}) {
|
constructor(\${params}) {
|
||||||
\${}
|
\${}
|
||||||
}
|
}
|
||||||
}`,{label:"class",detail:"definition",type:"keyword"}),A('import {${names}} from "${module}"\n${}',{label:"import",detail:"named",type:"keyword"}),A('import ${name} from "${module}"\n${}',{label:"import",detail:"default",type:"keyword"})],BA=k1.concat([A("interface ${name} {\n ${}\n}",{label:"interface",detail:"definition",type:"keyword"}),A("type ${name} = ${type}",{label:"type",detail:"definition",type:"keyword"}),A("enum ${name} {\n ${}\n}",{label:"enum",detail:"definition",type:"keyword"})]),y1=new br,w1=new Set(["Script","Block","FunctionExpression","FunctionDeclaration","ArrowFunction","MethodDeclaration","ForStatement"]);function so(t){return(e,i)=>{let n=e.node.getChild("VariableDefinition");return n&&i(n,t),!0}}var NA=["FunctionDeclaration"],jA={FunctionDeclaration:so("function"),ClassDeclaration:so("class"),ClassExpression:()=>!0,EnumDeclaration:so("constant"),TypeAliasDeclaration:so("type"),NamespaceDeclaration:so("namespace"),VariableDefinition(t,e){t.matchContext(NA)||e(t,"variable")},TypeDefinition(t,e){e(t,"type")},__proto__:null};function v1(t,e){let i=y1.get(e);if(i)return i;let n=[],r=!0;function s(o,l){let a=t.sliceString(o.from,o.to);n.push({label:a,type:l})}return e.cursor(Oe.IncludeAnonymous).iterate(o=>{if(r)r=!1;else if(o.name){let l=jA[o.name];if(l&&l(o,s)||w1.has(o.name))return!1}else if(o.to-o.from>8192){for(let l of v1(t,o.node))n.push(l);return!1}}),y1.set(e,n),n}var S1=/^[\w$\xa1-\uffff][\w$\d\xa1-\uffff]*$/,Q1=["TemplateString","String","RegExp","LineComment","BlockComment","VariableDefinition","TypeDefinition","Label","PropertyDefinition","PropertyName","PrivatePropertyDefinition","PrivatePropertyName","JSXText","JSXAttributeValue","JSXOpenTag","JSXCloseTag","JSXSelfClosingTag",".","?."];function zA(t){let e=he(t.state).resolveInner(t.pos,-1);if(Q1.indexOf(e.name)>-1)return null;let i=e.name=="VariableName"||e.to-e.from<20&&S1.test(t.state.sliceDoc(e.from,e.to));if(!i&&!t.explicit)return null;let n=[];for(let r=e;r;r=r.parent)w1.has(r.name)&&(n=n.concat(v1(t.state.doc,r)));return{options:n,from:i?e.from:t.pos,validFor:S1}}var Ut=Yt.define({name:"javascript",parser:b1.configure({props:[Et.add({IfStatement:kr({except:/^\s*({|else\b)/}),TryStatement:kr({except:/^\s*({|catch\b|finally\b)/}),LabeledStatement:a0,SwitchBody:t=>{let e=t.textAfter,i=/^\s*\}/.test(e),n=/^\s*(case|default)\b/.test(e);return t.baseIndent+(i?0:n?1:2)*t.unit},Block:Zs({closing:"}"}),ArrowFunction:t=>t.baseIndent+t.unit,"TemplateString BlockComment":()=>null,"Statement Property":kr({except:/^\s*{/}),JSXElement(t){let e=/^\s*<\//.test(t.textAfter);return t.lineIndent(t.node.from)+(e?0:t.unit)},JSXEscape(t){let e=/\s*\}/.test(t.textAfter);return t.lineIndent(t.node.from)+(e?0:t.unit)},"JSXOpenTag JSXSelfClosingTag"(t){return t.column(t.node.from)+t.unit}}),Mt.add({"Block ClassBody SwitchBody EnumBody ObjectExpression ArrayExpression ObjectType":wr,BlockComment(t){return{from:t.from+2,to:t.to-2}},JSXElement(t){let e=t.firstChild;if(!e||e.name=="JSXSelfClosingTag")return null;let i=t.lastChild;return{from:e.to,to:i.type.isError?t.to:i.from}},"JSXSelfClosingTag JSXOpenTag"(t){var e;let i=(e=t.firstChild)===null||e===void 0?void 0:e.nextSibling,n=t.lastChild;return!i||i.type.isError?null:{from:i.to,to:n.type.isError?t.to:n.from}}})]}),languageData:{closeBrackets:{brackets:["(","[","{","'",'"',"`"]},commentTokens:{line:"//",block:{open:"/*",close:"*/"}},indentOnInput:/^\s*(?:case |default:|\{|\}|<\/)$/,wordChars:"$"}}),P1={test:t=>/^JSX/.test(t.name),facet:Sr({commentTokens:{block:{open:"{/*",close:"*/}"}}})},pd=Ut.configure({dialect:"ts"},"typescript"),gd=Ut.configure({dialect:"jsx",props:[Al.add(t=>t.isTop?[P1]:void 0)]}),Od=Ut.configure({dialect:"jsx ts",props:[Al.add(t=>t.isTop?[P1]:void 0)]},"typescript"),$1=t=>({label:t,type:"keyword"}),T1="break case const continue default delete export extends false finally in instanceof let new return static super switch this throw true typeof var yield".split(" ").map($1),YA=T1.concat(["declare","implements","private","protected","public"].map($1));function C1(t={}){let e=t.jsx?t.typescript?Od:gd:t.typescript?pd:Ut,i=t.typescript?BA.concat(YA):k1.concat(T1);return new Qt(e,[Ut.data.of({autocomplete:_b(Q1,bu(i))}),Ut.data.of({autocomplete:zA}),t.jsx?VA:[]])}function qA(t){for(;;){if(t.name=="JSXOpenTag"||t.name=="JSXSelfClosingTag"||t.name=="JSXFragmentTag")return t;if(t.name=="JSXEscape"||!t.parent)return null;t=t.parent}}function x1(t,e,i=t.length){for(let n=e==null?void 0:e.firstChild;n;n=n.nextSibling)if(n.name=="JSXIdentifier"||n.name=="JSXBuiltin"||n.name=="JSXNamespacedName"||n.name=="JSXMemberExpression")return t.sliceString(n.from,Math.min(n.to,i));return""}var WA=typeof navigator=="object"&&/Android\b/.test(navigator.userAgent),VA=T.inputHandler.of((t,e,i,n,r)=>{if((WA?t.composing:t.compositionStarted)||t.state.readOnly||e!=i||n!=">"&&n!="/"||!Ut.isActiveAt(t.state,e,-1))return!1;let s=r(),{state:o}=s,l=o.changeByRange(a=>{var h;let{head:c}=a,f=he(o).resolveInn
Line truncated
|
}`,{label:"class",detail:"definition",type:"keyword"}),M('import {${names}} from "${module}"\n${}',{label:"import",detail:"named",type:"keyword"}),M('import ${name} from "${module}"\n${}',{label:"import",detail:"default",type:"keyword"})],jA=P1.concat([M("interface ${name} {\n ${}\n}",{label:"interface",detail:"definition",type:"keyword"}),M("type ${name} = ${type}",{label:"type",detail:"definition",type:"keyword"}),M("enum ${name} {\n ${}\n}",{label:"enum",detail:"definition",type:"keyword"})]),w1=new mr,$1=new Set(["Script","Block","FunctionExpression","FunctionDeclaration","ArrowFunction","MethodDeclaration","ForStatement"]);function oo(t){return(e,i)=>{let n=e.node.getChild("VariableDefinition");return n&&i(n,t),!0}}var zA=["FunctionDeclaration"],YA={FunctionDeclaration:oo("function"),ClassDeclaration:oo("class"),ClassExpression:()=>!0,EnumDeclaration:oo("constant"),TypeAliasDeclaration:oo("type"),NamespaceDeclaration:oo("namespace"),VariableDefinition(t,e){t.matchContext(zA)||e(t,"variable")},TypeDefinition(t,e){e(t,"type")},__proto__:null};function T1(t,e){let i=w1.get(e);if(i)return i;let n=[],r=!0;function s(o,l){let a=t.sliceString(o.from,o.to);n.push({label:a,type:l})}return e.cursor(be.IncludeAnonymous).iterate(o=>{if(r)r=!1;else if(o.name){let l=YA[o.name];if(l&&l(o,s)||$1.has(o.name))return!1}else if(o.to-o.from>8192){for(let l of T1(t,o.node))n.push(l);return!1}}),w1.set(e,n),n}var v1=/^[\w$\xa1-\uffff][\w$\d\xa1-\uffff]*$/,C1=["TemplateString","String","RegExp","LineComment","BlockComment","VariableDefinition","TypeDefinition","Label","PropertyDefinition","PropertyName","PrivatePropertyDefinition","PrivatePropertyName","JSXText","JSXAttributeValue","JSXOpenTag","JSXCloseTag","JSXSelfClosingTag",".","?."];function qA(t){let e=fe(t.state).resolveInner(t.pos,-1);if(C1.indexOf(e.name)>-1)return null;let i=e.name=="VariableName"||e.to-e.from<20&&v1.test(t.state.sliceDoc(e.from,e.to));if(!i&&!t.explicit)return null;let n=[];for(let r=e;r;r=r.parent)$1.has(r.name)&&(n=n.concat(T1(t.state.doc,r)));return{options:n,from:i?e.from:t.pos,validFor:v1}}var Ft=qt.define({name:"javascript",parser:k1.configure({props:[Et.add({IfStatement:xr({except:/^\s*({|else\b)/}),TryStatement:xr({except:/^\s*({|catch\b|finally\b)/}),LabeledStatement:u0,SwitchBody:t=>{let e=t.textAfter,i=/^\s*\}/.test(e),n=/^\s*(case|default)\b/.test(e);return t.baseIndent+(i?0:n?1:2)*t.unit},Block:Ds({closing:"}"}),ArrowFunction:t=>t.baseIndent+t.unit,"TemplateString BlockComment":()=>null,"Statement Property":xr({except:/^\s*{/}),JSXElement(t){let e=/^\s*<\//.test(t.textAfter);return t.lineIndent(t.node.from)+(e?0:t.unit)},JSXEscape(t){let e=/\s*\}/.test(t.textAfter);return t.lineIndent(t.node.from)+(e?0:t.unit)},"JSXOpenTag JSXSelfClosingTag"(t){return t.column(t.node.from)+t.unit}}),Mt.add({"Block ClassBody SwitchBody EnumBody ObjectExpression ArrayExpression ObjectType":kr,BlockComment(t){return{from:t.from+2,to:t.to-2}},JSXElement(t){let e=t.firstChild;if(!e||e.name=="JSXSelfClosingTag")return null;let i=t.lastChild;return{from:e.to,to:i.type.isError?t.to:i.from}},"JSXSelfClosingTag JSXOpenTag"(t){var e;let i=(e=t.firstChild)===null||e===void 0?void 0:e.nextSibling,n=t.lastChild;return!i||i.type.isError?null:{from:i.to,to:n.type.isError?t.to:n.from}}})]}),languageData:{closeBrackets:{brackets:["(","[","{","'",'"',"`"]},commentTokens:{line:"//",block:{open:"/*",close:"*/"}},indentOnInput:/^\s*(?:case |default:|\{|\}|<\/)$/,wordChars:"$"}}),A1={test:t=>/^JSX/.test(t.name),facet:yr({commentTokens:{block:{open:"{/*",close:"*/}"}}})},md=Ft.configure({dialect:"ts"},"typescript"),bd=Ft.configure({dialect:"jsx",props:[Ml.add(t=>t.isTop?[A1]:void 0)]}),yd=Ft.configure({dialect:"jsx ts",props:[Ml.add(t=>t.isTop?[A1]:void 0)]},"typescript"),R1=t=>({label:t,type:"keyword"}),E1="break case const continue default delete export extends false finally in instanceof let new return static super switch this throw true typeof var yield".split(" ").map(R1),WA=E1.concat(["declare","implements","private","protected","public"].map(R1));function M1(t={}){let e=t.jsx?t.typescript?yd:bd:t.typescript?md:Ft,i=t.typescript?jA.concat(WA):P1.concat(E1);return new Pt(e,[Ft.data.of({autocomplete:Bb(C1,xu(i))}),Ft.data.of({autocomplete:qA}),t.jsx?UA:[]])}function VA(t){for(;;){if(t.name=="JSXOpenTag"||t.name=="JSXSelfClosingTag"||t.name=="JSXFragmentTag")return t;if(t.name=="JSXEscape"||!t.parent)return null;t=t.parent}}function Q1(t,e,i=t.length){for(let n=e==null?void 0:e.firstChild;n;n=n.nextSibling)if(n.name=="JSXIdentifier"||n.name=="JSXBuiltin"||n.name=="JSXNamespacedName"||n.name=="JSXMemberExpression")return t.sliceString(n.from,Math.min(n.to,i));return""}var GA=typeof navigator=="object"&&/Android\b/.test(navigator.userAgent),UA=T.inputHandler.of((t,e,i,n,r)=>{if((GA?t.composing:t.compositionStarted)||t.state.readOnly||e!=i||n!=">"&&n!="/"||!Ft.isActiveAt(t.state,e,-1))return!1;let s=r(),{state:o}=s,l=o.changeByRange(a=>{var h;let{head:c}=a,f=fe(o).resolveInn
Line truncated
|
||||||
${a}`}let f=Ed(t.buffer,r[l],s[l],t.position,c);a+=`${" ".repeat(i.indent)}${Md((t.line+1).toString(),h)} | ${f.str}
|
${a}`}let f=Xd(t.buffer,r[l],s[l],t.position,c);a+=`${" ".repeat(i.indent)}${_d((t.line+1).toString(),h)} | ${f.str}
|
||||||
`,a+=`${"-".repeat(i.indent+h+3+f.pos)}^
|
`,a+=`${"-".repeat(i.indent+h+3+f.pos)}^
|
||||||
`;for(let u=1;u<=i.linesAfter&&!(l+u>=s.length);u++){let d=Ed(t.buffer,r[l+u],s[l+u],t.position-(r[l]-r[l+u]),c);a+=`${" ".repeat(i.indent)}${Md((t.line+u+1).toString(),h)} | ${d.str}
|
`;for(let u=1;u<=i.linesAfter&&!(l+u>=s.length);u++){let d=Xd(t.buffer,r[l+u],s[l+u],t.position-(r[l]-r[l+u]),c);a+=`${" ".repeat(i.indent)}${_d((t.line+u+1).toString(),h)} | ${d.str}
|
||||||
`}return a.replace(/\n$/,"")}function bS(t,e){let i="";return t.mark?(t.mark.name&&(i+=`in "${t.mark.name}" `),i+=`(${t.mark.line+1}:${t.mark.column+1})`,!e&&t.mark.snippet&&(i+=`
|
`}return a.replace(/\n$/,"")}function kS(t,e){let i="";return t.mark?(t.mark.name&&(i+=`in "${t.mark.name}" `),i+=`(${t.mark.line+1}:${t.mark.column+1})`,!e&&t.mark.snippet&&(i+=`
|
||||||
|
|
||||||
${t.mark.snippet}`),`${t.reason} ${i}`):t.reason}var CS=class extends Error{constructor(e,i){super();J(this,"reason");J(this,"mark");this.name="YAMLException",this.reason=e,this.mark=i,this.message=bS(this,!1),Error.captureStackTrace&&Error.captureStackTrace(this,this.constructor)}toString(e){return`${this.name}: ${bS(this,e)}`}};function Pa(t,e,i,n=""){let r=0,s=0;for(let l=0;l<e;l++){let a=t.charCodeAt(l);a===10?(r++,s=l+1):a===13&&(r++,t.charCodeAt(l+1)===10&&l++,s=l+1)}let o={name:n,buffer:t,position:e,line:r,column:e-s};throw o.snippet=X2(o),new CS(i,o)}var _2=-1;function yS(t){switch(t){case 48:return"\0";case 97:return"\x07";case 98:return"\b";case 116:return" ";case 9:return" ";case 110:return`
|
${t.mark.snippet}`),`${t.reason} ${i}`):t.reason}var MS=class extends Error{constructor(e,i){super();K(this,"reason");K(this,"mark");this.name="YAMLException",this.reason=e,this.mark=i,this.message=kS(this,!1),Error.captureStackTrace&&Error.captureStackTrace(this,this.constructor)}toString(e){return`${this.name}: ${kS(this,e)}`}};function Ca(t,e,i,n=""){let r=0,s=0;for(let l=0;l<e;l++){let a=t.charCodeAt(l);a===10?(r++,s=l+1):a===13&&(r++,t.charCodeAt(l+1)===10&&l++,s=l+1)}let o={name:n,buffer:t,position:e,line:r,column:e-s};throw o.snippet=Z2(o),new MS(i,o)}var D2=-1;function wS(t){switch(t){case 48:return"\0";case 97:return"\x07";case 98:return"\b";case 116:return" ";case 9:return" ";case 110:return`
|
||||||
`;case 118:return"\v";case 102:return"\f";case 114:return"\r";case 101:return"\x1B";case 32:return" ";case 34:return'"';case 47:return"/";case 92:return"\\";case 78:return"\x85";case 95:return"\xA0";case 76:return"\u2028";case 80:return"\u2029";default:return""}}var AS=new Array(256),RS=new Array(256);for(let t=0;t<256;t++)AS[t]=yS(t)?1:0,RS[t]=yS(t);function Z2(t){return t<=65535?String.fromCharCode(t):String.fromCharCode((t-65536>>10)+55296,(t-65536&1023)+56320)}function D2(t){return t>=48&&t<=57?t-48:(t|32)-97+10}function I2(t){return t===120?2:t===117?4:8}function Sa(t,e,i){let n=0;for(;e<i;){let r=t.charCodeAt(e);if(r===10)n++,e++;else if(r===13)n++,e++,t.charCodeAt(e)===10&&e++;else if(r===32||r===9)e++;else break}return{position:e,breaks:n}}function Wd(t){return t===1?" ":`
|
`;case 118:return"\v";case 102:return"\f";case 114:return"\r";case 101:return"\x1B";case 32:return" ";case 34:return'"';case 47:return"/";case 92:return"\\";case 78:return"\x85";case 95:return"\xA0";case 76:return"\u2028";case 80:return"\u2029";default:return""}}var LS=new Array(256),XS=new Array(256);for(let t=0;t<256;t++)LS[t]=wS(t)?1:0,XS[t]=wS(t);function I2(t){return t<=65535?String.fromCharCode(t):String.fromCharCode((t-65536>>10)+55296,(t-65536&1023)+56320)}function B2(t){return t>=48&&t<=57?t-48:(t|32)-97+10}function N2(t){return t===120?2:t===117?4:8}function wa(t,e,i){let n=0;for(;e<i;){let r=t.charCodeAt(e);if(r===10)n++,e++;else if(r===13)n++,e++,t.charCodeAt(e)===10&&e++;else if(r===32||r===9)e++;else break}return{position:e,breaks:n}}function Ud(t){return t===1?" ":`
|
||||||
`.repeat(t-1)}function B2(t,e,i){let n="",r=e,s=e,o=e;for(;r<i;){let l=t.charCodeAt(r);if(l===10||l===13){n+=t.slice(s,o);let a=Sa(t,r,i);n+=Wd(a.breaks),r=s=o=a.position}else r++,l!==32&&l!==9&&(o=r)}return n+t.slice(s,o)}function N2(t,e,i){let n="",r=e,s=e,o=e;for(;r<i;){let l=t.charCodeAt(r);if(l===39)n+=t.slice(s,r)+"'",r+=2,s=o=r;else if(l===10||l===13){n+=t.slice(s,o);let a=Sa(t,r,i);n+=Wd(a.breaks),r=s=o=a.position}else r++,l!==32&&l!==9&&(o=r)}return n+t.slice(s,i)}function j2(t,e,i){let n="",r=e,s=e,o=e;for(;r<i;){let l=t.charCodeAt(r);if(l===92){n+=t.slice(s,r),r++;let a=t.charCodeAt(r);if(a===10||a===13)r=Sa(t,r,i).position;else if(a<256&&AS[a])n+=RS[a],r++;else{let h=I2(a),c=0;for(;h>0;h--){r++;let f=D2(t.charCodeAt(r));c=(c<<4)+f}n+=Z2(c),r++}s=o=r}else if(l===10||l===13){n+=t.slice(s,o);let a=Sa(t,r,i);n+=Wd(a.breaks),r=s=o=a.position}else r++,l!==32&&l!==9&&(o=r)}return n+t.slice(s,i)}function SS(t,e,i,n,r,s){let o=n<0?0:n,l=t.slice(e,i).replace(/\r\n?/g,`
|
`.repeat(t-1)}function j2(t,e,i){let n="",r=e,s=e,o=e;for(;r<i;){let l=t.charCodeAt(r);if(l===10||l===13){n+=t.slice(s,o);let a=wa(t,r,i);n+=Ud(a.breaks),r=s=o=a.position}else r++,l!==32&&l!==9&&(o=r)}return n+t.slice(s,o)}function z2(t,e,i){let n="",r=e,s=e,o=e;for(;r<i;){let l=t.charCodeAt(r);if(l===39)n+=t.slice(s,r)+"'",r+=2,s=o=r;else if(l===10||l===13){n+=t.slice(s,o);let a=wa(t,r,i);n+=Ud(a.breaks),r=s=o=a.position}else r++,l!==32&&l!==9&&(o=r)}return n+t.slice(s,i)}function Y2(t,e,i){let n="",r=e,s=e,o=e;for(;r<i;){let l=t.charCodeAt(r);if(l===92){n+=t.slice(s,r),r++;let a=t.charCodeAt(r);if(a===10||a===13)r=wa(t,r,i).position;else if(a<256&&LS[a])n+=XS[a],r++;else{let h=N2(a),c=0;for(;h>0;h--){r++;let f=B2(t.charCodeAt(r));c=(c<<4)+f}n+=I2(c),r++}s=o=r}else if(l===10||l===13){n+=t.slice(s,o);let a=wa(t,r,i);n+=Ud(a.breaks),r=s=o=a.position}else r++,l!==32&&l!==9&&(o=r)}return n+t.slice(s,i)}function vS(t,e,i,n,r,s){let o=n<0?0:n,l=t.slice(e,i).replace(/\r\n?/g,`
|
||||||
`),a=l===""?[]:(l.endsWith(`
|
`),a=l===""?[]:(l.endsWith(`
|
||||||
`)?l.slice(0,-1):l).split(`
|
`)?l.slice(0,-1):l).split(`
|
||||||
`),h="",c=!1,f=0,u=!1;for(let d of a){let p=0;for(;p<o&&d.charCodeAt(p)===32;)p++;if(n<0||p>=d.length){f++;continue}let g=d.slice(o),m=g.charCodeAt(0);s?m===32||m===9?(u=!0,h+=`
|
`),h="",c=!1,f=0,u=!1;for(let d of a){let p=0;for(;p<o&&d.charCodeAt(p)===32;)p++;if(n<0||p>=d.length){f++;continue}let g=d.slice(o),m=g.charCodeAt(0);s?m===32||m===9?(u=!0,h+=`
|
||||||
@@ -46,13 +46,13 @@ ${t.mark.snippet}`),`${t.reason} ${i}`):t.reason}var CS=class extends Error{cons
|
|||||||
`.repeat(f):h+=`
|
`.repeat(f):h+=`
|
||||||
`.repeat(c?1+f:f),h+=g,c=!0,f=0}return r===3?h+=`
|
`.repeat(c?1+f:f),h+=g,c=!0,f=0}return r===3?h+=`
|
||||||
`.repeat(c?1+f:f):r!==2&&c&&(h+=`
|
`.repeat(c?1+f:f):r!==2&&c&&(h+=`
|
||||||
`),h}function z2(t,e){if(e.valueStart===_2)return"";let{valueStart:i,valueEnd:n}=e;if(e.fast)return t.slice(i,n);switch(e.style){case 2:return N2(t,i,n);case 3:return j2(t,i,n);case 4:return SS(t,i,n,e.indent,e.chomping,!1);case 5:return SS(t,i,n,e.indent,e.chomping,!0);default:return B2(t,i,n)}}var Y2={"!":"!","!!":"tag:yaml.org,2002:"};function ES(t,e){var s,o;if(t.startsWith("!<")&&t.endsWith(">"))return decodeURIComponent(t.slice(2,-1));let i=t.indexOf("!",1),n=i===-1?"!":t.slice(0,i+1),r=(o=(s=e==null?void 0:e[n])!=null?s:Y2[n])!=null?o:n;return decodeURIComponent(r)+decodeURIComponent(t.slice(n.length))}var Zr=-1,Vd={filename:"",schema:M2,json:!1,maxTotalMergeKeys:1e4,maxAliases:-1};function q2(t){return"tagStart"in t&&t.tagStart!==Zr?t.tagStart:"anchorStart"in t&&t.anchorStart!==Zr?t.anchorStart:"valueStart"in t&&t.valueStart!==Zr?t.valueStart:"start"in t?t.start:0}function St(t,e){Pa(t.source,t.position,e,t.filename)}function MS(t,e,i,n){try{return i.finalize(n)}catch(r){if(r instanceof CS)throw r;Pa(t.source,e,r instanceof Error?r.message:String(r),t.filename)}}function ya(t,e,i){let n=t[i];if(n)return n;for(let r of e)if(i.startsWith(r.tagName))return r}function W2(t,e,i,n,r){let s=ya(e,i,n);if(s)return s;St(t,`unknown ${r} tag !<${n}>`)}function V2(t,e){var s,o;let i=z2(t.source,e),n=e.tagStart===Zr?"":t.source.slice(e.tagStart,e.tagEnd),r=t.schema.defaultScalarTag;if(n!==""){if(n==="!")return{value:i,tag:r};let l=ES(n,t.tagHandlers),a=ya(t.schema.exact.scalar,t.schema.prefix.scalar,l);if(a){let c=a.resolve(i,!0,l);return c===ae&&St(t,`cannot resolve a node with !<${l}> explicit tag`),{value:c,tag:a}}let h=(s=ya(t.schema.exact.mapping,t.schema.prefix.mapping,l))!=null?s:ya(t.schema.exact.sequence,t.schema.prefix.sequence,l);if(h){i!==""&&St(t,`cannot resolve a node with !<${l}> explicit tag`);let c=h.create(l);return{value:h.carrierIsResult?c:MS(t,t.position,h,c),tag:h}}St(t,`unknown scalar tag !<${l}>`)}if(e.style===1){let l=(o=t.schema.implicitScalarByFirstChar.get(i.charAt(0)))!=null?o:t.schema.implicitScalarAnyFirstChar;for(let a of l){let h=a.resolve(i,!1,a.tagName);if(h!==ae)return{value:h,tag:a}}}return{value:r.resolve(i,!1,r.tagName),tag:r}}function xS(t,e,i,n,r,s){let o=e.tagStart===Zr?"":t.source.slice(e.tagStart,e.tagEnd),l=o===""||o==="!"?r:ES(o,t.tagHandlers);return{tagName:l,tag:W2(t,i,n,l,s)}}function LS(t){return t.nodeKind==="mapping"}function kS(t,e,i,n){var r;for(let s of n.keys(i)){if(t.maxTotalMergeKeys!==-1&&++t.totalMergeKeys>t.maxTotalMergeKeys&&St(t,`merge keys exceeded maxTotalMergeKeys (${t.maxTotalMergeKeys})`),e.tag.has(e.value,s))continue;let o=e.tag.addPair(e.value,s,n.get(i,s));o&&St(t,o),((r=e.overridable)!=null?r:e.overridable=new Set).add(s)}}function G2(t,e,i,n){if(t.position=e.keyPosition,LS(n))kS(t,e,i,n);else if(n.nodeKind==="sequence"&&Array.isArray(i))for(let r of i)kS(t,e,r,e.tag);else St(t,"cannot merge mappings; the provided source object is unacceptable")}function U2(t,e,i,n,r){var o,l;if(t.position=e.keyPosition,i===jd){G2(t,e,n,r);return}!t.json&&e.tag.has(e.value,i)&&!((o=e.overridable)!=null&&o.has(i))&&St(t,"duplicated mapping key");let s=e.tag.addPair(e.value,i,n);s&&St(t,s),(l=e.overridable)==null||l.delete(i)}function Ld(t,e,i){let n=t.frames[t.frames.length-1];if(n.kind==="document")n.value=e,n.hasValue=!0;else if(n.kind==="sequence"){n.merge&&(LS(i)||St(t,"cannot merge mappings; the provided source object is unacceptable"));let r=n.tag.addItem(n.value,e,n.index++);r&&St(t,r)}else if(n.hasKey){let r=n.key;n.key=void 0,n.hasKey=!1,U2(t,n,r,e,i)}else n.key=e,n.keyPosition=t.position,n.hasKey=!0}function Xd(t,e,i,n,r){if(e.anchorStart!==Zr){let s={value:i,tag:n,isValueFinal:r};return t.anchors.set(t.source.slice(e.anchorStart,e.anchorEnd),s),s}return null}function F2(t,e){let i={...Vd,...e,events:t,documents:[],eventIndex:0,position:0,frames:[],anchors:new Map,tagHandlers:Object.create(null),totalMergeKeys:0,aliasCount:0};for(;i.eventIndex<i.events.length;){let n=i.events[i.eventIndex++];switch(i.position=q2(n),n.type){case 1:i.anchors=new Map,i.aliasCount=0,i.tagHandlers=Object.create(null);for(let r of n.directives)r.kind==="tag"&&(i.tagHandlers[r.handle]=r.prefix);i.frames.push({kind:"document",position:i.position,value:void 0,hasValue:!1});break;case 4:{let{value:r,tag:s}=V2(i,n);Xd(i,n,r,s,!0),Ld(i,r,s);break}case 2:{let r=xS(i,n,i.schema.exact.sequence,i.schema.prefix.sequence,"tag:yaml.org,2002:seq","sequence"),s=r.tag.create(r.tagName),o=Xd(i,n,s,r.tag,r.tag.carrierIsResult),l=i.frames[i.frames.length-1],a=l!==void 0&&l.kind==="mapping"&&l.hasKey&&l.key===jd;i.frames.push({kind:"sequence",position:i.position,value:s,tag:r.tag,anchor:o,index:0,merge:a});break}case 3:{let r=xS(i,n,i.schema.exact.mapping,i.schema.prefix.mapping,"tag:yaml.org,2002:map","mapping"),s=r.tag.create(r.tagName),o=Xd(i,n,s,r.tag,r.tag.carrierIsResult);i.frames.push({kind:"mapping",position:i.position,value:s,tag:r.tag,anchor:o,key:void 0,keyPosition:i.position,hasK
Line truncated
|
`),h}function q2(t,e){if(e.valueStart===D2)return"";let{valueStart:i,valueEnd:n}=e;if(e.fast)return t.slice(i,n);switch(e.style){case 2:return z2(t,i,n);case 3:return Y2(t,i,n);case 4:return vS(t,i,n,e.indent,e.chomping,!1);case 5:return vS(t,i,n,e.indent,e.chomping,!0);default:return j2(t,i,n)}}var W2={"!":"!","!!":"tag:yaml.org,2002:"};function _S(t,e){var s,o;if(t.startsWith("!<")&&t.endsWith(">"))return decodeURIComponent(t.slice(2,-1));let i=t.indexOf("!",1),n=i===-1?"!":t.slice(0,i+1),r=(o=(s=e==null?void 0:e[n])!=null?s:W2[n])!=null?o:n;return decodeURIComponent(r)+decodeURIComponent(t.slice(n.length))}var _r=-1,Fd={filename:"",schema:X2,json:!1,maxTotalMergeKeys:1e4,maxAliases:-1};function V2(t){return"tagStart"in t&&t.tagStart!==_r?t.tagStart:"anchorStart"in t&&t.anchorStart!==_r?t.anchorStart:"valueStart"in t&&t.valueStart!==_r?t.valueStart:"start"in t?t.start:0}function xt(t,e){Ca(t.source,t.position,e,t.filename)}function ZS(t,e,i,n){try{return i.finalize(n)}catch(r){if(r instanceof MS)throw r;Ca(t.source,e,r instanceof Error?r.message:String(r),t.filename)}}function ka(t,e,i){let n=t[i];if(n)return n;for(let r of e)if(i.startsWith(r.tagName))return r}function G2(t,e,i,n,r){let s=ka(e,i,n);if(s)return s;xt(t,`unknown ${r} tag !<${n}>`)}function U2(t,e){var s,o;let i=q2(t.source,e),n=e.tagStart===_r?"":t.source.slice(e.tagStart,e.tagEnd),r=t.schema.defaultScalarTag;if(n!==""){if(n==="!")return{value:i,tag:r};let l=_S(n,t.tagHandlers),a=ka(t.schema.exact.scalar,t.schema.prefix.scalar,l);if(a){let c=a.resolve(i,!0,l);return c===ae&&xt(t,`cannot resolve a node with !<${l}> explicit tag`),{value:c,tag:a}}let h=(s=ka(t.schema.exact.mapping,t.schema.prefix.mapping,l))!=null?s:ka(t.schema.exact.sequence,t.schema.prefix.sequence,l);if(h){i!==""&&xt(t,`cannot resolve a node with !<${l}> explicit tag`);let c=h.create(l);return{value:h.carrierIsResult?c:ZS(t,t.position,h,c),tag:h}}xt(t,`unknown scalar tag !<${l}>`)}if(e.style===1){let l=(o=t.schema.implicitScalarByFirstChar.get(i.charAt(0)))!=null?o:t.schema.implicitScalarAnyFirstChar;for(let a of l){let h=a.resolve(i,!1,a.tagName);if(h!==ae)return{value:h,tag:a}}}return{value:r.resolve(i,!1,r.tagName),tag:r}}function QS(t,e,i,n,r,s){let o=e.tagStart===_r?"":t.source.slice(e.tagStart,e.tagEnd),l=o===""||o==="!"?r:_S(o,t.tagHandlers);return{tagName:l,tag:G2(t,i,n,l,s)}}function DS(t){return t.nodeKind==="mapping"}function PS(t,e,i,n){var r;for(let s of n.keys(i)){if(t.maxTotalMergeKeys!==-1&&++t.totalMergeKeys>t.maxTotalMergeKeys&&xt(t,`merge keys exceeded maxTotalMergeKeys (${t.maxTotalMergeKeys})`),e.tag.has(e.value,s))continue;let o=e.tag.addPair(e.value,s,n.get(i,s));o&&xt(t,o),((r=e.overridable)!=null?r:e.overridable=new Set).add(s)}}function F2(t,e,i,n){if(t.position=e.keyPosition,DS(n))PS(t,e,i,n);else if(n.nodeKind==="sequence"&&Array.isArray(i))for(let r of i)PS(t,e,r,e.tag);else xt(t,"cannot merge mappings; the provided source object is unacceptable")}function H2(t,e,i,n,r){var o,l;if(t.position=e.keyPosition,i===qd){F2(t,e,n,r);return}!t.json&&e.tag.has(e.value,i)&&!((o=e.overridable)!=null&&o.has(i))&&xt(t,"duplicated mapping key");let s=e.tag.addPair(e.value,i,n);s&&xt(t,s),(l=e.overridable)==null||l.delete(i)}function Zd(t,e,i){let n=t.frames[t.frames.length-1];if(n.kind==="document")n.value=e,n.hasValue=!0;else if(n.kind==="sequence"){n.merge&&(DS(i)||xt(t,"cannot merge mappings; the provided source object is unacceptable"));let r=n.tag.addItem(n.value,e,n.index++);r&&xt(t,r)}else if(n.hasKey){let r=n.key;n.key=void 0,n.hasKey=!1,H2(t,n,r,e,i)}else n.key=e,n.keyPosition=t.position,n.hasKey=!0}function Dd(t,e,i,n,r){if(e.anchorStart!==_r){let s={value:i,tag:n,isValueFinal:r};return t.anchors.set(t.source.slice(e.anchorStart,e.anchorEnd),s),s}return null}function K2(t,e){let i={...Fd,...e,events:t,documents:[],eventIndex:0,position:0,frames:[],anchors:new Map,tagHandlers:Object.create(null),totalMergeKeys:0,aliasCount:0};for(;i.eventIndex<i.events.length;){let n=i.events[i.eventIndex++];switch(i.position=V2(n),n.type){case 1:i.anchors=new Map,i.aliasCount=0,i.tagHandlers=Object.create(null);for(let r of n.directives)r.kind==="tag"&&(i.tagHandlers[r.handle]=r.prefix);i.frames.push({kind:"document",position:i.position,value:void 0,hasValue:!1});break;case 4:{let{value:r,tag:s}=U2(i,n);Dd(i,n,r,s,!0),Zd(i,r,s);break}case 2:{let r=QS(i,n,i.schema.exact.sequence,i.schema.prefix.sequence,"tag:yaml.org,2002:seq","sequence"),s=r.tag.create(r.tagName),o=Dd(i,n,s,r.tag,r.tag.carrierIsResult),l=i.frames[i.frames.length-1],a=l!==void 0&&l.kind==="mapping"&&l.hasKey&&l.key===qd;i.frames.push({kind:"sequence",position:i.position,value:s,tag:r.tag,anchor:o,index:0,merge:a});break}case 3:{let r=QS(i,n,i.schema.exact.mapping,i.schema.prefix.mapping,"tag:yaml.org,2002:map","mapping"),s=r.tag.create(r.tagName),o=Dd(i,n,s,r.tag,r.tag.carrierIsResult);i.frames.push({kind:"mapping",position:i.position,value:s,tag:r.tag,anchor:o,key:void 0,keyPosition:i.position,hasK
Line truncated
|
||||||
`:n=="r"?"\r":n=="t"?" ":"\\")}eq(e){return this.search==e.search&&this.replace==e.replace&&this.caseSensitive==e.caseSensitive&&this.regexp==e.regexp&&this.wholeWord==e.wholeWord}create(){return this.regexp?new Kd(this):new Hd(this)}getCursor(e,i=0,n){let r=e.doc?e:ce.create({doc:e});return n==null&&(n=r.doc.length),this.regexp?Nr(this,r,i,n):Br(this,r,i,n)}},Xa=class{constructor(e){this.spec=e}};function Br(t,e,i,n){return new tn(e.doc,t.unquoted,i,n,t.caseSensitive?void 0:r=>r.toLowerCase(),t.wholeWord?_E(e.doc,e.charCategorizer(e.selection.main.head)):void 0)}function _E(t,e){return(i,n,r,s)=>((s>i||s+r.length<n)&&(s=Math.max(0,i-2),r=t.sliceString(s,Math.min(t.length,n+2))),(e(_a(r,i-s))!=xe.Word||e(Za(r,i-s))!=xe.Word)&&(e(Za(r,n-s))!=xe.Word||e(_a(r,n-s))!=xe.Word))}var Hd=class extends Xa{constructor(e){super(e)}nextMatch(e,i,n){let r=Br(this.spec,e,n,e.doc.length).nextOverlapping();if(r.done){let s=Math.min(e.doc.length,i+this.spec.unquoted.length);r=Br(this.spec,e,0,s).nextOverlapping()}return r.done||r.value.from==i&&r.value.to==n?null:r.value}prevMatchInRange(e,i,n){for(let r=n;;){let s=Math.max(i,r-1e4-this.spec.unquoted.length),o=Br(this.spec,e,s,r),l=null;for(;!o.nextOverlapping().done;)l=o.value;if(l)return l;if(s==i)return null;r-=1e4}}prevMatch(e,i,n){let r=this.prevMatchInRange(e,0,i);return r||(r=this.prevMatchInRange(e,Math.max(0,n-this.spec.unquoted.length),e.doc.length)),r&&(r.from!=i||r.to!=n)?r:null}getReplacement(e){return this.spec.unquote(this.spec.replace)}matchAll(e,i){let n=Br(this.spec,e,0,e.doc.length),r=[];for(;!n.next().done;){if(r.length>=i)return null;r.push(n.value)}return r}highlight(e,i,n,r){let s=Br(this.spec,e,Math.max(0,i-this.spec.unquoted.length),Math.min(n+this.spec.unquoted.length,e.doc.length));for(;!s.next().done;)r(s.value.from,s.value.to)}};function Nr(t,e,i,n){return new Ca(e.doc,t.search,{ignoreCase:!t.caseSensitive,test:t.wholeWord?ZE(e.charCategorizer(e.selection.main.head)):void 0},i,n)}function _a(t,e){return t.slice(Xe(t,e,!1),e)}function Za(t,e){return t.slice(e,Xe(t,e))}function ZE(t){return(e,i,n)=>!n[0].length||(t(_a(n.input,n.index))!=xe.Word||t(Za(n.input,n.index))!=xe.Word)&&(t(Za(n.input,n.index+n[0].length))!=xe.Word||t(_a(n.input,n.index+n[0].length))!=xe.Word)}var Kd=class extends Xa{nextMatch(e,i,n){let r=Nr(this.spec,e,n,e.doc.length).next();return r.done&&(r=Nr(this.spec,e,0,i).next()),r.done?null:r.value}prevMatchInRange(e,i,n){for(let r=1;;r++){let s=Math.max(i,n-r*1e4),o=Nr(this.spec,e,s,n),l=null;for(;!o.next().done;)l=o.value;if(l&&(s==i||l.from>s+10))return l;if(s==i)return null}}prevMatch(e,i,n){return this.prevMatchInRange(e,0,i)||this.prevMatchInRange(e,n,e.doc.length)}getReplacement(e){return this.spec.unquote(this.spec.replace).replace(/\$([$&\d+])/g,(i,n)=>n=="$"?"$":n=="&"?e.match[0]:n!="0"&&+n<e.match.length?e.match[n]:i)}matchAll(e,i){let n=Nr(this.spec,e,0,e.doc.length),r=[];for(;!n.next().done;){if(r.length>=i)return null;r.push(n.value)}return r}highlight(e,i,n,r){let s=Nr(this.spec,e,Math.max(0,i-250),Math.min(n+250,e.doc.length));for(;!s.next().done;)r(s.value.from,s.value.to)}},fo=q.define(),sp=q.define(),en=pe.define({create(t){return new ho(Jd(t).create(),null)},update(t,e){for(let i of e.effects)i.is(fo)?t=new ho(i.value.create(),t.panel):i.is(sp)&&(t=new ho(t.query,i.value?op:null));return t},provide:t=>mn.from(t,e=>e.panel)});var ho=class{constructor(e,i){this.query=e,this.panel=i}},DE=E.mark({class:"cm-searchMatch"}),IE=E.mark({class:"cm-searchMatch cm-searchMatch-selected"}),BE=Se.fromClass(class{constructor(t){this.view=t,this.decorations=this.highlight(t.state.field(en))}update(t){let e=t.state.field(en);(e!=t.startState.field(en)||t.docChanged||t.selectionSet||t.viewportChanged)&&(this.decorations=this.highlight(e))}highlight({query:t,panel:e}){if(!e||!t.spec.valid)return E.none;let{view:i}=this,n=new Ee;for(let r=0,s=i.visibleRanges,o=s.length;r<o;r++){let{from:l,to:a}=s[r];for(;r<o-1&&a>s[r+1].from-500;)a=s[++r].to;t.highlight(i.state,l,a,(h,c)=>{let f=i.state.selection.ranges.some(u=>u.from==h&&u.to==c);n.add(h,c,f?IE:DE)})}return n.finish()}},{decorations:t=>t.decorations});function uo(t){return e=>{let i=e.state.field(en,!1);return i&&i.query.spec.valid?t(e,i):FS(e)}}var Da=uo((t,{query:e})=>{let{to:i}=t.state.selection.main,n=e.nextMatch(t.state,i,i);if(!n)return!1;let r=v.single(n.from,n.to),s=t.state.facet(Zn);return t.dispatch({selection:r,effects:[ap(t,n),s.scrollToMatch(r.main,t)],userEvent:"select.search"}),US(t),!0}),Ia=uo((t,{query:e})=>{let{state:i}=t,{from:n}=i.selection.main,r=e.prevMatch(i,n,n);if(!r)return!1;let s=v.single(r.from,r.to),o=t.state.facet(Zn);return t.dispatch({selection:s,effects:[ap(t,r),o.scrollToMatch(s.main,t)],userEvent:"select.search"}),US(t),!0}),NE=uo((t,{query:e})=>{let i=e.matchAll(t.state,1e3);return!i||!i.length?!1:(t.dispatch({selection:v.create(i.map(n=>v.range(n.from,n.to))),userEvent:"select.search.matches"}),!0)}),jE=({state:t,dispatch:e})=>{let i=t.select
Line truncated
|
`:n=="r"?"\r":n=="t"?" ":"\\")}eq(e){return this.search==e.search&&this.replace==e.replace&&this.caseSensitive==e.caseSensitive&&this.regexp==e.regexp&&this.wholeWord==e.wholeWord}create(){return this.regexp?new tp(this):new ep(this)}getCursor(e,i=0,n){let r=e.doc?e:he.create({doc:e});return n==null&&(n=r.doc.length),this.regexp?Br(this,r,i,n):Ir(this,r,i,n)}},Da=class{constructor(e){this.spec=e}};function Ir(t,e,i,n){return new tn(e.doc,t.unquoted,i,n,t.caseSensitive?void 0:r=>r.toLowerCase(),t.wholeWord?DE(e.doc,e.charCategorizer(e.selection.main.head)):void 0)}function DE(t,e){return(i,n,r,s)=>((s>i||s+r.length<n)&&(s=Math.max(0,i-2),r=t.sliceString(s,Math.min(t.length,n+2))),(e(Ia(r,i-s))!=ke.Word||e(Ba(r,i-s))!=ke.Word)&&(e(Ba(r,n-s))!=ke.Word||e(Ia(r,n-s))!=ke.Word))}var ep=class extends Da{constructor(e){super(e)}nextMatch(e,i,n){let r=Ir(this.spec,e,n,e.doc.length).nextOverlapping();if(r.done){let s=Math.min(e.doc.length,i+this.spec.unquoted.length);r=Ir(this.spec,e,0,s).nextOverlapping()}return r.done||r.value.from==i&&r.value.to==n?null:r.value}prevMatchInRange(e,i,n){for(let r=n;;){let s=Math.max(i,r-1e4-this.spec.unquoted.length),o=Ir(this.spec,e,s,r),l=null;for(;!o.nextOverlapping().done;)l=o.value;if(l)return l;if(s==i)return null;r-=1e4}}prevMatch(e,i,n){let r=this.prevMatchInRange(e,0,i);return r||(r=this.prevMatchInRange(e,Math.max(0,n-this.spec.unquoted.length),e.doc.length)),r&&(r.from!=i||r.to!=n)?r:null}getReplacement(e){return this.spec.unquote(this.spec.replace)}matchAll(e,i){let n=Ir(this.spec,e,0,e.doc.length),r=[];for(;!n.next().done;){if(r.length>=i)return null;r.push(n.value)}return r}highlight(e,i,n,r){let s=Ir(this.spec,e,Math.max(0,i-this.spec.unquoted.length),Math.min(n+this.spec.unquoted.length,e.doc.length));for(;!s.next().done;)r(s.value.from,s.value.to)}};function Br(t,e,i,n){return new Ea(e.doc,t.search,{ignoreCase:!t.caseSensitive,test:t.wholeWord?IE(e.charCategorizer(e.selection.main.head)):void 0},i,n)}function Ia(t,e){return t.slice(Xe(t,e,!1),e)}function Ba(t,e){return t.slice(e,Xe(t,e))}function IE(t){return(e,i,n)=>!n[0].length||(t(Ia(n.input,n.index))!=ke.Word||t(Ba(n.input,n.index))!=ke.Word)&&(t(Ba(n.input,n.index+n[0].length))!=ke.Word||t(Ia(n.input,n.index+n[0].length))!=ke.Word)}var tp=class extends Da{nextMatch(e,i,n){let r=Br(this.spec,e,n,e.doc.length).next();return r.done&&(r=Br(this.spec,e,0,i).next()),r.done?null:r.value}prevMatchInRange(e,i,n){for(let r=1;;r++){let s=Math.max(i,n-r*1e4),o=Br(this.spec,e,s,n),l=null;for(;!o.next().done;)l=o.value;if(l&&(s==i||l.from>s+10))return l;if(s==i)return null}}prevMatch(e,i,n){return this.prevMatchInRange(e,0,i)||this.prevMatchInRange(e,n,e.doc.length)}getReplacement(e){return this.spec.unquote(this.spec.replace).replace(/\$([$&\d+])/g,(i,n)=>n=="$"?"$":n=="&"?e.match[0]:n!="0"&&+n<e.match.length?e.match[n]:i)}matchAll(e,i){let n=Br(this.spec,e,0,e.doc.length),r=[];for(;!n.next().done;){if(r.length>=i)return null;r.push(n.value)}return r}highlight(e,i,n,r){let s=Br(this.spec,e,Math.max(0,i-250),Math.min(n+250,e.doc.length));for(;!s.next().done;)r(s.value.from,s.value.to)}},uo=W.define(),ap=W.define(),en=ge.define({create(t){return new fo(ip(t).create(),null)},update(t,e){for(let i of e.effects)i.is(uo)?t=new fo(i.value.create(),t.panel):i.is(ap)&&(t=new fo(t.query,i.value?cp:null));return t},provide:t=>mn.from(t,e=>e.panel)});var fo=class{constructor(e,i){this.query=e,this.panel=i}},BE=X.mark({class:"cm-searchMatch"}),NE=X.mark({class:"cm-searchMatch cm-searchMatch-selected"}),jE=me.fromClass(class{constructor(t){this.view=t,this.decorations=this.highlight(t.state.field(en))}update(t){let e=t.state.field(en);(e!=t.startState.field(en)||t.docChanged||t.selectionSet||t.viewportChanged)&&(this.decorations=this.highlight(e))}highlight({query:t,panel:e}){if(!e||!t.spec.valid)return X.none;let{view:i}=this,n=new Ee;for(let r=0,s=i.visibleRanges,o=s.length;r<o;r++){let{from:l,to:a}=s[r];for(;r<o-1&&a>s[r+1].from-500;)a=s[++r].to;t.highlight(i.state,l,a,(h,c)=>{let f=i.state.selection.ranges.some(u=>u.from==h&&u.to==c);n.add(h,c,f?NE:BE)})}return n.finish()}},{decorations:t=>t.decorations});function po(t){return e=>{let i=e.state.field(en,!1);return i&&i.query.spec.valid?t(e,i):ex(e)}}var Na=po((t,{query:e})=>{let{to:i}=t.state.selection.main,n=e.nextMatch(t.state,i,i);if(!n)return!1;let r=Q.single(n.from,n.to),s=t.state.facet(_n);return t.dispatch({selection:r,effects:[fp(t,n),s.scrollToMatch(r.main,t)],userEvent:"select.search"}),JS(t),!0}),ja=po((t,{query:e})=>{let{state:i}=t,{from:n}=i.selection.main,r=e.prevMatch(i,n,n);if(!r)return!1;let s=Q.single(r.from,r.to),o=t.state.facet(_n);return t.dispatch({selection:s,effects:[fp(t,r),o.scrollToMatch(s.main,t)],userEvent:"select.search"}),JS(t),!0}),zE=po((t,{query:e})=>{let i=e.matchAll(t.state,1e3);return!i||!i.length?!1:(t.dispatch({selection:Q.create(i.map(n=>Q.range(n.from,n.to))),userEvent:"select.search.matches"}),!0)}),YE=({state:t,dispatch:e})=>{let i=t.select
Line truncated
|
||||||
]`).replace("lheading",Gx).replace("|table","").replace("blockquote"," {0,3}>").replace("|fences","").replace("|list","").replace("|html","").replace("|tag","").getRegex()},qM=/^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/,WM=/^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,Fx=/^( {2,}|\\)\n(?!\s*$)/,VM=/^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\<!\[`*_]|\b_|$)|[^ ](?= {2,}\n)))/,Hr=/[\p{P}\p{S}]/u,nc=/[\s\p{P}\p{S}]/u,Hp=/[^\s\p{P}\p{S}]/u,GM=oe(/^((?![*_])punctSpace)/,"u").replace(/punctSpace/g,nc).getRegex(),Hx=/(?!~)[\p{P}\p{S}]/u,UM=/(?!~)[\s\p{P}\p{S}]/u,FM=/(?:[^\s\p{P}\p{S}]|~)/u,HM=oe(/link|precode-code|html/,"g").replace("link",/\[(?:[^\[\]`]|(?<a>`+)[^`]+\k<a>(?!`))*?\]\((?:\\[\s\S]|[^\\\(\)]|\((?:\\[\s\S]|[^\\\(\)])*\))*\)/).replace("precode-",EM?"(?<!`)()":"(^^|[^`])").replace("code",/(?<b>`+)[^`]+\k<b>(?!`)/).replace("html",/<(?! )[^<>]*?>/).getRegex(),Kx=/^(?:\*+(?:((?!\*)punct)|([^\s*]))?)|^_+(?:((?!_)punct)|([^\s_]))?/,KM=oe(Kx,"u").replace(/punct/g,Hr).getRegex(),JM=oe(Kx,"u").replace(/punct/g,Hx).getRegex(),Jx="^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\*)punct(\\*+)(?=[\\s]|$)|notPunctSpace(\\*+)(?!\\*)(?=punctSpace|$)|(?!\\*)punctSpace(\\*+)(?=notPunctSpace)|[\\s](\\*+)(?!\\*)(?=punct)|(?!\\*)punct(\\*+)(?!\\*)(?=punct)|notPunctSpace(\\*+)(?=notPunctSpace)",eL=oe(Jx,"gu").replace(/notPunctSpace/g,Hp).replace(/punctSpace/g,nc).replace(/punct/g,Hr).getRegex(),tL=oe(Jx,"gu").replace(/notPunctSpace/g,FM).replace(/punctSpace/g,UM).replace(/punct/g,Hx).getRegex(),iL=oe("^[^_*]*?\\*\\*[^_*]*?_[^_*]*?(?=\\*\\*)|[^_]+(?=[^_])|(?!_)punct(_+)(?=[\\s]|$)|notPunctSpace(_+)(?!_)(?=punctSpace|$)|(?!_)punctSpace(_+)(?=notPunctSpace)|[\\s](_+)(?!_)(?=punct)|(?!_)punct(_+)(?!_)(?=punct)","gu").replace(/notPunctSpace/g,Hp).replace(/punctSpace/g,nc).replace(/punct/g,Hr).getRegex(),nL=oe(/^~~?(?:((?!~)punct)|[^\s~])/,"u").replace(/punct/g,Hr).getRegex(),rL="^[^~]+(?=[^~])|(?!~)punct(~~?)(?=[\\s]|$)|notPunctSpace(~~?)(?!~)(?=punctSpace|$)|(?!~)punctSpace(~~?)(?=notPunctSpace)|[\\s](~~?)(?!~)(?=punct)|(?!~)punct(~~?)(?!~)(?=punct)|notPunctSpace(~~?)(?=notPunctSpace)",sL=oe(rL,"gu").replace(/notPunctSpace/g,Hp).replace(/punctSpace/g,nc).replace(/punct/g,Hr).getRegex(),oL=oe(/\\(punct)/,"gu").replace(/punct/g,Hr).getRegex(),lL=oe(/^<(scheme:[^\s\x00-\x1f<>]*|email)>/).replace("scheme",/[a-zA-Z][a-zA-Z0-9+.-]{1,31}/).replace("email",/[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/).getRegex(),aL=oe(Up).replace("(?:-->|$)","-->").getRegex(),cL=oe("^comment|^</[a-zA-Z][\\w:-]*\\s*>|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^<![a-zA-Z]+\\s[\\s\\S]*?>|^<!\\[CDATA\\[[\\s\\S]*?\\]\\]>").replace("comment",aL).replace("attribute",/\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/).getRegex(),Ja=/(?:\[(?:\\[\s\S]|[^\[\]\\])*\]|\\[\s\S]|`+(?!`)[^`]*?`+(?!`)|``+(?=\])|[^\[\]\\`])*?/,hL=oe(/^!?\[(label)\]\(\s*(href)(?:(?:[ \t]+(?:\n[ \t]*)?|\n[ \t]*)(title))?\s*\)/).replace("label",Ja).replace("href",/<(?:\\.|[^\n<>\\])+>|[^ \t\n\x00-\x1f]*/).replace("title",/"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/).getRegex(),ek=oe(/^!?\[(label)\]\[(ref)\]/).replace("label",Ja).replace("ref",Gp).getRegex(),tk=oe(/^!?\[(ref)\](?:\[\])?/).replace("ref",Gp).getRegex(),fL=oe("reflink|nolink(?!\\()","g").replace("reflink",ek).replace("nolink",tk).getRegex(),Bx=/[hH][tT][tT][pP][sS]?|[fF][tT][pP]/,Kp={_backpedal:Gn,anyPunctuation:oL,autolink:lL,blockSkip:HM,br:Fx,code:WM,del:Gn,delLDelim:Gn,delRDelim:Gn,emStrongLDelim:KM,emStrongRDelimAst:eL,emStrongRDelimUnd:iL,escape:qM,link:hL,nolink:tk,punctuation:GM,reflink:ek,reflinkSearch:fL,tag:cL,text:VM,url:Gn},uL={...Kp,link:oe(/^!?\[(label)\]\((.*?)\)/).replace("label",Ja).getRegex(),reflink:oe(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace("label",Ja).getRegex()},jp={...Kp,emStrongRDelimAst:tL,emStrongLDelim:JM,delLDelim:nL,delRDelim:sL,url:oe(/^((?:protocol):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/).replace("protocol",Bx).replace("email",/[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/).getRegex(),_backpedal:/(?:[^?!.,:;*_'"~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_'"~)]+(?!$))+/,del:/^(~~?)(?=[^\s~])((?:\\[\s\S]|[^\\])*?(?:\\[\s\S]|[^\s~\\]))\1(?=[^~]|$)/,text:oe(/^([`~]+|[^`~])(?:(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\<!\[`*~_]|\b_|protocol:\/\/|www\.|$)|[^ ](?= {2,}\n)|[^a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-](?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)))/).replace("protocol",Bx).getRegex()},dL={...jp,br:oe(Fx).replace("{2,}","*").getRegex(),text:oe(jp.text).replace("\\b_","\\b_| {2,}\\n").replace(/\{2,\}/g,"*").getRegex()},Ha={normal:Fp,gfm:zM,pedantic:YM},xo={normal:Kp,gfm:jp,breaks:dL,pedantic:uL},pL={"&":"&","<":"<",">":">",'"':""","'":"'"},Nx=t=>pL[t];function mi(t,e){if(e){if(nt.escapeTest.test(t))return t.replace(nt.escapeReplace,Nx)}else if(nt.escapeTestNoEncode.tesLine truncated
|
]`).replace("lheading",Kx).replace("|table","").replace("blockquote"," {0,3}>").replace("|fences","").replace("|list","").replace("|html","").replace("|tag","").getRegex()},VM=/^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/,GM=/^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,ek=/^( {2,}|\\)\n(?!\s*$)/,UM=/^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\<!\[`*_]|\b_|$)|[^ ](?= {2,}\n)))/,Fr=/[\p{P}\p{S}]/u,oc=/[\s\p{P}\p{S}]/u,eg=/[^\s\p{P}\p{S}]/u,FM=le(/^((?![*_])punctSpace)/,"u").replace(/punctSpace/g,oc).getRegex(),tk=/(?!~)[\p{P}\p{S}]/u,HM=/(?!~)[\s\p{P}\p{S}]/u,KM=/(?:[^\s\p{P}\p{S}]|~)/u,JM=le(/link|precode-code|html/,"g").replace("link",/\[(?:[^\[\]`]|(?<a>`+)[^`]+\k<a>(?!`))*?\]\((?:\\[\s\S]|[^\\\(\)]|\((?:\\[\s\S]|[^\\\(\)])*\))*\)/).replace("precode-",LM?"(?<!`)()":"(^^|[^`])").replace("code",/(?<b>`+)[^`]+\k<b>(?!`)/).replace("html",/<(?! )[^<>]*?>/).getRegex(),ik=/^(?:\*+(?:((?!\*)punct)|([^\s*]))?)|^_+(?:((?!_)punct)|([^\s_]))?/,eL=le(ik,"u").replace(/punct/g,Fr).getRegex(),tL=le(ik,"u").replace(/punct/g,tk).getRegex(),nk="^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\*)punct(\\*+)(?=[\\s]|$)|notPunctSpace(\\*+)(?!\\*)(?=punctSpace|$)|(?!\\*)punctSpace(\\*+)(?=notPunctSpace)|[\\s](\\*+)(?!\\*)(?=punct)|(?!\\*)punct(\\*+)(?!\\*)(?=punct)|notPunctSpace(\\*+)(?=notPunctSpace)",iL=le(nk,"gu").replace(/notPunctSpace/g,eg).replace(/punctSpace/g,oc).replace(/punct/g,Fr).getRegex(),nL=le(nk,"gu").replace(/notPunctSpace/g,KM).replace(/punctSpace/g,HM).replace(/punct/g,tk).getRegex(),rL=le("^[^_*]*?\\*\\*[^_*]*?_[^_*]*?(?=\\*\\*)|[^_]+(?=[^_])|(?!_)punct(_+)(?=[\\s]|$)|notPunctSpace(_+)(?!_)(?=punctSpace|$)|(?!_)punctSpace(_+)(?=notPunctSpace)|[\\s](_+)(?!_)(?=punct)|(?!_)punct(_+)(?!_)(?=punct)","gu").replace(/notPunctSpace/g,eg).replace(/punctSpace/g,oc).replace(/punct/g,Fr).getRegex(),sL=le(/^~~?(?:((?!~)punct)|[^\s~])/,"u").replace(/punct/g,Fr).getRegex(),oL="^[^~]+(?=[^~])|(?!~)punct(~~?)(?=[\\s]|$)|notPunctSpace(~~?)(?!~)(?=punctSpace|$)|(?!~)punctSpace(~~?)(?=notPunctSpace)|[\\s](~~?)(?!~)(?=punct)|(?!~)punct(~~?)(?!~)(?=punct)|notPunctSpace(~~?)(?=notPunctSpace)",lL=le(oL,"gu").replace(/notPunctSpace/g,eg).replace(/punctSpace/g,oc).replace(/punct/g,Fr).getRegex(),aL=le(/\\(punct)/,"gu").replace(/punct/g,Fr).getRegex(),cL=le(/^<(scheme:[^\s\x00-\x1f<>]*|email)>/).replace("scheme",/[a-zA-Z][a-zA-Z0-9+.-]{1,31}/).replace("email",/[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/).getRegex(),hL=le(Kp).replace("(?:-->|$)","-->").getRegex(),fL=le("^comment|^</[a-zA-Z][\\w:-]*\\s*>|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^<![a-zA-Z]+\\s[\\s\\S]*?>|^<!\\[CDATA\\[[\\s\\S]*?\\]\\]>").replace("comment",hL).replace("attribute",/\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/).getRegex(),ic=/(?:\[(?:\\[\s\S]|[^\[\]\\])*\]|\\[\s\S]|`+(?!`)[^`]*?`+(?!`)|``+(?=\])|[^\[\]\\`])*?/,uL=le(/^!?\[(label)\]\(\s*(href)(?:(?:[ \t]+(?:\n[ \t]*)?|\n[ \t]*)(title))?\s*\)/).replace("label",ic).replace("href",/<(?:\\.|[^\n<>\\])+>|[^ \t\n\x00-\x1f]*/).replace("title",/"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/).getRegex(),rk=le(/^!?\[(label)\]\[(ref)\]/).replace("label",ic).replace("ref",Hp).getRegex(),sk=le(/^!?\[(ref)\](?:\[\])?/).replace("ref",Hp).getRegex(),dL=le("reflink|nolink(?!\\()","g").replace("reflink",rk).replace("nolink",sk).getRegex(),Yx=/[hH][tT][tT][pP][sS]?|[fF][tT][pP]/,tg={_backpedal:Vn,anyPunctuation:aL,autolink:cL,blockSkip:JM,br:ek,code:GM,del:Vn,delLDelim:Vn,delRDelim:Vn,emStrongLDelim:eL,emStrongRDelimAst:iL,emStrongRDelimUnd:rL,escape:VM,link:uL,nolink:sk,punctuation:FM,reflink:rk,reflinkSearch:dL,tag:fL,text:UM,url:Vn},pL={...tg,link:le(/^!?\[(label)\]\((.*?)\)/).replace("label",ic).getRegex(),reflink:le(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace("label",ic).getRegex()},qp={...tg,emStrongRDelimAst:nL,emStrongLDelim:tL,delLDelim:sL,delRDelim:lL,url:le(/^((?:protocol):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/).replace("protocol",Yx).replace("email",/[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/).getRegex(),_backpedal:/(?:[^?!.,:;*_'"~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_'"~)]+(?!$))+/,del:/^(~~?)(?=[^\s~])((?:\\[\s\S]|[^\\])*?(?:\\[\s\S]|[^\s~\\]))\1(?=[^~]|$)/,text:le(/^([`~]+|[^`~])(?:(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\<!\[`*~_]|\b_|protocol:\/\/|www\.|$)|[^ ](?= {2,}\n)|[^a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-](?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)))/).replace("protocol",Yx).getRegex()},gL={...qp,br:le(ek).replace("{2,}","*").getRegex(),text:le(qp.text).replace("\\b_","\\b_| {2,}\\n").replace(/\{2,\}/g,"*").getRegex()},ec={normal:Jp,gfm:qM,pedantic:WM},ko={normal:tg,gfm:qp,breaks:gL,pedantic:pL},OL={"&":"&","<":"<",">":">",'"':""","'":"'"},qx=t=>OL[t];function bi(t,e){if(e){if(nt.escapeTest.test(t))return t.replace(nt.escapeReplace,qx)}else if(nt.escapeTestNoEncode.tesLine truncated
|
||||||
`),i=e.length-1;for(;i>=0&&nt.blankLine.test(e[i]);)i--;return e.length-i<=2?t:e.slice(0,i+1).join(`
|
`),i=e.length-1;for(;i>=0&&nt.blankLine.test(e[i]);)i--;return e.length-i<=2?t:e.slice(0,i+1).join(`
|
||||||
`)}function gL(t,e){if(t.indexOf(e[1])===-1)return-1;let i=0;for(let n=0;n<t.length;n++)if(t[n]==="\\")n++;else if(t[n]===e[0])i++;else if(t[n]===e[1]&&(i--,i<0))return n;return i>0?-2:-1}function OL(t,e=0){let i=e,n="";for(let r of t)if(r===" "){let s=4-i%4;n+=" ".repeat(s),i+=s}else n+=r,i++;return n}function qx(t,e,i,n,r){let s=e.href,o=e.title||null,l=t[1].replace(r.other.outputLinkReplace,"$1");n.state.inLink=!0;let a={type:t[0].charAt(0)==="!"?"image":"link",raw:i,href:s,title:o,text:l,tokens:n.inlineTokens(l)};return n.state.inLink=!1,a}function mL(t,e,i){let n=t.match(i.other.indentCodeCompensation);if(n===null)return e;let r=n[1];return e.split(`
|
`)}function mL(t,e){if(t.indexOf(e[1])===-1)return-1;let i=0;for(let n=0;n<t.length;n++)if(t[n]==="\\")n++;else if(t[n]===e[0])i++;else if(t[n]===e[1]&&(i--,i<0))return n;return i>0?-2:-1}function bL(t,e=0){let i=e,n="";for(let r of t)if(r===" "){let s=4-i%4;n+=" ".repeat(s),i+=s}else n+=r,i++;return n}function Ux(t,e,i,n,r){let s=e.href,o=e.title||null,l=t[1].replace(r.other.outputLinkReplace,"$1");n.state.inLink=!0;let a={type:t[0].charAt(0)==="!"?"image":"link",raw:i,href:s,title:o,text:l,tokens:n.inlineTokens(l)};return n.state.inLink=!1,a}function yL(t,e,i){let n=t.match(i.other.indentCodeCompensation);if(n===null)return e;let r=n[1];return e.split(`
|
||||||
`).map(s=>{let o=s.match(i.other.beginningSpace);if(o===null)return s;let[l]=o;return l.length>=r.length?s.slice(r.length):s}).join(`
|
`).map(s=>{let o=s.match(i.other.beginningSpace);if(o===null)return s;let[l]=o;return l.length>=r.length?s.slice(r.length):s}).join(`
|
||||||
`)}var ec=class{constructor(t){J(this,"options");J(this,"rules");J(this,"lexer");this.options=t||Fn}space(t){let e=this.rules.block.newline.exec(t);if(e&&e[0].length>0)return{type:"space",raw:e[0]}}code(t){let e=this.rules.block.code.exec(t);if(e){let i=this.options.pedantic?e[0]:Yx(e[0]),n=i.replace(this.rules.other.codeRemoveIndent,"");return{type:"code",raw:i,codeBlockStyle:"indented",text:n}}}fences(t){let e=this.rules.block.fences.exec(t);if(e){let i=e[0],n=mL(i,e[3]||"",this.rules);return{type:"code",raw:i,lang:e[2]?e[2].trim().replace(this.rules.inline.anyPunctuation,"$1"):e[2],text:n}}}heading(t){let e=this.rules.block.heading.exec(t);if(e){let i=e[2].trim();if(this.rules.other.endingHash.test(i)){let n=sn(i,"#");(this.options.pedantic||!n||this.rules.other.endingSpaceChar.test(n))&&(i=n.trim())}return{type:"heading",raw:sn(e[0],`
|
`)}var nc=class{constructor(t){K(this,"options");K(this,"rules");K(this,"lexer");this.options=t||Un}space(t){let e=this.rules.block.newline.exec(t);if(e&&e[0].length>0)return{type:"space",raw:e[0]}}code(t){let e=this.rules.block.code.exec(t);if(e){let i=this.options.pedantic?e[0]:Gx(e[0]),n=i.replace(this.rules.other.codeRemoveIndent,"");return{type:"code",raw:i,codeBlockStyle:"indented",text:n}}}fences(t){let e=this.rules.block.fences.exec(t);if(e){let i=e[0],n=yL(i,e[3]||"",this.rules);return{type:"code",raw:i,lang:e[2]?e[2].trim().replace(this.rules.inline.anyPunctuation,"$1"):e[2],text:n}}}heading(t){let e=this.rules.block.heading.exec(t);if(e){let i=e[2].trim();if(this.rules.other.endingHash.test(i)){let n=sn(i,"#");(this.options.pedantic||!n||this.rules.other.endingSpaceChar.test(n))&&(i=n.trim())}return{type:"heading",raw:sn(e[0],`
|
||||||
`),depth:e[1].length,text:i,tokens:this.lexer.inline(i)}}}hr(t){let e=this.rules.block.hr.exec(t);if(e)return{type:"hr",raw:sn(e[0],`
|
`),depth:e[1].length,text:i,tokens:this.lexer.inline(i)}}}hr(t){let e=this.rules.block.hr.exec(t);if(e)return{type:"hr",raw:sn(e[0],`
|
||||||
`)}}blockquote(t){let e=this.rules.block.blockquote.exec(t);if(e){let i=sn(e[0],`
|
`)}}blockquote(t){let e=this.rules.block.blockquote.exec(t);if(e){let i=sn(e[0],`
|
||||||
`).split(`
|
`).split(`
|
||||||
@@ -65,19 +65,19 @@ ${c}`:c;let f=this.lexer.state.top;if(this.lexer.state.top=!0,this.lexer.blockTo
|
|||||||
`),g=this.blockquote(p);s[s.length-1]=g,n=n.substring(0,n.length-d.raw.length)+g.raw,r=r.substring(0,r.length-d.text.length)+g.text;break}else if((u==null?void 0:u.type)==="list"){let d=u,p=d.raw+`
|
`),g=this.blockquote(p);s[s.length-1]=g,n=n.substring(0,n.length-d.raw.length)+g.raw,r=r.substring(0,r.length-d.text.length)+g.text;break}else if((u==null?void 0:u.type)==="list"){let d=u,p=d.raw+`
|
||||||
`+i.join(`
|
`+i.join(`
|
||||||
`),g=this.list(p);s[s.length-1]=g,n=n.substring(0,n.length-u.raw.length)+g.raw,r=r.substring(0,r.length-d.raw.length)+g.raw,i=p.substring(s.at(-1).raw.length).split(`
|
`),g=this.list(p);s[s.length-1]=g,n=n.substring(0,n.length-u.raw.length)+g.raw,r=r.substring(0,r.length-d.raw.length)+g.raw,i=p.substring(s.at(-1).raw.length).split(`
|
||||||
`);continue}}return{type:"blockquote",raw:n,tokens:s,text:r}}}list(t){let e=this.rules.block.list.exec(t);if(e){let i=e[1].trim(),n=i.length>1,r={type:"list",raw:"",ordered:n,start:n?+i.slice(0,-1):"",loose:!1,items:[]};i=n?`\\d{1,9}\\${i.slice(-1)}`:`\\${i}`,this.options.pedantic&&(i=n?i:"[*+-]");let s=this.rules.other.listItemRegex(i),o=!1;for(;t;){let a=!1,h="",c="";if(!(e=s.exec(t))||this.rules.block.hr.test(t))break;h=e[0],t=t.substring(h.length);let f=OL(e[2].split(`
|
`);continue}}return{type:"blockquote",raw:n,tokens:s,text:r}}}list(t){let e=this.rules.block.list.exec(t);if(e){let i=e[1].trim(),n=i.length>1,r={type:"list",raw:"",ordered:n,start:n?+i.slice(0,-1):"",loose:!1,items:[]};i=n?`\\d{1,9}\\${i.slice(-1)}`:`\\${i}`,this.options.pedantic&&(i=n?i:"[*+-]");let s=this.rules.other.listItemRegex(i),o=!1;for(;t;){let a=!1,h="",c="";if(!(e=s.exec(t))||this.rules.block.hr.test(t))break;h=e[0],t=t.substring(h.length);let f=bL(e[2].split(`
|
||||||
`,1)[0],e[1].length),u=t.split(`
|
`,1)[0],e[1].length),u=t.split(`
|
||||||
`,1)[0],d=!f.trim(),p=0;if(this.options.pedantic?(p=2,c=f.trimStart()):d?p=e[1].length+1:(p=f.search(this.rules.other.nonSpaceChar),p=p>4?1:p,c=f.slice(p),p+=e[1].length),d&&this.rules.other.blankLine.test(u)&&(h+=u+`
|
`,1)[0],d=!f.trim(),p=0;if(this.options.pedantic?(p=2,c=f.trimStart()):d?p=e[1].length+1:(p=f.search(this.rules.other.nonSpaceChar),p=p>4?1:p,c=f.slice(p),p+=e[1].length),d&&this.rules.other.blankLine.test(u)&&(h+=u+`
|
||||||
`,t=t.substring(u.length+1),a=!0),!a){let g=this.rules.other.nextBulletRegex(p),m=this.rules.other.hrRegex(p),b=this.rules.other.fencesBeginRegex(p),y=this.rules.other.headingBeginRegex(p),x=this.rules.other.htmlBeginRegex(p),Q=this.rules.other.blockquoteBeginRegex(p);for(;t;){let S=t.split(`
|
`,t=t.substring(u.length+1),a=!0),!a){let g=this.rules.other.nextBulletRegex(p),m=this.rules.other.hrRegex(p),b=this.rules.other.fencesBeginRegex(p),y=this.rules.other.headingBeginRegex(p),S=this.rules.other.htmlBeginRegex(p),v=this.rules.other.blockquoteBeginRegex(p);for(;t;){let x=t.split(`
|
||||||
`,1)[0],k;if(u=S,this.options.pedantic?(u=u.replace(this.rules.other.listReplaceNesting," "),k=u):k=u.replace(this.rules.other.tabCharGlobal," "),b.test(u)||y.test(u)||x.test(u)||Q.test(u)||g.test(u)||m.test(u))break;if(k.search(this.rules.other.nonSpaceChar)>=p||!u.trim())c+=`
|
`,1)[0],w;if(u=x,this.options.pedantic?(u=u.replace(this.rules.other.listReplaceNesting," "),w=u):w=u.replace(this.rules.other.tabCharGlobal," "),b.test(u)||y.test(u)||S.test(u)||v.test(u)||g.test(u)||m.test(u))break;if(w.search(this.rules.other.nonSpaceChar)>=p||!u.trim())c+=`
|
||||||
`+k.slice(p);else{if(d||f.replace(this.rules.other.tabCharGlobal," ").search(this.rules.other.nonSpaceChar)>=4||b.test(f)||y.test(f)||m.test(f))break;c+=`
|
`+w.slice(p);else{if(d||f.replace(this.rules.other.tabCharGlobal," ").search(this.rules.other.nonSpaceChar)>=4||b.test(f)||y.test(f)||m.test(f))break;c+=`
|
||||||
`+u}d=!u.trim(),h+=S+`
|
`+u}d=!u.trim(),h+=x+`
|
||||||
`,t=t.substring(S.length+1),f=k.slice(p)}}r.loose||(o?r.loose=!0:this.rules.other.doubleBlankLine.test(h)&&(o=!0)),r.items.push({type:"list_item",raw:h,task:!!this.options.gfm&&this.rules.other.listIsTask.test(c),loose:!1,text:c,tokens:[]}),r.raw+=h}let l=r.items.at(-1);if(l)l.raw=l.raw.trimEnd(),l.text=l.text.trimEnd();else return;r.raw=r.raw.trimEnd();for(let a of r.items){this.lexer.state.top=!1,a.tokens=this.lexer.blockTokens(a.text,[]);let h=a.tokens[0];if(a.task&&((h==null?void 0:h.type)==="text"||(h==null?void 0:h.type)==="paragraph")){a.text=a.text.replace(this.rules.other.listReplaceTask,""),h.raw=h.raw.replace(this.rules.other.listReplaceTask,""),h.text=h.text.replace(this.rules.other.listReplaceTask,"");for(let f=this.lexer.inlineQueue.length-1;f>=0;f--)if(this.rules.other.listIsTask.test(this.lexer.inlineQueue[f].src)){this.lexer.inlineQueue[f].src=this.lexer.inlineQueue[f].src.replace(this.rules.other.listReplaceTask,"");break}let c=this.rules.other.listTaskCheckbox.exec(a.raw);if(c){let f={type:"checkbox",raw:c[0]+" ",checked:c[0]!=="[ ]"};a.checked=f.checked,r.loose?a.tokens[0]&&["paragraph","text"].includes(a.tokens[0].type)&&"tokens"in a.tokens[0]&&a.tokens[0].tokens?(a.tokens[0].raw=f.raw+a.tokens[0].raw,a.tokens[0].text=f.raw+a.tokens[0].text,a.tokens[0].tokens.unshift(f)):a.tokens.unshift({type:"paragraph",raw:f.raw,text:f.raw,tokens:[f]}):a.tokens.unshift(f)}}else a.task&&(a.task=!1);if(!r.loose){let c=a.tokens.filter(u=>u.type==="space"),f=c.length>0&&c.some(u=>this.rules.other.anyLine.test(u.raw));r.loose=f}}if(r.loose)for(let a of r.items){a.loose=!0;for(let h of a.tokens)h.type==="text"&&(h.type="paragraph")}return r}}html(t){let e=this.rules.block.html.exec(t);if(e){let i=Yx(e[0]);return{type:"html",block:!0,raw:i,pre:e[1]==="pre"||e[1]==="script"||e[1]==="style",text:i}}}def(t){let e=this.rules.block.def.exec(t);if(e){let i=e[1].toLowerCase().replace(this.rules.other.multipleSpaceGlobal," "),n=e[2]?e[2].replace(this.rules.other.hrefBrackets,"$1").replace(this.rules.inline.anyPunctuation,"$1"):"",r=e[3]?e[3].substring(1,e[3].length-1).replace(this.rules.inline.anyPunctuation,"$1"):e[3];return{type:"def",tag:i,raw:sn(e[0],`
|
`,t=t.substring(x.length+1),f=w.slice(p)}}r.loose||(o?r.loose=!0:this.rules.other.doubleBlankLine.test(h)&&(o=!0)),r.items.push({type:"list_item",raw:h,task:!!this.options.gfm&&this.rules.other.listIsTask.test(c),loose:!1,text:c,tokens:[]}),r.raw+=h}let l=r.items.at(-1);if(l)l.raw=l.raw.trimEnd(),l.text=l.text.trimEnd();else return;r.raw=r.raw.trimEnd();for(let a of r.items){this.lexer.state.top=!1,a.tokens=this.lexer.blockTokens(a.text,[]);let h=a.tokens[0];if(a.task&&((h==null?void 0:h.type)==="text"||(h==null?void 0:h.type)==="paragraph")){a.text=a.text.replace(this.rules.other.listReplaceTask,""),h.raw=h.raw.replace(this.rules.other.listReplaceTask,""),h.text=h.text.replace(this.rules.other.listReplaceTask,"");for(let f=this.lexer.inlineQueue.length-1;f>=0;f--)if(this.rules.other.listIsTask.test(this.lexer.inlineQueue[f].src)){this.lexer.inlineQueue[f].src=this.lexer.inlineQueue[f].src.replace(this.rules.other.listReplaceTask,"");break}let c=this.rules.other.listTaskCheckbox.exec(a.raw);if(c){let f={type:"checkbox",raw:c[0]+" ",checked:c[0]!=="[ ]"};a.checked=f.checked,r.loose?a.tokens[0]&&["paragraph","text"].includes(a.tokens[0].type)&&"tokens"in a.tokens[0]&&a.tokens[0].tokens?(a.tokens[0].raw=f.raw+a.tokens[0].raw,a.tokens[0].text=f.raw+a.tokens[0].text,a.tokens[0].tokens.unshift(f)):a.tokens.unshift({type:"paragraph",raw:f.raw,text:f.raw,tokens:[f]}):a.tokens.unshift(f)}}else a.task&&(a.task=!1);if(!r.loose){let c=a.tokens.filter(u=>u.type==="space"),f=c.length>0&&c.some(u=>this.rules.other.anyLine.test(u.raw));r.loose=f}}if(r.loose)for(let a of r.items){a.loose=!0;for(let h of a.tokens)h.type==="text"&&(h.type="paragraph")}return r}}html(t){let e=this.rules.block.html.exec(t);if(e){let i=Gx(e[0]);return{type:"html",block:!0,raw:i,pre:e[1]==="pre"||e[1]==="script"||e[1]==="style",text:i}}}def(t){let e=this.rules.block.def.exec(t);if(e){let i=e[1].toLowerCase().replace(this.rules.other.multipleSpaceGlobal," "),n=e[2]?e[2].replace(this.rules.other.hrefBrackets,"$1").replace(this.rules.inline.anyPunctuation,"$1"):"",r=e[3]?e[3].substring(1,e[3].length-1).replace(this.rules.inline.anyPunctuation,"$1"):e[3];return{type:"def",tag:i,raw:sn(e[0],`
|
||||||
`),href:n,title:r}}}table(t){var o;let e=this.rules.block.table.exec(t);if(!e||!this.rules.other.tableDelimiter.test(e[2]))return;let i=zx(e[1]),n=e[2].replace(this.rules.other.tableAlignChars,"").split("|"),r=(o=e[3])!=null&&o.trim()?e[3].replace(this.rules.other.tableRowBlankLine,"").split(`
|
`),href:n,title:r}}}table(t){var o;let e=this.rules.block.table.exec(t);if(!e||!this.rules.other.tableDelimiter.test(e[2]))return;let i=Vx(e[1]),n=e[2].replace(this.rules.other.tableAlignChars,"").split("|"),r=(o=e[3])!=null&&o.trim()?e[3].replace(this.rules.other.tableRowBlankLine,"").split(`
|
||||||
`):[],s={type:"table",raw:sn(e[0],`
|
`):[],s={type:"table",raw:sn(e[0],`
|
||||||
`),header:[],align:[],rows:[]};if(i.length===n.length){for(let l of n)this.rules.other.tableAlignRight.test(l)?s.align.push("right"):this.rules.other.tableAlignCenter.test(l)?s.align.push("center"):this.rules.other.tableAlignLeft.test(l)?s.align.push("left"):s.align.push(null);for(let l=0;l<i.length;l++)s.header.push({text:i[l],tokens:this.lexer.inline(i[l]),header:!0,align:s.align[l]});for(let l of r)s.rows.push(zx(l,s.header.length).map((a,h)=>({text:a,tokens:this.lexer.inline(a),header:!1,align:s.align[h]})));return s}}lheading(t){let e=this.rules.block.lheading.exec(t);if(e){let i=e[1].trim();return{type:"heading",raw:sn(e[0],`
|
`),header:[],align:[],rows:[]};if(i.length===n.length){for(let l of n)this.rules.other.tableAlignRight.test(l)?s.align.push("right"):this.rules.other.tableAlignCenter.test(l)?s.align.push("center"):this.rules.other.tableAlignLeft.test(l)?s.align.push("left"):s.align.push(null);for(let l=0;l<i.length;l++)s.header.push({text:i[l],tokens:this.lexer.inline(i[l]),header:!0,align:s.align[l]});for(let l of r)s.rows.push(Vx(l,s.header.length).map((a,h)=>({text:a,tokens:this.lexer.inline(a),header:!1,align:s.align[h]})));return s}}lheading(t){let e=this.rules.block.lheading.exec(t);if(e){let i=e[1].trim();return{type:"heading",raw:sn(e[0],`
|
||||||
`),depth:e[2].charAt(0)==="="?1:2,text:i,tokens:this.lexer.inline(i)}}}paragraph(t){let e=this.rules.block.paragraph.exec(t);if(e){let i=e[1].charAt(e[1].length-1)===`
|
`),depth:e[2].charAt(0)==="="?1:2,text:i,tokens:this.lexer.inline(i)}}}paragraph(t){let e=this.rules.block.paragraph.exec(t);if(e){let i=e[1].charAt(e[1].length-1)===`
|
||||||
`?e[1].slice(0,-1):e[1];return{type:"paragraph",raw:e[0],text:i,tokens:this.lexer.inline(i)}}}text(t){let e=this.rules.block.text.exec(t);if(e)return{type:"text",raw:e[0],text:e[0],tokens:this.lexer.inline(e[0])}}escape(t){let e=this.rules.inline.escape.exec(t);if(e)return{type:"escape",raw:e[0],text:e[1]}}tag(t){let e=this.rules.inline.tag.exec(t);if(e)return!this.lexer.state.inLink&&this.rules.other.startATag.test(e[0])?this.lexer.state.inLink=!0:this.lexer.state.inLink&&this.rules.other.endATag.test(e[0])&&(this.lexer.state.inLink=!1),!this.lexer.state.inRawBlock&&this.rules.other.startPreScriptTag.test(e[0])?this.lexer.state.inRawBlock=!0:this.lexer.state.inRawBlock&&this.rules.other.endPreScriptTag.test(e[0])&&(this.lexer.state.inRawBlock=!1),{type:"html",raw:e[0],inLink:this.lexer.state.inLink,inRawBlock:this.lexer.state.inRawBlock,block:!1,text:e[0]}}link(t){let e=this.rules.inline.link.exec(t);if(e){let i=e[2].trim();if(!this.options.pedantic&&this.rules.other.startAngleBracket.test(i)){if(!this.rules.other.endAngleBracket.test(i))return;let s=sn(i.slice(0,-1),"\\");if((i.length-s.length)%2===0)return}else{let s=gL(e[2],"()");if(s===-2)return;if(s>-1){let o=(e[0].indexOf("!")===0?5:4)+e[1].length+s;e[2]=e[2].substring(0,s),e[0]=e[0].substring(0,o).trim(),e[3]=""}}let n=e[2],r="";if(this.options.pedantic){let s=this.rules.other.pedanticHrefTitle.exec(n);s&&(n=s[1],r=s[3])}else r=e[3]?e[3].slice(1,-1):"";return n=n.trim(),this.rules.other.startAngleBracket.test(n)&&(this.options.pedantic&&!this.rules.other.endAngleBracket.test(i)?n=n.slice(1):n=n.slice(1,-1)),qx(e,{href:n&&n.replace(this.rules.inline.anyPunctuation,"$1"),title:r&&r.replace(this.rules.inline.anyPunctuation,"$1")},e[0],this.lexer,this.rules)}}reflink(t,e){let i;if((i=this.rules.inline.reflink.exec(t))||(i=this.rules.inline.nolink.exec(t))){let n=(i[2]||i[1]).replace(this.rules.other.multipleSpaceGlobal," "),r=e[n.toLowerCase()];if(!r){let s=i[0].charAt(0);return{type:"text",raw:s,text:s}}return qx(i,r,i[0],this.lexer,this.rules)}}emStrong(t,e,i=""){let n=this.rules.inline.emStrongLDelim.exec(t);if(!(!n||!n[1]&&!n[2]&&!n[3]&&!n[4]||n[4]&&i.match(this.rules.other.unicodeAlphaNumeric))&&(!(n[1]||n[3])||!i||this.rules.inline.punctuation.exec(i))){let r=[...n[0]].length-1,s,o,l=r,a=0,h=n[0][0]==="*"?this.rules.inline.emStrongRDelimAst:this.rules.inline.emStrongRDelimUnd;for(h.lastIndex=0,e=e.slice(-1*t.length+r);(n=h.exec(e))!==null;){if(s=n[1]||n[2]||n[3]||n[4]||n[5]||n[6],!s)continue;if(o=[...s].length,n[3]||n[4]){l+=o;continue}else if((n[5]||n[6])&&r%3&&!((r+o)%3)){a+=o;continue}if(l-=o,l>0)continue;o=Math.min(o,o+l+a);let c=[...n[0]][0].length,f=t.slice(0,r+n.index+c+o);if(Math.min(r,o)%2){let d=f.slice(1,-1);return{type:"em",raw:f,text:d,tokens:this.lexer.inlineTokens(d)}}let u=f.slice(2,-2);return{type:"strong",raw:f,text:u,tokens:this.lexer.inlineTokens(u)}}}}codespan(t){let e=this.rules.inline.code.exec(t);if(e){let i=e[2].replace(this.rules.other.newLineCharGlobal," "),n=this.rules.other.nonSpaceChar.test(i),r=this.rules.other.startingSpaceChar.test(i)&&this.rules.other.endingSpaceChar.test(i);return n&&r&&(i=i.substring(1,i.length-1)),{type:"codespan",raw:e[0],text:i}}}br(t){let e=this.rules.inline.br.exec(t);if(e)return{type:"br",raw:e[0]}}del(t,e,i=""){let n=this.rules.inline.delLDelim.exec(t);if(n&&(!n[1]||!i||this.rules.inline.punctuation.exec(i))){let r=[...n[0]].length-1,s,o,l=r,a=this.rules.inline.delRDelim;for(a.lastIndex=0,e=e.slice(-1*t.length+r);(n=a.exec(e))!==null;){if(s=n[1]||n[2]||n[3]||n[4]||n[5]||n[6],!s||(o=[...s].length,o!==r))continue;if(n[3]||n[4]){l+=o;continue}if(l-=o,l>0)continue;o=Math.min(o,o+l);let h=[...n[0]][0].length,c=t.slice(0,r+n.index+h+o),f=c.slice(r,-r);return{type:"del",raw:c,text:f,tokens:this.lexer.inlineTokens(f)}}}}autolink(t){let e=this.rules.inline.autolink.exec(t);if(e){let i,n;return e[2]==="@"?(i=e[1],n="mailto:"+i):(i=e[1],n=i),{type:"link",raw:e[0],text:i,href:n,tokens:[{type:"text",raw:i,text:i}]}}}url(t){var i,n;let e;if(e=this.rules.inline.url.exec(t)){let r,s;if(e[2]==="@")r=e[0],s="mailto:"+r;else{let o;do o=e[0],e[0]=(n=(i=this.rules.inline._backpedal.exec(e[0]))==null?void 0:i[0])!=null?n:"";while(o!==e[0]);r=e[0],e[1]==="www."?s="http://"+e[0]:s=e[0]}return{type:"link",raw:e[0],text:r,href:s,tokens:[{type:"text",raw:r,text:r}]}}}inlineText(t){let e=this.rules.inline.text.exec(t);if(e){let i=this.lexer.state.inRawBlock;return{type:"text",raw:e[0],text:e[0],escaped:i}}}},Jt=class zp{constructor(e){J(this,"tokens");J(this,"options");J(this,"state");J(this,"inlineQueue");J(this,"tokenizer");this.tokens=[],this.tokens.links=Object.create(null),this.options=e||Fn,this.options.tokenizer=this.options.tokenizer||new ec,this.tokenizer=this.options.tokenizer,this.tokenizer.options=this.options,this.tokenizer.lexer=this,this.inlineQueue=[],this.state={inLink:!1,inRawBlock:!1,top:!0};let i={other:nt,block:Ha.normal,inline:xo.normal};this.options.pedantic?(i.block=Ha.pedantic,i.inline=xo.p
Line truncated
|
`?e[1].slice(0,-1):e[1];return{type:"paragraph",raw:e[0],text:i,tokens:this.lexer.inline(i)}}}text(t){let e=this.rules.block.text.exec(t);if(e)return{type:"text",raw:e[0],text:e[0],tokens:this.lexer.inline(e[0])}}escape(t){let e=this.rules.inline.escape.exec(t);if(e)return{type:"escape",raw:e[0],text:e[1]}}tag(t){let e=this.rules.inline.tag.exec(t);if(e)return!this.lexer.state.inLink&&this.rules.other.startATag.test(e[0])?this.lexer.state.inLink=!0:this.lexer.state.inLink&&this.rules.other.endATag.test(e[0])&&(this.lexer.state.inLink=!1),!this.lexer.state.inRawBlock&&this.rules.other.startPreScriptTag.test(e[0])?this.lexer.state.inRawBlock=!0:this.lexer.state.inRawBlock&&this.rules.other.endPreScriptTag.test(e[0])&&(this.lexer.state.inRawBlock=!1),{type:"html",raw:e[0],inLink:this.lexer.state.inLink,inRawBlock:this.lexer.state.inRawBlock,block:!1,text:e[0]}}link(t){let e=this.rules.inline.link.exec(t);if(e){let i=e[2].trim();if(!this.options.pedantic&&this.rules.other.startAngleBracket.test(i)){if(!this.rules.other.endAngleBracket.test(i))return;let s=sn(i.slice(0,-1),"\\");if((i.length-s.length)%2===0)return}else{let s=mL(e[2],"()");if(s===-2)return;if(s>-1){let o=(e[0].indexOf("!")===0?5:4)+e[1].length+s;e[2]=e[2].substring(0,s),e[0]=e[0].substring(0,o).trim(),e[3]=""}}let n=e[2],r="";if(this.options.pedantic){let s=this.rules.other.pedanticHrefTitle.exec(n);s&&(n=s[1],r=s[3])}else r=e[3]?e[3].slice(1,-1):"";return n=n.trim(),this.rules.other.startAngleBracket.test(n)&&(this.options.pedantic&&!this.rules.other.endAngleBracket.test(i)?n=n.slice(1):n=n.slice(1,-1)),Ux(e,{href:n&&n.replace(this.rules.inline.anyPunctuation,"$1"),title:r&&r.replace(this.rules.inline.anyPunctuation,"$1")},e[0],this.lexer,this.rules)}}reflink(t,e){let i;if((i=this.rules.inline.reflink.exec(t))||(i=this.rules.inline.nolink.exec(t))){let n=(i[2]||i[1]).replace(this.rules.other.multipleSpaceGlobal," "),r=e[n.toLowerCase()];if(!r){let s=i[0].charAt(0);return{type:"text",raw:s,text:s}}return Ux(i,r,i[0],this.lexer,this.rules)}}emStrong(t,e,i=""){let n=this.rules.inline.emStrongLDelim.exec(t);if(!(!n||!n[1]&&!n[2]&&!n[3]&&!n[4]||n[4]&&i.match(this.rules.other.unicodeAlphaNumeric))&&(!(n[1]||n[3])||!i||this.rules.inline.punctuation.exec(i))){let r=[...n[0]].length-1,s,o,l=r,a=0,h=n[0][0]==="*"?this.rules.inline.emStrongRDelimAst:this.rules.inline.emStrongRDelimUnd;for(h.lastIndex=0,e=e.slice(-1*t.length+r);(n=h.exec(e))!==null;){if(s=n[1]||n[2]||n[3]||n[4]||n[5]||n[6],!s)continue;if(o=[...s].length,n[3]||n[4]){l+=o;continue}else if((n[5]||n[6])&&r%3&&!((r+o)%3)){a+=o;continue}if(l-=o,l>0)continue;o=Math.min(o,o+l+a);let c=[...n[0]][0].length,f=t.slice(0,r+n.index+c+o);if(Math.min(r,o)%2){let d=f.slice(1,-1);return{type:"em",raw:f,text:d,tokens:this.lexer.inlineTokens(d)}}let u=f.slice(2,-2);return{type:"strong",raw:f,text:u,tokens:this.lexer.inlineTokens(u)}}}}codespan(t){let e=this.rules.inline.code.exec(t);if(e){let i=e[2].replace(this.rules.other.newLineCharGlobal," "),n=this.rules.other.nonSpaceChar.test(i),r=this.rules.other.startingSpaceChar.test(i)&&this.rules.other.endingSpaceChar.test(i);return n&&r&&(i=i.substring(1,i.length-1)),{type:"codespan",raw:e[0],text:i}}}br(t){let e=this.rules.inline.br.exec(t);if(e)return{type:"br",raw:e[0]}}del(t,e,i=""){let n=this.rules.inline.delLDelim.exec(t);if(n&&(!n[1]||!i||this.rules.inline.punctuation.exec(i))){let r=[...n[0]].length-1,s,o,l=r,a=this.rules.inline.delRDelim;for(a.lastIndex=0,e=e.slice(-1*t.length+r);(n=a.exec(e))!==null;){if(s=n[1]||n[2]||n[3]||n[4]||n[5]||n[6],!s||(o=[...s].length,o!==r))continue;if(n[3]||n[4]){l+=o;continue}if(l-=o,l>0)continue;o=Math.min(o,o+l);let h=[...n[0]][0].length,c=t.slice(0,r+n.index+h+o),f=c.slice(r,-r);return{type:"del",raw:c,text:f,tokens:this.lexer.inlineTokens(f)}}}}autolink(t){let e=this.rules.inline.autolink.exec(t);if(e){let i,n;return e[2]==="@"?(i=e[1],n="mailto:"+i):(i=e[1],n=i),{type:"link",raw:e[0],text:i,href:n,tokens:[{type:"text",raw:i,text:i}]}}}url(t){var i,n;let e;if(e=this.rules.inline.url.exec(t)){let r,s;if(e[2]==="@")r=e[0],s="mailto:"+r;else{let o;do o=e[0],e[0]=(n=(i=this.rules.inline._backpedal.exec(e[0]))==null?void 0:i[0])!=null?n:"";while(o!==e[0]);r=e[0],e[1]==="www."?s="http://"+e[0]:s=e[0]}return{type:"link",raw:e[0],text:r,href:s,tokens:[{type:"text",raw:r,text:r}]}}}inlineText(t){let e=this.rules.inline.text.exec(t);if(e){let i=this.lexer.state.inRawBlock;return{type:"text",raw:e[0],text:e[0],escaped:i}}}},ei=class Wp{constructor(e){K(this,"tokens");K(this,"options");K(this,"state");K(this,"inlineQueue");K(this,"tokenizer");this.tokens=[],this.tokens.links=Object.create(null),this.options=e||Un,this.options.tokenizer=this.options.tokenizer||new nc,this.tokenizer=this.options.tokenizer,this.tokenizer.options=this.options,this.tokenizer.lexer=this,this.inlineQueue=[],this.state={inLink:!1,inRawBlock:!1,top:!0};let i={other:nt,block:ec.normal,inline:ko.normal};this.options.pedantic?(i.block=ec.pedantic,i.inline=ko.p
Line truncated
|
||||||
`),this.blockTokens(e,this.tokens);for(let i=0;i<this.inlineQueue.length;i++){let n=this.inlineQueue[i];this.inlineTokens(n.src,n.tokens)}return this.inlineQueue=[],this.tokens}blockTokens(e,i=[],n=!1){var s,o,l;this.tokenizer.lexer=this,this.options.pedantic&&(e=e.replace(nt.tabCharGlobal," ").replace(nt.spaceLine,""));let r=1/0;for(;e;){if(e.length<r)r=e.length;else{this.infiniteLoopError(e.charCodeAt(0));break}let a;if((o=(s=this.options.extensions)==null?void 0:s.block)!=null&&o.some(c=>(a=c.call({lexer:this},e,i))?(e=e.substring(a.raw.length),i.push(a),!0):!1))continue;if(a=this.tokenizer.space(e)){e=e.substring(a.raw.length);let c=i.at(-1);a.raw.length===1&&c!==void 0?c.raw+=`
|
`),this.blockTokens(e,this.tokens);for(let i=0;i<this.inlineQueue.length;i++){let n=this.inlineQueue[i];this.inlineTokens(n.src,n.tokens)}return this.inlineQueue=[],this.tokens}blockTokens(e,i=[],n=!1){var s,o,l;this.tokenizer.lexer=this,this.options.pedantic&&(e=e.replace(nt.tabCharGlobal," ").replace(nt.spaceLine,""));let r=1/0;for(;e;){if(e.length<r)r=e.length;else{this.infiniteLoopError(e.charCodeAt(0));break}let a;if((o=(s=this.options.extensions)==null?void 0:s.block)!=null&&o.some(c=>(a=c.call({lexer:this},e,i))?(e=e.substring(a.raw.length),i.push(a),!0):!1))continue;if(a=this.tokenizer.space(e)){e=e.substring(a.raw.length);let c=i.at(-1);a.raw.length===1&&c!==void 0?c.raw+=`
|
||||||
`:i.push(a);continue}if(a=this.tokenizer.code(e)){e=e.substring(a.raw.length);let c=i.at(-1);(c==null?void 0:c.type)==="paragraph"||(c==null?void 0:c.type)==="text"?(c.raw+=(c.raw.endsWith(`
|
`:i.push(a);continue}if(a=this.tokenizer.code(e)){e=e.substring(a.raw.length);let c=i.at(-1);(c==null?void 0:c.type)==="paragraph"||(c==null?void 0:c.type)==="text"?(c.raw+=(c.raw.endsWith(`
|
||||||
`)?"":`
|
`)?"":`
|
||||||
@@ -91,9 +91,9 @@ ${c}`:c;let f=this.lexer.state.top;if(this.lexer.state.top=!0,this.lexer.blockTo
|
|||||||
`+a.text,this.inlineQueue.pop(),this.inlineQueue.at(-1).src=c.text):i.push(a),n=h.length!==e.length,e=e.substring(a.raw.length);continue}if(a=this.tokenizer.text(e)){e=e.substring(a.raw.length);let c=i.at(-1);(c==null?void 0:c.type)==="text"?(c.raw+=(c.raw.endsWith(`
|
`+a.text,this.inlineQueue.pop(),this.inlineQueue.at(-1).src=c.text):i.push(a),n=h.length!==e.length,e=e.substring(a.raw.length);continue}if(a=this.tokenizer.text(e)){e=e.substring(a.raw.length);let c=i.at(-1);(c==null?void 0:c.type)==="text"?(c.raw+=(c.raw.endsWith(`
|
||||||
`)?"":`
|
`)?"":`
|
||||||
`)+a.raw,c.text+=`
|
`)+a.raw,c.text+=`
|
||||||
`+a.text,this.inlineQueue.pop(),this.inlineQueue.at(-1).src=c.text):i.push(a);continue}if(e){this.infiniteLoopError(e.charCodeAt(0));break}}return this.state.top=!0,i}inline(e,i=[]){return this.inlineQueue.push({src:e,tokens:i}),i}inlineTokens(e,i=[]){var h,c,f,u,d,p;this.tokenizer.lexer=this;let n=e,r=null;if(this.tokens.links){let g=Object.keys(this.tokens.links);if(g.length>0)for(;(r=this.tokenizer.rules.inline.reflinkSearch.exec(n))!==null;)g.includes(r[0].slice(r[0].lastIndexOf("[")+1,-1))&&(n=n.slice(0,r.index)+"["+"a".repeat(r[0].length-2)+"]"+n.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex))}for(;(r=this.tokenizer.rules.inline.anyPunctuation.exec(n))!==null;)n=n.slice(0,r.index)+"++"+n.slice(this.tokenizer.rules.inline.anyPunctuation.lastIndex);let s;for(;(r=this.tokenizer.rules.inline.blockSkip.exec(n))!==null;)s=r[2]?r[2].length:0,n=n.slice(0,r.index+s)+"["+"a".repeat(r[0].length-s-2)+"]"+n.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);n=(f=(c=(h=this.options.hooks)==null?void 0:h.emStrongMask)==null?void 0:c.call({lexer:this},n))!=null?f:n;let o=!1,l="",a=1/0;for(;e;){if(e.length<a)a=e.length;else{this.infiniteLoopError(e.charCodeAt(0));break}o||(l=""),o=!1;let g;if((d=(u=this.options.extensions)==null?void 0:u.inline)!=null&&d.some(b=>(g=b.call({lexer:this},e,i))?(e=e.substring(g.raw.length),i.push(g),!0):!1))continue;if(g=this.tokenizer.escape(e)){e=e.substring(g.raw.length),i.push(g);continue}if(g=this.tokenizer.tag(e)){e=e.substring(g.raw.length),i.push(g);continue}if(g=this.tokenizer.link(e)){e=e.substring(g.raw.length),i.push(g);continue}if(g=this.tokenizer.reflink(e,this.tokens.links)){e=e.substring(g.raw.length);let b=i.at(-1);g.type==="text"&&(b==null?void 0:b.type)==="text"?(b.raw+=g.raw,b.text+=g.text):i.push(g);continue}if(g=this.tokenizer.emStrong(e,n,l)){e=e.substring(g.raw.length),i.push(g);continue}if(g=this.tokenizer.codespan(e)){e=e.substring(g.raw.length),i.push(g);continue}if(g=this.tokenizer.br(e)){e=e.substring(g.raw.length),i.push(g);continue}if(g=this.tokenizer.del(e,n,l)){e=e.substring(g.raw.length),i.push(g);continue}if(g=this.tokenizer.autolink(e)){e=e.substring(g.raw.length),i.push(g);continue}if(!this.state.inLink&&(g=this.tokenizer.url(e))){e=e.substring(g.raw.length),i.push(g);continue}let m=e;if((p=this.options.extensions)!=null&&p.startInline){let b=1/0,y=e.slice(1),x;this.options.extensions.startInline.forEach(Q=>{x=Q.call({lexer:this},y),typeof x=="number"&&x>=0&&(b=Math.min(b,x))}),b<1/0&&b>=0&&(m=e.substring(0,b+1))}if(g=this.tokenizer.inlineText(m)){e=e.substring(g.raw.length),g.raw.slice(-1)!=="_"&&(l=g.raw.slice(-1)),o=!0;let b=i.at(-1);(b==null?void 0:b.type)==="text"?(b.raw+=g.raw,b.text+=g.text):i.push(g);continue}if(e){this.infiniteLoopError(e.charCodeAt(0));break}}return i}infiniteLoopError(e){let i="Infinite loop on byte: "+e;if(this.options.silent)console.error(i);else throw new Error(i)}},tc=class{constructor(t){J(this,"options");J(this,"parser");this.options=t||Fn}space(t){return""}code({text:t,lang:e,escaped:i}){var s;let n=(s=(e||"").match(nt.notSpaceStart))==null?void 0:s[0],r=t.replace(nt.endingNewline,"")+`
|
`+a.text,this.inlineQueue.pop(),this.inlineQueue.at(-1).src=c.text):i.push(a);continue}if(e){this.infiniteLoopError(e.charCodeAt(0));break}}return this.state.top=!0,i}inline(e,i=[]){return this.inlineQueue.push({src:e,tokens:i}),i}inlineTokens(e,i=[]){var h,c,f,u,d,p;this.tokenizer.lexer=this;let n=e,r=null;if(this.tokens.links){let g=Object.keys(this.tokens.links);if(g.length>0)for(;(r=this.tokenizer.rules.inline.reflinkSearch.exec(n))!==null;)g.includes(r[0].slice(r[0].lastIndexOf("[")+1,-1))&&(n=n.slice(0,r.index)+"["+"a".repeat(r[0].length-2)+"]"+n.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex))}for(;(r=this.tokenizer.rules.inline.anyPunctuation.exec(n))!==null;)n=n.slice(0,r.index)+"++"+n.slice(this.tokenizer.rules.inline.anyPunctuation.lastIndex);let s;for(;(r=this.tokenizer.rules.inline.blockSkip.exec(n))!==null;)s=r[2]?r[2].length:0,n=n.slice(0,r.index+s)+"["+"a".repeat(r[0].length-s-2)+"]"+n.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);n=(f=(c=(h=this.options.hooks)==null?void 0:h.emStrongMask)==null?void 0:c.call({lexer:this},n))!=null?f:n;let o=!1,l="",a=1/0;for(;e;){if(e.length<a)a=e.length;else{this.infiniteLoopError(e.charCodeAt(0));break}o||(l=""),o=!1;let g;if((d=(u=this.options.extensions)==null?void 0:u.inline)!=null&&d.some(b=>(g=b.call({lexer:this},e,i))?(e=e.substring(g.raw.length),i.push(g),!0):!1))continue;if(g=this.tokenizer.escape(e)){e=e.substring(g.raw.length),i.push(g);continue}if(g=this.tokenizer.tag(e)){e=e.substring(g.raw.length),i.push(g);continue}if(g=this.tokenizer.link(e)){e=e.substring(g.raw.length),i.push(g);continue}if(g=this.tokenizer.reflink(e,this.tokens.links)){e=e.substring(g.raw.length);let b=i.at(-1);g.type==="text"&&(b==null?void 0:b.type)==="text"?(b.raw+=g.raw,b.text+=g.text):i.push(g);continue}if(g=this.tokenizer.emStrong(e,n,l)){e=e.substring(g.raw.length),i.push(g);continue}if(g=this.tokenizer.codespan(e)){e=e.substring(g.raw.length),i.push(g);continue}if(g=this.tokenizer.br(e)){e=e.substring(g.raw.length),i.push(g);continue}if(g=this.tokenizer.del(e,n,l)){e=e.substring(g.raw.length),i.push(g);continue}if(g=this.tokenizer.autolink(e)){e=e.substring(g.raw.length),i.push(g);continue}if(!this.state.inLink&&(g=this.tokenizer.url(e))){e=e.substring(g.raw.length),i.push(g);continue}let m=e;if((p=this.options.extensions)!=null&&p.startInline){let b=1/0,y=e.slice(1),S;this.options.extensions.startInline.forEach(v=>{S=v.call({lexer:this},y),typeof S=="number"&&S>=0&&(b=Math.min(b,S))}),b<1/0&&b>=0&&(m=e.substring(0,b+1))}if(g=this.tokenizer.inlineText(m)){e=e.substring(g.raw.length),g.raw.slice(-1)!=="_"&&(l=g.raw.slice(-1)),o=!0;let b=i.at(-1);(b==null?void 0:b.type)==="text"?(b.raw+=g.raw,b.text+=g.text):i.push(g);continue}if(e){this.infiniteLoopError(e.charCodeAt(0));break}}return i}infiniteLoopError(e){let i="Infinite loop on byte: "+e;if(this.options.silent)console.error(i);else throw new Error(i)}},rc=class{constructor(t){K(this,"options");K(this,"parser");this.options=t||Un}space(t){return""}code({text:t,lang:e,escaped:i}){var s;let n=(s=(e||"").match(nt.notSpaceStart))==null?void 0:s[0],r=t.replace(nt.endingNewline,"")+`
|
||||||
`;return n?'<pre><code class="language-'+mi(n)+'">'+(i?r:mi(r,!0))+`</code></pre>
|
`;return n?'<pre><code class="language-'+bi(n)+'">'+(i?r:bi(r,!0))+`</code></pre>
|
||||||
`:"<pre><code>"+(i?r:mi(r,!0))+`</code></pre>
|
`:"<pre><code>"+(i?r:bi(r,!0))+`</code></pre>
|
||||||
`}blockquote({tokens:t}){return`<blockquote>
|
`}blockquote({tokens:t}){return`<blockquote>
|
||||||
${this.parser.parse(t)}</blockquote>
|
${this.parser.parse(t)}</blockquote>
|
||||||
`}html({text:t}){return t}def(t){return""}heading({tokens:t,depth:e}){return`<h${e}>${this.parser.parseInline(t)}</h${e}>
|
`}html({text:t}){return t}def(t){return""}heading({tokens:t,depth:e}){return`<h${e}>${this.parser.parseInline(t)}</h${e}>
|
||||||
@@ -109,8 +109,8 @@ ${this.parser.parse(t)}</blockquote>
|
|||||||
`}tablerow({text:t}){return`<tr>
|
`}tablerow({text:t}){return`<tr>
|
||||||
${t}</tr>
|
${t}</tr>
|
||||||
`}tablecell(t){let e=this.parser.parseInline(t.tokens),i=t.header?"th":"td";return(t.align?`<${i} align="${t.align}">`:`<${i}>`)+e+`</${i}>
|
`}tablecell(t){let e=this.parser.parseInline(t.tokens),i=t.header?"th":"td";return(t.align?`<${i} align="${t.align}">`:`<${i}>`)+e+`</${i}>
|
||||||
`}strong({tokens:t}){return`<strong>${this.parser.parseInline(t)}</strong>`}em({tokens:t}){return`<em>${this.parser.parseInline(t)}</em>`}codespan({text:t}){return`<code>${mi(t,!0)}</code>`}br(t){return"<br>"}del({tokens:t}){return`<del>${this.parser.parseInline(t)}</del>`}link({href:t,title:e,tokens:i}){let n=this.parser.parseInline(i),r=jx(t);if(r===null)return n;t=r;let s='<a href="'+t+'"';return e&&(s+=' title="'+mi(e)+'"'),s+=">"+n+"</a>",s}image({href:t,title:e,text:i,tokens:n}){n&&(i=this.parser.parseInline(n,this.parser.textRenderer));let r=jx(t);if(r===null)return mi(i);t=r;let s=`<img src="${t}" alt="${mi(i)}"`;return e&&(s+=` title="${mi(e)}"`),s+=">",s}text(t){return"tokens"in t&&t.tokens?this.parser.parseInline(t.tokens):"escaped"in t&&t.escaped?t.text:mi(t.text)}},Jp=class{strong({text:t}){return t}em({text:t}){return t}codespan({text:t}){return t}del({text:t}){return t}html({text:t}){return t}text({text:t}){return t}link({text:t}){return""+t}image({text:t}){return""+t}br(){return""}checkbox({raw:t}){return t}},ei=class Yp{constructor(e){J(this,"options");J(this,"renderer");J(this,"textRenderer");this.options=e||Fn,this.options.renderer=this.options.renderer||new tc,this.renderer=this.options.renderer,this.renderer.options=this.options,this.renderer.parser=this,this.textRenderer=new Jp}static parse(e,i){return new Yp(i).parse(e)}static parseInline(e,i){return new Yp(i).parseInline(e)}parse(e){var n,r;this.renderer.parser=this;let i="";for(let s=0;s<e.length;s++){let o=e[s];if((r=(n=this.options.extensions)==null?void 0:n.renderers)!=null&&r[o.type]){let a=o,h=this.options.extensions.renderers[a.type].call({parser:this},a);if(h!==!1||!["space","hr","heading","code","table","blockquote","list","html","def","paragraph","text"].includes(a.type)){i+=h||"";continue}}let l=o;switch(l.type){case"space":{i+=this.renderer.space(l);break}case"hr":{i+=this.renderer.hr(l);break}case"heading":{i+=this.renderer.heading(l);break}case"code":{i+=this.renderer.code(l);break}case"table":{i+=this.renderer.table(l);break}case"blockquote":{i+=this.renderer.blockquote(l);break}case"list":{i+=this.renderer.list(l);break}case"checkbox":{i+=this.renderer.checkbox(l);break}case"html":{i+=this.renderer.html(l);break}case"def":{i+=this.renderer.def(l);break}case"paragraph":{i+=this.renderer.paragraph(l);break}case"text":{i+=this.renderer.text(l);break}default:{let a='Token with "'+l.type+'" type was not found.';if(this.options.silent)return console.error(a),"";throw new Error(a)}}}return i}parseInline(e,i=this.renderer){var r,s;this.renderer.parser=this;let n="";for(let o=0;o<e.length;o++){let l=e[o];if((s=(r=this.options.extensions)==null?void 0:r.renderers)!=null&&s[l.type]){let h=this.options.extensions.renderers[l.type].call({parser:this},l);if(h!==!1||!["escape","html","link","image","strong","em","codespan","br","del","text"].includes(l.type)){n+=h||"";continue}}let a=l;switch(a.type){case"escape":{n+=i.text(a);break}case"html":{n+=i.html(a);break}case"link":{n+=i.link(a);break}case"image":{n+=i.image(a);break}case"checkbox":{n+=i.checkbox(a);break}case"strong":{n+=i.strong(a);break}case"em":{n+=i.em(a);break}case"codespan":{n+=i.codespan(a);break}case"br":{n+=i.br(a);break}case"del":{n+=i.del(a);break}case"text":{n+=i.text(a);break}default:{let h='Token with "'+a.type+'" type was not found.';if(this.options.silent)return console.error(h),"";throw new Error(h)}}}return n}},Ka,ko=(Ka=class{constructor(t){J(this,"options");J(this,"block");this.options=t||Fn}preprocess(t){return t}postprocess(t){return t}processAllTokens(t){return t}emStrongMask(t){return t}provideLexer(t=this.block){return t?Jt.lex:Jt.lexInline}provideParser(t=this.block){return t?ei.parse:ei.parseInline}},J(Ka,"passThroughHooks",new Set(["preprocess","postprocess","processAllTokens","emStrongMask"])),J(Ka,"passThroughHooksRespectAsync",new Set(["preprocess","postprocess","processAllTokens"])),Ka),bL=class{constructor(...t){J(this,"defaults",qp());J(this,"options",this.setOptions);J(this,"parse",this.parseMarkdown(!0));J(this,"parseInline",this.parseMarkdown(!1));J(this,"Parser",ei);J(this,"Renderer",tc);J(this,"TextRenderer",Jp);J(this,"Lexer",Jt);J(this,"Tokenizer",ec);J(this,"Hooks",ko);this.use(...t)}walkTokens(t,e){var n,r;let i=[];for(let s of t)switch(i=i.concat(e.call(this,s)),s.type){case"table":{let o=s;for(let l of o.header)i=i.concat(this.walkTokens(l.tokens,e));for(let l of o.rows)for(let a of l)i=i.concat(this.walkTokens(a.tokens,e));break}case"list":{let o=s;i=i.concat(this.walkTokens(o.items,e));break}default:{let o=s;(r=(n=this.defaults.extensions)==null?void 0:n.childTokens)!=null&&r[o.type]?this.defaults.extensions.childTokens[o.type].forEach(l=>{let a=o[l].flat(1/0);i=i.concat(this.walkTokens(a,e))}):o.tokens&&(i=i.concat(this.walkTokens(o.tokens,e)))}}return i}use(...t){let e=this.defaults.extensions||{renderers:{},childTokens:{}};return t.forEach(i=>{let n={...i};if(n.async=this.defaults.async||n.async||!1,i.extensions&&(i.extensLine truncated
|
`}strong({tokens:t}){return`<strong>${this.parser.parseInline(t)}</strong>`}em({tokens:t}){return`<em>${this.parser.parseInline(t)}</em>`}codespan({text:t}){return`<code>${bi(t,!0)}</code>`}br(t){return"<br>"}del({tokens:t}){return`<del>${this.parser.parseInline(t)}</del>`}link({href:t,title:e,tokens:i}){let n=this.parser.parseInline(i),r=Wx(t);if(r===null)return n;t=r;let s='<a href="'+t+'"';return e&&(s+=' title="'+bi(e)+'"'),s+=">"+n+"</a>",s}image({href:t,title:e,text:i,tokens:n}){n&&(i=this.parser.parseInline(n,this.parser.textRenderer));let r=Wx(t);if(r===null)return bi(i);t=r;let s=`<img src="${t}" alt="${bi(i)}"`;return e&&(s+=` title="${bi(e)}"`),s+=">",s}text(t){return"tokens"in t&&t.tokens?this.parser.parseInline(t.tokens):"escaped"in t&&t.escaped?t.text:bi(t.text)}},ig=class{strong({text:t}){return t}em({text:t}){return t}codespan({text:t}){return t}del({text:t}){return t}html({text:t}){return t}text({text:t}){return t}link({text:t}){return""+t}image({text:t}){return""+t}br(){return""}checkbox({raw:t}){return t}},ti=class Vp{constructor(e){K(this,"options");K(this,"renderer");K(this,"textRenderer");this.options=e||Un,this.options.renderer=this.options.renderer||new rc,this.renderer=this.options.renderer,this.renderer.options=this.options,this.renderer.parser=this,this.textRenderer=new ig}static parse(e,i){return new Vp(i).parse(e)}static parseInline(e,i){return new Vp(i).parseInline(e)}parse(e){var n,r;this.renderer.parser=this;let i="";for(let s=0;s<e.length;s++){let o=e[s];if((r=(n=this.options.extensions)==null?void 0:n.renderers)!=null&&r[o.type]){let a=o,h=this.options.extensions.renderers[a.type].call({parser:this},a);if(h!==!1||!["space","hr","heading","code","table","blockquote","list","html","def","paragraph","text"].includes(a.type)){i+=h||"";continue}}let l=o;switch(l.type){case"space":{i+=this.renderer.space(l);break}case"hr":{i+=this.renderer.hr(l);break}case"heading":{i+=this.renderer.heading(l);break}case"code":{i+=this.renderer.code(l);break}case"table":{i+=this.renderer.table(l);break}case"blockquote":{i+=this.renderer.blockquote(l);break}case"list":{i+=this.renderer.list(l);break}case"checkbox":{i+=this.renderer.checkbox(l);break}case"html":{i+=this.renderer.html(l);break}case"def":{i+=this.renderer.def(l);break}case"paragraph":{i+=this.renderer.paragraph(l);break}case"text":{i+=this.renderer.text(l);break}default:{let a='Token with "'+l.type+'" type was not found.';if(this.options.silent)return console.error(a),"";throw new Error(a)}}}return i}parseInline(e,i=this.renderer){var r,s;this.renderer.parser=this;let n="";for(let o=0;o<e.length;o++){let l=e[o];if((s=(r=this.options.extensions)==null?void 0:r.renderers)!=null&&s[l.type]){let h=this.options.extensions.renderers[l.type].call({parser:this},l);if(h!==!1||!["escape","html","link","image","strong","em","codespan","br","del","text"].includes(l.type)){n+=h||"";continue}}let a=l;switch(a.type){case"escape":{n+=i.text(a);break}case"html":{n+=i.html(a);break}case"link":{n+=i.link(a);break}case"image":{n+=i.image(a);break}case"checkbox":{n+=i.checkbox(a);break}case"strong":{n+=i.strong(a);break}case"em":{n+=i.em(a);break}case"codespan":{n+=i.codespan(a);break}case"br":{n+=i.br(a);break}case"del":{n+=i.del(a);break}case"text":{n+=i.text(a);break}default:{let h='Token with "'+a.type+'" type was not found.';if(this.options.silent)return console.error(h),"";throw new Error(h)}}}return n}},tc,wo=(tc=class{constructor(t){K(this,"options");K(this,"block");this.options=t||Un}preprocess(t){return t}postprocess(t){return t}processAllTokens(t){return t}emStrongMask(t){return t}provideLexer(t=this.block){return t?ei.lex:ei.lexInline}provideParser(t=this.block){return t?ti.parse:ti.parseInline}},K(tc,"passThroughHooks",new Set(["preprocess","postprocess","processAllTokens","emStrongMask"])),K(tc,"passThroughHooksRespectAsync",new Set(["preprocess","postprocess","processAllTokens"])),tc),SL=class{constructor(...t){K(this,"defaults",Gp());K(this,"options",this.setOptions);K(this,"parse",this.parseMarkdown(!0));K(this,"parseInline",this.parseMarkdown(!1));K(this,"Parser",ti);K(this,"Renderer",rc);K(this,"TextRenderer",ig);K(this,"Lexer",ei);K(this,"Tokenizer",nc);K(this,"Hooks",wo);this.use(...t)}walkTokens(t,e){var n,r;let i=[];for(let s of t)switch(i=i.concat(e.call(this,s)),s.type){case"table":{let o=s;for(let l of o.header)i=i.concat(this.walkTokens(l.tokens,e));for(let l of o.rows)for(let a of l)i=i.concat(this.walkTokens(a.tokens,e));break}case"list":{let o=s;i=i.concat(this.walkTokens(o.items,e));break}default:{let o=s;(r=(n=this.defaults.extensions)==null?void 0:n.childTokens)!=null&&r[o.type]?this.defaults.extensions.childTokens[o.type].forEach(l=>{let a=o[l].flat(1/0);i=i.concat(this.walkTokens(a,e))}):o.tokens&&(i=i.concat(this.walkTokens(o.tokens,e)))}}return i}use(...t){let e=this.defaults.extensions||{renderers:{},childTokens:{}};return t.forEach(i=>{let n={...i};if(n.async=this.defaults.async||n.async||!1,i.extensions&&(i.extensLine truncated
|
||||||
Please report this to https://github.com/markedjs/marked.`,t){let n="<p>An error occurred:</p><pre>"+mi(i.message+"",!0)+"</pre>";return e?Promise.resolve(n):n}if(e)return Promise.reject(i);throw i}}},Un=new bL;function de(t,e){return Un.parse(t,e)}de.options=de.setOptions=function(t){return Un.setOptions(t),de.defaults=Un.defaults,Wx(de.defaults),de};de.getDefaults=qp;de.defaults=Fn;de.use=function(...t){return Un.use(...t),de.defaults=Un.defaults,Wx(de.defaults),de};de.walkTokens=function(t,e){return Un.walkTokens(t,e)};de.parseInline=Un.parseInline;de.Parser=ei;de.parser=ei.parse;de.Renderer=tc;de.TextRenderer=Jp;de.Lexer=Jt;de.lexer=Jt.lex;de.Tokenizer=ec;de.Hooks=ko;de.parse=de;var gZ=de.options,OZ=de.setOptions,mZ=de.use,bZ=de.walkTokens,yZ=de.parseInline;var SZ=ei.parse,xZ=Jt.lex;var kk=Yk(xk(),1);var Ei=kk.default;function ag(t){let e="true false yes no null",i="[\\w#;/?:@&=+$,.~*'()[\\]]+",n={className:"attr",variants:[{begin:/[\w*@][\w*@ :()\./-]*:(?=[ \t]|$)/},{begin:/"[\w*@][\w*@ :()\./-]*":(?=[ \t]|$)/},{begin:/'[\w*@][\w*@ :()\./-]*':(?=[ \t]|$)/}]},r={className:"template-variable",variants:[{begin:/\{\{/,end:/\}\}/},{begin:/%\{/,end:/\}/}]},s={className:"string",relevance:0,begin:/'/,end:/'/,contains:[{match:/''/,scope:"char.escape",relevance:0}]},o={className:"string",relevance:0,variants:[{begin:/"/,end:/"/},{begin:/\S+/}],contains:[t.BACKSLASH_ESCAPE,r]},l=t.inherit(o,{variants:[{begin:/'/,end:/'/,contains:[{begin:/''/,relevance:0}]},{begin:/"/,end:/"/},{begin:/[^\s,{}[\]]+/}]}),u={className:"number",begin:"\\b"+"[0-9]{4}(-[0-9][0-9]){0,2}"+"([Tt \\t][0-9][0-9]?(:[0-9][0-9]){2})?"+"(\\.[0-9]*)?"+"([ \\t])*(Z|[-+][0-9][0-9]?(:[0-9][0-9])?)?"+"\\b"},d={end:",",endsWithParent:!0,excludeEnd:!0,keywords:e,relevance:0},p={begin:/\{/,end:/\}/,contains:[d],illegal:"\\n",relevance:0},g={begin:"\\[",end:"\\]",contains:[d],illegal:"\\n",relevance:0},m=[n,{className:"meta",begin:"^---\\s*$",relevance:10},{className:"string",begin:"[\\|>]([1-9]?[+-])?[ ]*\\n( +)[^ ][^\\n]*\\n(\\2[^\\n]+\\n?)*"},{begin:"<%[%=-]?",end:"[%-]?%>",subLanguage:"ruby",excludeBegin:!0,excludeEnd:!0,relevance:0},{className:"type",begin:"!\\w+!"+i},{className:"type",begin:"!<"+i+">"},{className:"type",begin:"!"+i},{className:"type",begin:"!!"+i},{className:"meta",begin:"&"+t.UNDERSCORE_IDENT_RE+"$"},{className:"meta",begin:"\\*"+t.UNDERSCORE_IDENT_RE+"$"},{className:"bullet",begin:"-(?=[ ]|$)",relevance:0},t.HASH_COMMENT_MODE,{beginKeywords:e,keywords:{literal:e}},u,{className:"number",begin:t.C_NUMBER_RE+"\\b",relevance:0},p,g,s,o],b=[...m];return b.pop(),b.push(l),d.contains=b,{name:"YAML",case_insensitive:!0,aliases:["yml"],contains:m}}function ac(t){let e=t.regex,i={},n={begin:/\$\{/,end:/\}/,contains:["self",{begin:/:-/,contains:[i]}]};Object.assign(i,{className:"variable",variants:[{begin:e.concat(/\$[\w\d#@][\w\d_]*/,"(?![\\w\\d])(?![$])")},n]});let r={className:"subst",begin:/\$\(/,end:/\)/,contains:[t.BACKSLASH_ESCAPE]},s=t.inherit(t.COMMENT(),{match:[/(^|\s)/,/#.*$/],scope:{2:"comment"}}),o={begin:/<<-?\s*(?=\w+)/,starts:{contains:[t.END_SAME_AS_BEGIN({begin:/(\w+)/,end:/(\w+)/,className:"string"})]}},l={className:"string",begin:/"/,end:/"/,contains:[t.BACKSLASH_ESCAPE,i,r]};r.contains.push(l);let a={match:/\\"/},h={className:"string",begin:/'/,end:/'/},c={match:/\\'/},f={begin:/\$?\(\(/,end:/\)\)/,contains:[{begin:/\d+#[0-9a-f]+/,className:"number"},t.NUMBER_MODE,i]},u=["fish","bash","zsh","sh","csh","ksh","tcsh","dash","scsh"],d=t.SHEBANG({binary:`(${u.join("|")})`,relevance:10}),p={className:"function",begin:/\w[\w\d_]*\s*\(\s*\)\s*\{/,returnBegin:!0,contains:[t.inherit(t.TITLE_MODE,{begin:/\w[\w\d_]*/})],relevance:0},g=["if","then","else","elif","fi","time","for","while","until","in","do","done","case","esac","coproc","function","select"],m=["true","false"],b={match:/(\/[a-z._-]+)+/},y=["break","cd","continue","eval","exec","exit","export","getopts","hash","pwd","readonly","return","shift","test","times","trap","umask","unset"],x=["alias","bind","builtin","caller","command","declare","echo","enable","help","let","local","logout","mapfile","printf","read","readarray","source","sudo","type","typeset","ulimit","unalias"],Q=["autoload","bg","bindkey","bye","cap","chdir","clone","comparguments","compcall","compctl","compdescribe","compfiles","compgroups","compquote","comptags","comptry","compvalues","dirs","disable","disown","echotc","echoti","emulate","fc","fg","float","functions","getcap","getln","history","integer","jobs","kill","limit","log","noglob","popd","print","pushd","pushln","rehash","sched","setcap","setopt","stat","suspend","ttyctl","unfunction","unhash","unlimit","unsetopt","vared","wait","whence","where","which","zcompile","zformat","zftp","zle","zmodload","zparseopts","zprof","zpty","zregexparse","zsocket","zstyle","ztcp"],S=["chcon","chgrp","chown","chmod","cp","dd","df","dir","dircolors","ln","ls","mkdir","mkfifo","mknod","mktemp","mv","realpath","rm","rmdir","shred","sync","touch","truncate","vdir","
Line truncated
|
Please report this to https://github.com/markedjs/marked.`,t){let n="<p>An error occurred:</p><pre>"+bi(i.message+"",!0)+"</pre>";return e?Promise.resolve(n):n}if(e)return Promise.reject(i);throw i}}},Gn=new SL;function pe(t,e){return Gn.parse(t,e)}pe.options=pe.setOptions=function(t){return Gn.setOptions(t),pe.defaults=Gn.defaults,Fx(pe.defaults),pe};pe.getDefaults=Gp;pe.defaults=Un;pe.use=function(...t){return Gn.use(...t),pe.defaults=Gn.defaults,Fx(pe.defaults),pe};pe.walkTokens=function(t,e){return Gn.walkTokens(t,e)};pe.parseInline=Gn.parseInline;pe.Parser=ti;pe.parser=ti.parse;pe.Renderer=rc;pe.TextRenderer=ig;pe.Lexer=ei;pe.lexer=ei.lex;pe.Tokenizer=nc;pe.Hooks=wo;pe.parse=pe;var gZ=pe.options,OZ=pe.setOptions,mZ=pe.use,bZ=pe.walkTokens,yZ=pe.parseInline;var SZ=ti.parse,xZ=ei.lex;var Pk=Wk(Qk(),1);var Mi=Pk.default;function fg(t){let e="true false yes no null",i="[\\w#;/?:@&=+$,.~*'()[\\]]+",n={className:"attr",variants:[{begin:/[\w*@][\w*@ :()\./-]*:(?=[ \t]|$)/},{begin:/"[\w*@][\w*@ :()\./-]*":(?=[ \t]|$)/},{begin:/'[\w*@][\w*@ :()\./-]*':(?=[ \t]|$)/}]},r={className:"template-variable",variants:[{begin:/\{\{/,end:/\}\}/},{begin:/%\{/,end:/\}/}]},s={className:"string",relevance:0,begin:/'/,end:/'/,contains:[{match:/''/,scope:"char.escape",relevance:0}]},o={className:"string",relevance:0,variants:[{begin:/"/,end:/"/},{begin:/\S+/}],contains:[t.BACKSLASH_ESCAPE,r]},l=t.inherit(o,{variants:[{begin:/'/,end:/'/,contains:[{begin:/''/,relevance:0}]},{begin:/"/,end:/"/},{begin:/[^\s,{}[\]]+/}]}),u={className:"number",begin:"\\b"+"[0-9]{4}(-[0-9][0-9]){0,2}"+"([Tt \\t][0-9][0-9]?(:[0-9][0-9]){2})?"+"(\\.[0-9]*)?"+"([ \\t])*(Z|[-+][0-9][0-9]?(:[0-9][0-9])?)?"+"\\b"},d={end:",",endsWithParent:!0,excludeEnd:!0,keywords:e,relevance:0},p={begin:/\{/,end:/\}/,contains:[d],illegal:"\\n",relevance:0},g={begin:"\\[",end:"\\]",contains:[d],illegal:"\\n",relevance:0},m=[n,{className:"meta",begin:"^---\\s*$",relevance:10},{className:"string",begin:"[\\|>]([1-9]?[+-])?[ ]*\\n( +)[^ ][^\\n]*\\n(\\2[^\\n]+\\n?)*"},{begin:"<%[%=-]?",end:"[%-]?%>",subLanguage:"ruby",excludeBegin:!0,excludeEnd:!0,relevance:0},{className:"type",begin:"!\\w+!"+i},{className:"type",begin:"!<"+i+">"},{className:"type",begin:"!"+i},{className:"type",begin:"!!"+i},{className:"meta",begin:"&"+t.UNDERSCORE_IDENT_RE+"$"},{className:"meta",begin:"\\*"+t.UNDERSCORE_IDENT_RE+"$"},{className:"bullet",begin:"-(?=[ ]|$)",relevance:0},t.HASH_COMMENT_MODE,{beginKeywords:e,keywords:{literal:e}},u,{className:"number",begin:t.C_NUMBER_RE+"\\b",relevance:0},p,g,s,o],b=[...m];return b.pop(),b.push(l),d.contains=b,{name:"YAML",case_insensitive:!0,aliases:["yml"],contains:m}}function fc(t){let e=t.regex,i={},n={begin:/\$\{/,end:/\}/,contains:["self",{begin:/:-/,contains:[i]}]};Object.assign(i,{className:"variable",variants:[{begin:e.concat(/\$[\w\d#@][\w\d_]*/,"(?![\\w\\d])(?![$])")},n]});let r={className:"subst",begin:/\$\(/,end:/\)/,contains:[t.BACKSLASH_ESCAPE]},s=t.inherit(t.COMMENT(),{match:[/(^|\s)/,/#.*$/],scope:{2:"comment"}}),o={begin:/<<-?\s*(?=\w+)/,starts:{contains:[t.END_SAME_AS_BEGIN({begin:/(\w+)/,end:/(\w+)/,className:"string"})]}},l={className:"string",begin:/"/,end:/"/,contains:[t.BACKSLASH_ESCAPE,i,r]};r.contains.push(l);let a={match:/\\"/},h={className:"string",begin:/'/,end:/'/},c={match:/\\'/},f={begin:/\$?\(\(/,end:/\)\)/,contains:[{begin:/\d+#[0-9a-f]+/,className:"number"},t.NUMBER_MODE,i]},u=["fish","bash","zsh","sh","csh","ksh","tcsh","dash","scsh"],d=t.SHEBANG({binary:`(${u.join("|")})`,relevance:10}),p={className:"function",begin:/\w[\w\d_]*\s*\(\s*\)\s*\{/,returnBegin:!0,contains:[t.inherit(t.TITLE_MODE,{begin:/\w[\w\d_]*/})],relevance:0},g=["if","then","else","elif","fi","time","for","while","until","in","do","done","case","esac","coproc","function","select"],m=["true","false"],b={match:/(\/[a-z._-]+)+/},y=["break","cd","continue","eval","exec","exit","export","getopts","hash","pwd","readonly","return","shift","test","times","trap","umask","unset"],S=["alias","bind","builtin","caller","command","declare","echo","enable","help","let","local","logout","mapfile","printf","read","readarray","source","sudo","type","typeset","ulimit","unalias"],v=["autoload","bg","bindkey","bye","cap","chdir","clone","comparguments","compcall","compctl","compdescribe","compfiles","compgroups","compquote","comptags","comptry","compvalues","dirs","disable","disown","echotc","echoti","emulate","fc","fg","float","functions","getcap","getln","history","integer","jobs","kill","limit","log","noglob","popd","print","pushd","pushln","rehash","sched","setcap","setopt","stat","suspend","ttyctl","unfunction","unhash","unlimit","unsetopt","vared","wait","whence","where","which","zcompile","zformat","zftp","zle","zmodload","zparseopts","zprof","zpty","zregexparse","zsocket","zstyle","ztcp"],x=["chcon","chgrp","chown","chmod","cp","dd","df","dir","dircolors","ln","ls","mkdir","mkfifo","mknod","mktemp","mv","realpath","rm","rmdir","shred","sync","touch","truncate","vdir","
Line truncated
|
||||||
display: block;
|
display: block;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
padding: 1em
|
padding: 1em
|
||||||
@@ -227,7 +227,7 @@ code.hljs {
|
|||||||
.hljs-tag {
|
.hljs-tag {
|
||||||
/* purposely ignored */
|
/* purposely ignored */
|
||||||
|
|
||||||
}`;var hg=`pre code.hljs {
|
}`;var dg=`pre code.hljs {
|
||||||
display: block;
|
display: block;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
padding: 1em
|
padding: 1em
|
||||||
@@ -343,14 +343,14 @@ code.hljs {
|
|||||||
.hljs-tag {
|
.hljs-tag {
|
||||||
/* purposely ignored */
|
/* purposely ignored */
|
||||||
|
|
||||||
}`;var Ce={timestamp:Pe.define(),bracket:Pe.define(),category:Pe.define(),logString:Pe.define(),logLink:Pe.define(),levelInfo:Pe.define(),levelWarning:Pe.define(),levelError:Pe.define(),levelDebug:Pe.define(),levelTip:Pe.define(),levelFatal:Pe.define(),levelWatchdog:Pe.define()};Ei.registerLanguage("yaml",ag);Ei.registerLanguage("yml",ag);Ei.registerLanguage("bash",ac);Ei.registerLanguage("sh",ac);Ei.registerLanguage("shell",ac);Ei.registerLanguage("json",wk);var hX=[{label:"port",type:"keyword",detail:"HTTP proxy port",info:"Invalid when mixed port is enabled"},{label:"socks-port",type:"keyword",detail:"SOCKS5 proxy port"},{label:"mixed-port",type:"keyword",detail:"HTTP/SOCKS mixed port",info:"Overrides port and socks-port when set"},{label:"redir-port",type:"keyword",detail:"Transparent proxy port"},{label:"tproxy-port",type:"keyword",detail:"TPROXY transparent proxy port"},{label:"mode",type:"keyword",detail:"Run mode: rule / global / direct"},{label:"log-level",type:"keyword",detail:"Log level: debug / info / warning / error / silent"},{label:"ipv6",type:"keyword",detail:"IPv6 traffic handling: true / false"},{label:"allow-lan",type:"keyword",detail:"Allow LAN connections: true / false"},{label:"bind-address",type:"keyword",detail:"Bind address, default *"},{label:"authentication",type:"keyword",detail:"HTTP/SOCKS authentication, array format"},{label:"external-controller",type:"keyword",detail:"RESTful API listen address"},{label:"external-ui",type:"keyword",detail:"Dashboard path"},{label:"secret",type:"keyword",detail:"API secret"},{label:"interface-name",type:"keyword",detail:"Outbound interface name"},{label:"routing-mark",type:"keyword",detail:"Routing mark"},{label:"hosts",type:"keyword",detail:"Custom hosts mapping"},{label:"profile",type:"keyword",detail:"Profiling configuration"},{label:"global-ua",type:"keyword",detail:"Global User-Agent"},{label:"unified-delay",type:"keyword",detail:"Unified delay: true / false"},{label:"tcp-concurrent",type:"keyword",detail:"TCP concurrent connections"},{label:"find-process-mode",type:"keyword",detail:"Find process mode: off / strict / always"},{label:"sniffing",type:"keyword",detail:"Domain sniffing: true / false"},{label:"keep-alive-interval",type:"keyword",detail:"TCP keep-alive interval (seconds)"},{label:"geodata-mode",type:"keyword",detail:"GEO data mode: true / false"},{label:"geodata-loader",type:"keyword",detail:"GEO loader: memconservative / standard"},{label:"geox-url",type:"keyword",detail:"GEOX custom URL template"},{label:"geosite",type:"keyword",detail:"GeoSite configuration"},{label:"geo-auto-update",type:"keyword",detail:"GEO auto update: true / false"},{label:"geo-update-interval",type:"keyword",detail:"GEO update interval (hours)"},{label:"tun",type:"keyword",detail:"TUN mode configuration"},{label:"enable",type:"property",detail:"Enable: true / false"},{label:"stack",type:"property",detail:"Protocol stack: system / gvisor / mixed"},{label:"device",type:"property",detail:"TUN device name"},{label:"dns-hijack",type:"property",detail:"DNS hijack address list"},{label:"auto-route",type:"property",detail:"Auto set route: true / false"},{label:"auto-detect-interface",type:"property",detail:"Auto detect interface: true / false"},{label:"mtu",type:"property",detail:"MTU value"},{label:"inet4-address",type:"property",detail:"IPv4 address range"},{label:"inet6-address",type:"property",detail:"IPv6 address range"},{label:"strict-route",type:"property",detail:"Strict route: true / false"},{label:"endpoint-independent-nat",type:"property",detail:"Endpoint-independent NAT: true / false"},{label:"udp-timeout",type:"property",detail:"UDP timeout"},{label:"dns",type:"keyword",detail:"DNS configuration"},{label:"nameserver",type:"property",detail:"DNS upstream servers"},{label:"fallback",type:"property",detail:"Fallback DNS servers"},{label:"fallback-filter",type:"property",detail:"Fallback filter configuration"},{label:"default-nameserver",type:"property",detail:"Default DNS servers"},{label:"nameserver-policy",type:"property",detail:"DNS by domain name"},{label:"proxy-server-nameserver",type:"property",detail:"Proxy DNS servers"},{label:"use-hosts",type:"property",detail:"Use hosts: true / false"},{label:"enhanced-mode",type:"property",detail:"DNS mode: normal / redir-host / fake-ip"},{label:"fake-ip-range",type:"property",detail:"Fake-IP address range"},{label:"fake-ip-filter",type:"property",detail:"Fake-IP filter domains"},{label:"type",type:"type",detail:"ss / ssr / vmess / trojan / snell / http / socks5 / hysteria / vless / tuic / wireguard"},{label:"server",type:"property",detail:"Server address"},{label:"name",type:"property",detail:"Proxy name"},{label:"password",type:"property",detail:"Password"},{label:"cipher",type:"property",detail:"Encryption method"},{label:"udp",type:"property",detail:"UDP relay: true / false"},{label:"xudp",type:"property",detail:"XUDP mode"},{label:"tfo",type:"property",detail:"TCP Fast Open: true / false"},{label:"mpt
Line truncated
|
}`;var Ae={timestamp:$e.define(),bracket:$e.define(),category:$e.define(),logString:$e.define(),logLink:$e.define(),levelInfo:$e.define(),levelWarning:$e.define(),levelError:$e.define(),levelDebug:$e.define(),levelTip:$e.define(),levelFatal:$e.define(),levelWatchdog:$e.define()};Mi.registerLanguage("yaml",fg);Mi.registerLanguage("yml",fg);Mi.registerLanguage("bash",fc);Mi.registerLanguage("sh",fc);Mi.registerLanguage("shell",fc);Mi.registerLanguage("json",$k);var uX=[{label:"port",type:"keyword",detail:"HTTP proxy port",info:"Invalid when mixed port is enabled"},{label:"socks-port",type:"keyword",detail:"SOCKS5 proxy port"},{label:"mixed-port",type:"keyword",detail:"HTTP/SOCKS mixed port",info:"Overrides port and socks-port when set"},{label:"redir-port",type:"keyword",detail:"Transparent proxy port"},{label:"tproxy-port",type:"keyword",detail:"TPROXY transparent proxy port"},{label:"mode",type:"keyword",detail:"Run mode: rule / global / direct"},{label:"log-level",type:"keyword",detail:"Log level: debug / info / warning / error / silent"},{label:"ipv6",type:"keyword",detail:"IPv6 traffic handling: true / false"},{label:"allow-lan",type:"keyword",detail:"Allow LAN connections: true / false"},{label:"bind-address",type:"keyword",detail:"Bind address, default *"},{label:"authentication",type:"keyword",detail:"HTTP/SOCKS authentication, array format"},{label:"external-controller",type:"keyword",detail:"RESTful API listen address"},{label:"external-ui",type:"keyword",detail:"Dashboard path"},{label:"secret",type:"keyword",detail:"API secret"},{label:"interface-name",type:"keyword",detail:"Outbound interface name"},{label:"routing-mark",type:"keyword",detail:"Routing mark"},{label:"hosts",type:"keyword",detail:"Custom hosts mapping"},{label:"profile",type:"keyword",detail:"Profiling configuration"},{label:"global-ua",type:"keyword",detail:"Global User-Agent"},{label:"unified-delay",type:"keyword",detail:"Unified delay: true / false"},{label:"tcp-concurrent",type:"keyword",detail:"TCP concurrent connections"},{label:"find-process-mode",type:"keyword",detail:"Find process mode: off / strict / always"},{label:"sniffing",type:"keyword",detail:"Domain sniffing: true / false"},{label:"keep-alive-interval",type:"keyword",detail:"TCP keep-alive interval (seconds)"},{label:"geodata-mode",type:"keyword",detail:"GEO data mode: true / false"},{label:"geodata-loader",type:"keyword",detail:"GEO loader: memconservative / standard"},{label:"geox-url",type:"keyword",detail:"GEOX custom URL template"},{label:"geosite",type:"keyword",detail:"GeoSite configuration"},{label:"geo-auto-update",type:"keyword",detail:"GEO auto update: true / false"},{label:"geo-update-interval",type:"keyword",detail:"GEO update interval (hours)"},{label:"tun",type:"keyword",detail:"TUN mode configuration"},{label:"enable",type:"property",detail:"Enable: true / false"},{label:"stack",type:"property",detail:"Protocol stack: system / gvisor / mixed"},{label:"device",type:"property",detail:"TUN device name"},{label:"dns-hijack",type:"property",detail:"DNS hijack address list"},{label:"auto-route",type:"property",detail:"Auto set route: true / false"},{label:"auto-detect-interface",type:"property",detail:"Auto detect interface: true / false"},{label:"mtu",type:"property",detail:"MTU value"},{label:"inet4-address",type:"property",detail:"IPv4 address range"},{label:"inet6-address",type:"property",detail:"IPv6 address range"},{label:"strict-route",type:"property",detail:"Strict route: true / false"},{label:"endpoint-independent-nat",type:"property",detail:"Endpoint-independent NAT: true / false"},{label:"udp-timeout",type:"property",detail:"UDP timeout"},{label:"dns",type:"keyword",detail:"DNS configuration"},{label:"nameserver",type:"property",detail:"DNS upstream servers"},{label:"fallback",type:"property",detail:"Fallback DNS servers"},{label:"fallback-filter",type:"property",detail:"Fallback filter configuration"},{label:"default-nameserver",type:"property",detail:"Default DNS servers"},{label:"nameserver-policy",type:"property",detail:"DNS by domain name"},{label:"proxy-server-nameserver",type:"property",detail:"Proxy DNS servers"},{label:"use-hosts",type:"property",detail:"Use hosts: true / false"},{label:"enhanced-mode",type:"property",detail:"DNS mode: normal / redir-host / fake-ip"},{label:"fake-ip-range",type:"property",detail:"Fake-IP address range"},{label:"fake-ip-filter",type:"property",detail:"Fake-IP filter domains"},{label:"type",type:"type",detail:"ss / ssr / vmess / trojan / snell / http / socks5 / hysteria / vless / tuic / wireguard"},{label:"server",type:"property",detail:"Server address"},{label:"name",type:"property",detail:"Proxy name"},{label:"password",type:"property",detail:"Password"},{label:"cipher",type:"property",detail:"Encryption method"},{label:"udp",type:"property",detail:"UDP relay: true / false"},{label:"xudp",type:"property",detail:"XUDP mode"},{label:"tfo",type:"property",detail:"TCP Fast Open: true / false"},{label:"mpt
Line truncated
|
||||||
mode: #{2}
|
mode: #{2}
|
||||||
log-level: #{3}
|
log-level: #{3}
|
||||||
allow-lan: #{4}
|
allow-lan: #{4}
|
||||||
bind-address: "#{5}"
|
bind-address: "#{5}"
|
||||||
ipv6: #{6}
|
ipv6: #{6}
|
||||||
external-controller: 0.0.0.0:9093
|
external-controller: 0.0.0.0:9093
|
||||||
#{}`,{label:"config-base",type:"snippet",detail:"Basic configuration"}),A(`- name: "#{1}"
|
#{}`,{label:"config-base",type:"snippet",detail:"Basic configuration"}),M(`- name: "#{1}"
|
||||||
type: ss
|
type: ss
|
||||||
server: "#{2}"
|
server: "#{2}"
|
||||||
port: #{3}
|
port: #{3}
|
||||||
@@ -364,7 +364,7 @@ external-controller: 0.0.0.0:9093
|
|||||||
# client-fingerprint: chrome
|
# client-fingerprint: chrome
|
||||||
# smux:
|
# smux:
|
||||||
# enabled: false
|
# enabled: false
|
||||||
#{}`,{label:"ss-template",type:"snippet",detail:"Shadowsocks node"}),A(`- name: "#{1}"
|
#{}`,{label:"ss-template",type:"snippet",detail:"Shadowsocks node"}),M(`- name: "#{1}"
|
||||||
type: ssr
|
type: ssr
|
||||||
server: "#{2}"
|
server: "#{2}"
|
||||||
port: #{3}
|
port: #{3}
|
||||||
@@ -375,7 +375,7 @@ external-controller: 0.0.0.0:9093
|
|||||||
# obfs-param: ""
|
# obfs-param: ""
|
||||||
# protocol-param: ""
|
# protocol-param: ""
|
||||||
# udp: true
|
# udp: true
|
||||||
#{}`,{label:"ssr-template",type:"snippet",detail:"ShadowsocksR node"}),A(`- name: "#{1}"
|
#{}`,{label:"ssr-template",type:"snippet",detail:"ShadowsocksR node"}),M(`- name: "#{1}"
|
||||||
type: vmess
|
type: vmess
|
||||||
server: "#{2}"
|
server: "#{2}"
|
||||||
port: #{3}
|
port: #{3}
|
||||||
@@ -392,7 +392,7 @@ external-controller: 0.0.0.0:9093
|
|||||||
# path: /
|
# path: /
|
||||||
# headers:
|
# headers:
|
||||||
# Host: ""
|
# Host: ""
|
||||||
#{}`,{label:"vmess-template",type:"snippet",detail:"VMess node"}),A(`- name: "#{1}"
|
#{}`,{label:"vmess-template",type:"snippet",detail:"VMess node"}),M(`- name: "#{1}"
|
||||||
type: vmess
|
type: vmess
|
||||||
server: "#{2}"
|
server: "#{2}"
|
||||||
port: #{3}
|
port: #{3}
|
||||||
@@ -406,7 +406,7 @@ external-controller: 0.0.0.0:9093
|
|||||||
# client-fingerprint: chrome
|
# client-fingerprint: chrome
|
||||||
grpc-opts:
|
grpc-opts:
|
||||||
grpc-service-name: "#{6}"
|
grpc-service-name: "#{6}"
|
||||||
#{}`,{label:"vmess-grpc",type:"snippet",detail:"VMess gRPC node"}),A(`- name: "#{1}"
|
#{}`,{label:"vmess-grpc",type:"snippet",detail:"VMess gRPC node"}),M(`- name: "#{1}"
|
||||||
type: trojan
|
type: trojan
|
||||||
server: "#{2}"
|
server: "#{2}"
|
||||||
port: #{3}
|
port: #{3}
|
||||||
@@ -418,7 +418,7 @@ external-controller: 0.0.0.0:9093
|
|||||||
# network: ws
|
# network: ws
|
||||||
# ws-opts:
|
# ws-opts:
|
||||||
# path: /
|
# path: /
|
||||||
#{}`,{label:"trojan-template",type:"snippet",detail:"Trojan node"}),A(`- name: "#{1}"
|
#{}`,{label:"trojan-template",type:"snippet",detail:"Trojan node"}),M(`- name: "#{1}"
|
||||||
type: vless
|
type: vless
|
||||||
server: "#{2}"
|
server: "#{2}"
|
||||||
port: #{3}
|
port: #{3}
|
||||||
@@ -432,7 +432,7 @@ external-controller: 0.0.0.0:9093
|
|||||||
# reality-opts:
|
# reality-opts:
|
||||||
# public-key: ""
|
# public-key: ""
|
||||||
# short-id: ""
|
# short-id: ""
|
||||||
#{}`,{label:"vless-template",type:"snippet",detail:"VLESS node"}),A(`- name: "#{1}"
|
#{}`,{label:"vless-template",type:"snippet",detail:"VLESS node"}),M(`- name: "#{1}"
|
||||||
type: vless
|
type: vless
|
||||||
server: "#{2}"
|
server: "#{2}"
|
||||||
port: #{3}
|
port: #{3}
|
||||||
@@ -446,7 +446,7 @@ external-controller: 0.0.0.0:9093
|
|||||||
reality-opts:
|
reality-opts:
|
||||||
public-key: "#{6}"
|
public-key: "#{6}"
|
||||||
short-id: "#{7}"
|
short-id: "#{7}"
|
||||||
#{}`,{label:"vless-reality",type:"snippet",detail:"VLESS REALITY node"}),A(`- name: "#{1}"
|
#{}`,{label:"vless-reality",type:"snippet",detail:"VLESS REALITY node"}),M(`- name: "#{1}"
|
||||||
type: hysteria2
|
type: hysteria2
|
||||||
server: "#{2}"
|
server: "#{2}"
|
||||||
port: #{3}
|
port: #{3}
|
||||||
@@ -457,7 +457,7 @@ external-controller: 0.0.0.0:9093
|
|||||||
# skip-cert-verify: false
|
# skip-cert-verify: false
|
||||||
# obfs: salamander
|
# obfs: salamander
|
||||||
# obfs-password: ""
|
# obfs-password: ""
|
||||||
#{}`,{label:"hysteria2-template",type:"snippet",detail:"Hysteria2 node"}),A(`- name: "#{1}"
|
#{}`,{label:"hysteria2-template",type:"snippet",detail:"Hysteria2 node"}),M(`- name: "#{1}"
|
||||||
type: tuic
|
type: tuic
|
||||||
server: "#{2}"
|
server: "#{2}"
|
||||||
port: #{3}
|
port: #{3}
|
||||||
@@ -469,7 +469,7 @@ external-controller: 0.0.0.0:9093
|
|||||||
# alpn:
|
# alpn:
|
||||||
# - h3
|
# - h3
|
||||||
# congestion-controller: bbr
|
# congestion-controller: bbr
|
||||||
#{}`,{label:"tuic-template",type:"snippet",detail:"TUIC node"}),A(`- name: "#{1}"
|
#{}`,{label:"tuic-template",type:"snippet",detail:"TUIC node"}),M(`- name: "#{1}"
|
||||||
type: wireguard
|
type: wireguard
|
||||||
server: "#{2}"
|
server: "#{2}"
|
||||||
port: #{3}
|
port: #{3}
|
||||||
@@ -480,7 +480,7 @@ external-controller: 0.0.0.0:9093
|
|||||||
udp: true
|
udp: true
|
||||||
# reserved: ""
|
# reserved: ""
|
||||||
# dialer-proxy: ""
|
# dialer-proxy: ""
|
||||||
#{}`,{label:"wireguard-template",type:"snippet",detail:"WireGuard node"}),A(`- name: "#{1}"
|
#{}`,{label:"wireguard-template",type:"snippet",detail:"WireGuard node"}),M(`- name: "#{1}"
|
||||||
type: socks5
|
type: socks5
|
||||||
server: "#{2}"
|
server: "#{2}"
|
||||||
port: #{3}
|
port: #{3}
|
||||||
@@ -489,7 +489,7 @@ external-controller: 0.0.0.0:9093
|
|||||||
# tls: true
|
# tls: true
|
||||||
# skip-cert-verify: true
|
# skip-cert-verify: true
|
||||||
# udp: true
|
# udp: true
|
||||||
#{}`,{label:"socks5-template",type:"snippet",detail:"SOCKS5 node"}),A(`- name: "#{1}"
|
#{}`,{label:"socks5-template",type:"snippet",detail:"SOCKS5 node"}),M(`- name: "#{1}"
|
||||||
type: http
|
type: http
|
||||||
server: "#{2}"
|
server: "#{2}"
|
||||||
port: #{3}
|
port: #{3}
|
||||||
@@ -497,7 +497,7 @@ external-controller: 0.0.0.0:9093
|
|||||||
# password: ""
|
# password: ""
|
||||||
# tls: true
|
# tls: true
|
||||||
# skip-cert-verify: true
|
# skip-cert-verify: true
|
||||||
#{}`,{label:"http-template",type:"snippet",detail:"HTTP node"}),A(`- name: "#{1}"
|
#{}`,{label:"http-template",type:"snippet",detail:"HTTP node"}),M(`- name: "#{1}"
|
||||||
type: snell
|
type: snell
|
||||||
server: "#{2}"
|
server: "#{2}"
|
||||||
port: #{3}
|
port: #{3}
|
||||||
@@ -507,7 +507,7 @@ external-controller: 0.0.0.0:9093
|
|||||||
# obfs-opts:
|
# obfs-opts:
|
||||||
# mode: http
|
# mode: http
|
||||||
# host: bing.com
|
# host: bing.com
|
||||||
#{}`,{label:"snell-template",type:"snippet",detail:"Snell node"}),A(`- name: "#{1}"
|
#{}`,{label:"snell-template",type:"snippet",detail:"Snell node"}),M(`- name: "#{1}"
|
||||||
type: hysteria
|
type: hysteria
|
||||||
server: "#{2}"
|
server: "#{2}"
|
||||||
port: #{3}
|
port: #{3}
|
||||||
@@ -519,7 +519,7 @@ external-controller: 0.0.0.0:9093
|
|||||||
# skip-cert-verify: false
|
# skip-cert-verify: false
|
||||||
# alpn:
|
# alpn:
|
||||||
# - h3
|
# - h3
|
||||||
#{}`,{label:"hysteria-template",type:"snippet",detail:"Hysteria (v1) node"}),A(`- name: "#{1}"
|
#{}`,{label:"hysteria-template",type:"snippet",detail:"Hysteria (v1) node"}),M(`- name: "#{1}"
|
||||||
type: mieru
|
type: mieru
|
||||||
server: "#{2}"
|
server: "#{2}"
|
||||||
port: #{3}
|
port: #{3}
|
||||||
@@ -529,7 +529,7 @@ external-controller: 0.0.0.0:9093
|
|||||||
udp: true
|
udp: true
|
||||||
# multiplexing: MULTIPLEXING_LOW
|
# multiplexing: MULTIPLEXING_LOW
|
||||||
# handshake-mode: HANDSHAKE_STANDARD
|
# handshake-mode: HANDSHAKE_STANDARD
|
||||||
#{}`,{label:"mieru-template",type:"snippet",detail:"Mieru node"}),A(`- name: "#{1}"
|
#{}`,{label:"mieru-template",type:"snippet",detail:"Mieru node"}),M(`- name: "#{1}"
|
||||||
type: anytls
|
type: anytls
|
||||||
server: "#{2}"
|
server: "#{2}"
|
||||||
port: #{3}
|
port: #{3}
|
||||||
@@ -540,7 +540,7 @@ external-controller: 0.0.0.0:9093
|
|||||||
# client-fingerprint: chrome
|
# client-fingerprint: chrome
|
||||||
# alpn:
|
# alpn:
|
||||||
# - h2
|
# - h2
|
||||||
#{}`,{label:"anytls-template",type:"snippet",detail:"AnyTLS node"}),A(`- name: "#{1}"
|
#{}`,{label:"anytls-template",type:"snippet",detail:"AnyTLS node"}),M(`- name: "#{1}"
|
||||||
type: trusttunnel
|
type: trusttunnel
|
||||||
server: "#{2}"
|
server: "#{2}"
|
||||||
port: #{3}
|
port: #{3}
|
||||||
@@ -552,7 +552,7 @@ external-controller: 0.0.0.0:9093
|
|||||||
# client-fingerprint: chrome
|
# client-fingerprint: chrome
|
||||||
# quic: true
|
# quic: true
|
||||||
# congestion-controller: bbr
|
# congestion-controller: bbr
|
||||||
#{}`,{label:"trusttunnel-template",type:"snippet",detail:"TrustTunnel node"}),A(`- name: "#{1}"
|
#{}`,{label:"trusttunnel-template",type:"snippet",detail:"TrustTunnel node"}),M(`- name: "#{1}"
|
||||||
type: sudoku
|
type: sudoku
|
||||||
server: "#{2}"
|
server: "#{2}"
|
||||||
port: #{3}
|
port: #{3}
|
||||||
@@ -564,7 +564,7 @@ external-controller: 0.0.0.0:9093
|
|||||||
# httpmask:
|
# httpmask:
|
||||||
# disable: false
|
# disable: false
|
||||||
# mode: legacy
|
# mode: legacy
|
||||||
#{}`,{label:"sudoku-template",type:"snippet",detail:"Sudoku node"}),A(`- name: "#{1}"
|
#{}`,{label:"sudoku-template",type:"snippet",detail:"Sudoku node"}),M(`- name: "#{1}"
|
||||||
type: openvpn
|
type: openvpn
|
||||||
server: "#{2}"
|
server: "#{2}"
|
||||||
port: #{3}
|
port: #{3}
|
||||||
@@ -584,25 +584,25 @@ external-controller: 0.0.0.0:9093
|
|||||||
...
|
...
|
||||||
-----END PRIVATE KEY-----
|
-----END PRIVATE KEY-----
|
||||||
udp: true
|
udp: true
|
||||||
#{}`,{label:"openvpn-template",type:"snippet",detail:"OpenVPN node"}),A(`- name: "#{1}"
|
#{}`,{label:"openvpn-template",type:"snippet",detail:"OpenVPN node"}),M(`- name: "#{1}"
|
||||||
type: ssh
|
type: ssh
|
||||||
server: "#{2}"
|
server: "#{2}"
|
||||||
port: #{3}
|
port: #{3}
|
||||||
username: "#{4}"
|
username: "#{4}"
|
||||||
# password: ""
|
# password: ""
|
||||||
# privateKey: path
|
# privateKey: path
|
||||||
#{}`,{label:"ssh-template",type:"snippet",detail:"SSH node"}),A(`- name: "#{1}"
|
#{}`,{label:"ssh-template",type:"snippet",detail:"SSH node"}),M(`- name: "#{1}"
|
||||||
type: dns
|
type: dns
|
||||||
#{}`,{label:"dns-out-template",type:"snippet",detail:"DNS outbound"}),A(`- name: "#{1}"
|
#{}`,{label:"dns-out-template",type:"snippet",detail:"DNS outbound"}),M(`- name: "#{1}"
|
||||||
type: direct
|
type: direct
|
||||||
# interface-name: en0
|
# interface-name: en0
|
||||||
# routing-mark: 6667
|
# routing-mark: 6667
|
||||||
#{}`,{label:"direct-template",type:"snippet",detail:"Direct outbound (custom interface)"}),A(`- name: "#{1}"
|
#{}`,{label:"direct-template",type:"snippet",detail:"Direct outbound (custom interface)"}),M(`- name: "#{1}"
|
||||||
type: select
|
type: select
|
||||||
proxies:
|
proxies:
|
||||||
- "#{2}"
|
- "#{2}"
|
||||||
# disable-udp: false
|
# disable-udp: false
|
||||||
#{}`,{label:"group-select",type:"snippet",detail:"Select manual proxy group"}),A(`- name: "#{1}"
|
#{}`,{label:"group-select",type:"snippet",detail:"Select manual proxy group"}),M(`- name: "#{1}"
|
||||||
type: url-test
|
type: url-test
|
||||||
proxies:
|
proxies:
|
||||||
- "#{2}"
|
- "#{2}"
|
||||||
@@ -610,20 +610,20 @@ external-controller: 0.0.0.0:9093
|
|||||||
interval: #{4}
|
interval: #{4}
|
||||||
# tolerance: 150
|
# tolerance: 150
|
||||||
# lazy: true
|
# lazy: true
|
||||||
#{}`,{label:"group-url-test",type:"snippet",detail:"URL-Test auto speed test group"}),A(`- name: "#{1}"
|
#{}`,{label:"group-url-test",type:"snippet",detail:"URL-Test auto speed test group"}),M(`- name: "#{1}"
|
||||||
type: fallback
|
type: fallback
|
||||||
proxies:
|
proxies:
|
||||||
- "#{2}"
|
- "#{2}"
|
||||||
url: "#{3}"
|
url: "#{3}"
|
||||||
interval: #{4}
|
interval: #{4}
|
||||||
#{}`,{label:"group-fallback",type:"snippet",detail:"Fallback failover group"}),A(`- name: "#{1}"
|
#{}`,{label:"group-fallback",type:"snippet",detail:"Fallback failover group"}),M(`- name: "#{1}"
|
||||||
type: load-balance
|
type: load-balance
|
||||||
proxies:
|
proxies:
|
||||||
- "#{2}"
|
- "#{2}"
|
||||||
url: "#{3}"
|
url: "#{3}"
|
||||||
interval: #{4}
|
interval: #{4}
|
||||||
# strategy: consistent-hashing
|
# strategy: consistent-hashing
|
||||||
#{}`,{label:"group-load-balance",type:"snippet",detail:"Load-Balance group"}),A(`- name: "#{1}"
|
#{}`,{label:"group-load-balance",type:"snippet",detail:"Load-Balance group"}),M(`- name: "#{1}"
|
||||||
type: smart
|
type: smart
|
||||||
proxies:
|
proxies:
|
||||||
- "#{2}"
|
- "#{2}"
|
||||||
@@ -639,15 +639,15 @@ external-controller: 0.0.0.0:9093
|
|||||||
# collectdata: false
|
# collectdata: false
|
||||||
# sample-rate: 1.0
|
# sample-rate: 1.0
|
||||||
# prefer-asn: false
|
# prefer-asn: false
|
||||||
#{}`,{label:"group-smart",type:"snippet",detail:"Smart selection group"}),A(`- DOMAIN-SUFFIX,#{1},#{2}
|
#{}`,{label:"group-smart",type:"snippet",detail:"Smart selection group"}),M(`- DOMAIN-SUFFIX,#{1},#{2}
|
||||||
#{}`,{label:"rule-domain-suffix",type:"snippet",detail:"Domain suffix rule"}),A(`- DOMAIN,#{1},#{2}
|
#{}`,{label:"rule-domain-suffix",type:"snippet",detail:"Domain suffix rule"}),M(`- DOMAIN,#{1},#{2}
|
||||||
#{}`,{label:"rule-domain",type:"snippet",detail:"Domain rule"}),A(`- DOMAIN-KEYWORD,#{1},#{2}
|
#{}`,{label:"rule-domain",type:"snippet",detail:"Domain rule"}),M(`- DOMAIN-KEYWORD,#{1},#{2}
|
||||||
#{}`,{label:"rule-domain-keyword",type:"snippet",detail:"Domain keyword rule"}),A(`- GEOSITE,#{1},#{2}
|
#{}`,{label:"rule-domain-keyword",type:"snippet",detail:"Domain keyword rule"}),M(`- GEOSITE,#{1},#{2}
|
||||||
#{}`,{label:"rule-geosite",type:"snippet",detail:"GeoSite rule"}),A(`- GEOIP,#{1},#{2}
|
#{}`,{label:"rule-geosite",type:"snippet",detail:"GeoSite rule"}),M(`- GEOIP,#{1},#{2}
|
||||||
#{}`,{label:"rule-geoip",type:"snippet",detail:"GEOIP rule"}),A(`- IP-CIDR,#{1},#{2}
|
#{}`,{label:"rule-geoip",type:"snippet",detail:"GEOIP rule"}),M(`- IP-CIDR,#{1},#{2}
|
||||||
#{}`,{label:"rule-ip-cidr",type:"snippet",detail:"IP-CIDR rule"}),A(`- RULE-SET,#{1},#{2}
|
#{}`,{label:"rule-ip-cidr",type:"snippet",detail:"IP-CIDR rule"}),M(`- RULE-SET,#{1},#{2}
|
||||||
#{}`,{label:"rule-set",type:"snippet",detail:"RULE-SET rule"}),A(`- MATCH,#{1}
|
#{}`,{label:"rule-set",type:"snippet",detail:"RULE-SET rule"}),M(`- MATCH,#{1}
|
||||||
#{}`,{label:"rule-match",type:"snippet",detail:"MATCH fallback rule"}),A(`dns:
|
#{}`,{label:"rule-match",type:"snippet",detail:"MATCH fallback rule"}),M(`dns:
|
||||||
enable: #{1}
|
enable: #{1}
|
||||||
listen: 0.0.0.0:53
|
listen: 0.0.0.0:53
|
||||||
enhanced-mode: #{2}
|
enhanced-mode: #{2}
|
||||||
@@ -661,10 +661,10 @@ external-controller: 0.0.0.0:9093
|
|||||||
# fallback-filter:
|
# fallback-filter:
|
||||||
# geoip: true
|
# geoip: true
|
||||||
# geoip-code: CN
|
# geoip-code: CN
|
||||||
#{}`,{label:"dns-template",type:"snippet",detail:"DNS configuration"}),A(`nameserver-policy:
|
#{}`,{label:"dns-template",type:"snippet",detail:"DNS configuration"}),M(`nameserver-policy:
|
||||||
"#{1}":
|
"#{1}":
|
||||||
- "#{2}"
|
- "#{2}"
|
||||||
#{}`,{label:"dns-nameserver-policy",type:"snippet",detail:"DNS nameserver-policy"}),A(`tun:
|
#{}`,{label:"dns-nameserver-policy",type:"snippet",detail:"DNS nameserver-policy"}),M(`tun:
|
||||||
enable: #{1}
|
enable: #{1}
|
||||||
stack: #{2}
|
stack: #{2}
|
||||||
device: utun
|
device: utun
|
||||||
@@ -674,7 +674,7 @@ external-controller: 0.0.0.0:9093
|
|||||||
- any:53
|
- any:53
|
||||||
# auto-redirect: false
|
# auto-redirect: false
|
||||||
# mtu: 9000
|
# mtu: 9000
|
||||||
#{}`,{label:"tun-template",type:"snippet",detail:"TUN configuration"}),A(`proxy-providers:
|
#{}`,{label:"tun-template",type:"snippet",detail:"TUN configuration"}),M(`proxy-providers:
|
||||||
#{1}:
|
#{1}:
|
||||||
type: http
|
type: http
|
||||||
url: "#{2}"
|
url: "#{2}"
|
||||||
@@ -693,7 +693,7 @@ external-controller: 0.0.0.0:9093
|
|||||||
# udp: true
|
# udp: true
|
||||||
# filter: "HK|TW|SG"
|
# filter: "HK|TW|SG"
|
||||||
# exclude-filter: "Expired|Traffic"
|
# exclude-filter: "Expired|Traffic"
|
||||||
#{}`,{label:"proxy-providers",type:"snippet",detail:"Proxy provider configuration"}),A(`rule-providers:
|
#{}`,{label:"proxy-providers",type:"snippet",detail:"Proxy provider configuration"}),M(`rule-providers:
|
||||||
#{1}:
|
#{1}:
|
||||||
type: http
|
type: http
|
||||||
behavior: #{2}
|
behavior: #{2}
|
||||||
@@ -701,31 +701,31 @@ external-controller: 0.0.0.0:9093
|
|||||||
interval: #{4}
|
interval: #{4}
|
||||||
path: ./rule_provider/#{1}.#{5}
|
path: ./rule_provider/#{1}.#{5}
|
||||||
format: #{6}
|
format: #{6}
|
||||||
#{}`,{label:"rule-providers",type:"snippet",detail:"Rule provider configuration"}),A(`rule-providers:
|
#{}`,{label:"rule-providers",type:"snippet",detail:"Rule provider configuration"}),M(`rule-providers:
|
||||||
#{1}:
|
#{1}:
|
||||||
type: file
|
type: file
|
||||||
behavior: #{2}
|
behavior: #{2}
|
||||||
path: /path/to/#{1}.yaml
|
path: /path/to/#{1}.yaml
|
||||||
format: #{3}
|
format: #{3}
|
||||||
#{}`,{label:"rule-providers-file",type:"snippet",detail:"Rule provider (local file)"}),A(`rule-providers:
|
#{}`,{label:"rule-providers-file",type:"snippet",detail:"Rule provider (local file)"}),M(`rule-providers:
|
||||||
#{1}:
|
#{1}:
|
||||||
type: inline
|
type: inline
|
||||||
behavior: #{2}
|
behavior: #{2}
|
||||||
payload:
|
payload:
|
||||||
- '#{3}'
|
- '#{3}'
|
||||||
#{}`,{label:"rule-providers-inline",type:"snippet",detail:"Rule provider (inline)"}),A(`hosts:
|
#{}`,{label:"rule-providers-inline",type:"snippet",detail:"Rule provider (inline)"}),M(`hosts:
|
||||||
'#{1}': #{2}
|
'#{1}': #{2}
|
||||||
# '*.: 127.0.0.1
|
# '*.: 127.0.0.1
|
||||||
# 'alpha..': '::1'
|
# 'alpha..': '::1'
|
||||||
# 'baidu.com': google.com
|
# 'baidu.com': google.com
|
||||||
#{}`,{label:"hosts",type:"snippet",detail:"Custom hosts mapping"}),A(`fake-ip-filter:
|
#{}`,{label:"hosts",type:"snippet",detail:"Custom hosts mapping"}),M(`fake-ip-filter:
|
||||||
- '#{1}'
|
- '#{1}'
|
||||||
- '+.#{2}'
|
- '+.#{2}'
|
||||||
# - rule-set:fakeip-filter
|
# - rule-set:fakeip-filter
|
||||||
# - geosite:fakeip-filter
|
# - geosite:fakeip-filter
|
||||||
# - '*.lan'
|
# - '*.lan'
|
||||||
# - localhost.ptlogin2.qq.com
|
# - localhost.ptlogin2.qq.com
|
||||||
#{}`,{label:"fake-ip-filter",type:"snippet",detail:"Fake-IP filter list"}),A(`sniffer:
|
#{}`,{label:"fake-ip-filter",type:"snippet",detail:"Fake-IP filter list"}),M(`sniffer:
|
||||||
enable: #{1}
|
enable: #{1}
|
||||||
override-destination: #{2}
|
override-destination: #{2}
|
||||||
sniff:
|
sniff:
|
||||||
@@ -742,7 +742,7 @@ external-controller: 0.0.0.0:9093
|
|||||||
# - Mijia Cloud
|
# - Mijia Cloud
|
||||||
# parse-pure-ip: true
|
# parse-pure-ip: true
|
||||||
# force-dns-mapping: true
|
# force-dns-mapping: true
|
||||||
#{}`,{label:"sniffer",type:"snippet",detail:"Domain sniffing configuration"}),A(`dns:
|
#{}`,{label:"sniffer",type:"snippet",detail:"Domain sniffing configuration"}),M(`dns:
|
||||||
enable: #{1}
|
enable: #{1}
|
||||||
enhanced-mode: #{2}
|
enhanced-mode: #{2}
|
||||||
listen: 0.0.0.0:53
|
listen: 0.0.0.0:53
|
||||||
@@ -762,7 +762,7 @@ external-controller: 0.0.0.0:9093
|
|||||||
# proxy-server-nameserver:
|
# proxy-server-nameserver:
|
||||||
# - https://doh.pub/dns-query
|
# - https://doh.pub/dns-query
|
||||||
# respect-rules: false
|
# respect-rules: false
|
||||||
#{}`,{label:"dns",type:"snippet",detail:"DNS configuration"}),A(`nameserver-policy:
|
#{}`,{label:"dns",type:"snippet",detail:"DNS configuration"}),M(`nameserver-policy:
|
||||||
"#{1}":
|
"#{1}":
|
||||||
- "#{2}"
|
- "#{2}"
|
||||||
# "geosite:cn,private,apple":
|
# "geosite:cn,private,apple":
|
||||||
@@ -770,7 +770,7 @@ external-controller: 0.0.0.0:9093
|
|||||||
# - https://dns.alidns.com/dns-query
|
# - https://dns.alidns.com/dns-query
|
||||||
# "geosite:category-ads-all": rcode://success
|
# "geosite:category-ads-all": rcode://success
|
||||||
# "rule-set:global,dns": 8.8.8.8
|
# "rule-set:global,dns": 8.8.8.8
|
||||||
#{}`,{label:"nameserver-policy",type:"snippet",detail:"DNS by domain/geo/rule-set"}),A(`fallback-filter:
|
#{}`,{label:"nameserver-policy",type:"snippet",detail:"DNS by domain/geo/rule-set"}),M(`fallback-filter:
|
||||||
geoip: #{1}
|
geoip: #{1}
|
||||||
geoip-code: #{2}
|
geoip-code: #{2}
|
||||||
ipcidr:
|
ipcidr:
|
||||||
@@ -779,7 +779,7 @@ external-controller: 0.0.0.0:9093
|
|||||||
# domain:
|
# domain:
|
||||||
# - '+.google.com'
|
# - '+.google.com'
|
||||||
# - '+.facebook.com'
|
# - '+.facebook.com'
|
||||||
#{}`,{label:"fallback-filter",type:"snippet",detail:"DNS fallback filter criteria"}),A(`tun:
|
#{}`,{label:"fallback-filter",type:"snippet",detail:"DNS fallback filter criteria"}),M(`tun:
|
||||||
enable: #{1}
|
enable: #{1}
|
||||||
stack: #{2}
|
stack: #{2}
|
||||||
device: utun
|
device: utun
|
||||||
@@ -791,16 +791,16 @@ external-controller: 0.0.0.0:9093
|
|||||||
# mtu: 9000
|
# mtu: 9000
|
||||||
# strict-route: true
|
# strict-route: true
|
||||||
# endpoint-independent-nat: false
|
# endpoint-independent-nat: false
|
||||||
#{}`,{label:"tun",type:"snippet",detail:"TUN mode configuration"}),A(`authentication:
|
#{}`,{label:"tun",type:"snippet",detail:"TUN mode configuration"}),M(`authentication:
|
||||||
- "#{1}:#{2}"
|
- "#{1}:#{2}"
|
||||||
#{}`,{label:"authentication",type:"snippet",detail:"HTTP/SOCKS authentication"}),A(`geox-url:
|
#{}`,{label:"authentication",type:"snippet",detail:"HTTP/SOCKS authentication"}),M(`geox-url:
|
||||||
geoip: "#{1}"
|
geoip: "#{1}"
|
||||||
geosite: "#{2}"
|
geosite: "#{2}"
|
||||||
mmdb: "#{3}"
|
mmdb: "#{3}"
|
||||||
#{}`,{label:"geox-url",type:"snippet",detail:"Custom GEO data source URL"}),A(`profile:
|
#{}`,{label:"geox-url",type:"snippet",detail:"Custom GEO data source URL"}),M(`profile:
|
||||||
store-selected: #{1}
|
store-selected: #{1}
|
||||||
store-fake-ip: #{2}
|
store-fake-ip: #{2}
|
||||||
#{}`,{label:"profile",type:"snippet",detail:"Persistent storage configuration"}),A(`- name: "#{1}"
|
#{}`,{label:"profile",type:"snippet",detail:"Persistent storage configuration"}),M(`- name: "#{1}"
|
||||||
type: select
|
type: select
|
||||||
use:
|
use:
|
||||||
- #{2}
|
- #{2}
|
||||||
@@ -808,18 +808,18 @@ external-controller: 0.0.0.0:9093
|
|||||||
# exclude-filter: "Expired|Traffic"
|
# exclude-filter: "Expired|Traffic"
|
||||||
proxies:
|
proxies:
|
||||||
- DIRECT
|
- DIRECT
|
||||||
#{}`,{label:"proxy-group-use",type:"snippet",detail:"Proxy group (reference provider)"}),A(`listeners:
|
#{}`,{label:"proxy-group-use",type:"snippet",detail:"Proxy group (reference provider)"}),M(`listeners:
|
||||||
- name: socks5-in
|
- name: socks5-in
|
||||||
type: socks
|
type: socks
|
||||||
port: #{1}
|
port: #{1}
|
||||||
# listen: 0.0.0.0
|
# listen: 0.0.0.0
|
||||||
# udp: true
|
# udp: true
|
||||||
#{}`,{label:"listener-socks",type:"snippet",detail:"SOCKS5 inbound"}),A(`listeners:
|
#{}`,{label:"listener-socks",type:"snippet",detail:"SOCKS5 inbound"}),M(`listeners:
|
||||||
- name: http-in
|
- name: http-in
|
||||||
type: http
|
type: http
|
||||||
port: #{1}
|
port: #{1}
|
||||||
# listen: 0.0.0.0
|
# listen: 0.0.0.0
|
||||||
#{}`,{label:"listener-http",type:"snippet",detail:"HTTP inbound"}),A(`listeners:
|
#{}`,{label:"listener-http",type:"snippet",detail:"HTTP inbound"}),M(`listeners:
|
||||||
- name: mixed-in
|
- name: mixed-in
|
||||||
type: mixed
|
type: mixed
|
||||||
port: #{1}
|
port: #{1}
|
||||||
@@ -828,7 +828,7 @@ external-controller: 0.0.0.0:9093
|
|||||||
# users:
|
# users:
|
||||||
# - username: aaa
|
# - username: aaa
|
||||||
# password: aaa
|
# password: aaa
|
||||||
#{}`,{label:"listener-mixed",type:"snippet",detail:"HTTP/SOCKS mixed inbound"}),A(`listeners:
|
#{}`,{label:"listener-mixed",type:"snippet",detail:"HTTP/SOCKS mixed inbound"}),M(`listeners:
|
||||||
- name: tun-in
|
- name: tun-in
|
||||||
type: tun
|
type: tun
|
||||||
# stack: system
|
# stack: system
|
||||||
@@ -836,20 +836,20 @@ external-controller: 0.0.0.0:9093
|
|||||||
# - 0.0.0.0:53
|
# - 0.0.0.0:53
|
||||||
# auto-route: true
|
# auto-route: true
|
||||||
# mtu: 9000
|
# mtu: 9000
|
||||||
#{}`,{label:"listener-tun",type:"snippet",detail:"TUN inbound"}),A(`sub-rules:
|
#{}`,{label:"listener-tun",type:"snippet",detail:"TUN inbound"}),M(`sub-rules:
|
||||||
#{1}:
|
#{1}:
|
||||||
- DOMAIN,#{2},#{3}
|
- DOMAIN,#{2},#{3}
|
||||||
- DOMAIN-SUFFIX,#{4},#{5}
|
- DOMAIN-SUFFIX,#{4},#{5}
|
||||||
- IP-CIDR,#{6},#{7}
|
- IP-CIDR,#{6},#{7}
|
||||||
- MATCH,#{8}
|
- MATCH,#{8}
|
||||||
#{}`,{label:"sub-rules",type:"snippet",detail:"Sub-rule set definition"}),A(`tunnels:
|
#{}`,{label:"sub-rules",type:"snippet",detail:"Sub-rule set definition"}),M(`tunnels:
|
||||||
- tcp/udp,127.0.0.1:#{1},#{2}:#{3},#{4}
|
- tcp/udp,127.0.0.1:#{1},#{2}:#{3},#{4}
|
||||||
#{}`,{label:"tunnels",type:"snippet",detail:"Tunnel forwarding (short format)"}),A(`tunnels:
|
#{}`,{label:"tunnels",type:"snippet",detail:"Tunnel forwarding (short format)"}),M(`tunnels:
|
||||||
- network: [tcp, udp]
|
- network: [tcp, udp]
|
||||||
address: 127.0.0.1:#{1}
|
address: 127.0.0.1:#{1}
|
||||||
target: #{2}:#{3}
|
target: #{2}:#{3}
|
||||||
proxy: #{4}
|
proxy: #{4}
|
||||||
#{}`,{label:"tunnels-full",type:"snippet",detail:"Tunnel forwarding (full format)"}),A(`- name: "#{1}"
|
#{}`,{label:"tunnels-full",type:"snippet",detail:"Tunnel forwarding (full format)"}),M(`- name: "#{1}"
|
||||||
type: masque
|
type: masque
|
||||||
server: "#{2}"
|
server: "#{2}"
|
||||||
port: #{3}
|
port: #{3}
|
||||||
@@ -859,11 +859,11 @@ external-controller: 0.0.0.0:9093
|
|||||||
udp: true
|
udp: true
|
||||||
# network: h3 # h3 / h2 / h3-l4proxy
|
# network: h3 # h3 / h2 / h3-l4proxy
|
||||||
# dialer-proxy: ""
|
# dialer-proxy: ""
|
||||||
#{}`,{label:"masque-template",type:"snippet",detail:"MASQUE node"}),A(`- name: "#{1}"
|
#{}`,{label:"masque-template",type:"snippet",detail:"MASQUE node"}),M(`- name: "#{1}"
|
||||||
type: rematch
|
type: rematch
|
||||||
target-rematch-name: "#{2}"
|
target-rematch-name: "#{2}"
|
||||||
# target-sub-rule: ""
|
# target-sub-rule: ""
|
||||||
#{}`,{label:"rematch-template",type:"snippet",detail:"Rematch node"}),A(`- name: "#{1}"
|
#{}`,{label:"rematch-template",type:"snippet",detail:"Rematch node"}),M(`- name: "#{1}"
|
||||||
type: gost-relay
|
type: gost-relay
|
||||||
server: "#{2}"
|
server: "#{2}"
|
||||||
port: #{3}
|
port: #{3}
|
||||||
@@ -872,4 +872,4 @@ external-controller: 0.0.0.0:9093
|
|||||||
# mux: true
|
# mux: true
|
||||||
# username: ""
|
# username: ""
|
||||||
# password: ""
|
# password: ""
|
||||||
#{}`,{label:"gost-relay-template",type:"snippet",detail:"GOST Relay node"})];function uX(t){let e=t.matchBefore(/[\w-]+/);if(!e||e.from===e.to&&!t.explicit)return null;let i=hX.filter(s=>s.label.toLowerCase().startsWith(e.text.toLowerCase())),n=fX.filter(s=>(s.label||s.name||"").toLowerCase().startsWith(e.text.toLowerCase())),r=[...i,...n];return r.length?{from:e.from,options:r,validFor:/^[\w-]*$/}:null}function dX(){return Ad(t=>{let e=[];try{NS(t.state.doc.toString(),{schema:qd})}catch(i){let n=i.mark;if(n&&n.line!==void 0){let r=n.line+1;if(r<=t.state.doc.lines){let s=t.state.doc.line(r),o=Math.min(s.from+(n.column||0),s.to);e.push({from:o,to:Math.min(o+1,s.to),severity:"error",message:i.reason||i.message})}}else e.push({from:0,to:0,severity:"error",message:i.reason||i.message})}return e})}var cc=null,fg=null;function pX(){if(!window.levelTranslations){cc={},fg=/(?!)/;return}var t={},e=[];for(var i in window.levelTranslations)if(window.levelTranslations.hasOwnProperty(i)){var n=window.levelTranslations[i];t[n]=i,e.push(n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"))}cc=t,fg=new RegExp("^\\[("+e.join("|")+")\\]")}var gX=Xs.define({tokenTable:{timestamp:Ce.timestamp,bracket:Ce.bracket,category:Ce.category,logString:Ce.logString,logLink:Ce.logLink,levelInfo:Ce.levelInfo,levelWarning:Ce.levelWarning,levelError:Ce.levelError,levelDebug:Ce.levelDebug,levelTip:Ce.levelTip,levelFatal:Ce.levelFatal,levelWatchdog:Ce.levelWatchdog},startState(){return{tabDone:!1}},token(t,e){if(t.sol()&&(e.tabDone=!1,t.match(/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/)))return"timestamp";if(t.eatSpace())return null;var i=t.peek();if(!i)return t.skipToEnd(),null;if(i==="\u3010"&&t.match(/\u3010[^\u3011]*\u3011/))return"bracket";if(e.tabDone)return t.next(),"logString";if(i==="["){cc===null&&pX();var n=t.match(fg);if(n){var r=cc[n[1]];if(r){var s="level"+r.charAt(0).toUpperCase()+r.slice(1);if(Ce[s])return s}return"category"}if(t.match(/\[[A-Z][^\]]*\]/))return"category"}return i!=="["&&(e.tabDone=!0),t.next(),"logString"}}),OX=Wt.define([{tag:Ce.timestamp,class:"cmt-log-timestamp"},{tag:Ce.bracket,class:"cmt-log-bracket"},{tag:Ce.category,class:"cmt-log-category"},{tag:Ce.logString,class:"cmt-log-string"},{tag:Ce.logLink,class:"cmt-log-link"},{tag:Ce.levelInfo,class:"cmt-log-level-info"},{tag:Ce.levelWarning,class:"cmt-log-level-warning"},{tag:Ce.levelError,class:"cmt-log-level-error"},{tag:Ce.levelDebug,class:"cmt-log-level-debug"},{tag:Ce.levelTip,class:"cmt-log-level-tip"},{tag:Ce.levelFatal,class:"cmt-log-level-fatal"},{tag:Ce.levelWatchdog,class:"cmt-log-level-watchdog"}]);function mX(t=[]){return[qh(),Bh(),Wh(),Ih(),Zh(),Dh(),Nh(),jh(),Tf(),$f({placeholderDOM:null}),wf(),Bf(),np(),T.lineWrapping,Qu(),ki.of([...zf,...Nf,...lp,...Pu,...Qf,{key:"Tab",run:function(e){return ku(e)||Il(e)}}]),...t]}var bX=T.baseTheme({".cm-line":{position:"relative"},".cm-oc-im::before":{content:'""',position:"absolute",top:0,left:"6px",right:0,bottom:0,background:"var(--oc-im)",pointerEvents:"none",zIndex:"-1"},"&light":{"--oc-im-c":"#e1e4e8","--oc-im-ca":"#d0d7de"},"&dark":{"--oc-im-c":"#30363d","--oc-im-ca":"#484f58"}});function vk(t,e){let i=0;for(let n=0;n<t.length;n++)if(t[n]===" ")i++;else if(t[n]===" ")i+=e;else break;return i}function yX(t,e,i,n){for(var r=[],s=e;s<=i;s++){var o=vn(t,n.line(s).from,n.line(s).to);o&&r.push({from:o.from,to:o.to})}for(var l=new Int32Array(i-e+1),s=e;s<=i;s++){for(var a=n.line(s).from,h=0,c=0;c<r.length;c++)r[c].from<a&&a<r[c].to&&h++;l[s-e]=h}return l}function SX(t,e,i,n,r){for(var s=r.line(e).from,o=0,l=i;l<=n;l++){var a=vn(t,r.line(l).from,r.line(l).to);a&&a.from<s&&s<a.to&&o++}return o}function xX({highlightActiveBlock:t=!0,hideFirstIndent:e=!1,thickness:i=1,colors:n}={}){var r=n?T.baseTheme({"&light":{"--oc-im-c":n.light||"#e1e4e8","--oc-im-ca":n.activeLight||"#d0d7de"},"&dark":{"--oc-im-c":n.dark||"#30363d","--oc-im-ca":n.activeDark||"#484f58"}}):[];return[bX,r,Se.fromClass(class{constructor(s){this._view=s,this._stepPx=null,this._measurePending=!1,this.decorations=this._build(s),this._scheduleMeasure(s)}update(s){this._view=s.view;var o=s.docChanged||s.viewportChanged||t&&s.selectionSet;o?(this._stepPx=null,this._measurePending=!1,this.decorations=this._build(s.view),this._scheduleMeasure(s.view)):this._measurePending&&(this._measurePending=!1,this.decorations=this._build(s.view))}_scheduleMeasure(s){this._measureId!==void 0&&s.cancelMeasure(this._measureId),this._measureId=s.requestMeasure(this._mkSpec())}_mkSpec(){var s=this;return{read:function(o){for(var l=e?1:0,a=o.state,h=qt(a),c=a.tabSize,f=a.doc,u=f.lineAt(o.viewport.from).number,d=f.lineAt(o.viewport.to).number,p=Math.max(1,u-80),g=Math.min(f.lines,d+80),m=0,b=u;b<=d;b++)if(!(b<p||b>g)){var y=SX(a,b,u,d,f);y>m&&(m=y)}if(m<=l)return-1;for(var x=0,b=u;b<=d;b++)if(!(b<p||b>g)){var Q=f.line(b).text;if(Q.trim()!==""&&vk(Q,c)>=h){var S=o.coordsAtPos(f.line(b).from),k=o.coordsAtPos(f.line(b).from+h);if(S&&k){x=Math.round((k.left-S.left)*100)/100;break}}}return x>0
Line truncated
|
#{}`,{label:"gost-relay-template",type:"snippet",detail:"GOST Relay node"})];function pX(t){let e=t.matchBefore(/[\w-]+/);if(!e||e.from===e.to&&!t.explicit)return null;let i=uX.filter(s=>s.label.toLowerCase().startsWith(e.text.toLowerCase())),n=dX.filter(s=>(s.label||s.name||"").toLowerCase().startsWith(e.text.toLowerCase())),r=[...i,...n];return r.length?{from:e.from,options:r,validFor:/^[\w-]*$/}:null}function gX(t=750){return Md(e=>{let i=[];try{qS(e.state.doc.toString(),{schema:Gd})}catch(n){let r=n.mark;if(r&&r.line!==void 0){let s=r.line+1;if(s<=e.state.doc.lines){let o=e.state.doc.line(s),l=Math.min(o.from+(r.column||0),o.to);i.push({from:l,to:Math.min(l+1,o.to),severity:"error",message:n.reason||n.message})}}else i.push({from:0,to:0,severity:"error",message:n.reason||n.message})}return i},typeof t=="number"?{delay:t}:void 0)}var uc=null,gg=null;function OX(){if(!window.levelTranslations){uc={},gg=/(?!)/;return}var t={},e=[];for(var i in window.levelTranslations)if(window.levelTranslations.hasOwnProperty(i)){var n=window.levelTranslations[i];t[n]=i,e.push(n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"))}uc=t,gg=new RegExp("^\\[("+e.join("|")+")\\]")}var mX=_s.define({tokenTable:{timestamp:Ae.timestamp,bracket:Ae.bracket,category:Ae.category,logString:Ae.logString,logLink:Ae.logLink,levelInfo:Ae.levelInfo,levelWarning:Ae.levelWarning,levelError:Ae.levelError,levelDebug:Ae.levelDebug,levelTip:Ae.levelTip,levelFatal:Ae.levelFatal,levelWatchdog:Ae.levelWatchdog},startState(){return{tabDone:!1}},token(t,e){if(t.sol()&&(e.tabDone=!1,t.match(/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/)))return"timestamp";if(t.eatSpace())return null;var i=t.peek();if(!i)return t.skipToEnd(),null;if(i==="\u3010"&&t.match(/\u3010[^\u3011]*\u3011/))return"bracket";if(e.tabDone)return t.next(),"logString";if(i==="["){uc===null&&OX();var n=t.match(gg);if(n){var r=uc[n[1]];if(r){var s="level"+r.charAt(0).toUpperCase()+r.slice(1);if(Ae[s])return s}return"category"}if(t.match(/\[[A-Z][^\]]*\]/))return"category"}return i!=="["&&(e.tabDone=!0),t.next(),"logString"}}),bX=Vt.define([{tag:Ae.timestamp,class:"cmt-log-timestamp"},{tag:Ae.bracket,class:"cmt-log-bracket"},{tag:Ae.category,class:"cmt-log-category"},{tag:Ae.logString,class:"cmt-log-string"},{tag:Ae.logLink,class:"cmt-log-link"},{tag:Ae.levelInfo,class:"cmt-log-level-info"},{tag:Ae.levelWarning,class:"cmt-log-level-warning"},{tag:Ae.levelError,class:"cmt-log-level-error"},{tag:Ae.levelDebug,class:"cmt-log-level-debug"},{tag:Ae.levelTip,class:"cmt-log-level-tip"},{tag:Ae.levelFatal,class:"cmt-log-level-fatal"},{tag:Ae.levelWatchdog,class:"cmt-log-level-watchdog"}]);function Tk(t=1e3){return me.fromClass(class{constructor(e){this._preload(e)}update(e){if(e.viewportChanged||e.docChanged){this._rafId&&cancelAnimationFrame(this._rafId);var i=this;this._rafId=requestAnimationFrame(function(){i._rafId=null,i._preload(e.view)})}}_preload(e){var i=e.state.doc,n=i.lineAt(e.viewport.to).number,r=Math.min(n+t,i.lines);a0(e.state,i.line(r).to,50)}})}function yX(t=[]){return[Gh(),zh(),Uh(),jh(),Bh(),Nh(),Yh(),qh(),Rf(),Af({placeholderDOM:null}),Pf(),zf(),op(),T.lineWrapping,Tu(),Tk(),wi.of([...Wf,...Yf,...hp,...Cu,...Tf,{key:"Tab",run:function(e){return Qu(e)||jl(e)}}]),...t]}var SX=T.baseTheme({".cm-line":{position:"relative"},".cm-oc-im::before":{content:'""',position:"absolute",top:0,left:"6px",right:0,height:"var(--oc-lh, 100%)",background:"var(--oc-im)",pointerEvents:"none",zIndex:"-1"},"&light":{"--oc-im-c":"#e1e4e8","--oc-im-ca":"#d0d7de"},"&dark":{"--oc-im-c":"#30363d","--oc-im-ca":"#484f58"}});function pg(t,e){let i=0;for(let n=0;n<t.length;n++)if(t[n]===" ")i++;else if(t[n]===" ")i+=e;else break;return i}function xX({highlightActiveBlock:t=!0,hideFirstIndent:e=!1,thickness:i=1,colors:n,deferMode:r="raf",buffer:s=1e3}={}){var o=n?T.baseTheme({"&light":{"--oc-im-c":n.light||"#e1e4e8","--oc-im-ca":n.activeLight||"#d0d7de"},"&dark":{"--oc-im-c":n.dark||"#30363d","--oc-im-ca":n.activeDark||"#484f58"}}):[];return[SX,o,me.fromClass(class{constructor(l){this._view=l,this._stepPx=null,this._measurePending=!1,this.decorations=this._build(l),this._scheduleMeasure(l)}update(l){this._view=l.view;var a=l.docChanged||l.viewportChanged||t&&l.selectionSet;if(a){if(r==="raf"&&l.viewportChanged&&!l.docChanged){this._rafId&&cancelAnimationFrame(this._rafId);var h=this;this._rafId=requestAnimationFrame(function(){h._rafId=null,h._stepPx=null,h._measurePending=!1,h.decorations=h._build(l.view),h._scheduleMeasure(l.view)});return}this._rafId&&(cancelAnimationFrame(this._rafId),this._rafId=null),this._stepPx=null,this._measurePending=!1,this.decorations=this._build(l.view),this._scheduleMeasure(l.view)}else this._measurePending&&(this._measurePending=!1,this.decorations=this._build(l.view))}_scheduleMeasure(l){this._measureId!==void 0&&l.cancelMeasure(this._measureId),this._measureId=l.requestMeasure(this._mkSpec())}_mkSpec(){var l=this;return{read:function(a){for(var h=a.state,c=Wt(h),f=h.tabSize,u=h.doc,d=u.lineAt(a
Line truncated
|
||||||
@@ -1,14 +1,68 @@
|
|||||||
/**
|
// OpenClash shared utilities
|
||||||
* OpenClash Common JavaScript Utilities
|
|
||||||
* Shared functions used across multiple view templates.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
// ═══ Internal helpers ═══
|
||||||
* Detects if an element has a dark background by analyzing its computed CSS.
|
|
||||||
* Used by CodeMirror log editor to set dark mode attribute.
|
// Parse a CSS color string and return relative luminance (0-255).
|
||||||
* @param {HTMLElement} element - The element to check
|
// Returns 128 for unparseable colors (sentinel: neither dark nor light).
|
||||||
* @returns {boolean} True if the background is dark
|
function _luminanceFromColor(color) {
|
||||||
*/
|
var r, g, b;
|
||||||
|
if (color[0] === '#') {
|
||||||
|
if (color.length === 4) {
|
||||||
|
r = parseInt(color[1] + color[1], 16);
|
||||||
|
g = parseInt(color[2] + color[2], 16);
|
||||||
|
b = parseInt(color[3] + color[3], 16);
|
||||||
|
} else {
|
||||||
|
r = parseInt(color.substr(1, 2), 16);
|
||||||
|
g = parseInt(color.substr(3, 2), 16);
|
||||||
|
b = parseInt(color.substr(5, 2), 16);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var m = color.match(/[\d.]+/g);
|
||||||
|
if (!m || m.length < 3) return 128;
|
||||||
|
r = parseInt(m[0]); g = parseInt(m[1]); b = parseInt(m[2]);
|
||||||
|
}
|
||||||
|
return 0.2126 * r + 0.7152 * g + 0.0722 * b;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Multi-signal dark-mode detection for initial load (runs in <head>,
|
||||||
|
// before <body> exists). Covers Bootstrap 5.3, Argon, Material, and
|
||||||
|
// generic LuCI themes. Defaults to light when no signal detected —
|
||||||
|
// after DOM ready isDarkBackground(document.body) corrects if needed.
|
||||||
|
function _detectInitialAutoDark() {
|
||||||
|
var html = document.documentElement,
|
||||||
|
v, cls, lum;
|
||||||
|
// 1. HTML data-* attributes (Bootstrap 5.3, Material, OpenClash, and generic)
|
||||||
|
v = html.getAttribute('data-bs-theme') || html.getAttribute('data-theme') || html.getAttribute('data-darkmode');
|
||||||
|
if (v === 'dark' || v === 'dim' || v === 'true') return true;
|
||||||
|
if (v === 'light' || v === 'false') return false;
|
||||||
|
// 2. HTML class name (Argon dark-mode, generic theme-dark, etc.)
|
||||||
|
cls = ' ' + (html.className || '') + ' ';
|
||||||
|
if (cls.indexOf(' dark ') >= 0 || cls.indexOf(' dark-mode ') >= 0 ||
|
||||||
|
cls.indexOf(' theme-dark ') >= 0 || cls.indexOf(' night-mode ') >= 0) return true;
|
||||||
|
// 3. localStorage keys used by popular LuCI themes
|
||||||
|
var keys = [['mode', 'dark'], ['dark_mode', '1'], ['argon_dark_mode', '1'],
|
||||||
|
['theme', 'dark'], ['luci-theme-mode', 'dark']];
|
||||||
|
for (var i = 0; i < keys.length; i++) {
|
||||||
|
v = localStorage.getItem(keys[i][0]);
|
||||||
|
if (v === keys[i][1]) return true;
|
||||||
|
if (v === 'light' || v === '0' || v === 'false') return false;
|
||||||
|
}
|
||||||
|
// 4. CSS custom properties for dark themes
|
||||||
|
var style = getComputedStyle(html),
|
||||||
|
checkBg = style.getPropertyValue('--bs-body-bg').trim()
|
||||||
|
|| style.getPropertyValue('--body-bg').trim()
|
||||||
|
|| style.getPropertyValue('--theme-bg').trim();
|
||||||
|
if (checkBg && checkBg !== 'transparent' && checkBg !== 'rgba(0, 0, 0, 0)') return _luminanceFromColor(checkBg) < 128;
|
||||||
|
|
||||||
|
// 5. System preference (ultimate fallback)
|
||||||
|
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Detect whether the given element sits on a dark background.
|
||||||
|
// Explicit oc-theme → immediate. Auto → computed background-color
|
||||||
|
// (fallback to <html> if element background is transparent).
|
||||||
function isDarkBackground(element) {
|
function isDarkBackground(element) {
|
||||||
var cachedTheme = localStorage.getItem('oc-theme');
|
var cachedTheme = localStorage.getItem('oc-theme');
|
||||||
if (cachedTheme === 'dark') {
|
if (cachedTheme === 'dark') {
|
||||||
@@ -17,44 +71,539 @@ function isDarkBackground(element) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var style = window.getComputedStyle(element);
|
var style = window.getComputedStyle(element);
|
||||||
var bgColor = style.backgroundColor;
|
var bgColor = style.backgroundColor;
|
||||||
var r, g, b;
|
if (!bgColor || bgColor === 'transparent' || bgColor === 'rgba(0, 0, 0, 0)') {
|
||||||
if (/rgb\(/.test(bgColor)) {
|
bgColor = window.getComputedStyle(document.documentElement).backgroundColor;
|
||||||
var rgb = bgColor.match(/\d+/g);
|
|
||||||
r = parseInt(rgb[0]);
|
|
||||||
g = parseInt(rgb[1]);
|
|
||||||
b = parseInt(rgb[2]);
|
|
||||||
} else if (/#/.test(bgColor)) {
|
|
||||||
if (bgColor.length === 4) {
|
|
||||||
r = parseInt(bgColor[1] + bgColor[1], 16);
|
|
||||||
g = parseInt(bgColor[2] + bgColor[2], 16);
|
|
||||||
b = parseInt(bgColor[3] + bgColor[3], 16);
|
|
||||||
} else {
|
|
||||||
r = parseInt(bgColor.slice(1, 3), 16);
|
|
||||||
g = parseInt(bgColor.slice(3, 5), 16);
|
|
||||||
b = parseInt(bgColor.slice(5, 7), 16);
|
|
||||||
}
|
}
|
||||||
} else {
|
var lum = _luminanceFromColor(bgColor);
|
||||||
return false;
|
if (lum > 100 && lum < 156 && window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
var luminance = 0.2126 * r + 0.7152 * g + 0.0722 * b;
|
return lum < 128;
|
||||||
return luminance < 128;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// ═══ Theme system ═══
|
||||||
* Opens a URL in a new window. Used for external links (Wiki, GitHub, etc.).
|
|
||||||
* @param {string} url - The URL to open
|
// Sets html[data-darkmode] and <meta name="color-scheme">.
|
||||||
* @returns {boolean} false to prevent default link behavior
|
// Explicit dark/light → immediate. Auto → background detection
|
||||||
*/
|
// (isDarkBackground after DOM ready; _detectInitialAutoDark initially).
|
||||||
|
function ocApplyRootTheme() {
|
||||||
|
var t = localStorage.getItem('oc-theme') || 'auto',
|
||||||
|
d;
|
||||||
|
if (t === 'dark') {
|
||||||
|
d = true;
|
||||||
|
} else if (t === 'light') {
|
||||||
|
d = false;
|
||||||
|
} else {
|
||||||
|
if (document.body && document.readyState !== 'loading') {
|
||||||
|
d = isDarkBackground(document.body);
|
||||||
|
} else {
|
||||||
|
d = _detectInitialAutoDark();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
document.documentElement.setAttribute('data-darkmode', d ? 'true' : 'false');
|
||||||
|
var m = document.querySelector('meta[name="color-scheme"]');
|
||||||
|
if (!m) {
|
||||||
|
m = document.createElement('meta');
|
||||||
|
m.name = 'color-scheme';
|
||||||
|
document.head.appendChild(m);
|
||||||
|
}
|
||||||
|
m.content = d ? 'dark' : 'light';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Idempotent theme initializer. First call registers DOMContentLoaded
|
||||||
|
// listener (if page still loading); subsequent calls just re-apply.
|
||||||
|
function ocInitTheme() {
|
||||||
|
if (window._ocThemeInited) {
|
||||||
|
ocUpdateTheme();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
window._ocThemeInited = true;
|
||||||
|
|
||||||
|
if (document.readyState === 'loading') {
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
ocUpdateTheme();
|
||||||
|
ocHideEmptyCbiElements();
|
||||||
|
ocCenterCbiActions();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
ocUpdateTheme();
|
||||||
|
ocHideEmptyCbiElements();
|
||||||
|
ocCenterCbiActions();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Respond to OS-level theme changes when oc-theme is 'auto'.
|
||||||
|
if (window.matchMedia) {
|
||||||
|
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', function() {
|
||||||
|
if ((localStorage.getItem('oc-theme') || 'auto') === 'auto') {
|
||||||
|
ocApplyRootTheme();
|
||||||
|
if (document.readyState !== 'loading') ocUpdateTheme();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// ═══ General utilities ═══
|
||||||
|
|
||||||
function winOpen(url) {
|
function winOpen(url) {
|
||||||
var win = window.open(url);
|
var win = window.open(url);
|
||||||
if (win == null || typeof(win) == 'undefined') {
|
if (win == null) {
|
||||||
window.location.href = url;
|
window.location.href = url;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function ocFormatUnixTime(unixTimestamp) {
|
||||||
|
if (!unixTimestamp || unixTimestamp === 0) {
|
||||||
|
return '--';
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
var date = new Date(unixTimestamp * 1000);
|
||||||
|
var year = date.getFullYear();
|
||||||
|
var month = String(date.getMonth() + 1).padStart(2, '0');
|
||||||
|
var day = String(date.getDate()).padStart(2, '0');
|
||||||
|
var hour = String(date.getHours()).padStart(2, '0');
|
||||||
|
var minute = String(date.getMinutes()).padStart(2, '0');
|
||||||
|
var second = String(date.getSeconds()).padStart(2, '0');
|
||||||
|
return year + '-' + month + '-' + day + ' ' + hour + ':' + minute + ':' + second;
|
||||||
|
} catch (e) {
|
||||||
|
return '--';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function ocFormatBytes(bytes) {
|
||||||
|
if (bytes == null || bytes === 0) return '0 B';
|
||||||
|
var sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
|
||||||
|
var i = Math.floor(Math.log(bytes) / Math.log(1024));
|
||||||
|
if (i >= sizes.length) i = sizes.length - 1;
|
||||||
|
return (i === 0 ? bytes : (bytes / Math.pow(1024, i)).toFixed(1)) + ' ' + sizes[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
function ocFormatFileSize(bytes) {
|
||||||
|
if (!bytes || bytes === 0) return '--';
|
||||||
|
return ocFormatBytes(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ocDebounce(fn, delay) {
|
||||||
|
var timer = null;
|
||||||
|
return function(btn) {
|
||||||
|
var key = btn.id || btn.value;
|
||||||
|
if (timer) clearTimeout(timer);
|
||||||
|
btn.disabled = true;
|
||||||
|
timer = setTimeout(function() {
|
||||||
|
try { fn(btn); } finally { timer = null; }
|
||||||
|
}, delay || 300);
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function ocGetDashboardBaseURL(status) {
|
||||||
|
var host, port, proto;
|
||||||
|
if (status.daip && window.location.hostname === status.daip) {
|
||||||
|
host = window.location.hostname;
|
||||||
|
port = status.cn_port;
|
||||||
|
proto = 'http://';
|
||||||
|
} else if (status.daip && status.db_foward_domain && status.db_foward_port) {
|
||||||
|
host = status.db_foward_domain;
|
||||||
|
port = status.db_foward_port;
|
||||||
|
proto = (status.db_forward_ssl == 0 ? 'http://' : 'https://');
|
||||||
|
} else {
|
||||||
|
host = window.location.hostname;
|
||||||
|
port = status.cn_port;
|
||||||
|
proto = 'http://';
|
||||||
|
}
|
||||||
|
return { host: host, port: port, proto: proto, secret: status.dase || '' };
|
||||||
|
}
|
||||||
|
|
||||||
|
function ocBuildDashboardURL(status, uiPath, needsSetup) {
|
||||||
|
var base = ocGetDashboardBaseURL(status);
|
||||||
|
var url = base.proto + base.host + ':' + base.port + '/ui/' + uiPath;
|
||||||
|
if (needsSetup) {
|
||||||
|
url += '/#/setup?hostname=' + base.host + '&port=' + base.port;
|
||||||
|
if (base.secret) url += '&secret=' + base.secret;
|
||||||
|
} else if (uiPath === 'yacd') {
|
||||||
|
url += '/?hostname=' + base.host + '&port=' + base.port;
|
||||||
|
if (base.secret) url += '&secret=' + base.secret;
|
||||||
|
} else if (uiPath === 'dashboard') {
|
||||||
|
url += '/#/?host=' + base.host + '&port=' + base.port;
|
||||||
|
if (base.secret) url += '&secret=' + base.secret;
|
||||||
|
}
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ═══ Editor state ═══
|
||||||
|
|
||||||
|
window._ocFullscreenActive = false;
|
||||||
|
window._ocMergeShowDifferences = true;
|
||||||
|
window._ocEditorHotkeysBound = false;
|
||||||
|
window._ocFullscreenPatch = null;
|
||||||
|
|
||||||
|
window._ocZoomLevels = [75, 90, 100, 110, 125, 150, 200];
|
||||||
|
window._ocCurrentZoom = 100;
|
||||||
|
|
||||||
|
// ═══ Editor — fullscreen ═══
|
||||||
|
// Walk ancestors and patch stacking contexts so position:fixed can
|
||||||
|
// break out. backdrop-filter traps fixed children (creates a
|
||||||
|
// containing block); positioned+z-index creates a stacking context.
|
||||||
|
// We fix the closest backdrop-filter and the outermost z-index.
|
||||||
|
|
||||||
|
// Handles both EditorView (.dom) and MergeView (.a.dom, .b.dom)
|
||||||
|
function ocGetEditorDom(instance) {
|
||||||
|
if (!instance) return null;
|
||||||
|
if (instance.dom) return instance.dom;
|
||||||
|
if (instance.a && instance.a.dom) return instance.a.dom;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _ocEnterFullscreen(dom) {
|
||||||
|
_ocExitFullscreen();
|
||||||
|
var patch = window._ocFullscreenPatch = {};
|
||||||
|
var el = dom.parentNode;
|
||||||
|
while (el && el !== document.body && el !== document.documentElement) {
|
||||||
|
var cs = window.getComputedStyle(el);
|
||||||
|
if (!patch.bfEl) {
|
||||||
|
var bf = cs.backdropFilter || cs.webkitBackdropFilter;
|
||||||
|
if (bf && bf !== 'none') {
|
||||||
|
patch.bfEl = el;
|
||||||
|
patch.bfOld = el.style.backdropFilter;
|
||||||
|
el.style.backdropFilter = 'none';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var pos = cs.position;
|
||||||
|
var zi = cs.zIndex;
|
||||||
|
if ((pos === 'relative' || pos === 'absolute' || pos === 'fixed' || pos === 'sticky') && zi !== 'auto') {
|
||||||
|
patch.zEl = el;
|
||||||
|
patch.zOld = el.style.zIndex;
|
||||||
|
}
|
||||||
|
el = el.parentNode;
|
||||||
|
}
|
||||||
|
if (patch.zEl) {
|
||||||
|
patch.zEl.style.setProperty('z-index', '999999', 'important');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function _ocExitFullscreen() {
|
||||||
|
var p = window._ocFullscreenPatch;
|
||||||
|
if (!p) return;
|
||||||
|
if (p.zEl) {
|
||||||
|
if (p.zOld !== undefined && p.zOld !== '') {
|
||||||
|
p.zEl.style.zIndex = p.zOld;
|
||||||
|
} else {
|
||||||
|
p.zEl.style.removeProperty('z-index');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (p.bfEl) {
|
||||||
|
if (p.bfOld !== undefined && p.bfOld !== '') {
|
||||||
|
p.bfEl.style.backdropFilter = p.bfOld;
|
||||||
|
} else {
|
||||||
|
p.bfEl.style.removeProperty('backdrop-filter');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
window._ocFullscreenPatch = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ═══ Editor — lookup ═══
|
||||||
|
// Priority: merge editor state > ConfigEditor modal > CM6.getActiveEditor()
|
||||||
|
|
||||||
|
function ocGetActiveEditorInstance() {
|
||||||
|
if (window._mergeEditorState && window._mergeEditorState.instance) {
|
||||||
|
return window._mergeEditorState.instance;
|
||||||
|
}
|
||||||
|
if (window.ConfigEditor && window.ConfigEditor.editorInstance) {
|
||||||
|
return window.ConfigEditor.editorInstance;
|
||||||
|
}
|
||||||
|
if (typeof CM6 !== 'undefined' && CM6.getActiveEditor) {
|
||||||
|
return CM6.getActiveEditor();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ═══ Editor — zoom ═══
|
||||||
|
// Applies zoom-{level} CSS class to .cm-editor elements.
|
||||||
|
// For MergeView, applies to BOTH side panels so the .oc .cm-editor.zoom-XX rules match.
|
||||||
|
|
||||||
|
function ocApplyZoom(instance, zoomLevel) {
|
||||||
|
var doms = [];
|
||||||
|
if (instance) {
|
||||||
|
if (instance.a && instance.a.dom && instance.b && instance.b.dom) {
|
||||||
|
doms = [instance.a.dom, instance.b.dom];
|
||||||
|
} else if (instance.dom) {
|
||||||
|
doms = [instance.dom];
|
||||||
|
} else if (instance.classList && instance.classList.contains('cm-editor')) {
|
||||||
|
doms = [instance];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!doms.length) {
|
||||||
|
var activeEl = document.activeElement;
|
||||||
|
if (activeEl) {
|
||||||
|
var ed = activeEl.closest('.cm-editor');
|
||||||
|
if (ed) doms = [ed];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!doms.length) return;
|
||||||
|
|
||||||
|
doms.forEach(function(dom) {
|
||||||
|
window._ocZoomLevels.forEach(function(level) {
|
||||||
|
dom.classList.remove('zoom-' + level);
|
||||||
|
});
|
||||||
|
if (zoomLevel !== 100) {
|
||||||
|
dom.classList.add('zoom-' + zoomLevel);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
window._ocCurrentZoom = zoomLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns new zoom level without applying it
|
||||||
|
function ocZoomIn(currentZoom) {
|
||||||
|
var cur = typeof currentZoom === 'number' ? currentZoom : window._ocCurrentZoom;
|
||||||
|
var idx = window._ocZoomLevels.indexOf(cur);
|
||||||
|
if (idx < window._ocZoomLevels.length - 1) {
|
||||||
|
return window._ocZoomLevels[idx + 1];
|
||||||
|
}
|
||||||
|
return cur;
|
||||||
|
}
|
||||||
|
|
||||||
|
function ocZoomOut(currentZoom) {
|
||||||
|
var cur = typeof currentZoom === 'number' ? currentZoom : window._ocCurrentZoom;
|
||||||
|
var idx = window._ocZoomLevels.indexOf(cur);
|
||||||
|
if (idx > 0) {
|
||||||
|
return window._ocZoomLevels[idx - 1];
|
||||||
|
}
|
||||||
|
return cur;
|
||||||
|
}
|
||||||
|
|
||||||
|
function ocResetZoom() {
|
||||||
|
return 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Passthrough for CM5-era _cmWhenReady compatibility
|
||||||
|
window._cmWhenReady = function(cb) { cb(); };
|
||||||
|
|
||||||
|
// ═══ Theme — CM6 & CBI helpers ═══
|
||||||
|
|
||||||
|
// Apply theme to CodeMirror editors + highlight.js.
|
||||||
|
function ocUpdateTheme() {
|
||||||
|
ocApplyRootTheme();
|
||||||
|
var isDark = isDarkBackground(document.body);
|
||||||
|
if (typeof CM6 !== 'undefined' && CM6.dispatchTheme) {
|
||||||
|
var editors = document.querySelectorAll('.cm-editor');
|
||||||
|
for (var j = 0; j < editors.length; j++) {
|
||||||
|
var view = editors[j].cmView && editors[j].cmView.view;
|
||||||
|
if (view) {
|
||||||
|
try { CM6.dispatchTheme(view, isDark); } catch(e) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (typeof CM6 !== 'undefined' && CM6.mirrorThemeScrollbar) {
|
||||||
|
try { CM6.mirrorThemeScrollbar(); } catch(e) {}
|
||||||
|
}
|
||||||
|
if (typeof CM6 !== 'undefined' && CM6.switchHljsTheme) {
|
||||||
|
CM6.switchHljsTheme(isDark);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function ocHideEmptyCbiElements() {
|
||||||
|
var emptyEls = document.querySelectorAll('.cbi-section-table-titles, .cbi-section-table-descr, .cbi-section-descr');
|
||||||
|
for (var i = 0; i < emptyEls.length; i++) {
|
||||||
|
if (emptyEls[i].textContent.trim() === '') { emptyEls[i].style.display = 'none'; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function ocCenterCbiActions() {
|
||||||
|
var ids = ['Commit', 'Apply', 'Create', 'Back', 'Load_Config',
|
||||||
|
'Delete_Unused_Servers', 'Delete_Servers', 'Delete_Proxy_Provider', 'Delete_Groups',
|
||||||
|
'proxy_mg', 'rule_mg', 'pro_mg'];
|
||||||
|
for (var i = 0; i < ids.length; i++) {
|
||||||
|
var els = document.querySelectorAll('[id$="-' + ids[i] + '"]');
|
||||||
|
for (var j = 0; j < els.length; j++) {
|
||||||
|
els[j].style.textAlign = 'center';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ═══ Hotkeys ═══
|
||||||
|
// F11 fullscreen, F10 diff toggle, Esc exit, Ctrl+/-/0 zoom, Ctrl+Wheel zoom.
|
||||||
|
// Registered once globally (capture phase so it beats CM6's own key handling).
|
||||||
|
|
||||||
|
function ocRegisterEditorHotkeys() {
|
||||||
|
if (window._ocEditorHotkeysBound) return;
|
||||||
|
window._ocEditorHotkeysBound = true;
|
||||||
|
|
||||||
|
document.addEventListener('keydown', function(e) {
|
||||||
|
if ((e.ctrlKey || e.metaKey) && (e.key === '=' || e.key === '+')) {
|
||||||
|
var inst = ocGetActiveEditorInstance();
|
||||||
|
if (inst) {
|
||||||
|
e.preventDefault();
|
||||||
|
var newZoom = ocZoomIn();
|
||||||
|
ocApplyZoom(inst, newZoom);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((e.ctrlKey || e.metaKey) && e.key === '-') {
|
||||||
|
var inst = ocGetActiveEditorInstance();
|
||||||
|
if (inst) {
|
||||||
|
e.preventDefault();
|
||||||
|
var newZoom = ocZoomOut();
|
||||||
|
ocApplyZoom(inst, newZoom);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((e.ctrlKey || e.metaKey) && e.key === '0') {
|
||||||
|
var inst = ocGetActiveEditorInstance();
|
||||||
|
if (inst) {
|
||||||
|
e.preventDefault();
|
||||||
|
var newZoom = ocResetZoom();
|
||||||
|
ocApplyZoom(inst, newZoom);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.key === 'F11') {
|
||||||
|
e.preventDefault();
|
||||||
|
if (window._ocFullscreenActive) {
|
||||||
|
var fsEl = document.getElementById('oc-fullscreen-active');
|
||||||
|
if (fsEl && typeof CM6 !== 'undefined' && CM6.toggleFullscreen) {
|
||||||
|
CM6.toggleFullscreen(fsEl);
|
||||||
|
}
|
||||||
|
_ocExitFullscreen();
|
||||||
|
window._ocFullscreenActive = false;
|
||||||
|
if (window.ConfigEditor) window.ConfigEditor.isFullscreen = false;
|
||||||
|
} else {
|
||||||
|
if (typeof CM6 !== 'undefined' && CM6.getActiveEditor && CM6.toggleFullscreen) {
|
||||||
|
var target = CM6.getActiveEditor();
|
||||||
|
if (target) {
|
||||||
|
_ocEnterFullscreen(target);
|
||||||
|
window._ocFullscreenActive = !!CM6.toggleFullscreen(target);
|
||||||
|
if (window.ConfigEditor) window.ConfigEditor.isFullscreen = window._ocFullscreenActive;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ocUpdateTheme();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.key === 'F10' && window._mergeViewInstance && window._mergeViewInstance.reconfigure) {
|
||||||
|
e.preventDefault();
|
||||||
|
window._ocMergeShowDifferences = !window._ocMergeShowDifferences;
|
||||||
|
window._mergeViewInstance.reconfigure({
|
||||||
|
highlightChanges: window._ocMergeShowDifferences,
|
||||||
|
gutter: window._ocMergeShowDifferences
|
||||||
|
});
|
||||||
|
if (window._mergeViewInstance.dom) {
|
||||||
|
window._mergeViewInstance.dom.classList.toggle('oc-diff-hidden', !window._ocMergeShowDifferences);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.key === 'Escape' && window._ocFullscreenActive) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
var fsEl = document.getElementById('oc-fullscreen-active');
|
||||||
|
if (fsEl && typeof CM6 !== 'undefined' && CM6.toggleFullscreen) {
|
||||||
|
CM6.toggleFullscreen(fsEl);
|
||||||
|
}
|
||||||
|
_ocExitFullscreen();
|
||||||
|
window._ocFullscreenActive = false;
|
||||||
|
if (window.ConfigEditor) window.ConfigEditor.isFullscreen = false;
|
||||||
|
ocUpdateTheme();
|
||||||
|
}
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
// Separate listener — wheel needs {passive:false} for preventDefault
|
||||||
|
document.addEventListener('wheel', function(e) {
|
||||||
|
if (e.ctrlKey || e.metaKey) {
|
||||||
|
if (e.target.closest && e.target.closest('#config-editor-overlay')) return;
|
||||||
|
var inst = ocGetActiveEditorInstance();
|
||||||
|
if (inst) {
|
||||||
|
e.preventDefault();
|
||||||
|
var newZoom = e.deltaY < 0 ? ocZoomIn() : ocZoomOut();
|
||||||
|
ocApplyZoom(inst, newZoom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, { passive: false });
|
||||||
|
}
|
||||||
|
|
||||||
|
// ═══ Loading overlay ═══
|
||||||
|
|
||||||
|
var _ocLoadingMap = typeof WeakMap !== 'undefined' ? new WeakMap() : (function(){
|
||||||
|
var m = {};
|
||||||
|
return {
|
||||||
|
get: function(k) { return m[k._ocLid]; },
|
||||||
|
set: function(k, v) { var id = '_ocl' + Math.random(); k._ocLid = id; m[id] = v; },
|
||||||
|
delete: function(k) { delete m[k._ocLid]; }
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
|
function ocShowLoading(container, message, minHeight) {
|
||||||
|
if (!container) return;
|
||||||
|
var prevPos = container.style.position;
|
||||||
|
var prevMinH = container.style.minHeight;
|
||||||
|
container.style.position = 'relative';
|
||||||
|
if (minHeight) container.style.minHeight = minHeight;
|
||||||
|
var el = document.createElement('div');
|
||||||
|
el.className = 'config-editor-loading';
|
||||||
|
el.innerHTML = '<div class="loading-spinner"></div><span>' + (message || 'Loading\u2026') + '</span>';
|
||||||
|
container.appendChild(el);
|
||||||
|
_ocLoadingMap.set(container, { el: el, prevPos: prevPos, prevMinH: prevMinH });
|
||||||
|
}
|
||||||
|
|
||||||
|
function ocHideLoading(container) {
|
||||||
|
if (!container) return;
|
||||||
|
var handle = _ocLoadingMap.get(container);
|
||||||
|
if (!handle) return;
|
||||||
|
if (handle.el && handle.el.parentNode) handle.el.remove();
|
||||||
|
container.style.position = handle.prevPos || '';
|
||||||
|
if (handle.prevMinH !== undefined) {
|
||||||
|
container.style.minHeight = handle.prevMinH;
|
||||||
|
}
|
||||||
|
_ocLoadingMap.delete(container);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ═══ Clipboard ═══
|
||||||
|
|
||||||
|
window.ocCopyToClipboard = function(text, btnElement, successMessage, failMessage) {
|
||||||
|
if (navigator.clipboard && navigator.clipboard.writeText) {
|
||||||
|
navigator.clipboard.writeText(text).then(function() {
|
||||||
|
ocShowCopySuccess(btnElement);
|
||||||
|
}).catch(function() {
|
||||||
|
ocFallbackCopy(text, btnElement, successMessage, failMessage);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
ocFallbackCopy(text, btnElement, successMessage, failMessage);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function ocShowCopySuccess(element) {
|
||||||
|
if (!element) return;
|
||||||
|
var origHTML = element.innerHTML;
|
||||||
|
element.innerHTML = '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg>';
|
||||||
|
element.classList.add('copy-success');
|
||||||
|
setTimeout(function() {
|
||||||
|
element.innerHTML = origHTML;
|
||||||
|
element.classList.remove('copy-success');
|
||||||
|
}, 1500);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ocFallbackCopy(text, btnElement, successMessage, failMessage) {
|
||||||
|
var ta = document.createElement('textarea');
|
||||||
|
ta.value = text;
|
||||||
|
ta.style.cssText = 'position:fixed;top:0;left:0;opacity:0';
|
||||||
|
document.body.appendChild(ta);
|
||||||
|
ta.select();
|
||||||
|
var ok = false;
|
||||||
|
try { ok = document.execCommand('copy'); } catch(e) {}
|
||||||
|
document.body.removeChild(ta);
|
||||||
|
if (ok) {
|
||||||
|
ocShowCopySuccess(btnElement);
|
||||||
|
} else if (failMessage) {
|
||||||
|
prompt(failMessage, text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ocApplyRootTheme();
|
||||||
|
ocInitTheme();
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
// oc-icons.js — OpenClash unified SVG icon library
|
||||||
|
// Include in HTM files: <script src="/luci-static/resources/openclash/js/oc-icons.js?v=<%=plugin_version%>"></script>
|
||||||
|
(function() {
|
||||||
|
var SPRITE_ID = 'oc-icon-sprite';
|
||||||
|
if (document.getElementById(SPRITE_ID)) return;
|
||||||
|
|
||||||
|
var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
||||||
|
svg.id = SPRITE_ID;
|
||||||
|
svg.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
|
||||||
|
svg.setAttribute('style', 'display:none;position:absolute;width:0;height:0');
|
||||||
|
svg.setAttribute('aria-hidden', 'true');
|
||||||
|
|
||||||
|
svg.innerHTML = [
|
||||||
|
'<symbol id="oc-icon-refresh" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M23 4v6h-6"/><path d="M20.49 15a9 9 0 1 1-2.12-9.36L23 10"/></symbol>',
|
||||||
|
'<symbol id="oc-icon-close" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></symbol>',
|
||||||
|
'<symbol id="oc-icon-copy" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></symbol>',
|
||||||
|
'<symbol id="oc-icon-megaphone" viewBox="0 0 256 256" fill="currentColor"><path d="M228.54,86.66l-176.06-54A16,16,0,0,0,32,48V192a16,16,0,0,0,16,16,16,16,0,0,0,4.52-.65L136,181.73V192a16,16,0,0,0,16,16h32a16,16,0,0,0,16-16v-29.9l28.54-8.75A16.09,16.09,0,0,0,240,138V102A16.09,16.09,0,0,0,228.54,86.66ZM136,165,48,192V48l88,27Zm48,27H152V176.82L184,167Zm40-54-.11,0L152,160.08V79.92l71.89,22,.11,0v36Z"/></symbol>',
|
||||||
|
'<symbol id="oc-icon-shield-check" viewBox="0 0 48 48" fill="none" stroke="currentColor" stroke-width="4" stroke-linejoin="round"><path d="M6 9.25564L24.0086 4L42 9.25564V20.0337C42 31.3622 34.7502 41.4194 24.0026 45.0005C13.2521 41.4195 6 31.36 6 20.0287V9.25564Z"/><path d="M15 23L22 30L34 18" stroke-linecap="round" stroke-linejoin="round"/></symbol>',
|
||||||
|
'<symbol id="oc-icon-lock" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="11" width="18" height="11" rx="2"/><circle cx="12" cy="16" r="1"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></symbol>',
|
||||||
|
'<symbol id="oc-icon-home" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9.75,20.25V14.25h4.5v6h6V11.25a0.75,0.75,0,0,0-0.22-0.53l-7.5-7.5a0.75,0.75,0,0,0-1.06,0l-7.5,7.5A0.75,0.75,0,0,0,3.75,11.25v9Z"/></symbol>',
|
||||||
|
'<symbol id="oc-icon-globe" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="3" y1="12" x2="21" y2="12"/><circle cx="12" cy="12" r="9"/><path d="M15.75,12c0,6-3.75,9-3.75,9s-3.75-3-3.75-9,3.75-9,3.75-9S15.75,6,15.75,12Z"/></symbol>',
|
||||||
|
'<symbol id="oc-icon-edit" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/></symbol>',
|
||||||
|
'<symbol id="oc-icon-upload" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></symbol>',
|
||||||
|
'<symbol id="oc-icon-download" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7,11 12,16 17,11"/><line x1="12" y1="2" x2="12" y2="16"/></symbol>',
|
||||||
|
'<symbol id="oc-icon-save" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"/><polyline points="17,21 17,13 7,13 7,21"/><polyline points="7,3 7,8 15,8"/></symbol>',
|
||||||
|
'<symbol id="oc-icon-switch" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="17 1 21 5 17 9"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><polyline points="7 23 3 19 7 15"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/></symbol>',
|
||||||
|
'<symbol id="oc-icon-update" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 12a9 9 0 0 0-9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"/><path d="M3 3v5h5"/><path d="M3 12a9 9 0 0 0 9 9 9.75 9.75 0 0 0 6.74-2.74L21 16"/><path d="M21 21v-5h-5"/></symbol>',
|
||||||
|
'<symbol id="oc-icon-compare" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="2" y="3" width="8" height="18" rx="2"/><rect x="14" y="3" width="8" height="18" rx="2"/></symbol>',
|
||||||
|
'<symbol id="oc-icon-restore" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="18" height="18" rx="2"/></symbol>',
|
||||||
|
'<symbol id="oc-icon-help" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"/><line x1="12" y1="17" x2="12.01" y2="17"/></symbol>',
|
||||||
|
'<symbol id="oc-icon-chat" viewBox="0 0 48 48" fill="none" stroke="currentColor" stroke-width="4"><path d="M4 6H44V36H29L24 41L19 36H4V6Z"/><path d="M23 21H25.0025"/><path d="M33.001 21H34.9999"/><path d="M13.001 21H14.9999"/></symbol>',
|
||||||
|
'<symbol id="oc-icon-overwrite" viewBox="0 0 256 256" fill="currentColor"><path d="M12,111l112,64a8,8,0,0,0,7.94,0l112-64a8,8,0,0,0,0-13.9l-112-64a8,8,0,0,0-7.94,0l-112,64A8,8,0,0,0,12,111ZM128,49.21,223.87,104,128,158.79,32.13,104ZM246.94,140A8,8,0,0,1,244,151L132,215a8,8,0,0,1-7.94,0L12,151A8,8,0,0,1,20,137.05l108,61.74,108-61.74A8,8,0,0,1,246.94,140Z"/></symbol>',
|
||||||
|
'<symbol id="oc-icon-sun" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="5"/><line x1="12" y1="1" x2="12" y2="3"/><line x1="12" y1="21" x2="12" y2="23"/><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/><line x1="1" y1="12" x2="3" y2="12"/><line x1="21" y1="12" x2="23" y2="12"/><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"/></symbol>',
|
||||||
|
'<symbol id="oc-icon-moon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/></symbol>',
|
||||||
|
'<symbol id="oc-icon-auto-theme" viewBox="0 0 48 48" fill="none" stroke="currentColor" stroke-width="4"><path d="M24 44C29.9601 44 26.3359 35.136 30 31C33.1264 27.4709 44 29.0856 44 24C44 12.9543 35.0457 4 24 4C12.9543 4 4 12.9543 4 24C4 35.0457 12.9543 44 24 44Z"/><path d="M28 17C29.6569 17 31 15.6569 31 14C31 12.3431 29.6569 11 28 11C26.3431 11 25 12.3431 25 14C25 15.6569 26.3431 17 28 17Z"/><path d="M16 21C17.6569 21 19 19.6569 19 18C19 16.3431 17.6569 15 16 15C14.3431 15 13 16.3431 13 18C13 19.6569 14.3431 21 16 21Z"/><path d="M17 34C18.6569 34 20 32.6569 20 31C20 29.3431 18.6569 28 17 28C15.3431 28 14 29.3431 14 31C14 32.6569 15.3431 34 17 34Z"/></symbol>',
|
||||||
|
'<symbol id="oc-icon-wiki" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 10v6M2 10l10-5 10 5-10 5z"/><path d="M6 12v5c3 3 9 3 12 0v-5"/></symbol>',
|
||||||
|
'<symbol id="oc-icon-book" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"/><path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"/></symbol>',
|
||||||
|
'<symbol id="oc-icon-star" viewBox="0 0 24 24" fill="currentColor"><path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/></symbol>',
|
||||||
|
'<symbol id="oc-icon-telegram" viewBox="0 0 256 256" fill="none" stroke="currentColor" stroke-width="20"><path d="M80,134.87,170.26,214a8,8,0,0,0,13.09-4.21L224,33.22a1,1,0,0,0-1.34-1.15L20,111.38A6.23,6.23,0,0,0,21,123.3Z" stroke-linecap="round" stroke-linejoin="round"/><line x1="80" y1="134.87" x2="223.41" y2="32.09" stroke-linecap="round" stroke-linejoin="round"/><path d="M124.37,173.78,93.76,205.54A8,8,0,0,1,80,200V134.87" stroke-linecap="round" stroke-linejoin="round"/></symbol>',
|
||||||
|
'<symbol id="oc-icon-heart" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"/></symbol>',
|
||||||
|
'<symbol id="oc-icon-settings" viewBox="0 0 48 48" fill="none" stroke="currentColor" stroke-width="4" stroke-linejoin="round"><path d="M18.2838 43.1713C14.9327 42.1736 11.9498 40.3213 9.58787 37.867C10.469 36.8227 11 35.4734 11 34.0001C11 30.6864 8.31371 28.0001 5 28.0001C4.79955 28.0001 4.60139 28.01 4.40599 28.0292C4.13979 26.7277 4 25.3803 4 24.0001C4 21.9095 4.32077 19.8938 4.91579 17.9995C4.94381 17.9999 4.97188 18.0001 5 18.0001C8.31371 18.0001 11 15.3138 11 12.0001C11 11.0488 10.7786 10.1493 10.3846 9.35011C12.6975 7.1995 15.5205 5.59002 18.6521 4.72314C19.6444 6.66819 21.6667 8.00013 24 8.00013C26.3333 8.00013 28.3556 6.66819 29.3479 4.72314C32.4795 5.59002 35.3025 7.1995 37.6154 9.35011C37.2214 10.1493 37 11.0488 37 12.0001C37 15.3138 39.6863 18.0001 43 18.0001C43.0281 18.0001 43.0562 17.9999 43.0842 17.9995C43.6792 19.8938 44 21.9095 44 24.0001C44 25.3803 43.8602 26.7277 43.594 28.0292C43.3986 28.01 43.2005 28.0001 43 28.0001C39.6863 28.0001 37 30.6864 37 34.0001C37 35.4734 37.531 36.8227 38.4121 37.867C36.0502 40.3213 33.0673 42.1736 29.7162 43.1713C28.9428 40.752 26.676 39.0001 24 39.0001C21.324 39.0001 19.0572 40.752 18.2838 43.1713Z"/><path d="M24 31C27.866 31 31 27.866 31 24C31 20.134 27.866 17 24 17C20.134 17 17 20.134 17 24C17 27.866 20.134 31 24 31Z"/></symbol>',
|
||||||
|
'<symbol id="oc-icon-document" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="4" y="4" width="16" height="16" rx="2"/><line x1="8" y1="8" x2="16" y2="8"/><line x1="8" y1="12" x2="16" y2="12"/><line x1="8" y1="16" x2="12" y2="16"/></symbol>',
|
||||||
|
'<symbol id="oc-icon-lightning" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polygon points="13 2 3 14 12 14 11 22 21 10 13 10 13 2"/></symbol>',
|
||||||
|
'<symbol id="oc-icon-alert-circle" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12" y2="16"/></symbol>',
|
||||||
|
'<symbol id="oc-icon-link" viewBox="0 0 48 48" fill="none" stroke="currentColor" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"><path d="M26.2401 16.373L17.1001 7.23303C14.4388 4.57168 10.0653 4.6303 7.33158 7.36397C4.59791 10.0976 4.53929 14.4712 7.20064 17.1325L15.1359 25.0678"/><path d="M32.9027 23.0031L40.838 30.9384C43.4994 33.5998 43.4407 37.9733 40.7071 40.707C37.9734 43.4407 33.5999 43.4993 30.9385 40.8379L21.7985 31.6979"/><path d="M26.1093 26.1416C28.843 23.4079 28.9016 19.0344 26.2403 16.373"/><path d="M21.7989 21.7984C19.0652 24.5321 19.0066 28.9056 21.6679 31.5669"/></symbol>',
|
||||||
|
'<symbol id="oc-icon-key" viewBox="0 0 16 16" fill="currentColor"><path d="M10.5 0a5.499 5.499 0 1 1-1.288 10.848l-.932.932a.749.749 0 0 1-.53.22H7v.75a.749.749 0 0 1-.22.53l-.5.5a.749.749 0 0 1-.53.22H5v.75a.749.749 0 0 1-.22.53l-.5.5a.749.749 0 0 1-.53.22h-2A1.75 1.75 0 0 1 0 14.25v-2c0-.199.079-.389.22-.53l4.932-4.932A5.5 5.5 0 0 1 10.5 0Zm-4 5.5c-.001.431.069.86.205 1.269a.75.75 0 0 1-.181.768L1.5 12.56v1.69c0 .138.112.25.25.25h1.69l.06-.06v-1.19a.75.75 0 0 1 .75-.75h1.19l.06-.06v-1.19a.75.75 0 0 1 .75-.75h1.19l1.023-1.025a.75.75 0 0 1 .768-.18A4 4 0 1 0 6.5 5.5ZM11 6a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z"/></symbol>',
|
||||||
|
'<symbol id="oc-icon-calculator" viewBox="0 0 48 48" fill="none" stroke="currentColor" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"><path d="M28 32.5H42"/><path d="M28 41.5H42"/><path d="M6 13H22"/><path d="M14 5L14 21"/><path d="M42 5L6 41"/></symbol>',
|
||||||
|
'<symbol id="oc-icon-chevron-down" viewBox="0 0 24 24" fill="currentColor"><polygon points="6,9 18,9 12,15"/></symbol>',
|
||||||
|
'<symbol id="oc-icon-trash" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2v2"/></symbol>',
|
||||||
|
'<symbol id="oc-icon-info" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></symbol>',
|
||||||
|
'<symbol id="oc-icon-usage-help" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="7" width="18" height="13" rx="2"/><circle cx="9" cy="13" r="1"/><circle cx="15" cy="13" r="1"/><line x1="9" y1="17" x2="15" y2="17"/><path d="M12 3v4"/><circle cx="12" cy="3" r="1"/></symbol>',
|
||||||
|
'<symbol id="oc-icon-eye" viewBox="0 0 256 256" fill="none" stroke="currentColor" stroke-width="12" stroke-linecap="round" stroke-linejoin="round"><path d="M128,56C48,56,16,128,16,128s32,72,112,72,112-72,112-72S208,56,128,56Z"/><circle cx="128" cy="128" r="40"/></symbol>',
|
||||||
|
'<symbol id="oc-icon-eye-off" viewBox="0 0 256 256" fill="none" stroke="currentColor" stroke-width="12" stroke-linecap="round" stroke-linejoin="round"><line x1="48" y1="40" x2="208" y2="216"/><path d="M154.9,157.6A39.6,39.6,0,0,1,128,168a40,40,0,0,1-26.9-69.6"/><path d="M74,68.6C33.2,89.2,16,128,16,128s32,72,112,72a117.9,117.9,0,0,0,54-12.6"/><path d="M208.6,169.1C230.4,149.6,240,128,240,128S208,56,128,56a123.9,123.9,0,0,0-20.7,1.7"/><path d="M135.5,88.7a39.9,39.9,0,0,1,32.3,35.5"/></symbol>',
|
||||||
|
'<symbol id="oc-icon-success" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="20 6 9 17 4 12"/></symbol>',
|
||||||
|
'<symbol id="oc-icon-error" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><circle cx="12" cy="12" r="10"/><line x1="15" y1="9" x2="9" y2="15"/><line x1="9" y1="9" x2="15" y2="15"/></symbol>',
|
||||||
|
'<symbol id="oc-icon-copy-bold" viewBox="0 0 24 24" fill="currentColor"><path d="M16 1H4a2 2 0 00-2 2v12h2V3h12V1zM20 5H8a2 2 0 00-2 2v14a2 2 0 002 2h12a2 2 0 002-2V7a2 2 0 00-2-2zm0 16H8V7h12v14z"/></symbol>',
|
||||||
|
'<symbol id="oc-icon-user" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></symbol>',
|
||||||
|
'<symbol id="oc-icon-login" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4"/><polyline points="10 17 15 12 10 7"/><line x1="15" y1="12" x2="3" y2="12"/></symbol>',
|
||||||
|
'<symbol id="oc-icon-gift" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="20 12 20 22 4 22 4 12"/><rect x="2" y="7" width="20" height="5"/><line x1="12" y1="22" x2="12" y2="7"/><path d="M12 7H7.5a2.5 2.5 0 0 1 0-5C11 2 12 7 12 7z"/><path d="M12 7h4.5a2.5 2.5 0 0 0 0-5C13 2 12 7 12 7z"/></symbol>',
|
||||||
|
'<symbol id="oc-icon-logout" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/><polyline points="16,17 21,12 16,7"/><line x1="21" y1="12" x2="9" y2="12"/></symbol>',
|
||||||
|
'<symbol id="oc-icon-bell" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"/><path d="M13.73 21a2 2 0 0 1-3.46 0"/></symbol>',
|
||||||
|
'<symbol id="oc-icon-key-oix" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 2l-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.778 7.778 5.5 5.5 0 0 1 7.777-7.777zm0 0L15.5 7.5m0 0l3 3L22 7l-3-3m-3.5 3.5L19 4"/></symbol>',
|
||||||
|
'<symbol id="oc-icon-chevron-oix" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="6 9 12 15 18 9"/></symbol>',
|
||||||
|
'<symbol id="oc-icon-badge" viewBox="0 0 48 48" fill="none" stroke="currentColor" stroke-width="4" stroke-linejoin="round"><path d="M9 40L4 17L14 22L24 8L34 22L44 17L39 40H9Z"/><path d="M24 33C26.2091 33 28 31.2091 28 29C28 26.7909 26.2091 25 24 25C21.7909 25 20 26.7909 20 29C20 31.2091 21.7909 33 24 33Z"/></symbol>'
|
||||||
|
].join('');
|
||||||
|
|
||||||
|
document.body.insertBefore(svg, document.body.firstChild);
|
||||||
|
})();
|
||||||
+388
@@ -0,0 +1,388 @@
|
|||||||
|
(function(window, document) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var cache = {};
|
||||||
|
var defaultLabels = {
|
||||||
|
checking: 'Checking backend version...',
|
||||||
|
versionPrefix: 'Backend Version',
|
||||||
|
empty: 'Please enter backend URL',
|
||||||
|
invalid: 'Invalid backend URL',
|
||||||
|
unrecognized: 'Backend version information not detected',
|
||||||
|
failed: 'Unable to detect backend version'
|
||||||
|
};
|
||||||
|
|
||||||
|
function $(target) {
|
||||||
|
if (!target) return null;
|
||||||
|
if (typeof target === 'string') return document.querySelector(target);
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isElement(target) {
|
||||||
|
return target && target.nodeType === 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
function extend(base, extra) {
|
||||||
|
var result = {};
|
||||||
|
var key;
|
||||||
|
for (key in base) result[key] = base[key];
|
||||||
|
extra = extra || {};
|
||||||
|
for (key in extra) result[key] = extra[key];
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeBackendURL(value) {
|
||||||
|
value = String(value || '').trim();
|
||||||
|
if (!value) return { error: 'empty' };
|
||||||
|
|
||||||
|
if (!/^[a-z][a-z0-9+\-.]*:\/\//i.test(value)) {
|
||||||
|
value = 'https://' + value;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
var url = new URL(value);
|
||||||
|
if (url.protocol !== 'http:' && url.protocol !== 'https:') {
|
||||||
|
return { error: 'invalid' };
|
||||||
|
}
|
||||||
|
var versionURLs = buildVersionURLs(url);
|
||||||
|
return {
|
||||||
|
base: url.origin,
|
||||||
|
versionURL: versionURLs[0],
|
||||||
|
versionURLs: versionURLs
|
||||||
|
};
|
||||||
|
} catch (e) {
|
||||||
|
return { error: 'invalid' };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function addUniqueURL(list, value) {
|
||||||
|
if (list.indexOf(value) === -1) list.push(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildVersionURLs(url) {
|
||||||
|
var versionURLs = [];
|
||||||
|
var path = (url.pathname || '').replace(/\/+$/, '');
|
||||||
|
var pathBase;
|
||||||
|
|
||||||
|
if (path && path !== '/') {
|
||||||
|
pathBase = path.replace(/\/sub$/i, '');
|
||||||
|
if (pathBase) addUniqueURL(versionURLs, url.origin + pathBase + '/version');
|
||||||
|
}
|
||||||
|
|
||||||
|
addUniqueURL(versionURLs, url.origin + '/version');
|
||||||
|
return versionURLs;
|
||||||
|
}
|
||||||
|
|
||||||
|
function readElementValue(element) {
|
||||||
|
var selected;
|
||||||
|
var hidden;
|
||||||
|
|
||||||
|
if (!element) return '';
|
||||||
|
if (element.classList && element.classList.contains('cbi-dropdown')) {
|
||||||
|
if (typeof element.value !== 'undefined' && element.value !== null) return element.value;
|
||||||
|
selected = element.querySelector('li[selected][data-value]');
|
||||||
|
if (selected) return selected.getAttribute('data-value') || '';
|
||||||
|
hidden = element.querySelector('input[type="hidden"]');
|
||||||
|
return hidden ? hidden.value : '';
|
||||||
|
}
|
||||||
|
return element.value || '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSelectedBackend(selectEl, customInputEl) {
|
||||||
|
if (!selectEl) return '';
|
||||||
|
if (readElementValue(selectEl) === 'custom') {
|
||||||
|
return readElementValue(customInputEl);
|
||||||
|
}
|
||||||
|
return readElementValue(selectEl);
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderStatus(statusEl, state, message, labels) {
|
||||||
|
if (!statusEl) return;
|
||||||
|
|
||||||
|
statusEl.hidden = false;
|
||||||
|
statusEl.setAttribute('data-state', state);
|
||||||
|
|
||||||
|
var labelEl = statusEl.querySelector('.subconverter-version-label');
|
||||||
|
var textEl = statusEl.querySelector('.subconverter-version-text');
|
||||||
|
var showLabel = state === 'success';
|
||||||
|
|
||||||
|
if (labelEl) {
|
||||||
|
labelEl.textContent = showLabel ? labels.versionPrefix + ':' : '';
|
||||||
|
labelEl.style.display = showLabel ? '' : 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (textEl) textEl.textContent = message || '';
|
||||||
|
else statusEl.textContent = message || '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function hideStatus(statusEl) {
|
||||||
|
if (!statusEl) return;
|
||||||
|
statusEl.hidden = true;
|
||||||
|
statusEl.setAttribute('data-state', 'idle');
|
||||||
|
}
|
||||||
|
|
||||||
|
function sanitizeVersionText(text) {
|
||||||
|
text = String(text || '').replace(/\r/g, '\n').split('\n').map(function(line) {
|
||||||
|
return line.trim();
|
||||||
|
}).filter(Boolean).join(' ');
|
||||||
|
text = text.replace(/\s+/g, ' ').trim();
|
||||||
|
|
||||||
|
if (!text) return '';
|
||||||
|
if (/<\s*\/?\s*[a-z!][^>]*>/i.test(text)) return '';
|
||||||
|
if (text.length > 220) return '';
|
||||||
|
if (!/(subconverter|backend|\bversion\b|v?\d+(?:\.\d+){1,})/i.test(text)) return '';
|
||||||
|
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
function fetchDirectVersion(versionURL, timeoutMs, signal) {
|
||||||
|
var controller = typeof AbortController !== 'undefined' ? new AbortController() : null;
|
||||||
|
var timeoutId;
|
||||||
|
|
||||||
|
if (controller && signal) {
|
||||||
|
if (signal.aborted) controller.abort();
|
||||||
|
else signal.addEventListener('abort', function() {
|
||||||
|
controller.abort();
|
||||||
|
}, { once: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (controller && timeoutMs > 0) {
|
||||||
|
timeoutId = window.setTimeout(function() {
|
||||||
|
controller.abort();
|
||||||
|
}, timeoutMs);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fetch(versionURL, {
|
||||||
|
method: 'GET',
|
||||||
|
mode: 'cors',
|
||||||
|
credentials: 'omit',
|
||||||
|
cache: 'no-store',
|
||||||
|
referrerPolicy: 'no-referrer',
|
||||||
|
headers: {
|
||||||
|
'Accept': 'text/plain, */*'
|
||||||
|
},
|
||||||
|
signal: controller ? controller.signal : undefined
|
||||||
|
}).then(function(response) {
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error('HTTP ' + response.status);
|
||||||
|
}
|
||||||
|
return response.text();
|
||||||
|
}).then(function(text) {
|
||||||
|
if (timeoutId) window.clearTimeout(timeoutId);
|
||||||
|
var version = sanitizeVersionText(text);
|
||||||
|
if (!version) return { state: 'unrecognized', text: '' };
|
||||||
|
return { state: 'success', text: version };
|
||||||
|
}).catch(function(error) {
|
||||||
|
if (timeoutId) window.clearTimeout(timeoutId);
|
||||||
|
if (signal && signal.aborted) return { state: 'aborted', text: '' };
|
||||||
|
throw error;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function fetchProxiedVersion(versionURL, proxyURL, timeoutMs, signal) {
|
||||||
|
if (!proxyURL) return Promise.reject(new Error('Proxy endpoint unavailable'));
|
||||||
|
|
||||||
|
var controller = typeof AbortController !== 'undefined' ? new AbortController() : null;
|
||||||
|
var timeoutId;
|
||||||
|
var separator = proxyURL.indexOf('?') === -1 ? '?' : '&';
|
||||||
|
|
||||||
|
if (controller && signal) {
|
||||||
|
if (signal.aborted) controller.abort();
|
||||||
|
else signal.addEventListener('abort', function() {
|
||||||
|
controller.abort();
|
||||||
|
}, { once: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (controller && timeoutMs > 0) {
|
||||||
|
timeoutId = window.setTimeout(function() {
|
||||||
|
controller.abort();
|
||||||
|
}, timeoutMs);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fetch(proxyURL + separator + 'url=' + encodeURIComponent(versionURL), {
|
||||||
|
method: 'GET',
|
||||||
|
credentials: 'same-origin',
|
||||||
|
cache: 'no-store',
|
||||||
|
headers: {
|
||||||
|
'Accept': 'application/json'
|
||||||
|
},
|
||||||
|
signal: controller ? controller.signal : undefined
|
||||||
|
}).then(function(response) {
|
||||||
|
if (!response.ok) throw new Error('HTTP ' + response.status);
|
||||||
|
return response.json();
|
||||||
|
}).then(function(data) {
|
||||||
|
if (timeoutId) window.clearTimeout(timeoutId);
|
||||||
|
if (data && data.status === 'success') {
|
||||||
|
var version = sanitizeVersionText(data.version || '');
|
||||||
|
if (version) return { state: 'success', text: version };
|
||||||
|
}
|
||||||
|
if (data && data.status === 'unrecognized') return { state: 'unrecognized', text: '' };
|
||||||
|
throw new Error((data && data.message) || 'Proxy request failed');
|
||||||
|
}).catch(function(error) {
|
||||||
|
if (timeoutId) window.clearTimeout(timeoutId);
|
||||||
|
if (signal && signal.aborted) return { state: 'aborted', text: '' };
|
||||||
|
throw error;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function fetchVersion(versionURL, timeoutMs, signal, proxyURL) {
|
||||||
|
return fetchDirectVersion(versionURL, timeoutMs, signal).catch(function(error) {
|
||||||
|
if (signal && signal.aborted) return { state: 'aborted', text: '' };
|
||||||
|
if (!proxyURL) throw error;
|
||||||
|
return fetchProxiedVersion(versionURL, proxyURL, timeoutMs, signal);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function fetchVersionCandidates(versionURLs, timeoutMs, signal, proxyURL) {
|
||||||
|
var index = 0;
|
||||||
|
var sawUnrecognized = false;
|
||||||
|
|
||||||
|
function next() {
|
||||||
|
if (signal && signal.aborted) return Promise.resolve({ state: 'aborted', text: '' });
|
||||||
|
|
||||||
|
return fetchVersion(versionURLs[index++], timeoutMs, signal, proxyURL).then(function(result) {
|
||||||
|
if (result.state === 'success' || result.state === 'aborted') return result;
|
||||||
|
sawUnrecognized = true;
|
||||||
|
if (index < versionURLs.length) return next();
|
||||||
|
return result;
|
||||||
|
}).catch(function(error) {
|
||||||
|
if (signal && signal.aborted) return { state: 'aborted', text: '' };
|
||||||
|
if (index < versionURLs.length) return next();
|
||||||
|
if (sawUnrecognized) return { state: 'unrecognized', text: '' };
|
||||||
|
throw error;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
|
||||||
|
function init(options) {
|
||||||
|
options = options || {};
|
||||||
|
var selectTarget = options.select;
|
||||||
|
var customInputTarget = options.customInput;
|
||||||
|
var enableTarget = options.enable;
|
||||||
|
var selectEl = $(selectTarget);
|
||||||
|
var customInputEl = $(customInputTarget);
|
||||||
|
var enableEl = $(enableTarget);
|
||||||
|
var statusEl = $(options.status);
|
||||||
|
var labels = extend(defaultLabels, options.labels);
|
||||||
|
var debounceMs = typeof options.debounceMs === 'number' ? options.debounceMs : 500;
|
||||||
|
var timeoutMs = typeof options.timeoutMs === 'number' ? options.timeoutMs : 6000;
|
||||||
|
var cacheMs = typeof options.cacheMs === 'number' ? options.cacheMs : 60000;
|
||||||
|
var proxyURL = options.proxyURL || '';
|
||||||
|
var debounceTimer = null;
|
||||||
|
var activeController = null;
|
||||||
|
var requestId = 0;
|
||||||
|
|
||||||
|
if (!selectEl || !statusEl) {
|
||||||
|
return {
|
||||||
|
update: function() {},
|
||||||
|
hide: function() {}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function refreshTargets() {
|
||||||
|
selectEl = $(selectTarget);
|
||||||
|
customInputEl = $(customInputTarget);
|
||||||
|
enableEl = $(enableTarget);
|
||||||
|
}
|
||||||
|
|
||||||
|
function enabled() {
|
||||||
|
refreshTargets();
|
||||||
|
return !enableEl || !!enableEl.checked;
|
||||||
|
}
|
||||||
|
|
||||||
|
function run() {
|
||||||
|
window.clearTimeout(debounceTimer);
|
||||||
|
refreshTargets();
|
||||||
|
|
||||||
|
if (!enabled()) {
|
||||||
|
hideStatus(statusEl);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var selected = getSelectedBackend(selectEl, customInputEl);
|
||||||
|
var normalized = normalizeBackendURL(selected);
|
||||||
|
|
||||||
|
if (normalized.error === 'empty') {
|
||||||
|
renderStatus(statusEl, 'empty', labels.empty, labels);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (normalized.error === 'invalid') {
|
||||||
|
renderStatus(statusEl, 'error', labels.invalid, labels);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var now = Date.now();
|
||||||
|
var cacheKey = normalized.versionURLs.join('|');
|
||||||
|
var cached = cache[cacheKey];
|
||||||
|
if (cached && now - cached.time < cacheMs) {
|
||||||
|
renderStatus(statusEl, cached.state, cached.message, labels);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (activeController) activeController.abort();
|
||||||
|
activeController = typeof AbortController !== 'undefined' ? new AbortController() : null;
|
||||||
|
var currentRequestId = ++requestId;
|
||||||
|
|
||||||
|
renderStatus(statusEl, 'checking', labels.checking, labels);
|
||||||
|
|
||||||
|
fetchVersionCandidates(normalized.versionURLs, timeoutMs, activeController ? activeController.signal : null, proxyURL).then(function(result) {
|
||||||
|
if (currentRequestId !== requestId || result.state === 'aborted') return;
|
||||||
|
|
||||||
|
var state = result.state;
|
||||||
|
var message = state === 'success' ? result.text : labels.unrecognized;
|
||||||
|
|
||||||
|
cache[cacheKey] = {
|
||||||
|
time: Date.now(),
|
||||||
|
state: state,
|
||||||
|
message: message
|
||||||
|
};
|
||||||
|
renderStatus(statusEl, state, message, labels);
|
||||||
|
}).catch(function() {
|
||||||
|
if (currentRequestId !== requestId) return;
|
||||||
|
renderStatus(statusEl, 'error', labels.failed, labels);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function schedule() {
|
||||||
|
window.clearTimeout(debounceTimer);
|
||||||
|
debounceTimer = window.setTimeout(run, debounceMs);
|
||||||
|
}
|
||||||
|
|
||||||
|
selectEl.addEventListener('change', run);
|
||||||
|
selectEl.addEventListener('input', schedule);
|
||||||
|
if (customInputEl) {
|
||||||
|
customInputEl.addEventListener('input', schedule);
|
||||||
|
customInputEl.addEventListener('change', run);
|
||||||
|
}
|
||||||
|
if (enableEl) enableEl.addEventListener('change', run);
|
||||||
|
if (options.watchDocument) {
|
||||||
|
document.addEventListener('change', run, true);
|
||||||
|
document.addEventListener('input', schedule, true);
|
||||||
|
document.addEventListener('click', schedule, true);
|
||||||
|
}
|
||||||
|
var watchRootEl = $(options.watchRoot);
|
||||||
|
if (isElement(watchRootEl)) {
|
||||||
|
watchRootEl.addEventListener('change', run, true);
|
||||||
|
watchRootEl.addEventListener('input', schedule, true);
|
||||||
|
watchRootEl.addEventListener('click', schedule, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
run();
|
||||||
|
|
||||||
|
return {
|
||||||
|
update: run,
|
||||||
|
schedule: schedule,
|
||||||
|
hide: function() {
|
||||||
|
if (activeController) activeController.abort();
|
||||||
|
hideStatus(statusEl);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
window.OpenClashSubconverterVersion = {
|
||||||
|
init: init,
|
||||||
|
normalizeBackendURL: normalizeBackendURL
|
||||||
|
};
|
||||||
|
})(window, document);
|
||||||
@@ -24,7 +24,7 @@ import {
|
|||||||
import {
|
import {
|
||||||
syntaxHighlighting, HighlightStyle, bracketMatching,
|
syntaxHighlighting, HighlightStyle, bracketMatching,
|
||||||
foldGutter, indentOnInput, StreamLanguage, foldKeymap, indentUnit,
|
foldGutter, indentOnInput, StreamLanguage, foldKeymap, indentUnit,
|
||||||
getIndentUnit, foldable
|
getIndentUnit, foldable, ensureSyntaxTree
|
||||||
} from "@codemirror/language"
|
} from "@codemirror/language"
|
||||||
|
|
||||||
// ---- Tags ----
|
// ---- Tags ----
|
||||||
@@ -467,7 +467,7 @@ function mihomoCompletion(context) {
|
|||||||
return { from: word.from, options, validFor: /^[\w-]*$/ }
|
return { from: word.from, options, validFor: /^[\w-]*$/ }
|
||||||
}
|
}
|
||||||
|
|
||||||
function yamlLinter() {
|
function yamlLinter(delay = 750) {
|
||||||
return linter(view => {
|
return linter(view => {
|
||||||
const diagnostics = []
|
const diagnostics = []
|
||||||
try { loadAll(view.state.doc.toString(), { schema: YAML11_SCHEMA }) } catch (e) {
|
try { loadAll(view.state.doc.toString(), { schema: YAML11_SCHEMA }) } catch (e) {
|
||||||
@@ -484,7 +484,7 @@ function yamlLinter() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return diagnostics
|
return diagnostics
|
||||||
})
|
}, typeof delay === 'number' ? { delay: delay } : undefined)
|
||||||
}
|
}
|
||||||
|
|
||||||
var _levelTagMap = null
|
var _levelTagMap = null
|
||||||
@@ -563,6 +563,28 @@ const logHighlightStyle = HighlightStyle.define([
|
|||||||
{ tag: logTag.levelWatchdog, class: "cmt-log-level-watchdog" },
|
{ tag: logTag.levelWatchdog, class: "cmt-log-level-watchdog" },
|
||||||
])
|
])
|
||||||
|
|
||||||
|
function syntaxPreload(buffer = 1000) {
|
||||||
|
return ViewPlugin.fromClass(class {
|
||||||
|
constructor(view) { this._preload(view) }
|
||||||
|
update(u) {
|
||||||
|
if (u.viewportChanged || u.docChanged) {
|
||||||
|
if (this._rafId) cancelAnimationFrame(this._rafId)
|
||||||
|
var self = this
|
||||||
|
this._rafId = requestAnimationFrame(function() {
|
||||||
|
self._rafId = null
|
||||||
|
self._preload(u.view)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_preload(view) {
|
||||||
|
var doc = view.state.doc
|
||||||
|
var ll = doc.lineAt(view.viewport.to).number
|
||||||
|
var target = Math.min(ll + buffer, doc.lines)
|
||||||
|
ensureSyntaxTree(view.state, doc.line(target).to, 50)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
function baseExtensions(extra = []) {
|
function baseExtensions(extra = []) {
|
||||||
return [
|
return [
|
||||||
lineNumbers(), highlightActiveLine(), highlightActiveLineGutter(),
|
lineNumbers(), highlightActiveLine(), highlightActiveLineGutter(),
|
||||||
@@ -572,6 +594,7 @@ function baseExtensions(extra = []) {
|
|||||||
indentOnInput(), history(),
|
indentOnInput(), history(),
|
||||||
highlightSelectionMatches(), EditorView.lineWrapping,
|
highlightSelectionMatches(), EditorView.lineWrapping,
|
||||||
closeBrackets(),
|
closeBrackets(),
|
||||||
|
syntaxPreload(),
|
||||||
cmKeymap.of([...defaultKeymap, ...historyKeymap, ...searchKeymap, ...closeBracketsKeymap, ...foldKeymap, { key: 'Tab', run: function(v) { return acceptCompletion(v) || indentMore(v) } }]),
|
cmKeymap.of([...defaultKeymap, ...historyKeymap, ...searchKeymap, ...closeBracketsKeymap, ...foldKeymap, { key: 'Tab', run: function(v) { return acceptCompletion(v) || indentMore(v) } }]),
|
||||||
...extra
|
...extra
|
||||||
]
|
]
|
||||||
@@ -579,9 +602,11 @@ function baseExtensions(extra = []) {
|
|||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// Custom indentation markers
|
// Custom indentation markers
|
||||||
// Replaces @replit/codemirror-indentation-markers (unmaintained).
|
|
||||||
// Fixes left:2px→6px: @codemirror/view >=~6.29 changed .cm-line
|
// Fixes left:2px→6px: @codemirror/view >=~6.29 changed .cm-line
|
||||||
// padding from "0 2px" to "0 2px 0 6px".
|
// padding from "0 2px" to "0 2px 0 6px".
|
||||||
|
// The ::before pseudo-element fills the full line height (no gaps)
|
||||||
|
// but is capped at one visual row (--oc-lh) so it never bleeds
|
||||||
|
// through wrapped text on long lines.
|
||||||
// ============================================================
|
// ============================================================
|
||||||
|
|
||||||
const _ocImBaseTheme = EditorView.baseTheme({
|
const _ocImBaseTheme = EditorView.baseTheme({
|
||||||
@@ -592,7 +617,7 @@ const _ocImBaseTheme = EditorView.baseTheme({
|
|||||||
top: 0,
|
top: 0,
|
||||||
left: '6px',
|
left: '6px',
|
||||||
right: 0,
|
right: 0,
|
||||||
bottom: 0,
|
height: 'var(--oc-lh, 100%)',
|
||||||
background: 'var(--oc-im)',
|
background: 'var(--oc-im)',
|
||||||
pointerEvents: 'none',
|
pointerEvents: 'none',
|
||||||
zIndex: '-1',
|
zIndex: '-1',
|
||||||
@@ -611,9 +636,6 @@ function _ocImIndent(text, ts) {
|
|||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute per-line structural nesting depth using CM6's foldable() function.
|
|
||||||
// foldable(state, lineStart, lineEnd) → {from, to} | null
|
|
||||||
// Returns an array of depths indexed by (lineNo - fl).
|
|
||||||
function _foldDepth(state, fl, ll, doc) {
|
function _foldDepth(state, fl, ll, doc) {
|
||||||
var ranges = []
|
var ranges = []
|
||||||
for (var n = fl; n <= ll; n++) {
|
for (var n = fl; n <= ll; n++) {
|
||||||
@@ -631,8 +653,6 @@ function _foldDepth(state, fl, ll, doc) {
|
|||||||
return depths
|
return depths
|
||||||
}
|
}
|
||||||
|
|
||||||
// Single-line version of _foldDepth, for measure.read where the full
|
|
||||||
// array hasn't been precomputed.
|
|
||||||
function _foldDepth1(state, lineNo, fl, ll, doc) {
|
function _foldDepth1(state, lineNo, fl, ll, doc) {
|
||||||
var pos = doc.line(lineNo).from, d = 0
|
var pos = doc.line(lineNo).from, d = 0
|
||||||
for (var n = fl; n <= ll; n++) {
|
for (var n = fl; n <= ll; n++) {
|
||||||
@@ -642,7 +662,7 @@ function _foldDepth1(state, lineNo, fl, ll, doc) {
|
|||||||
return d
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
function indentMarkerExtension({ highlightActiveBlock = true, hideFirstIndent = false, thickness = 1, colors } = {}) {
|
function indentMarkerExtension({ highlightActiveBlock = true, hideFirstIndent = false, thickness = 1, colors, deferMode = 'raf', buffer = 1000 } = {}) {
|
||||||
var extra = colors ? EditorView.baseTheme({
|
var extra = colors ? EditorView.baseTheme({
|
||||||
'&light': { '--oc-im-c': colors.light || '#e1e4e8', '--oc-im-ca': colors.activeLight || '#d0d7de' },
|
'&light': { '--oc-im-c': colors.light || '#e1e4e8', '--oc-im-ca': colors.activeLight || '#d0d7de' },
|
||||||
'&dark': { '--oc-im-c': colors.dark || '#30363d', '--oc-im-ca': colors.activeDark || '#484f58' },
|
'&dark': { '--oc-im-c': colors.dark || '#30363d', '--oc-im-ca': colors.activeDark || '#484f58' },
|
||||||
@@ -654,7 +674,7 @@ function indentMarkerExtension({ highlightActiveBlock = true, hideFirstIndent =
|
|||||||
ViewPlugin.fromClass(class {
|
ViewPlugin.fromClass(class {
|
||||||
constructor(view) {
|
constructor(view) {
|
||||||
this._view = view
|
this._view = view
|
||||||
this._stepPx = null // measured indent-unit pixel width
|
this._stepPx = null
|
||||||
this._measurePending = false
|
this._measurePending = false
|
||||||
this.decorations = this._build(view)
|
this.decorations = this._build(view)
|
||||||
this._scheduleMeasure(view)
|
this._scheduleMeasure(view)
|
||||||
@@ -665,6 +685,19 @@ function indentMarkerExtension({ highlightActiveBlock = true, hideFirstIndent =
|
|||||||
var needsRebuild = u.docChanged || u.viewportChanged ||
|
var needsRebuild = u.docChanged || u.viewportChanged ||
|
||||||
(highlightActiveBlock && u.selectionSet)
|
(highlightActiveBlock && u.selectionSet)
|
||||||
if (needsRebuild) {
|
if (needsRebuild) {
|
||||||
|
if (deferMode === 'raf' && u.viewportChanged && !u.docChanged) {
|
||||||
|
if (this._rafId) cancelAnimationFrame(this._rafId)
|
||||||
|
var self = this
|
||||||
|
this._rafId = requestAnimationFrame(function() {
|
||||||
|
self._rafId = null
|
||||||
|
self._stepPx = null
|
||||||
|
self._measurePending = false
|
||||||
|
self.decorations = self._build(u.view)
|
||||||
|
self._scheduleMeasure(u.view)
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (this._rafId) { cancelAnimationFrame(this._rafId); this._rafId = null }
|
||||||
this._stepPx = null
|
this._stepPx = null
|
||||||
this._measurePending = false
|
this._measurePending = false
|
||||||
this.decorations = this._build(u.view)
|
this.decorations = this._build(u.view)
|
||||||
@@ -680,31 +713,23 @@ function indentMarkerExtension({ highlightActiveBlock = true, hideFirstIndent =
|
|||||||
this._measureId = view.requestMeasure(this._mkSpec())
|
this._measureId = view.requestMeasure(this._mkSpec())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Measure one indent unit's pixel width in the read phase
|
|
||||||
// (coordsAtPos is only safe here, not during update).
|
|
||||||
_mkSpec() {
|
_mkSpec() {
|
||||||
var self = this
|
var self = this
|
||||||
return {
|
return {
|
||||||
read: function(view) {
|
read: function(view) {
|
||||||
var sa = hideFirstIndent ? 1 : 0
|
|
||||||
var state = view.state, iw = getIndentUnit(state), ts = state.tabSize, doc = state.doc
|
var state = view.state, iw = getIndentUnit(state), ts = state.tabSize, doc = state.doc
|
||||||
var fl = doc.lineAt(view.viewport.from).number
|
var fl = doc.lineAt(view.viewport.from).number
|
||||||
var ll = doc.lineAt(view.viewport.to).number
|
var ll = doc.lineAt(view.viewport.to).number
|
||||||
var bl = Math.max(1, fl - 80), el = Math.min(doc.lines, ll + 80)
|
|
||||||
|
|
||||||
// Compute max fold depth in visible range
|
var hasIndent = false
|
||||||
var maxLvl = 0
|
|
||||||
for (var n = fl; n <= ll; n++) {
|
for (var n = fl; n <= ll; n++) {
|
||||||
if (n < bl || n > el) continue
|
if (_ocImIndent(doc.line(n).text, ts) >= iw) { hasIndent = true; break }
|
||||||
var fd = _foldDepth1(state, n, fl, ll, doc)
|
|
||||||
if (fd > maxLvl) maxLvl = fd
|
|
||||||
}
|
}
|
||||||
if (maxLvl <= sa) return -1
|
|
||||||
|
|
||||||
// Measure exact pixel width of one indent unit
|
var stepPx = 0, lineHeight = 0
|
||||||
var stepPx = 0
|
|
||||||
|
if (hasIndent) {
|
||||||
for (var n = fl; n <= ll; n++) {
|
for (var n = fl; n <= ll; n++) {
|
||||||
if (n < bl || n > el) continue
|
|
||||||
var t = doc.line(n).text
|
var t = doc.line(n).text
|
||||||
if (t.trim() === '') continue
|
if (t.trim() === '') continue
|
||||||
if (_ocImIndent(t, ts) >= iw) {
|
if (_ocImIndent(t, ts) >= iw) {
|
||||||
@@ -713,11 +738,30 @@ function indentMarkerExtension({ highlightActiveBlock = true, hideFirstIndent =
|
|||||||
if (c0 && c1) { stepPx = Math.round((c1.left - c0.left) * 100) / 100; break }
|
if (c0 && c1) { stepPx = Math.round((c1.left - c0.left) * 100) / 100; break }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return stepPx > 0 ? stepPx : -1
|
}
|
||||||
|
|
||||||
|
if (fl < doc.lines) {
|
||||||
|
var c0 = view.coordsAtPos(doc.line(fl).from)
|
||||||
|
var c1 = view.coordsAtPos(doc.line(fl + 1).from)
|
||||||
|
if (c0 && c1) lineHeight = Math.round(c1.top - c0.top)
|
||||||
|
}
|
||||||
|
|
||||||
|
return lineHeight > 0
|
||||||
|
? { stepPx: stepPx > 0 ? stepPx : -1, lineHeight: lineHeight }
|
||||||
|
: (stepPx > 0 ? stepPx : -1)
|
||||||
},
|
},
|
||||||
write: function(stepPx) {
|
write: function(result) {
|
||||||
|
var stepPx, lineHeight
|
||||||
|
if (typeof result === 'number') {
|
||||||
|
stepPx = result; lineHeight = 0
|
||||||
|
} else if (result) {
|
||||||
|
stepPx = result.stepPx; lineHeight = result.lineHeight || 0
|
||||||
|
} else {
|
||||||
|
stepPx = -1; lineHeight = 0
|
||||||
|
}
|
||||||
if (typeof stepPx === 'number') {
|
if (typeof stepPx === 'number') {
|
||||||
self._stepPx = stepPx > 0 ? stepPx : -1
|
self._stepPx = stepPx > 0 ? stepPx : -1
|
||||||
|
self._lineHeight = lineHeight
|
||||||
self._measurePending = true
|
self._measurePending = true
|
||||||
var v = self._view
|
var v = self._view
|
||||||
// Defer dispatch past the current update cycle
|
// Defer dispatch past the current update cycle
|
||||||
@@ -737,9 +781,8 @@ function indentMarkerExtension({ highlightActiveBlock = true, hideFirstIndent =
|
|||||||
var doc = state.doc
|
var doc = state.doc
|
||||||
var fl = doc.lineAt(view.viewport.from).number
|
var fl = doc.lineAt(view.viewport.from).number
|
||||||
var ll = doc.lineAt(view.viewport.to).number
|
var ll = doc.lineAt(view.viewport.to).number
|
||||||
var bl = Math.max(1, fl - 80), el = Math.min(doc.lines, ll + 80)
|
var bl = Math.max(1, fl - buffer), el = Math.min(doc.lines, ll + buffer)
|
||||||
|
|
||||||
// Compute visual indent levels
|
|
||||||
var lvls = new Int32Array(el - bl + 1)
|
var lvls = new Int32Array(el - bl + 1)
|
||||||
var bk = new Uint8Array(el - bl + 1)
|
var bk = new Uint8Array(el - bl + 1)
|
||||||
for (var n = bl; n <= el; n++) {
|
for (var n = bl; n <= el; n++) {
|
||||||
@@ -748,7 +791,6 @@ function indentMarkerExtension({ highlightActiveBlock = true, hideFirstIndent =
|
|||||||
bk[n - bl] = b ? 1 : 0
|
bk[n - bl] = b ? 1 : 0
|
||||||
lvls[n - bl] = b ? -1 : Math.floor(_ocImIndent(t, ts) / iw)
|
lvls[n - bl] = b ? -1 : Math.floor(_ocImIndent(t, ts) / iw)
|
||||||
}
|
}
|
||||||
// Blank lines inherit the shallower of prev/next non-blank level
|
|
||||||
for (var n = bl; n <= el; n++) {
|
for (var n = bl; n <= el; n++) {
|
||||||
if (!bk[n - bl]) continue
|
if (!bk[n - bl]) continue
|
||||||
var p = 0, nx = 0
|
var p = 0, nx = 0
|
||||||
@@ -757,49 +799,83 @@ function indentMarkerExtension({ highlightActiveBlock = true, hideFirstIndent =
|
|||||||
lvls[n - bl] = Math.min(p, nx)
|
lvls[n - bl] = Math.min(p, nx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Structural depth from CM6's fold system
|
var maxLvl = 0
|
||||||
var foldDepths = _foldDepth(state, fl, ll, doc)
|
for (var n = fl; n <= ll; n++) {
|
||||||
|
var lv = lvls[n - bl]
|
||||||
|
if (lv > maxLvl) maxLvl = lv
|
||||||
|
}
|
||||||
|
if (maxLvl <= sa) return Decoration.none
|
||||||
|
|
||||||
|
var scopeOpen = new Uint8Array(maxLvl)
|
||||||
|
var showGuides = new Array(ll - fl + 1)
|
||||||
|
|
||||||
|
for (var n = bl; n <= el; n++) {
|
||||||
|
var lv = lvls[n - bl]
|
||||||
|
var isBlank = bk[n - bl] === 1
|
||||||
|
|
||||||
|
if (!isBlank) {
|
||||||
|
for (var k = lv; k < maxLvl; k++) scopeOpen[k] = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n >= fl && n <= ll) {
|
||||||
|
var guides = new Uint8Array(maxLvl)
|
||||||
|
showGuides[n - fl] = guides
|
||||||
|
if (lv > sa) {
|
||||||
|
for (var k = sa; k < lv && k < maxLvl; k++) {
|
||||||
|
if (scopeOpen[k]) guides[k] = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isBlank) {
|
||||||
|
var nextN = -1, nextLv = -1
|
||||||
|
for (var x = n + 1; x <= el; x++) {
|
||||||
|
if (!bk[x - bl]) { nextN = x; nextLv = lvls[x - bl]; break }
|
||||||
|
}
|
||||||
|
if (nextN >= 0 && nextLv > lv && lv < maxLvl) {
|
||||||
|
scopeOpen[lv] = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var activeLvl = undefined
|
||||||
|
if (highlightActiveBlock) {
|
||||||
|
var cn = doc.lineAt(state.selection.main.head).number
|
||||||
|
if (cn >= fl && cn <= ll) {
|
||||||
|
var cl = lvls[cn - bl]
|
||||||
|
var cGuides = showGuides[cn - fl]
|
||||||
|
if (cGuides && cl > sa) {
|
||||||
|
for (var k = cl - 1; k >= sa; k--) {
|
||||||
|
if (cGuides[k]) { activeLvl = k; break }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Indent-unit width: measured or character-width fallback
|
|
||||||
var stepPx = this._stepPx
|
var stepPx = this._stepPx
|
||||||
if (stepPx === null || stepPx <= 0)
|
if (stepPx === null || stepPx <= 0)
|
||||||
stepPx = iw * (view.defaultCharacterWidth || 8)
|
stepPx = iw * (view.defaultCharacterWidth || 8)
|
||||||
|
var lh = this._lineHeight
|
||||||
// Highlight the active block (guide at cursor's deepest ancestor level)
|
|
||||||
var activeLvl
|
|
||||||
if (highlightActiveBlock) {
|
|
||||||
var cn = doc.lineAt(state.selection.main.head).number
|
|
||||||
if (cn >= bl && cn <= el) {
|
|
||||||
var cl = lvls[cn - bl]
|
|
||||||
var cfd = foldDepths[cn - fl] || 0
|
|
||||||
var cel = Math.max(cl, cfd)
|
|
||||||
if (cel > sa) activeLvl = cel - 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var builder = new RangeSetBuilder()
|
var builder = new RangeSetBuilder()
|
||||||
for (var n = fl; n <= ll; n++) {
|
for (var n = fl; n <= ll; n++) {
|
||||||
if (n < bl || n > el) continue
|
var guides = showGuides[n - fl]
|
||||||
var lv = lvls[n - bl]
|
if (!guides) continue
|
||||||
var fd = foldDepths[n - fl]
|
|
||||||
var effectiveLv = Math.max(lv, fd)
|
|
||||||
|
|
||||||
if (effectiveLv <= sa) continue
|
|
||||||
var parts = []
|
var parts = []
|
||||||
// Start from level 1 — level 0 (0 px) is never useful
|
for (var k = sa; k < maxLvl; k++) {
|
||||||
var startL = Math.max(sa, 1)
|
if (!guides[k]) continue
|
||||||
for (var l = startL; l <= effectiveLv; l++) {
|
var pos = Math.round(k * stepPx)
|
||||||
if (l > lv) break // cap at visual indent
|
var cv = (activeLvl !== undefined && k === activeLvl)
|
||||||
var pos = Math.round(l * stepPx)
|
|
||||||
var cv = (activeLvl !== undefined && l === activeLvl)
|
|
||||||
? 'var(--oc-im-ca)' : 'var(--oc-im-c)'
|
? 'var(--oc-im-ca)' : 'var(--oc-im-c)'
|
||||||
parts.push('linear-gradient(' + cv + ',' + cv + ') ' + pos + 'px 0/' + thickness + 'px 100% no-repeat')
|
parts.push('linear-gradient(' + cv + ',' + cv + ') ' + pos + 'px 0/' + thickness + 'px 100% no-repeat')
|
||||||
}
|
}
|
||||||
if (!parts.length) continue
|
if (!parts.length) continue
|
||||||
var line = doc.line(n)
|
var line = doc.line(n)
|
||||||
|
var style = '--oc-im:' + parts.join(',')
|
||||||
|
if (lh > 0) style += ';--oc-lh:' + lh + 'px'
|
||||||
builder.add(line.from, line.from, Decoration.line({
|
builder.add(line.from, line.from, Decoration.line({
|
||||||
class: 'cm-oc-im',
|
class: 'cm-oc-im',
|
||||||
attributes: { style: '--oc-im:' + parts.join(',') }
|
attributes: { style: style }
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
return builder.finish()
|
return builder.finish()
|
||||||
@@ -823,6 +899,93 @@ const mergeDefaultConfig = {
|
|||||||
collapseUnchanged: false,
|
collapseUnchanged: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// Merge scrollbar mirror — clones .cm-scroller scrollbar rules from
|
||||||
|
// the active CM6 theme onto .cm-mergeView and #debug-rendered so
|
||||||
|
// that all scrollbars share the same theme-aware appearance.
|
||||||
|
// Also injects .cm-merge-revert button colours.
|
||||||
|
// ============================================================
|
||||||
|
function mirrorThemeScrollbar() {
|
||||||
|
var styles = document.querySelectorAll('style');
|
||||||
|
var themeStyle = null;
|
||||||
|
var themeText = null;
|
||||||
|
|
||||||
|
for (var i = 0; i < styles.length; i++) {
|
||||||
|
var text = styles[i].textContent || '';
|
||||||
|
if (text.indexOf('.cm-scroller::-webkit-scrollbar') === -1) continue;
|
||||||
|
themeStyle = styles[i];
|
||||||
|
themeText = text;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
var editorEl = document.querySelector('.cm-editor');
|
||||||
|
var contentEl = editorEl ? editorEl.querySelector('.cm-content') : null;
|
||||||
|
var cs = contentEl ? getComputedStyle(contentEl) : null;
|
||||||
|
var txt = cs ? cs.color : null;
|
||||||
|
var rgb = txt ? txt.match(/[\d.]+/g) : null;
|
||||||
|
var r, g, b;
|
||||||
|
if (rgb && rgb.length >= 3) { r = rgb[0]; g = rgb[1]; b = rgb[2]; }
|
||||||
|
|
||||||
|
if (r) {
|
||||||
|
var thumbColor = 'rgba(' + r + ',' + g + ',' + b + ',0.60)';
|
||||||
|
var thumbHover = 'rgba(' + r + ',' + g + ',' + b + ',0.70)';
|
||||||
|
} else {
|
||||||
|
var thumbColor = _isDarkMode() ? 'rgba(255,255,255,0.60)' : 'rgba(0,0,0,0.60)';
|
||||||
|
var thumbHover = _isDarkMode() ? 'rgba(255,255,255,0.70)' : 'rgba(0,0,0,0.70)';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!themeText) return;
|
||||||
|
|
||||||
|
var parts = [], m;
|
||||||
|
var reWebkit = /([^{}]*)\.cm-scroller(::-webkit-scrollbar[^{]*)\{([^}]*)\}/gi;
|
||||||
|
while ((m = reWebkit.exec(themeText)) !== null) {
|
||||||
|
var body = m[3].replace(/;/g, ' !important;');
|
||||||
|
parts.push('.cm-mergeView' + m[2] + '{' + m[3] + '}');
|
||||||
|
parts.push('#debug-rendered' + m[2] + '{' + body + '}');
|
||||||
|
parts.push('#debug-rendered pre' + m[2] + '{' + body + '}');
|
||||||
|
}
|
||||||
|
// Clone Firefox rules
|
||||||
|
var reFF = /([^{}]*)\.cm-scroller\{([^}]*scrollbar-(?:width|color)[^}]*)\}/gi;
|
||||||
|
while ((m = reFF.exec(themeText)) !== null) {
|
||||||
|
var body = m[2];
|
||||||
|
var sw = body.match(/scrollbar-width\s*:\s*[^;]+;?/);
|
||||||
|
var sc = body.match(/scrollbar-color\s*:\s*[^;]+;?/);
|
||||||
|
if (sw || sc) {
|
||||||
|
var ffRule = (sw ? sw[0] : '') + (sc ? sc[0] : '');
|
||||||
|
parts.push('.cm-mergeView{' + ffRule + '}');
|
||||||
|
parts.push('#debug-rendered{' + ffRule + '}');
|
||||||
|
parts.push('#debug-rendered pre{' + ffRule + '}');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var gutterBg = r ? 'rgba(' + r + ',' + g + ',' + b + ',0.06)' : 'rgba(175,184,193,0.06)';
|
||||||
|
parts.push(
|
||||||
|
'.cm-merge-revert{background:' + gutterBg + '}' +
|
||||||
|
'.cm-merge-revert button{color:' + (r ? 'rgba(' + r + ',' + g + ',' + b + ',0.5)' : '#656d76') + '}' +
|
||||||
|
'.cm-merge-revert button:hover{color:' + (txt || '#1f2328') + ';background:' + (r ? 'rgba(' + r + ',' + g + ',' + b + ',0.12)' : 'rgba(175,184,193,0.2)') + '}'
|
||||||
|
);
|
||||||
|
|
||||||
|
var marker = '/*oc-merge-mirror*/';
|
||||||
|
var idx = themeStyle.textContent.indexOf(marker);
|
||||||
|
if (idx !== -1) {
|
||||||
|
themeStyle.textContent = themeStyle.textContent.substring(0, idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
var thumbVal = thumbColor + ' !important';
|
||||||
|
var hoverVal = thumbHover + ' !important';
|
||||||
|
parts.push(
|
||||||
|
'.cm-editor .cm-scroller::-webkit-scrollbar-thumb,' +
|
||||||
|
'.cm-mergeView::-webkit-scrollbar-thumb,' +
|
||||||
|
'#debug-rendered::-webkit-scrollbar-thumb,' +
|
||||||
|
'#debug-rendered pre::-webkit-scrollbar-thumb{background:' + thumbVal + ';background-color:' + thumbVal + '}',
|
||||||
|
'.cm-editor .cm-scroller::-webkit-scrollbar-thumb:hover,' +
|
||||||
|
'.cm-mergeView::-webkit-scrollbar-thumb:hover,' +
|
||||||
|
'#debug-rendered::-webkit-scrollbar-thumb:hover,' +
|
||||||
|
'#debug-rendered pre::-webkit-scrollbar-thumb:hover{background:' + hoverVal + ';background-color:' + hoverVal + '}'
|
||||||
|
);
|
||||||
|
themeStyle.textContent += marker + parts.join('');
|
||||||
|
}
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// Theme compartment — allows dynamic light/dark switching
|
// Theme compartment — allows dynamic light/dark switching
|
||||||
// ============================================================
|
// ============================================================
|
||||||
@@ -836,6 +999,8 @@ function dispatchTheme(view, isDark) {
|
|||||||
view.dispatch({
|
view.dispatch({
|
||||||
effects: themeCompartment.reconfigure(isDark ? githubDark : githubLight)
|
effects: themeCompartment.reconfigure(isDark ? githubDark : githubLight)
|
||||||
})
|
})
|
||||||
|
// Mirror scrollbar rules into the new theme stylesheet
|
||||||
|
mirrorThemeScrollbar();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
@@ -867,29 +1032,14 @@ function toggleFullscreen(dom) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// Theme observer — watch data-darkmode on <html> for all CM6 editors
|
// Theme detection — reads localStorage then falls back to system preference
|
||||||
// ============================================================
|
// ============================================================
|
||||||
var _themeObserverInstalled = false;
|
|
||||||
|
|
||||||
function startThemeObserver() {
|
function _isDarkMode() {
|
||||||
if (_themeObserverInstalled || typeof MutationObserver === 'undefined') return;
|
|
||||||
_themeObserverInstalled = true;
|
|
||||||
var observer = new MutationObserver(function() {
|
|
||||||
var theme = localStorage.getItem('oc-theme') || 'auto';
|
var theme = localStorage.getItem('oc-theme') || 'auto';
|
||||||
var isDark;
|
if (theme === 'dark') return true;
|
||||||
if (theme === 'dark') isDark = true;
|
if (theme === 'light') return false;
|
||||||
else if (theme === 'light') isDark = false;
|
return window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||||
else isDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
||||||
switchHljsTheme(isDark);
|
|
||||||
var editors = document.querySelectorAll('.cm-editor');
|
|
||||||
for (var i = 0; i < editors.length; i++) {
|
|
||||||
var view = editors[i].cmView && editors[i].cmView.view;
|
|
||||||
if (view) {
|
|
||||||
try { dispatchTheme(view, isDark); } catch(e) {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
observer.observe(document.body, { attributes: true, attributeFilter: ['data-darkmode'], subtree: true });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
@@ -900,11 +1050,7 @@ var _hljsCSSInjected = false
|
|||||||
function injectHljsCSS() {
|
function injectHljsCSS() {
|
||||||
if (_hljsCSSInjected) return
|
if (_hljsCSSInjected) return
|
||||||
_hljsCSSInjected = true
|
_hljsCSSInjected = true
|
||||||
var theme = localStorage.getItem('oc-theme') || 'auto'
|
var isDark = _isDarkMode()
|
||||||
var isDark
|
|
||||||
if (theme === 'dark') isDark = true
|
|
||||||
else if (theme === 'light') isDark = false
|
|
||||||
else isDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches
|
|
||||||
var style = document.createElement("style")
|
var style = document.createElement("style")
|
||||||
style.id = "hljs-theme"
|
style.id = "hljs-theme"
|
||||||
style.textContent = isDark ? githubDarkCSS : githubLightCSS
|
style.textContent = isDark ? githubDarkCSS : githubLightCSS
|
||||||
@@ -931,9 +1077,9 @@ marked.use({
|
|||||||
if (lang && hljs.getLanguage(lang)) {
|
if (lang && hljs.getLanguage(lang)) {
|
||||||
injectHljsCSS()
|
injectHljsCSS()
|
||||||
var result = hljs.highlight(token.text, { language: lang, ignoreIllegals: true })
|
var result = hljs.highlight(token.text, { language: lang, ignoreIllegals: true })
|
||||||
return '<pre><code class="hljs language-' + lang + '">' + result.value + '</code></pre>'
|
return '<pre><code class="hljs language-' + lang + '"><span class="code-content">' + result.value + '</span></code></pre>'
|
||||||
}
|
}
|
||||||
return '<pre><code>' + escapeHtml(token.text) + '</code></pre>'
|
return '<pre><code><span class="code-content">' + escapeHtml(token.text) + '</span></code></pre>'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -960,10 +1106,10 @@ export {
|
|||||||
githubDark, githubLight,
|
githubDark, githubLight,
|
||||||
MergeView,
|
MergeView,
|
||||||
logLanguage, logHighlightStyle,
|
logLanguage, logHighlightStyle,
|
||||||
baseExtensions, placeholderExtension, indentMarkerExtension,
|
baseExtensions, syntaxPreload, placeholderExtension, indentMarkerExtension,
|
||||||
topSearchExtension, mergeDefaultConfig,
|
topSearchExtension, mergeDefaultConfig, mirrorThemeScrollbar,
|
||||||
themeExtension, dispatchTheme,
|
themeExtension, dispatchTheme,
|
||||||
startThemeObserver,
|
switchHljsTheme,
|
||||||
renderMarkdown,
|
renderMarkdown,
|
||||||
getActiveEditor, toggleFullscreen
|
getActiveEditor, toggleFullscreen
|
||||||
}
|
}
|
||||||
@@ -4,7 +4,7 @@ LUCI_TITLE:=luci-app-ssr-plus
|
|||||||
LUCI_PKGARCH:=all
|
LUCI_PKGARCH:=all
|
||||||
PKG_NAME:=luci-app-ssr-plus
|
PKG_NAME:=luci-app-ssr-plus
|
||||||
PKG_VERSION:=196
|
PKG_VERSION:=196
|
||||||
PKG_RELEASE:=48
|
PKG_RELEASE:=49
|
||||||
|
|
||||||
PKG_CONFIG_DEPENDS:= \
|
PKG_CONFIG_DEPENDS:= \
|
||||||
CONFIG_PACKAGE_$(PKG_NAME)_Iptables_Transparent_Proxy \
|
CONFIG_PACKAGE_$(PKG_NAME)_Iptables_Transparent_Proxy \
|
||||||
|
|||||||
@@ -180,7 +180,7 @@
|
|||||||
line-height: 1.2 !important;
|
line-height: 1.2 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
select[name^="cbid.shadowsocksr."][name*="_time"] {
|
.ssr-schedule-item select {
|
||||||
width: 100% !important;
|
width: 100% !important;
|
||||||
min-width: 0 !important;
|
min-width: 0 !important;
|
||||||
max-width: 100% !important;
|
max-width: 100% !important;
|
||||||
|
|||||||
+2
-2
@@ -10,12 +10,12 @@ include $(INCLUDE_DIR)/kernel.mk
|
|||||||
|
|
||||||
PKG_NAME:=natflow
|
PKG_NAME:=natflow
|
||||||
PKG_VERSION:=20260531
|
PKG_VERSION:=20260531
|
||||||
PKG_RELEASE:=49
|
PKG_RELEASE:=50
|
||||||
|
|
||||||
PKG_SOURCE:=$(PKG_VERSION).tar.xz
|
PKG_SOURCE:=$(PKG_VERSION).tar.xz
|
||||||
PKG_SOURCE_URL:=https://github.com/ptpt52/natflow.git
|
PKG_SOURCE_URL:=https://github.com/ptpt52/natflow.git
|
||||||
PKG_SOURCE_PROTO:=git
|
PKG_SOURCE_PROTO:=git
|
||||||
PKG_SOURCE_VERSION:=9e99abf4f6eda285ecd999b32cf7357e8628dc84
|
PKG_SOURCE_VERSION:=18b46f71fc2a6ed6d9b6acceb2b5c2ebaf287cf2
|
||||||
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
|
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
|
||||||
PKG_MAINTAINER:=Chen Minqiang <ptpt52@gmail.com>
|
PKG_MAINTAINER:=Chen Minqiang <ptpt52@gmail.com>
|
||||||
PKG_LICENSE:=GPL-2.0
|
PKG_LICENSE:=GPL-2.0
|
||||||
|
|||||||
Reference in new issue
Block a user