fixup! use legacy vars

This commit is contained in:
tophf 2022-07-28 23:29:25 +03:00
parent 4bfbd2e631
commit 56cd6e90a7
3 changed files with 132 additions and 96 deletions

View File

@ -115,7 +115,7 @@ const updateMan = (() => {
} = opts; } = opts;
if (!id) id = style.id; if (!id) id = style.id;
const {md5Url} = style; const {md5Url} = style;
let ucd = style.usercssData; let {usercssData: ucd, updateUrl} = style;
let res, state; let res, state;
try { try {
await checkIfEdited(); await checkIfEdited();
@ -151,9 +151,11 @@ const updateMan = (() => {
if (md5 === style.originalMd5 && style.originalDigest && !ignoreDigest) { if (md5 === style.originalMd5 && style.originalDigest && !ignoreDigest) {
return Promise.reject(STATES.SAME_MD5); return Promise.reject(STATES.SAME_MD5);
} }
let varsUrl = '';
if (!ucd) { if (!ucd) {
ucd = true; ucd = {};
style.updateUrl = `${URLS.uso}api/v1/styles/${md5Url.match(/\/(\d+)/)[1]}`; varsUrl = updateUrl;
updateUrl = style.updateUrl = `${URLS.uso}api/v1/styles/${md5Url.match(/\/(\d+)/)[1]}`;
} }
usoSpooferStart(); usoSpooferStart();
let json; let json;
@ -161,6 +163,7 @@ const updateMan = (() => {
json = await tryDownload(style.updateUrl, {responseType: 'json'}); json = await tryDownload(style.updateUrl, {responseType: 'json'});
json = await updateUsercss(json.css) || json = await updateUsercss(json.css) ||
(await API.uso.toUsercss(json)).style; (await API.uso.toUsercss(json)).style;
if (varsUrl) await API.uso.useVarsUrl(json, varsUrl);
} finally { } finally {
usoSpooferStop(); usoSpooferStop();
} }

View File

@ -2,18 +2,31 @@
/* global usercssMan */ /* global usercssMan */
'use strict'; 'use strict';
/* exported usoApi */ const usoApi = {};
const usoApi = {
(() => {
const pingers = {};
usoApi.pingback = (usoId, delay) => {
clearTimeout(pingers[usoId]);
delete pingers[usoId];
if (delay > 0) {
return new Promise(resolve => (pingers[usoId] = setTimeout(ping, delay, usoId, resolve)));
} else if (delay !== false) {
return ping(usoId);
}
};
/** /**
* Replicating USO-Archive format * Replicating USO-Archive format
* https://github.com/33kk/uso-archive/blob/flomaster/lib/uso.js * https://github.com/33kk/uso-archive/blob/flomaster/lib/uso.js
* https://github.com/33kk/uso-archive/blob/flomaster/lib/converters.js * https://github.com/33kk/uso-archive/blob/flomaster/lib/converters.js
*/ */
async toUsercss(data, {metaOnly = true} = {}) { usoApi.toUsercss = async (data, {metaOnly = true, varsUrl} = {}) => {
const badKeys = {}; const badKeys = {};
const newKeys = []; const newKeys = [];
const descr = JSON.stringify(data.description.trim()); const descr = JSON.stringify(data.description.trim());
const vars = (data.style_settings || []).map(makeVar).join(''); const vars = (data.style_settings || []).map(makeVar, {badKeys, newKeys}).join('');
const sourceCode = `\ const sourceCode = `\
/* ==UserStyle== /* ==UserStyle==
@name ${data.name} @name ${data.name}
@ -23,9 +36,58 @@ const usoApi = {
@author ${(data.user || {}).name || '?'} @author ${(data.user || {}).name || '?'}
@license ${makeLicense(data.license)}${vars ? '\n@preprocessor uso' + vars : ''}` @license ${makeLicense(data.license)}${vars ? '\n@preprocessor uso' + vars : ''}`
.replace(/\*\//g, '*\\/') + .replace(/\*\//g, '*\\/') +
`==/UserStyle== */\n${newKeys[0] ? useNewKeys(data.css) : data.css}`; `==/UserStyle== */\n${newKeys[0] ? useNewKeys(data.css, badKeys) : data.css}`;
const res = await usercssMan.build({sourceCode, metaOnly}); const {style} = await usercssMan.build({sourceCode, metaOnly});
return Object.assign(res, {badKeys, newKeys}); usoApi.useVarsUrl(style, varsUrl);
return {style, badKeys, newKeys};
};
usoApi.useVarsUrl = (style, url) => {
if (!/\?ik-/.test(url)) {
return;
}
const cfg = {badKeys: {}, newKeys: []};
const {vars} = style.usercssData;
if (!vars) {
return;
}
for (let [key, val] of new URLSearchParams(url.split('?')[1])) {
if (!key.startsWith('ik-')) continue;
key = makeKey(key.slice(3), cfg);
const v = vars[key];
if (!v) continue;
if (v.options) {
let sel = val.startsWith('ik-') && optByName(v, makeKey(val.slice(3), cfg));
if (!sel) {
key += '-custom';
sel = optByName(v, key + '-dropdown');
if (sel) vars[key].value = val;
}
if (sel) v.value = sel.name;
} else {
v.value = val;
}
}
return true;
};
function ping(id, resolve) {
return fetch(`${URLS.uso}styles/install/${id}?source=stylish-ch`)
.then(resolve);
}
function makeKey(key, {badKeys, newKeys}) {
let res = badKeys[key];
if (!res) {
res = key.replace(/[^-\w]/g, '-');
res += newKeys.includes(res) ? '-' : '';
if (key !== res) {
badKeys[key] = res;
newKeys.push(res);
}
}
return res;
}
function makeLicense(s) { function makeLicense(s) {
return !s ? 'NO-REDISTRIBUTION' : return !s ? 'NO-REDISTRIBUTION' :
@ -40,8 +102,9 @@ const usoApi = {
install_key: ik, install_key: ik,
style_setting_options: opts, style_setting_options: opts,
}) { }) {
const cfg = this;
let value, suffix; let value, suffix;
ik = makeKey(ik); ik = makeKey(ik, cfg);
label = JSON.stringify(label); label = JSON.stringify(label);
switch (type) { switch (type) {
@ -69,7 +132,7 @@ const usoApi = {
for (const o of opts) { for (const o of opts) {
const def = o.default ? '*' : ''; const def = o.default ? '*' : '';
const val = o.value; const val = o.value;
const s = ` ${makeKey(o.install_key)} ${JSON.stringify(o.label + def)} <<<EOT${ const s = ` ${makeKey(o.install_key, cfg)} ${JSON.stringify(o.label + def)} <<<EOT${
val.includes('\n') ? '\n' : ' '}${val} EOT;\n`; val.includes('\n') ? '\n' : ' '}${val} EOT;\n`;
value = def ? s + value : value + s; value = def ? s + value : value + s;
} }
@ -82,43 +145,13 @@ const usoApi = {
return `\n@advanced ${type} ${ik} ${label} ${value}${suffix || ''}`; return `\n@advanced ${type} ${ik} ${label} ${value}${suffix || ''}`;
} }
function makeKey(key) { function optByName(v, name) {
let res = badKeys[key]; return v.options.find(o => o.name === name);
if (!res) {
res = key.replace(/[^-\w]/g, '-');
res += newKeys.includes(res) ? '-' : '';
if (key !== res) {
badKeys[key] = res;
newKeys.push(res);
}
}
return res;
} }
function useNewKeys(css) { function useNewKeys(css, badKeys) {
const rxsKeys = stringAsRegExp(Object.keys(badKeys).join('\n'), '', true).replace(/\n/g, '|'); const rxsKeys = stringAsRegExp(Object.keys(badKeys).join('\n'), '', true).replace(/\n/g, '|');
const rxUsoVars = new RegExp(`(/\\*\\[\\[)(${rxsKeys})(?=]]\\*/)`, 'g'); const rxUsoVars = new RegExp(`(/\\*\\[\\[)(${rxsKeys})(?=]]\\*/)`, 'g');
return css.replace(rxUsoVars, (s, a, key) => a + badKeys[key]); return css.replace(rxUsoVars, (s, a, key) => a + badKeys[key]);
} }
},
};
(() => {
const timers = {};
usoApi.pingback = (usoId, delay) => {
clearTimeout(timers[usoId]);
delete timers[usoId];
if (delay > 0) {
return new Promise(resolve => {
timers[usoId] = setTimeout(ping, delay, usoId, resolve);
});
} else if (delay !== false) {
return ping(usoId);
}
};
function ping(id, resolve) {
return fetch(`${URLS.uso}styles/install/${id}?source=stylish-ch`).then(resolve);
}
})(); })();

View File

@ -108,7 +108,7 @@
async function buildStyle() { async function buildStyle() {
if (!pageData) pageData = await (await fetch(apiUrl)).json(); if (!pageData) pageData = await (await fetch(apiUrl)).json();
({style, badKeys} = await API.uso.toUsercss(pageData)); ({style, badKeys} = await API.uso.toUsercss(pageData, {varsUrl: dup.updateUrl}));
Object.assign(style, { Object.assign(style, {
md5Url, md5Url,
id: dup.id, id: dup.id,