stylus/install-usercss/install-usercss.js

213 lines
6.1 KiB
JavaScript
Raw Normal View History

2017-09-25 10:45:44 +00:00
/* global CodeMirror semverCompare makeLink closeCurrentTab */
2017-09-24 03:39:04 +00:00
'use strict';
(function () {
const params = getParams();
const port = chrome.tabs.connect(
Number(params.tabId),
{name: 'usercss-install', frameId: 0}
);
port.postMessage({method: 'getSourceCode'});
port.onMessage.addListener(msg => {
switch (msg.method) {
case 'getSourceCodeResponse':
2017-09-24 08:54:21 +00:00
if (msg.error) {
alert(msg.error);
} else {
initSourceCode(msg.sourceCode);
}
2017-09-24 03:39:04 +00:00
break;
}
});
2017-09-25 10:43:55 +00:00
port.onDisconnect.addListener(closeCurrentTab);
2017-09-24 03:39:04 +00:00
const cm = CodeMirror.fromTextArea($('.code textarea'), {readOnly: true});
function runtimeSend(request) {
return new Promise((resolve, reject) => {
chrome.runtime.sendMessage(
request,
({status, result}) => (status === 'error' ? reject : resolve)(result)
);
});
}
function install(style) {
const request = Object.assign(style, {
method: 'saveUsercss',
reason: 'update'
});
return runtimeSend(request)
.then(result => {
$$('.warning')
.forEach(el => el.remove());
2017-09-24 08:54:21 +00:00
$('.install').textContent = 'Installed';
$('.install').disabled = true;
$('.install').classList.add('installed');
$('.set-update-url input[type=checkbox]').disabled = true;
$('.set-update-url').title = result.updateUrl ?
2017-09-24 03:39:04 +00:00
t('installUpdateFrom', result.updateUrl) : '';
window.dispatchEvent(new CustomEvent('installed', {detail: result}));
})
.catch(err => {
alert(chrome.i18n.getMessage('styleInstallFailed', String(err)));
});
}
function initSourceCode(sourceCode) {
cm.setValue(sourceCode);
runtimeSend({
method: 'buildUsercss',
sourceCode,
checkDup: true
}).then(init, initError);
}
function initError(err) {
$('.main').insertBefore(buildWarning(err), $('.main').childNodes[0]);
}
function buildWarning(err) {
return $element({className: 'warning', appendChild: [
t('parseUsercssError'),
$element({tag: 'pre', textContent: String(err)})
]});
}
function init({style, dup}) {
const data = style.usercssData;
const dupData = dup && dup.usercssData;
const versionTest = dup && semverCompare(data.version, dupData.version);
2017-09-24 08:54:21 +00:00
// update UI
2017-09-24 03:39:04 +00:00
if (versionTest < 0) {
$('.actions').parentNode.insertBefore(
$element({className: 'warning', textContent: t('versionInvalidOlder')}),
$('.actions')
);
}
$('button.install').onclick = () => {
if (dup) {
if (confirm(chrome.i18n.getMessage('styleInstallOverwrite', [
data.name, dupData.version, data.version
]))) {
install(style);
}
} else if (confirm(chrome.i18n.getMessage('styleInstall', [data.name]))) {
install(style);
}
};
2017-09-24 08:54:21 +00:00
// set updateUrl
2017-09-24 03:39:04 +00:00
const setUpdate = $('.set-update-url input[type=checkbox]');
const updateUrl = new URL(params.updateUrl);
2017-09-24 08:54:21 +00:00
$('.set-update-url > span').textContent = t('installUpdateFromLabel', updateUrl.href);
2017-09-24 03:39:04 +00:00
if (dup && dup.updateUrl === updateUrl.href) {
setUpdate.checked = true;
// there is no way to "unset" updateUrl, you can only overwrite it.
setUpdate.disabled = true;
} else if (!dup && updateUrl.protocol !== 'file:') {
setUpdate.checked = true;
style.updateUrl = updateUrl.href;
}
setUpdate.onchange = e => {
if (e.target.checked) {
style.updateUrl = updateUrl.href;
} else {
delete style.updateUrl;
}
};
2017-09-24 08:54:21 +00:00
// update editor
cm.setPreprocessor(data.preprocessor);
2017-09-24 03:39:04 +00:00
// update metas
2017-09-25 10:21:11 +00:00
document.title = `${installButtonLabel()} ${data.name}`;
2017-09-24 03:39:04 +00:00
$('.install').textContent = installButtonLabel();
$('.set-update-url').title = dup && dup.updateUrl && t('installUpdateFrom', dup.updateUrl) || '';
$('.meta-name').textContent = data.name;
$('.meta-version').textContent = data.version;
$('.meta-description').textContent = data.description;
if (data.author) {
$('.meta-author').textContent = data.author;
} else {
$('.meta-author').parentNode.remove();
}
if (data.license) {
$('.meta-license').textContent = data.license;
} else {
$('.meta-license').parentNode.remove();
}
getAppliesTo(style).forEach(pattern =>
$('.applies-to').appendChild($element({tag: 'li', textContent: pattern}))
);
2017-09-25 10:21:11 +00:00
const externalLink = makeExternalLink();
if (externalLink) {
2017-09-25 10:43:55 +00:00
$('.external-link').appendChild(externalLink);
2017-09-25 10:21:11 +00:00
}
2017-09-24 03:39:04 +00:00
2017-09-25 10:21:11 +00:00
function makeExternalLink() {
2017-09-24 03:39:04 +00:00
const urls = [];
if (data.homepageURL) {
urls.push([data.homepageURL, t('externalHomepage')]);
}
if (data.supportURL) {
urls.push([data.supportURL, t('externalSupport')]);
}
if (urls.length) {
return $element({appendChild: [
$element({tag: 'h3', textContent: t('externalLink')}),
$element({tag: 'ul', appendChild: urls.map(args =>
$element({tag: 'li', appendChild: makeLink(...args)})
)})
]});
}
}
function installButtonLabel() {
return t(!dup ? 'installButton' :
versionTest > 0 ? 'installButtonUpdate' : 'installButtonReinstall');
}
}
function getParams() {
// URL.searchParams needs chrome 51+
const {search} = location;
const result = {};
for (const param of search.slice(1).split('&')) {
let key, value;
if (param.includes('=')) {
[key, value] = param.split('=').map(decodeURIComponent);
} else {
key = decodeURIComponent(param);
value = true;
}
result[key] = value;
}
return result;
}
function getAppliesTo(style) {
function *_gen() {
for (const section of style.sections) {
for (const type of ['urls', 'urlPrefixes', 'domains', 'regexps']) {
if (section[type]) {
yield *section[type];
}
}
}
}
const result = [..._gen()];
if (!result.length) {
result.push(chrome.i18n.getMessage('appliesToEverything'));
}
return result;
}
})();