mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-10-29 03:15:13 +08:00
🎄 Sync 2026-06-14 03:16:16
This commit is contained in:
1 parent
8eb87f53b0
commit
79dca49776
13 files changed
+1477
-24
No files matched your search
+2
-2
@@ -3,8 +3,8 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=dae
|
||||
PKG_VERSION:=2026.06.13.2
|
||||
PKG_RELEASE:=3
|
||||
PKG_VERSION:=2026.06.14-2
|
||||
PKG_RELEASE:=4
|
||||
|
||||
PKG_SOURCE:=dae-src-$(PKG_VERSION).tar.gz
|
||||
PKG_SOURCE_URL:=https://github.com/kenzok8/openwrt-daede/releases/download/dae-src
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-daede
|
||||
PKG_VERSION:=1.10.4
|
||||
PKG_RELEASE:=5
|
||||
PKG_VERSION:=1.12.0
|
||||
PKG_RELEASE:=6
|
||||
PKG_MAINTAINER:=kenzok8
|
||||
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
|
||||
|
||||
@@ -76,9 +76,12 @@ define Package/$(PKG_NAME)/install
|
||||
$(INSTALL_BIN) ./root/usr/share/luci-app-daede/update-pkg.sh $(1)/usr/share/luci-app-daede/update-pkg.sh
|
||||
$(INSTALL_BIN) ./root/usr/share/luci-app-daede/gen-dae-config.sh $(1)/usr/share/luci-app-daede/gen-dae-config.sh
|
||||
$(INSTALL_BIN) ./root/usr/share/luci-app-daede/proxy-check.sh $(1)/usr/share/luci-app-daede/proxy-check.sh
|
||||
$(INSTALL_BIN) ./root/usr/share/luci-app-daede/fetch-clash-yaml.sh $(1)/usr/share/luci-app-daede/fetch-clash-yaml.sh
|
||||
|
||||
$(INSTALL_DIR) $(1)/www/luci-static/resources/view/daede
|
||||
$(INSTALL_DATA) ./htdocs/luci-static/resources/view/daede/*.js $(1)/www/luci-static/resources/view/daede/
|
||||
$(INSTALL_DIR) $(1)/www/luci-static/resources/view/daede/vendor
|
||||
$(INSTALL_DATA) ./htdocs/luci-static/resources/view/daede/vendor/* $(1)/www/luci-static/resources/view/daede/vendor/
|
||||
|
||||
$(INSTALL_DIR) $(1)/usr/lib/lua/luci/i18n
|
||||
$(INSTALL_DATA) $(PKG_BUILD_DIR)/daede.zh-cn.lmo $(1)/usr/lib/lua/luci/i18n/daede.zh-cn.lmo
|
||||
|
||||
@@ -0,0 +1,261 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
'use strict';
|
||||
'require baseclass';
|
||||
|
||||
function utf8Base64(value) {
|
||||
const bytes = new TextEncoder().encode(String(value));
|
||||
let binary = '';
|
||||
for (let i = 0; i < bytes.length; i++)
|
||||
binary += String.fromCharCode(bytes[i]);
|
||||
return btoa(binary);
|
||||
}
|
||||
|
||||
function utf8FromBase64(value) {
|
||||
const binary = atob(value.replace(/-/g, '+').replace(/_/g, '/'));
|
||||
const bytes = Uint8Array.from(binary, function(ch) { return ch.charCodeAt(0); });
|
||||
return new TextDecoder('utf-8').decode(bytes);
|
||||
}
|
||||
|
||||
function base64Url(value) {
|
||||
return utf8Base64(value).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
|
||||
}
|
||||
|
||||
function endpoint(server, port) {
|
||||
const host = String(server).indexOf(':') >= 0 && String(server)[0] !== '['
|
||||
? '[' + server + ']'
|
||||
: server;
|
||||
return host + ':' + port;
|
||||
}
|
||||
|
||||
function requireFields(node, fields) {
|
||||
for (let i = 0; i < fields.length; i++) {
|
||||
const key = fields[i];
|
||||
if (node[key] === undefined || node[key] === null || node[key] === '')
|
||||
throw new Error('Missing required field: ' + key);
|
||||
}
|
||||
}
|
||||
|
||||
function setIf(params, key, value) {
|
||||
if (value !== undefined && value !== null && value !== '')
|
||||
params.set(key, String(value));
|
||||
}
|
||||
|
||||
function arrayValue(value) {
|
||||
return Array.isArray(value) ? value.join(',') : value;
|
||||
}
|
||||
|
||||
function addTransport(params, node) {
|
||||
const network = node.network || 'tcp';
|
||||
params.set('type', network);
|
||||
|
||||
if (network === 'ws') {
|
||||
const opts = node['ws-opts'] || {};
|
||||
setIf(params, 'path', opts.path);
|
||||
setIf(params, 'host', opts.headers && (opts.headers.Host || opts.headers.host));
|
||||
} else if (network === 'grpc') {
|
||||
const opts = node['grpc-opts'] || {};
|
||||
setIf(params, 'serviceName', opts['grpc-service-name'] || opts.serviceName);
|
||||
} else if (network === 'http' || network === 'h2') {
|
||||
const opts = node['h2-opts'] || node['http-opts'] || {};
|
||||
setIf(params, 'path', Array.isArray(opts.path) ? opts.path[0] : opts.path);
|
||||
setIf(params, 'host', arrayValue(opts.host));
|
||||
}
|
||||
}
|
||||
|
||||
function makeResult(node, link) {
|
||||
return {
|
||||
ok: true,
|
||||
name: String(node.name || 'Node'),
|
||||
type: String(node.type || '').toLowerCase(),
|
||||
link: link,
|
||||
error: ''
|
||||
};
|
||||
}
|
||||
|
||||
function convertSs(node) {
|
||||
requireFields(node, [ 'server', 'port', 'cipher', 'password' ]);
|
||||
const auth = base64Url(node.cipher + ':' + node.password);
|
||||
let query = '';
|
||||
if (node.plugin) {
|
||||
const fields = [ String(node.plugin) ];
|
||||
const opts = node['plugin-opts'] || {};
|
||||
Object.keys(opts).forEach(function(key) {
|
||||
const value = opts[key];
|
||||
if (value === true)
|
||||
fields.push(key);
|
||||
else if (value !== false && value !== undefined && value !== null && value !== '')
|
||||
fields.push(key + '=' + value);
|
||||
});
|
||||
const params = new URLSearchParams();
|
||||
params.set('plugin', fields.join(';'));
|
||||
query = '?' + params.toString();
|
||||
}
|
||||
return 'ss://' + auth + '@' + endpoint(node.server, node.port) + query + '#' + encodeURIComponent(node.name || 'Node');
|
||||
}
|
||||
|
||||
function convertVmess(node) {
|
||||
requireFields(node, [ 'server', 'port', 'uuid' ]);
|
||||
const network = node.network || 'tcp';
|
||||
const ws = node['ws-opts'] || {};
|
||||
const grpc = node['grpc-opts'] || {};
|
||||
const h2 = node['h2-opts'] || {};
|
||||
const payload = {
|
||||
v: '2',
|
||||
ps: String(node.name || 'Node'),
|
||||
add: String(node.server),
|
||||
port: String(node.port),
|
||||
id: String(node.uuid),
|
||||
aid: Number(node.alterId || node.alter_id || 0),
|
||||
scy: String(node.cipher || 'auto'),
|
||||
net: network,
|
||||
type: 'none',
|
||||
host: String((ws.headers && (ws.headers.Host || ws.headers.host)) || arrayValue(h2.host) || ''),
|
||||
path: String(ws.path || grpc['grpc-service-name'] || (Array.isArray(h2.path) ? h2.path[0] : h2.path) || ''),
|
||||
tls: node.tls ? 'tls' : 'none',
|
||||
sni: String(node.servername || node.sni || ''),
|
||||
alpn: String(arrayValue(node.alpn) || ''),
|
||||
fp: String(node.fingerprint || node['client-fingerprint'] || '')
|
||||
};
|
||||
return 'vmess://' + utf8Base64(JSON.stringify(payload));
|
||||
}
|
||||
|
||||
function convertVless(node) {
|
||||
requireFields(node, [ 'server', 'port', 'uuid' ]);
|
||||
const params = new URLSearchParams();
|
||||
addTransport(params, node);
|
||||
params.set('encryption', String(node.encryption || 'none'));
|
||||
setIf(params, 'flow', node.flow);
|
||||
|
||||
const reality = node['reality-opts'];
|
||||
if (reality || node.tls) {
|
||||
params.set('security', reality ? 'reality' : 'tls');
|
||||
setIf(params, 'sni', node.servername || node.sni);
|
||||
setIf(params, 'fp', node.fingerprint || node['client-fingerprint']);
|
||||
setIf(params, 'alpn', arrayValue(node.alpn));
|
||||
if (node['skip-cert-verify'])
|
||||
params.set('allowInsecure', '1');
|
||||
if (reality) {
|
||||
setIf(params, 'pbk', reality['public-key']);
|
||||
setIf(params, 'sid', reality['short-id']);
|
||||
setIf(params, 'spx', reality['spider-x']);
|
||||
}
|
||||
}
|
||||
|
||||
return 'vless://' + encodeURIComponent(node.uuid) + '@' + endpoint(node.server, node.port) +
|
||||
'?' + params.toString() + '#' + encodeURIComponent(node.name || 'Node');
|
||||
}
|
||||
|
||||
function convertTrojan(node) {
|
||||
requireFields(node, [ 'server', 'port', 'password' ]);
|
||||
const params = new URLSearchParams();
|
||||
addTransport(params, node);
|
||||
setIf(params, 'sni', node.sni || node.servername);
|
||||
setIf(params, 'fp', node.fingerprint || node['client-fingerprint']);
|
||||
setIf(params, 'alpn', arrayValue(node.alpn));
|
||||
if (node['skip-cert-verify'])
|
||||
params.set('allowInsecure', '1');
|
||||
return 'trojan://' + encodeURIComponent(node.password) + '@' + endpoint(node.server, node.port) +
|
||||
'?' + params.toString() + '#' + encodeURIComponent(node.name || 'Node');
|
||||
}
|
||||
|
||||
function convertTuic(node) {
|
||||
requireFields(node, [ 'server', 'port', 'uuid', 'password' ]);
|
||||
const params = new URLSearchParams();
|
||||
setIf(params, 'sni', node.sni);
|
||||
setIf(params, 'alpn', arrayValue(node.alpn));
|
||||
setIf(params, 'congestion_control', node['congestion-controller'] || node['congestion-control']);
|
||||
setIf(params, 'udp_relay_mode', node['udp-relay-mode']);
|
||||
if (node['skip-cert-verify'])
|
||||
params.set('allow_insecure', '1');
|
||||
return 'tuic://' + encodeURIComponent(node.uuid) + ':' + encodeURIComponent(node.password) + '@' +
|
||||
endpoint(node.server, node.port) + (params.toString() ? '?' + params.toString() : '') +
|
||||
'#' + encodeURIComponent(node.name || 'Node');
|
||||
}
|
||||
|
||||
function convertHysteria2(node) {
|
||||
requireFields(node, [ 'server', 'port', 'password' ]);
|
||||
const params = new URLSearchParams();
|
||||
setIf(params, 'sni', node.sni);
|
||||
setIf(params, 'alpn', arrayValue(node.alpn));
|
||||
setIf(params, 'obfs', node.obfs);
|
||||
setIf(params, 'obfs-password', node['obfs-password']);
|
||||
if (node['skip-cert-verify'])
|
||||
params.set('insecure', '1');
|
||||
return 'hysteria2://' + encodeURIComponent(node.password) + '@' + endpoint(node.server, node.port) +
|
||||
(params.toString() ? '?' + params.toString() : '') + '#' + encodeURIComponent(node.name || 'Node');
|
||||
}
|
||||
|
||||
function convertAnytls(node) {
|
||||
requireFields(node, [ 'server', 'port', 'password' ]);
|
||||
const params = new URLSearchParams();
|
||||
setIf(params, 'sni', node.sni || node.servername);
|
||||
setIf(params, 'alpn', arrayValue(node.alpn));
|
||||
setIf(params, 'client-fingerprint', node['client-fingerprint'] || node.fingerprint);
|
||||
if (node['skip-cert-verify'])
|
||||
params.set('allowInsecure', '1');
|
||||
if (node.udp)
|
||||
params.set('udp', '1');
|
||||
return 'anytls://' + encodeURIComponent(node.password) + '@' + endpoint(node.server, node.port) +
|
||||
(params.toString() ? '?' + params.toString() : '') + '#' + encodeURIComponent(node.name || 'Node');
|
||||
}
|
||||
|
||||
function convertProxy(node) {
|
||||
const type = String(node && node.type || '').toLowerCase();
|
||||
const converters = {
|
||||
ss: convertSs,
|
||||
vmess: convertVmess,
|
||||
vless: convertVless,
|
||||
trojan: convertTrojan,
|
||||
tuic: convertTuic,
|
||||
hysteria2: convertHysteria2,
|
||||
hy2: convertHysteria2,
|
||||
anytls: convertAnytls
|
||||
};
|
||||
|
||||
try {
|
||||
if (!node || typeof node !== 'object')
|
||||
throw new Error('Node must be an object');
|
||||
if (!converters[type])
|
||||
throw new Error('Unsupported protocol: ' + (type || 'unknown'));
|
||||
return makeResult(node, converters[type](node));
|
||||
} catch (e) {
|
||||
return {
|
||||
ok: false,
|
||||
name: String(node && node.name || 'Node'),
|
||||
type: type || 'unknown',
|
||||
link: '',
|
||||
error: String(e && e.message || e)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function convertProxies(proxies) {
|
||||
return Array.isArray(proxies) ? proxies.map(convertProxy) : [];
|
||||
}
|
||||
|
||||
function normalizeLink(link) {
|
||||
const value = String(link || '').trim();
|
||||
if (value.indexOf('vmess://') === 0) {
|
||||
try {
|
||||
const payload = JSON.parse(utf8FromBase64(value.slice(8)));
|
||||
delete payload.ps;
|
||||
return 'vmess://' + utf8Base64(JSON.stringify(payload));
|
||||
} catch (e) {}
|
||||
}
|
||||
return value.replace(/#.*$/, '');
|
||||
}
|
||||
|
||||
const api = {
|
||||
convertProxy: convertProxy,
|
||||
convertProxies: convertProxies,
|
||||
normalizeLink: normalizeLink
|
||||
};
|
||||
|
||||
if (typeof module !== 'undefined' && module.exports)
|
||||
module.exports = api;
|
||||
|
||||
if (typeof baseclass !== 'undefined')
|
||||
return baseclass.extend(api);
|
||||
|
||||
return api;
|
||||
@@ -0,0 +1,419 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
'use strict';
|
||||
'require fs';
|
||||
'require uci';
|
||||
'require ui';
|
||||
'require view';
|
||||
'require view.daede.backend as backend';
|
||||
'require view.daede.clash-converter as clashConverter';
|
||||
'require view.daede.styles as styles';
|
||||
|
||||
const FETCHER = '/usr/share/luci-app-daede/fetch-clash-yaml.sh';
|
||||
const GENERATOR = '/usr/share/luci-app-daede/gen-dae-config.sh';
|
||||
|
||||
function loadYamlParser() {
|
||||
if (window.jsyaml && window.jsyaml.load)
|
||||
return Promise.resolve(window.jsyaml);
|
||||
|
||||
return new Promise(function(resolve, reject) {
|
||||
const script = document.createElement('script');
|
||||
script.src = L.resource('view/daede/vendor/js-yaml.min.js');
|
||||
script.onload = function() {
|
||||
if (window.jsyaml && window.jsyaml.load)
|
||||
resolve(window.jsyaml);
|
||||
else
|
||||
reject(new Error(_('YAML parser failed to load')));
|
||||
};
|
||||
script.onerror = function() { reject(new Error(_('YAML parser failed to load'))); };
|
||||
document.head.appendChild(script);
|
||||
});
|
||||
}
|
||||
|
||||
function daedEndpoint() {
|
||||
const listen = uci.get('daed', 'config', 'listen_addr') || '0.0.0.0:2023';
|
||||
const match = String(listen).match(/:(\d+)$/);
|
||||
const port = match ? match[1] : '2023';
|
||||
const host = window.location.hostname.indexOf(':') >= 0 ? '[' + window.location.hostname + ']' : window.location.hostname;
|
||||
return 'http://' + host + ':' + port + '/graphql';
|
||||
}
|
||||
|
||||
function graphQL(endpoint, query, variables, token) {
|
||||
const headers = { 'Content-Type': 'application/json' };
|
||||
if (token)
|
||||
headers.Authorization = 'Bearer ' + token;
|
||||
|
||||
return fetch(endpoint, {
|
||||
method: 'POST',
|
||||
headers: headers,
|
||||
body: JSON.stringify({ query: query, variables: variables || {} })
|
||||
}).then(function(response) {
|
||||
if (!response.ok)
|
||||
throw new Error(_('daed returned HTTP %s').format(response.status));
|
||||
return response.json();
|
||||
}).then(function(body) {
|
||||
if (body.errors && body.errors.length)
|
||||
throw new Error(body.errors.map(function(e) { return e.message; }).join('; '));
|
||||
return body.data;
|
||||
});
|
||||
}
|
||||
|
||||
function requestDaedCredentials() {
|
||||
return new Promise(function(resolve, reject) {
|
||||
const username = E('input', { 'class': 'cbi-input-text', 'autocomplete': 'username', 'placeholder': _('Username') });
|
||||
const password = E('input', { 'class': 'cbi-input-password', 'type': 'password', 'autocomplete': 'current-password', 'placeholder': _('Password') });
|
||||
const cancel = E('button', { 'class': 'btn cbi-button' }, _('Cancel'));
|
||||
const login = E('button', { 'class': 'btn cbi-button cbi-button-positive' }, _('Sign in and import'));
|
||||
|
||||
cancel.addEventListener('click', function() {
|
||||
password.value = '';
|
||||
ui.hideModal();
|
||||
reject(new Error(_('Import cancelled')));
|
||||
});
|
||||
login.addEventListener('click', function() {
|
||||
if (!username.value || !password.value)
|
||||
return;
|
||||
const result = { username: username.value, password: password.value };
|
||||
password.value = '';
|
||||
ui.hideModal();
|
||||
resolve(result);
|
||||
});
|
||||
|
||||
ui.showModal(_('Sign in to daed'), [
|
||||
E('p', {}, _('Credentials are used only for this import and are not saved.')),
|
||||
E('div', { 'class': 'cbi-value' }, [ E('label', { 'class': 'cbi-value-title' }, _('Username')), E('div', { 'class': 'cbi-value-field' }, username) ]),
|
||||
E('div', { 'class': 'cbi-value' }, [ E('label', { 'class': 'cbi-value-title' }, _('Password')), E('div', { 'class': 'cbi-value-field' }, password) ]),
|
||||
E('div', { 'class': 'right' }, [ cancel, ' ', login ])
|
||||
]);
|
||||
username.focus();
|
||||
});
|
||||
}
|
||||
|
||||
function uniqueNodeTag(existing, index) {
|
||||
let n = index + 1;
|
||||
let tag = 'converted_' + n;
|
||||
while (existing[tag]) {
|
||||
n++;
|
||||
tag = 'converted_' + n;
|
||||
}
|
||||
existing[tag] = true;
|
||||
return tag;
|
||||
}
|
||||
|
||||
return view.extend({
|
||||
load: function() {
|
||||
return Promise.all([
|
||||
backend.detectBackend(),
|
||||
uci.load('dae').catch(function() {}),
|
||||
uci.load('daed').catch(function() {}),
|
||||
loadYamlParser()
|
||||
]).then(function(values) {
|
||||
return { ctx: values[0], yaml: values[3] };
|
||||
});
|
||||
},
|
||||
|
||||
render: function(data) {
|
||||
const state = {
|
||||
results: [],
|
||||
filter: '',
|
||||
target: data.ctx.installed[data.ctx.name] ? data.ctx.name : (data.ctx.installed.dae ? 'dae' : 'daed')
|
||||
};
|
||||
|
||||
const urlInput = E('input', { 'class': 'dd-conv-url', 'placeholder': 'https://example.com/clash.yaml', 'autocomplete': 'off' });
|
||||
const yamlInput = E('textarea', { 'class': 'dd-conv-yaml', 'placeholder': _('Or paste Clash YAML here'), 'spellcheck': 'false' });
|
||||
const parseUrl = E('button', { 'class': 'cbi-button cbi-button-action' }, _('Fetch and parse'));
|
||||
const parsePaste = E('button', { 'class': 'cbi-button' }, _('Parse pasted YAML'));
|
||||
const filterInput = E('input', { 'class': 'dd-conv-filter', 'placeholder': _('Filter name or protocol') });
|
||||
const selectNew = E('button', { 'class': 'cbi-button' }, _('Select compatible new nodes'));
|
||||
const clearSelection = E('button', { 'class': 'cbi-button' }, _('Clear selection'));
|
||||
const targetSelect = E('select', { 'class': 'dd-conv-target' });
|
||||
const importButton = E('button', { 'class': 'cbi-button cbi-button-positive', 'disabled': 'disabled' }, _('Import selected nodes'));
|
||||
const summary = E('span', { 'class': 'dd-meta' }, _('No YAML parsed yet'));
|
||||
const status = E('div', { 'class': 'dd-conv-status' }, '');
|
||||
const resultBody = E('div', { 'class': 'dd-conv-results' });
|
||||
|
||||
[ 'dae', 'daed' ].forEach(function(name) {
|
||||
if (data.ctx.installed[name])
|
||||
targetSelect.appendChild(E('option', { 'value': name, 'selected': state.target === name ? 'selected' : null }, name));
|
||||
});
|
||||
|
||||
const setStatus = function(text, kind) {
|
||||
status.textContent = text || '';
|
||||
status.className = 'dd-conv-status' + (kind ? ' ' + kind : '');
|
||||
};
|
||||
|
||||
const selectedResults = function() {
|
||||
return state.results.filter(function(item) { return item.ok && item.selected && !item.duplicate; });
|
||||
};
|
||||
|
||||
const classifyDaeDuplicates = function() {
|
||||
const existing = {};
|
||||
(uci.sections('dae', 'node') || []).forEach(function(section) {
|
||||
if (section.link)
|
||||
existing[clashConverter.normalizeLink(section.link)] = true;
|
||||
});
|
||||
state.results.forEach(function(item) {
|
||||
item.duplicate = !!(item.ok && existing[clashConverter.normalizeLink(item.link)]);
|
||||
if (item.duplicate)
|
||||
item.selected = false;
|
||||
});
|
||||
};
|
||||
|
||||
const renderResults = function() {
|
||||
while (resultBody.firstChild)
|
||||
resultBody.removeChild(resultBody.firstChild);
|
||||
|
||||
const filter = state.filter.toLowerCase();
|
||||
const shown = state.results.filter(function(item) {
|
||||
return !filter || item.name.toLowerCase().indexOf(filter) >= 0 || item.type.toLowerCase().indexOf(filter) >= 0;
|
||||
});
|
||||
|
||||
shown.forEach(function(item) {
|
||||
const checkbox = E('input', { 'type': 'checkbox' });
|
||||
checkbox.checked = !!item.selected;
|
||||
checkbox.disabled = !item.ok || item.duplicate;
|
||||
checkbox.addEventListener('change', function() {
|
||||
item.selected = checkbox.checked;
|
||||
renderResults();
|
||||
});
|
||||
|
||||
let resultText, resultClass;
|
||||
if (!item.ok) {
|
||||
resultText = item.error;
|
||||
resultClass = 'bad';
|
||||
} else if (item.duplicate) {
|
||||
resultText = _('Already exists, skipped');
|
||||
resultClass = 'dup';
|
||||
} else {
|
||||
resultText = _('Ready to import');
|
||||
resultClass = 'good';
|
||||
}
|
||||
|
||||
resultBody.appendChild(E('div', { 'class': 'dd-conv-result' }, [
|
||||
checkbox,
|
||||
E('span', { 'class': 'dd-conv-name', 'title': item.name }, item.name),
|
||||
E('span', { 'class': 'dd-conv-proto' }, item.type.toUpperCase()),
|
||||
E('span', { 'class': 'dd-conv-result-state ' + resultClass, 'title': resultText }, resultText)
|
||||
]));
|
||||
});
|
||||
|
||||
const compatible = state.results.filter(function(item) { return item.ok; }).length;
|
||||
const unsupported = state.results.length - compatible;
|
||||
const duplicates = state.results.filter(function(item) { return item.duplicate; }).length;
|
||||
summary.textContent = _('Detected %d · compatible %d · duplicates %d · incompatible %d')
|
||||
.format(state.results.length, compatible, duplicates, unsupported);
|
||||
importButton.textContent = _('Import selected nodes (%d)').format(selectedResults().length);
|
||||
importButton.disabled = selectedResults().length === 0;
|
||||
};
|
||||
|
||||
const acceptYaml = function(text) {
|
||||
let documentValue;
|
||||
try {
|
||||
documentValue = data.yaml.load(text);
|
||||
} catch (e) {
|
||||
setStatus(_('YAML parse failed: %s').format(e.message || e), 'err');
|
||||
return;
|
||||
}
|
||||
if (!documentValue || !Array.isArray(documentValue.proxies) || documentValue.proxies.length === 0) {
|
||||
setStatus(_('No top-level proxies list was found'), 'err');
|
||||
return;
|
||||
}
|
||||
|
||||
state.results = clashConverter.convertProxies(documentValue.proxies).map(function(item) {
|
||||
item.selected = item.ok;
|
||||
item.duplicate = false;
|
||||
return item;
|
||||
});
|
||||
if (state.target === 'dae')
|
||||
classifyDaeDuplicates();
|
||||
setStatus(_('Conversion preview is ready'), 'ok');
|
||||
renderResults();
|
||||
};
|
||||
|
||||
parseUrl.addEventListener('click', function() {
|
||||
const value = urlInput.value.trim();
|
||||
if (!/^https?:\/\//i.test(value)) {
|
||||
setStatus(_('Enter an HTTP or HTTPS subscription URL'), 'err');
|
||||
return;
|
||||
}
|
||||
parseUrl.disabled = true;
|
||||
setStatus(_('Fetching subscription…'));
|
||||
fs.exec(FETCHER, [ value ]).then(function(res) {
|
||||
if (!res || res.code !== 0)
|
||||
throw new Error((res && (res.stderr || res.stdout)) || _('Fetch failed'));
|
||||
acceptYaml(res.stdout || '');
|
||||
}).catch(function(e) {
|
||||
setStatus(_('Fetch failed: %s').format(String(e.message || e).trim()), 'err');
|
||||
}).finally(function() { parseUrl.disabled = false; });
|
||||
});
|
||||
|
||||
parsePaste.addEventListener('click', function() {
|
||||
const value = yamlInput.value.trim();
|
||||
if (!value) {
|
||||
setStatus(_('Paste Clash YAML first'), 'err');
|
||||
return;
|
||||
}
|
||||
acceptYaml(value);
|
||||
});
|
||||
|
||||
filterInput.addEventListener('input', function() {
|
||||
state.filter = filterInput.value;
|
||||
renderResults();
|
||||
});
|
||||
selectNew.addEventListener('click', function() {
|
||||
state.results.forEach(function(item) { item.selected = item.ok && !item.duplicate; });
|
||||
renderResults();
|
||||
});
|
||||
clearSelection.addEventListener('click', function() {
|
||||
state.results.forEach(function(item) { item.selected = false; });
|
||||
renderResults();
|
||||
});
|
||||
targetSelect.addEventListener('change', function() {
|
||||
state.target = targetSelect.value;
|
||||
state.results.forEach(function(item) { item.duplicate = false; });
|
||||
if (state.target === 'dae')
|
||||
classifyDaeDuplicates();
|
||||
renderResults();
|
||||
});
|
||||
|
||||
const importDae = function(items) {
|
||||
const usedTags = {};
|
||||
(uci.sections('dae', 'node') || []).forEach(function(section) {
|
||||
if (section.tag)
|
||||
usedTags[section.tag] = true;
|
||||
});
|
||||
items.forEach(function(item, index) {
|
||||
const sid = uci.add('dae', 'node');
|
||||
uci.set('dae', sid, 'tag', uniqueNodeTag(usedTags, index));
|
||||
uci.set('dae', sid, 'link', item.link);
|
||||
uci.set('dae', sid, 'enabled', '1');
|
||||
});
|
||||
|
||||
return uci.save().then(function() {
|
||||
return uci.changes().then(function(changes) {
|
||||
return changes && Object.keys(changes).length ? uci.apply() : null;
|
||||
});
|
||||
}).then(function() {
|
||||
return fs.exec(GENERATOR, [ 'generate' ]);
|
||||
}).then(function(res) {
|
||||
if (res && res.code !== 0)
|
||||
throw new Error(res.stderr || res.stdout || ('exit ' + res.code));
|
||||
items.forEach(function(item) { item.duplicate = true; item.selected = false; });
|
||||
return { added: items.length, duplicates: 0, failed: 0 };
|
||||
});
|
||||
};
|
||||
|
||||
const importDaed = function(items) {
|
||||
let credentials;
|
||||
let token = '';
|
||||
const endpoint = daedEndpoint();
|
||||
return requestDaedCredentials().then(function(value) {
|
||||
credentials = value;
|
||||
return graphQL(endpoint,
|
||||
'query Login($username:String!,$password:String!){token(username:$username,password:$password)}',
|
||||
credentials);
|
||||
}).then(function(login) {
|
||||
token = login.token;
|
||||
credentials.password = '';
|
||||
credentials = null;
|
||||
return graphQL(endpoint, 'query ExistingNodes{nodes(first:10000){edges{link}}}', {}, token);
|
||||
}).then(function(existingData) {
|
||||
const existing = {};
|
||||
(existingData.nodes.edges || []).forEach(function(node) {
|
||||
existing[clashConverter.normalizeLink(node.link)] = true;
|
||||
});
|
||||
const fresh = items.filter(function(item) {
|
||||
const duplicate = !!existing[clashConverter.normalizeLink(item.link)];
|
||||
if (duplicate) {
|
||||
item.duplicate = true;
|
||||
item.selected = false;
|
||||
}
|
||||
return !duplicate;
|
||||
});
|
||||
if (!fresh.length)
|
||||
return { importNodes: [], preDuplicates: items.length };
|
||||
return graphQL(endpoint,
|
||||
'mutation ImportNodes($args:[ImportArgument!]!){importNodes(rollbackError:false,args:$args){link error node{id}}}',
|
||||
{ args: fresh.map(function(item) { return { link: item.link }; }) }, token)
|
||||
.then(function(value) { value.preDuplicates = items.length - fresh.length; return value; });
|
||||
}).then(function(result) {
|
||||
const rows = result.importNodes || [];
|
||||
const importedItems = {};
|
||||
items.forEach(function(item) { importedItems[clashConverter.normalizeLink(item.link)] = item; });
|
||||
rows.forEach(function(row) {
|
||||
if (!row.error || row.error === 'node already exists') {
|
||||
const item = importedItems[clashConverter.normalizeLink(row.link)];
|
||||
if (item) {
|
||||
item.duplicate = true;
|
||||
item.selected = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
const failed = rows.filter(function(row) { return !!row.error && row.error !== 'node already exists'; }).length;
|
||||
const apiDuplicates = rows.filter(function(row) { return row.error === 'node already exists'; }).length;
|
||||
const duplicates = (result.preDuplicates || 0) + apiDuplicates;
|
||||
const added = rows.filter(function(row) { return !row.error; }).length;
|
||||
return { added: added, duplicates: duplicates, failed: failed };
|
||||
}).finally(function() {
|
||||
if (credentials)
|
||||
credentials.password = '';
|
||||
credentials = null;
|
||||
token = '';
|
||||
});
|
||||
};
|
||||
|
||||
importButton.addEventListener('click', function() {
|
||||
const items = selectedResults();
|
||||
if (!items.length)
|
||||
return;
|
||||
importButton.disabled = true;
|
||||
setStatus(_('Importing selected nodes…'));
|
||||
const action = state.target === 'dae' ? importDae(items) : importDaed(items);
|
||||
action.then(function(result) {
|
||||
setStatus(_('Import complete: added %d, duplicates %d, failed %d')
|
||||
.format(result.added, result.duplicates, result.failed), result.failed ? 'err' : 'ok');
|
||||
renderResults();
|
||||
}).catch(function(e) {
|
||||
setStatus(_('Import failed: %s').format(e.message || e), 'err');
|
||||
}).finally(function() {
|
||||
importButton.disabled = selectedResults().length === 0;
|
||||
});
|
||||
});
|
||||
|
||||
renderResults();
|
||||
|
||||
return E('div', { 'class': 'dd-wrap dd-converter' }, [
|
||||
E('style', {}, styles.CSS),
|
||||
E('div', { 'class': 'dd-card dd-conv-card' }, [
|
||||
E('h3', {}, _('Subscription Converter')),
|
||||
E('p', { 'class': 'dd-settings-descr' }, _('Convert Clash YAML into share links, preview the result, then import selected nodes into dae or daed. Inputs and credentials are not saved.')),
|
||||
E('h4', { 'class': 'dd-card-title' }, _('1. Input Clash YAML')),
|
||||
E('div', { 'class': 'dd-conv-url-row' }, [ urlInput, parseUrl ]),
|
||||
E('div', { 'class': 'dd-conv-or' }, _('or')),
|
||||
yamlInput,
|
||||
E('div', { 'class': 'dd-actions' }, [ parsePaste ])
|
||||
]),
|
||||
E('div', { 'class': 'dd-card dd-conv-card' }, [
|
||||
E('div', { 'class': 'dd-conv-heading' }, [
|
||||
E('h4', { 'class': 'dd-card-title' }, _('2. Conversion Preview')),
|
||||
summary
|
||||
]),
|
||||
E('div', { 'class': 'dd-conv-toolbar' }, [ selectNew, clearSelection, filterInput ]),
|
||||
resultBody
|
||||
]),
|
||||
E('div', { 'class': 'dd-card dd-conv-card' }, [
|
||||
E('h4', { 'class': 'dd-card-title' }, _('3. Import Selected Nodes')),
|
||||
E('div', { 'class': 'dd-conv-import' }, [
|
||||
E('label', {}, _('Target backend')),
|
||||
targetSelect,
|
||||
importButton
|
||||
]),
|
||||
status
|
||||
])
|
||||
]);
|
||||
},
|
||||
|
||||
handleSave: null,
|
||||
handleSaveApply: null,
|
||||
handleReset: null
|
||||
});
|
||||
@@ -178,7 +178,31 @@ const CSS = [
|
||||
'.dd-settings-card .cbi-section-table-row>td:nth-child(2){flex:1 1 auto !important}',
|
||||
'.dd-settings-card .cbi-section-table-row>td:nth-child(3){flex:0 0 auto !important;text-align:center}',
|
||||
'.dd-settings-card .cbi-section-table-row>td.cbi-section-actions{flex:0 0 auto !important;display:flex;gap:4px}',
|
||||
'}'
|
||||
'}',
|
||||
'.dd-conv-card{padding:14px 16px;margin-bottom:10px}',
|
||||
'.dd-conv-card h3{font-size:18px;margin:0 0 6px}',
|
||||
'.dd-conv-url-row,.dd-conv-import,.dd-conv-toolbar,.dd-conv-heading{display:flex;align-items:center;gap:8px;flex-wrap:wrap}',
|
||||
'.dd-conv-url-row input,.dd-conv-filter,.dd-conv-target,.dd-conv-yaml{box-sizing:border-box;border:1px solid rgba(128,128,128,.28);border-radius:6px;background:transparent;color:inherit;font-size:12px;padding:7px 9px}',
|
||||
'.dd-conv-url-row input{flex:1;min-width:240px}',
|
||||
'.dd-conv-yaml{width:100%;min-height:150px;resize:vertical;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.5}',
|
||||
'.dd-conv-or{text-align:center;font-size:11px;opacity:.5;margin:7px 0}',
|
||||
'.dd-conv-heading{justify-content:space-between;margin-bottom:8px}',
|
||||
'.dd-conv-heading .dd-card-title{margin:0}',
|
||||
'.dd-conv-toolbar{margin-bottom:8px}',
|
||||
'.dd-conv-filter{margin-left:auto;min-width:220px}',
|
||||
'.dd-conv-results{border:1px solid rgba(128,128,128,.18);border-radius:7px;max-height:420px;overflow:auto}',
|
||||
'.dd-conv-result{display:grid;grid-template-columns:22px minmax(100px,1fr) 90px minmax(130px,1.3fr);gap:8px;align-items:center;padding:7px 9px;border-bottom:1px solid rgba(128,128,128,.13);font-size:12px}',
|
||||
'.dd-conv-result:last-child{border-bottom:0}',
|
||||
'.dd-conv-result input{appearance:checkbox !important;-webkit-appearance:checkbox !important;accent-color:#4aa065;width:15px;height:15px}',
|
||||
'.dd-conv-name,.dd-conv-result-state{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}',
|
||||
'.dd-conv-proto{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;font-size:11px;opacity:.7}',
|
||||
'.dd-conv-result-state.good,.dd-conv-status.ok{color:#3da66a}',
|
||||
'.dd-conv-result-state.dup{opacity:.55}',
|
||||
'.dd-conv-result-state.bad,.dd-conv-status.err{color:#d96d6d}',
|
||||
'.dd-conv-import label{font-size:12px;font-weight:600;opacity:.72}',
|
||||
'.dd-conv-import .cbi-button{margin-left:auto}',
|
||||
'.dd-conv-status{margin-top:9px;font-size:11.5px;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;min-height:16px}',
|
||||
'@media(max-width:640px){.dd-conv-filter{margin-left:0;width:100%}.dd-conv-result{grid-template-columns:20px minmax(90px,1fr) 68px}.dd-conv-result-state{grid-column:2/4;font-size:11px}.dd-conv-import .cbi-button{margin-left:0;width:100%}.dd-conv-url-row input{min-width:100%;width:100%}.dd-conv-url-row .cbi-button{width:100%}}'
|
||||
].join('');
|
||||
|
||||
return baseclass.extend({ CSS: CSS });
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
(The MIT License)
|
||||
|
||||
Copyright (C) 2011-2015 by Vitaly Puzrin
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
@@ -0,0 +1,33 @@
|
||||
(function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports):typeof define==`function`&&define.amd?define([`exports`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.jsyaml={}))})(this,function(e){Object.defineProperties(e,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});var t=Object.create,n=Object.defineProperty,r=Object.getOwnPropertyDescriptor,i=Object.getOwnPropertyNames,a=Object.getPrototypeOf,o=Object.prototype.hasOwnProperty,s=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports),c=(e,t,a,s)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var c=i(t),l=0,u=c.length,d;l<u;l++)d=c[l],!o.call(e,d)&&d!==a&&n(e,d,{get:(e=>t[e]).bind(null,d),enumerable:!(s=r(t,d))||s.enumerable});return e},l=(e,r,i)=>(i=e==null?{}:t(a(e)),c(r||!e||!e.__esModule?n(i,`default`,{value:e,enumerable:!0}):i,e)),u=s(((e,t)=>{function n(e){return e==null}function r(e){return typeof e==`object`&&!!e}function i(e){return Array.isArray(e)?e:n(e)?[]:[e]}function a(e,t){if(t){let n=Object.keys(t);for(let r=0,i=n.length;r<i;r+=1){let i=n[r];e[i]=t[i]}}return e}function o(e,t){let n=``;for(let r=0;r<t;r+=1)n+=e;return n}function s(e){return e===0&&1/e==-1/0}t.exports.isNothing=n,t.exports.isObject=r,t.exports.toArray=i,t.exports.repeat=o,t.exports.isNegativeZero=s,t.exports.extend=a})),d=s(((e,t)=>{function n(e,t){let n=``,r=e.reason||`(unknown reason)`;return e.mark?(e.mark.name&&(n+=`in "`+e.mark.name+`" `),n+=`(`+(e.mark.line+1)+`:`+(e.mark.column+1)+`)`,!t&&e.mark.snippet&&(n+=`
|
||||
|
||||
`+e.mark.snippet),r+` `+n):r}function r(e,t){Error.call(this),this.name=`YAMLException`,this.reason=e,this.mark=t,this.message=n(this,!1),Error.captureStackTrace?Error.captureStackTrace(this,this.constructor):this.stack=Error().stack||``}r.prototype=Object.create(Error.prototype),r.prototype.constructor=r,r.prototype.toString=function(e){return this.name+`: `+n(this,e)},t.exports=r})),f=s(((e,t)=>{var n=u();function r(e,t,n,r,i){let a=``,o=``,s=Math.floor(i/2)-1;return r-t>s&&(a=` ... `,t=r-s+a.length),n-r>s&&(o=` ...`,n=r+s-o.length),{str:a+e.slice(t,n).replace(/\t/g,`→`)+o,pos:r-t+a.length}}function i(e,t){return n.repeat(` `,t-e.length)+e}function a(e,t){if(t=Object.create(t||null),!e.buffer)return null;t.maxLength||(t.maxLength=79),typeof t.indent!=`number`&&(t.indent=1),typeof t.linesBefore!=`number`&&(t.linesBefore=3),typeof t.linesAfter!=`number`&&(t.linesAfter=2);let a=/\r?\n|\r|\0/g,o=[0],s=[],c,l=-1;for(;c=a.exec(e.buffer);)s.push(c.index),o.push(c.index+c[0].length),e.position<=c.index&&l<0&&(l=o.length-2);l<0&&(l=o.length-1);let u=``,d=Math.min(e.line+t.linesAfter,s.length).toString().length,f=t.maxLength-(t.indent+d+3);for(let a=1;a<=t.linesBefore&&!(l-a<0);a++){let c=r(e.buffer,o[l-a],s[l-a],e.position-(o[l]-o[l-a]),f);u=n.repeat(` `,t.indent)+i((e.line-a+1).toString(),d)+` | `+c.str+`
|
||||
`+u}let p=r(e.buffer,o[l],s[l],e.position,f);u+=n.repeat(` `,t.indent)+i((e.line+1).toString(),d)+` | `+p.str+`
|
||||
`,u+=n.repeat(`-`,t.indent+d+3+p.pos)+`^
|
||||
`;for(let a=1;a<=t.linesAfter&&!(l+a>=s.length);a++){let c=r(e.buffer,o[l+a],s[l+a],e.position-(o[l]-o[l+a]),f);u+=n.repeat(` `,t.indent)+i((e.line+a+1).toString(),d)+` | `+c.str+`
|
||||
`}return u.replace(/\n$/,``)}t.exports=a})),p=s(((e,t)=>{var n=d(),r=[`kind`,`multi`,`resolve`,`construct`,`instanceOf`,`predicate`,`represent`,`representName`,`defaultStyle`,`styleAliases`],i=[`scalar`,`sequence`,`mapping`];function a(e){let t={};return e!==null&&Object.keys(e).forEach(function(n){e[n].forEach(function(e){t[String(e)]=n})}),t}function o(e,t){if(t=t||{},Object.keys(t).forEach(function(t){if(r.indexOf(t)===-1)throw new n(`Unknown option "`+t+`" is met in definition of "`+e+`" YAML type.`)}),this.options=t,this.tag=e,this.kind=t.kind||null,this.resolve=t.resolve||function(){return!0},this.construct=t.construct||function(e){return e},this.instanceOf=t.instanceOf||null,this.predicate=t.predicate||null,this.represent=t.represent||null,this.representName=t.representName||null,this.defaultStyle=t.defaultStyle||null,this.multi=t.multi||!1,this.styleAliases=a(t.styleAliases||null),i.indexOf(this.kind)===-1)throw new n(`Unknown kind "`+this.kind+`" is specified for "`+e+`" YAML type.`)}t.exports=o})),m=s(((e,t)=>{var n=d(),r=p();function i(e,t){let n=[];return e[t].forEach(function(e){let t=n.length;n.forEach(function(n,r){n.tag===e.tag&&n.kind===e.kind&&n.multi===e.multi&&(t=r)}),n[t]=e}),n}function a(){let e={scalar:{},sequence:{},mapping:{},fallback:{},multi:{scalar:[],sequence:[],mapping:[],fallback:[]}};function t(t){t.multi?(e.multi[t.kind].push(t),e.multi.fallback.push(t)):e[t.kind][t.tag]=e.fallback[t.tag]=t}for(let e=0,n=arguments.length;e<n;e+=1)arguments[e].forEach(t);return e}function o(e){return this.extend(e)}o.prototype.extend=function(e){let t=[],s=[];if(e instanceof r)s.push(e);else if(Array.isArray(e))s=s.concat(e);else if(e&&(Array.isArray(e.implicit)||Array.isArray(e.explicit)))e.implicit&&(t=t.concat(e.implicit)),e.explicit&&(s=s.concat(e.explicit));else throw new n(`Schema.extend argument should be a Type, [ Type ], or a schema definition ({ implicit: [...], explicit: [...] })`);t.forEach(function(e){if(!(e instanceof r))throw new n(`Specified list of YAML types (or a single Type object) contains a non-Type object.`);if(e.loadKind&&e.loadKind!==`scalar`)throw new n(`There is a non-scalar type in the implicit list of a schema. Implicit resolving of such types is not supported.`);if(e.multi)throw new n(`There is a multi type in the implicit list of a schema. Multi tags can only be listed as explicit.`)}),s.forEach(function(e){if(!(e instanceof r))throw new n(`Specified list of YAML types (or a single Type object) contains a non-Type object.`)});let c=Object.create(o.prototype);return c.implicit=(this.implicit||[]).concat(t),c.explicit=(this.explicit||[]).concat(s),c.compiledImplicit=i(c,`implicit`),c.compiledExplicit=i(c,`explicit`),c.compiledTypeMap=a(c.compiledImplicit,c.compiledExplicit),c},t.exports=o})),h=s(((e,t)=>{t.exports=new(p())(`tag:yaml.org,2002:str`,{kind:`scalar`,construct:function(e){return e===null?``:e}})})),g=s(((e,t)=>{t.exports=new(p())(`tag:yaml.org,2002:seq`,{kind:`sequence`,construct:function(e){return e===null?[]:e}})})),_=s(((e,t)=>{t.exports=new(p())(`tag:yaml.org,2002:map`,{kind:`mapping`,construct:function(e){return e===null?{}:e}})})),v=s(((e,t)=>{t.exports=new(m())({explicit:[h(),g(),_()]})})),y=s(((e,t)=>{var n=p();function r(e){if(e===null)return!0;let t=e.length;return t===1&&e===`~`||t===4&&(e===`null`||e===`Null`||e===`NULL`)}function i(){return null}function a(e){return e===null}t.exports=new n(`tag:yaml.org,2002:null`,{kind:`scalar`,resolve:r,construct:i,predicate:a,represent:{canonical:function(){return`~`},lowercase:function(){return`null`},uppercase:function(){return`NULL`},camelcase:function(){return`Null`},empty:function(){return``}},defaultStyle:`lowercase`})})),b=s(((e,t)=>{var n=p();function r(e){if(e===null)return!1;let t=e.length;return t===4&&(e===`true`||e===`True`||e===`TRUE`)||t===5&&(e===`false`||e===`False`||e===`FALSE`)}function i(e){return e===`true`||e===`True`||e===`TRUE`}function a(e){return Object.prototype.toString.call(e)===`[object Boolean]`}t.exports=new n(`tag:yaml.org,2002:bool`,{kind:`scalar`,resolve:r,construct:i,predicate:a,represent:{lowercase:function(e){return e?`true`:`false`},uppercase:function(e){return e?`TRUE`:`FALSE`},camelcase:function(e){return e?`True`:`False`}},defaultStyle:`lowercase`})})),x=s(((e,t)=>{var n=u(),r=p();function i(e){return e>=48&&e<=57||e>=65&&e<=70||e>=97&&e<=102}function a(e){return e>=48&&e<=55}function o(e){return e>=48&&e<=57}function s(e){if(e===null)return!1;let t=e.length,n=0,r=!1;if(!t)return!1;let s=e[n];if((s===`-`||s===`+`)&&(s=e[++n]),s===`0`){if(n+1===t)return!0;if(s=e[++n],s===`b`){for(n++;n<t;n++){if(s=e[n],s!==`0`&&s!==`1`)return!1;r=!0}return r&&Number.isFinite(c(e))}if(s===`x`){for(n++;n<t;n++){if(!i(e.charCodeAt(n)))return!1;r=!0}return r&&Number.isFinite(c(e))}if(s===`o`){for(n++;n<t;n++){if(!a(e.charCodeAt(n)))return!1;r=!0}return r&&Number.isFinite(c(e))}}for(;n<t;n++){if(!o(e.charCodeAt(n)))return!1;r=!0}return r?Number.isFinite(c(e)):!1}function c(e){let t=e
Line truncated
|
||||
\r`;function i(e){if(e===null)return!1;let t=0,n=e.length,i=r;for(let r=0;r<n;r++){let n=i.indexOf(e.charAt(r));if(!(n>64)){if(n<0)return!1;t+=6}}return t%8==0}function a(e){let t=e.replace(/[\r\n=]/g,``),n=t.length,i=r,a=0,o=[];for(let e=0;e<n;e++)e%4==0&&e&&(o.push(a>>16&255),o.push(a>>8&255),o.push(a&255)),a=a<<6|i.indexOf(t.charAt(e));let s=n%4*6;return s===0?(o.push(a>>16&255),o.push(a>>8&255),o.push(a&255)):s===18?(o.push(a>>10&255),o.push(a>>2&255)):s===12&&o.push(a>>4&255),new Uint8Array(o)}function o(e){let t=``,n=0,i=e.length,a=r;for(let r=0;r<i;r++)r%3==0&&r&&(t+=a[n>>18&63],t+=a[n>>12&63],t+=a[n>>6&63],t+=a[n&63]),n=(n<<8)+e[r];let o=i%3;return o===0?(t+=a[n>>18&63],t+=a[n>>12&63],t+=a[n>>6&63],t+=a[n&63]):o===2?(t+=a[n>>10&63],t+=a[n>>4&63],t+=a[n<<2&63],t+=a[64]):o===1&&(t+=a[n>>2&63],t+=a[n<<4&63],t+=a[64],t+=a[64]),t}function s(e){return Object.prototype.toString.call(e)===`[object Uint8Array]`}t.exports=new n(`tag:yaml.org,2002:binary`,{kind:`scalar`,resolve:i,construct:a,predicate:s,represent:o})})),O=s(((e,t)=>{var n=p(),r=Object.prototype.hasOwnProperty,i=Object.prototype.toString;function a(e){if(e===null)return!0;let t=[],n=e;for(let e=0,a=n.length;e<a;e+=1){let a=n[e],o=!1;if(i.call(a)!==`[object Object]`)return!1;let s;for(s in a)if(r.call(a,s))if(!o)o=!0;else return!1;if(!o)return!1;if(t.indexOf(s)===-1)t.push(s);else return!1}return!0}function o(e){return e===null?[]:e}t.exports=new n(`tag:yaml.org,2002:omap`,{kind:`sequence`,resolve:a,construct:o})})),k=s(((e,t)=>{var n=p(),r=Object.prototype.toString;function i(e){if(e===null)return!0;let t=e,n=Array(t.length);for(let e=0,i=t.length;e<i;e+=1){let i=t[e];if(r.call(i)!==`[object Object]`)return!1;let a=Object.keys(i);if(a.length!==1)return!1;n[e]=[a[0],i[a[0]]]}return!0}function a(e){if(e===null)return[];let t=e,n=Array(t.length);for(let e=0,r=t.length;e<r;e+=1){let r=t[e],i=Object.keys(r);n[e]=[i[0],r[i[0]]]}return n}t.exports=new n(`tag:yaml.org,2002:pairs`,{kind:`sequence`,resolve:i,construct:a})})),A=s(((e,t)=>{var n=p(),r=Object.prototype.hasOwnProperty;function i(e){if(e===null)return!0;let t=e;for(let e in t)if(r.call(t,e)&&t[e]!==null)return!1;return!0}function a(e){return e===null?{}:e}t.exports=new n(`tag:yaml.org,2002:set`,{kind:`mapping`,resolve:i,construct:a})})),ee=s(((e,t)=>{t.exports=w().extend({implicit:[T(),E()],explicit:[D(),O(),k(),A()]})})),j=s(((e,t)=>{var n=u(),r=d(),i=f(),a=ee(),o=Object.prototype.hasOwnProperty,s=1,c=2,l=3,p=4,m=1,h=2,g=3,_=/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x84\x86-\x9F\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/,v=/[\x85\u2028\u2029]/,y=/[,\[\]{}]/,b=/^(?:!|!!|![0-9A-Za-z-]+!)$/,x=/^(?:!|[^,\[\]{}])(?:%[0-9a-f]{2}|[0-9a-z\-#;/?:@&=+$,_.!~*'()\[\]])*$/i;function S(e){return Object.prototype.toString.call(e)}function C(e){return e===10||e===13}function w(e){return e===9||e===32}function T(e){return e===9||e===32||e===10||e===13}function E(e){return e===44||e===91||e===93||e===123||e===125}function D(e){if(e>=48&&e<=57)return e-48;let t=e|32;return t>=97&&t<=102?t-97+10:-1}function O(e){return e===120?2:e===117?4:e===85?8:0}function k(e){return e>=48&&e<=57?e-48:-1}function A(e){switch(e){case 48:return`\0`;case 97:return`\x07`;case 98:return`\b`;case 116:return` `;case 9:return` `;case 110:return`
|
||||
`;case 118:return`\v`;case 102:return`\f`;case 114:return`\r`;case 101:return`\x1B`;case 32:return` `;case 34:return`"`;case 47:return`/`;case 92:return`\\`;case 78:return`
`;case 95:return`\xA0`;case 76:return`\u2028`;case 80:return`\u2029`;default:return``}}function j(e){return e<=65535?String.fromCharCode(e):String.fromCharCode((e-65536>>10)+55296,(e-65536&1023)+56320)}function te(e,t,n){t===`__proto__`?Object.defineProperty(e,t,{configurable:!0,enumerable:!0,writable:!0,value:n}):e[t]=n}var M=Array(256),N=Array(256);for(let e=0;e<256;e++)M[e]=+!!A(e),N[e]=A(e);function ne(e,t){this.input=e,this.filename=t.filename||null,this.schema=t.schema||a,this.onWarning=t.onWarning||null,this.legacy=t.legacy||!1,this.json=t.json||!1,this.listener=t.listener||null,this.maxDepth=typeof t.maxDepth==`number`?t.maxDepth:100,this.maxMergeSeqLength=typeof t.maxMergeSeqLength==`number`?t.maxMergeSeqLength:20,this.implicitTypes=this.schema.compiledImplicit,this.typeMap=this.schema.compiledTypeMap,this.length=e.length,this.position=0,this.line=0,this.lineStart=0,this.lineIndent=0,this.depth=0,this.firstTabInLine=-1,this.documents=[],this.anchorMapTransactions=[]}function P(e,t){let n={name:e.filename,buffer:e.input.slice(0,-1),position:e.position,line:e.line,column:e.position-e.lineStart};return n.snippet=i(n),new r(t,n)}function F(e,t){throw P(e,t)}function I(e,t){e.onWarning&&e.onWarning.call(null,P(e,t))}function L(e,t,n){let r=e.anchorMapTransactions;if(r.length!==0){let n=r[r.length-1];o.call(n,t)||(n[t]={existed:o.call(e.anchorMap,t),value:e.anchorMap[t]})}e.anchorMap[t]=n}function R(e){e.anchorMapTransactions.push(Object.create(null))}function re(e){let t=e.anchorMapTransactions.pop(),n=e.anchorMapTransactions;if(n.length===0)return;let r=n[n.length-1],i=Object.keys(t);for(let e=0,n=i.length;e<n;e+=1){let n=i[e];o.call(r,n)||(r[n]=t[n])}}function z(e){let t=e.anchorMapTransactions.pop(),n=Object.keys(t);for(let r=n.length-1;r>=0;--r){let i=t[n[r]];i.existed?e.anchorMap[n[r]]=i.value:delete e.anchorMap[n[r]]}}function B(e){return{position:e.position,line:e.line,lineStart:e.lineStart,lineIndent:e.lineIndent,firstTabInLine:e.firstTabInLine,tag:e.tag,anchor:e.anchor,kind:e.kind,result:e.result}}function V(e,t){e.position=t.position,e.line=t.line,e.lineStart=t.lineStart,e.lineIndent=t.lineIndent,e.firstTabInLine=t.firstTabInLine,e.tag=t.tag,e.anchor=t.anchor,e.kind=t.kind,e.result=t.result}var H={YAML:function(e,t,n){e.version!==null&&F(e,`duplication of %YAML directive`),n.length!==1&&F(e,`YAML directive accepts exactly one argument`);let r=/^([0-9]+)\.([0-9]+)$/.exec(n[0]);r===null&&F(e,`ill-formed argument of the YAML directive`);let i=parseInt(r[1],10),a=parseInt(r[2],10);i!==1&&F(e,`unacceptable YAML version of the document`),e.version=n[0],e.checkLineBreaks=a<2,a!==1&&a!==2&&I(e,`unsupported YAML version of the document`)},TAG:function(e,t,n){let r;n.length!==2&&F(e,`TAG directive accepts exactly two arguments`);let i=n[0];r=n[1],b.test(i)||F(e,`ill-formed tag handle (first argument) of the TAG directive`),o.call(e.tagMap,i)&&F(e,`there is a previously declared suffix for "`+i+`" tag handle`),x.test(r)||F(e,`ill-formed tag prefix (second argument) of the TAG directive`);try{r=decodeURIComponent(r)}catch(t){F(e,`tag prefix is malformed: `+r)}e.tagMap[i]=r}};function U(e,t,n,r){if(t<n){let i=e.input.slice(t,n);if(r)for(let t=0,n=i.length;t<n;t+=1){let n=i.charCodeAt(t);n===9||n>=32&&n<=1114111||F(e,`expected valid JSON character`)}else _.test(i)&&F(e,`the stream contains non-printable characters`);e.result+=i}}function W(e,t,r,i){n.isObject(r)||F(e,`cannot merge mappings; the provided source object is unacceptable`);let a=Object.keys(r);for(let e=0,n=a.length;e<n;e+=1){let n=a[e];o.call(t,n)||(te(t,n,r[n]),i[n]=!0)}}function G(e,t,n,r,i,a,s,c,l){if(Array.isArray(i)){i=Array.prototype.slice.call(i);for(let t=0,n=i.length;t<n;t+=1)Array.isArray(i[t])&&F(e,`nested arrays are not supported inside keys`),typeof i==`object`&&S(i[t])===`[object Object]`&&(i[t]=`[object Object]`)}if(typeof i==`object`&&S(i)===`[object Object]`&&(i=`[object Object]`),i=String(i),t===null&&(t={}),r===`tag:yaml.org,2002:merge`)if(Array.isArray(a)){a.length>e.maxMergeSeqLength&&F(e,`merge sequence length exceeded maxMergeSeqLength (`+e.maxMergeSeqLength+`)`);let r=new Set;for(let i=0,o=a.length;i<o;i+=1){let o=a[i];r.has(o)||(r.add(o),W(e,t,o,n))}}else W(e,t,a,n);else !e.json&&!o.call(n,i)&&o.call(t,i)&&(e.line=s||e.line,e.lineStart=c||e.lineStart,e.position=l||e.position,F(e,`duplicated mapping key`)),te(t,i,a),delete n[i];return t}function K(e){let t=e.input.charCodeAt(e.position);t===10?e.position++:t===13?(e.position++,e.input.charCodeAt(e.position)===10&&e.position++):F(e,`a line break is expected`),e.line+=1,e.lineStart=e.position,e.firstTabInLine=-1}function q(e,t,n){let r=0,i=e.input.charCodeAt(e.position);for(;i!==0;){for(;w(i);)i===9&&e.firstTabInLine===-1&&(e.firstTabInLine=e.position),i=e.input.charCodeAt(++e.position);if(t&&i===35)d
Line truncated
|
||||
`,t-1))}function ie(e,t,n){let r,i,a,o,s,c,l=e.kind,u=e.result,d=e.input.charCodeAt(e.position);if(T(d)||E(d)||d===35||d===38||d===42||d===33||d===124||d===62||d===39||d===34||d===37||d===64||d===96)return!1;if(d===63||d===45){let t=e.input.charCodeAt(e.position+1);if(T(t)||n&&E(t))return!1}for(e.kind=`scalar`,e.result=``,r=i=e.position,a=!1;d!==0;){if(d===58){let t=e.input.charCodeAt(e.position+1);if(T(t)||n&&E(t))break}else if(d===35){if(T(e.input.charCodeAt(e.position-1)))break}else if(e.position===e.lineStart&&J(e)||n&&E(d))break;else if(C(d))if(o=e.line,s=e.lineStart,c=e.lineIndent,q(e,!1,-1),e.lineIndent>=t){a=!0,d=e.input.charCodeAt(e.position);continue}else{e.position=i,e.line=o,e.lineStart=s,e.lineIndent=c;break}a&&(U(e,r,i,!1),Y(e,e.line-o),r=i=e.position,a=!1),w(d)||(i=e.position+1),d=e.input.charCodeAt(++e.position)}return U(e,r,i,!1),e.result?!0:(e.kind=l,e.result=u,!1)}function X(e,t){let n,r,i=e.input.charCodeAt(e.position);if(i!==39)return!1;for(e.kind=`scalar`,e.result=``,e.position++,n=r=e.position;(i=e.input.charCodeAt(e.position))!==0;)if(i===39)if(U(e,n,e.position,!0),i=e.input.charCodeAt(++e.position),i===39)n=e.position,e.position++,r=e.position;else return!0;else C(i)?(U(e,n,r,!0),Y(e,q(e,!1,t)),n=r=e.position):e.position===e.lineStart&&J(e)?F(e,`unexpected end of the document within a single quoted scalar`):(e.position++,w(i)||(r=e.position));F(e,`unexpected end of the stream within a single quoted scalar`)}function ae(e,t){let n,r,i,a=e.input.charCodeAt(e.position);if(a!==34)return!1;for(e.kind=`scalar`,e.result=``,e.position++,n=r=e.position;(a=e.input.charCodeAt(e.position))!==0;)if(a===34)return U(e,n,e.position,!0),e.position++,!0;else if(a===92){if(U(e,n,e.position,!0),a=e.input.charCodeAt(++e.position),C(a))q(e,!1,t);else if(a<256&&M[a])e.result+=N[a],e.position++;else if((i=O(a))>0){let t=i,n=0;for(;t>0;t--)a=e.input.charCodeAt(++e.position),(i=D(a))>=0?n=(n<<4)+i:F(e,`expected hexadecimal character`);e.result+=j(n),e.position++}else F(e,`unknown escape sequence`);n=r=e.position}else C(a)?(U(e,n,r,!0),Y(e,q(e,!1,t)),n=r=e.position):e.position===e.lineStart&&J(e)?F(e,`unexpected end of the document within a double quoted scalar`):(e.position++,w(a)||(r=e.position));F(e,`unexpected end of the stream within a double quoted scalar`)}function oe(e,t){let n=!0,r,i,a,o=e.tag,c,l=e.anchor,u,d,f,p,m=Object.create(null),h,g,_,v=e.input.charCodeAt(e.position);if(v===91)u=93,p=!1,c=[];else if(v===123)u=125,p=!0,c={};else return!1;for(e.anchor!==null&&L(e,e.anchor,c),v=e.input.charCodeAt(++e.position);v!==0;){if(q(e,!0,t),v=e.input.charCodeAt(e.position),v===u)return e.position++,e.tag=o,e.anchor=l,e.kind=p?`mapping`:`sequence`,e.result=c,!0;n?v===44&&F(e,`expected the node content, but found ','`):F(e,`missed comma between flow collection entries`),g=h=_=null,d=f=!1,v===63&&T(e.input.charCodeAt(e.position+1))&&(d=f=!0,e.position++,q(e,!0,t)),r=e.line,i=e.lineStart,a=e.position,Q(e,t,s,!1,!0),g=e.tag,h=e.result,q(e,!0,t),v=e.input.charCodeAt(e.position),(f||e.line===r)&&v===58&&(d=!0,v=e.input.charCodeAt(++e.position),q(e,!0,t),Q(e,t,s,!1,!0),_=e.result),p?G(e,c,m,g,h,_,r,i,a):d?c.push(G(e,null,m,g,h,_,r,i,a)):c.push(h),q(e,!0,t),v=e.input.charCodeAt(e.position),v===44?(n=!0,v=e.input.charCodeAt(++e.position)):n=!1}F(e,`unexpected end of the stream within a flow collection`)}function Z(e,t){let r,i=m,a=!1,o=!1,s=t,c=0,l=!1,u,d=e.input.charCodeAt(e.position);if(d===124)r=!1;else if(d===62)r=!0;else return!1;for(e.kind=`scalar`,e.result=``;d!==0;)if(d=e.input.charCodeAt(++e.position),d===43||d===45)m===i?i=d===43?g:h:F(e,`repeat of a chomping mode identifier`);else if((u=k(d))>=0)u===0?F(e,`bad explicit indentation width of a block scalar; it cannot be less than one`):o?F(e,`repeat of an indentation width identifier`):(s=t+u-1,o=!0);else break;if(w(d)){do d=e.input.charCodeAt(++e.position);while(w(d));if(d===35)do d=e.input.charCodeAt(++e.position);while(!C(d)&&d!==0)}for(;d!==0;){for(K(e),e.lineIndent=0,d=e.input.charCodeAt(e.position);(!o||e.lineIndent<s)&&d===32;)e.lineIndent++,d=e.input.charCodeAt(++e.position);if(!o&&e.lineIndent>s&&(s=e.lineIndent),C(d)){c++;continue}if(!o&&s===0&&F(e,`missing indentation for block scalar`),e.lineIndent<s){i===g?e.result+=n.repeat(`
|
||||
`,a?1+c:c):i===m&&a&&(e.result+=`
|
||||
`);break}r?w(d)?(l=!0,e.result+=n.repeat(`
|
||||
`,a?1+c:c)):l?(l=!1,e.result+=n.repeat(`
|
||||
`,c+1)):c===0?a&&(e.result+=` `):e.result+=n.repeat(`
|
||||
`,c):e.result+=n.repeat(`
|
||||
`,a?1+c:c),a=!0,o=!0,c=0;let t=e.position;for(;!C(d)&&d!==0;)d=e.input.charCodeAt(++e.position);U(e,t,e.position,!1)}return!0}function se(e,t){let n=e.tag,r=e.anchor,i=[],a=!1;if(e.firstTabInLine!==-1)return!1;e.anchor!==null&&L(e,e.anchor,i);let o=e.input.charCodeAt(e.position);for(;o!==0&&(e.firstTabInLine!==-1&&(e.position=e.firstTabInLine,F(e,`tab characters must not be used in indentation`)),!(o!==45||!T(e.input.charCodeAt(e.position+1))));){if(a=!0,e.position++,q(e,!0,-1)&&e.lineIndent<=t){i.push(null),o=e.input.charCodeAt(e.position);continue}let n=e.line;if(Q(e,t,l,!1,!0),i.push(e.result),q(e,!0,-1),o=e.input.charCodeAt(e.position),(e.line===n||e.lineIndent>t)&&o!==0)F(e,`bad indentation of a sequence entry`);else if(e.lineIndent<t)break}return a?(e.tag=n,e.anchor=r,e.kind=`sequence`,e.result=i,!0):!1}function ce(e,t,n){let r,i,a,o,s=e.tag,l=e.anchor,u={},d=Object.create(null),f=null,m=null,h=null,g=!1,_=!1;if(e.firstTabInLine!==-1)return!1;e.anchor!==null&&L(e,e.anchor,u);let v=e.input.charCodeAt(e.position);for(;v!==0;){!g&&e.firstTabInLine!==-1&&(e.position=e.firstTabInLine,F(e,`tab characters must not be used in indentation`));let y=e.input.charCodeAt(e.position+1),b=e.line;if((v===63||v===58)&&T(y))v===63?(g&&(G(e,u,d,f,m,null,i,a,o),f=m=h=null),_=!0,g=!0,r=!0):g?(g=!1,r=!0):F(e,`incomplete explicit mapping pair; a key node is missed; or followed by a non-tabulated empty line`),e.position+=1,v=y;else{if(i=e.line,a=e.lineStart,o=e.position,!Q(e,n,c,!1,!0))break;if(e.line===b){for(v=e.input.charCodeAt(e.position);w(v);)v=e.input.charCodeAt(++e.position);if(v===58)v=e.input.charCodeAt(++e.position),T(v)||F(e,`a whitespace character is expected after the key-value separator within a block mapping`),g&&(G(e,u,d,f,m,null,i,a,o),f=m=h=null),_=!0,g=!1,r=!1,f=e.tag,m=e.result;else if(_)F(e,`can not read an implicit mapping pair; a colon is missed`);else return e.tag=s,e.anchor=l,!0}else if(_)F(e,`can not read a block mapping entry; a multiline key may not be an implicit key`);else return e.tag=s,e.anchor=l,!0}if((e.line===b||e.lineIndent>t)&&(g&&(i=e.line,a=e.lineStart,o=e.position),Q(e,t,p,!0,r)&&(g?m=e.result:h=e.result),g||(G(e,u,d,f,m,h,i,a,o),f=m=h=null),q(e,!0,-1),v=e.input.charCodeAt(e.position)),(e.line===b||e.lineIndent>t)&&v!==0)F(e,`bad indentation of a mapping entry`);else if(e.lineIndent<t)break}return g&&G(e,u,d,f,m,null,i,a,o),_&&(e.tag=s,e.anchor=l,e.kind=`mapping`,e.result=u),_}function le(e){let t=!1,n=!1,r,i,a=e.input.charCodeAt(e.position);if(a!==33)return!1;e.tag!==null&&F(e,`duplication of a tag property`),a=e.input.charCodeAt(++e.position),a===60?(t=!0,a=e.input.charCodeAt(++e.position)):a===33?(n=!0,r=`!!`,a=e.input.charCodeAt(++e.position)):r=`!`;let s=e.position;if(t){do a=e.input.charCodeAt(++e.position);while(a!==0&&a!==62);e.position<e.length?(i=e.input.slice(s,e.position),a=e.input.charCodeAt(++e.position)):F(e,`unexpected end of the stream within a verbatim tag`)}else{for(;a!==0&&!T(a);)a===33&&(n?F(e,`tag suffix cannot contain exclamation marks`):(r=e.input.slice(s-1,e.position+1),b.test(r)||F(e,`named tag handle cannot contain such characters`),n=!0,s=e.position+1)),a=e.input.charCodeAt(++e.position);i=e.input.slice(s,e.position),y.test(i)&&F(e,`tag suffix cannot contain flow indicator characters`)}i&&!x.test(i)&&F(e,`tag name cannot contain such characters: `+i);try{i=decodeURIComponent(i)}catch(t){F(e,`tag name is malformed: `+i)}return t?e.tag=i:o.call(e.tagMap,r)?e.tag=e.tagMap[r]+i:r===`!`?e.tag=`!`+i:r===`!!`?e.tag=`tag:yaml.org,2002:`+i:F(e,`undeclared tag handle "`+r+`"`),!0}function ue(e){let t=e.input.charCodeAt(e.position);if(t!==38)return!1;e.anchor!==null&&F(e,`duplication of an anchor property`),t=e.input.charCodeAt(++e.position);let n=e.position;for(;t!==0&&!T(t)&&!E(t);)t=e.input.charCodeAt(++e.position);return e.position===n&&F(e,`name of an anchor node must contain at least one character`),e.anchor=e.input.slice(n,e.position),!0}function de(e){let t=e.input.charCodeAt(e.position);if(t!==42)return!1;t=e.input.charCodeAt(++e.position);let n=e.position;for(;t!==0&&!T(t)&&!E(t);)t=e.input.charCodeAt(++e.position);e.position===n&&F(e,`name of an alias node must contain at least one character`);let r=e.input.slice(n,e.position);return o.call(e.anchorMap,r)||F(e,`unidentified alias "`+r+`"`),e.result=e.anchorMap[r],q(e,!0,-1),!0}function fe(e,t,n,r){let i=B(e);return R(e),V(e,t),e.tag=null,e.anchor=null,e.kind=null,e.result=null,ce(e,n,r)&&e.kind===`mapping`?(re(e),!0):(z(e),V(e,i),!1)}function Q(e,t,n,r,i){let a,u,d=1,f=!1,m=!1,h=null,g,_,v;e.depth>=e.maxDepth&&F(e,`nesting exceeded maxDepth (`+e.maxDepth+`)`),e.depth+=1,e.listener!==null&&e.listener(`open`,e),e.tag=null,e.anchor=null,e.kind=null,e.result=null;let y=a=u=p===n||l===n;if(r&&q(e,!0,-1)&&(f=!0,e.lineIndent>t?d=1:e.lineIndent===t?d=0:e.lineIndent<t&&(d=-1)),d===1)for(;;){let n=e.input.charCodeAt(e.position),r=B(e);if(f&&(n===33&&e.tag!==null||n===38&&e.anchor!==null)||!le(e)&&!ue(e))break;h===nul
Line truncated
|
||||
`),e.charCodeAt(0)===65279&&(e=e.slice(1)));let n=new ne(e,t),r=e.indexOf(`\0`);for(r!==-1&&(n.position=r,F(n,`null byte is not allowed in input`)),n.input+=`\0`;n.input.charCodeAt(n.position)===32;)n.lineIndent+=1,n.position+=1;for(;n.position<n.length-1;)pe(n);return n.documents}function he(e,t,n){typeof t==`object`&&t&&n===void 0&&(n=t,t=null);let r=me(e,n);if(typeof t!=`function`)return r;for(let e=0,n=r.length;e<n;e+=1)t(r[e])}function ge(e,t){let n=me(e,t);if(n.length!==0){if(n.length===1)return n[0];throw new r(`expected a single document in the stream, but found more`)}}t.exports.loadAll=he,t.exports.load=ge})),te=s(((e,t)=>{var n=u(),r=d(),i=ee(),a=Object.prototype.toString,o=Object.prototype.hasOwnProperty,s=65279,c=9,l=10,f=13,p=32,m=33,h=34,g=35,_=37,v=38,y=39,b=42,x=44,S=45,C=58,w=61,T=62,E=63,D=64,O=91,k=93,A=96,j=123,te=124,M=125,N={};N[0]=`\\0`,N[7]=`\\a`,N[8]=`\\b`,N[9]=`\\t`,N[10]=`\\n`,N[11]=`\\v`,N[12]=`\\f`,N[13]=`\\r`,N[27]=`\\e`,N[34]=`\\"`,N[92]=`\\\\`,N[133]=`\\N`,N[160]=`\\_`,N[8232]=`\\L`,N[8233]=`\\P`;var ne=[`y`,`Y`,`yes`,`Yes`,`YES`,`on`,`On`,`ON`,`n`,`N`,`no`,`No`,`NO`,`off`,`Off`,`OFF`],P=/^[-+]?[0-9_]+(?::[0-9_]+)+(?:\.[0-9_]*)?$/;function F(e,t){if(t===null)return{};let n={},r=Object.keys(t);for(let i=0,a=r.length;i<a;i+=1){let a=r[i],s=String(t[a]);a.slice(0,2)===`!!`&&(a=`tag:yaml.org,2002:`+a.slice(2));let c=e.compiledTypeMap.fallback[a];c&&o.call(c.styleAliases,s)&&(s=c.styleAliases[s]),n[a]=s}return n}function I(e){let t,i,a=e.toString(16).toUpperCase();if(e<=255)t=`x`,i=2;else if(e<=65535)t=`u`,i=4;else if(e<=4294967295)t=`U`,i=8;else throw new r(`code point within a string may not be greater than 0xFFFFFFFF`);return`\\`+t+n.repeat(`0`,i-a.length)+a}var L=1,R=2;function re(e){this.schema=e.schema||i,this.indent=Math.max(1,e.indent||2),this.noArrayIndent=e.noArrayIndent||!1,this.skipInvalid=e.skipInvalid||!1,this.flowLevel=n.isNothing(e.flowLevel)?-1:e.flowLevel,this.styleMap=F(this.schema,e.styles||null),this.sortKeys=e.sortKeys||!1,this.lineWidth=e.lineWidth||80,this.noRefs=e.noRefs||!1,this.noCompatMode=e.noCompatMode||!1,this.condenseFlow=e.condenseFlow||!1,this.quotingType=e.quotingType===`"`?R:L,this.forceQuotes=e.forceQuotes||!1,this.replacer=typeof e.replacer==`function`?e.replacer:null,this.implicitTypes=this.schema.compiledImplicit,this.explicitTypes=this.schema.compiledExplicit,this.tag=null,this.result=``,this.duplicates=[],this.usedDuplicates=null}function z(e,t){let r=n.repeat(` `,t),i=0,a=``,o=e.length;for(;i<o;){let t,n=e.indexOf(`
|
||||
`,i);n===-1?(t=e.slice(i),i=o):(t=e.slice(i,n+1),i=n+1),t.length&&t!==`
|
||||
`&&(a+=r),a+=t}return a}function B(e,t){return`
|
||||
`+n.repeat(` `,e.indent*t)}function V(e,t){for(let n=0,r=e.implicitTypes.length;n<r;n+=1)if(e.implicitTypes[n].resolve(t))return!0;return!1}function H(e){return e===p||e===c}function U(e){return e>=32&&e<=126||e>=161&&e<=55295&&e!==8232&&e!==8233||e>=57344&&e<=65533&&e!==s||e>=65536&&e<=1114111}function W(e){return U(e)&&e!==s&&e!==f&&e!==l}function G(e,t,n){let r=W(e),i=r&&!H(e);return(n?r:r&&e!==x&&e!==O&&e!==k&&e!==j&&e!==M)&&e!==g&&!(t===C&&!i)||W(t)&&!H(t)&&e===g||t===C&&i}function K(e){return U(e)&&e!==s&&!H(e)&&e!==S&&e!==E&&e!==C&&e!==x&&e!==O&&e!==k&&e!==j&&e!==M&&e!==g&&e!==v&&e!==b&&e!==m&&e!==te&&e!==w&&e!==T&&e!==y&&e!==h&&e!==_&&e!==D&&e!==A}function q(e){return!H(e)&&e!==C}function J(e,t){let n=e.charCodeAt(t),r;return n>=55296&&n<=56319&&t+1<e.length&&(r=e.charCodeAt(t+1),r>=56320&&r<=57343)?(n-55296)*1024+r-56320+65536:n}function Y(e){return/^\n* /.test(e)}var ie=1,X=2,ae=3,oe=4,Z=5;function se(e,t,n,r,i,a,o,s){let c,u=0,d=null,f=!1,p=!1,m=r!==-1,h=-1,g=K(J(e,0))&&q(J(e,e.length-1));if(t||o)for(c=0;c<e.length;u>=65536?c+=2:c++){if(u=J(e,c),!U(u))return Z;g=g&&G(u,d,s),d=u}else{for(c=0;c<e.length;u>=65536?c+=2:c++){if(u=J(e,c),u===l)f=!0,m&&(p=p||c-h-1>r&&e[h+1]!==` `,h=c);else if(!U(u))return Z;g=g&&G(u,d,s),d=u}p=p||m&&c-h-1>r&&e[h+1]!==` `}return!f&&!p?g&&!o&&!i(e)?ie:a===R?Z:X:n>9&&Y(e)?Z:o?a===R?Z:X:p?oe:ae}function ce(e,t,n,i,a){e.dump=function(){if(t.length===0)return e.quotingType===R?`""`:`''`;if(!e.noCompatMode&&(ne.indexOf(t)!==-1||P.test(t)))return e.quotingType===R?`"`+t+`"`:`'`+t+`'`;let o=e.indent*Math.max(1,n),s=e.lineWidth===-1?-1:Math.max(Math.min(e.lineWidth,40),e.lineWidth-o),c=i||e.flowLevel>-1&&n>=e.flowLevel;function l(t){return V(e,t)}switch(se(t,c,e.indent,s,l,e.quotingType,e.forceQuotes&&!i,a)){case ie:return t;case X:return`'`+t.replace(/'/g,`''`)+`'`;case ae:return`|`+le(t,e.indent)+ue(z(t,o));case oe:return`>`+le(t,e.indent)+ue(z(de(t,s),o));case Z:return`"`+Q(t,s)+`"`;default:throw new r(`impossible error: invalid scalar style`)}}()}function le(e,t){let n=Y(e)?String(t):``,r=e[e.length-1]===`
|
||||
`;return n+(r&&(e[e.length-2]===`
|
||||
`||e===`
|
||||
`)?`+`:r?``:`-`)+`
|
||||
`}function ue(e){return e[e.length-1]===`
|
||||
`?e.slice(0,-1):e}function de(e,t){let n=/(\n+)([^\n]*)/g,r=function(){let r=e.indexOf(`
|
||||
`);return r=r===-1?e.length:r,n.lastIndex=r,fe(e.slice(0,r),t)}(),i=e[0]===`
|
||||
`||e[0]===` `,a,o;for(;o=n.exec(e);){let e=o[1],n=o[2];a=n[0]===` `,r+=e+(!i&&!a&&n!==``?`
|
||||
`:``)+fe(n,t),i=a}return r}function fe(e,t){if(e===``||e[0]===` `)return e;let n=/ [^ ]/g,r,i=0,a,o=0,s=0,c=``;for(;r=n.exec(e);)s=r.index,s-i>t&&(a=o>i?o:s,c+=`
|
||||
`+e.slice(i,a),i=a+1),o=s;return c+=`
|
||||
`,e.length-i>t&&o>i?c+=e.slice(i,o)+`
|
||||
`+e.slice(o+1):c+=e.slice(i),c.slice(1)}function Q(e){let t=``,n=0;for(let r=0;r<e.length;n>=65536?r+=2:r++){n=J(e,r);let i=N[n];!i&&U(n)?(t+=e[r],n>=65536&&(t+=e[r+1])):t+=i||I(n)}return t}function pe(e,t,n){let r=``,i=e.tag;for(let i=0,a=n.length;i<a;i+=1){let a=n[i];e.replacer&&(a=e.replacer.call(n,String(i),a)),($(e,t,a,!1,!1)||a===void 0&&$(e,t,null,!1,!1))&&(r!==``&&(r+=`,`+(e.condenseFlow?``:` `)),r+=e.dump)}e.tag=i,e.dump=`[`+r+`]`}function me(e,t,n,r){let i=``,a=e.tag;for(let a=0,o=n.length;a<o;a+=1){let o=n[a];e.replacer&&(o=e.replacer.call(n,String(a),o)),($(e,t+1,o,!0,!0,!1,!0)||o===void 0&&$(e,t+1,null,!0,!0,!1,!0))&&((!r||i!==``)&&(i+=B(e,t)),e.dump&&l===e.dump.charCodeAt(0)?i+=`-`:i+=`- `,i+=e.dump)}e.tag=a,e.dump=i||`[]`}function he(e,t,n){let r=``,i=e.tag,a=Object.keys(n);for(let i=0,o=a.length;i<o;i+=1){let o=``;r!==``&&(o+=`, `),e.condenseFlow&&(o+=`"`);let s=a[i],c=n[s];e.replacer&&(c=e.replacer.call(n,s,c)),$(e,t,s,!1,!1)&&(e.dump.length>1024&&(o+=`? `),o+=e.dump+(e.condenseFlow?`"`:``)+`:`+(e.condenseFlow?``:` `),$(e,t,c,!1,!1)&&(o+=e.dump,r+=o))}e.tag=i,e.dump=`{`+r+`}`}function ge(e,t,n,i){let a=``,o=e.tag,s=Object.keys(n);if(e.sortKeys===!0)s.sort();else if(typeof e.sortKeys==`function`)s.sort(e.sortKeys);else if(e.sortKeys)throw new r(`sortKeys must be a boolean or a function`);for(let r=0,o=s.length;r<o;r+=1){let o=``;(!i||a!==``)&&(o+=B(e,t));let c=s[r],u=n[c];if(e.replacer&&(u=e.replacer.call(n,c,u)),!$(e,t+1,c,!0,!0,!0))continue;let d=e.tag!==null&&e.tag!==`?`||e.dump&&e.dump.length>1024;d&&(e.dump&&l===e.dump.charCodeAt(0)?o+=`?`:o+=`? `),o+=e.dump,d&&(o+=B(e,t)),$(e,t+1,u,!0,d)&&(e.dump&&l===e.dump.charCodeAt(0)?o+=`:`:o+=`: `,o+=e.dump,a+=o)}e.tag=o,e.dump=a||`{}`}function _e(e,t,n){let i=n?e.explicitTypes:e.implicitTypes;for(let s=0,c=i.length;s<c;s+=1){let c=i[s];if((c.instanceOf||c.predicate)&&(!c.instanceOf||typeof t==`object`&&t instanceof c.instanceOf)&&(!c.predicate||c.predicate(t))){if(n?c.multi&&c.representName?e.tag=c.representName(t):e.tag=c.tag:e.tag=`?`,c.represent){let n=e.styleMap[c.tag]||c.defaultStyle,i;if(a.call(c.represent)===`[object Function]`)i=c.represent(t,n);else if(o.call(c.represent,n))i=c.represent[n](t,n);else throw new r(`!<`+c.tag+`> tag resolver accepts not "`+n+`" style`);e.dump=i}return!0}}return!1}function $(e,t,n,i,o,s,c){e.tag=null,e.dump=n,_e(e,n,!1)||_e(e,n,!0);let l=a.call(e.dump),u=i;i&&(i=e.flowLevel<0||e.flowLevel>t);let d=l===`[object Object]`||l===`[object Array]`,f,p;if(d&&(f=e.duplicates.indexOf(n),p=f!==-1),(e.tag!==null&&e.tag!==`?`||p||e.indent!==2&&t>0)&&(o=!1),p&&e.usedDuplicates[f])e.dump=`*ref_`+f;else{if(d&&p&&!e.usedDuplicates[f]&&(e.usedDuplicates[f]=!0),l===`[object Object]`)i&&Object.keys(e.dump).length!==0?(ge(e,t,e.dump,o),p&&(e.dump=`&ref_`+f+e.dump)):(he(e,t,e.dump),p&&(e.dump=`&ref_`+f+` `+e.dump));else if(l===`[object Array]`)i&&e.dump.length!==0?(e.noArrayIndent&&!c&&t>0?me(e,t-1,e.dump,o):me(e,t,e.dump,o),p&&(e.dump=`&ref_`+f+e.dump)):(pe(e,t,e.dump),p&&(e.dump=`&ref_`+f+` `+e.dump));else if(l===`[object String]`)e.tag!==`?`&&ce(e,e.dump,t,s,u);else if(l===`[object Undefined]`)return!1;else{if(e.skipInvalid)return!1;throw new r(`unacceptable kind of an object to dump `+l)}if(e.tag!==null&&e.tag!==`?`){let t=encodeURI(e.tag[0]===`!`?e.tag.slice(1):e.tag).replace(/!/g,`%21`);t=e.tag[0]===`!`?`!`+t:t.slice(0,18)===`tag:yaml.org,2002:`?`!!`+t.slice(18):`!<`+t+`>`,e.dump=t+` `+e.dump}}return!0}function ve(e,t){let n=[],r=[];ye(e,n,r);let i=r.length;for(let e=0;e<i;e+=1)t.duplicates.push(n[r[e]]);t.usedDuplicates=Array(i)}function ye(e,t,n){if(typeof e==`object`&&e){let r=t.indexOf(e);if(r!==-1)n.indexOf(r)===-1&&n.push(r);else if(t.push(e),Array.isArray(e))for(let r=0,i=e.length;r<i;r+=1)ye(e[r],t,n);else{let r=Object.keys(e);for(let i=0,a=r.length;i<a;i+=1)ye(e[r[i]],t,n)}}}function be(e,t){t=t||{};let n=new re(t);n.noRefs||ve(e,n);let r=e;return n.replacer&&(r=n.replacer.call({"":r},``,r)),$(n,0,r,!0,!0)?n.dump+`
|
||||
`:``}t.exports.dump=be})),M=l(s(((e,t)=>{var n=j(),r=te();function i(e,t){return function(){throw Error(`Function yaml.`+e+` is removed in js-yaml 4. Use yaml.`+t+` instead, which is now safe by default.`)}}t.exports.Type=p(),t.exports.Schema=m(),t.exports.FAILSAFE_SCHEMA=v(),t.exports.JSON_SCHEMA=C(),t.exports.CORE_SCHEMA=w(),t.exports.DEFAULT_SCHEMA=ee(),t.exports.load=n.load,t.exports.loadAll=n.loadAll,t.exports.dump=r.dump,t.exports.YAMLException=d(),t.exports.types={binary:D(),float:S(),map:_(),null:y(),pairs:k(),set:A(),timestamp:T(),bool:b(),int:x(),merge:E(),omap:O(),seq:g(),str:h()},t.exports.safeLoad=i(`safeLoad`,`load`),t.exports.safeLoadAll=i(`safeLoadAll`,`loadAll`),t.exports.safeDump=i(`safeDump`,`dump`)}))(),1),{Type:N,Schema:ne,FAILSAFE_SCHEMA:P,JSON_SCHEMA:F,CORE_SCHEMA:I,DEFAULT_SCHEMA:L,load:R,loadAll:re,dump:z,YAMLException:B,types:V,safeLoad:H,safeLoadAll:U,safeDump:W}=M.default,G=M.default;e.CORE_SCHEMA=I,e.DEFAULT_SCHEMA=L,e.FAILSAFE_SCHEMA=P,e.JSON_SCHEMA=F,e.Schema=ne,e.Type=N,e.YAMLException=B,e.default=G,e.dump=z,e.load=R,e.loadAll=re,e.safeDump=W,e.safeLoad=H,e.safeLoadAll=U,e.types=V});
|
||||
//# sourceMappingURL=js-yaml.min.js.map
|
||||
@@ -421,6 +421,182 @@ msgstr ""
|
||||
msgid "Starting…"
|
||||
msgstr ""
|
||||
|
||||
#: dae.js
|
||||
msgid "Name is required"
|
||||
msgstr ""
|
||||
|
||||
#: dae.js
|
||||
msgid "Group name must be unique"
|
||||
msgstr ""
|
||||
|
||||
#: dae.js
|
||||
msgid "Updating…"
|
||||
msgstr ""
|
||||
|
||||
#: dae.js
|
||||
msgid "Subscriptions updated (dae reloaded)"
|
||||
msgstr ""
|
||||
|
||||
#: dae.js
|
||||
msgid "Save manual config"
|
||||
msgstr ""
|
||||
|
||||
#: dae.js
|
||||
msgid "Start failed: %s"
|
||||
msgstr ""
|
||||
|
||||
#: converter.js
|
||||
msgid "Subscription Converter"
|
||||
msgstr ""
|
||||
|
||||
#: converter.js
|
||||
msgid "Convert Clash YAML into share links, preview the result, then import selected nodes into dae or daed. Inputs and credentials are not saved."
|
||||
msgstr ""
|
||||
|
||||
#: converter.js
|
||||
msgid "1. Input Clash YAML"
|
||||
msgstr ""
|
||||
|
||||
#: converter.js
|
||||
msgid "Fetch and parse"
|
||||
msgstr ""
|
||||
|
||||
#: converter.js
|
||||
msgid "Or paste Clash YAML here"
|
||||
msgstr ""
|
||||
|
||||
#: converter.js
|
||||
msgid "Parse pasted YAML"
|
||||
msgstr ""
|
||||
|
||||
#: converter.js
|
||||
msgid "2. Conversion Preview"
|
||||
msgstr ""
|
||||
|
||||
#: converter.js
|
||||
msgid "Select compatible new nodes"
|
||||
msgstr ""
|
||||
|
||||
#: converter.js
|
||||
msgid "Clear selection"
|
||||
msgstr ""
|
||||
|
||||
#: converter.js
|
||||
msgid "Filter name or protocol"
|
||||
msgstr ""
|
||||
|
||||
#: converter.js
|
||||
msgid "3. Import Selected Nodes"
|
||||
msgstr ""
|
||||
|
||||
#: converter.js
|
||||
msgid "Target backend"
|
||||
msgstr ""
|
||||
|
||||
#: converter.js
|
||||
msgid "Import selected nodes (%d)"
|
||||
msgstr ""
|
||||
|
||||
#: converter.js
|
||||
msgid "Detected %d · compatible %d · duplicates %d · incompatible %d"
|
||||
msgstr ""
|
||||
|
||||
#: converter.js
|
||||
msgid "Ready to import"
|
||||
msgstr ""
|
||||
|
||||
#: converter.js
|
||||
msgid "Already exists, skipped"
|
||||
msgstr ""
|
||||
|
||||
#: converter.js
|
||||
msgid "Sign in to daed"
|
||||
msgstr ""
|
||||
|
||||
#: converter.js
|
||||
msgid "Credentials are used only for this import and are not saved."
|
||||
msgstr ""
|
||||
|
||||
#: converter.js
|
||||
msgid "Sign in and import"
|
||||
msgstr ""
|
||||
|
||||
#: converter.js
|
||||
#: converter.js
|
||||
msgid "YAML parser failed to load"
|
||||
msgstr ""
|
||||
|
||||
#: converter.js
|
||||
msgid "daed returned HTTP %s"
|
||||
msgstr ""
|
||||
|
||||
#: converter.js
|
||||
msgid "Username"
|
||||
msgstr ""
|
||||
|
||||
#: converter.js
|
||||
msgid "Password"
|
||||
msgstr ""
|
||||
|
||||
#: converter.js
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
#: converter.js
|
||||
msgid "Import cancelled"
|
||||
msgstr ""
|
||||
|
||||
#: converter.js
|
||||
msgid "Import selected nodes"
|
||||
msgstr ""
|
||||
|
||||
#: converter.js
|
||||
msgid "No YAML parsed yet"
|
||||
msgstr ""
|
||||
|
||||
#: converter.js
|
||||
msgid "YAML parse failed: %s"
|
||||
msgstr ""
|
||||
|
||||
#: converter.js
|
||||
msgid "No top-level proxies list was found"
|
||||
msgstr ""
|
||||
|
||||
#: converter.js
|
||||
msgid "Conversion preview is ready"
|
||||
msgstr ""
|
||||
|
||||
#: converter.js
|
||||
msgid "Enter an HTTP or HTTPS subscription URL"
|
||||
msgstr ""
|
||||
|
||||
#: converter.js
|
||||
msgid "Fetching subscription…"
|
||||
msgstr ""
|
||||
|
||||
#: converter.js
|
||||
msgid "Fetch failed"
|
||||
msgstr ""
|
||||
|
||||
#: converter.js
|
||||
msgid "Fetch failed: %s"
|
||||
msgstr ""
|
||||
|
||||
#: converter.js
|
||||
msgid "Paste Clash YAML first"
|
||||
msgstr ""
|
||||
|
||||
#: converter.js
|
||||
msgid "or"
|
||||
msgstr ""
|
||||
|
||||
#: converter.js
|
||||
msgid "Importing selected nodes…"
|
||||
msgstr ""
|
||||
|
||||
#: converter.js
|
||||
msgid "Import failed: %s"
|
||||
msgstr ""
|
||||
|
||||
msgid "Import complete: added %d, duplicates %d, failed %d"
|
||||
msgstr ""
|
||||
@@ -689,6 +689,21 @@ msgstr "已保存并应用"
|
||||
msgid "Saved"
|
||||
msgstr "已保存"
|
||||
|
||||
msgid "Name is required"
|
||||
msgstr "名称不能为空"
|
||||
|
||||
msgid "Group name must be unique"
|
||||
msgstr "分组名称必须唯一"
|
||||
|
||||
msgid "Updating…"
|
||||
msgstr "更新中…"
|
||||
|
||||
msgid "Subscriptions updated (dae reloaded)"
|
||||
msgstr "订阅已更新(dae 已重载)"
|
||||
|
||||
msgid "Save manual config"
|
||||
msgstr "保存手动配置"
|
||||
|
||||
msgid "Saved · started"
|
||||
msgstr "已保存并启动"
|
||||
|
||||
@@ -697,3 +712,121 @@ msgstr "启动中…"
|
||||
|
||||
msgid "Start failed: %s"
|
||||
msgstr "启动失败:%s"
|
||||
|
||||
# ---- converter.js ----
|
||||
msgid "Subscription Converter"
|
||||
msgstr "订阅转换"
|
||||
|
||||
msgid "Convert Clash YAML into share links, preview the result, then import selected nodes into dae or daed. Inputs and credentials are not saved."
|
||||
msgstr "将 Clash YAML 转换为分享链接,预览后把所选节点导入 dae 或 daed。输入内容和凭据不会保存。"
|
||||
|
||||
msgid "1. Input Clash YAML"
|
||||
msgstr "1. 输入 Clash YAML"
|
||||
|
||||
msgid "Fetch and parse"
|
||||
msgstr "获取并解析"
|
||||
|
||||
msgid "Or paste Clash YAML here"
|
||||
msgstr "或在此粘贴 Clash YAML"
|
||||
|
||||
msgid "Parse pasted YAML"
|
||||
msgstr "解析粘贴内容"
|
||||
|
||||
msgid "2. Conversion Preview"
|
||||
msgstr "2. 转换预览"
|
||||
|
||||
msgid "Select compatible new nodes"
|
||||
msgstr "选择可导入的新节点"
|
||||
|
||||
msgid "Clear selection"
|
||||
msgstr "清空选择"
|
||||
|
||||
msgid "Filter name or protocol"
|
||||
msgstr "筛选节点名称或协议"
|
||||
|
||||
msgid "3. Import Selected Nodes"
|
||||
msgstr "3. 导入所选节点"
|
||||
|
||||
msgid "Target backend"
|
||||
msgstr "目标后端"
|
||||
|
||||
msgid "Import selected nodes (%d)"
|
||||
msgstr "导入所选节点(%d)"
|
||||
|
||||
msgid "Detected %d · compatible %d · duplicates %d · incompatible %d"
|
||||
msgstr "检测到 %d 个 · 可导入 %d 个 · 重复 %d 个 · 不兼容 %d 个"
|
||||
|
||||
msgid "Ready to import"
|
||||
msgstr "可导入"
|
||||
|
||||
msgid "Already exists, skipped"
|
||||
msgstr "已存在,跳过"
|
||||
|
||||
msgid "Sign in to daed"
|
||||
msgstr "登录 daed"
|
||||
|
||||
msgid "Credentials are used only for this import and are not saved."
|
||||
msgstr "凭据仅用于本次导入,不会保存。"
|
||||
|
||||
msgid "Sign in and import"
|
||||
msgstr "登录并导入"
|
||||
|
||||
msgid "YAML parser failed to load"
|
||||
msgstr "YAML 解析器加载失败"
|
||||
|
||||
msgid "daed returned HTTP %s"
|
||||
msgstr "daed 返回 HTTP %s"
|
||||
|
||||
msgid "Username"
|
||||
msgstr "用户名"
|
||||
|
||||
msgid "Password"
|
||||
msgstr "密码"
|
||||
|
||||
msgid "Cancel"
|
||||
msgstr "取消"
|
||||
|
||||
msgid "Import cancelled"
|
||||
msgstr "导入已取消"
|
||||
|
||||
msgid "Import selected nodes"
|
||||
msgstr "导入所选节点"
|
||||
|
||||
msgid "No YAML parsed yet"
|
||||
msgstr "尚未解析 YAML"
|
||||
|
||||
msgid "YAML parse failed: %s"
|
||||
msgstr "YAML 解析失败:%s"
|
||||
|
||||
msgid "No top-level proxies list was found"
|
||||
msgstr "未找到顶层 proxies 列表"
|
||||
|
||||
msgid "Conversion preview is ready"
|
||||
msgstr "转换预览已就绪"
|
||||
|
||||
msgid "Enter an HTTP or HTTPS subscription URL"
|
||||
msgstr "请输入 HTTP 或 HTTPS 订阅链接"
|
||||
|
||||
msgid "Fetching subscription…"
|
||||
msgstr "获取订阅中…"
|
||||
|
||||
msgid "Fetch failed"
|
||||
msgstr "获取失败"
|
||||
|
||||
msgid "Fetch failed: %s"
|
||||
msgstr "获取失败:%s"
|
||||
|
||||
msgid "Paste Clash YAML first"
|
||||
msgstr "请先粘贴 Clash YAML"
|
||||
|
||||
msgid "or"
|
||||
msgstr "或"
|
||||
|
||||
msgid "Importing selected nodes…"
|
||||
msgstr "导入所选节点中…"
|
||||
|
||||
msgid "Import failed: %s"
|
||||
msgstr "导入失败:%s"
|
||||
|
||||
msgid "Import complete: added %d, duplicates %d, failed %d"
|
||||
msgstr "导入完成:新增 %d,重复 %d,失败 %d"
|
||||
@@ -374,14 +374,8 @@ msgstr "自动滚动"
|
||||
msgid "Pause"
|
||||
msgstr "暂停"
|
||||
|
||||
msgid "All"
|
||||
msgstr "全部"
|
||||
|
||||
msgid "Node Status"
|
||||
msgstr "节点状态"
|
||||
|
||||
msgid "Proxy Traffic"
|
||||
msgstr "代理流量"
|
||||
msgid "Filter (substring)"
|
||||
msgstr "过滤(子串)"
|
||||
|
||||
msgid "Clear View"
|
||||
msgstr "清空显示"
|
||||
@@ -436,14 +430,227 @@ msgid "Edit config DSL — subscriptions, nodes, routing, DNS. Load template via
|
||||
msgstr "编辑 dae DSL 配置——订阅、节点、路由、DNS。通过「从示例初始化」载入模板。保存前务必替换占位订阅链接。图形化管理请切换至 daed。"
|
||||
|
||||
# ---- config.js: Proxy Health ----
|
||||
msgid "Check Proxy Status"
|
||||
msgstr "检测代理状态"
|
||||
msgid "Test YouTube"
|
||||
msgstr "测试 YouTube"
|
||||
|
||||
msgid "OK, %d flows through proxy"
|
||||
msgstr "正常,%d 条代理流量"
|
||||
msgid "Testing…"
|
||||
msgstr "测试中…"
|
||||
|
||||
msgid "No proxy traffic"
|
||||
msgstr "暂无代理流量"
|
||||
msgid "YouTube reachable · %d ms"
|
||||
msgstr "YouTube 可访问 · %d ms"
|
||||
|
||||
msgid "YouTube unreachable (timeout)"
|
||||
msgstr "YouTube 无法访问(超时)"
|
||||
|
||||
msgid "YouTube unreachable (HTTP %s)"
|
||||
msgstr "YouTube 无法访问(HTTP %s)"
|
||||
|
||||
# ---- config.js: dae friendly form ----
|
||||
msgid "Subscriptions"
|
||||
msgstr "订阅"
|
||||
|
||||
msgid "Airport / subscription links. dae resolves them into the node pool."
|
||||
msgstr "机场 / 订阅链接,dae 会解析成节点池里的节点。"
|
||||
|
||||
msgid "Tag"
|
||||
msgstr "标签"
|
||||
|
||||
msgid "Subscription URL"
|
||||
msgstr "订阅链接"
|
||||
|
||||
msgid "URL is required"
|
||||
msgstr "订阅链接不能为空"
|
||||
|
||||
msgid "Must start with http(s):// or file://"
|
||||
msgstr "需以 http(s):// 或 file:// 开头"
|
||||
|
||||
msgid "Enabled"
|
||||
msgstr "启用"
|
||||
|
||||
msgid "Nodes"
|
||||
msgstr "节点"
|
||||
|
||||
msgid "Single share links (ss / vmess / vless / trojan / tuic / hysteria2 / socks5 …)."
|
||||
msgstr "每行添加一个节点分享链接,支持 ss、vmess、vless、trojan、tuic、hysteria2、socks5。"
|
||||
|
||||
msgid "Share Link"
|
||||
msgstr "分享链接"
|
||||
|
||||
msgid "Groups"
|
||||
msgstr "分组"
|
||||
|
||||
msgid "Outbound groups. Leave the source empty to use all nodes. Set the route fallback to one of these."
|
||||
msgstr "出站分组。来源留空表示用全部节点。路由兜底要指向其中一个分组。"
|
||||
|
||||
msgid "Name"
|
||||
msgstr "名称"
|
||||
|
||||
msgid "Policy"
|
||||
msgstr "策略"
|
||||
|
||||
msgid "Min moving average latency"
|
||||
msgstr "最小移动平均延迟"
|
||||
|
||||
msgid "Min last latency"
|
||||
msgstr "最小最近延迟"
|
||||
|
||||
msgid "Min average of last 10"
|
||||
msgstr "最近 10 次最小均值"
|
||||
|
||||
msgid "Random"
|
||||
msgstr "随机"
|
||||
|
||||
msgid "Fixed (first node)"
|
||||
msgstr "固定(第一个节点)"
|
||||
|
||||
msgid "Source"
|
||||
msgstr "来源"
|
||||
|
||||
msgid "Subscriptions and nodes that feed this group. Pick from the list or type a name. Leave empty to use all nodes."
|
||||
msgstr "进入这个分组的订阅和节点。从列表里选,或手输名称。留空=用全部节点。"
|
||||
|
||||
msgid "subscription"
|
||||
msgstr "订阅"
|
||||
|
||||
msgid "node"
|
||||
msgstr "节点"
|
||||
|
||||
msgid "Name filter"
|
||||
msgstr "名称筛选"
|
||||
|
||||
msgid "Optional. Narrows subscriptions in the source to nodes whose name matches — e.g. 香港 or 新加坡|日本. Nodes you picked by name are always kept."
|
||||
msgstr "可选。只对来源里的订阅做收窄,留下名称匹配的节点,如 香港 或 新加坡|日本;你手动挑的单个节点始终保留。"
|
||||
|
||||
msgid "Routing"
|
||||
msgstr "路由"
|
||||
|
||||
msgid "Private IPs direct"
|
||||
msgstr "私网 IP 直连"
|
||||
|
||||
msgid "LAN / private addresses bypass the proxy."
|
||||
msgstr "局域网 / 私有地址不走代理。"
|
||||
|
||||
msgid "China direct"
|
||||
msgstr "国内直连"
|
||||
|
||||
msgid "China mainland IPs and domains bypass the proxy."
|
||||
msgstr "中国大陆 IP 和域名不走代理。"
|
||||
|
||||
msgid "Block ads"
|
||||
msgstr "拦截广告"
|
||||
|
||||
msgid "Drop traffic matching the ad domain list."
|
||||
msgstr "丢弃命中广告域名表的流量。"
|
||||
|
||||
msgid "Fallback group"
|
||||
msgstr "兜底分组"
|
||||
|
||||
msgid "Default outbound for everything else."
|
||||
msgstr "其余流量的默认出站。"
|
||||
|
||||
msgid "Custom rules"
|
||||
msgstr "自定义规则"
|
||||
|
||||
msgid "Raw dae routing lines, evaluated before fallback. Target must be a group name above (or direct/block)."
|
||||
msgstr "原始 dae 路由行,在兜底前生效。箭头右边要填上面的分组名(或 direct / block)。"
|
||||
|
||||
msgid "China upstream"
|
||||
msgstr "国内 DNS 上游"
|
||||
|
||||
msgid "Resolves China-mainland domains."
|
||||
msgstr "解析中国大陆域名。"
|
||||
|
||||
msgid "Fallback upstream"
|
||||
msgstr "兜底 DNS 上游"
|
||||
|
||||
msgid "Resolves everything else."
|
||||
msgstr "解析其余域名。"
|
||||
|
||||
msgid "Add a subscription or node, then save — it takes effect automatically."
|
||||
msgstr "填好订阅或节点,点保存就自动生效。"
|
||||
|
||||
msgid "Apply failed: %s"
|
||||
msgstr "应用失败:%s"
|
||||
|
||||
msgid "Saved · validated · hot-reloaded"
|
||||
msgstr "已保存 · 已校验 · 已热重载"
|
||||
|
||||
msgid "Please fix the highlighted fields."
|
||||
msgstr "请先修正高亮的字段。"
|
||||
|
||||
msgid "Import from existing config"
|
||||
msgstr "从现有配置导入"
|
||||
|
||||
msgid "Existing config detected"
|
||||
msgstr "检测到已有配置"
|
||||
|
||||
msgid "You have a hand-written config.dae. Import its subscriptions and nodes into the form, or keep editing manually below. Saving the form overwrites config.dae."
|
||||
msgstr "你已有手写的 config.dae。可把里面的订阅和节点导入表单,或在下方继续手动编辑。表单保存会覆盖 config.dae。"
|
||||
|
||||
msgid "Importing…"
|
||||
msgstr "导入中…"
|
||||
|
||||
msgid "Imported, reloading…"
|
||||
msgstr "已导入,正在刷新…"
|
||||
|
||||
msgid "Import failed"
|
||||
msgstr "导入失败"
|
||||
|
||||
msgid "Advanced / Manual Mode"
|
||||
msgstr "高级 / 手动模式"
|
||||
|
||||
msgid "Edit config.dae directly. Saving the form above regenerates the file and overwrites changes made here."
|
||||
msgstr "直接编辑 config.dae。上方表单保存会重新生成文件并覆盖这里的改动。"
|
||||
|
||||
msgid "Update Subscriptions"
|
||||
msgstr "更新订阅"
|
||||
|
||||
msgid "Re-fetch all airport subscriptions (reloads dae)"
|
||||
msgstr "重新拉取所有机场订阅(重载 dae)"
|
||||
|
||||
msgid "Updating subscriptions…"
|
||||
msgstr "更新订阅中…"
|
||||
|
||||
msgid "dae is stopped; it fetches subscriptions on start."
|
||||
msgstr "dae 未运行,启动时会自动拉取订阅。"
|
||||
|
||||
msgid "Update failed: %s"
|
||||
msgstr "更新失败:%s"
|
||||
|
||||
msgid "Subscriptions updated (dae reloaded)"
|
||||
msgstr "订阅已更新(dae 已重载)"
|
||||
|
||||
msgid "Section"
|
||||
msgstr "区块"
|
||||
|
||||
msgid "DNS"
|
||||
msgstr "DNS"
|
||||
|
||||
msgid "dae config file is empty. Click \"Initialize from example\" to start, or paste your config here."
|
||||
msgstr "dae 配置文件为空。点击「从示例初始化」开始,或直接在此粘贴你的配置。"
|
||||
|
||||
# ---- log.js: filter dropdown ----
|
||||
msgid "All"
|
||||
msgstr "全部"
|
||||
|
||||
msgid "Node Status"
|
||||
msgstr "节点状态"
|
||||
|
||||
msgid "Proxy Traffic"
|
||||
msgstr "代理流量"
|
||||
|
||||
|
||||
msgid "Logging"
|
||||
msgstr "日志"
|
||||
|
||||
msgid "Save manual config"
|
||||
msgstr "保存手动配置"
|
||||
|
||||
msgid "Save and Apply"
|
||||
msgstr "保存并应用"
|
||||
|
||||
msgid "Fixed link — nothing to fetch."
|
||||
msgstr "固定链接,无需更新。"
|
||||
|
||||
# ---- dae.js: i18n cleanup (was Chinese msgid) ----
|
||||
msgid "One node share link per line — ss, vmess, vless, trojan, tuic, hysteria2, socks5."
|
||||
@@ -470,9 +677,6 @@ msgstr "高级设置"
|
||||
msgid "auto-generated"
|
||||
msgstr "自动生成"
|
||||
|
||||
msgid "Save and Apply"
|
||||
msgstr "保存并应用"
|
||||
|
||||
msgid "Save config"
|
||||
msgstr "保存配置"
|
||||
|
||||
@@ -485,6 +689,21 @@ msgstr "已保存并应用"
|
||||
msgid "Saved"
|
||||
msgstr "已保存"
|
||||
|
||||
msgid "Name is required"
|
||||
msgstr "名称不能为空"
|
||||
|
||||
msgid "Group name must be unique"
|
||||
msgstr "分组名称必须唯一"
|
||||
|
||||
msgid "Updating…"
|
||||
msgstr "更新中…"
|
||||
|
||||
msgid "Subscriptions updated (dae reloaded)"
|
||||
msgstr "订阅已更新(dae 已重载)"
|
||||
|
||||
msgid "Save manual config"
|
||||
msgstr "保存手动配置"
|
||||
|
||||
msgid "Saved · started"
|
||||
msgstr "已保存并启动"
|
||||
|
||||
@@ -493,3 +712,121 @@ msgstr "启动中…"
|
||||
|
||||
msgid "Start failed: %s"
|
||||
msgstr "启动失败:%s"
|
||||
|
||||
# ---- converter.js ----
|
||||
msgid "Subscription Converter"
|
||||
msgstr "订阅转换"
|
||||
|
||||
msgid "Convert Clash YAML into share links, preview the result, then import selected nodes into dae or daed. Inputs and credentials are not saved."
|
||||
msgstr "将 Clash YAML 转换为分享链接,预览后把所选节点导入 dae 或 daed。输入内容和凭据不会保存。"
|
||||
|
||||
msgid "1. Input Clash YAML"
|
||||
msgstr "1. 输入 Clash YAML"
|
||||
|
||||
msgid "Fetch and parse"
|
||||
msgstr "获取并解析"
|
||||
|
||||
msgid "Or paste Clash YAML here"
|
||||
msgstr "或在此粘贴 Clash YAML"
|
||||
|
||||
msgid "Parse pasted YAML"
|
||||
msgstr "解析粘贴内容"
|
||||
|
||||
msgid "2. Conversion Preview"
|
||||
msgstr "2. 转换预览"
|
||||
|
||||
msgid "Select compatible new nodes"
|
||||
msgstr "选择可导入的新节点"
|
||||
|
||||
msgid "Clear selection"
|
||||
msgstr "清空选择"
|
||||
|
||||
msgid "Filter name or protocol"
|
||||
msgstr "筛选节点名称或协议"
|
||||
|
||||
msgid "3. Import Selected Nodes"
|
||||
msgstr "3. 导入所选节点"
|
||||
|
||||
msgid "Target backend"
|
||||
msgstr "目标后端"
|
||||
|
||||
msgid "Import selected nodes (%d)"
|
||||
msgstr "导入所选节点(%d)"
|
||||
|
||||
msgid "Detected %d · compatible %d · duplicates %d · incompatible %d"
|
||||
msgstr "检测到 %d 个 · 可导入 %d 个 · 重复 %d 个 · 不兼容 %d 个"
|
||||
|
||||
msgid "Ready to import"
|
||||
msgstr "可导入"
|
||||
|
||||
msgid "Already exists, skipped"
|
||||
msgstr "已存在,跳过"
|
||||
|
||||
msgid "Sign in to daed"
|
||||
msgstr "登录 daed"
|
||||
|
||||
msgid "Credentials are used only for this import and are not saved."
|
||||
msgstr "凭据仅用于本次导入,不会保存。"
|
||||
|
||||
msgid "Sign in and import"
|
||||
msgstr "登录并导入"
|
||||
|
||||
msgid "YAML parser failed to load"
|
||||
msgstr "YAML 解析器加载失败"
|
||||
|
||||
msgid "daed returned HTTP %s"
|
||||
msgstr "daed 返回 HTTP %s"
|
||||
|
||||
msgid "Username"
|
||||
msgstr "用户名"
|
||||
|
||||
msgid "Password"
|
||||
msgstr "密码"
|
||||
|
||||
msgid "Cancel"
|
||||
msgstr "取消"
|
||||
|
||||
msgid "Import cancelled"
|
||||
msgstr "导入已取消"
|
||||
|
||||
msgid "Import selected nodes"
|
||||
msgstr "导入所选节点"
|
||||
|
||||
msgid "No YAML parsed yet"
|
||||
msgstr "尚未解析 YAML"
|
||||
|
||||
msgid "YAML parse failed: %s"
|
||||
msgstr "YAML 解析失败:%s"
|
||||
|
||||
msgid "No top-level proxies list was found"
|
||||
msgstr "未找到顶层 proxies 列表"
|
||||
|
||||
msgid "Conversion preview is ready"
|
||||
msgstr "转换预览已就绪"
|
||||
|
||||
msgid "Enter an HTTP or HTTPS subscription URL"
|
||||
msgstr "请输入 HTTP 或 HTTPS 订阅链接"
|
||||
|
||||
msgid "Fetching subscription…"
|
||||
msgstr "获取订阅中…"
|
||||
|
||||
msgid "Fetch failed"
|
||||
msgstr "获取失败"
|
||||
|
||||
msgid "Fetch failed: %s"
|
||||
msgstr "获取失败:%s"
|
||||
|
||||
msgid "Paste Clash YAML first"
|
||||
msgstr "请先粘贴 Clash YAML"
|
||||
|
||||
msgid "or"
|
||||
msgstr "或"
|
||||
|
||||
msgid "Importing selected nodes…"
|
||||
msgstr "导入所选节点中…"
|
||||
|
||||
msgid "Import failed: %s"
|
||||
msgstr "导入失败:%s"
|
||||
|
||||
msgid "Import complete: added %d, duplicates %d, failed %d"
|
||||
msgstr "导入完成:新增 %d,重复 %d,失败 %d"
|
||||
@@ -0,0 +1,37 @@
|
||||
#!/bin/sh
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
set -eu
|
||||
|
||||
URL="${1:-}"
|
||||
MAX_BYTES=5242880
|
||||
FETCH_BIN="${DAEDE_FETCH_BIN:-uclient-fetch}"
|
||||
|
||||
case "$URL" in
|
||||
http://*|https://*) ;;
|
||||
*)
|
||||
echo "Subscription URL must use HTTP or HTTPS" >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
|
||||
TMP="$(mktemp /tmp/daede-clash-yaml.XXXXXX)"
|
||||
trap 'rm -f "$TMP"' EXIT INT TERM
|
||||
chmod 600 "$TMP"
|
||||
|
||||
if ! "$FETCH_BIN" -q -T 20 -U "ClashMeta" -O "$TMP" "$URL"; then
|
||||
echo "Failed to fetch subscription" >&2
|
||||
exit 3
|
||||
fi
|
||||
|
||||
SIZE="$(wc -c <"$TMP" | tr -d ' ')"
|
||||
if [ "$SIZE" -eq 0 ]; then
|
||||
echo "Subscription response is empty" >&2
|
||||
exit 4
|
||||
fi
|
||||
if [ "$SIZE" -gt "$MAX_BYTES" ]; then
|
||||
echo "Subscription response is too large (maximum 5 MiB)" >&2
|
||||
exit 5
|
||||
fi
|
||||
|
||||
cat "$TMP"
|
||||
@@ -17,9 +17,17 @@
|
||||
"path": "daede/config"
|
||||
}
|
||||
},
|
||||
"admin/services/daede/converter": {
|
||||
"title": "Subscription Converter",
|
||||
"order": 20,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "daede/converter"
|
||||
}
|
||||
},
|
||||
"admin/services/daede/updates": {
|
||||
"title": "Updates",
|
||||
"order": 20,
|
||||
"order": 30,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "daede/updates"
|
||||
@@ -27,7 +35,7 @@
|
||||
},
|
||||
"admin/services/daede/log": {
|
||||
"title": "Log",
|
||||
"order": 30,
|
||||
"order": 40,
|
||||
"action": {
|
||||
"type": "view",
|
||||
"path": "daede/log"
|
||||
|
||||
@@ -65,6 +65,7 @@
|
||||
"/usr/share/luci-app-daede/update-pkg.sh dae": [ "exec" ],
|
||||
"/usr/share/luci-app-daede/update-pkg.sh daed": [ "exec" ],
|
||||
"/usr/share/luci-app-daede/update-pkg.sh luci-app-daede": [ "exec" ],
|
||||
"/usr/share/luci-app-daede/fetch-clash-yaml.sh *": [ "exec" ],
|
||||
"/usr/share/luci-app-daede/gen-dae-config.sh generate": [ "exec" ],
|
||||
"/usr/share/luci-app-daede/gen-dae-config.sh import": [ "exec" ]
|
||||
},
|
||||
|
||||
Reference in new issue
Block a user