Apply editor theme to markdown snippets (#873)

* Apply editor theme to markdown snippets

* More tailwind
This commit is contained in:
Jonatan Kłosko 2022-01-16 13:50:44 +01:00 committed by GitHub
parent 751ca8296b
commit 357985eef4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 87 additions and 51 deletions

View file

@ -122,10 +122,8 @@
} }
.markdown pre > code { .markdown pre > code {
@apply p-4 rounded-lg text-sm align-middle font-mono flex-1 overflow-auto;
/* Match the editor colors */ /* Match the editor colors */
background-color: #282c34; @apply p-4 rounded-lg align-middle flex-1 overflow-auto bg-editor text-editor font-editor;
color: #c4cad6;
} }
.markdown kbd { .markdown kbd {

View file

@ -5,8 +5,12 @@
background-color: #282c34; background-color: #282c34;
} }
body[data-editor-theme="highContrast"] .bg-editor {
background-color: #060708;
}
.text-editor { .text-editor {
color: #abb2bf; color: #c4cad6;
} }
.font-editor { .font-editor {

View file

@ -29,6 +29,7 @@ import KeyboardControl from "./keyboard_control";
import morphdomCallbacks from "./morphdom_callbacks"; import morphdomCallbacks from "./morphdom_callbacks";
import JSOutput from "./js_output"; import JSOutput from "./js_output";
import { loadUserData } from "./lib/user"; import { loadUserData } from "./lib/user";
import { settingsStore } from "./lib/settings";
const hooks = { const hooks = {
Headline, Headline,
@ -109,3 +110,9 @@ window.addEventListener("contextmenu", (event) => {
target.dispatchEvent(new Event("click", { bubbles: true })); target.dispatchEvent(new Event("click", { bubbles: true }));
} }
}); });
// Global configuration
settingsStore.getAndSubscribe((settings) => {
document.body.setAttribute("data-editor-theme", settings.editor_theme);
});

View file

