From 6a1bc8c05be15f49a8e5232742ea2f75df2dab22 Mon Sep 17 00:00:00 2001 From: Nik Rolls Date: Sat, 22 Apr 2017 15:54:38 +1200 Subject: [PATCH] Workaround for Chrome queuing transitions bug Also reworked some more code around theme switching and messaging. --- src/js/background.js | 170 +++++++++-------- src/js/content.js | 87 +-------- src/js/lib/messaging.js | 16 ++ src/js/lib/theme-switcher.js | 103 +++++++++++ src/js/lib/theme.js | 56 ------ src/js/lib/themes.js | 183 +++++++++++++++++++ src/manifest.json | 2 +- src/sass/themes/chaos.scss | 8 +- src/sass/themes/chrome.scss | 8 +- src/sass/themes/clouds-midnight.scss | 12 +- src/sass/themes/clouds.scss | 12 +- src/sass/themes/cobalt.scss | 8 +- src/sass/themes/crimson-editor.scss | 8 +- src/sass/themes/dawn.scss | 8 +- src/sass/themes/dreamweaver.scss | 8 +- src/sass/themes/eclipse.scss | 8 +- src/sass/themes/github.scss | 6 +- src/sass/themes/gob.scss | 12 +- src/sass/themes/gruvbox.scss | 8 +- src/sass/themes/idle-fingers.scss | 12 +- src/sass/themes/iplastic.scss | 8 +- src/sass/themes/katzen-milch.scss | 8 +- src/sass/themes/kr-theme.scss | 8 +- src/sass/themes/kurior.scss | 8 +- src/sass/themes/merbivore-soft.scss | 12 +- src/sass/themes/merbivore.scss | 12 +- src/sass/themes/mono-industrial.scss | 8 +- src/sass/themes/monokai.scss | 8 +- src/sass/themes/pastel-on-dark.scss | 8 +- src/sass/themes/solarized-dark.scss | 8 +- src/sass/themes/solarized-light.scss | 8 +- src/sass/themes/terminal.scss | 8 +- src/sass/themes/textmate.scss | 8 +- src/sass/themes/tomorrow-night-blue.scss | 8 +- src/sass/themes/tomorrow-night-bright.scss | 8 +- src/sass/themes/tomorrow-night-eighties.scss | 8 +- src/sass/themes/tomorrow-night.scss | 8 +- src/sass/themes/tomorrow.scss | 8 +- src/sass/themes/twilight.scss | 8 +- src/sass/themes/vibrant-ink.scss | 8 +- src/sass/themes/xcode.scss | 10 +- src/sass/transition.scss | 41 ++++- 42 files changed, 691 insertions(+), 263 deletions(-) create mode 100644 src/js/lib/messaging.js create mode 100644 src/js/lib/theme-switcher.js delete mode 100644 src/js/lib/theme.js create mode 100644 src/js/lib/themes.js diff --git a/src/js/background.js b/src/js/background.js index 4762420..dec4d85 100644 --- a/src/js/background.js +++ b/src/js/background.js @@ -1,6 +1,7 @@ 'use strict'; import browser from './lib/browser'; +import { listen } from './lib/messaging'; import { removeComments, firstJSONCharIndex } from './lib/utilities'; import { jsonObjectToHTML } from './lib/dom-builder'; @@ -8,102 +9,99 @@ import { jsonObjectToHTML } from './lib/dom-builder'; browser.storage.local.set({appVersion: browser.runtime.getManifest().version}); // Listen for requests from content pages wanting to set up a port -browser.runtime.onConnect.addListener(function(port) { - if (port.name !== 'jf') { - console.log('JSON Formatter error - unknown port name ' + port.name, port); - return; - } +listen((port, msg) => { + let jsonpFunctionName = null; + let validJsonText; + + if (msg.type === 'SENDING TEXT') { + // Try to parse as JSON + let obj; + let text = msg.text; + + // Strip any leading garbage, such as a 'while(1);' + const strippedText = text.substring(firstJSONCharIndex(text)); + + try { + obj = JSON.parse(strippedText); + validJsonText = strippedText; + } catch (e) { + // Not JSON; could be JSONP though. + // Try stripping 'padding' (if any), and try parsing it again + text = text.trim(); + // Find where the first paren is (and exit if none) + const indexOfParen = text.indexOf('('); + if (!indexOfParen) { + port.postMessage(['NOT JSON', 'no opening parenthesis']); + port.disconnect(); + return; + } - port.onMessage.addListener(function(msg) { - let jsonpFunctionName = null; - let validJsonText; + // Get the substring up to the first "(", with any comments/whitespace stripped out + const firstBit = removeComments(text.substring(0, indexOfParen)).trim(); + if (!firstBit.match(/^[a-zA-Z_$][\.\[\]'"0-9a-zA-Z_$]*$/)) { + // The 'firstBit' is NOT a valid function identifier. + port.postMessage(['NOT JSON', 'first bit not a valid function name']); + port.disconnect(); + return; + } - if (msg.type === 'SENDING TEXT') { - // Try to parse as JSON - let obj; - let text = msg.text; + // Find last parenthesis (exit if none) + const indexOfLastParen = text.lastIndexOf(')'); + if (!indexOfLastParen) { + port.postMessage(['NOT JSON', 'no closing paren']); + port.disconnect(); + return; + } - // Strip any leading garbage, such as a 'while(1);' - const strippedText = text.substring(firstJSONCharIndex(text)); + // Check that what's after the last parenthesis is just whitespace, comments, and possibly a semicolon (exit if anything else) + const lastBit = removeComments(text.substring(indexOfLastParen + 1)).trim(); + if (lastBit !== "" && lastBit !== ';') { + port.postMessage(['NOT JSON', 'last closing paren followed by invalid characters']); + port.disconnect(); + return; + } + // So, it looks like a valid JS function call, but we don't know whether it's JSON inside the parentheses... + // Check if the 'argument' is actually JSON (and record the parsed result) + text = text.substring(indexOfParen + 1, indexOfLastParen); try { - obj = JSON.parse(strippedText); - validJsonText = strippedText; - } catch (e) { - // Not JSON; could be JSONP though. - // Try stripping 'padding' (if any), and try parsing it again - text = text.trim(); - // Find where the first paren is (and exit if none) - const indexOfParen = text.indexOf('('); - if (!indexOfParen) { - port.postMessage(['NOT JSON', 'no opening parenthesis']); - port.disconnect(); - return; - } - - // Get the substring up to the first "(", with any comments/whitespace stripped out - const firstBit = removeComments(text.substring(0, indexOfParen)).trim(); - if (!firstBit.match(/^[a-zA-Z_$][\.\[\]'"0-9a-zA-Z_$]*$/)) { - // The 'firstBit' is NOT a valid function identifier. - port.postMessage(['NOT JSON', 'first bit not a valid function name']); - port.disconnect(); - return; - } - - // Find last parenthesis (exit if none) - const indexOfLastParen = text.lastIndexOf(')'); - if (!indexOfLastParen) { - port.postMessage(['NOT JSON', 'no closing paren']); - port.disconnect(); - return; - } - - // Check that what's after the last parenthesis is just whitespace, comments, and possibly a semicolon (exit if anything else) - const lastBit = removeComments(text.substring(indexOfLastParen + 1)).trim(); - if (lastBit !== "" && lastBit !== ';') { - port.postMessage(['NOT JSON', 'last closing paren followed by invalid characters']); - port.disconnect(); - return; - } - - // So, it looks like a valid JS function call, but we don't know whether it's JSON inside the parentheses... - // Check if the 'argument' is actually JSON (and record the parsed result) - text = text.substring(indexOfParen + 1, indexOfLastParen); - try { - obj = JSON.parse(text); - validJsonText = text; - } - catch (e2) { - // Just some other text that happens to be in a function call. - // Respond as not JSON, and exit - port.postMessage(['NOT JSON', 'looks like a function call, but the parameter is not valid JSON']); - return; - } - - jsonpFunctionName = firstBit; + obj = JSON.parse(text); + validJsonText = text; } - - // If still running, we now have obj, which is valid JSON. - - // Ensure it's not a number or string (technically valid JSON, but no point prettifying it) - if (typeof obj !== 'object' && typeof obj !== 'array') { - port.postMessage(['NOT JSON', 'technically JSON but not an object or array']); - port.disconnect(); + catch (e2) { + // Just some other text that happens to be in a function call. + // Respond as not JSON, and exit + port.postMessage(['NOT JSON', 'looks like a function call, but the parameter is not valid JSON']); return; } - // And send it the message to confirm that we're now formatting (so it can show a spinner) - port.postMessage(['FORMATTING']); + jsonpFunctionName = firstBit; + } - // Do formatting - const html = jsonObjectToHTML(obj, jsonpFunctionName); + // If still running, we now have obj, which is valid JSON. - // Post the HTML string to the content script - port.postMessage(['FORMATTED', html, validJsonText]); - } else if (msg.type === 'GET STORED THEME') { - browser.storage.sync.get('theme', (data) => port.postMessage(['SWITCH THEME', data && data.theme])); - } else if (msg.type === 'UPDATE STORED THEME') { - browser.storage.sync.set({theme: msg.theme}, () => port.postMessage(['SWITCH THEME', msg.theme])); + // Ensure it's not a number or string (technically valid JSON, but no point prettifying it) + if (typeof obj !== 'object' && typeof obj !== 'array') { + port.postMessage(['NOT JSON', 'technically JSON but not an object or array']); + port.disconnect(); + return; } - }); + + // And send it the message to confirm that we're now formatting (so it can show a spinner) + port.postMessage(['FORMATTING']); + + // Do formatting + const html = jsonObjectToHTML(obj, jsonpFunctionName); + + // Post the HTML string to the content script + port.postMessage(['FORMATTED', html, validJsonText]); + } else if (msg.type === 'GET STORED THEME') { + browser.storage.sync.get('theme', (data) => { + port.postMessage({type: 'STORED THEME', themeName: data && data.theme}) + }); + } else if (msg.type === 'UPDATE STORED THEME') { + browser.storage.sync.set({theme: msg.theme}, () => { + port.postMessage({type: 'STORED THEME', themeName: msg.theme}); + }); + } }); diff --git a/src/js/content.js b/src/js/content.js index b06a249..6e81a26 100644 --- a/src/js/content.js +++ b/src/js/content.js @@ -1,5 +1,5 @@ -import browser from './lib/browser'; -import { themes, switchToTheme } from './lib/theme'; +import { connect } from './lib/messaging'; +import { enableTheming } from './lib/theme-switcher'; let jfContent; let pre; @@ -7,23 +7,12 @@ let jfStyleEl; let slowAnalysisTimeout; // Open the port "jf" now, ready for when we need it -const port = browser.runtime.connect({name: 'jf'}); +const port = connect(); // Add listener to receive response from BG when ready port.onMessage.addListener(function(message) { switch (message[0]) { - case 'SWITCH THEME': - const themeName = themes[message[1]] ? message[1] : themes.default; - switchToTheme(themes[themeName]); - - const themeSelectOption = document.getElementById('themeSelect').querySelector(`[value="${themeName}"]`); - if (themeSelectOption) { - themeSelectOption.selected = true; - } - - break; - case 'NOT JSON' : pre.hidden = false; document.body.removeChild(jfContent); @@ -31,8 +20,7 @@ port.onMessage.addListener(function(message) { case 'FORMATTING' : // It is JSON, and it's now being formatted in the background worker. - - port.postMessage({type: 'GET STORED THEME'}); + enableTheming(); // Clear the slowAnalysisTimeout (if the BG worker had taken longer than 1s to respond with an answer to whether or not this is JSON, then it would have fired, unhiding the PRE... But now that we know it's JSON, we can clear this timeout, ensuring the PRE stays hidden.) clearTimeout(slowAnalysisTimeout); @@ -52,8 +40,7 @@ port.onMessage.addListener(function(message) { formattingMsg.hidden = false; }, 250); - configureFormatOptionBar(); - configureThemeOptionBar(); + insertFormatOptionBar(); // Attach event handlers document.addEventListener('click', generalClick, false); @@ -79,7 +66,7 @@ port.onMessage.addListener(function(message) { } }); -function configureFormatOptionBar() { +function insertFormatOptionBar() { const formatBar = document.createElement('div'); formatBar.id = 'formatOptionBar'; formatBar.classList.add('optionBar'); @@ -111,68 +98,6 @@ function configureFormatOptionBar() { document.body.insertBefore(formatBar, pre); } -function configureThemeOptionBar() { - const themeBar = document.createElement('div'); - themeBar.id = 'themeOptionBar'; - themeBar.classList.add('optionBar'); - - const label = document.createElement('label'); - const select = document.createElement('select'); - label.innerText = 'Theme: '; - select.id = 'themeSelect'; - select.innerHTML = ` - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - `; - - select.addEventListener('change', () => { - port.postMessage({type: 'UPDATE STORED THEME', theme: select.value}); - select.blur(); - }); - - label.appendChild(select); - themeBar.appendChild(label); - document.body.insertBefore(themeBar, pre); -} - function ready() { // First, check if it's a PRE and exit if not diff --git a/src/js/lib/messaging.js b/src/js/lib/messaging.js new file mode 100644 index 0000000..b6187b1 --- /dev/null +++ b/src/js/lib/messaging.js @@ -0,0 +1,16 @@ +import browser from './browser'; + +export function connect() { + return browser.runtime.connect({name: 'jf'}); +} + +export function listen(onMessageReceived) { + browser.runtime.onConnect.addListener((port) => { + if (port.name !== 'jf') { + console.log(`JSON Formatter error - unknown port name ${port.name}`, port); + return; + } + + port.onMessage.addListener((...args) => onMessageReceived(port, ...args)); + }); +} diff --git a/src/js/lib/theme-switcher.js b/src/js/lib/theme-switcher.js new file mode 100644 index 0000000..aae2210 --- /dev/null +++ b/src/js/lib/theme-switcher.js @@ -0,0 +1,103 @@ +import { themes } from './themes'; +import { connect } from "./messaging"; + +const transitionStyles = require('../../sass/transition.scss'); +let port, themeStyleElement, transitionStyleElement; + +export function enableTheming() { + port = connect(); + port.onMessage.addListener((message) => { + if (message.type === 'STORED THEME') { + switchToTheme(message.themeName); + } + }); + insertThemeOptionBar(); +} + +function insertThemeOptionBar() { + const themeBar = document.createElement('div'); + themeBar.id = 'themeOptionBar'; + themeBar.classList.add('optionBar'); + + const label = document.createElement('label'); + const select = document.createElement('select'); + label.innerText = 'Theme: '; + select.id = 'themeSelect'; + select.innerHTML = generateOptionsHTML(); + + select.addEventListener('change', () => { + port.postMessage({type: 'UPDATE STORED THEME', theme: select.value}); + select.blur(); + }); + + label.appendChild(select); + themeBar.appendChild(label); + document.body.insertBefore(themeBar, document.body.childNodes[0]); + port.postMessage({type: 'GET STORED THEME'}); +} + +function getThemeSelect() { + return document.getElementById('themeSelect'); +} + +function getThemesNestedByType() { + return Object.keys(themes).reduce((output, key) => { + const theme = themes[key]; + if (typeof theme === 'object') { + output[theme.type] = output[theme.type] || []; + output[theme.type][key] = theme; + } + return output; + }, {}); +} + +function generateOptionsHTML() { + const nestedThemes = getThemesNestedByType(); + + return Object.keys(nestedThemes) + .map((groupName) => { + const themeGroup = nestedThemes[groupName]; + const groupOptions = Object.keys(themeGroup).map((key) => { + const theme = themeGroup[key]; + return ``; + }).join(''); + + return `${groupOptions}`; + }).join(''); +} + +function switchToTheme(themeName) { + themeName = themes[themeName] ? themeName : themes.default; + const theme = themes[themeName]; + const element = getThemeElement(); + + if (element.innerHTML) { + insertTransitionThemes(); + } + if (element.innerHTML !== theme.styles) { + element.innerHTML = theme.styles; + } + + const themeSelect = getThemeSelect(); + const themeSelectOption = themeSelect && themeSelect.querySelector(`[value="${themeName}"]`); + if (themeSelectOption) { + themeSelectOption.selected = true; + } +} + +function getThemeElement() { + if (!themeStyleElement) { + themeStyleElement = document.createElement('style'); + document.head.appendChild(themeStyleElement); + } + + return themeStyleElement; +} + +function insertTransitionThemes() { + if (!transitionStyleElement) { + transitionStyleElement = document.createElement('style'); + transitionStyleElement.innerHTML = transitionStyles; + document.head.appendChild(transitionStyleElement); + } +} diff --git a/src/js/lib/theme.js b/src/js/lib/theme.js deleted file mode 100644 index 512e24b..0000000 --- a/src/js/lib/theme.js +++ /dev/null @@ -1,56 +0,0 @@ -export const themes = { - ambiance: require('../../sass/themes/ambiance.scss'), - chaos: require('../../sass/themes/chaos.scss'), - clouds: require('../../sass/themes/clouds.scss'), - cloudsMidnight: require('../../sass/themes/clouds-midnight.scss'), - chrome: require('../../sass/themes/chrome.scss'), - cobalt: require('../../sass/themes/cobalt.scss'), - crimsonEditor: require('../../sass/themes/crimson-editor.scss'), - dawn: require('../../sass/themes/dawn.scss'), - dreamweaver: require('../../sass/themes/dreamweaver.scss'), - eclipse: require('../../sass/themes/eclipse.scss'), - github: require('../../sass/themes/github.scss'), - gob: require('../../sass/themes/gob.scss'), - gruvbox: require('../../sass/themes/gruvbox.scss'), - idleFingers: require('../../sass/themes/idle-fingers.scss'), - iplastic: require('../../sass/themes/iplastic.scss'), - katzenMilch: require('../../sass/themes/katzen-milch.scss'), - krTheme: require('../../sass/themes/kr-theme.scss'), - kurior: require('../../sass/themes/kurior.scss'), - merbivore: require('../../sass/themes/merbivore.scss'), - merbivoreSoft: require('../../sass/themes/merbivore-soft.scss'), - monoIndustrial: require('../../sass/themes/mono-industrial.scss'), - monokai: require('../../sass/themes/monokai.scss'), - pastelOnDark: require('../../sass/themes/pastel-on-dark.scss'), - solarizedDark: require('../../sass/themes/solarized-dark.scss'), - solarizedLight: require('../../sass/themes/solarized-light.scss'), - sqlServer: require('../../sass/themes/sql-server.scss'), - terminal: require('../../sass/themes/terminal.scss'), - textmate: require('../../sass/themes/textmate.scss'), - tomorrow: require('../../sass/themes/tomorrow.scss'), - tomorrowNight: require('../../sass/themes/tomorrow-night.scss'), - tomorrowNightBlue: require('../../sass/themes/tomorrow-night-blue.scss'), - tomorrowNightBright: require('../../sass/themes/tomorrow-night-bright.scss'), - tomorrowNightEighties: require('../../sass/themes/tomorrow-night-eighties.scss'), - twilight: require('../../sass/themes/twilight.scss'), - vibrantInk: require('../../sass/themes/vibrant-ink.scss'), - xcode: require('../../sass/themes/xcode.scss'), - default: 'dawn' -}; - -const transition = require('../../sass/transition.scss'); -let themeElement; - -export function switchToTheme(theme) { - const element = getThemeElement(); - element.innerText = element.innerText ? theme + transition : theme; -} - -function getThemeElement() { - if (!themeElement) { - themeElement = document.createElement('style'); - document.head.appendChild(themeElement); - } - - return themeElement; -} diff --git a/src/js/lib/themes.js b/src/js/lib/themes.js new file mode 100644 index 0000000..06f2770 --- /dev/null +++ b/src/js/lib/themes.js @@ -0,0 +1,183 @@ +export const themes = { + default: 'dawn', + chrome: { + name: 'Chrome', + type: 'Light', + styles: require('../../sass/themes/chrome.scss') + }, + clouds: { + name: 'Clouds', + type: 'Light', + styles: require('../../sass/themes/clouds.scss') + }, + crimsonEditor: { + name: 'Crimson Editor', + type: 'Light', + styles: require('../../sass/themes/crimson-editor.scss') + }, + dawn: { + name: 'Dawn', + type: 'Light', + styles: require('../../sass/themes/dawn.scss') + }, + dreamweaver: { + name: 'Dreamweaver', + type: 'Light', + styles: require('../../sass/themes/dreamweaver.scss') + }, + eclipse: { + name: 'Eclipse', + type: 'Light', + styles: require('../../sass/themes/eclipse.scss') + }, + github: { + name: 'GitHub', + type: 'Light', + styles: require('../../sass/themes/github.scss') + }, + iplastic: { + name: 'iPlastic', + type: 'Light', + styles: require('../../sass/themes/iplastic.scss') + }, + katzenMilch: { + name: 'KatzenMilch', + type: 'Light', + styles: require('../../sass/themes/katzen-milch.scss') + }, + kurior: { + name: 'Kurior', + type: 'Light', + styles: require('../../sass/themes/kurior.scss') + }, + solarizedLight: { + name: 'Solarized Light', + type: 'Light', + styles: require('../../sass/themes/solarized-light.scss') + }, + sqlServer: { + name: 'SQL Server', + type: 'Light', + styles: require('../../sass/themes/sql-server.scss') + }, + textmate: { + name: 'TextMate', + type: 'Light', + styles: require('../../sass/themes/textmate.scss') + }, + tomorrow: { + name: 'Tomorrow', + type: 'Light', + styles: require('../../sass/themes/tomorrow.scss') + }, + xcode: { + name: 'XCode', + type: 'Light', + styles: require('../../sass/themes/xcode.scss') + }, + ambiance: { + name: 'Ambiance', + type: 'Dark', + styles: require('../../sass/themes/ambiance.scss') + }, + chaos: { + name: 'Chaos', + type: 'Dark', + styles: require('../../sass/themes/chaos.scss') + }, + cloudsMidnight: { + name: 'Clouds Midnight', + type: 'Dark', + styles: require('../../sass/themes/clouds-midnight.scss') + }, + cobalt: { + name: 'Cobalt', + type: 'Dark', + styles: require('../../sass/themes/cobalt.scss') + }, + gob: { + name: 'Gob', + type: 'Dark', + styles: require('../../sass/themes/gob.scss') + }, + gruvbox: { + name: 'Gruvbox', + type: 'Dark', + styles: require('../../sass/themes/gruvbox.scss') + }, + idleFingers: { + name: 'idle Fingers', + type: 'Dark', + styles: require('../../sass/themes/idle-fingers.scss') + }, + krTheme: { + name: 'krTheme', + type: 'Dark', + styles: require('../../sass/themes/kr-theme.scss') + }, + merbivore: { + name: 'Merbivore', + type: 'Dark', + styles: require('../../sass/themes/merbivore.scss') + }, + merbivoreSoft: { + name: 'Merbivore Soft', + type: 'Dark', + styles: require('../../sass/themes/merbivore-soft.scss') + }, + monoIndustrial: { + name: 'Mono Industrial', + type: 'Dark', + styles: require('../../sass/themes/mono-industrial.scss') + }, + monokai: { + name: 'Monokai', + type: 'Dark', + styles: require('../../sass/themes/monokai.scss') + }, + pastelOnDark: { + name: 'Pastel on dark', + type: 'Dark', + styles: require('../../sass/themes/pastel-on-dark.scss') + }, + solarizedDark: { + name: 'Solarized Dark', + type: 'Dark', + styles: require('../../sass/themes/solarized-dark.scss') + }, + terminal: { + name: 'Terminal', + type: 'Dark', + styles: require('../../sass/themes/terminal.scss') + }, + tomorrowNight: { + name: 'Tomorrow Night', + type: 'Dark', + styles: require('../../sass/themes/tomorrow-night.scss') + }, + tomorrowNightBlue: { + name: 'Tomorrow Night Blue', + type: 'Dark', + styles: require('../../sass/themes/tomorrow-night-blue.scss') + }, + tomorrowNightBright: { + name: 'Tomorrow Night Blue', + type: 'Dark', + styles: require('../../sass/themes/tomorrow-night-bright.scss') + }, + tomorrowNightEighties: { + name: 'Tomorrow Night ’80s', + type: 'Dark', + styles: require('../../sass/themes/tomorrow-night-eighties.scss') + }, + twilight: { + name: 'Twilight', + type: 'Dark', + styles: require('../../sass/themes/twilight.scss') + }, + vibrantInk: { + name: 'Vibrant Ink', + type: 'Dark', + styles: require('../../sass/themes/vibrant-ink.scss') + } +}; diff --git a/src/manifest.json b/src/manifest.json index 2ca9897..8a7313f 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -1,6 +1,6 @@ { "name": "JSON Formatter", - "version": "0.8.1", + "version": "0.8.2", "manifest_version": 2, "description": "Makes JSON easy to read. Open source.", "homepage_url": "https://github.com/nikrolls/json-formatter", diff --git a/src/sass/themes/chaos.scss b/src/sass/themes/chaos.scss index 1884ae9..ccc2ac9 100644 --- a/src/sass/themes/chaos.scss +++ b/src/sass/themes/chaos.scss @@ -1,6 +1,8 @@ +$foreground: #e6e1dc; + body { background-color: #161616; - color: #e6e1dc; + color: $foreground; } ::selection { @@ -23,6 +25,10 @@ body { color: #fdc251; } +.brace { + color: $foreground; +} + .collapsed:after { font-style: italic; color: #555; diff --git a/src/sass/themes/chrome.scss b/src/sass/themes/chrome.scss index 0761874..a95ecbe 100644 --- a/src/sass/themes/chrome.scss +++ b/src/sass/themes/chrome.scss @@ -1,6 +1,8 @@ +$foreground: black; + body { background-color: white; - color: black; + color: $foreground; } ::selection { @@ -23,6 +25,10 @@ body { color: #6d79de; } +.brace { + color: $foreground; +} + .collapsed:after { color: #236e24; } diff --git a/src/sass/themes/clouds-midnight.scss b/src/sass/themes/clouds-midnight.scss index 6612f21..28b9f49 100644 --- a/src/sass/themes/clouds-midnight.scss +++ b/src/sass/themes/clouds-midnight.scss @@ -1,12 +1,18 @@ +$foreground: #929292; + body { background-color: #191919; - color: #929292; + color: $foreground; } ::selection { background-color: black; } +.key { + color: $foreground; +} + .number { color: #46a609; } @@ -19,6 +25,10 @@ body { color: #39946a; } +.brace { + color: $foreground; +} + .collapsed:after { color: #3c403b; } diff --git a/src/sass/themes/clouds.scss b/src/sass/themes/clouds.scss index a18d32a..8c40628 100644 --- a/src/sass/themes/clouds.scss +++ b/src/sass/themes/clouds.scss @@ -1,12 +1,18 @@ +$foreground: black; + body { background-color: white; - color: black; + color: $foreground; } ::selection { background-color: #bdd5fc; } +.key { + color: $foreground; +} + .number { color: #46a609; } @@ -19,6 +25,10 @@ body { color: #39946a; } +.brace { + color: $foreground; +} + .collapsed:after { color: #bcc8ba; } diff --git a/src/sass/themes/cobalt.scss b/src/sass/themes/cobalt.scss index 8db7ffb..1ea3801 100644 --- a/src/sass/themes/cobalt.scss +++ b/src/sass/themes/cobalt.scss @@ -1,6 +1,8 @@ +$foreground: white; + body { background-color: #002240; - color: white; + color: $foreground; } ::selection { @@ -19,6 +21,10 @@ body { color: #3ad900; } +.brace { + color: $foreground; +} + .collapsed:after { font-style: italic; color: #0088ff; diff --git a/src/sass/themes/crimson-editor.scss b/src/sass/themes/crimson-editor.scss index e3ebcc6..2e3dbbf 100644 --- a/src/sass/themes/crimson-editor.scss +++ b/src/sass/themes/crimson-editor.scss @@ -1,6 +1,8 @@ +$foreground: #404040; + body { background-color: white; - color: #404040; + color: $foreground; } ::selection { @@ -23,6 +25,10 @@ body { color: #ff9c00; } +.brace { + color: $foreground; +} + .collapsed:after { color: #4c886b; } diff --git a/src/sass/themes/dawn.scss b/src/sass/themes/dawn.scss index 9de1d85..e13da2e 100644 --- a/src/sass/themes/dawn.scss +++ b/src/sass/themes/dawn.scss @@ -1,6 +1,8 @@ +$foreground: #080808; + body { background-color: #f9f9f9; - color: #080808; + color: $foreground; } ::selection { @@ -19,6 +21,10 @@ body { color: #0b6125; } +.brace { + color: $foreground; +} + .collapsed:after { font-style: italic; color: #5a525f diff --git a/src/sass/themes/dreamweaver.scss b/src/sass/themes/dreamweaver.scss index a0ce9db..7815952 100644 --- a/src/sass/themes/dreamweaver.scss +++ b/src/sass/themes/dreamweaver.scss @@ -1,6 +1,8 @@ +$foreground: black; + body { background-color: #fff; - color: black; + color: $foreground; } ::selection { @@ -23,6 +25,10 @@ body { color: #585cf6; } +.brace { + color: $foreground; +} + .collapsed:after { color: #4c886b; } diff --git a/src/sass/themes/eclipse.scss b/src/sass/themes/eclipse.scss index cca1803..8fa3ed7 100644 --- a/src/sass/themes/eclipse.scss +++ b/src/sass/themes/eclipse.scss @@ -1,6 +1,8 @@ +$foreground: black; + body { background-color: #fff; - color: black; + color: $foreground; } ::selection { @@ -23,6 +25,10 @@ body { color: #5848f6; } +.brace { + color: $foreground; +} + .collapsed:after { color: #719682; } diff --git a/src/sass/themes/github.scss b/src/sass/themes/github.scss index 946dba4..7ffb5e8 100644 --- a/src/sass/themes/github.scss +++ b/src/sass/themes/github.scss @@ -1,6 +1,8 @@ +$foreground: black; + body { background-color: white; - color: black; + color: $foreground; } ::selection { @@ -16,11 +18,13 @@ body { } .bool, .null { + color: $foreground; font-weight: bold; } .brace { font-weight: bold; + color: $foreground; } .collapsed:after { diff --git a/src/sass/themes/gob.scss b/src/sass/themes/gob.scss index badb4ce..f64e419 100644 --- a/src/sass/themes/gob.scss +++ b/src/sass/themes/gob.scss @@ -1,6 +1,8 @@ +$foreground: #0f0; + body { background-color: #0b0b0b; - color: #0f0 + color: $foreground; } ::selection { @@ -12,11 +14,15 @@ body { } .string { - color: #10f060 + color: #10f060; } .bool, .null { - color: #10f0a0 + color: #10f0a0; +} + +.brace { + color: $foreground; } .collapsed:after { diff --git a/src/sass/themes/gruvbox.scss b/src/sass/themes/gruvbox.scss index d36a868..fb4d472 100644 --- a/src/sass/themes/gruvbox.scss +++ b/src/sass/themes/gruvbox.scss @@ -1,6 +1,8 @@ +$foreground: #ebdab4; + body { background-color: #1d2021; - color: #ebdab4; + color: $foreground; } ::selection { @@ -19,6 +21,10 @@ body { color: #b8ba37; } +.brace { + color: $foreground; +} + .collapsed:after { font-style: italic; color: #928375; diff --git a/src/sass/themes/idle-fingers.scss b/src/sass/themes/idle-fingers.scss index fca6f16..92ed7e8 100644 --- a/src/sass/themes/idle-fingers.scss +++ b/src/sass/themes/idle-fingers.scss @@ -1,12 +1,18 @@ +$foreground: white; + body { background-color: #323232; - color: #fff + color: $foreground; } ::selection { background-color: transparentize(#5a647e, 0.12); } +.key { + color: $foreground; +} + .number, .bool, .null { color: #6c99bb; } @@ -15,6 +21,10 @@ body { color: #a5c261; } +.brace { + color: $foreground; +} + .collapsed:after { font-style: italic; color: #bc9458; diff --git a/src/sass/themes/iplastic.scss b/src/sass/themes/iplastic.scss index 9648eba..3b30674 100644 --- a/src/sass/themes/iplastic.scss +++ b/src/sass/themes/iplastic.scss @@ -1,6 +1,8 @@ +$foreground: #333; + body { background-color: #eee; - color: #333; + color: $foreground; } ::selection { @@ -21,6 +23,10 @@ body { color: #a55f03; } +.brace { + color: $foreground; +} + .collapsed:after { color: #777; font-style: italic; diff --git a/src/sass/themes/katzen-milch.scss b/src/sass/themes/katzen-milch.scss index 8c84f30..3276fe6 100644 --- a/src/sass/themes/katzen-milch.scss +++ b/src/sass/themes/katzen-milch.scss @@ -1,6 +1,8 @@ +$foreground: #0f0009; + body { background-color: #f3f2f3; - color: #0f0009 + color: $foreground; } ::selection { @@ -27,6 +29,10 @@ body { background-color: transparentize(#bdbe82, 0.941); } +.brace { + color: $foreground; +} + .collapsed:after { font-style: italic; color: rgba(64, 79, 80, 0.67); diff --git a/src/sass/themes/kr-theme.scss b/src/sass/themes/kr-theme.scss index b891b4f..b779f06 100644 --- a/src/sass/themes/kr-theme.scss +++ b/src/sass/themes/kr-theme.scss @@ -1,6 +1,8 @@ +$foreground: #fcffe0; + body { background-color: #0b0a09; - color: #fcffe0; + color: $foreground; } ::selection { @@ -19,6 +21,10 @@ body { color: transparentize(#a4a1b5, 0.2); } +.brace { + color: $foreground; +} + .collapsed:after { font-style: italic; color: #706d5b; diff --git a/src/sass/themes/kurior.scss b/src/sass/themes/kurior.scss index d7c04d8..c9c1b0b 100644 --- a/src/sass/themes/kurior.scss +++ b/src/sass/themes/kurior.scss @@ -1,6 +1,8 @@ +$foreground: #363636; + body { background-color: #e8e9e8; - color: #363636; + color: $foreground; } ::selection { @@ -23,6 +25,10 @@ body { color: #cd6839; } +.brace { + color: $foreground; +} + .collapsed:after { color: transparentize(#949494, 0.09); background-color: transparentize(#dcdcdc, 0.44); diff --git a/src/sass/themes/merbivore-soft.scss b/src/sass/themes/merbivore-soft.scss index bdbc69b..3d5e24c 100644 --- a/src/sass/themes/merbivore-soft.scss +++ b/src/sass/themes/merbivore-soft.scss @@ -1,12 +1,18 @@ +$foreground: #e6e1dc; + body { background-color: #1c1c1c; - color: #e6e1dc; + color: $foreground; } ::selection { background-color: #494949; } +.key { + color: $foreground; +} + .number { color: #7fc578; } @@ -19,6 +25,10 @@ body { color: #e1c582; } +.brace { + color: $foreground; +} + .collapsed:after { font-style: italic; color: #ac4bb8; diff --git a/src/sass/themes/merbivore.scss b/src/sass/themes/merbivore.scss index 9ea6063..716088f 100644 --- a/src/sass/themes/merbivore.scss +++ b/src/sass/themes/merbivore.scss @@ -1,12 +1,18 @@ +$foreground: #e6e1dc; + body { background-color: #161616; - color: #e6e1dc; + color: $foreground; } ::selection { background-color: #454545; } +.key { + color: $foreground; +} + .number { color: #58c554; } @@ -19,6 +25,10 @@ body { color: #fdc251; } +.brace { + color: $foreground; +} + .collapsed:after { font-style: italic; color: #ad2ea4; diff --git a/src/sass/themes/mono-industrial.scss b/src/sass/themes/mono-industrial.scss index 55ce90f..5ac6d83 100644 --- a/src/sass/themes/mono-industrial.scss +++ b/src/sass/themes/mono-industrial.scss @@ -1,6 +1,8 @@ +$foreground: white; + body { background-color: #222c28; - color: #fff; + color: $foreground; } ::selection { @@ -24,6 +26,10 @@ body { color: #648bd2; } +.brace { + color: $foreground; +} + .collapsed:after { color: #666c68; background-color: #151c19; diff --git a/src/sass/themes/monokai.scss b/src/sass/themes/monokai.scss index e375705..197ab65 100644 --- a/src/sass/themes/monokai.scss +++ b/src/sass/themes/monokai.scss @@ -1,6 +1,8 @@ +$foreground: #f8f8f2; + body { background-color: #272822; - color: #f8f8f2; + color: $foreground; } ::selection { @@ -19,6 +21,10 @@ body { color: #e6db74; } +.brace { + color: $foreground; +} + .collapsed:after { color: #75715e; } diff --git a/src/sass/themes/pastel-on-dark.scss b/src/sass/themes/pastel-on-dark.scss index 55d4009..62c14c5 100644 --- a/src/sass/themes/pastel-on-dark.scss +++ b/src/sass/themes/pastel-on-dark.scss @@ -1,6 +1,8 @@ +$foreground: #8f938f; + body { background-color: #2c2828; - color: #8f938f; + color: $foreground; } ::selection { @@ -23,6 +25,10 @@ body { color: #de8e30; } +.brace { + color: $foreground; +} + .collapsed:after { color: #a6c6ff; } diff --git a/src/sass/themes/solarized-dark.scss b/src/sass/themes/solarized-dark.scss index 9a0a0dc..6a40852 100644 --- a/src/sass/themes/solarized-dark.scss +++ b/src/sass/themes/solarized-dark.scss @@ -1,6 +1,8 @@ +$foreground: #93a1a1; + body { background-color: #002b36; - color: #93a1a1; + color: $foreground; } ::selection { @@ -23,6 +25,10 @@ body { color: #b58900; } +.brace { + color: $foreground; +} + .collapsed:after { font-style: italic; color: #657b83; diff --git a/src/sass/themes/solarized-light.scss b/src/sass/themes/solarized-light.scss index 07b225d..eee94b4 100644 --- a/src/sass/themes/solarized-light.scss +++ b/src/sass/themes/solarized-light.scss @@ -1,6 +1,8 @@ +$foreground: #586e75; + body { background-color: #fdf6e3; - color: #586e75; + color: $foreground; } ::selection { @@ -23,6 +25,10 @@ body { color: #b58900 } +.brace { + color: $foreground; +} + .collapsed:after { color: #93a1a1; } diff --git a/src/sass/themes/terminal.scss b/src/sass/themes/terminal.scss index e9e2e39..5c41364 100644 --- a/src/sass/themes/terminal.scss +++ b/src/sass/themes/terminal.scss @@ -1,6 +1,8 @@ +$foreground: #dedede; + body { background-color: black; - color: #dedede; + color: $foreground; } ::selection { @@ -19,6 +21,10 @@ body { color: #b9ca4a; } +.brace { + color: $foreground; +} + .collapsed:after { color: orangered; } diff --git a/src/sass/themes/textmate.scss b/src/sass/themes/textmate.scss index 57c504a..1c5e059 100644 --- a/src/sass/themes/textmate.scss +++ b/src/sass/themes/textmate.scss @@ -1,6 +1,8 @@ +$foreground: black; + body { background-color: #fff; - color: black; + color: $foreground; } ::selection { @@ -23,6 +25,10 @@ body { color: #585cf6; } +.brace { + color: $foreground; +} + .collapsed:after { color: #4c886b; } diff --git a/src/sass/themes/tomorrow-night-blue.scss b/src/sass/themes/tomorrow-night-blue.scss index 12f03ba..f838256 100644 --- a/src/sass/themes/tomorrow-night-blue.scss +++ b/src/sass/themes/tomorrow-night-blue.scss @@ -1,6 +1,8 @@ +$foreground: white; + body { background-color: #002451; - color: #fff; + color: $foreground; } ::selection { @@ -19,6 +21,10 @@ body { color: #d1f1a9; } +.brace { + color: $foreground; +} + .collapsed:after { color: #7285b7; } diff --git a/src/sass/themes/tomorrow-night-bright.scss b/src/sass/themes/tomorrow-night-bright.scss index dc9fbcb..f9c2726 100644 --- a/src/sass/themes/tomorrow-night-bright.scss +++ b/src/sass/themes/tomorrow-night-bright.scss @@ -1,6 +1,8 @@ +$foreground: #dedede; + body { background-color: #000; - color: #dedede; + color: $foreground; } ::selection { @@ -19,6 +21,10 @@ body { color: #b9ca4a; } +.brace { + color: $foreground; +} + .collapsed:after { color: #969896; } diff --git a/src/sass/themes/tomorrow-night-eighties.scss b/src/sass/themes/tomorrow-night-eighties.scss index 8a91eb3..11388af 100644 --- a/src/sass/themes/tomorrow-night-eighties.scss +++ b/src/sass/themes/tomorrow-night-eighties.scss @@ -1,6 +1,8 @@ +$foreground: #ccc; + body { background-color: #2d2d2d; - color: #ccc; + color: $foreground; } ::selection { @@ -19,6 +21,10 @@ body { color: #9c9; } +.brace { + color: $foreground; +} + .collapsed:after { color: #999; } diff --git a/src/sass/themes/tomorrow-night.scss b/src/sass/themes/tomorrow-night.scss index 97eafcb..4d00aa7 100644 --- a/src/sass/themes/tomorrow-night.scss +++ b/src/sass/themes/tomorrow-night.scss @@ -1,6 +1,8 @@ +$foreground: #c5c8c6; + body { background-color: #1d1f21; - color: #c5c8c6; + color: $foreground; } ::selection { @@ -19,6 +21,10 @@ body { color: #b5bd68; } +.brace { + color: $foreground; +} + .collapsed:after { color: #969896; } diff --git a/src/sass/themes/tomorrow.scss b/src/sass/themes/tomorrow.scss index 6006e60..8e06788 100644 --- a/src/sass/themes/tomorrow.scss +++ b/src/sass/themes/tomorrow.scss @@ -1,6 +1,8 @@ +$foreground: #4d4d4c; + body { background-color: #fff; - color: #4d4d4c; + color: $foreground; } ::selection { @@ -19,6 +21,10 @@ body { color: #718c00; } +.brace { + color: $foreground; +} + .collapsed:after { color: #8e908c; } diff --git a/src/sass/themes/twilight.scss b/src/sass/themes/twilight.scss index ea8fcc6..c01954b 100644 --- a/src/sass/themes/twilight.scss +++ b/src/sass/themes/twilight.scss @@ -1,6 +1,8 @@ +$foreground: #f8f8f8; + body { background-color: #141414; - color: #f8f8f8; + color: $foreground; } ::selection { @@ -19,6 +21,10 @@ body { color: #8f9d6a; } +.brace { + color: $foreground; +} + .collapsed:after { font-style: italic; color: #5f5a60; diff --git a/src/sass/themes/vibrant-ink.scss b/src/sass/themes/vibrant-ink.scss index 2e9ab6e..879cb92 100644 --- a/src/sass/themes/vibrant-ink.scss +++ b/src/sass/themes/vibrant-ink.scss @@ -1,6 +1,8 @@ +$foreground: white; + body { background-color: #0f0f0f; - color: #fff; + color: $foreground; } ::selection { @@ -23,6 +25,10 @@ body { color: #399; } +.brace { + color: $foreground; +} + .collapsed:after { color: #93c; } diff --git a/src/sass/themes/xcode.scss b/src/sass/themes/xcode.scss index 2ecd584..549abce 100644 --- a/src/sass/themes/xcode.scss +++ b/src/sass/themes/xcode.scss @@ -1,6 +1,8 @@ +$foreground: black; + body { - background-color: #fff; - color: #000; + background-color: white; + color: $foreground; } ::selection { @@ -19,6 +21,10 @@ body { color: #c800a4; } +.brace { + color: $foreground; +} + .collapsed:after { color: #008e00; } diff --git a/src/sass/transition.scss b/src/sass/transition.scss index 18f62c9..d20e30d 100644 --- a/src/sass/transition.scss +++ b/src/sass/transition.scss @@ -1,5 +1,42 @@ -* { - transition-property: color, background-color; +@mixin transition { + transition-property: background-color, color; transition-duration: 500ms; + transition-delay: 0s; transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); } + +body { + @include transition; +} + +::selection { + @include transition; +} + +.key { + @include transition; +} + +.number { + @include transition; +} + +.string { + @include transition; +} + +.bool { + @include transition; +} + +.null { + @include transition; +} + +.brace { + @include transition; +} + +.collapsed:after { + @include transition; +}