Merge branch 'master' of https://github.com/openstyles/stylus
This commit is contained in:
commit
0366c8508f
|
@ -739,9 +739,9 @@
|
||||||
"message": "Search contents",
|
"message": "Search contents",
|
||||||
"description": "Label for the search filter textbox on the Manage styles page"
|
"description": "Label for the search filter textbox on the Manage styles page"
|
||||||
},
|
},
|
||||||
"searchStylesTooltip": {
|
"searchStylesHelp": {
|
||||||
"message": "To show styles for a URL, prefix it with 'url:'\nFor example, url:https://github.com/openstyles/stylus",
|
"message": "</> key focuses the search field.\nPlain text: search within the name, code, homepage URL and sites it is applied to. Words with less than 3 letters are ignored.\nMatching URL: prefix the search with <url:>, e.g. <url:https://github.com/openstyles/stylus>\nRegular expressions: include slashes and flags, e.g. </body.*?\\ba\\b/simguy>\nExact words: wrap the query in double quotes, e.g. <\".header ~ div\">",
|
||||||
"description": "Label for the search filter textbox on the Manage styles page"
|
"description": "Text in the minihelp displayed when clicking (i) icon to the right of the search input field on the Manage styles page"
|
||||||
},
|
},
|
||||||
"sectionAdd": {
|
"sectionAdd": {
|
||||||
"message": "Add another section",
|
"message": "Add another section",
|
||||||
|
|
|
@ -74,7 +74,7 @@
|
||||||
<link rel="stylesheet" href="/edit/codemirror-default.css">
|
<link rel="stylesheet" href="/edit/codemirror-default.css">
|
||||||
|
|
||||||
<template data-id="appliesTo">
|
<template data-id="appliesTo">
|
||||||
<li>
|
<li class="applies-to-item">
|
||||||
<div class="select-resizer">
|
<div class="select-resizer">
|
||||||
<select name="applies-type" class="applies-type style-contributor">
|
<select name="applies-type" class="applies-type style-contributor">
|
||||||
<option value="url" i18n-text="appliesUrlOption"></option>
|
<option value="url" i18n-text="appliesUrlOption"></option>
|
||||||
|
@ -322,7 +322,7 @@
|
||||||
<h2><span id="sections-heading" i18n-text="styleSectionsTitle"></span><svg id="sections-help" class="svg-icon info"><use xlink:href="#svg-icon-help"/></svg></h2>
|
<h2><span id="sections-heading" i18n-text="styleSectionsTitle"></span><svg id="sections-help" class="svg-icon info"><use xlink:href="#svg-icon-help"/></svg></h2>
|
||||||
</section>
|
</section>
|
||||||
<div id="help-popup">
|
<div id="help-popup">
|
||||||
<div class="title"></div><svg id="sections-help" class="svg-icon dismiss"><use xlink:href="#svg-icon-close"/></svg></svg>
|
<div class="title"></div><svg id="sections-help" class="svg-icon dismiss"><use xlink:href="#svg-icon-close"/></svg>
|
||||||
<div class="contents"></div>
|
<div class="contents"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ function createAppliesToLineWidget(cm) {
|
||||||
const THROTTLE_DELAY = 400;
|
const THROTTLE_DELAY = 400;
|
||||||
let TPL, EVENTS, CLICK_ROUTE;
|
let TPL, EVENTS, CLICK_ROUTE;
|
||||||
let widgets = [];
|
let widgets = [];
|
||||||
let fromLine, toLine, styleVariables;
|
let fromLine, toLine, actualStyle;
|
||||||
let initialized = false;
|
let initialized = false;
|
||||||
return {toggle};
|
return {toggle};
|
||||||
|
|
||||||
|
@ -29,28 +29,16 @@ function createAppliesToLineWidget(cm) {
|
||||||
$create('label', t('appliesLabel')),
|
$create('label', t('appliesLabel')),
|
||||||
$create('ul.applies-to-list'),
|
$create('ul.applies-to-list'),
|
||||||
]),
|
]),
|
||||||
listItem:
|
listItem: template.appliesTo,
|
||||||
$create('li.applies-to-item', [
|
|
||||||
$create('select.applies-type', [
|
|
||||||
$create('option', {value: 'url'}, t('appliesUrlOption')),
|
|
||||||
$create('option', {value: 'url-prefix'}, t('appliesUrlPrefixOption')),
|
|
||||||
$create('option', {value: 'domain'}, t('appliesDomainOption')),
|
|
||||||
$create('option', {value: 'regexp'}, t('appliesRegexpOption')),
|
|
||||||
]),
|
|
||||||
$create('input.applies-value', {spellcheck: false}),
|
|
||||||
$create('button.test-regexp', t('styleRegexpTestButton')),
|
|
||||||
$create('button.remove-applies-to', t('appliesRemove')),
|
|
||||||
$create('button.add-applies-to', t('appliesAdd')),
|
|
||||||
]),
|
|
||||||
appliesToEverything:
|
appliesToEverything:
|
||||||
$create('li.applies-to-everything', t('appliesToEverything')),
|
$create('li.applies-to-everything', t('appliesToEverything')),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$('button', TPL.listItem).insertAdjacentElement('beforebegin',
|
||||||
|
$create('button.test-regexp', t('styleRegexpTestButton')));
|
||||||
|
|
||||||
CLICK_ROUTE = {
|
CLICK_ROUTE = {
|
||||||
'.test-regexp': (item, apply) => {
|
'.test-regexp': showRegExpTester,
|
||||||
regExpTester.toggle();
|
|
||||||
regExpTester.update([apply.value.text]);
|
|
||||||
},
|
|
||||||
|
|
||||||
'.remove-applies-to': (item, apply) => {
|
'.remove-applies-to': (item, apply) => {
|
||||||
const applies = item.closest('.applies-to').__applies;
|
const applies = item.closest('.applies-to').__applies;
|
||||||
|
@ -108,20 +96,17 @@ function createAppliesToLineWidget(cm) {
|
||||||
if (typeElement) {
|
if (typeElement) {
|
||||||
const item = target.closest('.applies-to-item');
|
const item = target.closest('.applies-to-item');
|
||||||
const apply = item.__apply;
|
const apply = item.__apply;
|
||||||
changeItem(apply, 'type', typeElement.value);
|
changeItem(item, apply, 'type', typeElement.value);
|
||||||
item.dataset.type = apply.type.text;
|
item.dataset.type = apply.type.text;
|
||||||
|
} else {
|
||||||
|
return EVENTS.oninput.apply(this, arguments);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
oninput({target}) {
|
oninput({target}) {
|
||||||
if (target.matches('.applies-value')) {
|
if (target.matches('.applies-value')) {
|
||||||
const apply = target.closest('.applies-to-item').__apply;
|
const item = target.closest('.applies-to-item');
|
||||||
debounce(changeItem, THROTTLE_DELAY, apply, 'value', target.value);
|
const apply = item.__apply;
|
||||||
}
|
changeItem(item, apply, 'value', target.value);
|
||||||
},
|
|
||||||
onfocus({target}) {
|
|
||||||
if (target.matches('.test-regexp')) {
|
|
||||||
const apply = target.closest('.applies-to-item').__apply;
|
|
||||||
updateRegexpTest(apply);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onclick({target}) {
|
onclick({target}) {
|
||||||
|
@ -136,15 +121,13 @@ function createAppliesToLineWidget(cm) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
styleVariables = $create('style');
|
actualStyle = $create('style');
|
||||||
fromLine = 0;
|
fromLine = 0;
|
||||||
toLine = cm.doc.size;
|
toLine = cm.doc.size;
|
||||||
|
|
||||||
cm.on('change', onChange);
|
cm.on('change', onChange);
|
||||||
cm.on('optionChange', onOptionChange);
|
cm.on('optionChange', onOptionChange);
|
||||||
|
|
||||||
// is it possible to avoid flickering?
|
|
||||||
window.addEventListener('load', updateWidgetStyle);
|
|
||||||
chrome.runtime.onMessage.addListener(onRuntimeMessage);
|
chrome.runtime.onMessage.addListener(onRuntimeMessage);
|
||||||
|
|
||||||
updateWidgetStyle();
|
updateWidgetStyle();
|
||||||
|
@ -158,9 +141,8 @@ function createAppliesToLineWidget(cm) {
|
||||||
widgets.length = 0;
|
widgets.length = 0;
|
||||||
cm.off('change', onChange);
|
cm.off('change', onChange);
|
||||||
cm.off('optionChange', onOptionChange);
|
cm.off('optionChange', onOptionChange);
|
||||||
window.removeEventListener('load', updateWidgetStyle);
|
|
||||||
chrome.runtime.onMessage.removeListener(onRuntimeMessage);
|
chrome.runtime.onMessage.removeListener(onRuntimeMessage);
|
||||||
styleVariables.remove();
|
actualStyle.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
function onChange(cm, event) {
|
function onChange(cm, event) {
|
||||||
|
@ -229,24 +211,112 @@ function createAppliesToLineWidget(cm) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateWidgetStyle() {
|
function updateWidgetStyle() {
|
||||||
const gutterStyle = getComputedStyle(cm.getGutterElement());
|
const MIN_LUMA = .05;
|
||||||
const borderStyle = gutterStyle.borderRightWidth !== '0px' ?
|
const MIN_LUMA_DIFF = .4;
|
||||||
`${gutterStyle.borderRightWidth} ${gutterStyle.borderRightStyle} ${gutterStyle.borderRightColor}` :
|
const color = {
|
||||||
`1px solid ${gutterStyle.color}`;
|
wrapper: getRealColors(cm.display.wrapper),
|
||||||
const id = Date.now();
|
gutter: getRealColors(cm.display.gutters, {
|
||||||
styleVariables.textContent = `
|
bg: 'backgroundColor',
|
||||||
.single-editor {
|
border: 'borderRightColor',
|
||||||
--at-background-color-${id}: ${gutterStyle.backgroundColor};
|
}),
|
||||||
--at-border-top-${id}: ${borderStyle};
|
line: getRealColors('.CodeMirror-linenumber'),
|
||||||
--at-border-bottom-${id}: ${borderStyle};
|
comment: getRealColors('span.cm-comment'),
|
||||||
}
|
};
|
||||||
|
const hasBorder =
|
||||||
|
color.gutter.style.borderRightWidth !== '0px' &&
|
||||||
|
!/transparent|\b0\)/g.test(color.gutter.style.borderRightColor);
|
||||||
|
const diff = {
|
||||||
|
wrapper: Math.abs(color.gutter.bgLuma - color.wrapper.foreLuma),
|
||||||
|
border: hasBorder ? Math.abs(color.gutter.bgLuma - color.gutter.borderLuma) : 0,
|
||||||
|
line: Math.abs(color.gutter.bgLuma - color.line.foreLuma),
|
||||||
|
};
|
||||||
|
const preferLine = diff.line > diff.wrapper || diff.line > MIN_LUMA_DIFF;
|
||||||
|
const fore = preferLine ? color.line.fore : color.wrapper.fore;
|
||||||
|
|
||||||
|
const border = fore.replace(/[\d.]+(?=\))/, MIN_LUMA_DIFF / 2);
|
||||||
|
const borderStyleForced = `1px ${hasBorder ? color.gutter.style.borderRightStyle : 'solid'} ${border}`;
|
||||||
|
|
||||||
|
actualStyle.textContent = `
|
||||||
.applies-to {
|
.applies-to {
|
||||||
background-color: var(--at-background-color-${id});
|
background-color: ${color.gutter.bg};
|
||||||
border-top: var(--at-border-top-${id});
|
border-top: ${borderStyleForced};
|
||||||
border-bottom: var(--at-border-bottom-${id});
|
border-bottom: ${borderStyleForced};
|
||||||
|
}
|
||||||
|
.applies-to label {
|
||||||
|
color: ${fore};
|
||||||
|
}
|
||||||
|
.applies-to input,
|
||||||
|
.applies-to select {
|
||||||
|
background-color: rgba(255, 255, 255, ${
|
||||||
|
Math.max(MIN_LUMA, Math.pow(Math.max(0, color.gutter.bgLuma - MIN_LUMA * 2), 2)).toFixed(2)
|
||||||
|
});
|
||||||
|
border: ${borderStyleForced};
|
||||||
|
transition: none;
|
||||||
|
color: ${fore};
|
||||||
|
}
|
||||||
|
.applies-to .svg-icon.select-arrow {
|
||||||
|
fill: ${fore};
|
||||||
|
transition: none;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
document.documentElement.appendChild(styleVariables);
|
document.documentElement.appendChild(actualStyle);
|
||||||
|
|
||||||
|
function getRealColors(el, targets = {}) {
|
||||||
|
targets.fore = 'color';
|
||||||
|
const colors = {};
|
||||||
|
const done = {};
|
||||||
|
let numDone = 0;
|
||||||
|
let numTotal = 0;
|
||||||
|
for (const k in targets) {
|
||||||
|
colors[k] = {r: 255, g: 255, b: 255, a: 1};
|
||||||
|
numTotal++;
|
||||||
|
}
|
||||||
|
const isDummy = typeof el === 'string';
|
||||||
|
el = isDummy ? cm.display.lineDiv.appendChild($create(el, {style: 'display: none'})) : el;
|
||||||
|
for (let current = el; current; current = current && current.parentElement) {
|
||||||
|
const style = getComputedStyle(current);
|
||||||
|
for (const k in targets) {
|
||||||
|
if (!done[k]) {
|
||||||
|
done[k] = blend(colors[k], style[targets[k]]);
|
||||||
|
numDone += done[k] ? 1 : 0;
|
||||||
|
if (numDone === numTotal) {
|
||||||
|
current = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
colors.style = colors.style || style;
|
||||||
|
}
|
||||||
|
if (isDummy) {
|
||||||
|
el.remove();
|
||||||
|
}
|
||||||
|
for (const k in targets) {
|
||||||
|
const {r, g, b, a} = colors[k];
|
||||||
|
colors[k] = `rgba(${r}, ${g}, ${b}, ${a})`;
|
||||||
|
// https://www.w3.org/TR/AERT#color-contrast
|
||||||
|
colors[k + 'Luma'] = (r * .299 + g * .587 + b * .114) / 256;
|
||||||
|
}
|
||||||
|
return colors;
|
||||||
|
}
|
||||||
|
|
||||||
|
function blend(base, color) {
|
||||||
|
const [r, g, b, a = 255] = (color.match(/\d+/g) || []).map(Number);
|
||||||
|
if (a === 255) {
|
||||||
|
base.r = r;
|
||||||
|
base.g = g;
|
||||||
|
base.b = b;
|
||||||
|
base.a = 1;
|
||||||
|
} else if (a) {
|
||||||
|
const mixedA = 1 - (1 - a / 255) * (1 - base.a);
|
||||||
|
const q1 = a / 255 / mixedA;
|
||||||
|
const q2 = base.a * (1 - mixedA) / mixedA;
|
||||||
|
base.r = Math.round(r * q1 + base.r * q2);
|
||||||
|
base.g = Math.round(g * q1 + base.g * q2);
|
||||||
|
base.b = Math.round(b * q1 + base.b * q2);
|
||||||
|
base.a = mixedA;
|
||||||
|
}
|
||||||
|
return Math.abs(base.a - 1) < 1e-3;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function doUpdate() {
|
function doUpdate() {
|
||||||
|
@ -406,14 +476,14 @@ function createAppliesToLineWidget(cm) {
|
||||||
return el;
|
return el;
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeItem(apply, part, newText) {
|
function changeItem(itemElement, apply, part, newText) {
|
||||||
if (!apply) {
|
if (!apply) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
part = apply[part];
|
part = apply[part];
|
||||||
const range = part.mark.find();
|
const range = part.mark.find();
|
||||||
part.mark.clear();
|
part.mark.clear();
|
||||||
newText = newText.replace(/\\/g, '\\\\');
|
newText = unescapeDoubleslash(newText).replace(/\\/g, '\\\\');
|
||||||
cm.replaceRange(newText, range.from, range.to, 'appliesTo');
|
cm.replaceRange(newText, range.from, range.to, 'appliesTo');
|
||||||
part.mark = cm.markText(
|
part.mark = cm.markText(
|
||||||
range.from,
|
range.from,
|
||||||
|
@ -432,13 +502,8 @@ function createAppliesToLineWidget(cm) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateRegexpTest(apply);
|
if (apply.type.text === 'regexp' && apply.value.text.trim()) {
|
||||||
}
|
showRegExpTester(itemElement);
|
||||||
|
|
||||||
function updateRegexpTest(apply) {
|
|
||||||
if (apply.type.text === 'regexp') {
|
|
||||||
const rx = apply.value.text.trim();
|
|
||||||
regExpTester.update(rx ? [rx] : {});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -450,7 +515,6 @@ function createAppliesToLineWidget(cm) {
|
||||||
const valueStart = typeEnd + 1 + Number(isQuoted);
|
const valueStart = typeEnd + 1 + Number(isQuoted);
|
||||||
const valueEnd = valueStart + valueText.length;
|
const valueEnd = valueStart + valueText.length;
|
||||||
const end = valueEnd + Number(isQuoted) + 1;
|
const end = valueEnd + Number(isQuoted) + 1;
|
||||||
const hasSingleEscapes = /([^\\]|^)\\([^\\]|$)/.test(valueText);
|
|
||||||
return {
|
return {
|
||||||
start,
|
start,
|
||||||
type: {
|
type: {
|
||||||
|
@ -459,7 +523,7 @@ function createAppliesToLineWidget(cm) {
|
||||||
end: typeEnd,
|
end: typeEnd,
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
text: hasSingleEscapes ? valueText : valueText.replace(/\\\\/g, '\\'),
|
text: unescapeDoubleslash(valueText),
|
||||||
start: valueStart,
|
start: valueStart,
|
||||||
end: valueEnd,
|
end: valueEnd,
|
||||||
},
|
},
|
||||||
|
@ -505,4 +569,17 @@ function createAppliesToLineWidget(cm) {
|
||||||
const first = s.charAt(0);
|
const first = s.charAt(0);
|
||||||
return (first === '"' || first === "'") && s.endsWith(first) ? s.slice(1, -1) : s;
|
return (first === '"' || first === "'") && s.endsWith(first) ? s.slice(1, -1) : s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function unescapeDoubleslash(s) {
|
||||||
|
const hasSingleEscapes = /([^\\]|^)\\([^\\]|$)/.test(s);
|
||||||
|
return hasSingleEscapes ? s : s.replace(/\\\\/g, '\\');
|
||||||
|
}
|
||||||
|
|
||||||
|
function showRegExpTester(item) {
|
||||||
|
regExpTester.toggle(true);
|
||||||
|
regExpTester.update(
|
||||||
|
item.closest('.applies-to').__applies
|
||||||
|
.filter(a => a.type.text === 'regexp')
|
||||||
|
.map(a => unescapeDoubleslash(a.value.text)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,3 @@
|
||||||
position: absolute;
|
position: absolute;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.CodeMirror-activeline .applies-to ul {
|
|
||||||
z-index: 2;
|
|
||||||
}
|
|
||||||
|
|
|
@ -193,7 +193,8 @@ CodeMirror.hint && (() => {
|
||||||
string[pos - 3] === ']' &&
|
string[pos - 3] === ']' &&
|
||||||
string[pos - 4] === ']') {
|
string[pos - 4] === ']') {
|
||||||
const vars = typeof editor !== 'undefined' && (editor.getStyle().usercssData || {}).vars;
|
const vars = typeof editor !== 'undefined' && (editor.getStyle().usercssData || {}).vars;
|
||||||
if (vars && Object.hasOwnProperty.call(vars, string.slice(start + 4, pos - 4))) {
|
const name = vars && string.slice(start + 4, pos - 4);
|
||||||
|
if (vars && Object.hasOwnProperty.call(vars, name.endsWith('-rgb') ? name.slice(0, -4) : name)) {
|
||||||
token[0] = USO_VALID_VAR;
|
token[0] = USO_VALID_VAR;
|
||||||
} else {
|
} else {
|
||||||
token[0] = USO_INVALID_VAR;
|
token[0] = USO_INVALID_VAR;
|
||||||
|
|
|
@ -331,11 +331,11 @@ body[data-match-highlight="selection"] .CodeMirror-selection-highlight-scrollbar
|
||||||
min-height: 1.4rem;
|
min-height: 1.4rem;
|
||||||
margin-left: 0.35rem;
|
margin-left: 0.35rem;
|
||||||
}
|
}
|
||||||
.applies-to li .add-applies-to {
|
html:not(.usercss) .applies-to li .add-applies-to {
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
.applies-to li:last-child .add-applies-to {
|
html:not(.usercss) .applies-to li:last-child .add-applies-to {
|
||||||
visibility: visible
|
visibility: visible
|
||||||
}
|
}
|
||||||
.applies-to li .add-applies-to:first-child {
|
.applies-to li .add-applies-to:first-child {
|
||||||
|
@ -404,6 +404,12 @@ body[data-match-highlight="selection"] .CodeMirror-selection-highlight-scrollbar
|
||||||
margin-left: -20px;
|
margin-left: -20px;
|
||||||
margin-top: -1px;
|
margin-top: -1px;
|
||||||
}
|
}
|
||||||
|
.regexp-report-note {
|
||||||
|
color: #999;
|
||||||
|
position: absolute;
|
||||||
|
margin: 0 0.5rem 0 0;
|
||||||
|
hyphens: auto;
|
||||||
|
}
|
||||||
/************ help popup ************/
|
/************ help popup ************/
|
||||||
#help-popup {
|
#help-popup {
|
||||||
top: 3rem;
|
top: 3rem;
|
||||||
|
@ -646,8 +652,8 @@ html:not(.usercss) .usercss-only,
|
||||||
margin-top: 0.35rem;
|
margin-top: 0.35rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.CodeMirror-linewidget .applies-to li:not([data-type="regexp"]) .applies-to-regexp-test {
|
.CodeMirror-linewidget .applies-to li[data-type="regexp"] .test-regexp {
|
||||||
display: none;
|
display: inline;
|
||||||
}
|
}
|
||||||
|
|
||||||
.CodeMirror-linewidget li.applies-to-everything {
|
.CodeMirror-linewidget li.applies-to-everything {
|
||||||
|
|
|
@ -160,12 +160,14 @@ var regExpTester = (() => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
report.appendChild(
|
showHelp(t('styleRegexpTestTitle'), report);
|
||||||
$create('p.regexp-report-note',
|
|
||||||
|
const note = $create('p.regexp-report-note',
|
||||||
t('styleRegexpTestNote')
|
t('styleRegexpTestNote')
|
||||||
.split(/(\\+)/)
|
.split(/(\\+)/)
|
||||||
.map(s => (s.startsWith('\\') ? $create('code', s) : s))));
|
.map(s => (s.startsWith('\\') ? $create('code', s) : s)));
|
||||||
showHelp(t('styleRegexpTestTitle'), report);
|
report.appendChild(note);
|
||||||
|
report.style.paddingBottom = note.offsetHeight + 'px';
|
||||||
|
|
||||||
report.onclick = event => {
|
report.onclick = event => {
|
||||||
const target = event.target.closest('a, .regexp-report div');
|
const target = event.target.closest('a, .regexp-report div');
|
||||||
|
|
24
global.css
24
global.css
|
@ -42,6 +42,19 @@ input[type="checkbox"]:not(.slider):checked + .svg-icon.checked {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input[type="checkbox"]:not(.slider):disabled {
|
||||||
|
background-color: transparent;
|
||||||
|
border-color: hsl(0, 0%, 50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="checkbox"]:not(.slider):disabled + .svg-icon.checked {
|
||||||
|
fill: hsl(0, 0%, 50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="checkbox"]:not(.slider):disabled + .svg-icon.checked + span {
|
||||||
|
color: hsl(0, 0%, 50%);
|
||||||
|
}
|
||||||
|
|
||||||
label {
|
label {
|
||||||
transition: color .1s;
|
transition: color .1s;
|
||||||
}
|
}
|
||||||
|
@ -50,6 +63,7 @@ select {
|
||||||
-moz-appearance: none;
|
-moz-appearance: none;
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
height: 22px;
|
height: 22px;
|
||||||
|
color: currentColor;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
border: 1px solid hsl(0, 0%, 66%);
|
border: 1px solid hsl(0, 0%, 66%);
|
||||||
padding: 0 20px 0 6px;
|
padding: 0 20px 0 6px;
|
||||||
|
@ -72,7 +86,7 @@ select {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
height: 14px;
|
height: 14px;
|
||||||
width: 14px;
|
width: 14px;
|
||||||
fill: #000;
|
fill: currentColor;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 4px;
|
top: 4px;
|
||||||
right: 4px;
|
right: 4px;
|
||||||
|
@ -92,4 +106,12 @@ select {
|
||||||
padding-left: .75ex;
|
padding-left: .75ex;
|
||||||
padding-right: .75ex;
|
padding-right: .75ex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
::-moz-focus-inner {
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg {
|
||||||
|
transform: scale(1); /* de-blur */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -276,7 +276,7 @@
|
||||||
data.version,
|
data.version,
|
||||||
]))
|
]))
|
||||||
).then(ok => ok &&
|
).then(ok => ok &&
|
||||||
BG.usercssHelper.save(BG.deepCopy(Object.assign(style, {reason: 'update'})))
|
BG.usercssHelper.save(BG.deepCopy(Object.assign(style, dup && {reason: 'update'})))
|
||||||
.then(r => install(deepCopy(r)))
|
.then(r => install(deepCopy(r)))
|
||||||
.catch(err => messageBox.alert(t('styleInstallFailed', err)))
|
.catch(err => messageBox.alert(t('styleInstallFailed', err)))
|
||||||
);
|
);
|
||||||
|
|
|
@ -286,9 +286,9 @@ function tryCatch(func, ...args) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function tryRegExp(regexp) {
|
function tryRegExp(regexp, flags) {
|
||||||
try {
|
try {
|
||||||
return new RegExp(regexp);
|
return new RegExp(regexp, flags);
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,8 @@ var prefs = new function Prefs() {
|
||||||
'manage.onlyLocal.invert': false, // display only externally installed styles
|
'manage.onlyLocal.invert': false, // display only externally installed styles
|
||||||
'manage.onlyUsercss.invert': false, // display only non-usercss (standard) styles
|
'manage.onlyUsercss.invert': false, // display only non-usercss (standard) styles
|
||||||
// UI element state: expanded/collapsed
|
// UI element state: expanded/collapsed
|
||||||
|
'manage.backup.expanded': true,
|
||||||
|
'manage.filters.expanded': true,
|
||||||
'manage.options.expanded': true,
|
'manage.options.expanded': true,
|
||||||
// the new compact layout doesn't look good on Android yet
|
// the new compact layout doesn't look good on Android yet
|
||||||
'manage.newUI': !navigator.appVersion.includes('Android'),
|
'manage.newUI': !navigator.appVersion.includes('Android'),
|
||||||
|
|
|
@ -393,6 +393,7 @@ var usercss = (() => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const style = {
|
const style = {
|
||||||
|
reason: 'install',
|
||||||
enabled: true,
|
enabled: true,
|
||||||
sourceCode,
|
sourceCode,
|
||||||
sections: [],
|
sections: [],
|
||||||
|
|
43
manage.html
43
manage.html
|
@ -6,6 +6,7 @@
|
||||||
<title i18n-text="manageTitle"></title>
|
<title i18n-text="manageTitle"></title>
|
||||||
<link rel="stylesheet" href="global.css">
|
<link rel="stylesheet" href="global.css">
|
||||||
<link rel="stylesheet" href="manage/manage.css">
|
<link rel="stylesheet" href="manage/manage.css">
|
||||||
|
<link rel="stylesheet" href="manage/config-dialog.css">
|
||||||
<link rel="stylesheet" href="msgbox/msgbox.css">
|
<link rel="stylesheet" href="msgbox/msgbox.css">
|
||||||
<link rel="stylesheet" href="options/onoffswitch.css">
|
<link rel="stylesheet" href="options/onoffswitch.css">
|
||||||
<link rel="stylesheet" href="vendor-overwrites/colorpicker/colorpicker.css">
|
<link rel="stylesheet" href="vendor-overwrites/colorpicker/colorpicker.css">
|
||||||
|
@ -164,11 +165,15 @@
|
||||||
<div id="header">
|
<div id="header">
|
||||||
<h1 id="manage-heading" i18n-text="manageHeading"></h1>
|
<h1 id="manage-heading" i18n-text="manageHeading"></h1>
|
||||||
|
|
||||||
<fieldset>
|
<details id="filters" data-pref="manage.filters.expanded">
|
||||||
|
<summary>
|
||||||
<legend id="filters">
|
<h2 i18n-text="manageFilters">: <span id="filters-stats"></span></h2>
|
||||||
<span i18n-text="manageFilters"></span><span id="filters-stats"></span>
|
<svg id="reset-filters" class="svg-icon" viewBox="0 0 20 20">
|
||||||
</legend>
|
<title i18n-text="genericResetLabel"></title>
|
||||||
|
<polygon points="16.2,5.5 14.5,3.8 10,8.3 5.5,3.8 3.8,5.5 8.3,10 3.8,14.5
|
||||||
|
5.5,16.2 10,11.7 14.5,16.2 16.2,14.5 11.7,10 "/>
|
||||||
|
</svg>
|
||||||
|
</summary>
|
||||||
|
|
||||||
<div class="filter-selection">
|
<div class="filter-selection">
|
||||||
<label>
|
<label>
|
||||||
|
@ -232,12 +237,14 @@
|
||||||
<span i18n-text="manageOnlyUpdates"></span>
|
<span i18n-text="manageOnlyUpdates"></span>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
|
<div id="search-wrapper">
|
||||||
<input id="search" type="search" i18n-placeholder="searchStyles" spellcheck="false"
|
<input id="search" type="search" i18n-placeholder="searchStyles" spellcheck="false"
|
||||||
i18n-title="searchStylesTooltip"
|
|
||||||
data-filter=":not(.not-matching)"
|
data-filter=":not(.not-matching)"
|
||||||
data-filter-hide=".not-matching">
|
data-filter-hide=".not-matching">
|
||||||
|
<svg id="search-help" class="svg-icon info"><use xlink:href="#svg-icon-help"/></svg>
|
||||||
|
</div>
|
||||||
|
|
||||||
</fieldset>
|
</details>
|
||||||
|
|
||||||
<p class="nowrap">
|
<p class="nowrap">
|
||||||
<button id="check-all-updates" i18n-text="checkAllUpdates"><span id="update-progress"></span></button>
|
<button id="check-all-updates" i18n-text="checkAllUpdates"><span id="update-progress"></span></button>
|
||||||
|
@ -254,11 +261,11 @@
|
||||||
<button id="check-all-updates-force" class="hidden" i18n-text="checkAllUpdatesForce"></button>
|
<button id="check-all-updates-force" class="hidden" i18n-text="checkAllUpdatesForce"></button>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p id="add-style-wrapper">
|
||||||
<a href="edit.html">
|
<a href="edit.html">
|
||||||
<button id="add-style-label" i18n-text="addStyleLabel"></button>
|
<button id="add-style-label" i18n-text="addStyleLabel"></button>
|
||||||
</a>
|
</a>
|
||||||
<label id="newStyleAsUsercss-wrapper" class="nobreak">
|
<label id="add-style-as-usercss-wrapper">
|
||||||
<input type="checkbox" id="newStyleAsUsercss">
|
<input type="checkbox" id="newStyleAsUsercss">
|
||||||
<svg class="svg-icon checked"><use xlink:href="#svg-icon-checked"/></svg>
|
<svg class="svg-icon checked"><use xlink:href="#svg-icon-checked"/></svg>
|
||||||
<span i18n-text="manageNewStyleAsUsercss" i18n-title="optionsAdvancedNewStyleAsUsercss"></span>
|
<span i18n-text="manageNewStyleAsUsercss" i18n-title="optionsAdvancedNewStyleAsUsercss"></span>
|
||||||
|
@ -287,10 +294,11 @@
|
||||||
<label for="manage.newUI.favicons" i18n-text="manageFavicons">
|
<label for="manage.newUI.favicons" i18n-text="manageFavicons">
|
||||||
<input id="manage.newUI.favicons" type="checkbox">
|
<input id="manage.newUI.favicons" type="checkbox">
|
||||||
<svg class="svg-icon checked"><use xlink:href="#svg-icon-checked"/></svg>
|
<svg class="svg-icon checked"><use xlink:href="#svg-icon-checked"/></svg>
|
||||||
</label>
|
<svg class="svg-icon select-arrow" data-toggle-on-click="#faviconsHelp">
|
||||||
<svg class="svg-icon info" viewBox="0 0 14 16" i18n-alt="helpAlt" data-toggle-on-click="#faviconsHelp">
|
<title i18n-text="optionsSubheading"></title>
|
||||||
<path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path>
|
<use xlink:href="#svg-icon-select-arrow"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
</label>
|
||||||
<div id="faviconsHelp" class="hidden" i18n-text="manageFaviconsHelp">
|
<div id="faviconsHelp" class="hidden" i18n-text="manageFaviconsHelp">
|
||||||
<div>
|
<div>
|
||||||
<label for="manage.newUI.faviconsGray" i18n-text="manageFaviconsGray">
|
<label for="manage.newUI.faviconsGray" i18n-text="manageFaviconsGray">
|
||||||
|
@ -316,14 +324,14 @@
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
<div id="backup">
|
<details id="backup" data-pref="manage.backup.expanded">
|
||||||
<h2 id="backup-title" i18n-text="backupButtons"></h2>
|
<summary><h2 id="backup-title" i18n-text="backupButtons"></h2></summary>
|
||||||
<span id="backup-message" i18n-text="backupMessage"></span>
|
<span id="backup-message" i18n-text="backupMessage"></span>
|
||||||
<p>
|
<p>
|
||||||
<button id="file-all-styles" i18n-text="bckpInstStyles"></button>
|
<button id="file-all-styles" i18n-text="bckpInstStyles"></button>
|
||||||
<button id="unfile-all-styles" i18n-text="retrieveBckp"></button>
|
<button id="unfile-all-styles" i18n-text="retrieveBckp"></button>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</details>
|
||||||
|
|
||||||
<p id="manage-text" i18n-html="manageText"></p>
|
<p id="manage-text" i18n-html="manageText"></p>
|
||||||
|
|
||||||
|
@ -343,6 +351,11 @@
|
||||||
<symbol id="svg-icon-select-arrow" viewBox="0 0 1792 1792">
|
<symbol id="svg-icon-select-arrow" viewBox="0 0 1792 1792">
|
||||||
<path fill-rule="evenodd" d="M1408 704q0 26-19 45l-448 448q-19 19-45 19t-45-19l-448-448q-19-19-19-45t19-45 45-19h896q26 0 45 19t19 45z"/>
|
<path fill-rule="evenodd" d="M1408 704q0 26-19 45l-448 448q-19 19-45 19t-45-19l-448-448q-19-19-19-45t19-45 45-19h896q26 0 45 19t19 45z"/>
|
||||||
</symbol>
|
</symbol>
|
||||||
|
|
||||||
|
<symbol id="svg-icon-help" viewBox="0 0 14 16">
|
||||||
|
<title i18n-text="helpAlt"></title>
|
||||||
|
<path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path>
|
||||||
|
</symbol>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
112
manage/config-dialog.css
Normal file
112
manage/config-dialog.css
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
/* config dialog */
|
||||||
|
.config-dialog .config-heading {
|
||||||
|
float: right;
|
||||||
|
margin: -1.25rem 0 0 0;
|
||||||
|
font-size: 0.9em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-dialog label {
|
||||||
|
display: flex;
|
||||||
|
padding: .75em 0;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-dialog .select-resizer {
|
||||||
|
position: static;
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-dialog label:first-child {
|
||||||
|
padding-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-dialog label:last-child {
|
||||||
|
padding-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-dialog label:not(:first-child) {
|
||||||
|
border-top: 1px dotted #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-dialog label > :first-child {
|
||||||
|
margin-right: 8px;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-dialog label:not([disabled]) > :first-child {
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-dialog label:not([disabled]):hover > :first-child {
|
||||||
|
text-shadow: 0 0 0.01px rgba(0, 0, 0, .25);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-dialog .dirty:after {
|
||||||
|
content: "*";
|
||||||
|
position: absolute;
|
||||||
|
left: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-dialog .dirty {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-dialog input,
|
||||||
|
.config-dialog select,
|
||||||
|
.config-dialog .onoffswitch {
|
||||||
|
width: var(--onoffswitch-width);
|
||||||
|
margin: 0;
|
||||||
|
height: 2em;
|
||||||
|
box-sizing: border-box;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-dialog .select-resizer,
|
||||||
|
.config-dialog select {
|
||||||
|
width: auto;
|
||||||
|
min-width: var(--onoffswitch-width);
|
||||||
|
max-width: 124px;
|
||||||
|
left: auto;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-dialog .onoffswitch {
|
||||||
|
height: auto;
|
||||||
|
margin: calc((2em - 12px) / 2) 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-dialog input[type="text"] {
|
||||||
|
padding-left: 0.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-dialog label > :last-child {
|
||||||
|
box-sizing: border-box;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-dialog label > :last-child:not(.onoffswitch):not(.select-resizer) > :not(:last-child) {
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-colorview::before,
|
||||||
|
.color-swatch {
|
||||||
|
width: var(--onoffswitch-width) !important;
|
||||||
|
height: 20px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-colorview::before {
|
||||||
|
margin: 1px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-swatch {
|
||||||
|
position: absolute;
|
||||||
|
border: 1px solid gray;
|
||||||
|
margin-top: -22px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.colorpicker-popup {
|
||||||
|
z-index: 2147483647 !important;
|
||||||
|
border: none !important;
|
||||||
|
box-shadow: 3px 3px 50px rgba(0,0,0,.5) !important;
|
||||||
|
}
|
|
@ -6,35 +6,79 @@ function configDialog(style) {
|
||||||
const varsHash = deepCopy(data.vars) || {};
|
const varsHash = deepCopy(data.vars) || {};
|
||||||
const varNames = Object.keys(varsHash);
|
const varNames = Object.keys(varsHash);
|
||||||
const vars = varNames.map(name => varsHash[name]);
|
const vars = varNames.map(name => varsHash[name]);
|
||||||
|
let varsInitial = getInitialValues(varsHash);
|
||||||
|
|
||||||
const elements = [];
|
const elements = [];
|
||||||
const colorpicker = window.colorpicker();
|
const colorpicker = window.colorpicker();
|
||||||
|
const isPopup = location.href.includes('popup.html');
|
||||||
|
const buttons = {};
|
||||||
|
|
||||||
buildConfigForm();
|
buildConfigForm();
|
||||||
renderValues();
|
renderValues();
|
||||||
|
|
||||||
return messageBox({
|
return messageBox({
|
||||||
title: `${style.name} v${data.version}`,
|
title: `${style.name} v${data.version}`,
|
||||||
className: 'config-dialog',
|
className: 'config-dialog' + (isPopup ? ' stylus-popup' : ''),
|
||||||
contents: [
|
contents: [
|
||||||
$create('.config-heading', data.supportURL &&
|
$create('.config-heading', data.supportURL &&
|
||||||
$createLink({className: '.external-support', href: data.supportURL}, t('externalFeedback'))),
|
$createLink({className: '.external-support', href: data.supportURL}, t('externalFeedback'))),
|
||||||
$create('.config-body', elements)
|
$create('.config-body', elements)
|
||||||
],
|
],
|
||||||
buttons: [
|
buttons: [
|
||||||
t('confirmSave'),
|
{textContent: t('confirmSave'), dataset: {cmd: 'save'}, disabled: true, onclick: save},
|
||||||
{
|
{textContent: t('confirmDefault'), dataset: {cmd: 'default'}, onclick: useDefault},
|
||||||
textContent: t('confirmDefault'),
|
{textContent: t('confirmClose'), dataset: {cmd: 'close'}},
|
||||||
onclick: useDefault
|
],
|
||||||
},
|
onshow,
|
||||||
t('confirmCancel')
|
}).then(() => {
|
||||||
]
|
document.body.style.minWidth = '';
|
||||||
}).then(({button, esc}) => {
|
document.body.style.minHeight = '';
|
||||||
if (button !== 1) {
|
|
||||||
colorpicker.hide();
|
colorpicker.hide();
|
||||||
|
});
|
||||||
|
|
||||||
|
function getInitialValues(source) {
|
||||||
|
const data = {};
|
||||||
|
for (const name of varNames) {
|
||||||
|
const va = source[name];
|
||||||
|
data[name] = isDefault(va) ? va.default : va.value;
|
||||||
}
|
}
|
||||||
if (button > 0 || esc || !vars.length || !vars.some(va => va.dirty)) {
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
function onshow(box) {
|
||||||
|
if (isPopup) {
|
||||||
|
adjustSizeForPopup(box);
|
||||||
|
box.style.animationDuration = '0s';
|
||||||
|
}
|
||||||
|
box.addEventListener('change', onchange);
|
||||||
|
buttons.save = $('[data-cmd="save"]', box);
|
||||||
|
buttons.default = $('[data-cmd="default"]', box);
|
||||||
|
buttons.close = $('[data-cmd="close"]', box);
|
||||||
|
updateButtons();
|
||||||
|
}
|
||||||
|
|
||||||
|
function onchange({target}) {
|
||||||
|
// invoked after element's own onchange so 'va' contains the updated value
|
||||||
|
const va = target.va;
|
||||||
|
if (va) {
|
||||||
|
va.dirty = varsInitial[va.name] !== (isDefault(va) ? va.default : va.value);
|
||||||
|
target.closest('label').classList.toggle('dirty', va.dirty);
|
||||||
|
updateButtons();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateButtons() {
|
||||||
|
const someDirty = vars.some(va => va.dirty);
|
||||||
|
buttons.save.disabled = !someDirty;
|
||||||
|
buttons.default.disabled = vars.every(isDefault);
|
||||||
|
buttons.close.textContent = t(someDirty ? 'confirmCancel' : 'confirmClose');
|
||||||
|
}
|
||||||
|
|
||||||
|
function save() {
|
||||||
|
if (!vars.length || !vars.some(va => va.dirty)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
style.enabled = true;
|
||||||
style.reason = 'config';
|
style.reason = 'config';
|
||||||
const styleVars = style.usercssData.vars;
|
const styleVars = style.usercssData.vars;
|
||||||
const bgStyle = BG.cachedStyles.byId.get(style.id);
|
const bgStyle = BG.cachedStyles.byId.get(style.id);
|
||||||
|
@ -52,7 +96,7 @@ function configDialog(style) {
|
||||||
error = ['type ', '*' + va.type, ' != ', '*' + bgva.type];
|
error = ['type ', '*' + va.type, ' != ', '*' + bgva.type];
|
||||||
} else
|
} else
|
||||||
if ((va.type === 'select' || va.type === 'dropdown') &&
|
if ((va.type === 'select' || va.type === 'dropdown') &&
|
||||||
va.value !== null && va.value !== undefined &&
|
!isDefault(va) &&
|
||||||
bgva.options.every(o => o.name !== va.value)) {
|
bgva.options.every(o => o.name !== va.value)) {
|
||||||
error = `'${va.value}' not in the updated '${va.type}' list`;
|
error = `'${va.value}' not in the updated '${va.type}' list`;
|
||||||
} else if (!va.dirty) {
|
} else if (!va.dirty) {
|
||||||
|
@ -76,33 +120,52 @@ function configDialog(style) {
|
||||||
$create({tag: 'li', appendChild: msg}))),
|
$create({tag: 'li', appendChild: msg}))),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
return numValid && BG.usercssHelper.save(style);
|
return numValid && BG.usercssHelper.save(style).then(saved => {
|
||||||
|
varsInitial = getInitialValues(deepCopy(saved.usercssData.vars));
|
||||||
|
vars.forEach(va => onchange({target: va.input}));
|
||||||
|
updateButtons();
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function useDefault() {
|
||||||
|
for (const va of vars) {
|
||||||
|
va.value = null;
|
||||||
|
onchange({target: va.input});
|
||||||
|
}
|
||||||
|
renderValues();
|
||||||
|
}
|
||||||
|
|
||||||
|
function isDefault(va) {
|
||||||
|
return va.value === null || va.value === undefined || va.value === va.default;
|
||||||
|
}
|
||||||
|
|
||||||
function buildConfigForm() {
|
function buildConfigForm() {
|
||||||
for (const va of vars) {
|
for (const va of vars) {
|
||||||
let children;
|
let children;
|
||||||
switch (va.type) {
|
switch (va.type) {
|
||||||
case 'color':
|
case 'color':
|
||||||
va.inputColor = $create('.color-swatch', {va, onclick: showColorpicker});
|
|
||||||
children = [
|
children = [
|
||||||
$create('.cm-colorview', [
|
$create('.cm-colorview', [
|
||||||
va.inputColor,
|
va.input = $create('.color-swatch', {
|
||||||
|
va,
|
||||||
|
onclick: showColorpicker
|
||||||
|
}),
|
||||||
]),
|
]),
|
||||||
];
|
];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'checkbox':
|
case 'checkbox':
|
||||||
va.input = $create('input.slider', {type: 'checkbox'});
|
|
||||||
va.input.onchange = () => {
|
|
||||||
va.dirty = true;
|
|
||||||
va.value = String(Number(va.input.checked));
|
|
||||||
};
|
|
||||||
children = [
|
children = [
|
||||||
$create('span.onoffswitch', [
|
$create('span.onoffswitch', [
|
||||||
va.input,
|
va.input = $create('input.slider', {
|
||||||
|
va,
|
||||||
|
type: 'checkbox',
|
||||||
|
onchange() {
|
||||||
|
va.value = va.input.checked ? '1' : '0';
|
||||||
|
},
|
||||||
|
}),
|
||||||
$create('span'),
|
$create('span'),
|
||||||
])
|
]),
|
||||||
];
|
];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -110,26 +173,33 @@ function configDialog(style) {
|
||||||
case 'dropdown':
|
case 'dropdown':
|
||||||
case 'image':
|
case 'image':
|
||||||
// TODO: a image picker input?
|
// TODO: a image picker input?
|
||||||
va.input = $create('.select-resizer', [
|
children = [
|
||||||
$create('select', va.options.map(o =>
|
$create('.select-resizer', [
|
||||||
|
va.input = $create('select', {
|
||||||
|
va,
|
||||||
|
onchange() {
|
||||||
|
va.value = this.value;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
va.options.map(o =>
|
||||||
$create('option', {value: o.name}, o.label))),
|
$create('option', {value: o.name}, o.label))),
|
||||||
$create('SVG:svg.svg-icon.select-arrow',
|
$create('SVG:svg.svg-icon.select-arrow',
|
||||||
$create('SVG:use', {'xlink:href': '#svg-icon-select-arrow'})),
|
$create('SVG:use', {'xlink:href': '#svg-icon-select-arrow'})),
|
||||||
]);
|
]),
|
||||||
va.input.onchange = () => {
|
];
|
||||||
va.dirty = true;
|
|
||||||
va.value = va.input.value;
|
|
||||||
};
|
|
||||||
children = [va.input];
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
va.input = $create('input', {type: 'text'});
|
children = [
|
||||||
va.input.oninput = () => {
|
va.input = $create('input', {
|
||||||
va.dirty = true;
|
va,
|
||||||
va.value = va.input.value;
|
type: 'text',
|
||||||
};
|
oninput() {
|
||||||
children = [va.input];
|
va.value = this.value;
|
||||||
|
this.dispatchEvent(new Event('change', {bubbles: true}));
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
elements.push(
|
elements.push(
|
||||||
|
@ -142,10 +212,9 @@ function configDialog(style) {
|
||||||
|
|
||||||
function renderValues() {
|
function renderValues() {
|
||||||
for (const va of vars) {
|
for (const va of vars) {
|
||||||
const useDefault = va.value === null || va.value === undefined;
|
const value = isDefault(va) ? va.default : va.value;
|
||||||
const value = useDefault ? va.default : va.value;
|
|
||||||
if (va.type === 'color') {
|
if (va.type === 'color') {
|
||||||
va.inputColor.style.backgroundColor = value;
|
va.input.style.backgroundColor = value;
|
||||||
if (colorpicker.options.va === va) {
|
if (colorpicker.options.va === va) {
|
||||||
colorpicker.setColor(value);
|
colorpicker.setColor(value);
|
||||||
}
|
}
|
||||||
|
@ -157,15 +226,6 @@ function configDialog(style) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function useDefault() {
|
|
||||||
for (const va of vars) {
|
|
||||||
const hasValue = va.value !== null && va.value !== undefined;
|
|
||||||
va.dirty = hasValue && va.value !== va.default;
|
|
||||||
va.value = null;
|
|
||||||
}
|
|
||||||
renderValues();
|
|
||||||
}
|
|
||||||
|
|
||||||
function showColorpicker() {
|
function showColorpicker() {
|
||||||
window.removeEventListener('keydown', messageBox.listeners.key, true);
|
window.removeEventListener('keydown', messageBox.listeners.key, true);
|
||||||
const box = $('#message-box-contents');
|
const box = $('#message-box-contents');
|
||||||
|
@ -182,9 +242,9 @@ function configDialog(style) {
|
||||||
|
|
||||||
function onColorChanged(newColor) {
|
function onColorChanged(newColor) {
|
||||||
if (newColor) {
|
if (newColor) {
|
||||||
this.va.dirty = true;
|
|
||||||
this.va.value = newColor;
|
this.va.value = newColor;
|
||||||
this.va.inputColor.style.backgroundColor = newColor;
|
this.va.input.style.backgroundColor = newColor;
|
||||||
|
this.va.input.dispatchEvent(new Event('change', {bubbles: true}));
|
||||||
}
|
}
|
||||||
debounce(restoreEscInDialog);
|
debounce(restoreEscInDialog);
|
||||||
}
|
}
|
||||||
|
@ -194,4 +254,22 @@ function configDialog(style) {
|
||||||
window.addEventListener('keydown', messageBox.listeners.key, true);
|
window.addEventListener('keydown', messageBox.listeners.key, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function adjustSizeForPopup(box) {
|
||||||
|
box.style = 'white-space: nowrap !important';
|
||||||
|
box.firstElementChild.style = 'max-width: none; max-height: none;'.replace(/;/g, '!important;');
|
||||||
|
const {offsetWidth, offsetHeight} = box.firstElementChild;
|
||||||
|
box.style = box.firstElementChild.style = '';
|
||||||
|
|
||||||
|
const colorpicker = document.body.appendChild(
|
||||||
|
$create('.colorpicker-popup', {style: 'display: none!important'}));
|
||||||
|
const MIN_WIDTH = parseFloat(getComputedStyle(colorpicker).width) || 350;
|
||||||
|
const MIN_HEIGHT = 250;
|
||||||
|
colorpicker.remove();
|
||||||
|
|
||||||
|
const width = Math.max(Math.min(offsetWidth / 0.9 + 2, 800), MIN_WIDTH);
|
||||||
|
const height = Math.max(Math.min(offsetHeight / 0.9 + 2, 600), MIN_HEIGHT);
|
||||||
|
document.body.style.setProperty('min-width', width + 'px', 'important');
|
||||||
|
document.body.style.setProperty('min-height', height + 'px', 'important');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* global installed */
|
/* global installed messageBox */
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const filtersSelector = {
|
const filtersSelector = {
|
||||||
|
@ -31,6 +31,25 @@ onDOMready().then(onBackgroundReady).then(() => {
|
||||||
if (urlFilterParam) {
|
if (urlFilterParam) {
|
||||||
$('#search').value = 'url:' + urlFilterParam;
|
$('#search').value = 'url:' + urlFilterParam;
|
||||||
}
|
}
|
||||||
|
$('#search-help').onclick = () => {
|
||||||
|
messageBox({
|
||||||
|
className: 'help-text',
|
||||||
|
title: t('searchStyles'),
|
||||||
|
contents:
|
||||||
|
$create('ul',
|
||||||
|
t('searchStylesHelp').split('\n').map(line =>
|
||||||
|
$create('li', line.split(/(<.*?>)/).map((s, i, words) => {
|
||||||
|
if (s.startsWith('<')) {
|
||||||
|
const num = words.length;
|
||||||
|
const className = i === num - 2 && !words[num - 1] ? '.last' : '';
|
||||||
|
return $create('mark' + className, s.slice(1, -1));
|
||||||
|
} else {
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
})))),
|
||||||
|
buttons: [t('confirmOK')],
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
$$('select[id$=".invert"]').forEach(el => {
|
$$('select[id$=".invert"]').forEach(el => {
|
||||||
const slave = $('#' + el.id.replace('.invert', ''));
|
const slave = $('#' + el.id.replace('.invert', ''));
|
||||||
|
@ -76,6 +95,36 @@ onDOMready().then(onBackgroundReady).then(() => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$('#reset-filters').onclick = event => {
|
||||||
|
event.preventDefault();
|
||||||
|
if (!filtersSelector.hide) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (const el of $$('#filters [data-filter]')) {
|
||||||
|
let value;
|
||||||
|
if (el.type === 'checkbox' && el.checked) {
|
||||||
|
value = el.checked = false;
|
||||||
|
} else if (el.value) {
|
||||||
|
value = el.value = '';
|
||||||
|
}
|
||||||
|
if (value !== undefined) {
|
||||||
|
el.lastValue = value;
|
||||||
|
if (el.id in prefs.readOnlyValues) {
|
||||||
|
prefs.set(el.id, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
filterOnChange({forceRefilter: true});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Adjust width after selects are visible
|
||||||
|
prefs.subscribe(['manage.filters.expanded'], () => {
|
||||||
|
const el = $('#filters');
|
||||||
|
if (el.open) {
|
||||||
|
$$('select', el).forEach(select => select.adjustWidth());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
filterOnChange({forceRefilter: true});
|
filterOnChange({forceRefilter: true});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -303,7 +352,7 @@ function showFiltersStats() {
|
||||||
debounce(showFiltersStats, 100);
|
debounce(showFiltersStats, 100);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$('#filters').classList.toggle('active', filtersSelector.hide !== '');
|
$('#filters summary').classList.toggle('active', filtersSelector.hide !== '');
|
||||||
const numTotal = BG.cachedStyles.list.length;
|
const numTotal = BG.cachedStyles.list.length;
|
||||||
const numHidden = installed.getElementsByClassName('entry hidden').length;
|
const numHidden = installed.getElementsByClassName('entry hidden').length;
|
||||||
const numShown = Math.min(numTotal - numHidden, installed.children.length);
|
const numShown = Math.min(numTotal - numHidden, installed.children.length);
|
||||||
|
@ -320,10 +369,11 @@ function showFiltersStats() {
|
||||||
|
|
||||||
function searchStyles({immediately, container}) {
|
function searchStyles({immediately, container}) {
|
||||||
const searchElement = $('#search');
|
const searchElement = $('#search');
|
||||||
const urlMode = /^\s*url:/i.test(searchElement.value);
|
const value = searchElement.value;
|
||||||
|
const urlMode = /^\s*url:/i.test(value);
|
||||||
const query = urlMode
|
const query = urlMode
|
||||||
? searchElement.value.replace(/^\s*url:/i, '').trim()
|
? value.replace(/^\s*url:/i, '').trim()
|
||||||
: searchElement.value.toLocaleLowerCase();
|
: value.toLocaleLowerCase();
|
||||||
const queryPrev = searchElement.lastValue || '';
|
const queryPrev = searchElement.lastValue || '';
|
||||||
if (query === queryPrev && !immediately && !container) {
|
if (query === queryPrev && !immediately && !container) {
|
||||||
return;
|
return;
|
||||||
|
@ -334,6 +384,12 @@ function searchStyles({immediately, container}) {
|
||||||
}
|
}
|
||||||
searchElement.lastValue = query;
|
searchElement.lastValue = query;
|
||||||
|
|
||||||
|
const trimmed = query.trim();
|
||||||
|
const rx = trimmed.startsWith('/') && trimmed.indexOf('/', 1) > 0 &&
|
||||||
|
tryRegExp(...(value.match(/^\s*\/(.*?)\/([gimsuy]*)\s*$/) || []).slice(1));
|
||||||
|
const words = rx ? null :
|
||||||
|
trimmed.startsWith('"') && trimmed.endsWith('"') ? [value.trim().slice(1, -1)] :
|
||||||
|
query.split(/\s+/).filter(s => s.length > 2);
|
||||||
const searchInVisible = !urlMode && queryPrev && query.includes(queryPrev);
|
const searchInVisible = !urlMode && queryPrev && query.includes(queryPrev);
|
||||||
const entries = container && container.children || container ||
|
const entries = container && container.children || container ||
|
||||||
(searchInVisible ? $$('.entry:not(.hidden)') : installed.children);
|
(searchInVisible ? $$('.entry:not(.hidden)') : installed.children);
|
||||||
|
@ -349,6 +405,7 @@ function searchStyles({immediately, container}) {
|
||||||
urlMode ||
|
urlMode ||
|
||||||
isMatchingText(style.name) ||
|
isMatchingText(style.name) ||
|
||||||
style.url && isMatchingText(style.url) ||
|
style.url && isMatchingText(style.url) ||
|
||||||
|
style.sourceCode && isMatchingText(style.sourceCode) ||
|
||||||
isMatchingStyle(style)));
|
isMatchingStyle(style)));
|
||||||
}
|
}
|
||||||
if (entry.classList.contains('not-matching') !== !isMatching) {
|
if (entry.classList.contains('not-matching') !== !isMatching) {
|
||||||
|
@ -384,6 +441,17 @@ function searchStyles({immediately, container}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function isMatchingText(text) {
|
function isMatchingText(text) {
|
||||||
return text.toLocaleLowerCase().indexOf(query) >= 0;
|
if (rx) {
|
||||||
|
return rx.test(text);
|
||||||
|
}
|
||||||
|
for (let pass = 1; pass <= 2; pass++) {
|
||||||
|
for (const word of words) {
|
||||||
|
if (text.includes(word)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
text = text.toLocaleLowerCase();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,17 @@ function importFromFile({fileTypeFilter, file} = {}) {
|
||||||
const fReader = new FileReader();
|
const fReader = new FileReader();
|
||||||
fReader.onloadend = event => {
|
fReader.onloadend = event => {
|
||||||
fileInput.remove();
|
fileInput.remove();
|
||||||
importFromString(event.target.result).then(numStyles => {
|
const text = event.target.result;
|
||||||
|
const maybeUsercss = !/^[\s\r\n]*\[/.test(text) &&
|
||||||
|
(text.includes('==UserStyle==') || /==UserStyle==/i.test(text));
|
||||||
|
(!maybeUsercss ?
|
||||||
|
importFromString(text) :
|
||||||
|
getOwnTab().then(tab => {
|
||||||
|
tab.url = URL.createObjectURL(new Blob([text], {type: 'text/css'}));
|
||||||
|
return BG.usercssHelper.openInstallPage(tab, {direct: true})
|
||||||
|
.then(() => URL.revokeObjectURL(tab.url));
|
||||||
|
})
|
||||||
|
).then(numStyles => {
|
||||||
document.body.style.cursor = '';
|
document.body.style.cursor = '';
|
||||||
resolve(numStyles);
|
resolve(numStyles);
|
||||||
});
|
});
|
||||||
|
|
|
@ -79,6 +79,7 @@ select {
|
||||||
|
|
||||||
#header h1 {
|
#header h1 {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
|
margin-bottom: .3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
#header a[href^="edit"] {
|
#header a[href^="edit"] {
|
||||||
|
@ -90,25 +91,16 @@ select {
|
||||||
margin-bottom: .25em;
|
margin-bottom: .25em;
|
||||||
}
|
}
|
||||||
|
|
||||||
#newStyleAsUsercss-wrapper:not(:hover) input:not(:checked) ~ a svg {
|
#add-style-as-usercss-wrapper {
|
||||||
|
display: inline-flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
#add-style-as-usercss-wrapper:not(:hover) input:not(:checked) ~ a svg {
|
||||||
fill: #aaa;
|
fill: #aaa;
|
||||||
}
|
}
|
||||||
|
|
||||||
#usercss-wiki svg {
|
#usercss-wiki svg {
|
||||||
margin-top: -2px;
|
margin-top: -4px;
|
||||||
}
|
|
||||||
|
|
||||||
.nobreak {
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
label.nobreak input {
|
|
||||||
vertical-align: sub;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.firefox .chromium-only {
|
|
||||||
display: none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#installed {
|
#installed {
|
||||||
|
@ -264,9 +256,24 @@ label.nobreak input {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* collapsibles */
|
/* collapsibles */
|
||||||
|
#header details:not(#filters),
|
||||||
|
#add-style-wrapper {
|
||||||
|
padding-bottom: .7em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#add-style-wrapper,
|
||||||
|
#options :last-child,
|
||||||
|
#backup :last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#header details:not([open]),
|
||||||
#header details:not([open]) h2 {
|
#header details:not([open]) h2 {
|
||||||
margin-bottom: -.25em;
|
padding-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#header details[open] summary {
|
||||||
|
padding-bottom: .5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
#header summary {
|
#header summary {
|
||||||
|
@ -274,7 +281,6 @@ label.nobreak input {
|
||||||
margin-left: -13px;
|
margin-left: -13px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
outline: none;
|
outline: none;
|
||||||
margin-bottom: 8px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#header summary h2 {
|
#header summary h2 {
|
||||||
|
@ -326,6 +332,7 @@ label.nobreak input {
|
||||||
|
|
||||||
.filter-selection {
|
.filter-selection {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
left: -9px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#header label {
|
#header label {
|
||||||
|
@ -346,10 +353,6 @@ label.nobreak input {
|
||||||
margin-top: -2px;
|
margin-top: -2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.firefox #header .filter-selection label .checkmate {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.newUI #newUIoptions > label {
|
.newUI #newUIoptions > label {
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
}
|
}
|
||||||
|
@ -361,10 +364,7 @@ label.nobreak input {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
padding-left: 4px;
|
padding-left: 4px;
|
||||||
padding-right: 14px;
|
padding-right: 14px;
|
||||||
}
|
margin-left: 4px;
|
||||||
|
|
||||||
.firefox .filter-selection select {
|
|
||||||
padding-left: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.filter-selection .select-arrow {
|
.filter-selection .select-arrow {
|
||||||
|
@ -382,17 +382,13 @@ label.nobreak input {
|
||||||
left: 16px;
|
left: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.firefox .select-resizer {
|
#filters label,
|
||||||
left: 16px;
|
#filters .filter-selection {
|
||||||
}
|
|
||||||
|
|
||||||
fieldset > label,
|
|
||||||
fieldset > .filter-selection {
|
|
||||||
transition: background-color .25s;
|
transition: background-color .25s;
|
||||||
}
|
}
|
||||||
|
|
||||||
fieldset > label:hover,
|
#filters label:hover,
|
||||||
fieldset > .filter-selection:hover {
|
#filters .filter-selection:hover {
|
||||||
background-color: hsla(0, 0%, 50%, .2);
|
background-color: hsla(0, 0%, 50%, .2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -646,6 +642,7 @@ fieldset > .filter-selection:hover {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-bottom: auto;
|
margin-bottom: auto;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
#newUIoptions input[type="number"] {
|
#newUIoptions input[type="number"] {
|
||||||
|
@ -653,6 +650,18 @@ fieldset > .filter-selection:hover {
|
||||||
margin-right: .5em;
|
margin-right: .5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#newUIoptions [data-toggle-on-click] {
|
||||||
|
transform: rotate(-90deg);
|
||||||
|
cursor: pointer;
|
||||||
|
right: -16px;
|
||||||
|
top: 0;
|
||||||
|
pointer-events: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#newUIoptions [data-toggle-on-click][open] {
|
||||||
|
transform: none;
|
||||||
|
}
|
||||||
|
|
||||||
input[id^="manage.newUI"] {
|
input[id^="manage.newUI"] {
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
}
|
}
|
||||||
|
@ -751,26 +760,14 @@ input[id^="manage.newUI"] {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
fieldset {
|
#filters label {
|
||||||
border-width: 1px;
|
|
||||||
border-radius: 6px;
|
|
||||||
margin: 1em 0;
|
|
||||||
min-width: 0;
|
|
||||||
max-width: 250px;
|
|
||||||
}
|
|
||||||
|
|
||||||
fieldset > input,
|
|
||||||
fieldset > label {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
|
||||||
|
|
||||||
#header fieldset > label {
|
|
||||||
padding-left: 20px;
|
padding-left: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#header fieldset > label input[type="checkbox"]:not(.slider),
|
#filters label input[type="checkbox"]:not(.slider),
|
||||||
#header fieldset > label input[type="checkbox"]:not(.slider):checked + .svg-icon.checked{
|
#filters label input[type="checkbox"]:not(.slider):checked + .svg-icon.checked{
|
||||||
left: 4px;
|
left: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -778,28 +775,82 @@ fieldset > label {
|
||||||
border: 1px solid transparent;
|
border: 1px solid transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
#filters.active {
|
#filters summary h2 {
|
||||||
|
margin-left: -4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.active #filters-stats {
|
||||||
background-color: darkcyan;
|
background-color: darkcyan;
|
||||||
border-color: darkcyan;
|
border-color: darkcyan;
|
||||||
color: white;
|
color: white;
|
||||||
|
font-size: 0.7rem;
|
||||||
|
font-weight: normal;
|
||||||
|
padding: 2px 5px;
|
||||||
|
position: relative;
|
||||||
|
top: -2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#filters:not(.active) #filters-stats {
|
#reset-filters {
|
||||||
|
position: absolute;
|
||||||
|
margin-top: 2px;
|
||||||
|
fill: hsla(180, 50%, 27%, .5);
|
||||||
|
width: 24px; /* widen the click area a bit */
|
||||||
|
height: 20px;
|
||||||
|
padding: 2px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
#reset-filters:hover {
|
||||||
|
fill: hsla(180, 50%, 27%, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#filters summary:not(.active) #reset-filters,
|
||||||
|
#filters summary:not(.active) #filters-stats {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
#filters-stats::before {
|
#search-wrapper {
|
||||||
content: ": ";
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
#search {
|
#search {
|
||||||
width: calc(100% - 4px);
|
flex-grow: 1;
|
||||||
margin: 0.25rem 4px 0;
|
margin: 0.25rem 0 0;
|
||||||
border-radius: 0.25rem;
|
|
||||||
padding-left: 0.25rem;
|
padding-left: 0.25rem;
|
||||||
border-width: 1px;
|
border-width: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#search-wrapper .info {
|
||||||
|
margin: 4px -5px 0 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#message-box.help-text > div {
|
||||||
|
max-width: 26rem;
|
||||||
|
}
|
||||||
|
.help-text li:not(:last-child) {
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.help-text mark {
|
||||||
|
background-color: rgba(128, 128, 128, .15);
|
||||||
|
color: currentColor;
|
||||||
|
padding: 2px 6px;
|
||||||
|
font-weight: bold;
|
||||||
|
font-family: monospace;
|
||||||
|
border: 1px solid rgba(128, 128, 128, .25);
|
||||||
|
display: inline-block;
|
||||||
|
margin: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.help-text mark.last {
|
||||||
|
display: block;
|
||||||
|
width: -moz-min-content;
|
||||||
|
width: min-content;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
#import ul {
|
#import ul {
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
|
@ -860,109 +911,6 @@ fieldset > label {
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* config dialog */
|
|
||||||
.config-dialog .config-heading {
|
|
||||||
float: right;
|
|
||||||
margin: -1.25rem 0 0 0;
|
|
||||||
font-size: 0.9em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.config-dialog label {
|
|
||||||
display: flex;
|
|
||||||
padding: .75em 0;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.config-dialog .select-resizer {
|
|
||||||
position: static;
|
|
||||||
}
|
|
||||||
|
|
||||||
.config-dialog label:first-child {
|
|
||||||
padding-top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.config-dialog label:last-child {
|
|
||||||
padding-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.config-dialog label:not(:first-child) {
|
|
||||||
border-top: 1px dotted #ccc;
|
|
||||||
}
|
|
||||||
|
|
||||||
.config-dialog label > :first-child {
|
|
||||||
margin-right: 8px;
|
|
||||||
flex-grow: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.config-dialog label:not([disabled]) > :first-child {
|
|
||||||
cursor: default;
|
|
||||||
}
|
|
||||||
|
|
||||||
.config-dialog label:not([disabled]):hover > :first-child {
|
|
||||||
text-shadow: 0 0 0.01px rgba(0, 0, 0, .25);
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.config-dialog input,
|
|
||||||
.config-dialog select,
|
|
||||||
.config-dialog .onoffswitch {
|
|
||||||
width: var(--onoffswitch-width);
|
|
||||||
margin: 0;
|
|
||||||
height: 2em;
|
|
||||||
box-sizing: border-box;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
.config-dialog .select-resizer,
|
|
||||||
.config-dialog select {
|
|
||||||
width: auto;
|
|
||||||
min-width: var(--onoffswitch-width);
|
|
||||||
max-width: 124px;
|
|
||||||
left: auto;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.config-dialog .onoffswitch {
|
|
||||||
height: auto;
|
|
||||||
margin: calc((2em - 12px) / 2) 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.config-dialog input[type="text"] {
|
|
||||||
padding-left: 0.25em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.config-dialog label > :last-child {
|
|
||||||
box-sizing: border-box;
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.config-dialog label > :last-child:not(.onoffswitch):not(.select-resizer) > :not(:last-child) {
|
|
||||||
margin-right: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cm-colorview::before,
|
|
||||||
.color-swatch {
|
|
||||||
width: var(--onoffswitch-width) !important;
|
|
||||||
height: 20px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cm-colorview::before {
|
|
||||||
margin: 1px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.color-swatch {
|
|
||||||
position: absolute;
|
|
||||||
border: 1px solid gray;
|
|
||||||
margin-top: -22px;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.colorpicker-popup {
|
|
||||||
z-index: 2147483647 !important;
|
|
||||||
border: none !important;
|
|
||||||
box-shadow: 3px 3px 50px rgba(0,0,0,.5) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes fadein {
|
@keyframes fadein {
|
||||||
from {
|
from {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
|
@ -998,7 +946,6 @@ fieldset > label {
|
||||||
}
|
}
|
||||||
|
|
||||||
#header p,
|
#header p,
|
||||||
#header fieldset div,
|
|
||||||
#backup {
|
#backup {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
@ -1011,8 +958,7 @@ fieldset > label {
|
||||||
margin-right: 1em;
|
margin-right: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
#backup p,
|
#backup p {
|
||||||
#header fieldset {
|
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1053,12 +999,6 @@ fieldset > label {
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
fieldset {
|
|
||||||
max-width: none;
|
|
||||||
margin-top: 0;
|
|
||||||
margin-right: 2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
#header h1,
|
#header h1,
|
||||||
#header h2,
|
#header h2,
|
||||||
#header h3,
|
#header h3,
|
||||||
|
@ -1088,21 +1028,10 @@ fieldset > label {
|
||||||
|
|
||||||
.newUI #header > *:not(h1),
|
.newUI #header > *:not(h1),
|
||||||
.newUI #newUIoptions,
|
.newUI #newUIoptions,
|
||||||
#newUIoptions > *,
|
#newUIoptions > * {
|
||||||
fieldset label {
|
|
||||||
display: inline;
|
display: inline;
|
||||||
}
|
}
|
||||||
|
|
||||||
fieldset {
|
|
||||||
border: none;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0 0 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
fieldset legend {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
#header label {
|
#header label {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
@ -1111,3 +1040,29 @@ fieldset > label {
|
||||||
word-break: break-all;
|
word-break: break-all;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@supports (-moz-appearance: none) {
|
||||||
|
.chromium-only {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#header .filter-selection label .checkmate {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-selection select {
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select-resizer {
|
||||||
|
left: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#reset-filters {
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#filters summary h2 {
|
||||||
|
margin-left: -2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -66,7 +66,15 @@ function initGlobalEvents() {
|
||||||
$$('[data-toggle-on-click]').forEach(el => {
|
$$('[data-toggle-on-click]').forEach(el => {
|
||||||
// dataset on SVG doesn't work in Chrome 49-??, works in 57+
|
// dataset on SVG doesn't work in Chrome 49-??, works in 57+
|
||||||
const target = $(el.getAttribute('data-toggle-on-click'));
|
const target = $(el.getAttribute('data-toggle-on-click'));
|
||||||
el.onclick = () => target.classList.toggle('hidden');
|
el.onclick = event => {
|
||||||
|
event.preventDefault();
|
||||||
|
target.classList.toggle('hidden');
|
||||||
|
if (target.classList.contains('hidden')) {
|
||||||
|
el.removeAttribute('open');
|
||||||
|
} else {
|
||||||
|
el.setAttribute('open', '');
|
||||||
|
}
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
// triggered automatically by setupLivePrefs() below
|
// triggered automatically by setupLivePrefs() below
|
||||||
|
|
|
@ -132,6 +132,18 @@
|
||||||
margin: 0 .375rem;
|
margin: 0 .375rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* popup */
|
||||||
|
#message-box.stylus-popup {
|
||||||
|
margin: 0;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
#message-box.stylus-popup > div {
|
||||||
|
max-width: 90vw;
|
||||||
|
top: auto;
|
||||||
|
right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
@keyframes fadein {
|
@keyframes fadein {
|
||||||
from {
|
from {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
|
|
|
@ -70,11 +70,11 @@ function messageBox({
|
||||||
$create(`#${id}-contents`, tHTML(contents)),
|
$create(`#${id}-contents`, tHTML(contents)),
|
||||||
$create(`#${id}-buttons`,
|
$create(`#${id}-buttons`,
|
||||||
buttons.map((content, buttonIndex) => content &&
|
buttons.map((content, buttonIndex) => content &&
|
||||||
$create('button', {
|
$create('button', Object.assign({
|
||||||
buttonIndex,
|
buttonIndex,
|
||||||
textContent: content.textContent || content,
|
textContent: typeof content === 'object' ? '' : content,
|
||||||
onclick: content.onclick || messageBox.listeners.button,
|
onclick: messageBox.listeners.button,
|
||||||
}))),
|
}, typeof content === 'object' && content)))),
|
||||||
]),
|
]),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
20
popup.html
20
popup.html
|
@ -4,8 +4,6 @@
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<link rel="stylesheet" href="global.css">
|
<link rel="stylesheet" href="global.css">
|
||||||
<link rel="stylesheet" href="popup/popup.css">
|
|
||||||
<link rel="stylesheet" href="popup/search-results.css">
|
|
||||||
|
|
||||||
<style id="firefox-transitions-bug-suppressor">
|
<style id="firefox-transitions-bug-suppressor">
|
||||||
/* restrict to FF */
|
/* restrict to FF */
|
||||||
|
@ -34,6 +32,11 @@
|
||||||
<div class="actions">
|
<div class="actions">
|
||||||
<a href="#" class="enable" i18n-text="enableStyleLabel"></a>
|
<a href="#" class="enable" i18n-text="enableStyleLabel"></a>
|
||||||
<a href="#" class="disable" i18n-text="disableStyleLabel"></a>
|
<a href="#" class="disable" i18n-text="disableStyleLabel"></a>
|
||||||
|
<a href="#" class="configure" i18n-title="configureStyle">
|
||||||
|
<svg class="svg-icon config" viewBox="0 0 14 16">
|
||||||
|
<path d="m6.2578 1.1191c-0.4526 0-0.81641 0.36381-0.81641 0.81641v0.69531a5.5932 5.5932 0 0 0-1.1328 0.47266l-0.49414-0.49414c-0.16002-0.16002-0.36907-0.24023-0.57812-0.24023-0.20905 0-0.41811 0.080216-0.57812 0.24023l-1.0488 1.0488c-0.32004 0.32004-0.32004 0.83621 0 1.1562l0.49023 0.49023a5.5932 5.5932 0 0 0-0.4668 1.1348h-0.69726c-0.4526 0-0.81641 0.36576-0.81641 0.81836v1.4844c0 0.4526 0.36381 0.81641 0.81641 0.81641h0.69726a5.5932 5.5932 0 0 0 0.4707 1.1328l-0.49414 0.49414c-0.32004 0.32004-0.32004 0.83426 0 1.1543l1.0488 1.0508c0.32004 0.32003 0.83621 0.32003 1.1562 0l0.49023-0.49024a5.5932 5.5932 0 0 0 1.1367 0.4668v0.69727c0 0.4526 0.36381 0.81641 0.81641 0.81641h1.4844c0.4526 0 0.81641-0.36381 0.81641-0.81641v-0.69727a5.5932 5.5932 0 0 0 1.1328-0.4707l0.49414 0.49414c0.32004 0.32003 0.83622 0.32003 1.1562 0l1.0488-1.0508c0.32004-0.32004 0.32004-0.83426 0-1.1543l-0.49023-0.49023a5.5932 5.5932 0 0 0 0.4668-1.1367h0.69726c0.4526 0 0.81641-0.36381 0.81641-0.81641v-1.4844c0-0.4526-0.36381-0.81836-0.81641-0.81836h-0.69726a5.5932 5.5932 0 0 0-0.4707-1.1309l0.49414-0.49414c0.32004-0.32004 0.32004-0.83621 0-1.1562l-1.0488-1.0488c-0.16002-0.16002-0.36907-0.24023-0.57812-0.24023s-0.41811 0.080216-0.57812 0.24023l-0.49023 0.49023a5.5932 5.5932 0 0 0-1.1367-0.4668v-0.69727c0-0.4526-0.36381-0.81641-0.81641-0.81641zm0.56836 0.7793h0.34766c0.22291 0 0.40234 0.17943 0.40234 0.40234v1.1621a4.5763 4.5763 0 0 1 2.2227 0.92383l0.82422-0.82422c0.15762-0.15762 0.41074-0.15762 0.56836 0l0.24609 0.24609c0.15762 0.15762 0.15762 0.41074 0 0.56836l-0.82226 0.82227a4.5763 4.5763 0 0 1 0.91797 2.2246h1.166c0.22291 0 0.40234 0.17943 0.40234 0.40234v0.34766c0 0.22291-0.17943 0.40234-0.40234 0.40234h-1.1641a4.5763 4.5763 0 0 1-0.92188 2.2227l0.82422 0.82422c0.15762 0.15762 0.15762 0.41074 0 0.56836l-0.24609 0.24609c-0.15762 0.15763-0.41074 0.15763-0.56836 0l-0.82227-0.82226a4.5763 4.5763 0 0 1-2.2246 0.91797v1.166c0 0.22291-0.17943 0.40234-0.40234 0.40234h-0.34766c-0.22291 0-0.40234-0.17943-0.40234-0.40234v-1.1641a4.5763 4.5763 0 0 1-2.2227-0.92188l-0.82422 0.82422c-0.15762 0.15763-0.41074 0.15763-0.56836 0l-0.24609-0.24609c-0.15762-0.15762-0.15762-0.41074 0-0.56836l0.82226-0.82226a4.5763 4.5763 0 0 1-0.91797-2.2246h-1.166c-0.22291 0-0.40234-0.17943-0.40234-0.40234v-0.34766c0-0.22291 0.17943-0.40234 0.40234-0.40234h1.1641a4.5763 4.5763 0 0 1 0.92188-2.2227l-0.82422-0.82422c-0.15762-0.15762-0.15762-0.41074 0-0.56836l0.24609-0.24609c0.15762-0.15762 0.41074-0.15762 0.56836 0l0.82227 0.82227a4.5763 4.5763 0 0 1 2.2246-0.91797v-1.166c0-0.22291 0.17943-0.40234 0.40234-0.40234zm0.17383 2.7109a3.3898 3.3898 0 0 0-3.3906 3.3906 3.3898 3.3898 0 0 0 3.3906 3.3887 3.3898 3.3898 0 0 0 3.3906-3.3887 3.3898 3.3898 0 0 0-3.3906-3.3906zm0 1.1875a2.2034 2.2034 0 0 1 2.2031 2.2031 2.2034 2.2034 0 0 1-2.2031 2.2031 2.2034 2.2034 0 0 1-2.2031-2.2031 2.2034 2.2034 0 0 1 2.2031-2.2031z"/>
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
<a class="style-edit-link" href="edit.html?id=" i18n-title="editStyleLabel">
|
<a class="style-edit-link" href="edit.html?id=" i18n-title="editStyleLabel">
|
||||||
<svg class="svg-icon edit" viewBox="0 0 14 16">
|
<svg class="svg-icon edit" viewBox="0 0 14 16">
|
||||||
<path fill-rule="evenodd" d="M0 12v3h3l8-8-3-3-8 8zm3 2H1v-2h1v1h1v1zm10.3-9.3L12 6 9 3l1.3-1.3a.996.996 0 0 1 1.41 0l1.59 1.59c.39.39.39 1.02 0 1.41z"/>
|
<path fill-rule="evenodd" d="M0 12v3h3l8-8-3-3-8 8zm3 2H1v-2h1v1h1v1zm10.3-9.3L12 6 9 3l1.3-1.3a.996.996 0 0 1 1.41 0l1.59 1.59c.39.39.39 1.02 0 1.41z"/>
|
||||||
|
@ -117,11 +120,24 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="vendor-overwrites/colorpicker/colorpicker.css">
|
||||||
|
<script src="vendor-overwrites/colorpicker/colorpicker.js"></script>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="msgbox/msgbox.css">
|
||||||
|
<script src="msgbox/msgbox.js"></script>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="options/onoffswitch.css">
|
||||||
|
<link rel="stylesheet" href="manage/config-dialog.css">
|
||||||
|
<script src="manage/config-dialog.js"></script>
|
||||||
|
|
||||||
<script src="js/dom.js"></script>
|
<script src="js/dom.js"></script>
|
||||||
<script src="js/messaging.js"></script>
|
<script src="js/messaging.js"></script>
|
||||||
<script src="js/localization.js"></script>
|
<script src="js/localization.js"></script>
|
||||||
<script src="js/prefs.js"></script>
|
<script src="js/prefs.js"></script>
|
||||||
<script src="content/apply.js"></script>
|
<script src="content/apply.js"></script>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="popup/popup.css">
|
||||||
|
<link rel="stylesheet" href="popup/search-results.css">
|
||||||
<script src="popup/popup.js"></script>
|
<script src="popup/popup.js"></script>
|
||||||
<script src="popup/search-results.js"></script>
|
<script src="popup/search-results.js"></script>
|
||||||
<script src="popup/hotkeys.js"></script>
|
<script src="popup/hotkeys.js"></script>
|
||||||
|
|
|
@ -1,18 +1,36 @@
|
||||||
/* global applyOnMessage installed */
|
/* global applyOnMessage installed */
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-var
|
||||||
|
var hotkeys = (() => {
|
||||||
|
let togglablesShown;
|
||||||
|
let togglables;
|
||||||
|
let enabled = false;
|
||||||
|
let ready = false;
|
||||||
|
|
||||||
window.addEventListener('showStyles:done', function _() {
|
window.addEventListener('showStyles:done', function _() {
|
||||||
window.removeEventListener('showStyles:done', _);
|
window.removeEventListener('showStyles:done', _);
|
||||||
|
togglablesShown = true;
|
||||||
let togglablesShown = true;
|
togglables = getTogglables();
|
||||||
let togglables = getTogglables();
|
ready = true;
|
||||||
|
setState(true);
|
||||||
window.addEventListener('keydown', onKeyDown);
|
|
||||||
initHotkeyInfo();
|
initHotkeyInfo();
|
||||||
return;
|
});
|
||||||
|
|
||||||
|
return {setState};
|
||||||
|
|
||||||
|
function setState(newState = !enabled) {
|
||||||
|
if (!ready) {
|
||||||
|
throw new Error('hotkeys no ready');
|
||||||
|
}
|
||||||
|
if (newState !== enabled) {
|
||||||
|
window[`${newState ? 'add' : 'remove'}EventListener`]('keydown', onKeyDown);
|
||||||
|
enabled = newState;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function onKeyDown(event) {
|
function onKeyDown(event) {
|
||||||
if (event.ctrlKey || event.altKey || event.metaKey) {
|
if (event.ctrlKey || event.altKey || event.metaKey || !enabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let entry;
|
let entry;
|
||||||
|
@ -165,4 +183,4 @@ window.addEventListener('showStyles:done', function _() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
})();
|
||||||
|
|
|
@ -1,3 +1,12 @@
|
||||||
|
:root {
|
||||||
|
--header-width: 280px;
|
||||||
|
--checkbox-width: 24px;
|
||||||
|
--name-padding-left: 40px;
|
||||||
|
--name-padding-right: 40px;
|
||||||
|
--actions-width: 75px;
|
||||||
|
--onoffswitch-width: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
html, body {
|
html, body {
|
||||||
height: min-content;
|
height: min-content;
|
||||||
}
|
}
|
||||||
|
@ -14,7 +23,7 @@ body {
|
||||||
color: #000;
|
color: #000;
|
||||||
}
|
}
|
||||||
|
|
||||||
body > div:not(#installed) {
|
body > div:not(#installed):not(#message-box):not(.colorpicker-popup) {
|
||||||
margin-left: 9px;
|
margin-left: 9px;
|
||||||
margin-right: 9px;
|
margin-right: 9px;
|
||||||
}
|
}
|
||||||
|
@ -216,14 +225,15 @@ html[style] .entry:nth-child(10):before {
|
||||||
content: "0";
|
content: "0";
|
||||||
}
|
}
|
||||||
|
|
||||||
.entry .style-edit-link {
|
.entry .actions {
|
||||||
margin-right: 2px;
|
margin-left: -1px;
|
||||||
|
margin-right: -1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.entry .style-edit-link,
|
.entry .actions > * {
|
||||||
.entry .delete {
|
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding: 0 1px 0;
|
padding: 0 1px;
|
||||||
|
margin: 0 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.not-applied .checker,
|
.not-applied .checker,
|
||||||
|
@ -331,8 +341,8 @@ body.blocked .actions > .main-controls {
|
||||||
|
|
||||||
/* Never shown, but can be enabled with a style */
|
/* Never shown, but can be enabled with a style */
|
||||||
|
|
||||||
.enable,
|
.entry .actions > .enable,
|
||||||
.disable {
|
.entry .actions > .disable {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
/* global configDialog hotkeys */
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
let installed;
|
let installed;
|
||||||
|
@ -237,6 +239,7 @@ function createStyleElement({
|
||||||
Object.assign(entry, {
|
Object.assign(entry, {
|
||||||
id: ENTRY_ID_PREFIX_RAW + style.id,
|
id: ENTRY_ID_PREFIX_RAW + style.id,
|
||||||
styleId: style.id,
|
styleId: style.id,
|
||||||
|
styleIsUsercss: Boolean(style.usercssData),
|
||||||
className: entry.className + ' ' + (style.enabled ? 'enabled' : 'disabled'),
|
className: entry.className + ' ' + (style.enabled ? 'enabled' : 'disabled'),
|
||||||
onmousedown: handleEvent.maybeEdit,
|
onmousedown: handleEvent.maybeEdit,
|
||||||
});
|
});
|
||||||
|
@ -267,9 +270,18 @@ function createStyleElement({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const config = $('.configure', entry);
|
||||||
|
if (!style.usercssData && style.updateUrl && style.updateUrl.includes('?') && style.url) {
|
||||||
|
config.href = style.url;
|
||||||
|
config.target = '_blank';
|
||||||
|
} else if (!style.usercssData || !Object.keys(style.usercssData.vars || {}).length) {
|
||||||
|
config.style.display = 'none';
|
||||||
|
}
|
||||||
|
|
||||||
$('.enable', entry).onclick = handleEvent.toggle;
|
$('.enable', entry).onclick = handleEvent.toggle;
|
||||||
$('.disable', entry).onclick = handleEvent.toggle;
|
$('.disable', entry).onclick = handleEvent.toggle;
|
||||||
$('.delete', entry).onclick = handleEvent.delete;
|
$('.delete', entry).onclick = handleEvent.delete;
|
||||||
|
$('.configure', entry).onclick = handleEvent.configure;
|
||||||
|
|
||||||
invokeOrPostpone(!postponeDetect, detectSloppyRegexps, {entry, style});
|
invokeOrPostpone(!postponeDetect, detectSloppyRegexps, {entry, style});
|
||||||
|
|
||||||
|
@ -339,6 +351,18 @@ Object.assign(handleEvent, {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
configure(event) {
|
||||||
|
const {styleId, styleIsUsercss} = handleEvent.getClickedStyleElement(event);
|
||||||
|
if (styleIsUsercss) {
|
||||||
|
getStylesSafe({id: styleId}).then(([style]) => {
|
||||||
|
hotkeys.setState(false);
|
||||||
|
configDialog(style).then(() => {
|
||||||
|
hotkeys.setState(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
indicator(event) {
|
indicator(event) {
|
||||||
const entry = handleEvent.getClickedStyleElement(event);
|
const entry = handleEvent.getClickedStyleElement(event);
|
||||||
const info = template.regexpProblemExplanation.cloneNode(true);
|
const info = template.regexpProblemExplanation.cloneNode(true);
|
||||||
|
|
|
@ -218,8 +218,11 @@
|
||||||
setFromHexLettercaseElement();
|
setFromHexLettercaseElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
function hide() {
|
function hide({notify = true} = {}) {
|
||||||
if (shown) {
|
if (shown) {
|
||||||
|
if (notify) {
|
||||||
|
colorpickerCallback('');
|
||||||
|
}
|
||||||
unregisterEvents();
|
unregisterEvents();
|
||||||
focusNoScroll(prevFocusedElement);
|
focusNoScroll(prevFocusedElement);
|
||||||
$root.remove();
|
$root.remove();
|
||||||
|
@ -550,8 +553,11 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function onMouseUp(event) {
|
function onMouseUp(event) {
|
||||||
if (releaseMouse(event, ['saturation', 'hue', 'opacity']) &&
|
releaseMouse(event, ['saturation', 'hue', 'opacity']);
|
||||||
!event.target.closest('.codemirror-colorview, .colorpicker-popup, .CodeMirror')) {
|
}
|
||||||
|
|
||||||
|
function onMouseDown(event) {
|
||||||
|
if (event.button === 0 && !event.target.closest('.colorpicker-popup')) {
|
||||||
hide();
|
hide();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -592,7 +598,7 @@
|
||||||
colorpickerCallback(e.which === 27 ? '' : undefined);
|
colorpickerCallback(e.which === 27 ? '' : undefined);
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
hide();
|
hide({notify: false});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -660,6 +666,7 @@
|
||||||
|
|
||||||
function registerEvents() {
|
function registerEvents() {
|
||||||
window.addEventListener('keydown', onKeyDown, true);
|
window.addEventListener('keydown', onKeyDown, true);
|
||||||
|
window.addEventListener('mousedown', onMouseDown, true);
|
||||||
window.addEventListener('close-colorpicker-popup', onCloseRequest, true);
|
window.addEventListener('close-colorpicker-popup', onCloseRequest, true);
|
||||||
$root.addEventListener('mouseleave', snooze);
|
$root.addEventListener('mouseleave', snooze);
|
||||||
$root.addEventListener('mouseenter', stopSnoozing);
|
$root.addEventListener('mouseenter', stopSnoozing);
|
||||||
|
@ -681,6 +688,7 @@
|
||||||
|
|
||||||
function unregisterEvents() {
|
function unregisterEvents() {
|
||||||
window.removeEventListener('keydown', onKeyDown, true);
|
window.removeEventListener('keydown', onKeyDown, true);
|
||||||
|
window.removeEventListener('mousedown', onMouseDown, true);
|
||||||
window.removeEventListener('close-colorpicker-popup', hide, true);
|
window.removeEventListener('close-colorpicker-popup', hide, true);
|
||||||
$root.removeEventListener('mouseleave', snooze);
|
$root.removeEventListener('mouseleave', snooze);
|
||||||
$root.removeEventListener('mouseenter', stopSnoozing);
|
$root.removeEventListener('mouseenter', stopSnoozing);
|
||||||
|
@ -940,6 +948,9 @@
|
||||||
realColor.g = Math.round(g * q1 + realColor.g * q2);
|
realColor.g = Math.round(g * q1 + realColor.g * q2);
|
||||||
realColor.b = Math.round(b * q1 + realColor.b * q2);
|
realColor.b = Math.round(b * q1 + realColor.b * q2);
|
||||||
realColor.a = mixedA;
|
realColor.a = mixedA;
|
||||||
|
if (Math.abs(realColor.a - 1) < 1e-3) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// https://www.w3.org/TR/AERT#color-contrast
|
// https://www.w3.org/TR/AERT#color-contrast
|
||||||
const {r, g, b} = realColor;
|
const {r, g, b} = realColor;
|
||||||
|
|
|
@ -3181,6 +3181,17 @@ Parser.prototype = function() {
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
_unexpectedToken: function(token) {
|
_unexpectedToken: function(token) {
|
||||||
|
for (let i = tokenStream._ltIndex - 1; i >= 0; i--) {
|
||||||
|
const {type, value} = tokenStream._lt[i];
|
||||||
|
if (type === tokenStream._tokenData.S) {
|
||||||
|
// NOP
|
||||||
|
} else if (type === tokenStream._tokenData.COMMENT &&
|
||||||
|
value[2] === '[' && value[3] === '[' && value.endsWith(']]*/')) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
throw new SyntaxError("Unexpected token '" + token.value + "' at line " + token.startLine + ", col " + token.startCol + ".", token.startLine, token.startCol);
|
throw new SyntaxError("Unexpected token '" + token.value + "' at line " + token.startLine + ", col " + token.startCol + ".", token.startLine, token.startCol);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -7148,7 +7159,7 @@ TokenStreamBase.prototype = {
|
||||||
if (tokenTypes.includes(tt)) {
|
if (tokenTypes.includes(tt)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} while (tt === 4 && this.LA(0) !== 0);
|
} while (tt === this._tokenData.COMMENT && this.LA(0) !== 0);
|
||||||
|
|
||||||
//no match found, put the token back
|
//no match found, put the token back
|
||||||
this.unget();
|
this.unget();
|
||||||
|
@ -10967,25 +10978,6 @@ CSSLint.addFormatter({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!CSSLint.suppressUsoVarError) {
|
|
||||||
CSSLint.suppressUsoVarError = true;
|
|
||||||
parserlib.css.Tokens[parserlib.css.Tokens.COMMENT].hide = false;
|
|
||||||
const isUsoVar = ({value}) => value.startsWith('/*[[') && value.endsWith(']]*/');
|
|
||||||
CSSLint.addRule({
|
|
||||||
id: 'uso-vars',
|
|
||||||
init(parser, reporter) {
|
|
||||||
parser.addListener('error', function ({message, line, col}) {
|
|
||||||
if (!isUsoVar(this._tokenStream._token)) {
|
|
||||||
const {_lt, _ltIndex: i} = this._tokenStream;
|
|
||||||
if (i < 2 || !_lt.slice(0, i - 1).reverse().some(isUsoVar)) {
|
|
||||||
reporter.error(message, line, col);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
self.onmessage = ({data: {action = 'run', code, config}}) => {
|
self.onmessage = ({data: {action = 'run', code, config}}) => {
|
||||||
switch (action) {
|
switch (action) {
|
||||||
|
|
||||||
|
@ -11000,8 +10992,6 @@ self.onmessage = ({data: {action = 'run', code, config}}) => {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 'run':
|
case 'run':
|
||||||
Object.defineProperty(config, 'errors', {get: () => 0, set: () => 0});
|
|
||||||
config['uso-vars'] = 1;
|
|
||||||
self.postMessage(CSSLint.verify(code, config).messages.map(m => {
|
self.postMessage(CSSLint.verify(code, config).messages.map(m => {
|
||||||
// the functions are non-tranferable and we need only an id
|
// the functions are non-tranferable and we need only an id
|
||||||
m.rule = {id: m.rule.id};
|
m.rule = {id: m.rule.id};
|
||||||
|
|
Loading…
Reference in New Issue
Block a user