diff --git a/luci-app-mosdns/Makefile b/luci-app-mosdns/Makefile index 892e28bfa..a658bb9e3 100644 --- a/luci-app-mosdns/Makefile +++ b/luci-app-mosdns/Makefile @@ -1,12 +1,14 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-mosdns -PKG_VERSION:=1.5.23 +PKG_VERSION:=1.6.0 PKG_RELEASE:=1 LUCI_TITLE:=LuCI Support for mosdns LUCI_PKGARCH:=all -LUCI_DEPENDS:=+mosdns +jsonfilter +luci-compat +curl +v2ray-geoip +v2ray-geosite +v2dat +LUCI_DEPENDS:=+mosdns +jsonfilter +curl +v2ray-geoip +v2ray-geosite +v2dat + +PKG_MAINTAINER:=sbwml define Package/$(PKG_NAME)/conffiles /etc/config/mosdns diff --git a/luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/basic.js b/luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/basic.js new file mode 100644 index 000000000..b8bc2aa4a --- /dev/null +++ b/luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/basic.js @@ -0,0 +1,359 @@ +'use strict'; +'require form'; +'require fs'; +'require poll'; +'require rpc'; +'require uci'; +'require ui'; +'require view'; + +var callServiceList = rpc.declare({ + object: 'service', + method: 'list', + params: ['name'], + expect: { '': {} } +}); + +function getServiceStatus() { + return L.resolveDefault(callServiceList('mosdns'), {}).then(function (res) { + var isRunning = false; + try { + isRunning = res['mosdns']['instances']['mosdns']['running']; + } catch (e) { } + return isRunning; + }); +} + +function renderStatus(isRunning) { + var spanTemp = '%s %s'; + var renderHTML; + if (isRunning) { + renderHTML = spanTemp.format('green', _('MosDNS'), _('RUNNING')); + } else { + renderHTML = spanTemp.format('red', _('MosDNS'), _('NOT RUNNING')); + } + + return renderHTML; +} + +return view.extend({ + handleFlushCache: function (m, section_id, ev) { + return fs.exec('/usr/share/mosdns/mosdns.sh', ['flush']) + .then(function (lazy_cache) { + var res = lazy_cache.code; + if (res === 0) { + ui.addNotification(null, E('p', _('Flushing DNS Cache Success.')), 'info'); + } else { + ui.addNotification(null, E('p', _('Flushing DNS Cache Failed, Please check if MosDNS is running.')), 'error'); + } + }); + }, + + render: function () { + var m, s, o; + + m = new form.Map('mosdns', _('MosDNS'), + _('MosDNS is a plugin-based DNS forwarder/traffic splitter.')); + + s = m.section(form.TypedSection); + s.anonymous = true; + s.render = function () { + poll.add(function () { + return L.resolveDefault(getServiceStatus()).then(function (res) { + var view = document.getElementById('service_status'); + view.innerHTML = renderStatus(res); + }); + }); + + return E('div', { class: 'cbi-section', id: 'status_bar' }, [ + E('p', { id: 'service_status' }, _('Collecting data...')) + ]); + } + + s = m.section(form.NamedSection, 'config', 'mosdns'); + + s.tab('basic', _('Basic Options')); + s.tab("advanced", _("Advanced Options")); + s.tab("cloudflare", _("Cloudflare Options")); + s.tab("api", _("API Options")); + s.tab('geodata', _('GeoData Export')); + + /* basic */ + o = s.taboption('basic', form.Flag, 'enabled', _('Enabled')); + o.default = o.disabled; + o.rmempty = false; + + o = s.taboption('basic', form.ListValue, 'configfile', _('Config File')); + o.value('/var/etc/mosdns.json', _('Default Config')); + o.value('/etc/mosdns/config_custom.yaml', _('Custom Config')); + o.default = '/var/etc/mosdns.json'; + + o = s.taboption('basic', form.Value, 'listen_port', _('Listen port')); + o.default = '5335'; + o.datatype = 'port'; + o.depends('configfile', '/var/etc/mosdns.json'); + + o = s.taboption('basic', form.ListValue, 'log_level', _('Log Level')); + o.value('debug', _('Debug')); + o.value('info', _('Info')); + o.value('warn', _('Warning')); + o.value('error', _('Error')); + o.default = 'info'; + o.depends('configfile', '/var/etc/mosdns.json'); + + o = s.taboption('basic', form.Value, 'log_file', _('Log File')); + o.placeholder = '/var/log/mosdns.log'; + o.default = '/var/log/mosdns.log'; + o.depends('configfile', '/var/etc/mosdns.json'); + + o = s.taboption('basic', form.Flag, 'redirect', _('DNS Forward'), _('Forward Dnsmasq Domain Name resolution requests to MosDNS')); + o.default = false; + + o = s.taboption('basic', form.Flag, 'prefer_ipv4', _('Remote DNS prefer IPv4'), + _('IPv4 is preferred for Remote / Streaming Media DNS resolution of dual-stack addresses, and is not affected when the destination is IPv6 only')); + o.depends('configfile', '/var/etc/mosdns.json'); + o.default = false; + + o = s.taboption('basic', form.Flag, 'custom_local_dns', _('Custom China DNS'), _('Follow WAN interface DNS if not enabled')); + o.depends('configfile', '/var/etc/mosdns.json'); + o.default = false; + + o = s.taboption('basic', form.Flag, 'apple_optimization', _('Apple domains optimization'), + _('For Apple domains equipped with Chinese mainland CDN, always responsive to Chinese CDN IP addresses')); + o.depends('custom_local_dns', '1'); + o.default = false; + + o = s.taboption('basic', form.DynamicList, 'local_dns', _('China DNS server')); + o.value('119.29.29.29', _('Tencent Public DNS (119.29.29.29)')); + o.value('119.28.28.28', _('Tencent Public DNS (119.28.28.28)')); + o.value('223.5.5.5', _('Aliyun Public DNS (223.5.5.5)')); + o.value('223.6.6.6', _('Aliyun Public DNS (223.6.6.6)')); + o.value('180.184.1.1', _('TrafficRoute Public DNS (180.184.1.1)')); + o.value('180.184.2.2', _('TrafficRoute Public DNS (180.184.2.2)')); + o.value('114.114.114.114', _('Xinfeng Public DNS (114.114.114.114)')); + o.value('114.114.115.115', _('Xinfeng Public DNS (114.114.115.115)')); + o.value('180.76.76.76', _('Baidu Public DNS (180.76.76.76)')); + o.value('https://doh.pub/dns-query', _('Tencent Public DNS (DNS over HTTPS)')); + o.value('quic://dns.alidns.com', _('Aliyun Public DNS (DNS over QUIC)')); + o.value('https://dns.alidns.com/dns-query', _('Aliyun Public DNS (DNS over HTTPS)')); + o.value('h3://dns.alidns.com/dns-query', _('Aliyun Public DNS (DNS over HTTPS/3)')); + o.value('https://doh.360.cn/dns-query', _('360 Public DNS (DNS over HTTPS)')); + o.default = '119.29.29.29'; + o.depends('custom_local_dns', '1'); + + o = s.taboption('basic', form.DynamicList, 'remote_dns', _('Remote DNS server')); + o.value('tls://1.1.1.1', _('CloudFlare Public DNS (1.1.1.1)')); + o.value('tls://1.0.0.1', _('CloudFlare Public DNS (1.0.0.1)')); + o.value('tls://8.8.8.8', _('Google Public DNS (8.8.8.8)')); + o.value('tls://8.8.4.4', _('Google Public DNS (8.8.4.4)')); + o.value('tls://9.9.9.9', _('Quad9 Public DNS (9.9.9.9)')); + o.value('tls://149.112.112.112', _('Quad9 Public DNS (149.112.112.112)')); + o.value('tls://208.67.222.222', _('Cisco Public DNS (208.67.222.222)')); + o.value('tls://208.67.220.220', _('Cisco Public DNS (208.67.220.220)')); + o.default = 'tls://8.8.8.8'; + o.depends('configfile', '/var/etc/mosdns.json'); + + o = s.taboption('basic', form.Flag, 'custom_stream_media_dns', _('Custom Stream Media DNS'), + _('Netflix, Disney+, Hulu and streaming media rules list will use this DNS')); + o.depends('configfile', '/var/etc/mosdns.json'); + o.default = false; + + o = s.taboption('basic', form.DynamicList, 'stream_media_dns', _('Streaming Media DNS server')); + o.value('tls://1.1.1.1', _('CloudFlare Public DNS (1.1.1.1)')); + o.value('tls://1.0.0.1', _('CloudFlare Public DNS (1.0.0.1)')); + o.value('tls://8.8.8.8', _('Google Public DNS (8.8.8.8)')); + o.value('tls://8.8.4.4', _('Google Public DNS (8.8.4.4)')); + o.value('tls://9.9.9.9', _('Quad9 Public DNS (9.9.9.9)')); + o.value('tls://149.112.112.112', _('Quad9 Public DNS (149.112.112.112)')); + o.value('tls://208.67.222.222', _('Cisco Public DNS (208.67.222.222)')); + o.value('tls://208.67.220.220', _('Cisco Public DNS (208.67.220.220)')); + o.default = 'tls://8.8.8.8'; + o.depends('custom_stream_media_dns', '1'); + + o = s.taboption('basic', form.ListValue, 'bootstrap_dns', _('Bootstrap DNS servers'), + _('Bootstrap DNS servers are used to resolve IP addresses of the DoH/DoT resolvers you specify as upstreams')); + o.value('119.29.29.29', _('Tencent Public DNS (119.29.29.29)')); + o.value('119.28.28.28', _('Tencent Public DNS (119.28.28.28)')); + o.value('223.5.5.5', _('Aliyun Public DNS (223.5.5.5)')); + o.value('223.6.6.6', _('Aliyun Public DNS (223.6.6.6)')); + o.value('114.114.114.114', _('Xinfeng Public DNS (114.114.114.114)')); + o.value('114.114.115.115', _('Xinfeng Public DNS (114.114.115.115)')); + o.value('180.76.76.76', _('Baidu Public DNS (180.76.76.76)')); + o.value('8.8.8.8', _('Google Public DNS (8.8.8.8)')); + o.value('1.1.1.1', _('CloudFlare Public DNS (1.1.1.1)')); + o.default = '119.29.29.29'; + o.depends('configfile', '/var/etc/mosdns.json'); + + /* advanced */ + o = s.taboption('advanced', form.Value, 'concurrent', _('Concurrent'), + _('DNS query request concurrency, The number of upstream DNS servers that are allowed to initiate requests at the same time')); + o.datatype = 'and(uinteger,min(1),max(3))'; + o.default = '2'; + o.depends('configfile', '/var/etc/mosdns.json'); + + o = s.taboption('advanced', form.Value, 'idle_timeout', _('Idle Timeout'), + _('DoH/TCP/DoT Connection Multiplexing idle timeout (default 30 seconds)')) + o.datatype = 'and(uinteger,min(1))'; + o.default = '30'; + o.depends('configfile', '/var/etc/mosdns.json'); + + o = s.taboption('advanced', form.Flag, 'enable_pipeline', _('TCP/DoT Connection Multiplexing'), + _('Enable TCP/DoT RFC 7766 new Query Pipelining connection multiplexing mode')) + o.rmempty = false; + o.default = false; + o.depends('configfile', '/var/etc/mosdns.json'); + + o = s.taboption('advanced', form.Flag, 'insecure_skip_verify', _('Disable TLS Certificate'), + _('Disable TLS Servers certificate validation, Can be useful if system CA certificate expires or the system time is out of order')); + o.rmempty = false; + o.default = false; + o.depends('configfile', '/var/etc/mosdns.json'); + + o = s.taboption('advanced', form.Flag, 'enable_ecs_remote', + _('Enable EDNS client subnet')); + o.rmempty = false; + o.default = false; + o.depends('configfile', '/var/etc/mosdns.json'); + + o = s.taboption('advanced', form.Value, 'remote_ecs_ip', _('IP Address'), + _('Please provide the IP address you use when accessing foreign websites. This IP subnet (0/24) will be used as the ECS address for Remote / Streaming Media DNS requests') + + _('This feature is typically used when using a self-built DNS server as an Remote / Streaming Media DNS upstream (requires support from the upstream server)')); + o.datatype = 'ipaddr'; + o.depends('enable_ecs_remote', '1'); + + o = s.taboption('advanced', form.Flag, 'dns_leak', _('Prevent DNS Leaks'), + _('Enable this option fallback policy forces forwarding to remote DNS')); + o.rmempty = false; + o.default = false; + o.depends('configfile', '/var/etc/mosdns.json'); + + o = s.taboption('advanced', form.Flag, 'cache', _('Enable DNS Cache')); + o.rmempty = false; + o.default = false; + o.depends('configfile', '/var/etc/mosdns.json'); + + o = s.taboption('advanced', form.Value, 'cache_size', _('DNS Cache Size'), + _('DNS cache size (in piece). To disable caching, please set to 0.')); + o.datatype = 'and(uinteger,min(0))'; + o.default = 8000; + o.depends('cache', '1'); + + o = s.taboption('advanced', form.Value, 'lazy_cache_ttl', _('Lazy Cache TTL'), + _('Lazy cache survival time (in second). To disable Lazy Cache, please set to 0.')); + o.datatype = 'and(uinteger,min(0))'; + o.default = 86400; + o.depends('cache', '1'); + + o = s.taboption('advanced', form.Flag, 'dump_file', _('Cache Dump'), + _('Save the cache locally and reload the cache dump on the next startup')); + o.rmempty = false; + o.default = false; + o.depends('cache', '1'); + + o = s.taboption('advanced', form.Value, 'dump_interval', + _('Auto Save Cache Interval')); + o.datatype = 'and(uinteger,min(0))'; + o.default = 3600; + o.depends('dump_file', '1'); + + o = s.taboption('advanced', form.Value, 'minimal_ttl', _('Minimum TTL'), + _('Modify the Minimum TTL value (seconds) for DNS answer results, 0 indicating no modification')); + o.datatype = 'and(uinteger,min(0),max(604800))'; + o.default = 0; + o.depends('configfile', '/var/etc/mosdns.json'); + + o = s.taboption('advanced', form.Value, 'maximum_ttl', _('Maximum TTL'), + _('Modify the Maximum TTL value (seconds) for DNS answer results, 0 indicating no modification')); + o.datatype = 'and(uinteger,min(0),max(604800))'; + o.default = 0; + o.depends('configfile', '/var/etc/mosdns.json'); + + o = s.taboption('advanced', form.Flag, 'adblock', _('Enable DNS ADblock')); + o.depends('configfile', '/var/etc/mosdns.json'); + o.default = false; + + o = s.taboption('advanced', form.DynamicList, 'ad_source', _('ADblock Source'), + _('When using custom rule sources, please use rule types supported by MosDNS (domain lists).') + + '
' + + _('Support for local files, such as: file:///var/mosdns/example.txt')); + o.depends('adblock', '1'); + o.default = 'geosite.dat'; + o.value('geosite.dat', 'v2ray-geosite'); + o.value('https://raw.githubusercontent.com/privacy-protection-tools/anti-AD/master/anti-ad-domains.txt', 'anti-AD') + o.value('https://raw.githubusercontent.com/Cats-Team/AdRules/main/mosdns_adrules.txt', 'Cats-Team/AdRules') + o.value('https://raw.githubusercontent.com/neodevpro/neodevhost/master/domain', 'NEO DEV HOST') + + /* cloudflare */ + o = s.taboption('cloudflare', form.Flag, 'cloudflare', _('Enabled'), + _('Match the parsing result with the Cloudflare IP ranges, and when there is a successful match, \ + use the \'Custom IP\' as the parsing result (experimental feature)')); + o.rmempty = false; + o.default = false; + o.depends('configfile', '/var/etc/mosdns.json'); + + o = s.taboption('cloudflare', form.DynamicList, 'cloudflare_ip', _('Custom IP')); + o.datatype = 'ipaddr'; + o.depends('configfile', '/var/etc/mosdns.json'); + + o = s.taboption('cloudflare', form.TextValue, '_cloudflare', + _('Cloudflare IP Ranges'), + _('IPv4 CIDR: https://www.cloudflare.com/ips-v4
IPv6 CIDR: https://www.cloudflare.com/ips-v6')); + o.rows = 15; + o.depends('configfile', '/var/etc/mosdns.json'); + o.cfgvalue = function (section_id) { + return fs.trimmed('/etc/mosdns/rule/cloudflare-cidr.txt'); + }; + o.write = function (section_id, formvalue) { + return fs.write('/etc/mosdns/rule/cloudflare-cidr.txt', formvalue.trim().replace(/\r\n/g, '\n') + '\n') + .then(function (i) { + return fs.exec('/etc/init.d/mosdns', ['restart']); + }); + }; + + /* api */ + o = s.taboption('api', form.Value, 'listen_port_api', _('API Listen port')); + o.datatype = 'and(port,min(1))'; + o.default = 9091; + o.depends('configfile', '/var/etc/mosdns.json'); + + o = s.taboption('api', form.Button, '_flush_cache', null, + _('Flushing DNS Cache will clear any IP addresses or DNS records from MosDNS cache.')); + o.title = ' '; + o.inputtitle = _('Flush DNS Cache'); + o.inputstyle = 'apply'; + o.onclick = L.bind(this.handleFlushCache, this, m); + o.depends('cache', '1'); + + /* configuration */ + o = s.taboption('basic', form.TextValue, '_custom', _('Configuration Editor'), + _('This is the content of the file \'/etc/mosdns/config_custom.yaml\' from which your MosDNS configuration will be generated. \ + Only accepts configuration content in yaml format.')); + o.rows = 25; + o.depends('configfile', '/etc/mosdns/config_custom.yaml'); + o.cfgvalue = function (section_id) { + return fs.trimmed('/etc/mosdns/config_custom.yaml'); + }; + o.write = function (section_id, formvalue) { + return fs.write('/etc/mosdns/config_custom.yaml', formvalue.trim().replace(/\r\n/g, '\n') + '\n') + .then(function (i) { + ui.addNotification(null, E('p', _('Configuration have been saved.')), 'info'); + return fs.exec('/etc/init.d/mosdns', ['restart']); + }) + .catch(function (e) { + ui.addNotification(null, E('p', _('Unable to save contents: %s').format(e.message))); + }); + }; + + o = s.taboption('geodata', form.DynamicList, 'geosite_tags', _('GeoSite Tags'), + _('Enter the GeoSite.dat category to be exported, Allow add multiple tags'), + _('Export directory: /var/mosdns')); + o.depends('configfile', '/etc/mosdns/config_custom.yaml'); + + o = s.taboption('geodata', form.DynamicList, 'geoip_tags', _('GeoIP Tags'), + _('Enter the GeoIP.dat category to be exported, Allow add multiple tags'), + _('Export directory: /var/mosdns')); + o.depends('configfile', '/etc/mosdns/config_custom.yaml'); + + return m.render(); + } +}); diff --git a/luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/logs.js b/luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/logs.js new file mode 100644 index 000000000..d4cd902d4 --- /dev/null +++ b/luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/logs.js @@ -0,0 +1,77 @@ +'use strict'; +'require dom'; +'require fs'; +'require poll'; +'require view'; + +function pollLog(e) { + return Promise.all([ + fs.exec_direct('/usr/share/mosdns/mosdns.sh', ['printlog']).then(function (res) { + return res.trim().split(/\n/).join('\n') + }), + ]).then(function (data) { + var logTextarea = E('textarea', { 'class': 'cbi-input-textarea', 'wrap': 'off', 'readonly': 'readonly', 'style': 'width: calc(100% - 20px);height: 645px;margin: 10px;overflow-y: scroll;' }, [ + data[0] || _('No log data.') + ]); + + // Store the current scroll position + var storedScrollTop = e.querySelector('textarea') ? e.querySelector('textarea').scrollTop : null; + + dom.content(e, logTextarea); + + // If the storedScrollTop is not null, it means we have a previous scroll position + if (storedScrollTop !== null) { + logTextarea.scrollTop = storedScrollTop; + } + + // Add event listener to save the scroll position when scrolling stops + var timer; + logTextarea.addEventListener('scroll', function () { + clearTimeout(timer); + timer = setTimeout(function () { + storeScrollPosition(logTextarea.scrollTop); + }, 150); + }); + + function storeScrollPosition(scrollPos) { + localStorage.setItem("scrollPosition", JSON.stringify({ "log": scrollPos })); + } + + }); +}; + +return view.extend({ + handleCleanLogs: function () { + return fs.exec('/usr/share/mosdns/mosdns.sh', ['cleanlog']) + .catch(function (e) { ui.addNotification(null, E('p', e.message)) }); + }, + + render: function () { + var log_textarea = E('div', { 'id': 'log_textarea' }, + E('img', { + 'src': L.resource(['icons/loading.gif']), + 'alt': _('Loading'), + 'style': 'vertical-align:middle' + }, _('Collecting data...')) + ); + + poll.add(pollLog.bind(this, log_textarea)); + var clear_logs_button = E('input', { 'class': 'btn cbi-button-action', 'type': 'button', 'style': 'margin-left: 10px; margin-top: 10px;', 'value': _('Clear logs') }); + clear_logs_button.addEventListener('click', this.handleCleanLogs.bind(this)); + return E([ + E('div', { 'class': 'cbi-map' }, [ + E('h2', { 'name': 'content' }, '%s - %s'.format(_('MosDNS'), _('Log Data'))), + E('div', { 'class': 'cbi-section' }, [ + clear_logs_button, + log_textarea, + E('div', { 'style': 'text-align:right' }, + E('small', {}, _('Refresh every %s seconds.').format(L.env.pollinterval)) + ) + ])]) + ]); + }, + + handleSave: null, + handleSaveApply: null, + handleReset: null +}); diff --git a/luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/rules.js b/luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/rules.js new file mode 100644 index 000000000..f3cf9264f --- /dev/null +++ b/luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/rules.js @@ -0,0 +1,251 @@ +'use strict'; +'require form'; +'require fs'; +'require ui'; +'require view'; + +return view.extend({ + render: function () { + var m, s, o; + + m = new form.Map("mosdns", _("Rule Settings"), + _('The list of rules only apply to \'Default Config\' profiles.')); + + s = m.section(form.TypedSection); + s.anonymous = true; + s.sortable = true; + + s.tab('whitelist', _('White Lists')); + s.tab('blocklist', _('Block Lists')); + s.tab('greylist', _('Grey Lists')); + s.tab('ddnslist', _('DDNS Lists')); + s.tab('hostslist', _('Hosts')); + s.tab('redirectlist', _('Redirect')); + s.tab('localptrlist', _('Block PTR')); + s.tab('streamingmedialist', _('Streaming Media')); + + o = s.taboption('whitelist', form.TextValue, '_whitelist', + null, + '' + + _('Added domain names always permit resolution using \'local DNS\' with the highest priority (one domain per line, supports domain matching rules).') + + '' + ); + o.rows = 25; + o.cfgvalue = function (section_id) { + return fs.trimmed('/etc/mosdns/rule/whitelist.txt').catch(function (e) { + return ""; + }); + }; + o.write = function (section_id, formvalue) { + return this.cfgvalue(section_id).then(function (value) { + if (value == formvalue) { + return; + } + return fs.write('/etc/mosdns/rule/whitelist.txt', formvalue.trim().replace(/\r\n/g, '\n') + '\n') + .then(function (i) { + ui.addNotification(null, E('p', _('Rules have been saved.')), 'info'); + }) + .catch(function (e) { + ui.addNotification(null, E('p', _('Unable to save contents: %s').format(e.message))); + }); + }); + }; + + o = s.taboption('blocklist', form.TextValue, '_blocklist', + null, + '' + + _('Added domain names will block DNS resolution (one domain per line, supports domain matching rules).') + + '' + ); + o.rows = 25; + o.cfgvalue = function (section_id) { + return fs.trimmed('/etc/mosdns/rule/blocklist.txt').catch(function (e) { + return ""; + }); + }; + o.write = function (section_id, formvalue) { + return this.cfgvalue(section_id).then(function (value) { + if (value == formvalue) { + return; + } + return fs.write('/etc/mosdns/rule/blocklist.txt', formvalue.trim().replace(/\r\n/g, '\n') + '\n') + .then(function (i) { + ui.addNotification(null, E('p', _('Rules have been saved.')), 'info'); + }) + .catch(function (e) { + ui.addNotification(null, E('p', _('Unable to save contents: %s').format(e.message))); + }); + }); + }; + + o = s.taboption('greylist', form.TextValue, '_greylist', + null, + '' + + _('Added domain names will always use \'Remote DNS\' for resolution (one domain per line, supports domain matching rules).') + + '' + ); + o.rows = 25; + o.cfgvalue = function (section_id) { + return fs.trimmed('/etc/mosdns/rule/greylist.txt').catch(function (e) { + return ""; + }); + }; + o.write = function (section_id, formvalue) { + return this.cfgvalue(section_id).then(function (value) { + if (value == formvalue) { + return; + } + return fs.write('/etc/mosdns/rule/greylist.txt', formvalue.trim().replace(/\r\n/g, '\n') + '\n') + .then(function (i) { + ui.addNotification(null, E('p', _('Rules have been saved.')), 'info'); + }) + .catch(function (e) { + ui.addNotification(null, E('p', _('Unable to save contents: %s').format(e.message))); + }); + }); + }; + + o = s.taboption('ddnslist', form.TextValue, '_ddnslist', + null, + '' + + _('Added domain names will always use \'Local DNS\' for resolution, with a forced TTL of 5 seconds, and results will not be cached (one domain per line, supports domain matching rules).') + + '' + ); + o.rows = 25; + o.cfgvalue = function (section_id) { + return fs.trimmed('/etc/mosdns/rule/ddnslist.txt').catch(function (e) { + return ""; + }); + }; + o.write = function (section_id, formvalue) { + return this.cfgvalue(section_id).then(function (value) { + if (value == formvalue) { + return; + } + return fs.write('/etc/mosdns/rule/ddnslist.txt', formvalue.trim().replace(/\r\n/g, '\n') + '\n') + .then(function (i) { + ui.addNotification(null, E('p', _('Rules have been saved.')), 'info'); + }) + .catch(function (e) { + ui.addNotification(null, E('p', _('Unable to save contents: %s').format(e.message))); + }); + }); + }; + + o = s.taboption('hostslist', form.TextValue, '_hostslist', + null, + '' + + _('Custom Hosts rewrite, for example: baidu.com 10.0.0.1 (one rule per line, supports domain matching rules).') + + '' + ); + o.rows = 25; + o.cfgvalue = function (section_id) { + return fs.trimmed('/etc/mosdns/rule/hosts.txt').catch(function (e) { + return ""; + }); + }; + o.write = function (section_id, formvalue) { + return this.cfgvalue(section_id).then(function (value) { + if (value == formvalue) { + return; + } + return fs.write('/etc/mosdns/rule/hosts.txt', formvalue.trim().replace(/\r\n/g, '\n') + '\n') + .then(function (i) { + ui.addNotification(null, E('p', _('Rules have been saved.')), 'info'); + }) + .catch(function (e) { + ui.addNotification(null, E('p', _('Unable to save contents: %s').format(e.message))); + }); + }); + }; + + o = s.taboption('redirectlist', form.TextValue, '_redirectlist', + null, + '' + + _('Redirecting requests for domain names. Request domain A, but return records for domain B, for example: baidu.com qq.com (one rule per line).') + + '' + ); + o.rows = 25; + o.cfgvalue = function (section_id) { + return fs.trimmed('/etc/mosdns/rule/redirect.txt').catch(function (e) { + return ""; + }); + }; + o.write = function (section_id, formvalue) { + return this.cfgvalue(section_id).then(function (value) { + if (value == formvalue) { + return; + } + return fs.write('/etc/mosdns/rule/redirect.txt', formvalue.trim().replace(/\r\n/g, '\n') + '\n') + .then(function (i) { + ui.addNotification(null, E('p', _('Rules have been saved.')), 'info'); + }) + .catch(function (e) { + ui.addNotification(null, E('p', _('Unable to save contents: %s').format(e.message))); + }); + }); + }; + + o = s.taboption('localptrlist', form.TextValue, '_localptrlist', + null, + '' + + _('Added domain names will block PTR requests (one domain per line, supports domain matching rules).') + + '' + ); + o.rows = 25; + o.cfgvalue = function (section_id) { + return fs.trimmed('/etc/mosdns/rule/local-ptr.txt').catch(function (e) { + return ""; + }); + }; + o.write = function (section_id, formvalue) { + return this.cfgvalue(section_id).then(function (value) { + if (value == formvalue) { + return; + } + return fs.write('/etc/mosdns/rule/local-ptr.txt', formvalue.trim().replace(/\r\n/g, '\n') + '\n') + .then(function (i) { + ui.addNotification(null, E('p', _('Rules have been saved.')), 'info'); + }) + .catch(function (e) { + ui.addNotification(null, E('p', _('Unable to save contents: %s').format(e.message))); + }); + }); + }; + + o = s.taboption('streamingmedialist', form.TextValue, '_streamingmedialist', + null, + '' + + _('When enabling \'Custom Stream Media DNS\', added domains will always use the \'Streaming Media DNS server\' for resolution (one domain per line, supports domain matching rules).') + + '' + ); + o.rows = 25; + o.cfgvalue = function (section_id) { + return fs.trimmed('/etc/mosdns/rule/streaming.txt').catch(function (e) { + return ""; + }); + }; + o.write = function (section_id, formvalue) { + return this.cfgvalue(section_id).then(function (value) { + if (value == formvalue) { + return; + } + return fs.write('/etc/mosdns/rule/streaming.txt', formvalue.trim().replace(/\r\n/g, '\n') + '\n') + .then(function (i) { + ui.addNotification(null, E('p', _('Rules have been saved.')), 'info'); + }) + .catch(function (e) { + ui.addNotification(null, E('p', _('Unable to save contents: %s').format(e.message))); + }); + }); + }; + + return m.render(); + }, + + handleSaveApply: function (ev) { + onclick = L.bind(this.handleSave, this, m); + return fs.exec('/etc/init.d/mosdns', ['restart']); + }, + handleReset: null +}); diff --git a/luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/update.js b/luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/update.js new file mode 100644 index 000000000..1bff07036 --- /dev/null +++ b/luci-app-mosdns/htdocs/luci-static/resources/view/mosdns/update.js @@ -0,0 +1,65 @@ +'use strict'; +'require form'; +'require fs'; +'require ui'; +'require view'; + +return view.extend({ + handleUpdate: function (m, section_id, ev) { + return fs.exec('/usr/share/mosdns/mosdns.sh', ['geodata']) + .then(function (i) { + var res = i.code; + if (res === 0) { + ui.addNotification(null, E('p', _('Update success')), 'info'); + } else { + ui.addNotification(null, E('p', i.stderr + '
' + i.stdout), 'warn'); + ui.addNotification(null, E('p', _('Update failed, Please check the network status')), 'error'); + } + }); + }, + + render: function () { + var m, s, o; + + m = new form.Map('mosdns', _('Update GeoIP & GeoSite databases'), + _('Automatically update GeoIP and GeoSite databases as well as ad filtering rules through scheduled tasks.')); + + s = m.section(form.TypedSection); + s.anonymous = true; + + o = s.option(form.Flag, 'geo_auto_update', _('Enable Auto Database Update')); + o.rmempty = false; + + o = s.option(form.ListValue, 'geo_update_week_time', _('Update Cycle')); + o.value('*', _('Every Day')); + o.value('1', _('Every Monday')); + o.value('2', _('Every Tuesday')); + o.value('3', _('Every Wednesday')); + o.value('4', _('Every Thursday')); + o.value('5', _('Every Friday')); + o.value('6', _('Every Saturday')); + o.value('7', _('Every Sunday')); + o.default = 3; + + o = s.option(form.ListValue, 'geo_update_day_time', _('Update Time')); + for (let t = 0; t < 24; t++) { + o.value(t, t + ':00'); + }; + o.default = 3; + + o = s.option(form.Value, 'github_proxy', _('GitHub Proxy'), + _('Update data files with GitHub Proxy, leave blank to disable proxy downloads.')); + o.value('https://hub.gitmirror.com', _('https://hub.gitmirror.com')); + o.rmempty = true; + o.default = ''; + + o = s.option(form.Button, '_udpate', null, + _('Check And Update GeoData.')); + o.title = _('Database Update'); + o.inputtitle = _('Check And Update'); + o.inputstyle = 'apply'; + o.onclick = L.bind(this.handleUpdate, this, m); + + return m.render(); + } +}); diff --git a/luci-app-mosdns/luasrc/controller/mosdns.lua b/luci-app-mosdns/luasrc/controller/mosdns.lua deleted file mode 100644 index 60840fbb0..000000000 --- a/luci-app-mosdns/luasrc/controller/mosdns.lua +++ /dev/null @@ -1,53 +0,0 @@ -local sys = require "luci.sys" -local http = require "luci.http" - -module("luci.controller.mosdns", package.seeall) - -function index() - if not nixio.fs.access("/etc/config/mosdns") then - return - end - - local page = entry({"admin", "services", "mosdns"}, alias("admin", "services", "mosdns", "basic"), _("MosDNS"), 30) - page.dependent = true - page.acl_depends = { "luci-app-mosdns" } - - entry({"admin", "services", "mosdns", "basic"}, cbi("mosdns/basic"), _("Basic Setting"), 1).leaf = true - entry({"admin", "services", "mosdns", "rule_list"}, cbi("mosdns/rule_list"), _("Rule List"), 2).leaf = true - entry({"admin", "services", "mosdns", "update"}, cbi("mosdns/update"), _("Geodata Update"), 3).leaf = true - entry({"admin", "services", "mosdns", "log"}, cbi("mosdns/log"), _("Logs"), 4).leaf = true - entry({"admin", "services", "mosdns", "status"}, call("act_status")).leaf = true - entry({"admin", "services", "mosdns", "get_log"}, call("get_log")).leaf = true - entry({"admin", "services", "mosdns", "clear_log"}, call("clear_log")).leaf = true - entry({"admin", "services", "mosdns", "geo_update"}, call("geo_update")).leaf = true - entry({"admin", "services", "mosdns", "flush_cache"}, call("flush_cache")).leaf = true -end - -function act_status() - local e = {} - e.running = sys.call("pgrep -f mosdns >/dev/null") == 0 - http.prepare_content("application/json") - http.write_json(e) -end - -function get_log() - http.write(sys.exec("cat $(/usr/share/mosdns/mosdns.sh logfile)")) -end - -function clear_log() - sys.call("cat /dev/null > $(/usr/share/mosdns/mosdns.sh logfile)") -end - -function geo_update() - local e = {} - e.updating = sys.call("/usr/share/mosdns/mosdns.sh geodata >/dev/null") == 0 - http.prepare_content("application/json") - http.write_json(e) -end - -function flush_cache() - local e = {} - e.flushing = sys.call("/usr/share/mosdns/mosdns.sh flush >/dev/null") == 0 - http.prepare_content("application/json") - http.write_json(e) -end diff --git a/luci-app-mosdns/luasrc/model/cbi/mosdns/basic.lua b/luci-app-mosdns/luasrc/model/cbi/mosdns/basic.lua deleted file mode 100644 index dcd8f4871..000000000 --- a/luci-app-mosdns/luasrc/model/cbi/mosdns/basic.lua +++ /dev/null @@ -1,264 +0,0 @@ -local fs = require "nixio.fs" -local sys = require "luci.sys" - -if fs.access("/usr/bin/mosdns") then - mosdns_version = sys.exec("/usr/share/mosdns/mosdns.sh version") -else - mosdns_version = "Unknown Version" -end -m = Map("mosdns") -m.title = translate("MosDNS") .. " " .. mosdns_version -m.description = translate("MosDNS is a plugin-based DNS forwarder/traffic splitter.") - -m:section(SimpleSection).template = "mosdns/mosdns_status" - -s = m:section(TypedSection, "mosdns") -s.addremove = false -s.anonymous = true - -s:tab("basic", translate("Basic Options")) - -o = s:taboption("basic", Flag, "enabled", translate("Enabled")) -o.rmempty = false - -o = s:taboption("basic", ListValue, "configfile", translate("Config File")) -o:value("/var/etc/mosdns.json", translate("Default Config")) -o:value("/etc/mosdns/config_custom.yaml", translate("Custom Config")) -o.default = "/var/etc/mosdns.json" - -o = s:taboption("basic", Value, "listen_port", translate("Listen port")) -o.datatype = "and(port,min(1))" -o.default = 5335 -o:depends("configfile", "/var/etc/mosdns.json") - -o = s:taboption("basic", ListValue, "log_level", translate("Log Level")) -o:value("debug", translate("Debug")) -o:value("info", translate("Info")) -o:value("warn", translate("Warning")) -o:value("error", translate("Error")) -o.default = "info" -o:depends("configfile", "/var/etc/mosdns.json") - -o = s:taboption("basic", Value, "log_file", translate("Log File")) -o.placeholder = "/var/log/mosdns.log" -o.default = "/var/log/mosdns.log" -o:depends("configfile", "/var/etc/mosdns.json") - -o = s:taboption("basic", Flag, "redirect", translate("DNS Forward"), translate("Forward Dnsmasq Domain Name resolution requests to MosDNS")) -o.default = true - -o = s:taboption("basic", Flag, "prefer_ipv4", translate("Remote DNS prefer IPv4"), translate("IPv4 is preferred for Remote / Streaming Media DNS resolution of dual-stack addresses, and is not affected when the destination is IPv6 only")) -o:depends( "configfile", "/var/etc/mosdns.json") -o.default = true - -o = s:taboption("basic", Flag, "custom_local_dns", translate("Custom China DNS"), translate("Follow WAN interface DNS if not enabled")) -o:depends( "configfile", "/var/etc/mosdns.json") -o.default = false - -o = s:taboption("basic", Flag, "apple_optimization", translate("Apple domains optimization"), translate("For Apple domains equipped with Chinese mainland CDN, always responsive to Chinese CDN IP addresses")) -o:depends("custom_local_dns", "1") -o.default = false - -o = s:taboption("basic", DynamicList, "local_dns", translate("China DNS server")) -o:value("119.29.29.29", translate("Tencent Public DNS (119.29.29.29)")) -o:value("119.28.28.28", translate("Tencent Public DNS (119.28.28.28)")) -o:value("223.5.5.5", translate("Aliyun Public DNS (223.5.5.5)")) -o:value("223.6.6.6", translate("Aliyun Public DNS (223.6.6.6)")) -o:value("114.114.114.114", translate("Xinfeng Public DNS (114.114.114.114)")) -o:value("114.114.115.115", translate("Xinfeng Public DNS (114.114.115.115)")) -o:value("180.76.76.76", translate("Baidu Public DNS (180.76.76.76)")) -o:value("https://doh.pub/dns-query", translate("Tencent Public DNS (DNS over HTTPS)")) -o:value("quic://dns.alidns.com", translate("Aliyun Public DNS (DNS over QUIC)")) -o:value("https://dns.alidns.com/dns-query", translate("Aliyun Public DNS (DNS over HTTPS)")) -o:value("h3://dns.alidns.com/dns-query", translate("Aliyun Public DNS (DNS over HTTPS/3)")) -o:value("https://doh.360.cn/dns-query", translate("360 Public DNS (DNS over HTTPS)")) -o:depends("custom_local_dns", "1") - -o = s:taboption("basic", DynamicList, "remote_dns", translate("Remote DNS server")) -o:value("tls://1.1.1.1", translate("CloudFlare Public DNS (1.1.1.1)")) -o:value("tls://1.0.0.1", translate("CloudFlare Public DNS (1.0.0.1)")) -o:value("tls://8.8.8.8", translate("Google Public DNS (8.8.8.8)")) -o:value("tls://8.8.4.4", translate("Google Public DNS (8.8.4.4)")) -o:value("tls://9.9.9.9", translate("Quad9 Public DNS (9.9.9.9)")) -o:value("tls://149.112.112.112", translate("Quad9 Public DNS (149.112.112.112)")) -o:value("tls://208.67.222.222", translate("Cisco Public DNS (208.67.222.222)")) -o:value("tls://208.67.220.220", translate("Cisco Public DNS (208.67.220.220)")) -o:depends("configfile", "/var/etc/mosdns.json") - -o = s:taboption("basic", Flag, "custom_stream_media_dns", translate("Custom Stream Media DNS"), translate("Netflix, Disney+, Hulu and streaming media rules list will use this DNS")) -o:depends( "configfile", "/var/etc/mosdns.json") -o.default = false - -o = s:taboption("basic", DynamicList, "stream_media_dns", translate("Streaming Media DNS server")) -o:value("tls://1.1.1.1", translate("CloudFlare Public DNS (1.1.1.1)")) -o:value("tls://1.0.0.1", translate("CloudFlare Public DNS (1.0.0.1)")) -o:value("tls://8.8.8.8", translate("Google Public DNS (8.8.8.8)")) -o:value("tls://8.8.4.4", translate("Google Public DNS (8.8.4.4)")) -o:value("tls://9.9.9.9", translate("Quad9 Public DNS (9.9.9.9)")) -o:value("tls://149.112.112.112", translate("Quad9 Public DNS (149.112.112.112)")) -o:value("tls://208.67.222.222", translate("Cisco Public DNS (208.67.222.222)")) -o:value("tls://208.67.220.220", translate("Cisco Public DNS (208.67.220.220)")) -o.default = "tls://8.8.8.8" -o:depends("custom_stream_media_dns", "1") - -o = s:taboption("basic", ListValue, "bootstrap_dns", translate("Bootstrap DNS servers"), translate("Bootstrap DNS servers are used to resolve IP addresses of the DoH/DoT resolvers you specify as upstreams")) -o:value("119.29.29.29", translate("Tencent Public DNS (119.29.29.29)")) -o:value("119.28.28.28", translate("Tencent Public DNS (119.28.28.28)")) -o:value("223.5.5.5", translate("Aliyun Public DNS (223.5.5.5)")) -o:value("223.6.6.6", translate("Aliyun Public DNS (223.6.6.6)")) -o:value("114.114.114.114", translate("Xinfeng Public DNS (114.114.114.114)")) -o:value("114.114.115.115", translate("Xinfeng Public DNS (114.114.115.115)")) -o:value("180.76.76.76", translate("Baidu Public DNS (180.76.76.76)")) -o:value("8.8.8.8", translate("Google Public DNS (8.8.8.8)")) -o:value("1.1.1.1", translate("CloudFlare Public DNS (1.1.1.1)")) -o.default = "119.29.29.29" -o:depends("configfile", "/var/etc/mosdns.json") - -s:tab("advanced", translate("Advanced Options")) - -o = s:taboption("advanced", Value, "concurrent", translate("Concurrent"), translate("DNS query request concurrency, The number of upstream DNS servers that are allowed to initiate requests at the same time")) -o.datatype = "and(uinteger,min(1),max(3))" -o.default = "2" -o:depends("configfile", "/var/etc/mosdns.json") - -o = s:taboption("advanced", Value, "idle_timeout", translate("Idle Timeout"), translate("DoH/TCP/DoT Connection Multiplexing idle timeout (default 30 seconds)")) -o.datatype = "and(uinteger,min(1))" -o.default = "30" -o:depends("configfile", "/var/etc/mosdns.json") - -o = s:taboption("advanced", Flag, "enable_pipeline", translate("TCP/DoT Connection Multiplexing"), translate("Enable TCP/DoT RFC 7766 new Query Pipelining connection multiplexing mode")) -o.rmempty = false -o.default = false -o:depends("configfile", "/var/etc/mosdns.json") - -o = s:taboption("advanced", Flag, "insecure_skip_verify", translate("Disable TLS Certificate"), translate("Disable TLS Servers certificate validation, Can be useful if system CA certificate expires or the system time is out of order")) -o.rmempty = false -o.default = false -o:depends("configfile", "/var/etc/mosdns.json") - -o = s:taboption("advanced", Flag, "enable_ecs_remote", translate("Enable EDNS client subnet")) -o.rmempty = false -o.default = false -o:depends("configfile", "/var/etc/mosdns.json") - -o = s:taboption("advanced", Value, "remote_ecs_ip", translate("IP Address"), translate("Please provide the IP address you use when accessing foreign websites. This IP subnet (0/24) will be used as the ECS address for Remote / Streaming Media DNS requests") .. '
' .. translate("This feature is typically used when using a self-built DNS server as an Remote / Streaming Media DNS upstream (requires support from the upstream server)")) -o.datatype = "ipaddr" -o:depends("enable_ecs_remote", "1") - -o = s:taboption("advanced", Flag, "dns_leak", translate("Prevent DNS Leaks"), translate("Enable this option fallback policy forces forwarding to remote DNS")) -o.rmempty = false -o.default = false -o:depends("configfile", "/var/etc/mosdns.json") - -o = s:taboption("advanced", Flag, "cache", translate("Enable DNS Cache")) -o.rmempty = false -o.default = false -o:depends("configfile", "/var/etc/mosdns.json") - -o = s:taboption("advanced", Value, "cache_size", translate("DNS Cache Size"), translate("DNS cache size (in piece).")) -o.datatype = "and(uinteger,min(0))" -o.default = "8000" -o:depends("cache", "1") - -o = s:taboption("advanced", Value, "lazy_cache_ttl", translate("Lazy Cache TTL"), translate("Lazy cache survival time (in second). To disable Lazy Cache, please set to 0.")) -o.datatype = "and(uinteger,min(0))" -o.default = "86400" -o:depends("cache", "1") - -o = s:taboption("advanced", Flag, "dump_file", translate("Cache Dump"), translate("Save the cache locally and reload the cache dump on the next startup")) -o.rmempty = false -o.default = false -o:depends("cache", "1") - -o = s:taboption("advanced", Value, "dump_interval", translate("Auto Save Cache Interval")) -o.datatype = "and(uinteger,min(0))" -o.default = "3600" -o:depends("dump_file", "1") - -o = s:taboption("advanced", Value, "minimal_ttl", translate("Minimum TTL"), translate("Modify the Minimum TTL value (seconds) for DNS answer results, 0 indicating no modification")) -o.datatype = "and(uinteger,min(0),max(604800))" -o.default = "0" -o:depends("configfile", "/var/etc/mosdns.json") - -o = s:taboption("advanced", Value, "maximum_ttl", translate("Maximum TTL"), translate("Modify the Maximum TTL value (seconds) for DNS answer results, 0 indicating no modification")) -o.datatype = "and(uinteger,min(0),max(604800))" -o.default = "0" -o:depends("configfile", "/var/etc/mosdns.json") - -o = s:taboption("advanced", Flag, "adblock", translate("Enable DNS ADblock")) -o:depends("configfile", "/var/etc/mosdns.json") -o.default = false - -o = s:taboption("advanced", DynamicList, "ad_source", translate("ADblock Source"), translate("When using custom rule sources, please use rule types supported by MosDNS (domain lists).") .. '
' .. translate("Support for local files, such as: file:///var/mosdns/example.txt")) -o:depends("adblock", "1") -o.default = "geosite.dat" -o:value("geosite.dat", "v2ray-geosite") -o:value("https://raw.githubusercontent.com/privacy-protection-tools/anti-AD/master/anti-ad-domains.txt", "anti-AD") -o:value("https://raw.githubusercontent.com/Cats-Team/AdRules/main/mosdns_adrules.txt", "Cats-Team/AdRules") -o:value("https://raw.githubusercontent.com/neodevpro/neodevhost/master/domain", "NEO DEV HOST") - -o = s:taboption("basic", Button, "_reload", translate("Restart-Service"), translate("Restart the MosDNS process to take effect of new configuration")) -o.write = function() - sys.exec("/etc/init.d/mosdns reload") -end -o:depends("configfile", "/etc/mosdns/config_custom.yaml") - -o = s:taboption("basic", TextValue, "config_custom", translate("Configuration Editor")) -o.template = "cbi/tvalue" -o.rows = 25 -o:depends("configfile", "/etc/mosdns/config_custom.yaml") -function o.cfgvalue(self, section) - return fs.readfile("/etc/mosdns/config_custom.yaml") -end -function o.write(self, section, value) - value = value:gsub("\r\n?", "\n") - fs.writefile("/etc/mosdns/config_custom.yaml", value) -end --- codemirror -o = s:taboption("basic", DummyValue, "") -o.template = "mosdns/mosdns_editor" - -s:tab("cloudflare", translate("Cloudflare Options")) -o = s:taboption("cloudflare", Flag, "cloudflare", translate("Enabled"), translate("Match the parsing result with the Cloudflare IP ranges, and when there is a successful match, use the 'Custom IP' as the parsing result (experimental feature)")) -o.rmempty = false -o.default = false -o:depends("configfile", "/var/etc/mosdns.json") - -o = s:taboption("cloudflare", DynamicList, "cloudflare_ip", translate("Custom IP")) -o.datatype = "ipaddr" -o:depends("configfile", "/var/etc/mosdns.json") - -o = s:taboption("cloudflare", TextValue, "cloudflare_cidr", translate("Cloudflare IP Ranges")) -o.description = translate("IPv4 CIDR:") .. [[https://www.cloudflare.com/ips-v4]] .. '
' .. translate("IPv6 CIDR:") .. [[https://www.cloudflare.com/ips-v6]] -o.template = "cbi/tvalue" -o.rows = 15 -o:depends("configfile", "/var/etc/mosdns.json") -function o.cfgvalue(self, section) - return fs.readfile("/etc/mosdns/rule/cloudflare-cidr.txt") -end -function o.write(self, section, value) - value = value:gsub("\r\n?", "\n") - fs.writefile("/etc/mosdns/rule/cloudflare-cidr.txt", value) -end - -s:tab("api", translate("API Options")) - -o = s:taboption("api", Value, "listen_port_api", translate("API Listen port")) -o.datatype = "and(port,min(1))" -o.default = 9091 -o:depends("configfile", "/var/etc/mosdns.json") - -o = s:taboption("api", Button, "flush_cache", translate("Flush Cache"), translate("Flushing Cache will clear any IP addresses or DNS records from MosDNS cache")) -o.rawhtml = true -o.template = "mosdns/mosdns_flush_cache" -o:depends("configfile", "/var/etc/mosdns.json") - -s:tab("geodata", translate("GeoData Export")) - -o = s:taboption("geodata", DynamicList, "geosite_tags", translate("GeoSite Tags"), translate("Enter the GeoSite.dat category to be exported, Allow add multiple tags") .. '
' .. translate("Export directory: /var/mosdns")) -o:depends("configfile", "/etc/mosdns/config_custom.yaml") - -o = s:taboption("geodata", DynamicList, "geoip_tags", translate("GeoIP Tags"), translate("Enter the GeoIP.dat category to be exported, Allow add multiple tags") .. '
' .. translate("Export directory: /var/mosdns")) -o:depends("configfile", "/etc/mosdns/config_custom.yaml") - -return m diff --git a/luci-app-mosdns/luasrc/model/cbi/mosdns/log.lua b/luci-app-mosdns/luasrc/model/cbi/mosdns/log.lua deleted file mode 100644 index 79fc1a95e..000000000 --- a/luci-app-mosdns/luasrc/model/cbi/mosdns/log.lua +++ /dev/null @@ -1,5 +0,0 @@ -m = Map("mosdns") - -m:append(Template("mosdns/mosdns_log")) - -return m diff --git a/luci-app-mosdns/luasrc/model/cbi/mosdns/rule_list.lua b/luci-app-mosdns/luasrc/model/cbi/mosdns/rule_list.lua deleted file mode 100644 index d41957beb..000000000 --- a/luci-app-mosdns/luasrc/model/cbi/mosdns/rule_list.lua +++ /dev/null @@ -1,111 +0,0 @@ -local datatypes = require "luci.cbi.datatypes" - -local white_list_file = "/etc/mosdns/rule/whitelist.txt" -local block_list_file = "/etc/mosdns/rule/blocklist.txt" -local grey_list_file = "/etc/mosdns/rule/greylist.txt" -local hosts_list_file = "/etc/mosdns/rule/hosts.txt" -local redirect_list_file = "/etc/mosdns/rule/redirect.txt" -local local_ptr_file = "/etc/mosdns/rule/local-ptr.txt" -local ddns_list_file = "/etc/mosdns/rule/ddnslist.txt" -local streaming_media_list_file = "/etc/mosdns/rule/streaming.txt" - -m = Map("mosdns") - -s = m:section(TypedSection, "mosdns", translate("Rule Settings")) -s.anonymous = true - -s:tab("white_list", translate("White Lists")) -s:tab("block_list", translate("Block Lists")) -s:tab("grey_list", translate("Grey Lists")) -s:tab("ddns_list", translate("DDNS Lists")) -s:tab("hosts_list", translate("Hosts")) -s:tab("redirect_list", translate("Redirect")) -s:tab("local_ptr_list", translate("Block PTR")) -s:tab("streaming_media_list", translate("Streaming Media")) - -o = s:taboption("white_list", TextValue, "whitelist", "", "" .. translate("These domain names allow DNS resolution with the highest priority. Please input the domain names of websites, every line can input only one website domain. For example: hm.baidu.com.") .. "" .. "" .. translate("
The list of rules only apply to 'Default Config' profiles.") .. "
") -o.rows = 15 -o.wrap = "off" -o.cfgvalue = function(self, section) return nixio.fs.readfile(white_list_file) or "" end -o.write = function(self, section, value) nixio.fs.writefile(white_list_file , value:gsub("\r\n", "\n")) end -o.remove = function(self, section, value) nixio.fs.writefile(white_list_file , "") end -o.validate = function(self, value) - return value -end - -o = s:taboption("block_list", TextValue, "blocklist", "", "" .. translate("These domains are blocked from DNS resolution. Please input the domain names of websites, every line can input only one website domain. For example: baidu.com.") .. "" .. "" .. translate("
The list of rules only apply to 'Default Config' profiles.") .. "
") -o.rows = 15 -o.wrap = "off" -o.cfgvalue = function(self, section) return nixio.fs.readfile(block_list_file) or "" end -o.write = function(self, section, value) nixio.fs.writefile(block_list_file, value:gsub("\r\n", "\n")) end -o.remove = function(self, section, value) nixio.fs.writefile(block_list_file, "") end -o.validate = function(self, value) - return value -end - -o = s:taboption("grey_list", TextValue, "greylist", "", "" .. translate("These domains are always resolved using remote DNS. Please input the domain names of websites, every line can input only one website domain. For example: google.com.") .. "" .. "" .. translate("
The list of rules only apply to 'Default Config' profiles.") .. "
") -o.rows = 15 -o.wrap = "off" -o.cfgvalue = function(self, section) return nixio.fs.readfile(grey_list_file) or "" end -o.write = function(self, section, value) nixio.fs.writefile(grey_list_file, value:gsub("\r\n", "\n")) end -o.remove = function(self, section, value) nixio.fs.writefile(grey_list_file, "") end -o.validate = function(self, value) - return value -end - -o = s:taboption("ddns_list", TextValue, "ddns", "", "" .. translate("These domains are always resolved using local DNS. And force TTL 5 seconds, DNS resolution results will not enter the cache. For example: myddns.example.com.") .. "" .. "" .. translate("
The list of rules only apply to 'Default Config' profiles.") .. "
") -o.rows = 15 -o.wrap = "off" -o.cfgvalue = function(self, section) return nixio.fs.readfile(ddns_list_file) or "" end -o.write = function(self, section, value) nixio.fs.writefile(ddns_list_file, value:gsub("\r\n", "\n")) end -o.remove = function(self, section, value) nixio.fs.writefile(ddns_list_file, "") end -o.validate = function(self, value) - return value -end - -o = s:taboption("hosts_list", TextValue, "hosts", "", "" .. translate("Hosts For example: baidu.com 10.0.0.1") .. "" .. "" .. translate("
The list of rules only apply to 'Default Config' profiles.") .. "
") -o.rows = 15 -o.wrap = "off" -o.cfgvalue = function(self, section) return nixio.fs.readfile(hosts_list_file) or "" end -o.write = function(self, section, value) nixio.fs.writefile(hosts_list_file, value:gsub("\r\n", "\n")) end -o.remove = function(self, section, value) nixio.fs.writefile(hosts_list_file, "") end -o.validate = function(self, value) - return value -end - -o = s:taboption("redirect_list", TextValue, "redirect", "", "" .. translate("The domain name to redirect the request to. Requests domain A, but returns records for domain B. example: a.com b.com") .. "" .. "" .. translate("
The list of rules only apply to 'Default Config' profiles.") .. "
") -o.rows = 15 -o.wrap = "off" -o.cfgvalue = function(self, section) return nixio.fs.readfile(redirect_list_file) or "" end -o.write = function(self, section, value) nixio.fs.writefile(redirect_list_file, value:gsub("\r\n", "\n")) end -o.remove = function(self, section, value) nixio.fs.writefile(redirect_list_file, "") end -o.validate = function(self, value) - return value -end - -o = s:taboption("local_ptr_list", TextValue, "local_ptr", "", "" .. translate("These domains are blocked from PTR requests") .. "" .. "" .. translate("
The list of rules only apply to 'Default Config' profiles.") .. "
") -o.rows = 15 -o.wrap = "off" -o.cfgvalue = function(self, section) return nixio.fs.readfile(local_ptr_file) or "" end -o.write = function(self, section, value) nixio.fs.writefile(local_ptr_file, value:gsub("\r\n", "\n")) end -o.remove = function(self, section, value) nixio.fs.writefile(local_ptr_file, "") end -o.validate = function(self, value) - return value -end - -o = s:taboption("streaming_media_list", TextValue, "streaming_media", "", "" .. translate("These domains are always resolved using Streaming Media DNS. Please input the domain names of websites, every line can input only one website domain. For example: netflix.com.") .. "" .. "" .. translate("
The list of rules only apply to 'Default Config' profiles.") .. "
") -o.rows = 15 -o.wrap = "off" -o.cfgvalue = function(self, section) return nixio.fs.readfile(streaming_media_list_file) or "" end -o.write = function(self, section, value) nixio.fs.writefile(streaming_media_list_file, value:gsub("\r\n", "\n")) end -o.remove = function(self, section, value) nixio.fs.writefile(streaming_media_list_file, "") end -o.validate = function(self, value) - return value -end - -local apply = luci.http.formvalue("cbi.apply") -if apply then - luci.sys.exec("/etc/init.d/mosdns reload") -end - -return m diff --git a/luci-app-mosdns/luasrc/model/cbi/mosdns/update.lua b/luci-app-mosdns/luasrc/model/cbi/mosdns/update.lua deleted file mode 100644 index bcc14145b..000000000 --- a/luci-app-mosdns/luasrc/model/cbi/mosdns/update.lua +++ /dev/null @@ -1,37 +0,0 @@ -m = Map("mosdns") - -s = m:section(TypedSection, "mosdns", translate("Update GeoIP & GeoSite dat")) -s.addremove = false -s.anonymous = true - -o = s:option(Flag, "geo_auto_update", translate("Enable Auto Database Update")) -o.rmempty = false - -o = s:option(ListValue, "geo_update_week_time", translate("Update Cycle")) -o:value("*", translate("Every Day")) -o:value("1", translate("Every Monday")) -o:value("2", translate("Every Tuesday")) -o:value("3", translate("Every Wednesday")) -o:value("4", translate("Every Thursday")) -o:value("5", translate("Every Friday")) -o:value("6", translate("Every Saturday")) -o:value("7", translate("Every Sunday")) -o.default = "3" - -o = s:option(ListValue, "geo_update_day_time", translate("Update Time")) -for t = 0, 23 do - o:value(t, t..":00") -end -default = 3 - -o = s:option(Value, "github_proxy", translate("GitHub Proxy"), translate("Update data files with GitHub Proxy, leave blank to disable proxy downloads.")) -o:value("https://hub.gitmirror.com", translate("https://hub.gitmirror.com")) -o:value("https://ghps.cc", translate("https://ghps.cc")) -o.rmempty = true -o.default = "" - -o = s:option(Button, "geo_update_database", translate("Database Update")) -o.rawhtml = true -o.template = "mosdns/mosdns_geo_update" - -return m diff --git a/luci-app-mosdns/luasrc/view/mosdns/mosdns_editor.htm b/luci-app-mosdns/luasrc/view/mosdns/mosdns_editor.htm deleted file mode 100644 index 2ac907c7d..000000000 --- a/luci-app-mosdns/luasrc/view/mosdns/mosdns_editor.htm +++ /dev/null @@ -1,21 +0,0 @@ -<%+cbi/valueheader%> - - - - - - - - - -<%+cbi/valuefooter%> diff --git a/luci-app-mosdns/luasrc/view/mosdns/mosdns_flush_cache.htm b/luci-app-mosdns/luasrc/view/mosdns/mosdns_flush_cache.htm deleted file mode 100644 index 6734fbf0d..000000000 --- a/luci-app-mosdns/luasrc/view/mosdns/mosdns_flush_cache.htm +++ /dev/null @@ -1,34 +0,0 @@ -<%+cbi/valueheader%> - - -<%=self.value%> -<%+cbi/valuefooter%> diff --git a/luci-app-mosdns/luasrc/view/mosdns/mosdns_geo_update.htm b/luci-app-mosdns/luasrc/view/mosdns/mosdns_geo_update.htm deleted file mode 100644 index 813b3b530..000000000 --- a/luci-app-mosdns/luasrc/view/mosdns/mosdns_geo_update.htm +++ /dev/null @@ -1,34 +0,0 @@ -<%+cbi/valueheader%> - - -<%=self.value%> -<%+cbi/valuefooter%> diff --git a/luci-app-mosdns/luasrc/view/mosdns/mosdns_log.htm b/luci-app-mosdns/luasrc/view/mosdns/mosdns_log.htm deleted file mode 100644 index 9698f6917..000000000 --- a/luci-app-mosdns/luasrc/view/mosdns/mosdns_log.htm +++ /dev/null @@ -1,33 +0,0 @@ - -
- - -
diff --git a/luci-app-mosdns/luasrc/view/mosdns/mosdns_status.htm b/luci-app-mosdns/luasrc/view/mosdns/mosdns_status.htm deleted file mode 100644 index 268327957..000000000 --- a/luci-app-mosdns/luasrc/view/mosdns/mosdns_status.htm +++ /dev/null @@ -1,28 +0,0 @@ - - -
-

- <%:Collecting data...%> -

-
diff --git a/luci-app-mosdns/po/zh_Hans b/luci-app-mosdns/po/zh_Hans deleted file mode 120000 index 41451e4a1..000000000 --- a/luci-app-mosdns/po/zh_Hans +++ /dev/null @@ -1 +0,0 @@ -zh-cn \ No newline at end of file diff --git a/luci-app-mosdns/po/zh-cn/mosdns.po b/luci-app-mosdns/po/zh_Hans/mosdns.po similarity index 77% rename from luci-app-mosdns/po/zh-cn/mosdns.po rename to luci-app-mosdns/po/zh_Hans/mosdns.po index d60405403..16760aac9 100644 --- a/luci-app-mosdns/po/zh-cn/mosdns.po +++ b/luci-app-mosdns/po/zh_Hans/mosdns.po @@ -1,3 +1,19 @@ +msgid "" +msgstr "" +"Content-Type: text/plain; charset=UTF-8\n" +"Project-Id-Version: PACKAGE VERSION\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: zh_Hans\n" +"MIME-Version: 1.0\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "MosDNS" +msgstr "MosDNS" + +msgid "MosDNS is a plugin-based DNS forwarder/traffic splitter." +msgstr "MosDNS 是一个插件化的 DNS 转发/分流器。" + msgid "Basic Setting" msgstr "基本设置" @@ -13,9 +29,6 @@ msgstr "Cloudflare 选项" msgid "API Options" msgstr "API 选项" -msgid "MosDNS is a plugin-based DNS forwarder/traffic splitter." -msgstr "MosDNS 是一个插件化的 DNS 转发/分流器。" - msgid "RUNNING" msgstr "运行中" @@ -34,20 +47,17 @@ msgstr "监听端口" msgid "API Listen port" msgstr "API 监听端口" -msgid "Flush Cache" -msgstr "刷新缓存" - -msgid "Flushing Cache will clear any IP addresses or DNS records from MosDNS cache" -msgstr "刷新缓存会清空 MosDNS 所有 IP 地址和 DNS 解析缓存" +msgid "Flush DNS Cache" +msgstr "刷新 DNS 缓存" -msgid "Flushing..." -msgstr "正在刷新..." +msgid "Flushing DNS Cache will clear any IP addresses or DNS records from MosDNS cache." +msgstr "刷新 DNS 缓存会清空 MosDNS 所有 IP 地址和 DNS 解析缓存。" -msgid "Flushing Success" -msgstr "刷新成功" +msgid "Flushing DNS Cache Success." +msgstr "刷新 DNS 缓存成功" -msgid "Flushing Failed, Please check if MosDNS is enabled" -msgstr "刷新失败,请检查 MosDNS 是否已启用" +msgid "Flushing DNS Cache Failed, Please check if MosDNS is running." +msgstr "刷新 DNS 缓存失败,请检查 MosDNS 状态是否在运行中。" msgid "Match the parsing result with the Cloudflare IP ranges, and when there is a successful match, use the 'Custom IP' as the parsing result (experimental feature)" msgstr "将解析结果与 Cloudflare IP 范围进行匹配,当匹配成功时,使用 “自选 IP” 作为解析结果(实验性功能)" @@ -79,21 +89,27 @@ msgstr "使用自定义规则来源时,请使用 MosDNS 支持的规则类型 msgid "Support for local files, such as: file:///var/mosdns/example.txt" msgstr "支持本地文件,例如:file:///var/mosdns/example.txt" -msgid "Restart-Service" -msgstr "重启服务" - -msgid "Restart the MosDNS process to take effect of new configuration" -msgstr "重启 MosDNS 进程使新配置文件生效" - msgid "Configuration Editor" msgstr "配置编辑器" +msgid "Edit the MosDNS custom configuration file." +msgstr "编辑 MosDNS 自定义配置文件。" + +msgid "Configuration have been saved." +msgstr "配置已保存。" + +msgid "This is the content of the file '/etc/mosdns/config_custom.yaml' from which your MosDNS configuration will be generated. Only accepts configuration content in yaml format." +msgstr "这是文件 “/etc/mosdns/config_custom.yaml” 的内容,您的 MosDNS 配置将从此文件生成。仅接受 yaml 格式的配置内容。" + msgid "Geodata Update" msgstr "更新数据库" -msgid "Update GeoIP & GeoSite dat" +msgid "Update GeoIP & GeoSite databases" msgstr "更新广告规则、GeoIP & GeoSite 数据库" +msgid "Automatically update GeoIP and GeoSite databases as well as ad filtering rules through scheduled tasks." +msgstr "通过定时任务自动更新 GeoIP 和 GeoSite 数据库以及广告过滤规则。" + msgid "Update Time" msgstr "更新时间" @@ -133,15 +149,15 @@ msgstr "通过 GitHub 代理更新数据文件,留空则禁用代理下载。" msgid "Database Update" msgstr "数据库更新" +msgid "Check And Update GeoData." +msgstr "检查并更新 GeoData 数据库。" + msgid "Check And Update" msgstr "检查并更新" msgid "Enable Auto Database Update" msgstr "启用自动更新" -msgid "Updating..." -msgstr "正在更新..." - msgid "Update success" msgstr "更新成功" @@ -202,6 +218,12 @@ msgstr "阿里云公共 DNS(223.5.5.5)" msgid "Aliyun Public DNS (223.6.6.6)" msgstr "阿里云公共 DNS(223.6.6.6)" +msgid "TrafficRoute Public DNS (180.184.1.1)" +msgstr "火山引擎公共 DNS(180.184.1.1)" + +msgid "TrafficRoute Public DNS (180.184.2.2)" +msgstr "火山引擎公共 DNS(180.184.2.2)" + msgid "Xinfeng Public DNS (114.114.114.114)" msgstr "信风公共 DNS(114.114.114.114)" @@ -334,52 +356,67 @@ msgstr "日志" msgid "Clear logs" msgstr "清空日志" -msgid "Rule List" +msgid "Log Data" +msgstr "日志数据" + +msgid "No log data." +msgstr "无日志数据。" + +msgid "Refresh every %s seconds." +msgstr "每 %s 秒刷新。" + +msgid "Rules" msgstr "规则列表" msgid "Rule Settings" msgstr "自定义规则列表" -msgid "
The list of rules only apply to 'Default Config' profiles." -msgstr "
规则列表仅适用于 “内置预设” 配置文件" +msgid "Rules have been saved." +msgstr "规则已保存" + +msgid "Unable to save contents: %s" +msgstr "无法保存内容:%s" + +msgid "The list of rules only apply to 'Default Config' profiles." +msgstr "规则列表仅适用于 “内置预设” 配置文件。" msgid "White Lists" msgstr "白名单" -msgid "These domain names allow DNS resolution with the highest priority. Please input the domain names of websites, every line can input only one website domain. For example: hm.baidu.com." +msgid "Added domain names always permit resolution using 'local DNS' with the highest priority (one domain per line, supports domain matching rules)." msgstr "加入的域名始终允许使用 “本地 DNS” 进行解析,且优先级最高(每个域名一行,支持域名匹配规则)" msgid "Block Lists" msgstr "黑名单" -msgid "These domains are blocked from DNS resolution. Please input the domain names of websites, every line can input only one website domain. For example: baidu.com." +msgid "Added domain names will block DNS resolution (one domain per line, supports domain matching rules)." msgstr "加入的域名将屏蔽 DNS 解析(每个域名一行,支持域名匹配规则)" msgid "Grey Lists" msgstr "灰名单" -msgid "These domains are always resolved using remote DNS. Please input the domain names of websites, every line can input only one website domain. For example: google.com." +msgid "Added domain names will always use 'Remote DNS' for resolution (one domain per line, supports domain matching rules)." msgstr "加入的域名始终使用 “远程 DNS” 进行解析(每个域名一行,支持域名匹配规则)" msgid "DDNS Lists" msgstr "DDNS 域名" -msgid "These domains are always resolved using local DNS. And force TTL 5 seconds, DNS resolution results will not enter the cache. For example: myddns.example.com." +msgid "Added domain names will always use 'Local DNS' for resolution, with a forced TTL of 5 seconds, and results will not be cached (one domain per line, supports domain matching rules)." msgstr "加入的域名始终使用 “本地 DNS” 进行解析,并且强制 TTL 5 秒,解析结果不会进入缓存(每个域名一行,支持域名匹配规则)" -msgid "Hosts For example: baidu.com 10.0.0.1" +msgid "Custom Hosts rewrite, for example: baidu.com 10.0.0.1 (one rule per line, supports domain matching rules)." msgstr "自定义 Hosts 重写,如:baidu.com 10.0.0.1(每个规则一行,支持域名匹配规则)" msgid "Redirect" msgstr "重定向" -msgid "The domain name to redirect the request to. Requests domain A, but returns records for domain B. example: a.com b.com" +msgid "Redirecting requests for domain names. Request domain A, but return records for domain B, for example: baidu.com qq.com (one rule per line)." msgstr "重定向请求的域名。请求域名 A,但返回域名 B 的记录,如:baidu.com qq.com(每个规则一行)" msgid "Block PTR" msgstr "PTR 黑名单" -msgid "These domains are blocked from PTR requests" +msgid "Added domain names will block PTR requests (one domain per line, supports domain matching rules)." msgstr "加入的域名将阻止 PTR 请求(每个域名一行,支持域名匹配规则)" msgid "GeoData Export" @@ -412,5 +449,5 @@ msgstr "自定义 Netflix、Disney+、Hulu 以及 “流媒体” 规则列表 msgid "Streaming Media" msgstr "流媒体" -msgid "These domains are always resolved using Streaming Media DNS. Please input the domain names of websites, every line can input only one website domain. For example: netflix.com." +msgid "When enabling 'Custom Stream Media DNS', added domains will always use the 'Streaming Media DNS server' for resolution (one domain per line, supports domain matching rules)." msgstr "启用 “自定义流媒体 DNS” 时,加入的域名始终使用 “流媒体 DNS 服务器” 进行解析(每个域名一行,支持域名匹配规则)" diff --git a/luci-app-mosdns/root/etc/config/mosdns b/luci-app-mosdns/root/etc/config/mosdns index 11e2e843e..b14dc97b0 100644 --- a/luci-app-mosdns/root/etc/config/mosdns +++ b/luci-app-mosdns/root/etc/config/mosdns @@ -5,25 +5,25 @@ config mosdns 'config' option geo_auto_update '0' option geo_update_week_time '*' option geo_update_day_time '2' - option redirect '1' - option prefer_ipv4 '1' - option adblock '0' option configfile '/var/etc/mosdns.json' option log_level 'info' option log_file '/var/log/mosdns.log' - option cache '0' - option concurrent '1' + option cache '1' + option concurrent '2' option idle_timeout '30' option minimal_ttl '0' option maximum_ttl '0' - option custom_local_dns '0' - option enable_pipeline '0' + option enable_pipeline '1' option insecure_skip_verify '0' option dns_leak '0' option cloudflare '0' option listen_port_api '9091' - option custom_stream_media_dns '0' option bootstrap_dns '119.29.29.29' list remote_dns 'tls://8.8.8.8' - list remote_dns 'tls://1.1.1.1' + option redirect '1' + option prefer_ipv4 '1' + option enable_ecs_remote '0' + option cache_size '8000' + option lazy_cache_ttl '86400' + option dump_file '0' diff --git a/luci-app-mosdns/root/etc/mosdns/rule/blocklist.txt b/luci-app-mosdns/root/etc/mosdns/rule/blocklist.txt index e69de29bb..9a286f45e 100644 --- a/luci-app-mosdns/root/etc/mosdns/rule/blocklist.txt +++ b/luci-app-mosdns/root/etc/mosdns/rule/blocklist.txt @@ -0,0 +1,2 @@ +# MosDNS Rules + diff --git a/luci-app-mosdns/root/etc/mosdns/rule/ddnslist.txt b/luci-app-mosdns/root/etc/mosdns/rule/ddnslist.txt index e69de29bb..9a286f45e 100644 --- a/luci-app-mosdns/root/etc/mosdns/rule/ddnslist.txt +++ b/luci-app-mosdns/root/etc/mosdns/rule/ddnslist.txt @@ -0,0 +1,2 @@ +# MosDNS Rules + diff --git a/luci-app-mosdns/root/etc/mosdns/rule/greylist.txt b/luci-app-mosdns/root/etc/mosdns/rule/greylist.txt index e69de29bb..9a286f45e 100644 --- a/luci-app-mosdns/root/etc/mosdns/rule/greylist.txt +++ b/luci-app-mosdns/root/etc/mosdns/rule/greylist.txt @@ -0,0 +1,2 @@ +# MosDNS Rules + diff --git a/luci-app-mosdns/root/etc/mosdns/rule/hosts.txt b/luci-app-mosdns/root/etc/mosdns/rule/hosts.txt index e69de29bb..9a286f45e 100644 --- a/luci-app-mosdns/root/etc/mosdns/rule/hosts.txt +++ b/luci-app-mosdns/root/etc/mosdns/rule/hosts.txt @@ -0,0 +1,2 @@ +# MosDNS Rules + diff --git a/luci-app-mosdns/root/etc/mosdns/rule/redirect.txt b/luci-app-mosdns/root/etc/mosdns/rule/redirect.txt index e69de29bb..9a286f45e 100644 --- a/luci-app-mosdns/root/etc/mosdns/rule/redirect.txt +++ b/luci-app-mosdns/root/etc/mosdns/rule/redirect.txt @@ -0,0 +1,2 @@ +# MosDNS Rules + diff --git a/luci-app-mosdns/root/etc/mosdns/rule/streaming.txt b/luci-app-mosdns/root/etc/mosdns/rule/streaming.txt index e69de29bb..9a286f45e 100644 --- a/luci-app-mosdns/root/etc/mosdns/rule/streaming.txt +++ b/luci-app-mosdns/root/etc/mosdns/rule/streaming.txt @@ -0,0 +1,2 @@ +# MosDNS Rules + diff --git a/luci-app-mosdns/root/etc/mosdns/rule/whitelist.txt b/luci-app-mosdns/root/etc/mosdns/rule/whitelist.txt index 984708762..9a286f45e 100644 --- a/luci-app-mosdns/root/etc/mosdns/rule/whitelist.txt +++ b/luci-app-mosdns/root/etc/mosdns/rule/whitelist.txt @@ -1,11 +1,2 @@ -domain:bing.com -domain:live.com -domain:msn.com -domain:ntp.org -domain:office.com -domain:qlogo.cn -domain:qq.com -domain:redhat.com -keyword:douyin -keyword:microsoft -keyword:windows +# MosDNS Rules + diff --git a/luci-app-mosdns/root/usr/share/luci/menu.d/luci-app-mosdns.json b/luci-app-mosdns/root/usr/share/luci/menu.d/luci-app-mosdns.json new file mode 100644 index 000000000..d62a96e9a --- /dev/null +++ b/luci-app-mosdns/root/usr/share/luci/menu.d/luci-app-mosdns.json @@ -0,0 +1,45 @@ +{ + "admin/services/mosdns": { + "title": "MosDNS", + "order": 30, + "action": { + "type": "firstchild" + }, + "depends": { + "acl": [ "luci-app-mosdns" ], + "uci": { "mosdns": true } + } + }, + "admin/services/mosdns/basic": { + "title": "Basic Setting", + "order": 10, + "action": { + "type": "view", + "path": "mosdns/basic" + } + }, + "admin/services/mosdns/rules": { + "title": "Rules", + "order": 15, + "action": { + "type": "view", + "path": "mosdns/rules" + } + }, + "admin/services/mosdns/update": { + "title": "Geodata Update", + "order": 20, + "action": { + "type": "view", + "path": "mosdns/update" + } + }, + "admin/services/mosdns/logs": { + "title": "Logs", + "order": 25, + "action": { + "type": "view", + "path": "mosdns/logs" + } + } +} diff --git a/luci-app-mosdns/root/usr/share/mosdns/mosdns.sh b/luci-app-mosdns/root/usr/share/mosdns/mosdns.sh index 32eaf55c1..4f1667d55 100755 --- a/luci-app-mosdns/root/usr/share/mosdns/mosdns.sh +++ b/luci-app-mosdns/root/usr/share/mosdns/mosdns.sh @@ -2,7 +2,7 @@ script_action=${1} -logfile_path() ( +logfile_path() { configfile=$(uci -q get mosdns.config.configfile) if [ "$configfile" = "/var/etc/mosdns.json" ]; then uci -q get mosdns.config.log_file @@ -10,7 +10,15 @@ logfile_path() ( [ ! -f /etc/mosdns/config_custom.yaml ] && exit 1 awk '/^log:/{f=1;next}f==1{if($0~/file:/){print;exit}if($0~/^[^ ]/)exit}' /etc/mosdns/config_custom.yaml | grep -Eo "/[^'\"]+" fi -) +} + +print_logfile() { + cat $(logfile_path); +} + +clean_logfile() { + true > $(logfile_path); +} interface_dns() ( if [ "$(uci -q get mosdns.config.custom_local_dns)" = 1 ]; then @@ -76,12 +84,12 @@ adlist_update() { else mirror="" fi - echo -e "\e[1;32mDownloading $mirror$url\e[0m" + echo -e "Downloading $mirror$url" curl --connect-timeout 5 -m 90 --ipv4 -kfSLo "$AD_TMPDIR/$filename" "$mirror$url" fi done if [ $? -ne 0 ]; then - echo -e "\e[1;31mRules download failed.\e[0m" + echo -e "\e[1;31mRules download failed." rm -rf "$AD_TMPDIR" "$lock_file" exit 1 else @@ -98,29 +106,29 @@ geodat_update() ( TMPDIR=$(mktemp -d) || exit 1 [ -n "$(uci -q get mosdns.config.github_proxy)" ] && mirror="$(uci -q get mosdns.config.github_proxy)/" # geoip.dat - cn-private - echo -e "\e[1;32mDownloading "$mirror"https://github.com/Loyalsoldier/geoip/releases/latest/download/geoip-only-cn-private.dat\e[0m" + echo -e "Downloading "$mirror"https://github.com/Loyalsoldier/geoip/releases/latest/download/geoip-only-cn-private.dat" curl --connect-timeout 5 -m 60 --ipv4 -kfSLo "$TMPDIR/geoip.dat" ""$mirror"https://github.com/Loyalsoldier/geoip/releases/latest/download/geoip-only-cn-private.dat" [ $? -ne 0 ] && rm -rf "$TMPDIR" && exit 1 # checksum - geoip.dat - echo -e "\e[1;32mDownloading "$mirror"https://github.com/Loyalsoldier/geoip/releases/latest/download/geoip-only-cn-private.dat.sha256sum\e[0m" + echo -e "Downloading "$mirror"https://github.com/Loyalsoldier/geoip/releases/latest/download/geoip-only-cn-private.dat.sha256sum" curl --connect-timeout 5 -m 10 --ipv4 -kfSLo "$TMPDIR/geoip.dat.sha256sum" ""$mirror"https://github.com/Loyalsoldier/geoip/releases/latest/download/geoip-only-cn-private.dat.sha256sum" [ $? -ne 0 ] && rm -rf "$TMPDIR" && exit 1 if [ "$(sha256sum "$TMPDIR/geoip.dat" | awk '{print $1}')" != "$(cat "$TMPDIR/geoip.dat.sha256sum" | awk '{print $1}')" ]; then - echo -e "\e[1;31mgeoip.dat checksum error\e[0m" + echo -e "\e[1;31mgeoip.dat checksum error" rm -rf "$TMPDIR" exit 1 fi # geosite.dat - echo -e "\e[1;32mDownloading "$mirror"https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat\e[0m" + echo -e "Downloading "$mirror"https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat" curl --connect-timeout 5 -m 120 --ipv4 -kfSLo "$TMPDIR/geosite.dat" ""$mirror"https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat" [ $? -ne 0 ] && rm -rf "$TMPDIR" && exit 1 # checksum - geosite.dat - echo -e "\e[1;32mDownloading "$mirror"https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat.sha256sum\e[0m" + echo -e "Downloading "$mirror"https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat.sha256sum" curl --connect-timeout 5 -m 10 --ipv4 -kfSLo "$TMPDIR/geosite.dat.sha256sum" ""$mirror"https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat.sha256sum" [ $? -ne 0 ] && rm -rf "$TMPDIR" && exit 1 if [ "$(sha256sum "$TMPDIR/geosite.dat" | awk '{print $1}')" != "$(cat "$TMPDIR/geosite.dat.sha256sum" | awk '{print $1}')" ]; then - echo -e "\e[1;31mgeosite.dat checksum error\e[0m" + echo -e "\e[1;31mgeosite.dat checksum error" rm -rf "$TMPDIR" exit 1 fi @@ -150,8 +158,8 @@ v2dat_dump() { # default config v2dat unpack geoip -o /var/mosdns -f cn $v2dat_dir/geoip.dat v2dat unpack geosite -o /var/mosdns -f cn -f apple -f 'geolocation-!cn' $v2dat_dir/geosite.dat - [ "$adblock" -eq 1 ] && [ $(echo $ad_source | grep -c geosite.dat) -ge '1' ] && v2dat unpack geosite -o /var/mosdns -f category-ads-all $v2dat_dir/geosite.dat - [ "$streaming_media" -eq 1 ] && v2dat unpack geosite -o /var/mosdns -f netflix -f disney -f hulu $v2dat_dir/geosite.dat || \ + [ "$adblock" = 1 ] && [ $(echo $ad_source | grep -c geosite.dat) -ge '1' ] && v2dat unpack geosite -o /var/mosdns -f category-ads-all $v2dat_dir/geosite.dat + [ "$streaming_media" = 1 ] && v2dat unpack geosite -o /var/mosdns -f netflix -f disney -f hulu $v2dat_dir/geosite.dat || \ touch /var/mosdns/geosite_disney.txt ; touch /var/mosdns/geosite_netflix.txt ; touch /var/mosdns/geosite_hulu.txt else # custom config @@ -186,6 +194,12 @@ case $script_action in "v2dat_dump") v2dat_dump ;; + "printlog") + print_logfile + ;; + "cleanlog") + clean_logfile + ;; "version") mosdns version ;; diff --git a/luci-app-mosdns/root/usr/share/rpcd/acl.d/luci-app-mosdns.json b/luci-app-mosdns/root/usr/share/rpcd/acl.d/luci-app-mosdns.json index 6c79e3307..e0e94a23e 100644 --- a/luci-app-mosdns/root/usr/share/rpcd/acl.d/luci-app-mosdns.json +++ b/luci-app-mosdns/root/usr/share/rpcd/acl.d/luci-app-mosdns.json @@ -2,10 +2,44 @@ "luci-app-mosdns": { "description": "Grant UCI access for luci-app-mosdns", "read": { + "file": { + "/etc/init.d/mosdns": [ "exec" ], + "/etc/mosdns/config_custom.yaml": [ "read" ], + "/etc/mosdns/rule/blocklist.txt": [ "read" ], + "/etc/mosdns/rule/cloudflare-cidr.txt": [ "read" ], + "/etc/mosdns/rule/ddnslist.txt": [ "read" ], + "/etc/mosdns/rule/greylist.txt": [ "read" ], + "/etc/mosdns/rule/hosts.txt": [ "read" ], + "/etc/mosdns/rule/local-ptr.txt": [ "read" ], + "/etc/mosdns/rule/redirect.txt": [ "read" ], + "/etc/mosdns/rule/streaming.txt": [ "read" ], + "/etc/mosdns/rule/whitelist.txt": [ "read" ], + "/usr/share/mosdns/mosdns.sh": [ "exec" ] + }, + "ubus": { + "file": [ "read" ], + "luci": [ "getConntrackHelpers" ] + }, "uci": [ "mosdns" ] }, "write": { + "file": { + "/etc/mosdns/config_custom.yaml": [ "write" ], + "/etc/mosdns/rule/blocklist.txt": [ "write" ], + "/etc/mosdns/rule/cloudflare-cidr.txt": [ "write" ], + "/etc/mosdns/rule/ddnslist.txt": [ "write" ], + "/etc/mosdns/rule/greylist.txt": [ "write" ], + "/etc/mosdns/rule/hosts.txt": [ "write" ], + "/etc/mosdns/rule/local-ptr.txt": [ "write" ], + "/etc/mosdns/rule/redirect.txt": [ "write" ], + "/etc/mosdns/rule/streaming.txt": [ "write" ], + "/etc/mosdns/rule/whitelist.txt": [ "write" ] + }, + "ubus": { + "file": [ "write" ] + }, "uci": [ "mosdns" ] } } } + diff --git a/luci-app-mosdns/root/www/luci-static/resources/mosdns/addon/fold/foldcode.js b/luci-app-mosdns/root/www/luci-static/resources/mosdns/addon/fold/foldcode.js deleted file mode 100644 index f93d42b7f..000000000 --- a/luci-app-mosdns/root/www/luci-static/resources/mosdns/addon/fold/foldcode.js +++ /dev/null @@ -1 +0,0 @@ -!function(n){"object"==typeof exports&&"object"==typeof module?n(require("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],n):n(CodeMirror)}(function(n){"use strict";function e(e,o,i,t){if(i&&i.call){var l=i;i=null}else l=r(e,i,"rangeFinder");"number"==typeof o&&(o=n.Pos(o,0));var f=r(e,i,"minFoldSize");function d(n){var r=l(e,o);if(!r||r.to.line-r.from.linee.firstLine();)o=n.Pos(o.line-1,0),u=d(!1);if(u&&!u.cleared&&"unfold"!==t){var a=function(n,e){var o=r(n,e,"widget");if("string"==typeof o){var i=document.createTextNode(o);(o=document.createElement("span")).appendChild(i),o.className="CodeMirror-foldmarker"}else o&&(o=o.cloneNode(!0));return o}(e,i);n.on(a,"mousedown",function(e){c.clear(),n.e_preventDefault(e)});var c=e.markText(u.from,u.to,{replacedWith:a,clearOnEnter:r(e,i,"clearOnEnter"),__isFold:!0});c.on("clear",function(o,r){n.signal(e,"unfold",e,o,r)}),n.signal(e,"fold",e,u.from,u.to)}}n.newFoldFunction=function(n,o){return function(r,i){e(r,i,{rangeFinder:n,widget:o})}},n.defineExtension("foldCode",function(n,o,r){e(this,n,o,r)}),n.defineExtension("isFolded",function(n){for(var e=this.findMarksAt(n),o=0;o=u){if(s&&f&&s.test(f.className))return;i=r(a.indicatorOpen)}}(i||f)&&t.setGutterMarker(n,a.gutter,i)})}function i(t){return new RegExp("(^|\\s)"+t+"(?:$|\\s)\\s*")}function f(t){var o=t.getViewport(),e=t.state.foldGutter;e&&(t.operation(function(){n(t,o.from,o.to)}),e.from=o.from,e.to=o.to)}function a(t,r,n){var i=t.state.foldGutter;if(i){var f=i.options;if(n==f.gutter){var a=e(t,r);a?a.clear():t.foldCode(o(r,0),f)}}}function d(t){var o=t.state.foldGutter;if(o){var e=o.options;o.from=o.to=0,clearTimeout(o.changeUpdate),o.changeUpdate=setTimeout(function(){f(t)},e.foldOnChangeTimeSpan||600)}}function u(t){var o=t.state.foldGutter;if(o){var e=o.options;clearTimeout(o.changeUpdate),o.changeUpdate=setTimeout(function(){var e=t.getViewport();o.from==o.to||e.from-o.to>20||o.from-e.to>20?f(t):t.operation(function(){e.fromo.to&&(n(t,o.to,e.to),o.to=e.to)})},e.updateViewportTimeSpan||400)}}function l(t,o){var e=t.state.foldGutter;if(e){var r=o.line;r>=e.from&&ro))break;r=l}}return r?{from:e.Pos(i.line,t.getLine(i.line).length),to:e.Pos(r,t.getLine(r).length)}:void 0}})}); \ No newline at end of file diff --git a/luci-app-mosdns/root/www/luci-static/resources/mosdns/lib/codemirror.css b/luci-app-mosdns/root/www/luci-static/resources/mosdns/lib/codemirror.css deleted file mode 100644 index 504079b44..000000000 --- a/luci-app-mosdns/root/www/luci-static/resources/mosdns/lib/codemirror.css +++ /dev/null @@ -1 +0,0 @@ -.CodeMirror{/* Set height, width, borders, and global font properties here */ font-family: monospace; height: 500px; color: black; direction: ltr;}@media screen and (max-width: 768px){.CodeMirror{/* Set height, width, borders, and global font properties here */ font-size: small; font-family: monospace; height: 560px; width: 100%; color: black; direction: ltr;}}@media (min-width: 769px){.CodeMirror{/* Set height, width, borders, and global font properties here */ font-size: small; font-family: monospace; height: 560px; width: 750px; color: black; direction: ltr;}}.CodeMirror-lines{padding: 4px 0}.CodeMirror pre.CodeMirror-line,.CodeMirror pre.CodeMirror-line-like{padding: 0 4px}.CodeMirror-scrollbar-filler,.CodeMirror-gutter-filler{background-color: white}.CodeMirror-gutters{border-right: 1px solid #ddd; background-color: #f7f7f7; white-space: nowrap}.CodeMirror-linenumber{padding: 0 3px 0 5px; min-width: 20px; text-align: right; color: #999; white-space: nowrap}.CodeMirror-guttermarker{color: black}.CodeMirror-guttermarker-subtle{color: #999}.CodeMirror-cursor{border-left: 1px solid black; border-right: 0; width: 0}.CodeMirror div.CodeMirror-secondarycursor{border-left: 1px solid silver}.cm-fat-cursor .CodeMirror-cursor{width: auto; border: 0 !important; background: #7e7}.cm-fat-cursor div.CodeMirror-cursors{z-index: 1}.cm-fat-cursor-mark{background-color: rgba(20, 255, 20, 0.5); -webkit-animation: blink 1.06s steps(1) infinite; -moz-animation: blink 1.06s steps(1) infinite; animation: blink 1.06s steps(1) infinite}.cm-animate-fat-cursor{width: auto; border: 0; -webkit-animation: blink 1.06s steps(1) infinite; -moz-animation: blink 1.06s steps(1) infinite; animation: blink 1.06s steps(1) infinite; background-color: #7e7}@-moz-keyframes blink{50%{background-color: transparent}}@-webkit-keyframes blink{50%{background-color: transparent}}@keyframes blink{50%{background-color: transparent}}.cm-tab{display: inline-block; text-decoration: inherit}.CodeMirror-rulers{position: absolute; left: 0; right: 0; top: -50px; bottom: 0; overflow: hidden}.CodeMirror-ruler{border-left: 1px solid #ccc; top: 0; bottom: 0; position: absolute}.cm-s-default .cm-header{color: blue}.cm-s-default .cm-quote{color: #090}.cm-negative{color: #d44}.cm-positive{color: #292}.cm-header,.cm-strong{font-weight: bold}.cm-em{font-style: italic}.cm-link{text-decoration: underline}.cm-strikethrough{text-decoration: line-through}.cm-s-default .cm-keyword{color: #708}.cm-s-default .cm-atom{color: #219}.cm-s-default .cm-number{color: #164}.cm-s-default .cm-def{color: #00f}.cm-s-default .cm-variable-2{color: #05a}.cm-s-default .cm-variable-3,.cm-s-default .cm-type{color: #085}.cm-s-default .cm-comment{color: #a50}.cm-s-default .cm-string{color: #a11}.cm-s-default .cm-string-2{color: #f50}.cm-s-default .cm-meta{color: #555}.cm-s-default .cm-qualifier{color: #555}.cm-s-default .cm-builtin{color: #30a}.cm-s-default .cm-bracket{color: #997}.cm-s-default .cm-tag{color: #170}.cm-s-default .cm-attribute{color: #00c}.cm-s-default .cm-hr{color: #999}.cm-s-default .cm-link{color: #00c}.cm-s-default .cm-error{color: red}.cm-invalidchar{color: red}.CodeMirror-composing{border-bottom: 2px solid}div.CodeMirror span.CodeMirror-matchingbracket{color: #0b0}div.CodeMirror span.CodeMirror-nonmatchingbracket{color: #a22}.CodeMirror-matchingtag{background: rgba(255, 150, 0, .3)}.CodeMirror-activeline-background{background: #e8f2ff}.CodeMirror{position: relative; overflow: hidden; background: white}.CodeMirror-scroll{overflow: scroll !important; margin-bottom: -30px; margin-right: -30px; padding-bottom: 30px; height: 100%; outline: 0; position: relative}.CodeMirror-sizer{position: relative; border-right: 30px solid transparent}.CodeMirror-vscrollbar,.CodeMirror-hscrollbar,.CodeMirror-scrollbar-filler,.CodeMirror-gutter-filler{position: absolute; z-index: 6; display: none}.CodeMirror-vscrollbar{right: 0; top: 0; overflow-x: hidden; overflow-y: scroll}.CodeMirror-hscrollbar{bottom: 0; left: 0; overflow-y: hidden; overflow-x: scroll}.CodeMirror-scrollbar-filler{right: 0; bottom: 0}.CodeMirror-gutter-filler{left: 0; bottom: 0}.CodeMirror-gutters{position: absolute; left: 0; top: 0; min-height: 100%; z-index: 3}.CodeMirror-gutter{white-space: normal; height: 100%; display: inline-block; vertical-align: top; margin-bottom: -30px}.CodeMirror-gutter-wrapper{position: absolute; z-index: 4; background: none !important; border: none !important}.CodeMirror-gutter-background{position: absolute; top: 0; bottom: 0; z-index: 4}.CodeMirror-gutter-elt{position: absolute; cursor: default; z-index: 4}.CodeMirror-gutter-wrapper ::selection{background-color: transparent}.CodeMirror-gutter-wrapper ::-moz-selection{background-color: transparent}.CodeMirror-lines{cursor: text; min-height: 1px}.CodeMirror pre.CodeMirror-line,.CodeMirror pre.CodeMirror-line-like{-moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0; border-width: 0; background: transparent; font-family: inherit; font-size: inherit; margin: 0; white-space: pre; word-wrap: normal; line-height: inherit; color: inherit; z-index: 2; position: relative; overflow: visible; -webkit-tap-highlight-color: transparent; -webkit-font-variant-ligatures: contextual; font-variant-ligatures: contextual}.CodeMirror-wrap pre.CodeMirror-line,.CodeMirror-wrap pre.CodeMirror-line-like{word-wrap: break-word; white-space: pre-wrap; word-break: normal}.CodeMirror-linebackground{position: absolute; left: 0; right: 0; top: 0; bottom: 0; z-index: 0}.CodeMirror-linewidget{position: relative; z-index: 2; padding: .1px}.CodeMirror-rtl pre{direction: rtl}.CodeMirror-code{outline: 0}.CodeMirror-scroll,.CodeMirror-sizer,.CodeMirror-gutter,.CodeMirror-gutters,.CodeMirror-linenumber{-moz-box-sizing: content-box; box-sizing: content-box}.CodeMirror-measure{position: absolute; width: 100%; height: 0; overflow: hidden; visibility: hidden}.CodeMirror-cursor{position: absolute; pointer-events: none}.CodeMirror-measure pre{position: static}div.CodeMirror-cursors{visibility: hidden; position: relative; z-index: 3}div.CodeMirror-dragcursors{visibility: visible}.CodeMirror-focused div.CodeMirror-cursors{visibility: visible}.CodeMirror-selected{background: #d9d9d9}.CodeMirror-focused .CodeMirror-selected{background: #d7d4f0}.CodeMirror-crosshair{cursor: crosshair}.CodeMirror-line::selection,.CodeMirror-line>span::selection,.CodeMirror-line>span>span::selection{background: #d7d4f0}.CodeMirror-line::-moz-selection,.CodeMirror-line>span::-moz-selection,.CodeMirror-line>span>span::-moz-selection{background: #d7d4f0}.cm-searching{background-color: #ffa; background-color: rgba(255, 255, 0, .4)}.cm-force-border{padding-right: .1px}@media print{.CodeMirror div.CodeMirror-cursors{visibility: hidden}}.cm-tab-wrap-hack:after{content: ''}span.CodeMirror-selectedtext{background: 0} \ No newline at end of file diff --git a/luci-app-mosdns/root/www/luci-static/resources/mosdns/lib/codemirror.js b/luci-app-mosdns/root/www/luci-static/resources/mosdns/lib/codemirror.js deleted file mode 100644 index d01f072ee..000000000 --- a/luci-app-mosdns/root/www/luci-static/resources/mosdns/lib/codemirror.js +++ /dev/null @@ -1 +0,0 @@ -!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.CodeMirror=t()}(this,function(){"use strict";var e=navigator.userAgent,t=navigator.platform,r=/gecko\/\d/i.test(e),n=/MSIE \d/.test(e),i=/Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(e),o=/Edge\/(\d+)/.exec(e),l=n||i||o,s=l&&(n?document.documentMode||6:+(o||i)[1]),a=!o&&/WebKit\//.test(e),u=a&&/Qt\/\d+\.\d+/.test(e),c=!o&&/Chrome\//.test(e),h=/Opera\//.test(e),f=/Apple Computer/.test(navigator.vendor),d=/Mac OS X 1\d\D([8-9]|\d\d)\D/.test(e),p=/PhantomJS/.test(e),g=!o&&/AppleWebKit/.test(e)&&/Mobile\/\w+/.test(e),v=/Android/.test(e),m=g||v||/webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(e),y=g||/Mac/.test(t),b=/\bCrOS\b/.test(e),w=/win/i.test(t),x=h&&e.match(/Version\/(\d*\.\d*)/);x&&(x=Number(x[1])),x&&x>=15&&(h=!1,a=!0);var C=y&&(u||h&&(null==x||x<12.11)),S=r||l&&s>=9;function L(e){return new RegExp("(^|\\s)"+e+"(?:$|\\s)\\s*")}var k,T=function(e,t){var r=e.className,n=L(t).exec(r);if(n){var i=r.slice(n.index+n[0].length);e.className=r.slice(0,n.index)+(i?n[1]+i:"")}};function M(e){for(var t=e.childNodes.length;t>0;--t)e.removeChild(e.firstChild);return e}function N(e,t){return M(e).appendChild(t)}function O(e,t,r,n){var i=document.createElement(e);if(r&&(i.className=r),n&&(i.style.cssText=n),"string"==typeof t)i.appendChild(document.createTextNode(t));else if(t)for(var o=0;o=t)return l+(t-o);l+=s-o,l+=r-l%r,o=s+1}}g?P=function(e){e.selectionStart=0,e.selectionEnd=e.value.length}:l&&(P=function(e){try{e.select()}catch(e){}});var R=function(){this.id=null,this.f=null,this.time=0,this.handler=E(this.onTimeout,this)};function B(e,t){for(var r=0;r=t)return n+Math.min(l,t-i);if(i+=o-n,n=o+1,(i+=r-i%r)>=t)return n}}var Y=[""];function _(e){for(;Y.length<=e;)Y.push($(Y)+" ");return Y[e]}function $(e){return e[e.length-1]}function q(e,t){for(var r=[],n=0;n"€"&&(e.toUpperCase()!=e.toLowerCase()||J.test(e))}function te(e,t){return t?!!(t.source.indexOf("\\w")>-1&&ee(e))||t.test(e):ee(e)}function re(e){for(var t in e)if(e.hasOwnProperty(t)&&e[t])return!1;return!0}var ne=/[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/;function ie(e){return e.charCodeAt(0)>=768&&ne.test(e)}function oe(e,t,r){for(;(r<0?t>0:tr?-1:1;;){if(t==r)return t;var i=(t+r)/2,o=n<0?Math.ceil(i):Math.floor(i);if(o==t)return e(o)?t:r;e(o)?r=o:t=o+n}}var se=null;function ae(e,t,r){var n;se=null;for(var i=0;it)return i;o.to==t&&(o.from!=o.to&&"before"==r?n=i:se=i),o.from==t&&(o.from!=o.to&&"before"!=r?n=i:se=i)}return null!=n?n:se}var ue=function(){var e="bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN",t="nnnnnnNNr%%r,rNNmmmmmmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmmmnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmnNmmmmmmrrmmNmmmmrr1111111111";var r=/[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/,n=/[stwN]/,i=/[LRr]/,o=/[Lb1n]/,l=/[1n]/;function s(e,t,r){this.level=e,this.from=t,this.to=r}return function(a,u){var c="ltr"==u?"L":"R";if(0==a.length||"ltr"==u&&!r.test(a))return!1;for(var h,f=a.length,d=[],p=0;p-1&&(n[t]=i.slice(0,o).concat(i.slice(o+1)))}}}function ge(e,t){var r=de(e,t);if(r.length)for(var n=Array.prototype.slice.call(arguments,2),i=0;i0}function be(e){e.prototype.on=function(e,t){fe(this,e,t)},e.prototype.off=function(e,t){pe(this,e,t)}}function we(e){e.preventDefault?e.preventDefault():e.returnValue=!1}function xe(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0}function Ce(e){return null!=e.defaultPrevented?e.defaultPrevented:0==e.returnValue}function Se(e){we(e),xe(e)}function Le(e){return e.target||e.srcElement}function ke(e){var t=e.which;return null==t&&(1&e.button?t=1:2&e.button?t=3:4&e.button&&(t=2)),y&&e.ctrlKey&&1==t&&(t=3),t}var Te,Me,Ne=function(){if(l&&s<9)return!1;var e=O("div");return"draggable"in e||"dragDrop"in e}();function Oe(e){if(null==Te){var t=O("span","​");N(e,O("span",[t,document.createTextNode("x")])),0!=e.firstChild.offsetHeight&&(Te=t.offsetWidth<=1&&t.offsetHeight>2&&!(l&&s<8))}var r=Te?O("span","​"):O("span"," ",null,"display: inline-block; width: 1px; margin-right: -1px");return r.setAttribute("cm-text",""),r}function Ae(e){if(null!=Me)return Me;var t=N(e,document.createTextNode("AخA")),r=k(t,0,1).getBoundingClientRect(),n=k(t,1,2).getBoundingClientRect();return M(e),!(!r||r.left==r.right)&&(Me=n.right-r.right<3)}var De,We=3!="\n\nb".split(/\n/).length?function(e){for(var t=0,r=[],n=e.length;t<=n;){var i=e.indexOf("\n",t);-1==i&&(i=e.length);var o=e.slice(t,"\r"==e.charAt(i-1)?i-1:i),l=o.indexOf("\r");-1!=l?(r.push(o.slice(0,l)),t+=l+1):(r.push(o),t=i+1)}return r}:function(e){return e.split(/\r\n?|\n/)},He=window.getSelection?function(e){try{return e.selectionStart!=e.selectionEnd}catch(e){return!1}}:function(e){var t;try{t=e.ownerDocument.selection.createRange()}catch(e){}return!(!t||t.parentElement()!=e)&&0!=t.compareEndPoints("StartToEnd",t)},Fe="oncopy"in(De=O("div"))||(De.setAttribute("oncopy","return;"),"function"==typeof De.oncopy),Pe=null;var Ee={},Ie={};function ze(e){if("string"==typeof e&&Ie.hasOwnProperty(e))e=Ie[e];else if(e&&"string"==typeof e.name&&Ie.hasOwnProperty(e.name)){var t=Ie[e.name];"string"==typeof t&&(t={name:t}),(e=Q(t,e)).name=t.name}else{if("string"==typeof e&&/^[\w\-]+\/[\w\-]+\+xml$/.test(e))return ze("application/xml");if("string"==typeof e&&/^[\w\-]+\/[\w\-]+\+json$/.test(e))return ze("application/json")}return"string"==typeof e?{name:e}:e||{name:"null"}}function Re(e,t){t=ze(t);var r=Ee[t.name];if(!r)return Re(e,"text/plain");var n=r(e,t);if(Be.hasOwnProperty(t.name)){var i=Be[t.name];for(var o in i)i.hasOwnProperty(o)&&(n.hasOwnProperty(o)&&(n["_"+o]=n[o]),n[o]=i[o])}if(n.name=t.name,t.helperType&&(n.helperType=t.helperType),t.modeProps)for(var l in t.modeProps)n[l]=t.modeProps[l];return n}var Be={};function Ge(e,t){I(t,Be.hasOwnProperty(e)?Be[e]:Be[e]={})}function Ue(e,t){if(!0===t)return t;if(e.copyState)return e.copyState(t);var r={};for(var n in t){var i=t[n];i instanceof Array&&(i=i.concat([])),r[n]=i}return r}function Ve(e,t){for(var r;e.innerMode&&(r=e.innerMode(t))&&r.mode!=e;)t=r.state,e=r.mode;return r||{mode:e,state:t}}function Ke(e,t,r){return!e.startState||e.startState(t,r)}var je=function(e,t,r){this.pos=this.start=0,this.string=e,this.tabSize=t||8,this.lastColumnPos=this.lastColumnValue=0,this.lineStart=0,this.lineOracle=r};function Xe(e,t){if((t-=e.first)<0||t>=e.size)throw new Error("There is no line "+(t+e.first)+" in the document.");for(var r=e;!r.lines;)for(var n=0;;++n){var i=r.children[n],o=i.chunkSize();if(t=e.first&&tr?et(r,Xe(e,r).text.length):function(e,t){var r=e.ch;return null==r||r>t?et(e.line,t):r<0?et(e.line,0):e}(t,Xe(e,t.line).text.length)}function at(e,t){for(var r=[],n=0;n=this.string.length},je.prototype.sol=function(){return this.pos==this.lineStart},je.prototype.peek=function(){return this.string.charAt(this.pos)||void 0},je.prototype.next=function(){if(this.post},je.prototype.eatSpace=function(){for(var e=this.pos;/[\s\u00a0]/.test(this.string.charAt(this.pos));)++this.pos;return this.pos>e},je.prototype.skipToEnd=function(){this.pos=this.string.length},je.prototype.skipTo=function(e){var t=this.string.indexOf(e,this.pos);if(t>-1)return this.pos=t,!0},je.prototype.backUp=function(e){this.pos-=e},je.prototype.column=function(){return this.lastColumnPos0?null:(n&&!1!==t&&(this.pos+=n[0].length),n)}var i=function(e){return r?e.toLowerCase():e};if(i(this.string.substr(this.pos,e.length))==i(e))return!1!==t&&(this.pos+=e.length),!0},je.prototype.current=function(){return this.string.slice(this.start,this.pos)},je.prototype.hideFirstChars=function(e,t){this.lineStart+=e;try{return t()}finally{this.lineStart-=e}},je.prototype.lookAhead=function(e){var t=this.lineOracle;return t&&t.lookAhead(e)},je.prototype.baseToken=function(){var e=this.lineOracle;return e&&e.baseToken(this.pos)};var ut=function(e,t){this.state=e,this.lookAhead=t},ct=function(e,t,r,n){this.state=t,this.doc=e,this.line=r,this.maxLookAhead=n||0,this.baseTokens=null,this.baseTokenPos=1};function ht(e,t,r,n){var i=[e.state.modeGen],o={};wt(e,t.text,e.doc.mode,r,function(e,t){return i.push(e,t)},o,n);for(var l=r.state,s=function(n){r.baseTokens=i;var s=e.state.overlays[n],a=1,u=0;r.state=!0,wt(e,t.text,s.mode,r,function(e,t){for(var r=a;ue&&i.splice(a,1,e,i[a+1],n),a+=2,u=Math.min(e,n)}if(t)if(s.opaque)i.splice(r,a-r,e,"overlay "+t),a=r+2;else for(;re.options.maxHighlightLength&&Ue(e.doc.mode,n.state),o=ht(e,t,n);i&&(n.state=i),t.stateAfter=n.save(!i),t.styles=o.styles,o.classes?t.styleClasses=o.classes:t.styleClasses&&(t.styleClasses=null),r===e.doc.highlightFrontier&&(e.doc.modeFrontier=Math.max(e.doc.modeFrontier,++e.doc.highlightFrontier))}return t.styles}function dt(e,t,r){var n=e.doc,i=e.display;if(!n.mode.startState)return new ct(n,!0,t);var o=function(e,t,r){for(var n,i,o=e.doc,l=r?-1:t-(e.doc.mode.innerMode?1e3:100),s=t;s>l;--s){if(s<=o.first)return o.first;var a=Xe(o,s-1),u=a.stateAfter;if(u&&(!r||s+(u instanceof ut?u.lookAhead:0)<=o.modeFrontier))return s;var c=z(a.text,null,e.options.tabSize);(null==i||n>c)&&(i=s-1,n=c)}return i}(e,t,r),l=o>n.first&&Xe(n,o-1).stateAfter,s=l?ct.fromSaved(n,l,o):new ct(n,Ke(n.mode),o);return n.iter(o,t,function(r){pt(e,r.text,s);var n=s.line;r.stateAfter=n==t-1||n%5==0||n>=i.viewFrom&&nt.start)return o}throw new Error("Mode "+e.name+" failed to advance stream.")}ct.prototype.lookAhead=function(e){var t=this.doc.getLine(this.line+e);return null!=t&&e>this.maxLookAhead&&(this.maxLookAhead=e),t},ct.prototype.baseToken=function(e){if(!this.baseTokens)return null;for(;this.baseTokens[this.baseTokenPos]<=e;)this.baseTokenPos+=2;var t=this.baseTokens[this.baseTokenPos+1];return{type:t&&t.replace(/( |^)overlay .*/,""),size:this.baseTokens[this.baseTokenPos]-e}},ct.prototype.nextLine=function(){this.line++,this.maxLookAhead>0&&this.maxLookAhead--},ct.fromSaved=function(e,t,r){return t instanceof ut?new ct(e,Ue(e.mode,t.state),r,t.lookAhead):new ct(e,Ue(e.mode,t),r)},ct.prototype.save=function(e){var t=!1!==e?Ue(this.doc.mode,this.state):this.state;return this.maxLookAhead>0?new ut(t,this.maxLookAhead):t};var mt=function(e,t,r){this.start=e.start,this.end=e.pos,this.string=e.current(),this.type=t||null,this.state=r};function yt(e,t,r,n){var i,o,l=e.doc,s=l.mode,a=Xe(l,(t=st(l,t)).line),u=dt(e,t.line,r),c=new je(a.text,e.options.tabSize,u);for(n&&(o=[]);(n||c.pose.options.maxHighlightLength?(s=!1,l&&pt(e,t,n,h.pos),h.pos=t.length,a=null):a=bt(vt(r,h,n.state,f),o),f){var d=f[0].name;d&&(a="m-"+(a?d+" "+a:d))}if(!s||c!=a){for(;u=t:o.to>t);(n||(n=[])).push(new St(l,o.from,s?null:o.to))}}return n}(r,i,l),a=function(e,t,r){var n;if(e)for(var i=0;i=t:o.to>t)||o.from==t&&"bookmark"==l.type&&(!r||o.marker.insertLeft)){var s=null==o.from||(l.inclusiveLeft?o.from<=t:o.from0&&s)for(var b=0;bt)&&(!r||Wt(r,o.marker)<0)&&(r=o.marker)}return r}function It(e,t,r,n,i){var o=Xe(e,t),l=Ct&&o.markedSpans;if(l)for(var s=0;s=0&&h<=0||c<=0&&h>=0)&&(c<=0&&(a.marker.inclusiveRight&&i.inclusiveLeft?tt(u.to,r)>=0:tt(u.to,r)>0)||c>=0&&(a.marker.inclusiveRight&&i.inclusiveLeft?tt(u.from,n)<=0:tt(u.from,n)<0)))return!0}}}function zt(e){for(var t;t=Ft(e);)e=t.find(-1,!0).line;return e}function Rt(e,t){var r=Xe(e,t),n=zt(r);return r==n?t:qe(n)}function Bt(e,t){if(t>e.lastLine())return t;var r,n=Xe(e,t);if(!Gt(e,n))return t;for(;r=Pt(n);)n=r.find(1,!0).line;return qe(n)+1}function Gt(e,t){var r=Ct&&t.markedSpans;if(r)for(var n=void 0,i=0;it.maxLineLength&&(t.maxLineLength=r,t.maxLine=e)})}var Xt=function(e,t,r){this.text=e,Ot(this,t),this.height=r?r(this):1};function Yt(e){e.parent=null,Nt(e)}Xt.prototype.lineNo=function(){return qe(this)},be(Xt);var _t={},$t={};function qt(e,t){if(!e||/^\s*$/.test(e))return null;var r=t.addModeClass?$t:_t;return r[e]||(r[e]=e.replace(/\S+/g,"cm-$&"))}function Zt(e,t){var r=A("span",null,null,a?"padding-right: .1px":null),n={pre:A("pre",[r],"CodeMirror-line"),content:r,col:0,pos:0,cm:e,trailingSpace:!1,splitSpaces:e.getOption("lineWrapping")};t.measure={};for(var i=0;i<=(t.rest?t.rest.length:0);i++){var o=i?t.rest[i-1]:t.line,l=void 0;n.pos=0,n.addToken=Jt,Ae(e.display.measure)&&(l=ce(o,e.doc.direction))&&(n.addToken=er(n.addToken,l)),n.map=[],rr(o,n,ft(e,o,t!=e.display.externalMeasured&&qe(o))),o.styleClasses&&(o.styleClasses.bgClass&&(n.bgClass=F(o.styleClasses.bgClass,n.bgClass||"")),o.styleClasses.textClass&&(n.textClass=F(o.styleClasses.textClass,n.textClass||""))),0==n.map.length&&n.map.push(0,0,n.content.appendChild(Oe(e.display.measure))),0==i?(t.measure.map=n.map,t.measure.cache={}):((t.measure.maps||(t.measure.maps=[])).push(n.map),(t.measure.caches||(t.measure.caches=[])).push({}))}if(a){var s=n.content.lastChild;(/\bcm-tab\b/.test(s.className)||s.querySelector&&s.querySelector(".cm-tab"))&&(n.content.className="cm-tab-wrap-hack")}return ge(e,"renderLine",e,t.line,n.pre),n.pre.className&&(n.textClass=F(n.pre.className,n.textClass||"")),n}function Qt(e){var t=O("span","•","cm-invalidchar");return t.title="\\u"+e.charCodeAt(0).toString(16),t.setAttribute("aria-label",t.title),t}function Jt(e,t,r,n,i,o,a){if(t){var u,c=e.splitSpaces?function(e,t){if(e.length>1&&!/ /.test(e))return e;for(var r=t,n="",i=0;iu&&h.from<=u);f++);if(h.to>=c)return e(r,n,i,o,l,s,a);e(r,n.slice(0,h.to-u),i,o,null,s,a),o=null,n=n.slice(h.to-u),u=h.to}}}function tr(e,t,r,n){var i=!n&&r.widgetNode;i&&e.map.push(e.pos,e.pos+t,i),!n&&e.cm.display.input.needsContentAttribute&&(i||(i=e.content.appendChild(document.createElement("span"))),i.setAttribute("cm-marker",r.id)),i&&(e.cm.display.input.setUneditable(i),e.content.appendChild(i)),e.pos+=t,e.trailingSpace=!1}function rr(e,t,r){var n=e.markedSpans,i=e.text,o=0;if(n)for(var l,s,a,u,c,h,f,d=i.length,p=0,g=1,v="",m=0;;){if(m==p){a=u=c=s="",f=null,h=null,m=1/0;for(var y=[],b=void 0,w=0;wp||C.collapsed&&x.to==p&&x.from==p)){if(null!=x.to&&x.to!=p&&m>x.to&&(m=x.to,u=""),C.className&&(a+=" "+C.className),C.css&&(s=(s?s+";":"")+C.css),C.startStyle&&x.from==p&&(c+=" "+C.startStyle),C.endStyle&&x.to==m&&(b||(b=[])).push(C.endStyle,x.to),C.title&&((f||(f={})).title=C.title),C.attributes)for(var S in C.attributes)(f||(f={}))[S]=C.attributes[S];C.collapsed&&(!h||Wt(h.marker,C)<0)&&(h=x)}else x.from>p&&m>x.from&&(m=x.from)}if(b)for(var L=0;L=d)break;for(var T=Math.min(d,m);;){if(v){var M=p+v.length;if(!h){var N=M>T?v.slice(0,T-p):v;t.addToken(t,N,l?l+a:a,c,p+N.length==m?u:"",s,f)}if(M>=T){v=v.slice(T-p),p=T;break}p=M,c=""}v=i.slice(o,o=r[g++]),l=qt(r[g++],t.cm.options)}}else for(var O=1;Or)return{map:e.measure.maps[i],cache:e.measure.caches[i],before:!0}}function Or(e,t,r,n){return Wr(e,Dr(e,t),r,n)}function Ar(e,t){if(t>=e.display.viewFrom&&t=r.lineN&&t2&&o.push((a.bottom+u.top)/2-r.top)}}o.push(r.bottom-r.top)}}(e,t.view,t.rect),t.hasHeights=!0),(o=function(e,t,r,n){var i,o=Pr(t.map,r,n),a=o.node,u=o.start,c=o.end,h=o.collapse;if(3==a.nodeType){for(var f=0;f<4;f++){for(;u&&ie(t.line.text.charAt(o.coverStart+u));)--u;for(;o.coverStart+c1}(e))return t;var r=screen.logicalXDPI/screen.deviceXDPI,n=screen.logicalYDPI/screen.deviceYDPI;return{left:t.left*r,right:t.right*r,top:t.top*n,bottom:t.bottom*n}}(e.display.measure,i))}else{var d;u>0&&(h=n="right"),i=e.options.lineWrapping&&(d=a.getClientRects()).length>1?d["right"==n?d.length-1:0]:a.getBoundingClientRect()}if(l&&s<9&&!u&&(!i||!i.left&&!i.right)){var p=a.parentNode.getClientRects()[0];i=p?{left:p.left,right:p.left+tn(e.display),top:p.top,bottom:p.bottom}:Fr}for(var g=i.top-t.rect.top,v=i.bottom-t.rect.top,m=(g+v)/2,y=t.view.measure.heights,b=0;bt)&&(i=(o=a-s)-1,t>=a&&(l="right")),null!=i){if(n=e[u+2],s==a&&r==(n.insertLeft?"left":"right")&&(l=r),"left"==r&&0==i)for(;u&&e[u-2]==e[u-3]&&e[u-1].insertLeft;)n=e[2+(u-=3)],l="left";if("right"==r&&i==a-s)for(;u=0&&(r=e[i]).left==r.right;i--);return r}function Ir(e){if(e.measure&&(e.measure.cache={},e.measure.heights=null,e.rest))for(var t=0;t=n.text.length?(a=n.text.length,u="before"):a<=0&&(a=0,u="after"),!s)return l("before"==u?a-1:a,"before"==u);function c(e,t,r){return l(r?e-1:e,1==s[t].level!=r)}var h=ae(s,a,u),f=se,d=c(a,h,"before"==u);return null!=f&&(d.other=c(a,f,"before"!=u)),d}function Yr(e,t){var r=0;t=st(e.doc,t),e.options.lineWrapping||(r=tn(e.display)*t.ch);var n=Xe(e.doc,t.line),i=Vt(n)+Cr(e.display);return{left:r,right:r,top:i,bottom:i+n.height}}function _r(e,t,r,n,i){var o=et(e,t,r);return o.xRel=i,n&&(o.outside=n),o}function $r(e,t,r){var n=e.doc;if((r+=e.display.viewOffset)<0)return _r(n.first,0,null,-1,-1);var i=Ze(n,r),o=n.first+n.size-1;if(i>o)return _r(n.first+n.size-1,Xe(n,o).text.length,null,1,1);t<0&&(t=0);for(var l=Xe(n,i);;){var s=Jr(e,l,i,t,r),a=Et(l,s.ch+(s.xRel>0||s.outside>0?1:0));if(!a)return s;var u=a.find(1);if(u.line==i)return u;l=Xe(n,i=u.line)}}function qr(e,t,r,n){n-=Ur(t);var i=t.text.length,o=le(function(t){return Wr(e,r,t-1).bottom<=n},i,0);return{begin:o,end:i=le(function(t){return Wr(e,r,t).top>n},o,i)}}function Zr(e,t,r,n){return r||(r=Dr(e,t)),qr(e,t,r,Vr(e,t,Wr(e,r,n),"line").top)}function Qr(e,t,r,n){return!(e.bottom<=r)&&(e.top>r||(n?e.left:e.right)>t)}function Jr(e,t,r,n,i){i-=Vt(t);var o=Dr(e,t),l=Ur(t),s=0,a=t.text.length,u=!0,c=ce(t,e.doc.direction);if(c){var h=(e.options.lineWrapping?function(e,t,r,n,i,o,l){var s=qr(e,t,n,l),a=s.begin,u=s.end;/\s/.test(t.text.charAt(u-1))&&u--;for(var c=null,h=null,f=0;f=u||d.to<=a)){var p=1!=d.level,g=Wr(e,n,p?Math.min(u,d.to)-1:Math.max(a,d.from)).right,v=gv)&&(c=d,h=v)}}c||(c=i[i.length-1]);c.fromu&&(c={from:c.from,to:u,level:c.level});return c}:function(e,t,r,n,i,o,l){var s=le(function(s){var a=i[s],u=1!=a.level;return Qr(Xr(e,et(r,u?a.to:a.from,u?"before":"after"),"line",t,n),o,l,!0)},0,i.length-1),a=i[s];if(s>0){var u=1!=a.level,c=Xr(e,et(r,u?a.from:a.to,u?"after":"before"),"line",t,n);Qr(c,o,l,!0)&&c.top>l&&(a=i[s-1])}return a})(e,t,r,o,c,n,i);s=(u=1!=h.level)?h.from:h.to-1,a=u?h.to:h.from-1}var f,d,p=null,g=null,v=le(function(t){var r=Wr(e,o,t);return r.top+=l,r.bottom+=l,!!Qr(r,n,i,!1)&&(r.top<=i&&r.left<=n&&(p=t,g=r),!0)},s,a),m=!1;if(g){var y=n-g.left=w.bottom?1:0}return _r(r,v=oe(t.text,v,1),d,m,n-f)}function en(e){if(null!=e.cachedTextHeight)return e.cachedTextHeight;if(null==Hr){Hr=O("pre",null,"CodeMirror-line-like");for(var t=0;t<49;++t)Hr.appendChild(document.createTextNode("x")),Hr.appendChild(O("br"));Hr.appendChild(document.createTextNode("x"))}N(e.measure,Hr);var r=Hr.offsetHeight/50;return r>3&&(e.cachedTextHeight=r),M(e.measure),r||1}function tn(e){if(null!=e.cachedCharWidth)return e.cachedCharWidth;var t=O("span","xxxxxxxxxx"),r=O("pre",[t],"CodeMirror-line-like");N(e.measure,r);var n=t.getBoundingClientRect(),i=(n.right-n.left)/10;return i>2&&(e.cachedCharWidth=i),i||10}function rn(e){for(var t=e.display,r={},n={},i=t.gutters.clientLeft,o=t.gutters.firstChild,l=0;o;o=o.nextSibling,++l){var s=e.display.gutterSpecs[l].className;r[s]=o.offsetLeft+o.clientLeft+i,n[s]=o.clientWidth}return{fixedPos:nn(t),gutterTotalWidth:t.gutters.offsetWidth,gutterLeft:r,gutterWidth:n,wrapperWidth:t.wrapper.clientWidth}}function nn(e){return e.scroller.getBoundingClientRect().left-e.sizer.getBoundingClientRect().left}function on(e){var t=en(e.display),r=e.options.lineWrapping,n=r&&Math.max(5,e.display.scroller.clientWidth/tn(e.display)-3);return function(i){if(Gt(e.doc,i))return 0;var o=0;if(i.widgets)for(var l=0;l=e.display.viewTo)return null;if((t-=e.display.viewFrom)<0)return null;for(var r=e.display.view,n=0;nt)&&(i.updateLineNumbers=t),e.curOp.viewChanged=!0,t>=i.viewTo)Ct&&Rt(e.doc,t)i.viewFrom?hn(e):(i.viewFrom+=n,i.viewTo+=n);else if(t<=i.viewFrom&&r>=i.viewTo)hn(e);else if(t<=i.viewFrom){var o=fn(e,r,r+n,1);o?(i.view=i.view.slice(o.index),i.viewFrom=o.lineN,i.viewTo+=n):hn(e)}else if(r>=i.viewTo){var l=fn(e,t,t,-1);l?(i.view=i.view.slice(0,l.index),i.viewTo=l.lineN):hn(e)}else{var s=fn(e,t,t,-1),a=fn(e,r,r+n,1);s&&a?(i.view=i.view.slice(0,s.index).concat(ir(e,s.lineN,a.lineN)).concat(i.view.slice(a.index)),i.viewTo+=n):hn(e)}var u=i.externalMeasured;u&&(r=i.lineN&&t=n.viewTo)){var o=n.view[an(e,t)];if(null!=o.node){var l=o.changes||(o.changes=[]);-1==B(l,r)&&l.push(r)}}}function hn(e){e.display.viewFrom=e.display.viewTo=e.doc.first,e.display.view=[],e.display.viewOffset=0}function fn(e,t,r,n){var i,o=an(e,t),l=e.display.view;if(!Ct||r==e.doc.first+e.doc.size)return{index:o,lineN:r};for(var s=e.display.viewFrom,a=0;a0){if(o==l.length-1)return null;i=s+l[o].size-t,o++}else i=s-t;t+=i,r+=i}for(;Rt(e.doc,r)!=r;){if(o==(n<0?0:l.length-1))return null;r+=n*l[o-(n<0?1:0)].size,o+=n}return{index:o,lineN:r}}function dn(e){for(var t=e.display.view,r=0,n=0;n=e.display.viewTo||s.to().linet||t==r&&l.to==t)&&(n(Math.max(l.from,t),Math.min(l.to,r),1==l.level?"rtl":"ltr",o),i=!0)}i||n(t,r,"ltr")}(g,r||0,null==n?f:n,function(e,t,i,h){var v="ltr"==i,m=d(e,v?"left":"right"),y=d(t-1,v?"right":"left"),b=null==r&&0==e,w=null==n&&t==f,x=0==h,C=!g||h==g.length-1;if(y.top-m.top<=3){var S=(u?w:b)&&C,L=(u?b:w)&&x?s:(v?m:y).left,k=S?a:(v?y:m).right;c(L,m.top,k-L,m.bottom)}else{var T,M,N,O;v?(T=u&&b&&x?s:m.left,M=u?a:p(e,i,"before"),N=u?s:p(t,i,"after"),O=u&&w&&C?a:y.right):(T=u?p(e,i,"before"):s,M=!u&&b&&x?a:m.right,N=!u&&w&&C?s:y.left,O=u?p(t,i,"after"):a),c(T,m.top,M-T,m.bottom),m.bottom0?t.blinker=setInterval(function(){return t.cursorDiv.style.visibility=(r=!r)?"":"hidden"},e.options.cursorBlinkRate):e.options.cursorBlinkRate<0&&(t.cursorDiv.style.visibility="hidden")}}function wn(e){e.state.focused||(e.display.input.focus(),Cn(e))}function xn(e){e.state.delayingBlurEvent=!0,setTimeout(function(){e.state.delayingBlurEvent&&(e.state.delayingBlurEvent=!1,Sn(e))},100)}function Cn(e,t){e.state.delayingBlurEvent&&(e.state.delayingBlurEvent=!1),"nocursor"!=e.options.readOnly&&(e.state.focused||(ge(e,"focus",e,t),e.state.focused=!0,H(e.display.wrapper,"CodeMirror-focused"),e.curOp||e.display.selForContextMenu==e.doc.sel||(e.display.input.reset(),a&&setTimeout(function(){return e.display.input.reset(!0)},20)),e.display.input.receivedFocus()),bn(e))}function Sn(e,t){e.state.delayingBlurEvent||(e.state.focused&&(ge(e,"blur",e,t),e.state.focused=!1,T(e.display.wrapper,"CodeMirror-focused")),clearInterval(e.display.blinker),setTimeout(function(){e.state.focused||(e.display.shift=!1)},150))}function Ln(e){for(var t=e.display,r=t.lineDiv.offsetTop,n=0;n.005||f<-.005)&&($e(i.line,a),kn(i.line),i.rest))for(var d=0;de.display.sizerWidth){var p=Math.ceil(u/tn(e.display));p>e.display.maxLineLength&&(e.display.maxLineLength=p,e.display.maxLine=i.line,e.display.maxLineChanged=!0)}}}}function kn(e){if(e.widgets)for(var t=0;t=l&&(o=Ze(t,Vt(Xe(t,a))-e.wrapper.clientHeight),l=a)}return{from:o,to:Math.max(l,o+1)}}function Mn(e,t){var r=e.display,n=en(e.display);t.top<0&&(t.top=0);var i=e.curOp&&null!=e.curOp.scrollTop?e.curOp.scrollTop:r.scroller.scrollTop,o=Mr(e),l={};t.bottom-t.top>o&&(t.bottom=t.top+o);var s=e.doc.height+Sr(r),a=t.tops-n;if(t.topi+o){var c=Math.min(t.top,(u?s:t.bottom)-o);c!=i&&(l.scrollTop=c)}var h=e.curOp&&null!=e.curOp.scrollLeft?e.curOp.scrollLeft:r.scroller.scrollLeft,f=Tr(e)-(e.options.fixedGutter?r.gutters.offsetWidth:0),d=t.right-t.left>f;return d&&(t.right=t.left+f),t.left<10?l.scrollLeft=0:t.leftf+h-3&&(l.scrollLeft=t.right+(d?0:10)-f),l}function Nn(e,t){null!=t&&(Dn(e),e.curOp.scrollTop=(null==e.curOp.scrollTop?e.doc.scrollTop:e.curOp.scrollTop)+t)}function On(e){Dn(e);var t=e.getCursor();e.curOp.scrollToPos={from:t,to:t,margin:e.options.cursorScrollMargin}}function An(e,t,r){null==t&&null==r||Dn(e),null!=t&&(e.curOp.scrollLeft=t),null!=r&&(e.curOp.scrollTop=r)}function Dn(e){var t=e.curOp.scrollToPos;t&&(e.curOp.scrollToPos=null,Wn(e,Yr(e,t.from),Yr(e,t.to),t.margin))}function Wn(e,t,r,n){var i=Mn(e,{left:Math.min(t.left,r.left),top:Math.min(t.top,r.top)-n,right:Math.max(t.right,r.right),bottom:Math.max(t.bottom,r.bottom)+n});An(e,i.scrollLeft,i.scrollTop)}function Hn(e,t){Math.abs(e.doc.scrollTop-t)<2||(r||oi(e,{top:t}),Fn(e,t,!0),r&&oi(e),ei(e,100))}function Fn(e,t,r){t=Math.min(e.display.scroller.scrollHeight-e.display.scroller.clientHeight,t),(e.display.scroller.scrollTop!=t||r)&&(e.doc.scrollTop=t,e.display.scrollbars.setScrollTop(t),e.display.scroller.scrollTop!=t&&(e.display.scroller.scrollTop=t))}function Pn(e,t,r,n){t=Math.min(t,e.display.scroller.scrollWidth-e.display.scroller.clientWidth),(r?t==e.doc.scrollLeft:Math.abs(e.doc.scrollLeft-t)<2)&&!n||(e.doc.scrollLeft=t,ai(e),e.display.scroller.scrollLeft!=t&&(e.display.scroller.scrollLeft=t),e.display.scrollbars.setScrollLeft(t))}function En(e){var t=e.display,r=t.gutters.offsetWidth,n=Math.round(e.doc.height+Sr(e.display));return{clientHeight:t.scroller.clientHeight,viewHeight:t.wrapper.clientHeight,scrollWidth:t.scroller.scrollWidth,clientWidth:t.scroller.clientWidth,viewWidth:t.wrapper.clientWidth,barLeft:e.options.fixedGutter?r:0,docHeight:n,scrollHeight:n+kr(e)+t.barHeight,nativeBarWidth:t.nativeBarWidth,gutterWidth:r}}var In=function(e,t,r){this.cm=r;var n=this.vert=O("div",[O("div",null,null,"min-width: 1px")],"CodeMirror-vscrollbar"),i=this.horiz=O("div",[O("div",null,null,"height: 100%; min-height: 1px")],"CodeMirror-hscrollbar");n.tabIndex=i.tabIndex=-1,e(n),e(i),fe(n,"scroll",function(){n.clientHeight&&t(n.scrollTop,"vertical")}),fe(i,"scroll",function(){i.clientWidth&&t(i.scrollLeft,"horizontal")}),this.checkedZeroWidth=!1,l&&s<8&&(this.horiz.style.minHeight=this.vert.style.minWidth="18px")};In.prototype.update=function(e){var t=e.scrollWidth>e.clientWidth+1,r=e.scrollHeight>e.clientHeight+1,n=e.nativeBarWidth;if(r){this.vert.style.display="block",this.vert.style.bottom=t?n+"px":"0";var i=e.viewHeight-(t?n:0);this.vert.firstChild.style.height=Math.max(0,e.scrollHeight-e.clientHeight+i)+"px"}else this.vert.style.display="",this.vert.firstChild.style.height="0";if(t){this.horiz.style.display="block",this.horiz.style.right=r?n+"px":"0",this.horiz.style.left=e.barLeft+"px";var o=e.viewWidth-e.barLeft-(r?n:0);this.horiz.firstChild.style.width=Math.max(0,e.scrollWidth-e.clientWidth+o)+"px"}else this.horiz.style.display="",this.horiz.firstChild.style.width="0";return!this.checkedZeroWidth&&e.clientHeight>0&&(0==n&&this.zeroWidthHack(),this.checkedZeroWidth=!0),{right:r?n:0,bottom:t?n:0}},In.prototype.setScrollLeft=function(e){this.horiz.scrollLeft!=e&&(this.horiz.scrollLeft=e),this.disableHoriz&&this.enableZeroWidthBar(this.horiz,this.disableHoriz,"horiz")},In.prototype.setScrollTop=function(e){this.vert.scrollTop!=e&&(this.vert.scrollTop=e),this.disableVert&&this.enableZeroWidthBar(this.vert,this.disableVert,"vert")},In.prototype.zeroWidthHack=function(){var e=y&&!d?"12px":"18px";this.horiz.style.height=this.vert.style.width=e,this.horiz.style.pointerEvents=this.vert.style.pointerEvents="none",this.disableHoriz=new R,this.disableVert=new R},In.prototype.enableZeroWidthBar=function(e,t,r){e.style.pointerEvents="auto",t.set(1e3,function n(){var i=e.getBoundingClientRect();("vert"==r?document.elementFromPoint(i.right-1,(i.top+i.bottom)/2):document.elementFromPoint((i.right+i.left)/2,i.bottom-1))!=e?e.style.pointerEvents="none":t.set(1e3,n)})},In.prototype.clear=function(){var e=this.horiz.parentNode;e.removeChild(this.horiz),e.removeChild(this.vert)};var zn=function(){};function Rn(e,t){t||(t=En(e));var r=e.display.barWidth,n=e.display.barHeight;Bn(e,t);for(var i=0;i<4&&r!=e.display.barWidth||n!=e.display.barHeight;i++)r!=e.display.barWidth&&e.options.lineWrapping&&Ln(e),Bn(e,En(e)),r=e.display.barWidth,n=e.display.barHeight}function Bn(e,t){var r=e.display,n=r.scrollbars.update(t);r.sizer.style.paddingRight=(r.barWidth=n.right)+"px",r.sizer.style.paddingBottom=(r.barHeight=n.bottom)+"px",r.heightForcer.style.borderBottom=n.bottom+"px solid transparent",n.right&&n.bottom?(r.scrollbarFiller.style.display="block",r.scrollbarFiller.style.height=n.bottom+"px",r.scrollbarFiller.style.width=n.right+"px"):r.scrollbarFiller.style.display="",n.bottom&&e.options.coverGutterNextToScrollbar&&e.options.fixedGutter?(r.gutterFiller.style.display="block",r.gutterFiller.style.height=n.bottom+"px",r.gutterFiller.style.width=t.gutterWidth+"px"):r.gutterFiller.style.display=""}zn.prototype.update=function(){return{bottom:0,right:0}},zn.prototype.setScrollLeft=function(){},zn.prototype.setScrollTop=function(){},zn.prototype.clear=function(){};var Gn={native:In,null:zn};function Un(e){e.display.scrollbars&&(e.display.scrollbars.clear(),e.display.scrollbars.addClass&&T(e.display.wrapper,e.display.scrollbars.addClass)),e.display.scrollbars=new Gn[e.options.scrollbarStyle](function(t){e.display.wrapper.insertBefore(t,e.display.scrollbarFiller),fe(t,"mousedown",function(){e.state.focused&&setTimeout(function(){return e.display.input.focus()},0)}),t.setAttribute("cm-not-content","true")},function(t,r){"horizontal"==r?Pn(e,t):Hn(e,t)},e),e.display.scrollbars.addClass&&H(e.display.wrapper,e.display.scrollbars.addClass)}var Vn=0;function Kn(e){var t;e.curOp={cm:e,viewChanged:!1,startHeight:e.doc.height,forceUpdate:!1,updateInput:0,typing:!1,changeObjs:null,cursorActivityHandlers:null,cursorActivityCalled:0,selectionChanged:!1,updateMaxLine:!1,scrollLeft:null,scrollTop:null,scrollToPos:null,focus:!1,id:++Vn},t=e.curOp,or?or.ops.push(t):t.ownsGroup=or={ops:[t],delayedCallbacks:[]}}function jn(e){var t=e.curOp;t&&function(e,t){var r=e.ownsGroup;if(r)try{!function(e){var t=e.delayedCallbacks,r=0;do{for(;r=r.viewTo)||r.maxLineChanged&&t.options.lineWrapping,e.update=e.mustUpdate&&new ri(t,e.mustUpdate&&{top:e.scrollTop,ensure:e.scrollToPos},e.forceUpdate)}function Yn(e){var t=e.cm,r=t.display;e.updatedDisplay&&Ln(t),e.barMeasure=En(t),r.maxLineChanged&&!t.options.lineWrapping&&(e.adjustWidthTo=Or(t,r.maxLine,r.maxLine.text.length).left+3,t.display.sizerWidth=e.adjustWidthTo,e.barMeasure.scrollWidth=Math.max(r.scroller.clientWidth,r.sizer.offsetLeft+e.adjustWidthTo+kr(t)+t.display.barWidth),e.maxScrollLeft=Math.max(0,r.sizer.offsetLeft+e.adjustWidthTo-Tr(t))),(e.updatedDisplay||e.selectionChanged)&&(e.preparedSelection=r.input.prepareSelection())}function _n(e){var t=e.cm;null!=e.adjustWidthTo&&(t.display.sizer.style.minWidth=e.adjustWidthTo+"px",e.maxScrollLeft(window.innerHeight||document.documentElement.clientHeight)&&(i=!1),null!=i&&!p){var o=O("div","​",null,"position: absolute;\n top: "+(t.top-r.viewOffset-Cr(e.display))+"px;\n height: "+(t.bottom-t.top+kr(e)+r.barHeight)+"px;\n left: "+t.left+"px; width: "+Math.max(2,t.right-t.left)+"px;");e.display.lineSpace.appendChild(o),o.scrollIntoView(i),e.display.lineSpace.removeChild(o)}}}(t,function(e,t,r,n){var i;null==n&&(n=0),e.options.lineWrapping||t!=r||(r="before"==(t=t.ch?et(t.line,"before"==t.sticky?t.ch-1:t.ch,"after"):t).sticky?et(t.line,t.ch+1,"before"):t);for(var o=0;o<5;o++){var l=!1,s=Xr(e,t),a=r&&r!=t?Xr(e,r):s,u=Mn(e,i={left:Math.min(s.left,a.left),top:Math.min(s.top,a.top)-n,right:Math.max(s.left,a.left),bottom:Math.max(s.bottom,a.bottom)+n}),c=e.doc.scrollTop,h=e.doc.scrollLeft;if(null!=u.scrollTop&&(Hn(e,u.scrollTop),Math.abs(e.doc.scrollTop-c)>1&&(l=!0)),null!=u.scrollLeft&&(Pn(e,u.scrollLeft),Math.abs(e.doc.scrollLeft-h)>1&&(l=!0)),!l)break}return i}(t,st(n,e.scrollToPos.from),st(n,e.scrollToPos.to),e.scrollToPos.margin));var i=e.maybeHiddenMarkers,o=e.maybeUnhiddenMarkers;if(i)for(var l=0;l=e.display.viewTo)){var r=+new Date+e.options.workTime,n=dt(e,t.highlightFrontier),i=[];t.iter(n.line,Math.min(t.first+t.size,e.display.viewTo+500),function(o){if(n.line>=e.display.viewFrom){var l=o.styles,s=o.text.length>e.options.maxHighlightLength?Ue(t.mode,n.state):null,a=ht(e,o,n,!0);s&&(n.state=s),o.styles=a.styles;var u=o.styleClasses,c=a.classes;c?o.styleClasses=c:u&&(o.styleClasses=null);for(var h=!l||l.length!=o.styles.length||u!=c&&(!u||!c||u.bgClass!=c.bgClass||u.textClass!=c.textClass),f=0;!h&&fr)return ei(e,e.options.workDelay),!0}),t.highlightFrontier=n.line,t.modeFrontier=Math.max(t.modeFrontier,n.line),i.length&&qn(e,function(){for(var t=0;t=r.viewFrom&&t.visible.to<=r.viewTo&&(null==r.updateLineNumbers||r.updateLineNumbers>=r.viewTo)&&r.renderedView==r.view&&0==dn(e))return!1;ui(e)&&(hn(e),t.dims=rn(e));var i=n.first+n.size,o=Math.max(t.visible.from-e.options.viewportMargin,n.first),l=Math.min(i,t.visible.to+e.options.viewportMargin);r.viewFroml&&r.viewTo-l<20&&(l=Math.min(i,r.viewTo)),Ct&&(o=Rt(e.doc,o),l=Bt(e.doc,l));var s=o!=r.viewFrom||l!=r.viewTo||r.lastWrapHeight!=t.wrapperHeight||r.lastWrapWidth!=t.wrapperWidth;!function(e,t,r){var n=e.display;0==n.view.length||t>=n.viewTo||r<=n.viewFrom?(n.view=ir(e,t,r),n.viewFrom=t):(n.viewFrom>t?n.view=ir(e,t,n.viewFrom).concat(n.view):n.viewFromr&&(n.view=n.view.slice(0,an(e,r)))),n.viewTo=r}(e,o,l),r.viewOffset=Vt(Xe(e.doc,r.viewFrom)),e.display.mover.style.top=r.viewOffset+"px";var u=dn(e);if(!s&&0==u&&!t.force&&r.renderedView==r.view&&(null==r.updateLineNumbers||r.updateLineNumbers>=r.viewTo))return!1;var c=function(e){if(e.hasFocus())return null;var t=W();if(!t||!D(e.display.lineDiv,t))return null;var r={activeElt:t};if(window.getSelection){var n=window.getSelection();n.anchorNode&&n.extend&&D(e.display.lineDiv,n.anchorNode)&&(r.anchorNode=n.anchorNode,r.anchorOffset=n.anchorOffset,r.focusNode=n.focusNode,r.focusOffset=n.focusOffset)}return r}(e);return u>4&&(r.lineDiv.style.display="none"),function(e,t,r){var n=e.display,i=e.options.lineNumbers,o=n.lineDiv,l=o.firstChild;function s(t){var r=t.nextSibling;return a&&y&&e.display.currentWheelTarget==t?t.style.display="none":t.parentNode.removeChild(t),r}for(var u=n.view,c=n.viewFrom,h=0;h-1&&(d=!1),ur(e,f,c,r)),d&&(M(f.lineNumber),f.lineNumber.appendChild(document.createTextNode(Je(e.options,c)))),l=f.node.nextSibling}else{var p=vr(e,f,c,r);o.insertBefore(p,l)}c+=f.size}for(;l;)l=s(l)}(e,r.updateLineNumbers,t.dims),u>4&&(r.lineDiv.style.display=""),r.renderedView=r.view,function(e){if(e&&e.activeElt&&e.activeElt!=W()&&(e.activeElt.focus(),e.anchorNode&&D(document.body,e.anchorNode)&&D(document.body,e.focusNode))){var t=window.getSelection(),r=document.createRange();r.setEnd(e.anchorNode,e.anchorOffset),r.collapse(!1),t.removeAllRanges(),t.addRange(r),t.extend(e.focusNode,e.focusOffset)}}(c),M(r.cursorDiv),M(r.selectionDiv),r.gutters.style.height=r.sizer.style.minHeight=0,s&&(r.lastWrapHeight=t.wrapperHeight,r.lastWrapWidth=t.wrapperWidth,ei(e,400)),r.updateLineNumbers=null,!0}function ii(e,t){for(var r=t.viewport,n=!0;(n&&e.options.lineWrapping&&t.oldDisplayWidth!=Tr(e)||(r&&null!=r.top&&(r={top:Math.min(e.doc.height+Sr(e.display)-Mr(e),r.top)}),t.visible=Tn(e.display,e.doc,r),!(t.visible.from>=e.display.viewFrom&&t.visible.to<=e.display.viewTo)))&&ni(e,t);n=!1){Ln(e);var i=En(e);pn(e),Rn(e,i),si(e,i),t.force=!1}t.signal(e,"update",e),e.display.viewFrom==e.display.reportedViewFrom&&e.display.viewTo==e.display.reportedViewTo||(t.signal(e,"viewportChange",e,e.display.viewFrom,e.display.viewTo),e.display.reportedViewFrom=e.display.viewFrom,e.display.reportedViewTo=e.display.viewTo)}function oi(e,t){var r=new ri(e,t);if(ni(e,r)){Ln(e),ii(e,r);var n=En(e);pn(e),Rn(e,n),si(e,n),r.finish()}}function li(e){var t=e.gutters.offsetWidth;e.sizer.style.marginLeft=t+"px"}function si(e,t){e.display.sizer.style.minHeight=t.docHeight+"px",e.display.heightForcer.style.top=t.docHeight+"px",e.display.gutters.style.height=t.docHeight+e.display.barHeight+kr(e)+"px"}function ai(e){var t=e.display,r=t.view;if(t.alignWidgets||t.gutters.firstChild&&e.options.fixedGutter){for(var n=nn(t)-t.scroller.scrollLeft+e.doc.scrollLeft,i=t.gutters.offsetWidth,o=n+"px",l=0;ls.clientWidth,c=s.scrollHeight>s.clientHeight;if(i&&u||o&&c){if(o&&y&&a)e:for(var f=t.target,d=l.view;f!=s;f=f.parentNode)for(var p=0;p=0&&tt(e,n.to())<=0)return r}return-1};var bi=function(e,t){this.anchor=e,this.head=t};function wi(e,t,r){var n=e&&e.options.selectionsMayTouch,i=t[r];t.sort(function(e,t){return tt(e.from(),t.from())}),r=B(t,i);for(var o=1;o0:a>=0){var u=ot(s.from(),l.from()),c=it(s.to(),l.to()),h=s.empty()?l.from()==l.head:s.from()==s.head;o<=r&&--r,t.splice(--o,2,new bi(h?c:u,h?u:c))}}return new yi(t,r)}function xi(e,t){return new yi([new bi(e,t||e)],0)}function Ci(e){return e.text?et(e.from.line+e.text.length-1,$(e.text).length+(1==e.text.length?e.from.ch:0)):e.to}function Si(e,t){if(tt(e,t.from)<0)return e;if(tt(e,t.to)<=0)return Ci(t);var r=e.line+t.text.length-(t.to.line-t.from.line)-1,n=e.ch;return e.line==t.to.line&&(n+=Ci(t).ch-t.to.ch),et(r,n)}function Li(e,t){for(var r=[],n=0;n1&&e.remove(s.line+1,p-1),e.insert(s.line+1,m)}sr(e,"change",e,t)}function Ai(e,t,r){!function e(n,i,o){if(n.linked)for(var l=0;ls-(e.cm?e.cm.options.historyEventDelay:500)||"*"==t.origin.charAt(0)))&&(o=function(e,t){return t?(Pi(e.done),$(e.done)):e.done.length&&!$(e.done).ranges?$(e.done):e.done.length>1&&!e.done[e.done.length-2].ranges?(e.done.pop(),$(e.done)):void 0}(i,i.lastOp==n)))l=$(o.changes),0==tt(t.from,t.to)&&0==tt(t.from,l.to)?l.to=Ci(t):o.changes.push(Fi(e,t));else{var a=$(i.done);for(a&&a.ranges||zi(e.sel,i.done),o={changes:[Fi(e,t)],generation:i.generation},i.done.push(o);i.done.length>i.undoDepth;)i.done.shift(),i.done[0].ranges||i.done.shift()}i.done.push(r),i.generation=++i.maxGeneration,i.lastModTime=i.lastSelTime=s,i.lastOp=i.lastSelOp=n,i.lastOrigin=i.lastSelOrigin=t.origin,l||ge(e,"historyAdded")}function Ii(e,t,r,n){var i=e.history,o=n&&n.origin;r==i.lastSelOp||o&&i.lastSelOrigin==o&&(i.lastModTime==i.lastSelTime&&i.lastOrigin==o||function(e,t,r,n){var i=t.charAt(0);return"*"==i||"+"==i&&r.ranges.length==n.ranges.length&&r.somethingSelected()==n.somethingSelected()&&new Date-e.history.lastSelTime<=(e.cm?e.cm.options.historyEventDelay:500)}(e,o,$(i.done),t))?i.done[i.done.length-1]=t:zi(t,i.done),i.lastSelTime=+new Date,i.lastSelOrigin=o,i.lastSelOp=r,n&&!1!==n.clearRedo&&Pi(i.undone)}function zi(e,t){var r=$(t);r&&r.ranges&&r.equals(e)||t.push(e)}function Ri(e,t,r,n){var i=t["spans_"+e.id],o=0;e.iter(Math.max(e.first,r),Math.min(e.first+e.size,n),function(r){r.markedSpans&&((i||(i=t["spans_"+e.id]={}))[o]=r.markedSpans),++o})}function Bi(e){if(!e)return null;for(var t,r=0;r-1&&($(s)[h]=u[h],delete u[h])}}}return n}function Vi(e,t,r,n){if(n){var i=e.anchor;if(r){var o=tt(t,i)<0;o!=tt(r,i)<0?(i=t,t=r):o!=tt(t,r)<0&&(t=r)}return new bi(i,t)}return new bi(r||t,t)}function Ki(e,t,r,n,i){null==i&&(i=e.cm&&(e.cm.display.shift||e.extend)),$i(e,new yi([Vi(e.sel.primary(),t,r,i)],0),n)}function ji(e,t,r){for(var n=[],i=e.cm&&(e.cm.display.shift||e.extend),o=0;o=t.ch:s.to>t.ch))){if(i&&(ge(a,"beforeCursorEnter"),a.explicitlyCleared)){if(o.markedSpans){--l;continue}break}if(!a.atomic)continue;if(r){var h=a.find(n<0?1:-1),f=void 0;if((n<0?c:u)&&(h=ro(e,h,-n,h&&h.line==t.line?o:null)),h&&h.line==t.line&&(f=tt(h,r))&&(n<0?f<0:f>0))return eo(e,h,t,n,i)}var d=a.find(n<0?-1:1);return(n<0?u:c)&&(d=ro(e,d,n,d.line==t.line?o:null)),d?eo(e,d,t,n,i):null}}return t}function to(e,t,r,n,i){var o=n||1,l=eo(e,t,r,o,i)||!i&&eo(e,t,r,o,!0)||eo(e,t,r,-o,i)||!i&&eo(e,t,r,-o,!0);return l||(e.cantEdit=!0,et(e.first,0))}function ro(e,t,r,n){return r<0&&0==t.ch?t.line>e.first?st(e,et(t.line-1)):null:r>0&&t.ch==(n||Xe(e,t.line)).text.length?t.line0)){var c=[a,1],h=tt(u.from,s.from),f=tt(u.to,s.to);(h<0||!l.inclusiveLeft&&!h)&&c.push({from:u.from,to:s.from}),(f>0||!l.inclusiveRight&&!f)&&c.push({from:s.to,to:u.to}),i.splice.apply(i,c),a+=c.length-3}}return i}(e,t.from,t.to);if(n)for(var i=n.length-1;i>=0;--i)lo(e,{from:n[i].from,to:n[i].to,text:i?[""]:t.text,origin:t.origin});else lo(e,t)}}function lo(e,t){if(1!=t.text.length||""!=t.text[0]||0!=tt(t.from,t.to)){var r=Li(e,t);Ei(e,t,r,e.cm?e.cm.curOp.id:NaN),uo(e,t,r,Tt(e,t));var n=[];Ai(e,function(e,r){r||-1!=B(n,e.history)||(po(e.history,t),n.push(e.history)),uo(e,t,null,Tt(e,t))})}}function so(e,t,r){var n=e.cm&&e.cm.state.suppressEdits;if(!n||r){for(var i,o=e.history,l=e.sel,s="undo"==t?o.done:o.undone,a="undo"==t?o.undone:o.done,u=0;u=0;--d){var p=f(d);if(p)return p.v}}}}function ao(e,t){if(0!=t&&(e.first+=t,e.sel=new yi(q(e.sel.ranges,function(e){return new bi(et(e.anchor.line+t,e.anchor.ch),et(e.head.line+t,e.head.ch))}),e.sel.primIndex),e.cm)){un(e.cm,e.first,e.first-t,t);for(var r=e.cm.display,n=r.viewFrom;ne.lastLine())){if(t.from.lineo&&(t={from:t.from,to:et(o,Xe(e,o).text.length),text:[t.text[0]],origin:t.origin}),t.removed=Ye(e,t.from,t.to),r||(r=Li(e,t)),e.cm?function(e,t,r){var n=e.doc,i=e.display,o=t.from,l=t.to,s=!1,a=o.line;e.options.lineWrapping||(a=qe(zt(Xe(n,o.line))),n.iter(a,l.line+1,function(e){if(e==i.maxLine)return s=!0,!0}));n.sel.contains(t.from,t.to)>-1&&me(e);Oi(n,t,r,on(e)),e.options.lineWrapping||(n.iter(a,o.line+t.text.length,function(e){var t=Kt(e);t>i.maxLineLength&&(i.maxLine=e,i.maxLineLength=t,i.maxLineChanged=!0,s=!1)}),s&&(e.curOp.updateMaxLine=!0));(function(e,t){if(e.modeFrontier=Math.min(e.modeFrontier,t),!(e.highlightFrontierr;n--){var i=Xe(e,n).stateAfter;if(i&&(!(i instanceof ut)||n+i.lookAhead1||!(this.children[0]instanceof vo))){var s=[];this.collapse(s),this.children=[new vo(s)],this.children[0].parent=this}},collapse:function(e){for(var t=0;t50){for(var l=i.lines.length%25+25,s=l;s10);e.parent.maybeSpill()}},iterN:function(e,t,r){for(var n=0;n0||0==l&&!1!==o.clearWhenEmpty)return o;if(o.replacedWith&&(o.collapsed=!0,o.widgetNode=A("span",[o.replacedWith],"CodeMirror-widget"),n.handleMouseEvents||o.widgetNode.setAttribute("cm-ignore-events","true"),n.insertLeft&&(o.widgetNode.insertLeft=!0)),o.collapsed){if(It(e,t.line,t,r,o)||t.line!=r.line&&It(e,r.line,t,r,o))throw new Error("Inserting collapsed marker partially overlapping an existing one");Ct=!0}o.addToHistory&&Ei(e,{from:t,to:r,origin:"markText"},e.sel,NaN);var s,a=t.line,u=e.cm;if(e.iter(a,r.line+1,function(e){u&&o.collapsed&&!u.options.lineWrapping&&zt(e)==u.display.maxLine&&(s=!0),o.collapsed&&a!=t.line&&$e(e,0),function(e,t){e.markedSpans=e.markedSpans?e.markedSpans.concat([t]):[t],t.marker.attachLine(e)}(e,new St(o,a==t.line?t.ch:null,a==r.line?r.ch:null)),++a}),o.collapsed&&e.iter(t.line,r.line+1,function(t){Gt(e,t)&&$e(t,0)}),o.clearOnEnter&&fe(o,"beforeCursorEnter",function(){return o.clear()}),o.readOnly&&(xt=!0,(e.history.done.length||e.history.undone.length)&&e.clearHistory()),o.collapsed&&(o.id=++wo,o.atomic=!0),u){if(s&&(u.curOp.updateMaxLine=!0),o.collapsed)un(u,t.line,r.line+1);else if(o.className||o.startStyle||o.endStyle||o.css||o.attributes||o.title)for(var c=t.line;c<=r.line;c++)cn(u,c,"text");o.atomic&&Qi(u.doc),sr(u,"markerAdded",u,o)}return o}xo.prototype.clear=function(){if(!this.explicitlyCleared){var e=this.doc.cm,t=e&&!e.curOp;if(t&&Kn(e),ye(this,"clear")){var r=this.find();r&&sr(this,"clear",r.from,r.to)}for(var n=null,i=null,o=0;oe.display.maxLineLength&&(e.display.maxLine=u,e.display.maxLineLength=c,e.display.maxLineChanged=!0)}null!=n&&e&&this.collapsed&&un(e,n,i+1),this.lines.length=0,this.explicitlyCleared=!0,this.atomic&&this.doc.cantEdit&&(this.doc.cantEdit=!1,e&&Qi(e.doc)),e&&sr(e,"markerCleared",e,this,n,i),t&&jn(e),this.parent&&this.parent.clear()}},xo.prototype.find=function(e,t){var r,n;null==e&&"bookmark"==this.type&&(e=1);for(var i=0;i=0;a--)oo(this,n[a]);s?_i(this,s):this.cm&&On(this.cm)}),undo:Jn(function(){so(this,"undo")}),redo:Jn(function(){so(this,"redo")}),undoSelection:Jn(function(){so(this,"undo",!0)}),redoSelection:Jn(function(){so(this,"redo",!0)}),setExtending:function(e){this.extend=e},getExtending:function(){return this.extend},historySize:function(){for(var e=this.history,t=0,r=0,n=0;n=e.ch)&&t.push(i.marker.parent||i.marker)}return t},findMarks:function(e,t,r){e=st(this,e),t=st(this,t);var n=[],i=e.line;return this.iter(e.line,t.line+1,function(o){var l=o.markedSpans;if(l)for(var s=0;s=a.to||null==a.from&&i!=e.line||null!=a.from&&i==t.line&&a.from>=t.ch||r&&!r(a.marker)||n.push(a.marker.parent||a.marker)}++i}),n},getAllMarks:function(){var e=[];return this.iter(function(t){var r=t.markedSpans;if(r)for(var n=0;ne)return t=e,!0;e-=o,++r}),st(this,et(r,t))},indexFromPos:function(e){var t=(e=st(this,e)).ch;if(e.linet&&(t=e.from),null!=e.to&&e.to-1)return t.state.draggingText(e),void setTimeout(function(){return t.display.input.focus()},20);try{var c=e.dataTransfer.getData("Text");if(c){var h;if(t.state.draggingText&&!t.state.draggingText.copy&&(h=t.listSelections()),qi(t.doc,xi(r,r)),h)for(var f=0;f=0;t--)co(e.doc,"",n[t].from,n[t].to,"+delete");On(e)})}function _o(e,t,r){var n=oe(e.text,t+r,r);return n<0||n>e.text.length?null:n}function $o(e,t,r){var n=_o(e,t.ch,r);return null==n?null:new et(t.line,n,r<0?"after":"before")}function qo(e,t,r,n,i){if(e){var o=ce(r,t.doc.direction);if(o){var l,s=i<0?$(o):o[0],a=i<0==(1==s.level)?"after":"before";if(s.level>0||"rtl"==t.doc.direction){var u=Dr(t,r);l=i<0?r.text.length-1:0;var c=Wr(t,u,l).top;l=le(function(e){return Wr(t,u,e).top==c},i<0==(1==s.level)?s.from:s.to-1,l),"before"==a&&(l=_o(r,l,1))}else l=i<0?s.to:s.from;return new et(n,l,a)}}return new et(n,i<0?r.text.length:0,i<0?"before":"after")}Ro.basic={Left:"goCharLeft",Right:"goCharRight",Up:"goLineUp",Down:"goLineDown",End:"goLineEnd",Home:"goLineStartSmart",PageUp:"goPageUp",PageDown:"goPageDown",Delete:"delCharAfter",Backspace:"delCharBefore","Shift-Backspace":"delCharBefore",Tab:"defaultTab","Shift-Tab":"indentAuto",Enter:"newlineAndIndent",Insert:"toggleOverwrite",Esc:"singleSelection"},Ro.pcDefault={"Ctrl-A":"selectAll","Ctrl-D":"deleteLine","Ctrl-Z":"undo","Shift-Ctrl-Z":"redo","Ctrl-Y":"redo","Ctrl-Home":"goDocStart","Ctrl-End":"goDocEnd","Ctrl-Up":"goLineUp","Ctrl-Down":"goLineDown","Ctrl-Left":"goGroupLeft","Ctrl-Right":"goGroupRight","Alt-Left":"goLineStart","Alt-Right":"goLineEnd","Ctrl-Backspace":"delGroupBefore","Ctrl-Delete":"delGroupAfter","Ctrl-S":"save","Ctrl-F":"find","Ctrl-G":"findNext","Shift-Ctrl-G":"findPrev","Shift-Ctrl-F":"replace","Shift-Ctrl-R":"replaceAll","Ctrl-[":"indentLess","Ctrl-]":"indentMore","Ctrl-U":"undoSelection","Shift-Ctrl-U":"redoSelection","Alt-U":"redoSelection",fallthrough:"basic"},Ro.emacsy={"Ctrl-F":"goCharRight","Ctrl-B":"goCharLeft","Ctrl-P":"goLineUp","Ctrl-N":"goLineDown","Alt-F":"goWordRight","Alt-B":"goWordLeft","Ctrl-A":"goLineStart","Ctrl-E":"goLineEnd","Ctrl-V":"goPageDown","Shift-Ctrl-V":"goPageUp","Ctrl-D":"delCharAfter","Ctrl-H":"delCharBefore","Alt-D":"delWordAfter","Alt-Backspace":"delWordBefore","Ctrl-K":"killLine","Ctrl-T":"transposeChars","Ctrl-O":"openLine"},Ro.macDefault={"Cmd-A":"selectAll","Cmd-D":"deleteLine","Cmd-Z":"undo","Shift-Cmd-Z":"redo","Cmd-Y":"redo","Cmd-Home":"goDocStart","Cmd-Up":"goDocStart","Cmd-End":"goDocEnd","Cmd-Down":"goDocEnd","Alt-Left":"goGroupLeft","Alt-Right":"goGroupRight","Cmd-Left":"goLineLeft","Cmd-Right":"goLineRight","Alt-Backspace":"delGroupBefore","Ctrl-Alt-Backspace":"delGroupAfter","Alt-Delete":"delGroupAfter","Cmd-S":"save","Cmd-F":"find","Cmd-G":"findNext","Shift-Cmd-G":"findPrev","Cmd-Alt-F":"replace","Shift-Cmd-Alt-F":"replaceAll","Cmd-[":"indentLess","Cmd-]":"indentMore","Cmd-Backspace":"delWrappedLineLeft","Cmd-Delete":"delWrappedLineRight","Cmd-U":"undoSelection","Shift-Cmd-U":"redoSelection","Ctrl-Up":"goDocStart","Ctrl-Down":"goDocEnd",fallthrough:["basic","emacsy"]},Ro.default=y?Ro.macDefault:Ro.pcDefault;var Zo={selectAll:no,singleSelection:function(e){return e.setSelection(e.getCursor("anchor"),e.getCursor("head"),V)},killLine:function(e){return Yo(e,function(t){if(t.empty()){var r=Xe(e.doc,t.head.line).text.length;return t.head.ch==r&&t.head.line0)i=new et(i.line,i.ch+1),e.replaceRange(o.charAt(i.ch-1)+o.charAt(i.ch-2),et(i.line,i.ch-2),i,"+transpose");else if(i.line>e.doc.first){var l=Xe(e.doc,i.line-1).text;l&&(i=new et(i.line,1),e.replaceRange(o.charAt(0)+e.doc.lineSeparator()+l.charAt(l.length-1),et(i.line-1,l.length-1),i,"+transpose"))}r.push(new bi(i,i))}e.setSelections(r)})},newlineAndIndent:function(e){return qn(e,function(){for(var t=e.listSelections(),r=t.length-1;r>=0;r--)e.replaceRange(e.doc.lineSeparator(),t[r].anchor,t[r].head,"+input");t=e.listSelections();for(var n=0;n-1&&(tt((i=u.ranges[i]).from(),t)<0||t.xRel>0)&&(tt(i.to(),t)>0||t.xRel<0)?function(e,t,r,n){var i=e.display,o=!1,u=Zn(e,function(t){a&&(i.scroller.draggable=!1),e.state.draggingText=!1,pe(i.wrapper.ownerDocument,"mouseup",u),pe(i.wrapper.ownerDocument,"mousemove",c),pe(i.scroller,"dragstart",h),pe(i.scroller,"drop",u),o||(we(t),n.addNew||Ki(e.doc,r,null,null,n.extend),a||l&&9==s?setTimeout(function(){i.wrapper.ownerDocument.body.focus(),i.input.focus()},20):i.input.focus())}),c=function(e){o=o||Math.abs(t.clientX-e.clientX)+Math.abs(t.clientY-e.clientY)>=10},h=function(){return o=!0};a&&(i.scroller.draggable=!0);e.state.draggingText=u,u.copy=!n.moveOnDrag,i.scroller.dragDrop&&i.scroller.dragDrop();fe(i.wrapper.ownerDocument,"mouseup",u),fe(i.wrapper.ownerDocument,"mousemove",c),fe(i.scroller,"dragstart",h),fe(i.scroller,"drop",u),xn(e),setTimeout(function(){return i.input.focus()},20)}(e,n,t,o):function(e,t,r,n){var i=e.display,o=e.doc;we(t);var l,s,a=o.sel,u=a.ranges;n.addNew&&!n.extend?(s=o.sel.contains(r),l=s>-1?u[s]:new bi(r,r)):(l=o.sel.primary(),s=o.sel.primIndex);if("rectangle"==n.unit)n.addNew||(l=new bi(r,r)),r=sn(e,t,!0,!0),s=-1;else{var c=dl(e,r,n.unit);l=n.extend?Vi(l,c.anchor,c.head,n.extend):c}n.addNew?-1==s?(s=u.length,$i(o,wi(e,u.concat([l]),s),{scroll:!1,origin:"*mouse"})):u.length>1&&u[s].empty()&&"char"==n.unit&&!n.extend?($i(o,wi(e,u.slice(0,s).concat(u.slice(s+1)),0),{scroll:!1,origin:"*mouse"}),a=o.sel):Xi(o,s,l,K):(s=0,$i(o,new yi([l],0),K),a=o.sel);var h=r;function f(t){if(0!=tt(h,t))if(h=t,"rectangle"==n.unit){for(var i=[],u=e.options.tabSize,c=z(Xe(o,r.line).text,r.ch,u),f=z(Xe(o,t.line).text,t.ch,u),d=Math.min(c,f),p=Math.max(c,f),g=Math.min(r.line,t.line),v=Math.min(e.lastLine(),Math.max(r.line,t.line));g<=v;g++){var m=Xe(o,g).text,y=X(m,d,u);d==p?i.push(new bi(et(g,y),et(g,y))):m.length>y&&i.push(new bi(et(g,y),et(g,X(m,p,u))))}i.length||i.push(new bi(r,r)),$i(o,wi(e,a.ranges.slice(0,s).concat(i),s),{origin:"*mouse",scroll:!1}),e.scrollIntoView(t)}else{var b,w=l,x=dl(e,t,n.unit),C=w.anchor;tt(x.anchor,C)>0?(b=x.head,C=ot(w.from(),x.anchor)):(b=x.anchor,C=it(w.to(),x.head));var S=a.ranges.slice(0);S[s]=function(e,t){var r=t.anchor,n=t.head,i=Xe(e.doc,r.line);if(0==tt(r,n)&&r.sticky==n.sticky)return t;var o=ce(i);if(!o)return t;var l=ae(o,r.ch,r.sticky),s=o[l];if(s.from!=r.ch&&s.to!=r.ch)return t;var a,u=l+(s.from==r.ch==(1!=s.level)?0:1);if(0==u||u==o.length)return t;if(n.line!=r.line)a=(n.line-r.line)*("ltr"==e.doc.direction?1:-1)>0;else{var c=ae(o,n.ch,n.sticky),h=c-l||(n.ch-r.ch)*(1==s.level?-1:1);a=c==u-1||c==u?h<0:h>0}var f=o[u+(a?-1:0)],d=a==(1==f.level),p=d?f.from:f.to,g=d?"after":"before";return r.ch==p&&r.sticky==g?t:new bi(new et(r.line,p,g),n)}(e,new bi(st(o,C),b)),$i(o,wi(e,S,s),K)}}var d=i.wrapper.getBoundingClientRect(),p=0;function g(t){e.state.selectingText=!1,p=1/0,t&&(we(t),i.input.focus()),pe(i.wrapper.ownerDocument,"mousemove",v),pe(i.wrapper.ownerDocument,"mouseup",m),o.history.lastSelOrigin=null}var v=Zn(e,function(t){0!==t.buttons&&ke(t)?function t(r){var l=++p;var s=sn(e,r,!0,"rectangle"==n.unit);if(!s)return;if(0!=tt(s,h)){e.curOp.focus=W(),f(s);var a=Tn(i,o);(s.line>=a.to||s.lined.bottom?20:0;u&&setTimeout(Zn(e,function(){p==l&&(i.scroller.scrollTop+=u,t(r))}),50)}}(t):g(t)}),m=Zn(e,g);e.state.selectingText=m,fe(i.wrapper.ownerDocument,"mousemove",v),fe(i.wrapper.ownerDocument,"mouseup",m)}(e,n,t,o)}(t,n,o,e):Le(e)==r.scroller&&we(e):2==i?(n&&Ki(t.doc,n),setTimeout(function(){return r.input.focus()},20)):3==i&&(S?t.display.input.onContextMenu(e):xn(t)))}}function dl(e,t,r){if("char"==r)return new bi(t,t);if("word"==r)return e.findWordAt(t);if("line"==r)return new bi(et(t.line,0),st(e.doc,et(t.line+1,0)));var n=r(e,t);return new bi(n.from,n.to)}function pl(e,t,r,n){var i,o;if(t.touches)i=t.touches[0].clientX,o=t.touches[0].clientY;else try{i=t.clientX,o=t.clientY}catch(t){return!1}if(i>=Math.floor(e.display.gutters.getBoundingClientRect().right))return!1;n&&we(t);var l=e.display,s=l.lineDiv.getBoundingClientRect();if(o>s.bottom||!ye(e,r))return Ce(t);o-=s.top-l.viewOffset;for(var a=0;a=i)return ge(e,r,e,Ze(e.doc,o),e.display.gutterSpecs[a].className,t),Ce(t)}}function gl(e,t){return pl(e,t,"gutterClick",!0)}function vl(e,t){xr(e.display,t)||function(e,t){if(!ye(e,"gutterContextMenu"))return!1;return pl(e,t,"gutterContextMenu",!1)}(e,t)||ve(e,t,"contextmenu")||S||e.display.input.onContextMenu(t)}function ml(e){e.display.wrapper.className=e.display.wrapper.className.replace(/\s*cm-s-\S+/g,"")+e.options.theme.replace(/(^|\s)\s*/g," cm-s-"),Rr(e)}hl.prototype.compare=function(e,t,r){return this.time+400>e&&0==tt(t,this.pos)&&r==this.button};var yl={toString:function(){return"CodeMirror.Init"}},bl={},wl={};function xl(e,t,r){if(!t!=!(r&&r!=yl)){var n=e.display.dragFunctions,i=t?fe:pe;i(e.display.scroller,"dragstart",n.start),i(e.display.scroller,"dragenter",n.enter),i(e.display.scroller,"dragover",n.over),i(e.display.scroller,"dragleave",n.leave),i(e.display.scroller,"drop",n.drop)}}function Cl(e){e.options.lineWrapping?(H(e.display.wrapper,"CodeMirror-wrap"),e.display.sizer.style.minWidth="",e.display.sizerWidth=null):(T(e.display.wrapper,"CodeMirror-wrap"),jt(e)),ln(e),un(e),Rr(e),setTimeout(function(){return Rn(e)},100)}function Sl(e,t){var n=this;if(!(this instanceof Sl))return new Sl(e,t);this.options=t=t?I(t):{},I(bl,t,!1);var i=t.value;"string"==typeof i?i=new Mo(i,t.mode,null,t.lineSeparator,t.direction):t.mode&&(i.modeOption=t.mode),this.doc=i;var o=new Sl.inputStyles[t.inputStyle](this),u=this.display=new function(e,t,n,i){var o=this;this.input=n,o.scrollbarFiller=O("div",null,"CodeMirror-scrollbar-filler"),o.scrollbarFiller.setAttribute("cm-not-content","true"),o.gutterFiller=O("div",null,"CodeMirror-gutter-filler"),o.gutterFiller.setAttribute("cm-not-content","true"),o.lineDiv=A("div",null,"CodeMirror-code"),o.selectionDiv=O("div",null,null,"position: relative; z-index: 1"),o.cursorDiv=O("div",null,"CodeMirror-cursors"),o.measure=O("div",null,"CodeMirror-measure"),o.lineMeasure=O("div",null,"CodeMirror-measure"),o.lineSpace=A("div",[o.measure,o.lineMeasure,o.selectionDiv,o.cursorDiv,o.lineDiv],null,"position: relative; outline: none");var u=A("div",[o.lineSpace],"CodeMirror-lines");o.mover=O("div",[u],null,"position: relative"),o.sizer=O("div",[o.mover],"CodeMirror-sizer"),o.sizerWidth=null,o.heightForcer=O("div",null,null,"position: absolute; height: "+G+"px; width: 1px;"),o.gutters=O("div",null,"CodeMirror-gutters"),o.lineGutter=null,o.scroller=O("div",[o.sizer,o.heightForcer,o.gutters],"CodeMirror-scroll"),o.scroller.setAttribute("tabIndex","-1"),o.wrapper=O("div",[o.scrollbarFiller,o.gutterFiller,o.scroller],"CodeMirror"),l&&s<8&&(o.gutters.style.zIndex=-1,o.scroller.style.paddingRight=0),a||r&&m||(o.scroller.draggable=!0),e&&(e.appendChild?e.appendChild(o.wrapper):e(o.wrapper)),o.viewFrom=o.viewTo=t.first,o.reportedViewFrom=o.reportedViewTo=t.first,o.view=[],o.renderedView=null,o.externalMeasured=null,o.viewOffset=0,o.lastWrapHeight=o.lastWrapWidth=0,o.updateLineNumbers=null,o.nativeBarWidth=o.barHeight=o.barWidth=0,o.scrollbarsClipped=!1,o.lineNumWidth=o.lineNumInnerWidth=o.lineNumChars=null,o.alignWidgets=!1,o.cachedCharWidth=o.cachedTextHeight=o.cachedPaddingH=null,o.maxLine=null,o.maxLineLength=0,o.maxLineChanged=!1,o.wheelDX=o.wheelDY=o.wheelStartX=o.wheelStartY=null,o.shift=!1,o.selForContextMenu=null,o.activeTouch=null,o.gutterSpecs=ci(i.gutters,i.lineNumbers),hi(o),n.init(o)}(e,i,o,t);for(var c in u.wrapper.CodeMirror=this,ml(this),t.lineWrapping&&(this.display.wrapper.className+=" CodeMirror-wrap"),Un(this),this.state={keyMaps:[],overlays:[],modeGen:0,overwrite:!1,delayingBlurEvent:!1,focused:!1,suppressEdits:!1,pasteIncoming:-1,cutIncoming:-1,selectingText:!1,draggingText:!1,highlight:new R,keySeq:null,specialChars:null},t.autofocus&&!m&&u.input.focus(),l&&s<11&&setTimeout(function(){return n.display.input.reset(!0)},20),function(e){var t=e.display;fe(t.scroller,"mousedown",Zn(e,fl)),fe(t.scroller,"dblclick",l&&s<11?Zn(e,function(t){if(!ve(e,t)){var r=sn(e,t);if(r&&!gl(e,t)&&!xr(e.display,t)){we(t);var n=e.findWordAt(r);Ki(e.doc,n.anchor,n.head)}}}):function(t){return ve(e,t)||we(t)});fe(t.scroller,"contextmenu",function(t){return vl(e,t)});var r,n={end:0};function i(){t.activeTouch&&(r=setTimeout(function(){return t.activeTouch=null},1e3),(n=t.activeTouch).end=+new Date)}function o(e,t){if(null==t.left)return!0;var r=t.left-e.left,n=t.top-e.top;return r*r+n*n>400}fe(t.scroller,"touchstart",function(i){if(!ve(e,i)&&!function(e){if(1!=e.touches.length)return!1;var t=e.touches[0];return t.radiusX<=1&&t.radiusY<=1}(i)&&!gl(e,i)){t.input.ensurePolled(),clearTimeout(r);var o=+new Date;t.activeTouch={start:o,moved:!1,prev:o-n.end<=300?n:null},1==i.touches.length&&(t.activeTouch.left=i.touches[0].pageX,t.activeTouch.top=i.touches[0].pageY)}}),fe(t.scroller,"touchmove",function(){t.activeTouch&&(t.activeTouch.moved=!0)}),fe(t.scroller,"touchend",function(r){var n=t.activeTouch;if(n&&!xr(t,r)&&null!=n.left&&!n.moved&&new Date-n.start<300){var l,s=e.coordsChar(t.activeTouch,"page");l=!n.prev||o(n,n.prev)?new bi(s,s):!n.prev.prev||o(n,n.prev.prev)?e.findWordAt(s):new bi(et(s.line,0),st(e.doc,et(s.line+1,0))),e.setSelection(l.anchor,l.head),e.focus(),we(r)}i()}),fe(t.scroller,"touchcancel",i),fe(t.scroller,"scroll",function(){t.scroller.clientHeight&&(Hn(e,t.scroller.scrollTop),Pn(e,t.scroller.scrollLeft,!0),ge(e,"scroll",e))}),fe(t.scroller,"mousewheel",function(t){return mi(e,t)}),fe(t.scroller,"DOMMouseScroll",function(t){return mi(e,t)}),fe(t.wrapper,"scroll",function(){return t.wrapper.scrollTop=t.wrapper.scrollLeft=0}),t.dragFunctions={enter:function(t){ve(e,t)||Se(t)},over:function(t){ve(e,t)||(!function(e,t){var r=sn(e,t);if(r){var n=document.createDocumentFragment();vn(e,r,n),e.display.dragCursor||(e.display.dragCursor=O("div",null,"CodeMirror-cursors CodeMirror-dragcursors"),e.display.lineSpace.insertBefore(e.display.dragCursor,e.display.cursorDiv)),N(e.display.dragCursor,n)}}(e,t),Se(t))},start:function(t){return function(e,t){if(l&&(!e.state.draggingText||+new Date-No<100))Se(t);else if(!ve(e,t)&&!xr(e.display,t)&&(t.dataTransfer.setData("Text",e.getSelection()),t.dataTransfer.effectAllowed="copyMove",t.dataTransfer.setDragImage&&!f)){var r=O("img",null,null,"position: fixed; left: 0; top: 0;");r.src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==",h&&(r.width=r.height=1,e.display.wrapper.appendChild(r),r._top=r.offsetTop),t.dataTransfer.setDragImage(r,0,0),h&&r.parentNode.removeChild(r)}}(e,t)},drop:Zn(e,Oo),leave:function(t){ve(e,t)||Ao(e)}};var a=t.input.getField();fe(a,"keyup",function(t){return sl.call(e,t)}),fe(a,"keydown",Zn(e,ll)),fe(a,"keypress",Zn(e,al)),fe(a,"focus",function(t){return Cn(e,t)}),fe(a,"blur",function(t){return Sn(e,t)})}(this),Ho(),Kn(this),this.curOp.forceUpdate=!0,Di(this,i),t.autofocus&&!m||this.hasFocus()?setTimeout(E(Cn,this),20):Sn(this),wl)wl.hasOwnProperty(c)&&wl[c](n,t[c],yl);ui(this),t.finishInit&&t.finishInit(this);for(var d=0;d150)){if(!n)return;r="prev"}}else u=0,r="not";"prev"==r?u=t>o.first?z(Xe(o,t-1).text,null,l):0:"add"==r?u=a+e.options.indentUnit:"subtract"==r?u=a-e.options.indentUnit:"number"==typeof r&&(u=a+r),u=Math.max(0,u);var h="",f=0;if(e.options.indentWithTabs)for(var d=Math.floor(u/l);d;--d)f+=l,h+="\t";if(fl,a=We(t),u=null;if(s&&n.ranges.length>1)if(Tl&&Tl.text.join("\n")==t){if(n.ranges.length%Tl.text.length==0){u=[];for(var c=0;c=0;f--){var d=n.ranges[f],p=d.from(),g=d.to();d.empty()&&(r&&r>0?p=et(p.line,p.ch-r):e.state.overwrite&&!s?g=et(g.line,Math.min(Xe(o,g.line).text.length,g.ch+$(a).length)):s&&Tl&&Tl.lineWise&&Tl.text.join("\n")==t&&(p=g=et(p.line,0)));var v={from:p,to:g,text:u?u[f%u.length]:a,origin:i||(s?"paste":e.state.cutIncoming>l?"cut":"+input")};oo(e.doc,v),sr(e,"inputRead",e,v)}t&&!s&&Al(e,t),On(e),e.curOp.updateInput<2&&(e.curOp.updateInput=h),e.curOp.typing=!0,e.state.pasteIncoming=e.state.cutIncoming=-1}function Ol(e,t){var r=e.clipboardData&&e.clipboardData.getData("Text");if(r)return e.preventDefault(),t.isReadOnly()||t.options.disableInput||qn(t,function(){return Nl(t,r,0,null,"paste")}),!0}function Al(e,t){if(e.options.electricChars&&e.options.smartIndent)for(var r=e.doc.sel,n=r.ranges.length-1;n>=0;n--){var i=r.ranges[n];if(!(i.head.ch>100||n&&r.ranges[n-1].head.line==i.head.line)){var o=e.getModeAt(i.head),l=!1;if(o.electricChars){for(var s=0;s-1){l=kl(e,i.head.line,"smart");break}}else o.electricInput&&o.electricInput.test(Xe(e.doc,i.head.line).text.slice(0,i.head.ch))&&(l=kl(e,i.head.line,"smart"));l&&sr(e,"electricInput",e,i.head.line)}}}function Dl(e){for(var t=[],r=[],n=0;n=t.text.length?(r.ch=t.text.length,r.sticky="before"):r.ch<=0&&(r.ch=0,r.sticky="after");var o=ae(i,r.ch,r.sticky),l=i[o];if("ltr"==e.doc.direction&&l.level%2==0&&(n>0?l.to>r.ch:l.from=l.from&&f>=c.begin)){var d=h?"before":"after";return new et(r.line,f,d)}}var p=function(e,t,n){for(var o=function(e,t){return t?new et(r.line,a(e,1),"before"):new et(r.line,e,"after")};e>=0&&e0==(1!=l.level),u=s?n.begin:a(n.end,-1);if(l.from<=u&&u0?c.end:a(c.begin,-1);return null==v||n>0&&v==t.text.length||!(g=p(n>0?0:i.length-1,n,u(v)))?null:g}(e.cm,s,t,r):$o(s,t,r))){if(n||(l=t.line+r)=e.first+e.size||(t=new et(l,t.ch,t.sticky),!(s=Xe(e,l))))return!1;t=qo(i,e.cm,s,t.line,r)}else t=o;return!0}if("char"==n)a();else if("column"==n)a(!0);else if("word"==n||"group"==n)for(var u=null,c="group"==n,h=e.cm&&e.cm.getHelper(t,"wordChars"),f=!0;!(r<0)||a(!f);f=!1){var d=s.text.charAt(t.ch)||"\n",p=te(d,h)?"w":c&&"\n"==d?"n":!c||/\s/.test(d)?null:"p";if(!c||f||p||(p="s"),u&&u!=p){r<0&&(r=1,a(),t.sticky="after");break}if(p&&(u=p),r>0&&!a(!f))break}var g=to(e,t,o,l,!0);return rt(o,g)&&(g.hitSide=!0),g}function Pl(e,t,r,n){var i,o,l=e.doc,s=t.left;if("page"==n){var a=Math.min(e.display.wrapper.clientHeight,window.innerHeight||document.documentElement.clientHeight),u=Math.max(a-.5*en(e.display),3);i=(r>0?t.bottom:t.top)+r*u}else"line"==n&&(i=r>0?t.bottom+3:t.top-3);for(;(o=$r(e,s,i)).outside;){if(r<0?i<=0:i>=l.height){o.hitSide=!0;break}i+=5*r}return o}var El=function(e){this.cm=e,this.lastAnchorNode=this.lastAnchorOffset=this.lastFocusNode=this.lastFocusOffset=null,this.polling=new R,this.composing=null,this.gracePeriod=!1,this.readDOMTimeout=null};function Il(e,t){var r=Ar(e,t.line);if(!r||r.hidden)return null;var n=Xe(e.doc,t.line),i=Nr(r,n,t.line),o=ce(n,e.doc.direction),l="left";o&&(l=ae(o,t.ch)%2?"right":"left");var s=Pr(i.map,t.ch,l);return s.offset="right"==s.collapse?s.end:s.start,s}function zl(e,t){return t&&(e.bad=!0),e}function Rl(e,t,r){var n;if(t==e.display.lineDiv){if(!(n=e.display.lineDiv.childNodes[r]))return zl(e.clipPos(et(e.display.viewTo-1)),!0);t=null,r=0}else for(n=t;;n=n.parentNode){if(!n||n==e.display.lineDiv)return null;if(n.parentNode&&n.parentNode==e.display.lineDiv)break}for(var i=0;i=t.display.viewTo||o.line=t.display.viewFrom&&Il(t,i)||{node:a[0].measure.map[2],offset:0},c=o.linen.firstLine()&&(l=et(l.line-1,Xe(n.doc,l.line-1).length)),s.ch==Xe(n.doc,s.line).text.length&&s.linei.viewTo-1)return!1;l.line==i.viewFrom||0==(e=an(n,l.line))?(t=qe(i.view[0].line),r=i.view[0].node):(t=qe(i.view[e].line),r=i.view[e-1].node.nextSibling);var a,u,c=an(n,s.line);if(c==i.view.length-1?(a=i.viewTo-1,u=i.lineDiv.lastChild):(a=qe(i.view[c+1].line)-1,u=i.view[c+1].node.previousSibling),!r)return!1;for(var h=n.doc.splitLines(function(e,t,r,n,i){var o="",l=!1,s=e.doc.lineSeparator(),a=!1;function u(){l&&(o+=s,a&&(o+=s),l=a=!1)}function c(e){e&&(u(),o+=e)}function h(t){if(1==t.nodeType){var r=t.getAttribute("cm-text");if(r)return void c(r);var o,f=t.getAttribute("cm-marker");if(f){var d=e.findMarks(et(n,0),et(i+1,0),(v=+f,function(e){return e.id==v}));return void(d.length&&(o=d[0].find(0))&&c(Ye(e.doc,o.from,o.to).join(s)))}if("false"==t.getAttribute("contenteditable"))return;var p=/^(pre|div|p|li|table|br)$/i.test(t.nodeName);if(!/^br$/i.test(t.nodeName)&&0==t.textContent.length)return;p&&u();for(var g=0;g1&&f.length>1;)if($(h)==$(f))h.pop(),f.pop(),a--;else{if(h[0]!=f[0])break;h.shift(),f.shift(),t++}for(var d=0,p=0,g=h[0],v=f[0],m=Math.min(g.length,v.length);dl.ch&&y.charCodeAt(y.length-p-1)==b.charCodeAt(b.length-p-1);)d--,p++;h[h.length-1]=y.slice(0,y.length-p).replace(/^\u200b+/,""),h[0]=h[0].slice(d).replace(/\u200b+$/,"");var x=et(t,d),C=et(a,f.length?$(f).length-p:0);return h.length>1||h[0]||tt(x,C)?(co(n.doc,h,x,C,"+input"),!0):void 0},El.prototype.ensurePolled=function(){this.forceCompositionEnd()},El.prototype.reset=function(){this.forceCompositionEnd()},El.prototype.forceCompositionEnd=function(){this.composing&&(clearTimeout(this.readDOMTimeout),this.composing=null,this.updateFromDOM(),this.div.blur(),this.div.focus())},El.prototype.readFromDOMSoon=function(){var e=this;null==this.readDOMTimeout&&(this.readDOMTimeout=setTimeout(function(){if(e.readDOMTimeout=null,e.composing){if(!e.composing.done)return;e.composing=null}e.updateFromDOM()},80))},El.prototype.updateFromDOM=function(){var e=this;!this.cm.isReadOnly()&&this.pollContent()||qn(this.cm,function(){return un(e.cm)})},El.prototype.setUneditable=function(e){e.contentEditable="false"},El.prototype.onKeyPress=function(e){0==e.charCode||this.composing||(e.preventDefault(),this.cm.isReadOnly()||Zn(this.cm,Nl)(this.cm,String.fromCharCode(null==e.charCode?e.keyCode:e.charCode),0))},El.prototype.readOnlyChanged=function(e){this.div.contentEditable=String("nocursor"!=e)},El.prototype.onContextMenu=function(){},El.prototype.resetPosition=function(){},El.prototype.needsContentAttribute=!0;var Gl=function(e){this.cm=e,this.prevInput="",this.pollingFast=!1,this.polling=new R,this.hasSelection=!1,this.composing=null};Gl.prototype.init=function(e){var t=this,r=this,n=this.cm;this.createField(e);var i=this.textarea;function o(e){if(!ve(n,e)){if(n.somethingSelected())Ml({lineWise:!1,text:n.getSelections()});else{if(!n.options.lineWiseCopyCut)return;var t=Dl(n);Ml({lineWise:!0,text:t.text}),"cut"==e.type?n.setSelections(t.ranges,null,V):(r.prevInput="",i.value=t.text.join("\n"),P(i))}"cut"==e.type&&(n.state.cutIncoming=+new Date)}}e.wrapper.insertBefore(this.wrapper,e.wrapper.firstChild),g&&(i.style.width="0px"),fe(i,"input",function(){l&&s>=9&&t.hasSelection&&(t.hasSelection=null),r.poll()}),fe(i,"paste",function(e){ve(n,e)||Ol(e,n)||(n.state.pasteIncoming=+new Date,r.fastPoll())}),fe(i,"cut",o),fe(i,"copy",o),fe(e.scroller,"paste",function(t){if(!xr(e,t)&&!ve(n,t)){if(!i.dispatchEvent)return n.state.pasteIncoming=+new Date,void r.focus();var o=new Event("paste");o.clipboardData=t.clipboardData,i.dispatchEvent(o)}}),fe(e.lineSpace,"selectstart",function(t){xr(e,t)||we(t)}),fe(i,"compositionstart",function(){var e=n.getCursor("from");r.composing&&r.composing.range.clear(),r.composing={start:e,range:n.markText(e,n.getCursor("to"),{className:"CodeMirror-composing"})}}),fe(i,"compositionend",function(){r.composing&&(r.poll(),r.composing.range.clear(),r.composing=null)})},Gl.prototype.createField=function(e){this.wrapper=Hl(),this.textarea=this.wrapper.firstChild},Gl.prototype.prepareSelection=function(){var e=this.cm,t=e.display,r=e.doc,n=gn(e);if(e.options.moveInputWithCursor){var i=Xr(e,r.sel.primary().head,"div"),o=t.wrapper.getBoundingClientRect(),l=t.lineDiv.getBoundingClientRect();n.teTop=Math.max(0,Math.min(t.wrapper.clientHeight-10,i.top+l.top-o.top)),n.teLeft=Math.max(0,Math.min(t.wrapper.clientWidth-10,i.left+l.left-o.left))}return n},Gl.prototype.showSelection=function(e){var t=this.cm.display;N(t.cursorDiv,e.cursors),N(t.selectionDiv,e.selection),null!=e.teTop&&(this.wrapper.style.top=e.teTop+"px",this.wrapper.style.left=e.teLeft+"px")},Gl.prototype.reset=function(e){if(!this.contextMenuPending&&!this.composing){var t=this.cm;if(t.somethingSelected()){this.prevInput="";var r=t.getSelection();this.textarea.value=r,t.state.focused&&P(this.textarea),l&&s>=9&&(this.hasSelection=r)}else e||(this.prevInput=this.textarea.value="",l&&s>=9&&(this.hasSelection=null))}},Gl.prototype.getField=function(){return this.textarea},Gl.prototype.supportsTouch=function(){return!1},Gl.prototype.focus=function(){if("nocursor"!=this.cm.options.readOnly&&(!m||W()!=this.textarea))try{this.textarea.focus()}catch(e){}},Gl.prototype.blur=function(){this.textarea.blur()},Gl.prototype.resetPosition=function(){this.wrapper.style.top=this.wrapper.style.left=0},Gl.prototype.receivedFocus=function(){this.slowPoll()},Gl.prototype.slowPoll=function(){var e=this;this.pollingFast||this.polling.set(this.cm.options.pollInterval,function(){e.poll(),e.cm.state.focused&&e.slowPoll()})},Gl.prototype.fastPoll=function(){var e=!1,t=this;t.pollingFast=!0,t.polling.set(20,function r(){t.poll()||e?(t.pollingFast=!1,t.slowPoll()):(e=!0,t.polling.set(60,r))})},Gl.prototype.poll=function(){var e=this,t=this.cm,r=this.textarea,n=this.prevInput;if(this.contextMenuPending||!t.state.focused||He(r)&&!n&&!this.composing||t.isReadOnly()||t.options.disableInput||t.state.keySeq)return!1;var i=r.value;if(i==n&&!t.somethingSelected())return!1;if(l&&s>=9&&this.hasSelection===i||y&&/[\uf700-\uf7ff]/.test(i))return t.display.input.reset(),!1;if(t.doc.sel==t.display.selForContextMenu){var o=i.charCodeAt(0);if(8203!=o||n||(n="​"),8666==o)return this.reset(),this.cm.execCommand("undo")}for(var a=0,u=Math.min(n.length,i.length);a1e3||i.indexOf("\n")>-1?r.value=e.prevInput="":e.prevInput=i,e.composing&&(e.composing.range.clear(),e.composing.range=t.markText(e.composing.start,t.getCursor("to"),{className:"CodeMirror-composing"}))}),!0},Gl.prototype.ensurePolled=function(){this.pollingFast&&this.poll()&&(this.pollingFast=!1)},Gl.prototype.onKeyPress=function(){l&&s>=9&&(this.hasSelection=null),this.fastPoll()},Gl.prototype.onContextMenu=function(e){var t=this,r=t.cm,n=r.display,i=t.textarea;t.contextMenuPending&&t.contextMenuPending();var o=sn(r,e),u=n.scroller.scrollTop;if(o&&!h){r.options.resetSelectionOnContextMenu&&-1==r.doc.sel.contains(o)&&Zn(r,$i)(r.doc,xi(o),V);var c,f=i.style.cssText,d=t.wrapper.style.cssText,p=t.wrapper.offsetParent.getBoundingClientRect();if(t.wrapper.style.cssText="position: static",i.style.cssText="position: absolute; width: 30px; height: 30px;\n top: "+(e.clientY-p.top-5)+"px; left: "+(e.clientX-p.left-5)+"px;\n z-index: 1000; background: "+(l?"rgba(255, 255, 255, .05)":"transparent")+";\n outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);",a&&(c=window.scrollY),n.input.focus(),a&&window.scrollTo(null,c),n.input.reset(),r.somethingSelected()||(i.value=t.prevInput=" "),t.contextMenuPending=m,n.selForContextMenu=r.doc.sel,clearTimeout(n.detectingSelectAll),l&&s>=9&&v(),S){Se(e);var g=function(){pe(window,"mouseup",g),setTimeout(m,20)};fe(window,"mouseup",g)}else setTimeout(m,50)}function v(){if(null!=i.selectionStart){var e=r.somethingSelected(),o="​"+(e?i.value:"");i.value="⇚",i.value=o,t.prevInput=e?"":"​",i.selectionStart=1,i.selectionEnd=o.length,n.selForContextMenu=r.doc.sel}}function m(){if(t.contextMenuPending==m&&(t.contextMenuPending=!1,t.wrapper.style.cssText=d,i.style.cssText=f,l&&s<9&&n.scrollbars.setScrollTop(n.scroller.scrollTop=u),null!=i.selectionStart)){(!l||l&&s<9)&&v();var e=0,o=function(){n.selForContextMenu==r.doc.sel&&0==i.selectionStart&&i.selectionEnd>0&&"​"==t.prevInput?Zn(r,no)(r):e++<10?n.detectingSelectAll=setTimeout(o,500):(n.selForContextMenu=null,n.input.reset())};n.detectingSelectAll=setTimeout(o,200)}}},Gl.prototype.readOnlyChanged=function(e){e||this.reset(),this.textarea.disabled="nocursor"==e},Gl.prototype.setUneditable=function(){},Gl.prototype.needsContentAttribute=!1,function(e){var t=e.optionHandlers;function r(r,n,i,o){e.defaults[r]=n,i&&(t[r]=o?function(e,t,r){r!=yl&&i(e,t,r)}:i)}e.defineOption=r,e.Init=yl,r("value","",function(e,t){return e.setValue(t)},!0),r("mode",null,function(e,t){e.doc.modeOption=t,Ti(e)},!0),r("indentUnit",2,Ti,!0),r("indentWithTabs",!1),r("smartIndent",!0),r("tabSize",4,function(e){Mi(e),Rr(e),un(e)},!0),r("lineSeparator",null,function(e,t){if(e.doc.lineSep=t,t){var r=[],n=e.doc.first;e.doc.iter(function(e){for(var i=0;;){var o=e.text.indexOf(t,i);if(-1==o)break;i=o+t.length,r.push(et(n,o))}n++});for(var i=r.length-1;i>=0;i--)co(e.doc,t,r[i],et(r[i].line,r[i].ch+t.length))}}),r("specialChars",/[\u0000-\u001f\u007f-\u009f\u00ad\u061c\u200b-\u200f\u2028\u2029\ufeff\ufff9-\ufffc]/g,function(e,t,r){e.state.specialChars=new RegExp(t.source+(t.test("\t")?"":"|\t"),"g"),r!=yl&&e.refresh()}),r("specialCharPlaceholder",Qt,function(e){return e.refresh()},!0),r("electricChars",!0),r("inputStyle",m?"contenteditable":"textarea",function(){throw new Error("inputStyle can not (yet) be changed in a running editor")},!0),r("spellcheck",!1,function(e,t){return e.getInputField().spellcheck=t},!0),r("autocorrect",!1,function(e,t){return e.getInputField().autocorrect=t},!0),r("autocapitalize",!1,function(e,t){return e.getInputField().autocapitalize=t},!0),r("rtlMoveVisually",!w),r("wholeLineUpdateBefore",!0),r("theme","default",function(e){ml(e),fi(e)},!0),r("keyMap","default",function(e,t,r){var n=Xo(t),i=r!=yl&&Xo(r);i&&i.detach&&i.detach(e,n),n.attach&&n.attach(e,i||null)}),r("extraKeys",null),r("configureMouse",null),r("lineWrapping",!1,Cl,!0),r("gutters",[],function(e,t){e.display.gutterSpecs=ci(t,e.options.lineNumbers),fi(e)},!0),r("fixedGutter",!0,function(e,t){e.display.gutters.style.left=t?nn(e.display)+"px":"0",e.refresh()},!0),r("coverGutterNextToScrollbar",!1,function(e){return Rn(e)},!0),r("scrollbarStyle","native",function(e){Un(e),Rn(e),e.display.scrollbars.setScrollTop(e.doc.scrollTop),e.display.scrollbars.setScrollLeft(e.doc.scrollLeft)},!0),r("lineNumbers",!1,function(e,t){e.display.gutterSpecs=ci(e.options.gutters,t),fi(e)},!0),r("firstLineNumber",1,fi,!0),r("lineNumberFormatter",function(e){return e},fi,!0),r("showCursorWhenSelecting",!1,pn,!0),r("resetSelectionOnContextMenu",!0),r("lineWiseCopyCut",!0),r("pasteLinesPerSelection",!0),r("selectionsMayTouch",!1),r("readOnly",!1,function(e,t){"nocursor"==t&&(Sn(e),e.display.input.blur()),e.display.input.readOnlyChanged(t)}),r("disableInput",!1,function(e,t){t||e.display.input.reset()},!0),r("dragDrop",!0,xl),r("allowDropFileTypes",null),r("cursorBlinkRate",530),r("cursorScrollMargin",0),r("cursorHeight",1,pn,!0),r("singleCursorHeightPerLine",!0,pn,!0),r("workTime",100),r("workDelay",100),r("flattenSpans",!0,Mi,!0),r("addModeClass",!1,Mi,!0),r("pollInterval",100),r("undoDepth",200,function(e,t){return e.doc.history.undoDepth=t}),r("historyEventDelay",1250),r("viewportMargin",10,function(e){return e.refresh()},!0),r("maxHighlightLength",1e4,Mi,!0),r("moveInputWithCursor",!0,function(e,t){t||e.display.input.resetPosition()}),r("tabindex",null,function(e,t){return e.display.input.getField().tabIndex=t||""}),r("autofocus",null),r("direction","ltr",function(e,t){return e.doc.setDirection(t)},!0),r("phrases",null)}(Sl),function(e){var t=e.optionHandlers,r=e.helpers={};e.prototype={constructor:e,focus:function(){window.focus(),this.display.input.focus()},setOption:function(e,r){var n=this.options,i=n[e];n[e]==r&&"mode"!=e||(n[e]=r,t.hasOwnProperty(e)&&Zn(this,t[e])(this,r,i),ge(this,"optionChange",this,e))},getOption:function(e){return this.options[e]},getDoc:function(){return this.doc},addKeyMap:function(e,t){this.state.keyMaps[t?"push":"unshift"](Xo(e))},removeKeyMap:function(e){for(var t=this.state.keyMaps,r=0;rr&&(kl(this,i.head.line,e,!0),r=i.head.line,n==this.doc.sel.primIndex&&On(this));else{var o=i.from(),l=i.to(),s=Math.max(r,o.line);r=Math.min(this.lastLine(),l.line-(l.ch?0:1))+1;for(var a=s;a0&&Xi(this.doc,n,new bi(o,u[n].to()),V)}}}),getTokenAt:function(e,t){return yt(this,e,t)},getLineTokens:function(e,t){return yt(this,et(e),t,!0)},getTokenTypeAt:function(e){e=st(this.doc,e);var t,r=ft(this,Xe(this.doc,e.line)),n=0,i=(r.length-1)/2,o=e.ch;if(0==o)t=r[2];else for(;;){var l=n+i>>1;if((l?r[2*l-1]:0)>=o)i=l;else{if(!(r[2*l+1]o&&(e=o,i=!0),n=Xe(this.doc,e)}else n=e;return Vr(this,n,{top:0,left:0},t||"page",r||i).top+(i?this.doc.height-Vt(n):0)},defaultTextHeight:function(){return en(this.display)},defaultCharWidth:function(){return tn(this.display)},getViewport:function(){return{from:this.display.viewFrom,to:this.display.viewTo}},addWidget:function(e,t,r,n,i){var o,l,s,a=this.display,u=(e=Xr(this,st(this.doc,e))).bottom,c=e.left;if(t.style.position="absolute",t.setAttribute("cm-ignore-events","true"),this.display.input.setUneditable(t),a.sizer.appendChild(t),"over"==n)u=e.top;else if("above"==n||"near"==n){var h=Math.max(a.wrapper.clientHeight,this.doc.height),f=Math.max(a.sizer.clientWidth,a.lineSpace.clientWidth);("above"==n||e.bottom+t.offsetHeight>h)&&e.top>t.offsetHeight?u=e.top-t.offsetHeight:e.bottom+t.offsetHeight<=h&&(u=e.bottom),c+t.offsetWidth>f&&(c=f-t.offsetWidth)}t.style.top=u+"px",t.style.left=t.style.right="","right"==i?(c=a.sizer.clientWidth-t.offsetWidth,t.style.right="0px"):("left"==i?c=0:"middle"==i&&(c=(a.sizer.clientWidth-t.offsetWidth)/2),t.style.left=c+"px"),r&&(o=this,l={left:c,top:u,right:c+t.offsetWidth,bottom:u+t.offsetHeight},null!=(s=Mn(o,l)).scrollTop&&Hn(o,s.scrollTop),null!=s.scrollLeft&&Pn(o,s.scrollLeft))},triggerOnKeyDown:Qn(ll),triggerOnKeyPress:Qn(al),triggerOnKeyUp:sl,triggerOnMouseDown:Qn(fl),execCommand:function(e){if(Zo.hasOwnProperty(e))return Zo[e].call(null,this)},triggerElectric:Qn(function(e){Al(this,e)}),findPosH:function(e,t,r,n){var i=1;t<0&&(i=-1,t=-t);for(var o=st(this.doc,e),l=0;l0&&l(t.charAt(r-1));)--r;for(;n.5)&&ln(this),ge(this,"refresh",this)}),swapDoc:Qn(function(e){var t=this.doc;return t.cm=null,this.state.selectingText&&this.state.selectingText(),Di(this,e),Rr(this),this.display.input.reset(),An(this,e.scrollLeft,e.scrollTop),this.curOp.forceScroll=!0,sr(this,"swapDoc",this,t),t}),phrase:function(e){var t=this.options.phrases;return t&&Object.prototype.hasOwnProperty.call(t,e)?t[e]:e},getInputField:function(){return this.display.input.getField()},getWrapperElement:function(){return this.display.wrapper},getScrollerElement:function(){return this.display.scroller},getGutterElement:function(){return this.display.gutters}},be(e),e.registerHelper=function(t,n,i){r.hasOwnProperty(t)||(r[t]=e[t]={_global:[]}),r[t][n]=i},e.registerGlobalHelper=function(t,n,i,o){e.registerHelper(t,n,o),r[t]._global.push({pred:i,val:o})}}(Sl);var Ul="iter insert remove copy getEditor constructor".split(" ");for(var Vl in Mo.prototype)Mo.prototype.hasOwnProperty(Vl)&&B(Ul,Vl)<0&&(Sl.prototype[Vl]=function(e){return function(){return e.apply(this.doc,arguments)}}(Mo.prototype[Vl]));return be(Mo),Sl.inputStyles={textarea:Gl,contenteditable:El},Sl.defineMode=function(e){Sl.defaults.mode||"null"==e||(Sl.defaults.mode=e),function(e,t){arguments.length>2&&(t.dependencies=Array.prototype.slice.call(arguments,2)),Ee[e]=t}.apply(this,arguments)},Sl.defineMIME=function(e,t){Ie[e]=t},Sl.defineMode("null",function(){return{token:function(e){return e.skipToEnd()}}}),Sl.defineMIME("text/plain","null"),Sl.defineExtension=function(e,t){Sl.prototype[e]=t},Sl.defineDocExtension=function(e,t){Mo.prototype[e]=t},Sl.fromTextArea=function(e,t){if((t=t?I(t):{}).value=e.value,!t.tabindex&&e.tabIndex&&(t.tabindex=e.tabIndex),!t.placeholder&&e.placeholder&&(t.placeholder=e.placeholder),null==t.autofocus){var r=W();t.autofocus=r==e||null!=e.getAttribute("autofocus")&&r==document.body}function n(){e.value=s.getValue()}var i;if(e.form&&(fe(e.form,"submit",n),!t.leaveSubmitMethodAlone)){var o=e.form;i=o.submit;try{var l=o.submit=function(){n(),o.submit=i,o.submit(),o.submit=l}}catch(e){}}t.finishInit=function(r){r.save=n,r.getTextArea=function(){return e},r.toTextArea=function(){r.toTextArea=isNaN,n(),e.parentNode.removeChild(r.getWrapperElement()),e.style.display="",e.form&&(pe(e.form,"submit",n),t.leaveSubmitMethodAlone||"function"!=typeof e.form.submit||(e.form.submit=i))}},e.style.display="none";var s=Sl(function(t){return e.parentNode.insertBefore(t,e.nextSibling)},t);return s},function(e){e.off=pe,e.on=fe,e.wheelEventPixels=vi,e.Doc=Mo,e.splitLines=We,e.countColumn=z,e.findColumn=X,e.isWordChar=ee,e.Pass=U,e.signal=ge,e.Line=Xt,e.changeEnd=Ci,e.scrollbarModel=Gn,e.Pos=et,e.cmpPos=tt,e.modes=Ee,e.mimeModes=Ie,e.resolveMode=ze,e.getMode=Re,e.modeExtensions=Be,e.extendMode=Ge,e.copyState=Ue,e.startState=Ke,e.innerMode=Ve,e.commands=Zo,e.keyMap=Ro,e.keyName=jo,e.isModifierKey=Vo,e.lookupKey=Uo,e.normalizeKeyMap=Go,e.StringStream=je,e.SharedTextMarker=So,e.TextMarker=xo,e.LineWidget=yo,e.e_preventDefault=we,e.e_stopPropagation=xe,e.e_stop=Se,e.addClass=H,e.contains=D,e.rmClass=T,e.keyNames=Po}(Sl),Sl.version="5.49.2",Sl}); \ No newline at end of file diff --git a/luci-app-mosdns/root/www/luci-static/resources/mosdns/mode/yaml/yaml.js b/luci-app-mosdns/root/www/luci-static/resources/mosdns/mode/yaml/yaml.js deleted file mode 100644 index 4a5e499bf..000000000 --- a/luci-app-mosdns/root/www/luci-static/resources/mosdns/mode/yaml/yaml.js +++ /dev/null @@ -1 +0,0 @@ -!function(e){"object"==typeof exports&&"object"==typeof module?e(require("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],e):e(CodeMirror)}(function(e){"use strict";e.defineMode("yaml",function(){var e=new RegExp("\\b(("+["true","false","on","off","yes","no"].join(")|(")+"))$","i");return{token:function(i,t){var r=i.peek(),n=t.escaped;if(t.escaped=!1,"#"==r&&(0==i.pos||/\s/.test(i.string.charAt(i.pos-1))))return i.skipToEnd(),"comment";if(i.match(/^('([^']|\\.)*'?|"([^"]|\\.)*"?)/))return"string";if(t.literal&&i.indentation()>t.keyCol)return i.skipToEnd(),"string";if(t.literal&&(t.literal=!1),i.sol()){if(t.keyCol=0,t.pair=!1,t.pairStart=!1,i.match(/---/))return"def";if(i.match(/\.\.\./))return"def";if(i.match(/\s*-\s+/))return"meta"}if(i.match(/^(\{|\}|\[|\])/))return"{"==r?t.inlinePairs++:"}"==r?t.inlinePairs--:"["==r?t.inlineList++:t.inlineList--,"meta";if(t.inlineList>0&&!n&&","==r)return i.next(),"meta";if(t.inlinePairs>0&&!n&&","==r)return t.keyCol=0,t.pair=!1,t.pairStart=!1,i.next(),"meta";if(t.pairStart){if(i.match(/^\s*(\||\>)\s*/))return t.literal=!0,"meta";if(i.match(/^\s*(\&|\*)[a-z0-9\._-]+\b/i))return"variable-2";if(0==t.inlinePairs&&i.match(/^\s*-?[0-9\.\,]+\s?$/))return"number";if(t.inlinePairs>0&&i.match(/^\s*-?[0-9\.\,]+\s?(?=(,|}))/))return"number";if(i.match(e))return"keyword"}return!t.pair&&i.match(/^\s*(?:[,\[\]{}&*!|>'"%@`][^\s'":]|[^,\[\]{}#&*!|>'"%@`])[^#]*?(?=\s*:($|\s))/)?(t.pair=!0,t.keyCol=i.indentation(),"atom"):t.pair&&i.match(/^:\s*/)?(t.pairStart=!0,"meta"):(t.pairStart=!1,t.escaped="\\"==r,i.next(),null)},startState:function(){return{pair:!1,pairStart:!1,keyCol:0,inlinePairs:0,inlineList:0,literal:!1,escaped:!1}},lineComment:"#",fold:"indent"}}),e.defineMIME("text/x-yaml","yaml"),e.defineMIME("text/yaml","yaml")}); \ No newline at end of file diff --git a/luci-app-mosdns/root/www/luci-static/resources/mosdns/theme/dracula.css b/luci-app-mosdns/root/www/luci-static/resources/mosdns/theme/dracula.css deleted file mode 100644 index 6c708c010..000000000 --- a/luci-app-mosdns/root/www/luci-static/resources/mosdns/theme/dracula.css +++ /dev/null @@ -1 +0,0 @@ -.cm-s-dracula.CodeMirror,.cm-s-dracula .CodeMirror-gutters{background-color:#282a36 !important;color:#f8f8f2 !important;border:0}.cm-s-dracula .CodeMirror-gutters{color:#282a36}.cm-s-dracula .CodeMirror-cursor{border-left:solid thin #f8f8f0}.cm-s-dracula .CodeMirror-linenumber{color:#6d8a88}.cm-s-dracula .CodeMirror-selected{background:rgba(255,255,255,0.10)}.cm-s-dracula .CodeMirror-line::selection,.cm-s-dracula .CodeMirror-line>span::selection,.cm-s-dracula .CodeMirror-line>span>span::selection{background:rgba(255,255,255,0.10)}.cm-s-dracula .CodeMirror-line::-moz-selection,.cm-s-dracula .CodeMirror-line>span::-moz-selection,.cm-s-dracula .CodeMirror-line>span>span::-moz-selection{background:rgba(255,255,255,0.10)}.cm-s-dracula span.cm-comment{color:#6272a4}.cm-s-dracula span.cm-string,.cm-s-dracula span.cm-string-2{color:#f1fa8c}.cm-s-dracula span.cm-number{color:#bd93f9}.cm-s-dracula span.cm-variable{color:#50fa7b}.cm-s-dracula span.cm-variable-2{color:white}.cm-s-dracula span.cm-def{color:#50fa7b}.cm-s-dracula span.cm-operator{color:#ff79c6}.cm-s-dracula span.cm-keyword{color:#ff79c6}.cm-s-dracula span.cm-atom{color:#bd93f9}.cm-s-dracula span.cm-meta{color:#f8f8f2}.cm-s-dracula span.cm-tag{color:#ff79c6}.cm-s-dracula span.cm-attribute{color:#50fa7b}.cm-s-dracula span.cm-qualifier{color:#50fa7b}.cm-s-dracula span.cm-property{color:#66d9ef}.cm-s-dracula span.cm-builtin{color:#50fa7b}.cm-s-dracula span.cm-variable-3,.cm-s-dracula span.cm-type{color:#ffb86c}.cm-s-dracula .CodeMirror-activeline-background{background:rgba(255,255,255,0.1)}.cm-s-dracula .CodeMirror-matchingbracket{text-decoration:underline;color:white !important}