diff --git a/background/background.js b/background/background.js index 00a914b6..404639e5 100644 --- a/background/background.js +++ b/background/background.js @@ -177,6 +177,8 @@ msg.on((msg, sender) => { //#endregion Promise.all([ + browser.extension.isAllowedFileSchemeAccess() + .then(res => API.data.set('hasFileAccess', res)), bgReady.styles, /* These are loaded conditionally. Each item uses `require` individually so IDE can jump to the source and track usage. */ diff --git a/background/style-manager.js b/background/style-manager.js index 0ae6c45e..c71a70ba 100644 --- a/background/style-manager.js +++ b/background/style-manager.js @@ -1,5 +1,5 @@ /* 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 calcStyleDigest styleCodeEmpty styleSectionGlobal */// sections-util.js /* global db */ @@ -480,7 +480,7 @@ const styleMan = (() => { async function init() { const styles = await db.exec('getAll') || []; - const updated = styles.filter(fixKnownProblems); + const updated = await Promise.all(styles.map(fixKnownProblems).filter(Boolean)); if (updated.length) { await db.exec('putMany', updated); } @@ -492,7 +492,7 @@ const styleMan = (() => { bgReady._resolveStyles(); } - function fixKnownProblems(style) { + function fixKnownProblems(style, initIndex, initArray) { let res = 0; for (const key in MISSING_PROPS) { if (!style[key]) { @@ -536,7 +536,17 @@ const styleMan = (() => { if (!style.url) res = style.url = 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) { diff --git a/background/update-manager.js b/background/update-manager.js index 9797c115..0c84cef8 100644 --- a/background/update-manager.js +++ b/background/update-manager.js @@ -223,7 +223,9 @@ const updateMan = (() => { let err; if (!delta && !ignoreDigest) { // re-install is invalid in a soft upgrade - err = response === style.sourceCode ? STATES.SAME_CODE : STATES.SAME_VERSION; + err = response === style.sourceCode + ? STATES.SAME_CODE + : !URLS.isLocalhost(updateUrl) && STATES.SAME_VERSION; } if (delta < 0) { // downgrade is always invalid diff --git a/edit/edit.css b/edit/edit.css index 61f52e65..ebaca302 100644 --- a/edit/edit.css +++ b/edit/edit.css @@ -435,6 +435,9 @@ input:invalid { content: counter(codebox) ": " attr(data-text); margin-left: 0.25rem; } +.single-editor .applies-to { + border-width: 1px 0; +} .single-editor .applies-to > label::before { content: attr(data-index) ":"; margin-right: 0.25rem; @@ -589,9 +592,6 @@ body:not(.find-open) [data-match-highlight-count="1"] .CodeMirror-selection-high align-items: flex-start; min-height: 30px; flex-wrap: wrap; - background-color: #f7f7f7; /* .CodeMirror-gutters */ - border: solid #bbb; - border-width: 1px 0; } .applies-to.error { background-color: #f002; @@ -988,9 +988,18 @@ body.linter-disabled .hidden-unless-compact { margin-top: .75rem; } +.single-editor { + position: relative; + height: 100%; +} .single-editor .CodeMirror { - width: 100%; - height: 100vh; /* WARNING! Don't use 100% as it's dead slow */ +/* WARNING! If you change this or .single-editor make sure editor opens huge styles like GitHub Dark instantly */ + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + height: auto; border: none; outline: none; } @@ -1038,10 +1047,11 @@ body.linter-disabled .hidden-unless-compact { padding: .5rem 1rem .5rem .5rem; } .fixed-header { + --fixed-height: 40px; padding-top: var(--fixed-padding); } .fixed-header #header { - min-height: 40px; + min-height: var(--fixed-height); position: fixed; top: 0; left: 0; @@ -1053,6 +1063,9 @@ body.linter-disabled .hidden-unless-compact { .fixed-header #options { display: none !important; } + .fixed-header #details-wrapper { + padding-top: calc((var(--fixed-height) - 1.2rem) / 2); /* 1.2 is the normal line height */ + } #header summary + *, #lint > .lint-scroll-container { margin-left: 1rem; diff --git a/install-usercss/install-usercss.js b/install-usercss/install-usercss.js index edbeecb6..6c79a9fd 100644 --- a/install-usercss/install-usercss.js +++ b/install-usercss/install-usercss.js @@ -1,6 +1,6 @@ /* global $ $create $createLink $$remove showSpinner */// dom.js /* global API */// msg.js -/* global closeCurrentTab deepEqual */// toolbox.js +/* global URLS closeCurrentTab deepEqual */// toolbox.js /* global messageBox */ /* global prefs */ /* global preinit */ @@ -61,12 +61,18 @@ setTimeout(() => !cm && showSpinner($('#header')), 200); '/js/color/color-view', ])); - ({tabId, initialUrl} = await preinit); + ({tabId, initialUrl} = preinit); liveReload = initLiveReload(); - const {dup, style, error, sourceCode} = await preinit.ready; + const [ + {dup, style, error, sourceCode}, + hasFileAccess, + ] = await Promise.all([ + preinit.ready, + API.data.get('hasFileAccess'), + ]); if (!style && sourceCode == null) { - messageBox.alert(isNaN(error) ? error : 'HTTP Error ' + error, 'pre'); + messageBox.alert(isNaN(error) ? `${error}` : 'HTTP Error ' + error, 'pre'); return; } await scriptsReady; @@ -118,7 +124,7 @@ setTimeout(() => !cm && showSpinner($('#header')), 200); checker.checked = true; // there is no way to "unset" updateUrl, you can only overwrite it. checker.disabled = true; - } else if (updateUrl.protocol !== 'file:') { + } else if (updateUrl.protocol !== 'file:' || hasFileAccess) { checker.checked = true; style.updateUrl = updateUrl.href; } @@ -136,7 +142,7 @@ setTimeout(() => !cm && showSpinner($('#header')), 200); }; preferScheme.onchange(); - if (initialUrl.startsWith('file:')) { + if (URLS.isLocalhost(initialUrl)) { $('.live-reload input').onchange = liveReload.onToggled; } else { $('.live-reload').remove(); diff --git a/install-usercss/preinit.js b/install-usercss/preinit.js index 6f37f2e0..8451e095 100644 --- a/install-usercss/preinit.js +++ b/install-usercss/preinit.js @@ -25,7 +25,10 @@ const preinit = (() => { function DirectDownloader() { let oldCode = null; return async () => { - const code = await download(initialUrl); + const code = await download(initialUrl, { + // Disabling cache on http://localhost otherwise the recheck delay gets too big + headers: {'Cache-Control': 'no-cache, no-store'}, + }); if (oldCode !== code) { oldCode = code; return code; diff --git a/js/csslint/parserlib.js b/js/csslint/parserlib.js index 2d6fa3d5..cdef79a3 100644 --- a/js/csslint/parserlib.js +++ b/js/csslint/parserlib.js @@ -458,7 +458,7 @@ self.parserlib = (() => { 'pause': 1, 'pause-after': 1, 'pause-before': 1, - 'perspective': 'none | ', + 'perspective': 'none | ', 'perspective-origin': '', 'phonemes': 1, 'pitch': 1, @@ -492,7 +492,7 @@ self.parserlib = (() => { 'ruby-position': 1, 'ruby-span': 1, - 'scale': 'none | {1,3}', + 'scale': 'none | {1,3}', 'scroll-behavior': 'auto | smooth', 'scroll-margin': '{1,4}', @@ -579,7 +579,7 @@ self.parserlib = (() => { 'transform': 'none | +', 'transform-box': 'border-box | fill-box | view-box', 'transform-origin': '', - 'transform-style': 'auto | flat | preserve-3d', + 'transform-style': 'flat | preserve-3d', 'transition': '#', 'transition-delay': '