add vars after @import in compiled code (#1348)

fixes #1347
This commit is contained in:
tophf 2021-11-14 11:00:12 +03:00 committed by GitHub
parent b17eef4053
commit 19ebeedf6a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 40 additions and 6 deletions

View File

@ -1,5 +1,5 @@
/* global API msg */// msg.js /* global API msg */// msg.js
/* global CHROME URLS stringAsRegExp tryRegExp tryURL */// toolbox.js /* global CHROME URLS isEmptyObj stringAsRegExp tryRegExp tryURL */// toolbox.js
/* global bgReady compareRevision */// common.js /* global bgReady compareRevision */// common.js
/* global calcStyleDigest styleCodeEmpty styleSectionGlobal */// sections-util.js /* global calcStyleDigest styleCodeEmpty styleSectionGlobal */// sections-util.js
/* global db */ /* global db */
@ -467,7 +467,7 @@ const styleMan = (() => {
async function init() { async function init() {
const styles = await db.exec('getAll') || []; const styles = await db.exec('getAll') || [];
const updated = styles.filter(fixKnownProblems); const updated = await Promise.all(styles.map(fixKnownProblems).filter(Boolean));
if (updated.length) { if (updated.length) {
await db.exec('putMany', updated); await db.exec('putMany', updated);
} }
@ -479,7 +479,7 @@ const styleMan = (() => {
bgReady._resolveStyles(); bgReady._resolveStyles();
} }
function fixKnownProblems(style) { function fixKnownProblems(style, initIndex, initArray) {
let res = 0; let res = 0;
for (const key in MISSING_PROPS) { for (const key in MISSING_PROPS) {
if (!style[key]) { if (!style[key]) {
@ -523,7 +523,17 @@ const styleMan = (() => {
if (!style.url) res = style.url = url; if (!style.url) res = style.url = url;
if (!style.installationUrl) res = style.installationUrl = url; if (!style.installationUrl) res = style.installationUrl = url;
} }
return Boolean(res); /* @import must precede `vars` that we add at beginning */
if (
initArray &&
!isEmptyObj((style.usercssData || {}).vars) &&
style.sections.some(({code}) =>
code.startsWith(':root {\n --') &&
/@import\s/i.test(code))
) {
return usercssMan.buildCode(style);
}
return res && style;
} }
function urlMatchStyle(query, style) { function urlMatchStyle(query, style) {

View File

@ -4678,6 +4678,7 @@ self.parserlib = (() => {
//#endregion //#endregion
//#region PUBLIC API //#region PUBLIC API
/** @namespace parserlib */
return { return {
css: { css: {
Colors, Colors,

View File

@ -71,12 +71,15 @@ function styleCodeEmpty(code) {
if (!code) { if (!code) {
return true; return true;
} }
let lastIndex = 0;
const rx = /\s+|\/\*([^*]|\*(?!\/))*(\*\/|$)|@namespace[^;]+;|@charset[^;]+;/giyu; const rx = /\s+|\/\*([^*]|\*(?!\/))*(\*\/|$)|@namespace[^;]+;|@charset[^;]+;/giyu;
while (rx.exec(code)) { while (rx.exec(code)) {
if (rx.lastIndex === code.length) { lastIndex = rx.lastIndex;
if (lastIndex === code.length) {
return true; return true;
} }
} }
styleCodeEmpty.lastIndex = lastIndex;
return false; return false;
} }

View File

@ -12,7 +12,7 @@ const BUILDERS = Object.assign(Object.create(null), {
varDef = ':root {\n' + varDef + '}\n'; varDef = ':root {\n' + varDef + '}\n';
for (const section of sections) { for (const section of sections) {
if (!styleCodeEmpty(section.code)) { if (!styleCodeEmpty(section.code)) {
section.code = varDef + section.code; spliceCssAfterGlobals(section, varDef, styleCodeEmpty.lastIndex);
} }
} }
}, },
@ -165,3 +165,23 @@ function simplifyUsercssVars(vars) {
va.value = value; va.value = value;
} }
} }
function spliceCssAfterGlobals(section, newText, after) {
const {code} = section;
const RX_IMPORT = /@import\s/gi;
RX_IMPORT.lastIndex = after;
if (RX_IMPORT.test(code)) {
require(['/js/csslint/parserlib']); /* global parserlib */
const parser = new parserlib.css.Parser();
parser._tokenStream = new parserlib.css.TokenStream(code);
parser._sheetGlobals();
const {col, line, offset} = parser._tokenStream._token;
// normalizing newlines in non-usercss to match line:col from parserlib
if ((code.indexOf('\r') + 1 || 1e99) - 1 < offset) {
after = col + code.split('\n', line).reduce((len, s) => len + s.length + 1, 0);
} else {
after = offset + 1;
}
}
section.code = (after ? code.slice(0, after) + '\n' : '') + newText + code.slice(after);
}