Skip to content

Commit

Permalink
usercss editor: use real theme color for inputs in widgets
Browse files Browse the repository at this point in the history
  • Loading branch information
tophf committed Dec 5, 2017
1 parent 69736ef commit bd0f460
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 39 deletions.
2 changes: 1 addition & 1 deletion edit.html
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@
<link rel="stylesheet" href="/edit/codemirror-default.css">

<template data-id="appliesTo">
<li>
<li class="applies-to-item">
<div class="select-resizer">
<select name="applies-type" class="applies-type style-contributor">
<option value="url" i18n-text="appliesUrlOption"></option>
Expand Down
144 changes: 110 additions & 34 deletions edit/applies-to-line-widget.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ function createAppliesToLineWidget(cm) {
const THROTTLE_DELAY = 400;
let TPL, EVENTS, CLICK_ROUTE;
let widgets = [];
let fromLine, toLine, styleVariables;
let fromLine, toLine, actualStyle;
let initialized = false;
return {toggle};

Expand All @@ -29,23 +29,14 @@ function createAppliesToLineWidget(cm) {
$create('label', t('appliesLabel')),
$create('ul.applies-to-list'),
]),
listItem:
$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')),
]),
listItem: template.appliesTo,
appliesToEverything:
$create('li.applies-to-everything', t('appliesToEverything')),
};

$('button', TPL.listItem).insertAdjacentElement('afterend',
$create('button.test-regexp', t('styleRegexpTestButton')));

CLICK_ROUTE = {
'.test-regexp': (item, apply) => {
regExpTester.toggle();
Expand Down Expand Up @@ -136,15 +127,13 @@ function createAppliesToLineWidget(cm) {
}
};

styleVariables = $create('style');
actualStyle = $create('style');
fromLine = 0;
toLine = cm.doc.size;

cm.on('change', onChange);
cm.on('optionChange', onOptionChange);

// is it possible to avoid flickering?
window.addEventListener('load', updateWidgetStyle);
chrome.runtime.onMessage.addListener(onRuntimeMessage);

updateWidgetStyle();
Expand All @@ -158,9 +147,8 @@ function createAppliesToLineWidget(cm) {
widgets.length = 0;
cm.off('change', onChange);
cm.off('optionChange', onOptionChange);
window.removeEventListener('load', updateWidgetStyle);
chrome.runtime.onMessage.removeListener(onRuntimeMessage);
styleVariables.remove();
actualStyle.remove();
}

function onChange(cm, event) {
Expand Down Expand Up @@ -229,24 +217,112 @@ function createAppliesToLineWidget(cm) {
}

function updateWidgetStyle() {
const gutterStyle = getComputedStyle(cm.getGutterElement());
const borderStyle = gutterStyle.borderRightWidth !== '0px' ?
`${gutterStyle.borderRightWidth} ${gutterStyle.borderRightStyle} ${gutterStyle.borderRightColor}` :
`1px solid ${gutterStyle.color}`;
const id = Date.now();
styleVariables.textContent = `
.single-editor {
--at-background-color-${id}: ${gutterStyle.backgroundColor};
--at-border-top-${id}: ${borderStyle};
--at-border-bottom-${id}: ${borderStyle};
}
const MIN_LUMA = .05;
const MIN_LUMA_DIFF = .4;
const color = {
wrapper: getRealColors(cm.display.wrapper),
gutter: getRealColors(cm.display.gutters, {
bg: 'backgroundColor',
border: 'borderRightColor',
}),
line: getRealColors('.CodeMirror-linenumber'),
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 {
background-color: var(--at-background-color-${id});
border-top: var(--at-border-top-${id});
border-bottom: var(--at-border-bottom-${id});
background-color: ${color.gutter.bg};
border-top: ${borderStyleForced};
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() {
Expand Down
4 changes: 0 additions & 4 deletions edit/codemirror-default.css
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,3 @@
position: absolute;
pointer-events: none;
}

.CodeMirror-activeline .applies-to ul {
z-index: 2;
}

0 comments on commit bd0f460

Please sign in to comment.