diff options
| author | neauoire <aliceffekt@gmail.com> | 2019-11-09 10:47:37 -0500 |
|---|---|---|
| committer | neauoire <aliceffekt@gmail.com> | 2019-11-09 10:47:37 -0500 |
| commit | a0015b535b78ae49e39af1c76bf53b70c14d20b4 (patch) | |
| tree | d8b282ddcb7d2d94c374e4e41de4605197833b52 /editor | |
| parent | 3226de0b193d505ebe0504f263f59cd64e24597c (diff) | |
*
Diffstat (limited to 'editor')
| -rw-r--r-- | editor/links/main.css | 8 | ||||
| -rw-r--r-- | editor/links/reset.css | 1 | ||||
| -rw-r--r-- | editor/links/theme.css | 15 | ||||
| -rw-r--r-- | editor/scripts/benchmark.js | 47 | ||||
| -rw-r--r-- | editor/scripts/color.js | 34 | ||||
| -rw-r--r-- | editor/scripts/lib/theme.js | 167 |
6 files changed, 272 insertions, 0 deletions
diff --git a/editor/links/main.css b/editor/links/main.css new file mode 100644 index 0000000..e96b69b --- /dev/null +++ b/editor/links/main.css @@ -0,0 +1,8 @@ +body { font-size:14px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; padding:30px; transition: background-color 500ms;} +body svg { margin:0px auto 30px; display: block; } +table { margin:0px auto 30px; } +table tr td { padding:5px 10px; transition: background-color 250ms, color 250ms; font-weight: bold; font-size:12px; line-height: 16px; position: relative; padding-left:32px;} +table tr td svg { stroke:none; display: inline-block; margin:0px 15px 0px 0px; position: absolute; left:8px;} +table tr td span { display: inline-block; } +#print { font-family: courier; font-size:12px; padding:5px 10px; } +#print b { font-weight: bold } diff --git a/editor/links/reset.css b/editor/links/reset.css new file mode 100644 index 0000000..9f57584 --- /dev/null +++ b/editor/links/reset.css @@ -0,0 +1 @@ +* { margin:0;padding:0;border:0;outline:0;text-decoration:none;font-weight:inherit;font-style:inherit;color:inherit;font-size:100%;font-family:inherit;vertical-align:baseline;list-style:none;border-collapse:collapse;border-spacing:0; -webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;}
\ No newline at end of file diff --git a/editor/links/theme.css b/editor/links/theme.css new file mode 100644 index 0000000..5cd3594 --- /dev/null +++ b/editor/links/theme.css @@ -0,0 +1,15 @@ +body { background:var(--background) !important } +.bg { background:var(--background) !important } +.f_high { color:var(--f_high) !important; stroke:var(--f_high) !important } +.f_med { color:var(--f_med) !important ; stroke:var(--f_med) !important } +.f_low { color:var(--f_low) !important ; stroke:var(--f_low) !important } +.f_inv { color:var(--f_inv) !important ; stroke:var(--f_inv) !important } +.b_high { background:var(--b_high) !important; fill:var(--b_high) !important } +.b_med { background:var(--b_med) !important ; fill:var(--b_med) !important } +.b_low { background:var(--b_low) !important ; fill:var(--b_low) !important } +.b_inv { background:var(--b_inv) !important ; fill:var(--b_inv) !important } + +table tr th { color:var(--f_high) !important; } +pre { color:var(--f_high) !important; } +pre b { color:var(--f_med) !important; } +pre i { color:var(--f_low) !important; }
\ No newline at end of file diff --git a/editor/scripts/benchmark.js b/editor/scripts/benchmark.js new file mode 100644 index 0000000..84c6d1b --- /dev/null +++ b/editor/scripts/benchmark.js @@ -0,0 +1,47 @@ +'use strict' + +function Benchmark () { + this.matches = function () { + var a = [{ id: 'b_inv_f_inv', fc: theme.active.f_inv, bc: theme.active.b_inv }] + for (const fid in theme.active) { + if (fid.substr(0, 1) != 'f' || fid.indexOf('_inv') > -1) { continue } + const fc = theme.active[fid] + for (const bid in theme.active) { + if (bid.substr(0, 1) != 'b' || bid.indexOf('_inv') > -1) { continue } + const bc = theme.active[bid] + a.push({ id: `${bid}_${fid}`, fc: fc, bc: bc }) + } + } + return a + } + + this.refresh = function () { + const el = document.getElementById('print') + const html = '' + const count = 0 + const matches = bench.matches() + + console.log(matches) + for (const match of matches) { + const cell = document.getElementById(match.id) + console.log(cell, match.id) + // cell.textContent = '0.0' + } + + el.innerHTML = html + } + + this.log = function (id, fc, bc) { + let html = '' + + const rating = new Color(fc).contrast(new Color(bc)) + + if (rating == 1) { + html += `Overlap: <b>${id}</b> <i>${bc}</i>\n` + } else if (rating < 1.5) { + html += `Low contrast(${rating.toFixed(2)}): <b>${id}</b> <i>${bc}</i>\n` + } + + return html + } +} diff --git a/editor/scripts/color.js b/editor/scripts/color.js new file mode 100644 index 0000000..8296e1e --- /dev/null +++ b/editor/scripts/color.js @@ -0,0 +1,34 @@ +function Color (hex = '#000000') { + this.hex = hex + + var r = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(this.hex) + + this.rgb = { r: parseInt(r[1], 16), g: parseInt(r[2], 16), b: parseInt(r[3], 16) } + + this.r = this.rgb.r + this.g = this.rgb.g + this.b = this.rgb.b + + this.average = parseInt((this.rgb.r + this.rgb.g + this.rgb.b) / 3) + this.invert = { r: 255 - this.rgb.r, g: 255 - this.rgb.g, b: 255 - this.rgb.b } + + this.contrast = function (b) { + const a_lum = 0.2126 * _linear(this.r / 256) + 0.7152 * _linear(this.g / 256) + 0.0722 * _linear(this.b / 256) + const b_lum = 0.2126 * _linear(b.r / 256) + 0.7152 * _linear(b.g / 256) + 0.0722 * _linear(b.b / 256) + return a_lum > b_lum ? (a_lum + 0.05) / (b_lum + 0.05) : (b_lum + 0.05) / (a_lum + 0.05) + } + + this.rgba = function () { + return 'rgba(' + this.rgb().r + ',' + this.rgb().g + ',' + this.rgb().b + ',1)' + } + + this.floats = function () { + return { r: this.rgb.r / 255, g: this.rgb.g / 255, b: this.rgb.b / 255 } + } + + this.toString = function () { + return this.hex + } + + function _linear (v) { return (v <= 0.03928) ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4) } +} diff --git a/editor/scripts/lib/theme.js b/editor/scripts/lib/theme.js new file mode 100644 index 0000000..6a01c24 --- /dev/null +++ b/editor/scripts/lib/theme.js @@ -0,0 +1,167 @@ +'use strict' + +/* global localStorage */ +/* global FileReader */ +/* global DOMParser */ + +function Theme (client) { + this.el = document.createElement('style') + this.el.type = 'text/css' + + this.active = {} + this.default = { + background: '#eee', + f_high: '#000', + f_med: '#999', + f_low: '#ccc', + f_inv: '#000', + b_high: '#000', + b_med: '#888', + b_low: '#aaa', + b_inv: '#ffb545' + } + + this.install = (host = document.body) => { + window.addEventListener('dragover', this.drag) + window.addEventListener('drop', this.drop) + host.appendChild(this.el) + } + + this.start = () => { + console.log('Theme', 'Starting..') + if (isJson(localStorage.theme)) { + const storage = JSON.parse(localStorage.theme) + if (isValid(storage)) { + console.log('Theme', 'Loading theme in localStorage..') + this.load(storage) + return + } + } + this.load(this.default) + } + + this.open = () => { + console.log('Theme', 'Open theme..') + const input = document.createElement('input') + input.type = 'file' + input.onchange = (e) => { + this.read(e.target.files[0], this.load) + } + input.click() + } + + this.load = (data) => { + const theme = this.parse(data) + if (!isValid(theme)) { console.warn('Theme', 'Invalid format'); return } + console.log('Theme', 'Loaded theme!') + this.el.innerHTML = `:root { + --background: ${theme.background}; + --f_high: ${theme.f_high}; + --f_med: ${theme.f_med}; + --f_low: ${theme.f_low}; + --f_inv: ${theme.f_inv}; + --b_high: ${theme.b_high}; + --b_med: ${theme.b_med}; + --b_low: ${theme.b_low}; + --b_inv: ${theme.b_inv}; + }` + localStorage.setItem('theme', JSON.stringify(theme)) + this.active = theme + if (this.onLoad) { + this.onLoad(data) + } + } + + this.reset = () => { + this.load(this.default) + } + + this.set = (key, val) => { + if (!val) { return } + const hex = (`${val}`.substr(0, 1) !== '#' ? '#' : '') + `${val}` + if (!isColor(hex)) { console.warn('Theme', `${hex} is not a valid color.`); return } + this.active[key] = hex + } + + this.read = (key) => { + return this.active[key] + } + + this.parse = (any) => { + if (isValid(any)) { return any } + if (isJson(any)) { return JSON.parse(any) } + if (isHtml(any)) { return extract(any) } + } + + // Drag + + this.drag = (e) => { + e.stopPropagation() + e.preventDefault() + e.dataTransfer.dropEffect = 'copy' + } + + this.drop = (e) => { + e.preventDefault() + const file = e.dataTransfer.files[0] + if (file.name.indexOf('.svg') > -1) { + this.read(file, this.load) + } + e.stopPropagation() + } + + this.read = (file, callback) => { + const reader = new FileReader() + reader.onload = (event) => { + callback(event.target.result) + } + reader.readAsText(file, 'UTF-8') + } + + // Helpers + + function extract (xml) { + const svg = new DOMParser().parseFromString(xml, 'text/xml') + try { + return { + background: svg.getElementById('background').getAttribute('fill'), + f_high: svg.getElementById('f_high').getAttribute('fill'), + f_med: svg.getElementById('f_med').getAttribute('fill'), + f_low: svg.getElementById('f_low').getAttribute('fill'), + f_inv: svg.getElementById('f_inv').getAttribute('fill'), + b_high: svg.getElementById('b_high').getAttribute('fill'), + b_med: svg.getElementById('b_med').getAttribute('fill'), + b_low: svg.getElementById('b_low').getAttribute('fill'), + b_inv: svg.getElementById('b_inv').getAttribute('fill') + } + } catch (err) { + console.warn('Theme', 'Incomplete SVG Theme', err) + } + } + + function isValid (json) { + if (!json) { return false } + if (!json.background) { return false } + if (!json.f_high) { return false } + if (!json.f_med) { return false } + if (!json.f_low) { return false } + if (!json.f_inv) { return false } + if (!json.b_high) { return false } + if (!json.b_med) { return false } + if (!json.b_low) { return false } + if (!json.b_inv) { return false } + return true + } + + function isColor (hex) { + return /^#([0-9A-F]{3}){1,2}$/i.test(hex) + } + + function isJson (text) { + try { JSON.parse(text); return true } catch (error) { return false } + } + + function isHtml (text) { + try { new DOMParser().parseFromString(text, 'text/xml'); return true } catch (error) { return false } + } +} |