@ -5,7 +5,6 @@ import { globalPubSub } from "../lib/pub_sub";
import { md5Base64, smoothlyScrollToElement } from "../lib/utils"; import { md5Base64, smoothlyScrollToElement } from "../lib/utils";
import scrollIntoView from "scroll-into-view-if-needed"; import scrollIntoView from "scroll-into-view-if-needed";
import { loadLocalSettings } from "../lib/settings"; import { loadLocalSettings } from "../lib/settings";
import { THEME_BACKGROUND_COLOR } from "./live_editor/theme";
/** /**
* A hook managing a single cell. * A hook managing a single cell.
@ -43,10 +42,6 @@ const Cell = {
// Create an empty container for the editor to be mounted in. // Create an empty container for the editor to be mounted in.
const editorElement = document.createElement("div"); const editorElement = document.createElement("div");
editorContainer.appendChild(editorElement); editorContainer.appendChild(editorElement);
// Adjust the background color based on local settings
const settings = loadLocalSettings();
editorContainer.style.backgroundColor =
THEME_BACKGROUND_COLOR[settings.editor_theme];
// Setup the editor instance. // Setup the editor instance.
this.state.liveEditor = new LiveEditor( this.state.liveEditor = new LiveEditor(
this, this,

View file

@ -4,7 +4,7 @@ import MonacoEditorAdapter from "./live_editor/monaco_editor_adapter";
import HookServerAdapter from "./live_editor/hook_server_adapter"; import HookServerAdapter from "./live_editor/hook_server_adapter";
import RemoteUser from "./live_editor/remote_user"; import RemoteUser from "./live_editor/remote_user";
import { replacedSuffixLength } from "../lib/text_utils"; import { replacedSuffixLength } from "../lib/text_utils";
import { loadLocalSettings } from "../lib/settings"; import { settingsStore } from "../lib/settings";
/** /**
* Mounts cell source editor with real-time collaboration mechanism. * Mounts cell source editor with real-time collaboration mechanism.
@ -141,7 +141,7 @@ class LiveEditor {
} }
__mountEditor() { __mountEditor() {
const settings = loadLocalSettings(); const settings = settingsStore.get();
this.editor = monaco.editor.create(this.container, { this.editor = monaco.editor.create(this.container, {
language: this.type, language: this.type,
@ -219,7 +219,7 @@ class LiveEditor {
* Defines cell-specific providers for various editor features. * Defines cell-specific providers for various editor features.
*/ */
__setupIntellisense() { __setupIntellisense() {
const settings = loadLocalSettings(); const settings = settingsStore.get();
this.handlerByRef = {}; this.handlerByRef = {};

View file

@ -13,7 +13,7 @@ const colors = {
peach: "#d19a66", peach: "#d19a66",
}; };
const THEME_BACKGROUND_COLOR = { default: "#282c34", highContrast: "#060708" }; const background = { default: "#282c34", highContrast: "#060708" };
const theme = { const theme = {
base: "vs-dark", base: "vs-dark",
@ -57,7 +57,7 @@ const theme = {
], ],
colors: { colors: {
"editor.background": THEME_BACKGROUND_COLOR.default, "editor.background": background.default,
"editor.foreground": colors.default, "editor.foreground": colors.default,
"editorLineNumber.foreground": "#636d83", "editorLineNumber.foreground": "#636d83",
"editorCursor.foreground": "#636d83", "editorCursor.foreground": "#636d83",
@ -77,8 +77,8 @@ const highContrast = {
...theme, ...theme,
colors: { colors: {
...theme.colors, ...theme.colors,
"editor.background": THEME_BACKGROUND_COLOR.highContrast, "editor.background": background.highContrast,
}, },
}; };
export { theme, highContrast, THEME_BACKGROUND_COLOR }; export { theme, highContrast };

View file

@ -1,9 +1,4 @@
import { import { settingsStore, EDITOR_FONT_SIZE, EDITOR_THEME } from "../lib/settings";
loadLocalSettings,
storeLocalSettings,
EDITOR_FONT_SIZE,
EDITOR_THEME,
} from "../lib/settings";
/** /**
* A hook for the editor settings. * A hook for the editor settings.
@ -14,7 +9,7 @@ import {
*/ */
const EditorSettings = { const EditorSettings = {
mounted() { mounted() {
const settings = loadLocalSettings(); const settings = settingsStore.get();
const editorAutoCompletionCheckbox = this.el.querySelector( const editorAutoCompletionCheckbox = this.el.querySelector(
`[name="editor_auto_completion"][value="true"]` `[name="editor_auto_completion"][value="true"]`
@ -37,15 +32,15 @@ const EditorSettings = {
settings.editor_theme === EDITOR_THEME.highContrast ? true : false; settings.editor_theme === EDITOR_THEME.highContrast ? true : false;
editorAutoCompletionCheckbox.addEventListener("change", (event) => { editorAutoCompletionCheckbox.addEventListener("change", (event) => {
storeLocalSettings({ editor_auto_completion: event.target.checked }); settingsStore.update({ editor_auto_completion: event.target.checked });
}); });
editorAutoSignatureCheckbox.addEventListener("change", (event) => { editorAutoSignatureCheckbox.addEventListener("change", (event) => {
storeLocalSettings({ editor_auto_signature: event.target.checked }); settingsStore.update({ editor_auto_signature: event.target.checked });
}); });
editorFontSizeCheckbox.addEventListener("change", (event) => { editorFontSizeCheckbox.addEventListener("change", (event) => {
storeLocalSettings({ settingsStore.update({
editor_font_size: event.target.checked editor_font_size: event.target.checked
? EDITOR_FONT_SIZE.large ? EDITOR_FONT_SIZE.large
: EDITOR_FONT_SIZE.normal, : EDITOR_FONT_SIZE.normal,
@ -53,7 +48,7 @@ const EditorSettings = {
}); });
editorHighContrastCheckbox.addEventListener("change", (event) => { editorHighContrastCheckbox.addEventListener("change", (event) => {
storeLocalSettings({ settingsStore.update({
editor_theme: event.target.checked editor_theme: event.target.checked
? EDITOR_THEME.highContrast ? EDITOR_THEME.highContrast
: EDITOR_THEME.default, : EDITOR_THEME.default,

View file

@ -18,32 +18,69 @@ const DEFAULT_SETTINGS = {
}; };
/** /**
* Stores the given settings in local storage. * Stores local configuration and persists it across browser sessions.
*/
class SettingsStore {
constructor() {
this._subscribers = [];
this._settings = DEFAULT_SETTINGS;
this._loadSettings();
}
/**
* Returns the current settings.
*/
get() {
return this._settings;
}
/**
* Stores new settings.
* *
* The given attributes are merged into the current settings. * The given attributes are merged into the current settings.
*/ */
export function storeLocalSettings(settings) { update(newSettings) {
const prevSettings = loadLocalSettings(); const prevSettings = this._settings;
const newSettings = { ...prevSettings, ...settings }; this._settings = { ...this._settings, ...newSettings };
this._subscribers.forEach((callback) =>
callback(this._settings, prevSettings)
);
this._storeSettings();
}
/**
* Registers to settings changes.
*
* The given function is called immediately with the current
* settings and then on every change.
*/
getAndSubscribe(callback) {
this._subscribers.push(callback);
callback(this._settings);
}
_loadSettings() {
try { try {
const json = JSON.stringify(newSettings); const json = localStorage.getItem(SETTINGS_KEY);
if (json) {
const settings = JSON.parse(json);
this._settings = { ...this._settings, ...settings };
}
} catch (error) {
console.error(`Failed to load local settings, reason: ${error.message}`);
}
}
_storeSettings() {
try {
const json = JSON.stringify(this._settings);
localStorage.setItem(SETTINGS_KEY, json); localStorage.setItem(SETTINGS_KEY, json);
} catch (error) { } catch (error) {
console.error(`Failed to store local settings, reason: ${error.message}`); console.error(`Failed to store local settings, reason: ${error.message}`);
} }
} }
}
/** export const settingsStore = new SettingsStore();
* Loads settings from local storage.
*/
export function loadLocalSettings() {
try {
const json = localStorage.getItem(SETTINGS_KEY);
const settings = json ? JSON.parse(json) : {};
return { ...DEFAULT_SETTINGS, ...settings };
} catch (error) {
console.error(`Failed to load local settings, reason: ${error.message}`);
return DEFAULT_SETTINGS;
}
}