mirror of
https://github.com/anticensority/runet-censorship-bypass.git
synced 2024-11-27 20:03:45 +03:00
Add error catching, viewing and reporting via sentry
This commit is contained in:
parent
6750872ea5
commit
38ac7450a6
|
@ -4,7 +4,6 @@
|
||||||
|
|
||||||
const handlersState = function(key, value) {
|
const handlersState = function(key, value) {
|
||||||
|
|
||||||
console.log(key, value, '!');
|
|
||||||
key = 'handlers-' + key;
|
key = 'handlers-' + key;
|
||||||
if (value === null) {
|
if (value === null) {
|
||||||
return localStorage.removeItem(key);
|
return localStorage.removeItem(key);
|
||||||
|
@ -21,6 +20,7 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
const ifPrefix = 'if-on-';
|
const ifPrefix = 'if-on-';
|
||||||
|
const extName = chrome.runtime.getManifest().name;
|
||||||
|
|
||||||
window.apis.errorHandlers = {
|
window.apis.errorHandlers = {
|
||||||
|
|
||||||
|
@ -67,29 +67,19 @@
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
};
|
idToErr: {},
|
||||||
|
|
||||||
}
|
mayNotify(
|
||||||
|
id, title, errOrMessage,
|
||||||
// INIT
|
|
||||||
chrome.proxy.settings.get(
|
|
||||||
{},
|
|
||||||
(details) => window.apis.errorHandlers.isNotControlled(details)
|
|
||||||
);
|
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
const extName = chrome.runtime.getManifest().name;
|
|
||||||
|
|
||||||
const mayNotify = function(
|
|
||||||
id, title, message,
|
|
||||||
icon = 'default-128.png',
|
icon = 'default-128.png',
|
||||||
context = extName
|
context = extName
|
||||||
) {
|
) {
|
||||||
|
|
||||||
if ( !window.apis.errorHandlers.isOn(id) ) {
|
if ( !this.isOn(id) ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
this.idToErr[id] = errOrMessage;
|
||||||
|
const message = errOrMessage.message || errOrMessage.toString();
|
||||||
chrome.notifications.create(
|
chrome.notifications.create(
|
||||||
id,
|
id,
|
||||||
{
|
{
|
||||||
|
@ -103,31 +93,66 @@ chrome.proxy.settings.get(
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
};
|
},
|
||||||
|
|
||||||
window.addEventListener('error', (err) => {
|
installListenersOn(win, name, cb) {
|
||||||
|
|
||||||
console.warn('GLOBAL ERROR', err);
|
win.addEventListener('error', (errEvent) => {
|
||||||
mayNotify('ext-error', 'Unhandled error', JSON.stringify(err),
|
|
||||||
'ext-error-128.png');
|
console.warn(name + ':GLOBAL ERROR', errEvent);
|
||||||
|
this.mayNotify('ext-error', 'Ошибка расширения', errEvent,
|
||||||
|
'ext-error-128.png');
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
win.addEventListener('unhandledrejection', (event) => {
|
||||||
|
|
||||||
|
console.warn(name + ':Unhandled rejection. Throwing error.');
|
||||||
|
event.preventDefault();
|
||||||
|
throw event.reason;
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
if (cb) {
|
||||||
|
// setTimeout changes error context.
|
||||||
|
setTimeout(cb, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
const handlers = window.apis.errorHandlers;
|
||||||
|
|
||||||
|
// INIT
|
||||||
|
chrome.proxy.settings.get(
|
||||||
|
{},
|
||||||
|
(details) => handlers.isNotControlled(details)
|
||||||
|
);
|
||||||
|
|
||||||
|
chrome.notifications.onClicked.addListener( function(notId) {
|
||||||
|
|
||||||
|
chrome.notifications.clear(notId);
|
||||||
|
if(notId === 'no-control') {
|
||||||
|
return chrome.tabs.create({active: true, url: 'chrome://settings/#proxy'});
|
||||||
|
}
|
||||||
|
chrome.tabs.create({active: true, url: './pages/view-error/index.html#' + notId});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
window.addEventListener('unhandledrejection', (event) => {
|
handlers.installListenersOn(window, 'BG');
|
||||||
|
|
||||||
console.warn('Unhandled rejection. Throwing error.');
|
|
||||||
event.preventDefault();
|
|
||||||
throw event.reason;
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
chrome.proxy.onProxyError.addListener((details) => {
|
chrome.proxy.onProxyError.addListener((details) => {
|
||||||
|
|
||||||
if (window.apis.errorHandlers.ifNoControl) {
|
if (handlers.ifNoControl) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
console.warn('PAC ERROR', details);
|
console.warn('PAC ERROR', details);
|
||||||
mayNotify('pac-error', ' PAC !', JSON.stringify(details),
|
handlers.mayNotify('pac-error', 'Ошибка PAC!', details,
|
||||||
'pac-error-128.png' );
|
'pac-error-128.png' );
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -136,8 +161,9 @@ chrome.proxy.settings.get(
|
||||||
|
|
||||||
console.log('Proxy settings changed.', details);
|
console.log('Proxy settings changed.', details);
|
||||||
const noCon = 'no-control';
|
const noCon = 'no-control';
|
||||||
if ( window.apis.errorHandlers.isNotControlled(details) ) {
|
if ( handlers.isNotControlled(details) ) {
|
||||||
mayNotify(noCon, 'Proxy changed', JSON.stringify(details),
|
console.log(details);
|
||||||
|
handlers.mayNotify(noCon, 'Прокси контролирует другое расширение', details,
|
||||||
'no-control-128.png');
|
'no-control-128.png');
|
||||||
} else {
|
} else {
|
||||||
chrome.notifications.clear( noCon );
|
chrome.notifications.clear( noCon );
|
||||||
|
|
|
@ -99,7 +99,7 @@
|
||||||
|
|
||||||
_periodicUpdateAlarmReason: 'Периодичное обновление PAC-скрипта Антизапрет',
|
_periodicUpdateAlarmReason: 'Периодичное обновление PAC-скрипта Антизапрет',
|
||||||
|
|
||||||
pushToStorage(cb) {
|
pushToStorageAsync(cb) {
|
||||||
|
|
||||||
console.log('Pushing to storage...');
|
console.log('Pushing to storage...');
|
||||||
|
|
||||||
|
@ -143,7 +143,7 @@
|
||||||
},
|
},
|
||||||
*/
|
*/
|
||||||
|
|
||||||
syncWithPacProvider(key, cb) {
|
syncWithPacProviderAsync(key, cb) {
|
||||||
|
|
||||||
if( !key || typeof(key) === 'function' ) {
|
if( !key || typeof(key) === 'function' ) {
|
||||||
cb = key;
|
cb = key;
|
||||||
|
@ -200,7 +200,7 @@
|
||||||
if (pacErr && ipsErr) {
|
if (pacErr && ipsErr) {
|
||||||
return cb(pacErr, pacRes);
|
return cb(pacErr, pacRes);
|
||||||
}
|
}
|
||||||
this.pushToStorage(
|
this.pushToStorageAsync(
|
||||||
(pushErr) => cb(pacErr || ipsErr || pushErr, pacRes)
|
(pushErr) => cb(pacErr || ipsErr || pushErr, pacRes)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -239,21 +239,21 @@
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
installPac(key, cb) {
|
installPacAsync(key, cb) {
|
||||||
|
|
||||||
console.log('Installing PAC...');
|
console.log('Installing PAC...');
|
||||||
if (!key) {
|
if (!key) {
|
||||||
throw new Error('Key must be defined.');
|
throw new Error('Key must be defined.');
|
||||||
}
|
}
|
||||||
if (this.currentProviderKey !== key) {
|
if (this.currentProviderKey !== key) {
|
||||||
return this.syncWithPacProvider(key, cb);
|
return this.syncWithPacProviderAsync(key, cb);
|
||||||
}
|
}
|
||||||
console.log(key + ' already installed.');
|
console.log(key + ' already installed.');
|
||||||
cb();
|
cb();
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
clearPac(cb) {
|
clearPacAsync(cb) {
|
||||||
|
|
||||||
cb = asyncLogGroup('Cearing alarms and PAC...', cb);
|
cb = asyncLogGroup('Cearing alarms and PAC...', cb);
|
||||||
chrome.alarms.clearAll(
|
chrome.alarms.clearAll(
|
||||||
|
@ -266,7 +266,7 @@
|
||||||
return cb(err);
|
return cb(err);
|
||||||
}
|
}
|
||||||
this.currentPacProviderKey = null;
|
this.currentPacProviderKey = null;
|
||||||
this.pushToStorage(cb);
|
this.pushToStorageAsync(cb);
|
||||||
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -296,7 +296,7 @@
|
||||||
'Periodic PAC update triggered:',
|
'Periodic PAC update triggered:',
|
||||||
new Date().toLocaleString('ru-RU')
|
new Date().toLocaleString('ru-RU')
|
||||||
);
|
);
|
||||||
antiCensorRu.syncWithPacProvider(/* Swallows errors. */);
|
antiCensorRu.syncWithPacProviderAsync(/* Swallows errors. */);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -358,7 +358,7 @@
|
||||||
// UPDATE & MIGRATION
|
// UPDATE & MIGRATION
|
||||||
console.log('Extension updated.');
|
console.log('Extension updated.');
|
||||||
if (!ifAlarmTriggered) {
|
if (!ifAlarmTriggered) {
|
||||||
antiCensorRu.pushToStorage(/* Swallows errors. */);
|
antiCensorRu.pushToStorageAsync(/* Swallows errors. */);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -414,7 +414,9 @@
|
||||||
args = replaceArgs;
|
args = replaceArgs;
|
||||||
}
|
}
|
||||||
const err = checkChromeError(stack);
|
const err = checkChromeError(stack);
|
||||||
cb && cb.call(null, err, ...args);
|
if (cb) {
|
||||||
|
setTimeout( cb.bind(null, err, ...args), 0 );
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -4,20 +4,23 @@
|
||||||
(e.g. popup) to background window, so we may catch errors
|
(e.g. popup) to background window, so we may catch errors
|
||||||
in bg error handlers.
|
in bg error handlers.
|
||||||
More: https://bugs.chromium.org/p/chromium/issues/detail?id=357568
|
More: https://bugs.chromium.org/p/chromium/issues/detail?id=357568
|
||||||
|
|
||||||
|
setTimeout is applied to Async methods only (name ends with Async)
|
||||||
*/
|
*/
|
||||||
// Fix error context of methods of all APIs.
|
// Fix error context of methods of all APIs.
|
||||||
for(const api of Object.keys(window.apis)) {
|
/*
|
||||||
|
for(const apiName of Object.keys(window.apis)) {
|
||||||
|
const api = window.apis[apiName];
|
||||||
for(const prop of Object.keys(api)) {
|
for(const prop of Object.keys(api)) {
|
||||||
if ( typeof(api[prop]) !== 'function' ) {
|
const method = api[prop];
|
||||||
|
if ( !(typeof(api[prop]) === 'function'
|
||||||
|
&& method.name.endsWith('Async')) ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const method = api[prop];
|
|
||||||
api[prop] = function(...args) {
|
api[prop] = function(...args) {
|
||||||
|
|
||||||
setTimeout(method.bind(this, ...args), 0);
|
setTimeout(method.bind(this, ...args), 0);
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
"contextMenus",
|
"contextMenus",
|
||||||
"notifications"
|
"notifications"
|
||||||
],
|
],
|
||||||
|
|
||||||
"background": {
|
"background": {
|
||||||
"scripts": ["00-init-apis.js", "11-api-error-handlers.js", "12-api-sync-pac-script-with-pac-provider.js", "20-api-fixes.js", "30-block-informer.js", "40-context-menus.js"]
|
"scripts": ["00-init-apis.js", "11-api-error-handlers.js", "12-api-sync-pac-script-with-pac-provider.js", "20-api-fixes.js", "30-block-informer.js", "40-context-menus.js"]
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,210 +1,211 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
chrome.runtime.getBackgroundPage( (backgroundPage) => {
|
chrome.runtime.getBackgroundPage( (backgroundPage) =>
|
||||||
|
backgroundPage.apis.errorHandlers.installListenersOn(window, 'POPUP', () => {
|
||||||
|
|
||||||
const getStatus = () => document.querySelector('#status');
|
const getStatus = () => document.querySelector('#status');
|
||||||
|
|
||||||
const setStatusTo = (msg) => {
|
const setStatusTo = (msg) => {
|
||||||
|
|
||||||
const status = getStatus();
|
const status = getStatus();
|
||||||
if (msg) {
|
if (msg) {
|
||||||
status.classList.remove('off');
|
status.classList.remove('off');
|
||||||
status.innerHTML = msg;
|
status.innerHTML = msg;
|
||||||
} else {
|
} else {
|
||||||
status.classList.add('off');
|
status.classList.add('off');
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
const antiCensorRu = backgroundPage.apis.antiCensorRu;
|
|
||||||
|
|
||||||
// SET DATE
|
|
||||||
|
|
||||||
const setDate = () => {
|
|
||||||
|
|
||||||
let dateForUser = 'никогда';
|
|
||||||
if( antiCensorRu.lastPacUpdateStamp ) {
|
|
||||||
let diff = Date.now() - antiCensorRu.lastPacUpdateStamp;
|
|
||||||
let units = ' мс';
|
|
||||||
const gauges = [
|
|
||||||
[1000, ' с'],
|
|
||||||
[60, ' мин'],
|
|
||||||
[60, ' ч'],
|
|
||||||
[24, ' дн'],
|
|
||||||
[7, ' недель'],
|
|
||||||
[4, ' месяцев'],
|
|
||||||
[12, ' г'],
|
|
||||||
];
|
|
||||||
for(const g of gauges) {
|
|
||||||
const diffy = Math.floor(diff / g[0]);
|
|
||||||
if (!diffy)
|
|
||||||
break;
|
|
||||||
diff = diffy;
|
|
||||||
units = g[1];
|
|
||||||
}
|
}
|
||||||
dateForUser = diff + units + ' назад';
|
|
||||||
}
|
|
||||||
|
|
||||||
const dateElement = document.querySelector('.update-date');
|
|
||||||
dateElement.innerText = dateForUser;
|
|
||||||
dateElement.title = new Date(antiCensorRu.lastPacUpdateStamp)
|
|
||||||
.toLocaleString('ru-RU');
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
setDate();
|
|
||||||
chrome.storage.onChanged.addListener(
|
|
||||||
(changes) => changes.lastPacUpdateStamp.newValue && setDate()
|
|
||||||
);
|
|
||||||
|
|
||||||
// CLOSE BUTTON
|
|
||||||
|
|
||||||
document.querySelector('.close-button').onclick = () => window.close();
|
|
||||||
|
|
||||||
// RADIOS
|
|
||||||
|
|
||||||
const currentProviderRadio = () => {
|
|
||||||
|
|
||||||
const id = antiCensorRu.currentPacProviderKey || 'none';
|
|
||||||
return document.querySelector('#'+id);
|
|
||||||
|
|
||||||
};
|
|
||||||
const checkChosenProvider = () => currentProviderRadio().checked = true;
|
|
||||||
|
|
||||||
const showError = (err) => {
|
|
||||||
|
|
||||||
let clarification = err.clarification;
|
|
||||||
const ifNotCritical = clarification && clarification.ifNotCritical;
|
|
||||||
let message = err.message || '';
|
|
||||||
|
|
||||||
while( clarification ) {
|
|
||||||
message = (clarification && (clarification.message + ' ')) + message;
|
|
||||||
clarification = clarification.prev;
|
|
||||||
}
|
|
||||||
message = message.trim();
|
|
||||||
setStatusTo(
|
|
||||||
`<span style="color:red">
|
|
||||||
${ifNotCritical ? 'Некритичная ошибка.' : 'Ошибка!'}
|
|
||||||
</span>
|
|
||||||
<br/>
|
|
||||||
<span style="font-size: 0.9em; color: darkred">${message}</span>
|
|
||||||
<a href class="link-button">[Ещё подробнее]</a>`
|
|
||||||
);
|
|
||||||
getStatus().querySelector('.link-button').onclick = function() {
|
|
||||||
|
|
||||||
const div = document.createElement('div');
|
|
||||||
div.innerHTML = `
|
|
||||||
Более подробную информацию можно узнать из логов фоновой страницы:<br/>
|
|
||||||
<a href="chrome://extensions?id=${chrome.runtime.id}" data-in-bg="true">
|
|
||||||
chrome://extensions</a> ›
|
|
||||||
Это расширение › Отладка страниц: фоновая страница › Console (DevTools)
|
|
||||||
<br>
|
|
||||||
Ещё: ${JSON.stringify({err: err, stack: err.stack})}
|
|
||||||
`;
|
|
||||||
getStatus().replaceChild(div, this);
|
|
||||||
return false;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
const antiCensorRu = backgroundPage.apis.antiCensorRu;
|
||||||
|
|
||||||
const enableDisableInputs = function() {
|
// SET DATE
|
||||||
|
|
||||||
const inputs = document.querySelectorAll('input');
|
const setDate = () => {
|
||||||
for ( let i = 0; i < inputs.length; i++ ) {
|
|
||||||
inputs[i].disabled = !inputs[i].disabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
let dateForUser = 'никогда';
|
||||||
|
if( antiCensorRu.lastPacUpdateStamp ) {
|
||||||
const conduct = (beforeStatus, operation, afterStatus, onSuccess) => {
|
let diff = Date.now() - antiCensorRu.lastPacUpdateStamp;
|
||||||
|
let units = ' мс';
|
||||||
setStatusTo(beforeStatus);
|
const gauges = [
|
||||||
enableDisableInputs();
|
[1000, ' с'],
|
||||||
operation((err) => {
|
[60, ' мин'],
|
||||||
if (err) {
|
[60, ' ч'],
|
||||||
showError(err);
|
[24, ' дн'],
|
||||||
} else {
|
[7, ' недель'],
|
||||||
setStatusTo(afterStatus);
|
[4, ' месяцев'],
|
||||||
onSuccess && onSuccess();
|
[12, ' г'],
|
||||||
|
];
|
||||||
|
for(const g of gauges) {
|
||||||
|
const diffy = Math.floor(diff / g[0]);
|
||||||
|
if (!diffy)
|
||||||
|
break;
|
||||||
|
diff = diffy;
|
||||||
|
units = g[1];
|
||||||
|
}
|
||||||
|
dateForUser = diff + units + ' назад';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const dateElement = document.querySelector('.update-date');
|
||||||
|
dateElement.innerText = dateForUser;
|
||||||
|
dateElement.title = new Date(antiCensorRu.lastPacUpdateStamp)
|
||||||
|
.toLocaleString('ru-RU');
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
setDate();
|
||||||
|
chrome.storage.onChanged.addListener(
|
||||||
|
(changes) => changes.lastPacUpdateStamp.newValue && setDate()
|
||||||
|
);
|
||||||
|
|
||||||
|
// CLOSE BUTTON
|
||||||
|
|
||||||
|
document.querySelector('.close-button').onclick = () => window.close();
|
||||||
|
|
||||||
|
// RADIOS
|
||||||
|
|
||||||
|
const currentProviderRadio = () => {
|
||||||
|
|
||||||
|
const id = antiCensorRu.currentPacProviderKey || 'none';
|
||||||
|
return document.querySelector('#'+id);
|
||||||
|
|
||||||
|
};
|
||||||
|
const checkChosenProvider = () => currentProviderRadio().checked = true;
|
||||||
|
|
||||||
|
const showError = (err) => {
|
||||||
|
|
||||||
|
let clarification = err.clarification;
|
||||||
|
const ifNotCritical = clarification && clarification.ifNotCritical;
|
||||||
|
let message = err.message || '';
|
||||||
|
|
||||||
|
while( clarification ) {
|
||||||
|
message = (clarification && (clarification.message + ' ')) + message;
|
||||||
|
clarification = clarification.prev;
|
||||||
|
}
|
||||||
|
message = message.trim();
|
||||||
|
setStatusTo(
|
||||||
|
`<span style="color:red">
|
||||||
|
${ifNotCritical ? 'Некритичная ошибка.' : 'Ошибка!'}
|
||||||
|
</span>
|
||||||
|
<br/>
|
||||||
|
<span style="font-size: 0.9em; color: darkred">${message}</span>
|
||||||
|
<a href class="link-button">[Ещё подробнее]</a>`
|
||||||
|
);
|
||||||
|
getStatus().querySelector('.link-button').onclick = function() {
|
||||||
|
|
||||||
|
const div = document.createElement('div');
|
||||||
|
div.innerHTML = `
|
||||||
|
Более подробную информацию можно узнать из логов фоновой страницы:<br/>
|
||||||
|
<a href="chrome://extensions?id=${chrome.runtime.id}" data-in-bg="true">
|
||||||
|
chrome://extensions</a> ›
|
||||||
|
Это расширение › Отладка страниц: фоновая страница › Console (DevTools)
|
||||||
|
<br>
|
||||||
|
Ещё: ` + JSON.stringify({err: err, stack: err.stack});
|
||||||
|
getStatus().replaceChild(div, this);
|
||||||
|
return false;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
const enableDisableInputs = function() {
|
||||||
|
|
||||||
|
const inputs = document.querySelectorAll('input');
|
||||||
|
for ( let i = 0; i < inputs.length; i++ ) {
|
||||||
|
inputs[i].disabled = !inputs[i].disabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
const conduct = (beforeStatus, operation, afterStatus, onSuccess) => {
|
||||||
|
|
||||||
|
setStatusTo(beforeStatus);
|
||||||
enableDisableInputs();
|
enableDisableInputs();
|
||||||
});
|
operation((err) => {
|
||||||
|
if (err) {
|
||||||
|
showError(err);
|
||||||
|
} else {
|
||||||
|
setStatusTo(afterStatus);
|
||||||
|
onSuccess && onSuccess();
|
||||||
|
}
|
||||||
|
enableDisableInputs();
|
||||||
|
});
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const ul = document.querySelector('#list-of-providers');
|
const ul = document.querySelector('#list-of-providers');
|
||||||
const _firstChild = ul.firstChild;
|
const _firstChild = ul.firstChild;
|
||||||
for( const providerKey of Object.keys(antiCensorRu.pacProviders).sort() ) {
|
for( const providerKey of Object.keys(antiCensorRu.pacProviders).sort() ) {
|
||||||
const li = document.createElement('li');
|
const li = document.createElement('li');
|
||||||
li.innerHTML = `<input type="radio" name="pacProvider" id="${providerKey}">
|
li.innerHTML = `<input type="radio" name="pacProvider" id="${providerKey}">
|
||||||
<label for="${providerKey}">${providerKey}</label>
|
<label for="${providerKey}">${providerKey}</label>
|
||||||
<a href class="link-button checked-radio-panel"
|
<a href class="link-button checked-radio-panel"
|
||||||
id="update-${providerKey}">[обновить]</a>`;
|
id="update-${providerKey}">[обновить]</a>`;
|
||||||
li.querySelector('.link-button').onclick =
|
li.querySelector('.link-button').onclick =
|
||||||
() => {
|
() => {
|
||||||
conduct(
|
conduct(
|
||||||
'Обновляем...', (cb) => antiCensorRu.syncWithPacProvider(cb),
|
'Обновляем...', (cb) => antiCensorRu.syncWithPacProviderAsync(cb),
|
||||||
'Обновлено.'
|
'Обновлено.'
|
||||||
);
|
);
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
ul.insertBefore( li, _firstChild );
|
||||||
|
}
|
||||||
|
checkChosenProvider();
|
||||||
|
|
||||||
|
const radios = [].slice.apply(
|
||||||
|
document.querySelectorAll('[name=pacProvider]')
|
||||||
|
);
|
||||||
|
for(const radio of radios) {
|
||||||
|
radio.onclick = function(event) {
|
||||||
|
|
||||||
|
if (event.target.id === (antiCensorRu.currentPacProviderKey || 'none')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const pacKey = event.target.id;
|
||||||
|
if (pacKey === 'none') {
|
||||||
|
conduct(
|
||||||
|
'Отключение...',
|
||||||
|
(cb) => antiCensorRu.clearPacAsync(cb),
|
||||||
|
'Отключено.',
|
||||||
|
checkChosenProvider
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
conduct(
|
||||||
|
'Установка...',
|
||||||
|
(cb) => antiCensorRu.installPacAsync(pacKey, cb),
|
||||||
|
'PAC-скрипт установлен.',
|
||||||
|
checkChosenProvider
|
||||||
|
);
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
ul.insertBefore( li, _firstChild );
|
}
|
||||||
}
|
|
||||||
checkChosenProvider();
|
|
||||||
|
|
||||||
const radios = [].slice.apply(
|
const conpanel = document.getElementById('list-of-handlers');
|
||||||
document.querySelectorAll('[name=pacProvider]')
|
backgroundPage.apis.errorHandlers.getEventsMap().forEach( (value, name) => {
|
||||||
);
|
|
||||||
for(const radio of radios) {
|
|
||||||
radio.onclick = function(event) {
|
|
||||||
|
|
||||||
if (event.target.id === (antiCensorRu.currentPacProviderKey || 'none')) {
|
const li = document.createElement('li');
|
||||||
return false;
|
li.innerHTML = `
|
||||||
}
|
<input type="checkbox" id="if-on-${name}"/>
|
||||||
const pacKey = event.target.id;
|
<label for="if-on-${name}">${value}</label>`;
|
||||||
if (pacKey === 'none') {
|
const box = li.querySelector('input');
|
||||||
conduct(
|
box.checked = backgroundPage.apis.errorHandlers.isOn(name);
|
||||||
'Отключение...',
|
box.onclick = function() {
|
||||||
(cb) => antiCensorRu.clearPac(cb),
|
|
||||||
'Отключено.',
|
|
||||||
checkChosenProvider
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
conduct(
|
|
||||||
'Установка...',
|
|
||||||
(cb) => antiCensorRu.installPac(pacKey, cb),
|
|
||||||
'PAC-скрипт установлен.',
|
|
||||||
checkChosenProvider
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const conpanel = document.getElementById('list-of-handlers');
|
const id = this.id.replace('if-on-', '');
|
||||||
backgroundPage.apis.errorHandlers.getEventsMap().forEach( (value, name) => {
|
backgroundPage.apis.errorHandlers.switch(this.checked ? 'on' : 'off', id);
|
||||||
|
|
||||||
const li = document.createElement('li');
|
};
|
||||||
li.innerHTML = `
|
conpanel.appendChild(li);
|
||||||
<input type="checkbox" id="if-on-${name}"/>
|
|
||||||
<label for="if-on-${name}">${value}</label>`;
|
|
||||||
const box = li.querySelector('input');
|
|
||||||
box.checked = backgroundPage.apis.errorHandlers.isOn(name);
|
|
||||||
box.onclick = function() {
|
|
||||||
|
|
||||||
const id = this.id.replace('if-on-', '');
|
});
|
||||||
backgroundPage.apis.errorHandlers.switch(this.checked ? 'on' : 'off', id);
|
|
||||||
|
|
||||||
};
|
setStatusTo('');
|
||||||
conpanel.appendChild(li);
|
if (antiCensorRu.ifFirstInstall) {
|
||||||
|
const id = antiCensorRu.currentPacProviderKey || 'none';
|
||||||
|
document.querySelector('#update-' + id).click();
|
||||||
|
}
|
||||||
|
|
||||||
});
|
})
|
||||||
|
);
|
||||||
setStatusTo('');
|
|
||||||
if (antiCensorRu.ifFirstInstall) {
|
|
||||||
const id = antiCensorRu.currentPacProviderKey || 'none';
|
|
||||||
document.querySelector('#update-' + id).click();
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 110 KiB |
|
@ -0,0 +1,75 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Ошибка</title>
|
||||||
|
<style type="text/css" media="screen">
|
||||||
|
html, body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
html {
|
||||||
|
background: black url('./err.jpg') repeat;
|
||||||
|
background-position: left;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
background: linear-gradient(to bottom, black 45em, transparent);
|
||||||
|
}
|
||||||
|
header {
|
||||||
|
padding-top: 1em;
|
||||||
|
}
|
||||||
|
h2 {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
main {
|
||||||
|
color: #999999;
|
||||||
|
font-size: 1.5em;
|
||||||
|
}
|
||||||
|
pre {
|
||||||
|
margin: 0 !important;
|
||||||
|
padding: 1em !important;
|
||||||
|
width: 100% !important;
|
||||||
|
border-radius: 0 !important;
|
||||||
|
box-sizing: border-box !important;
|
||||||
|
background-color: transparent !important;
|
||||||
|
}
|
||||||
|
header {
|
||||||
|
padding-left: 2em;
|
||||||
|
}
|
||||||
|
ol, ul {
|
||||||
|
list-style-type: none;
|
||||||
|
}
|
||||||
|
textarea {
|
||||||
|
width: 40em;
|
||||||
|
height: 10em;
|
||||||
|
font: inherit;
|
||||||
|
}
|
||||||
|
#output {
|
||||||
|
background-color: black;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header>
|
||||||
|
<h2>Информация об ошибке</h2>
|
||||||
|
</header>
|
||||||
|
<main>
|
||||||
|
<ol>
|
||||||
|
<li>Тип: <span>ext-error</span></li>
|
||||||
|
<li><pre><code id="output" class='hljs'></code></pre></li>
|
||||||
|
<li><textarea placeholder='Ваш комментарий (опционально)' id="comment"></textarea></li>
|
||||||
|
<li>
|
||||||
|
<button id="raven-report">Отправить автору</button>
|
||||||
|
<button id="github-search">Искать на GitHub</button>
|
||||||
|
<button id="github-report">Написать на GitHub</button>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
</main>
|
||||||
|
<script src="./vendor/raven3.8.1.min.js" crossorigin="anonymous"></script>
|
||||||
|
<link rel="stylesheet" href="./vendor/highlight.js/styles/atom-one-dark.css">
|
||||||
|
<script src="./vendor/highlight.js/highlight9.8.0.min.js"></script>
|
||||||
|
<script src="./index.js" charset="utf-8"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,100 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
function errorJsonReplacer(key, value) {
|
||||||
|
|
||||||
|
if ( !['Error', 'ErrorEvent'].includes( value.constructor.name ) ) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
const alt = {};
|
||||||
|
|
||||||
|
Object.getOwnPropertyNames(value).forEach(function (key) {
|
||||||
|
alt[key] = value[key];
|
||||||
|
}, value);
|
||||||
|
|
||||||
|
for(const prop in value) {
|
||||||
|
if (/^[A-Z]/.test(prop)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
alt[prop] = value[prop];
|
||||||
|
}
|
||||||
|
|
||||||
|
// fooWindow.ErrorEvent !== barWindow.ErrorEvent
|
||||||
|
if (value.constructor.name === 'ErrorEvent') {
|
||||||
|
for(const circularProp of
|
||||||
|
[ // First line are circular props.
|
||||||
|
'target', 'srcElement', 'path', 'currentTarget',
|
||||||
|
'bubbles', 'cancelBubble', 'cancelable', 'composed',
|
||||||
|
'defaultPrevented', 'eventPhase', 'isTrusted', 'returnValue',
|
||||||
|
'timeStamp']) {
|
||||||
|
delete alt[circularProp];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return alt;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
chrome.runtime.getBackgroundPage( (backgroundPage) =>
|
||||||
|
backgroundPage.apis.errorHandlers.installListenersOn(window, 'ErrView', () => {
|
||||||
|
|
||||||
|
Raven.config('https://bc534321358f455b9ae861740c2d3af8@sentry.io/116007', {
|
||||||
|
release: chrome.runtime.getManifest().version,
|
||||||
|
autoBreadcrumbs: false,
|
||||||
|
}).install();
|
||||||
|
|
||||||
|
const errId = window.location.hash.slice(1);
|
||||||
|
const err = backgroundPage.apis.errorHandlers.idToErr[errId];
|
||||||
|
const json = JSON.stringify(err, errorJsonReplacer, 2);
|
||||||
|
document.getElementById('output').innerHTML = hljs.highlight('json', json).value;
|
||||||
|
|
||||||
|
document.addEventListener('ravenSuccess', () => alert('Готово'));
|
||||||
|
document.addEventListener('ravenFailure', () => alert('Ошибка sentry.io! (подробности недоступны)'));
|
||||||
|
|
||||||
|
document.getElementById('raven-report').onclick = () => {
|
||||||
|
|
||||||
|
const e = err.error || err;
|
||||||
|
const extra = JSON.parse(json);
|
||||||
|
const comment = document.getElementById('comment').value;
|
||||||
|
if (comment.trim()) {
|
||||||
|
extra.comment = comment;
|
||||||
|
}
|
||||||
|
Raven.captureException(e, {
|
||||||
|
extra: extra,
|
||||||
|
onSuccess: () => alert('Готово'),
|
||||||
|
onError: (err) => { throw err; }
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
document.getElementById('github-search').onclick = () => {
|
||||||
|
|
||||||
|
const title = err.message || err;
|
||||||
|
chrome.tabs.create({
|
||||||
|
active: true,
|
||||||
|
url: 'https://rebrand.ly/ac-search-issues?q=' + encodeURIComponent(title)
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
document.getElementById('github-report').onclick = () => {
|
||||||
|
|
||||||
|
const comment = document.getElementById('comment').value;
|
||||||
|
const title = err.message || err;
|
||||||
|
const body = (comment || 'Ваш текст') + `
|
||||||
|
|
||||||
|
### Ошибка
|
||||||
|
|
||||||
|
\`\`\`json
|
||||||
|
${json}
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
Версия: ${chrome.runtime.getManifest().version}
|
||||||
|
`;
|
||||||
|
chrome.tabs.create({
|
||||||
|
active: true,
|
||||||
|
url: `https://rebrand.ly/ac-new-issue?title=${encodeURIComponent(title)}&body=${encodeURIComponent(body)}`
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
})
|
||||||
|
);
|
|
@ -0,0 +1,63 @@
|
||||||
|
!function(){/*
|
||||||
|
|
||||||
|
Copyright (C) 2013 Google Inc.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
Copyright (C) 2006 Google Inc.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
(function(){function ba(g){function k(){try{M.doScroll("left")}catch(g){t.setTimeout(k,50);return}z("poll")}function z(k){if("readystatechange"!=k.type||"complete"==A.readyState)("load"==k.type?t:A)[B](p+k.type,z,!1),!q&&(q=!0)&&g.call(t,k.type||k)}var Y=A.addEventListener,q=!1,C=!0,x=Y?"addEventListener":"attachEvent",B=Y?"removeEventListener":"detachEvent",p=Y?"":"on";if("complete"==A.readyState)g.call(t,"lazy");else{if(A.createEventObject&&M.doScroll){try{C=!t.frameElement}catch(da){}C&&k()}A[x](p+
|
||||||
|
"DOMContentLoaded",z,!1);A[x](p+"readystatechange",z,!1);t[x](p+"load",z,!1)}}function U(){V&&ba(function(){var g=N.length;ca(g?function(){for(var k=0;k<g;++k)(function(g){t.setTimeout(function(){t.exports[N[g]].apply(t,arguments)},0)})(k)}:void 0)})}for(var t=window,A=document,M=A.documentElement,O=A.head||A.getElementsByTagName("head")[0]||M,B="",F=A.getElementsByTagName("script"),q=F.length;0<=--q;){var P=F[q],Z=P.src.match(/^[^?#]*\/run_prettify\.js(\?[^#]*)?(?:#.*)?$/);if(Z){B=Z[1]||"";P.parentNode.removeChild(P);
|
||||||
|
break}}var V=!0,H=[],Q=[],N=[];B.replace(/[?&]([^&=]+)=([^&]+)/g,function(g,k,z){z=decodeURIComponent(z);k=decodeURIComponent(k);"autorun"==k?V=!/^[0fn]/i.test(z):"lang"==k?H.push(z):"skin"==k?Q.push(z):"callback"==k&&N.push(z)});q=0;for(B=H.length;q<B;++q)(function(){var g=A.createElement("script");g.onload=g.onerror=g.onreadystatechange=function(){!g||g.readyState&&!/loaded|complete/.test(g.readyState)||(g.onerror=g.onload=g.onreadystatechange=null,--T,T||t.setTimeout(U,0),g.parentNode&&g.parentNode.removeChild(g),
|
||||||
|
g=null)};g.type="text/javascript";g.src="https://cdn.rawgit.com/google/code-prettify/master/loader/lang-"+encodeURIComponent(H[q])+".js";O.insertBefore(g,O.firstChild)})(H[q]);for(var T=H.length,F=[],q=0,B=Q.length;q<B;++q)F.push("./vendor/code-prettify/skins/"+encodeURIComponent(Q[q])+".css");F.push("https://cdn.rawgit.com/google/code-prettify/master/loader/prettify.css");(function(g){function k(q){if(q!==z){var t=A.createElement("link");t.rel="stylesheet";t.type=
|
||||||
|
"text/css";q+1<z&&(t.error=t.onerror=function(){k(q+1)});t.href=g[q];O.appendChild(t)}}var z=g.length;k(0)})(F);var ca=function(){window.PR_SHOULD_USE_CONTINUATION=!0;var g;(function(){function k(a){function d(e){var b=e.charCodeAt(0);if(92!==b)return b;var a=e.charAt(1);return(b=W[a])?b:"0"<=a&&"7">=a?parseInt(e.substring(1),8):"u"===a||"x"===a?parseInt(e.substring(2),16):e.charCodeAt(1)}function f(e){if(32>e)return(16>e?"\\x0":"\\x")+e.toString(16);e=String.fromCharCode(e);return"\\"===e||"-"===
|
||||||
|
e||"]"===e||"^"===e?"\\"+e:e}function b(e){var b=e.substring(1,e.length-1).match(/\\u[0-9A-Fa-f]{4}|\\x[0-9A-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\s\S]|-|[^-\\]/g);e=[];var a="^"===b[0],c=["["];a&&c.push("^");for(var a=a?1:0,h=b.length;a<h;++a){var l=b[a];if(/\\[bdsw]/i.test(l))c.push(l);else{var l=d(l),n;a+2<h&&"-"===b[a+1]?(n=d(b[a+2]),a+=2):n=l;e.push([l,n]);65>n||122<l||(65>n||90<l||e.push([Math.max(65,l)|32,Math.min(n,90)|32]),97>n||122<l||e.push([Math.max(97,l)&-33,Math.min(n,122)&-33]))}}e.sort(function(e,
|
||||||
|
a){return e[0]-a[0]||a[1]-e[1]});b=[];h=[];for(a=0;a<e.length;++a)l=e[a],l[0]<=h[1]+1?h[1]=Math.max(h[1],l[1]):b.push(h=l);for(a=0;a<b.length;++a)l=b[a],c.push(f(l[0])),l[1]>l[0]&&(l[1]+1>l[0]&&c.push("-"),c.push(f(l[1])));c.push("]");return c.join("")}function g(e){for(var a=e.source.match(/(?:\[(?:[^\x5C\x5D]|\\[\s\S])*\]|\\u[A-Fa-f0-9]{4}|\\x[A-Fa-f0-9]{2}|\\[0-9]+|\\[^ux0-9]|\(\?[:!=]|[\(\)\^]|[^\x5B\x5C\(\)\^]+)/g),c=a.length,d=[],h=0,l=0;h<c;++h){var n=a[h];"("===n?++l:"\\"===n.charAt(0)&&(n=
|
||||||
|
+n.substring(1))&&(n<=l?d[n]=-1:a[h]=f(n))}for(h=1;h<d.length;++h)-1===d[h]&&(d[h]=++k);for(l=h=0;h<c;++h)n=a[h],"("===n?(++l,d[l]||(a[h]="(?:")):"\\"===n.charAt(0)&&(n=+n.substring(1))&&n<=l&&(a[h]="\\"+d[n]);for(h=0;h<c;++h)"^"===a[h]&&"^"!==a[h+1]&&(a[h]="");if(e.ignoreCase&&I)for(h=0;h<c;++h)n=a[h],e=n.charAt(0),2<=n.length&&"["===e?a[h]=b(n):"\\"!==e&&(a[h]=n.replace(/[a-zA-Z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return a.join("")}for(var k=0,I=!1,
|
||||||
|
m=!1,J=0,c=a.length;J<c;++J){var r=a[J];if(r.ignoreCase)m=!0;else if(/[a-z]/i.test(r.source.replace(/\\u[0-9a-f]{4}|\\x[0-9a-f]{2}|\\[^ux]/gi,""))){I=!0;m=!1;break}}for(var W={b:8,t:9,n:10,v:11,f:12,r:13},u=[],J=0,c=a.length;J<c;++J){r=a[J];if(r.global||r.multiline)throw Error(""+r);u.push("(?:"+g(r)+")")}return new RegExp(u.join("|"),m?"gi":"g")}function q(a,d){function f(a){var c=a.nodeType;if(1==c){if(!b.test(a.className)){for(c=a.firstChild;c;c=c.nextSibling)f(c);c=a.nodeName.toLowerCase();if("br"===
|
||||||
|
c||"li"===c)g[m]="\n",I[m<<1]=k++,I[m++<<1|1]=a}}else if(3==c||4==c)c=a.nodeValue,c.length&&(c=d?c.replace(/\r\n?/g,"\n"):c.replace(/[ \t\r\n]+/g," "),g[m]=c,I[m<<1]=k,k+=c.length,I[m++<<1|1]=a)}var b=/(?:^|\s)nocode(?:\s|$)/,g=[],k=0,I=[],m=0;f(a);return{a:g.join("").replace(/\n$/,""),c:I}}function t(a,d,f,b,g){f&&(a={h:a,l:1,j:null,m:null,a:f,c:null,i:d,g:null},b(a),g.push.apply(g,a.g))}function A(a){for(var d=void 0,f=a.firstChild;f;f=f.nextSibling)var b=f.nodeType,d=1===b?d?a:f:3===b?T.test(f.nodeValue)?
|
||||||
|
a:d:d;return d===a?void 0:d}function C(a,d){function f(a){for(var m=a.i,k=a.h,c=[m,"pln"],r=0,W=a.a.match(g)||[],u={},e=0,q=W.length;e<q;++e){var D=W[e],w=u[D],h=void 0,l;if("string"===typeof w)l=!1;else{var n=b[D.charAt(0)];if(n)h=D.match(n[1]),w=n[0];else{for(l=0;l<p;++l)if(n=d[l],h=D.match(n[1])){w=n[0];break}h||(w="pln")}!(l=5<=w.length&&"lang-"===w.substring(0,5))||h&&"string"===typeof h[1]||(l=!1,w="src");l||(u[D]=w)}n=r;r+=D.length;if(l){l=h[1];var E=D.indexOf(l),G=E+l.length;h[2]&&(G=D.length-
|
||||||
|
h[2].length,E=G-l.length);w=w.substring(5);t(k,m+n,D.substring(0,E),f,c);t(k,m+n+E,l,F(w,l),c);t(k,m+n+G,D.substring(G),f,c)}else c.push(m+n,w)}a.g=c}var b={},g;(function(){for(var f=a.concat(d),m=[],p={},c=0,r=f.length;c<r;++c){var q=f[c],u=q[3];if(u)for(var e=u.length;0<=--e;)b[u.charAt(e)]=q;q=q[1];u=""+q;p.hasOwnProperty(u)||(m.push(q),p[u]=null)}m.push(/[\0-\uffff]/);g=k(m)})();var p=d.length;return f}function x(a){var d=[],f=[];a.tripleQuotedStrings?d.push(["str",/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,
|
||||||
|
null,"'\""]):a.multiLineStrings?d.push(["str",/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"]):d.push(["str",/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"]);a.verbatimStrings&&f.push(["str",/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null]);var b=a.hashComments;b&&(a.cStyleComments?(1<b?d.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,null,"#"]):d.push(["com",/^#(?:(?:define|e(?:l|nd)if|else|error|ifn?def|include|line|pragma|undef|warning)\b|[^\r\n]*)/,
|
||||||
|
null,"#"]),f.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h(?:h|pp|\+\+)?|[a-z]\w*)>/,null])):d.push(["com",/^#[^\r\n]*/,null,"#"]));a.cStyleComments&&(f.push(["com",/^\/\/[^\r\n]*/,null]),f.push(["com",/^\/\*[\s\S]*?(?:\*\/|$)/,null]));if(b=a.regexLiterals){var g=(b=1<b?"":"\n\r")?".":"[\\S\\s]";f.push(["lang-regex",RegExp("^(?:^^\\.?|[+-]|[!=]=?=?|\\#|%=?|&&?=?|\\(|\\*=?|[+\\-]=|->|\\/=?|::?|<<?=?|>>?>?=?|,|;|\\?|@|\\[|~|{|\\^\\^?=?|\\|\\|?=?|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*("+
|
||||||
|
("/(?=[^/*"+b+"])(?:[^/\\x5B\\x5C"+b+"]|\\x5C"+g+"|\\x5B(?:[^\\x5C\\x5D"+b+"]|\\x5C"+g+")*(?:\\x5D|$))+/")+")")])}(b=a.types)&&f.push(["typ",b]);b=(""+a.keywords).replace(/^ | $/g,"");b.length&&f.push(["kwd",new RegExp("^(?:"+b.replace(/[\s,]+/g,"|")+")\\b"),null]);d.push(["pln",/^\s+/,null," \r\n\t\u00a0"]);b="^.[^\\s\\w.$@'\"`/\\\\]*";a.regexLiterals&&(b+="(?!s*/)");f.push(["lit",/^@[a-z_$][a-z_$@0-9]*/i,null],["typ",/^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/,null],["pln",/^[a-z_$][a-z_$@0-9]*/i,
|
||||||
|
null],["lit",/^(?:0x[a-f0-9]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+\-]?\d+)?)[a-z]*/i,null,"0123456789"],["pln",/^\\[\s\S]?/,null],["pun",new RegExp(b),null]);return C(d,f)}function B(a,d,f){function b(a){var c=a.nodeType;if(1==c&&!k.test(a.className))if("br"===a.nodeName)g(a),a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)b(a);else if((3==c||4==c)&&f){var d=a.nodeValue,p=d.match(q);p&&(c=d.substring(0,p.index),a.nodeValue=c,(d=d.substring(p.index+p[0].length))&&
|
||||||
|
a.parentNode.insertBefore(m.createTextNode(d),a.nextSibling),g(a),c||a.parentNode.removeChild(a))}}function g(a){function b(a,c){var d=c?a.cloneNode(!1):a,n=a.parentNode;if(n){var n=b(n,1),e=a.nextSibling;n.appendChild(d);for(var f=e;f;f=e)e=f.nextSibling,n.appendChild(f)}return d}for(;!a.nextSibling;)if(a=a.parentNode,!a)return;a=b(a.nextSibling,0);for(var d;(d=a.parentNode)&&1===d.nodeType;)a=d;c.push(a)}for(var k=/(?:^|\s)nocode(?:\s|$)/,q=/\r\n?|\n/,m=a.ownerDocument,p=m.createElement("li");a.firstChild;)p.appendChild(a.firstChild);
|
||||||
|
for(var c=[p],r=0;r<c.length;++r)b(c[r]);d===(d|0)&&c[0].setAttribute("value",d);var t=m.createElement("ol");t.className="linenums";d=Math.max(0,d-1|0)||0;for(var r=0,u=c.length;r<u;++r)p=c[r],p.className="L"+(r+d)%10,p.firstChild||p.appendChild(m.createTextNode("\u00a0")),t.appendChild(p);a.appendChild(t)}function p(a,d){for(var f=d.length;0<=--f;){var b=d[f];X.hasOwnProperty(b)?R.console&&console.warn("cannot override language handler %s",b):X[b]=a}}function F(a,d){a&&X.hasOwnProperty(a)||(a=/^\s*</.test(d)?
|
||||||
|
"default-markup":"default-code");return X[a]}function H(a){var d=a.j;try{var f=q(a.h,a.l),b=f.a;a.a=b;a.c=f.c;a.i=0;F(d,b)(a);var g=/\bMSIE\s(\d+)/.exec(navigator.userAgent),g=g&&8>=+g[1],d=/\n/g,p=a.a,k=p.length,f=0,m=a.c,t=m.length,b=0,c=a.g,r=c.length,x=0;c[r]=k;var u,e;for(e=u=0;e<r;)c[e]!==c[e+2]?(c[u++]=c[e++],c[u++]=c[e++]):e+=2;r=u;for(e=u=0;e<r;){for(var A=c[e],D=c[e+1],w=e+2;w+2<=r&&c[w+1]===D;)w+=2;c[u++]=A;c[u++]=D;e=w}c.length=u;var h=a.h;a="";h&&(a=h.style.display,h.style.display="none");
|
||||||
|
try{for(;b<t;){var l=m[b+2]||k,n=c[x+2]||k,w=Math.min(l,n),E=m[b+1],G;if(1!==E.nodeType&&(G=p.substring(f,w))){g&&(G=G.replace(d,"\r"));E.nodeValue=G;var aa=E.ownerDocument,v=aa.createElement("span");v.className=c[x+1];var B=E.parentNode;B.replaceChild(v,E);v.appendChild(E);f<l&&(m[b+1]=E=aa.createTextNode(p.substring(w,l)),B.insertBefore(E,v.nextSibling))}f=w;f>=l&&(b+=2);f>=n&&(x+=2)}}finally{h&&(h.style.display=a)}}catch(y){R.console&&console.log(y&&y.stack||y)}}var R=window,K=["break,continue,do,else,for,if,return,while"],
|
||||||
|
L=[[K,"auto,case,char,const,default,double,enum,extern,float,goto,inline,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"],"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],S=[L,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,delegate,dynamic_cast,explicit,export,friend,generic,late_check,mutable,namespace,nullptr,property,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],
|
||||||
|
M=[L,"abstract,assert,boolean,byte,extends,finally,final,implements,import,instanceof,interface,null,native,package,strictfp,super,synchronized,throws,transient"],N=[L,"abstract,as,base,bool,by,byte,checked,decimal,delegate,descending,dynamic,event,finally,fixed,foreach,from,group,implicit,in,interface,internal,into,is,let,lock,null,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var,virtual,where"],L=[L,"debugger,eval,export,function,get,instanceof,null,set,undefined,var,with,Infinity,NaN"],
|
||||||
|
O=[K,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"],P=[K,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],K=[K,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],Q=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)\b/,
|
||||||
|
T=/\S/,U=x({keywords:[S,N,M,L,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",O,P,K],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),X={};p(U,["default-code"]);p(C([],[["pln",/^[^<?]+/],["dec",/^<!\w[^>]*(?:>|$)/],["com",/^<\!--[\s\S]*?(?:-\->|$)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",
|
||||||
|
/^<xmp\b[^>]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-js",/^<script\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^<style\b[^>]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),"default-markup htm html mxml xhtml xml xsl".split(" "));p(C([["pln",/^[\s]+/,null," \t\r\n"],["atv",/^(?:\"[^\"]*\"?|\'[^\']*\'?)/,null,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],
|
||||||
|
["pun",/^[=<>\/]+/],["lang-js",/^on\w+\s*=\s*\"([^\"]+)\"/i],["lang-js",/^on\w+\s*=\s*\'([^\']+)\'/i],["lang-js",/^on\w+\s*=\s*([^\"\'>\s]+)/i],["lang-css",/^style\s*=\s*\"([^\"]+)\"/i],["lang-css",/^style\s*=\s*\'([^\']+)\'/i],["lang-css",/^style\s*=\s*([^\"\'>\s]+)/i]]),["in.tag"]);p(C([],[["atv",/^[\s\S]+/]]),["uq.val"]);p(x({keywords:S,hashComments:!0,cStyleComments:!0,types:Q}),"c cc cpp cxx cyc m".split(" "));p(x({keywords:"null,true,false"}),["json"]);p(x({keywords:N,hashComments:!0,cStyleComments:!0,
|
||||||
|
verbatimStrings:!0,types:Q}),["cs"]);p(x({keywords:M,cStyleComments:!0}),["java"]);p(x({keywords:K,hashComments:!0,multiLineStrings:!0}),["bash","bsh","csh","sh"]);p(x({keywords:O,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}),["cv","py","python"]);p(x({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:2}),
|
||||||
|
["perl","pl","pm"]);p(x({keywords:P,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb","ruby"]);p(x({keywords:L,cStyleComments:!0,regexLiterals:!0}),["javascript","js"]);p(x({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,throw,true,try,unless,until,when,while,yes",hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);p(C([],[["str",/^[\s\S]+/]]),["regex"]);
|
||||||
|
var V=R.PR={createSimpleLexer:C,registerLangHandler:p,sourceDecorator:x,PR_ATTRIB_NAME:"atn",PR_ATTRIB_VALUE:"atv",PR_COMMENT:"com",PR_DECLARATION:"dec",PR_KEYWORD:"kwd",PR_LITERAL:"lit",PR_NOCODE:"nocode",PR_PLAIN:"pln",PR_PUNCTUATION:"pun",PR_SOURCE:"src",PR_STRING:"str",PR_TAG:"tag",PR_TYPE:"typ",prettyPrintOne:function(a,d,f){f=f||!1;d=d||null;var b=document.createElement("div");b.innerHTML="<pre>"+a+"</pre>";b=b.firstChild;f&&B(b,f,!0);H({j:d,m:f,h:b,l:1,a:null,i:null,c:null,g:null});return b.innerHTML},
|
||||||
|
prettyPrint:g=g=function(a,d){function f(){for(var b=R.PR_SHOULD_USE_CONTINUATION?c.now()+250:Infinity;r<p.length&&c.now()<b;r++){for(var d=p[r],k=h,q=d;q=q.previousSibling;){var m=q.nodeType,v=(7===m||8===m)&&q.nodeValue;if(v?!/^\??prettify\b/.test(v):3!==m||/\S/.test(q.nodeValue))break;if(v){k={};v.replace(/\b(\w+)=([\w:.%+-]+)/g,function(a,b,c){k[b]=c});break}}q=d.className;if((k!==h||u.test(q))&&!e.test(q)){m=!1;for(v=d.parentNode;v;v=v.parentNode)if(w.test(v.tagName)&&v.className&&u.test(v.className)){m=
|
||||||
|
!0;break}if(!m){d.className+=" prettyprinted";m=k.lang;if(!m){var m=q.match(t),C;!m&&(C=A(d))&&z.test(C.tagName)&&(m=C.className.match(t));m&&(m=m[1])}if(x.test(d.tagName))v=1;else var v=d.currentStyle,y=g.defaultView,v=(v=v?v.whiteSpace:y&&y.getComputedStyle?y.getComputedStyle(d,null).getPropertyValue("white-space"):0)&&"pre"===v.substring(0,3);y=k.linenums;(y="true"===y||+y)||(y=(y=q.match(/\blinenums\b(?::(\d+))?/))?y[1]&&y[1].length?+y[1]:!0:!1);y&&B(d,y,v);H({j:m,h:d,m:y,l:v,a:null,i:null,c:null,
|
||||||
|
g:null})}}}r<p.length?R.setTimeout(f,250):"function"===typeof a&&a()}for(var b=d||document.body,g=b.ownerDocument||document,b=[b.getElementsByTagName("pre"),b.getElementsByTagName("code"),b.getElementsByTagName("xmp")],p=[],k=0;k<b.length;++k)for(var m=0,q=b[k].length;m<q;++m)p.push(b[k][m]);var b=null,c=Date;c.now||(c={now:function(){return+new Date}});var r=0,t=/\blang(?:uage)?-([\w.]+)(?!\S)/,u=/\bprettyprint\b/,e=/\bprettyprinted\b/,x=/pre|xmp/i,z=/^code$/i,w=/^(?:pre|code|xmp)$/i,h={};f()}},
|
||||||
|
S=R.define;"function"===typeof S&&S.amd&&S("google-code-prettify",[],function(){return V})})();return g}();T||t.setTimeout(U,0)})();}()
|
|
@ -0,0 +1 @@
|
||||||
|
pre .str,code .str{color:#65b042}pre .kwd,code .kwd{color:#e28964}pre .com,code .com{color:#aeaeae;font-style:italic}pre .typ,code .typ{color:#89bdff}pre .lit,code .lit{color:#3387cc}pre .pun,code .pun{color:#fff}pre .pln,code .pln{color:#fff}pre .tag,code .tag{color:#89bdff}pre .atn,code .atn{color:#bdb76b}pre .atv,code .atv{color:#65b042}pre .dec,code .dec{color:#3387cc}pre.prettyprint,code.prettyprint{background-color:#000;-moz-border-radius:8px;-webkit-border-radius:8px;-o-border-radius:8px;-ms-border-radius:8px;-khtml-border-radius:8px;border-radius:8px}pre.prettyprint{width:95%;margin:1em auto;padding:1em;white-space:pre-wrap}ol.linenums{margin-top:0;margin-bottom:0;color:#aeaeae}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}@media print{pre .str,code .str{color:#060}pre .kwd,code .kwd{color:#006;font-weight:bold}pre .com,code .com{color:#600;font-style:italic}pre .typ,code .typ{color:#404;font-weight:bold}pre .lit,code .lit{color:#044}pre .pun,code .pun{color:#440}pre .pln,code .pln{color:#000}pre .tag,code .tag{color:#006;font-weight:bold}pre .atn,code .atn{color:#404}pre .atv,code .atv{color:#060}}
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,96 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
Atom One Dark by Daniel Gamage
|
||||||
|
Original One Dark Syntax theme from https://github.com/atom/one-dark-syntax
|
||||||
|
|
||||||
|
base: #282c34
|
||||||
|
mono-1: #abb2bf
|
||||||
|
mono-2: #818896
|
||||||
|
mono-3: #5c6370
|
||||||
|
hue-1: #56b6c2
|
||||||
|
hue-2: #61aeee
|
||||||
|
hue-3: #c678dd
|
||||||
|
hue-4: #98c379
|
||||||
|
hue-5: #e06c75
|
||||||
|
hue-5-2: #be5046
|
||||||
|
hue-6: #d19a66
|
||||||
|
hue-6-2: #e6c07b
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
.hljs {
|
||||||
|
display: block;
|
||||||
|
overflow-x: auto;
|
||||||
|
padding: 0.5em;
|
||||||
|
color: #abb2bf;
|
||||||
|
background: #282c34;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-comment,
|
||||||
|
.hljs-quote {
|
||||||
|
color: #5c6370;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-doctag,
|
||||||
|
.hljs-keyword,
|
||||||
|
.hljs-formula {
|
||||||
|
color: #c678dd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-section,
|
||||||
|
.hljs-name,
|
||||||
|
.hljs-selector-tag,
|
||||||
|
.hljs-deletion,
|
||||||
|
.hljs-subst {
|
||||||
|
color: #e06c75;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-literal {
|
||||||
|
color: #56b6c2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-string,
|
||||||
|
.hljs-regexp,
|
||||||
|
.hljs-addition,
|
||||||
|
.hljs-attr,
|
||||||
|
.hljs-meta-string {
|
||||||
|
color: #98c379;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-built_in,
|
||||||
|
.hljs-class .hljs-title {
|
||||||
|
color: #e6c07b;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-attr,
|
||||||
|
.hljs-variable,
|
||||||
|
.hljs-template-variable,
|
||||||
|
.hljs-type,
|
||||||
|
.hljs-selector-class,
|
||||||
|
.hljs-selector-attr,
|
||||||
|
.hljs-selector-pseudo,
|
||||||
|
.hljs-number {
|
||||||
|
color: #d19a66;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-symbol,
|
||||||
|
.hljs-bullet,
|
||||||
|
.hljs-link,
|
||||||
|
.hljs-meta,
|
||||||
|
.hljs-selector-id,
|
||||||
|
.hljs-title {
|
||||||
|
color: #61aeee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-emphasis {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-strong {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hljs-link {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user