mirror of
https://github.com/eliasstepanik/strudel.git
synced 2026-01-11 21:58:37 +00:00
261 lines
8.1 KiB
JavaScript
261 lines
8.1 KiB
JavaScript
import strudelTheme, { settings as strudelThemeSettings } from './themes/strudel-theme.mjs';
|
|
import bluescreen, { settings as bluescreenSettings } from './themes/bluescreen.mjs';
|
|
import blackscreen, { settings as blackscreenSettings } from './themes/blackscreen.mjs';
|
|
import whitescreen, { settings as whitescreenSettings } from './themes/whitescreen.mjs';
|
|
import teletext, { settings as teletextSettings } from './themes/teletext.mjs';
|
|
import algoboy, { settings as algoboySettings } from './themes/algoboy.mjs';
|
|
import terminal, { settings as terminalSettings } from './themes/terminal.mjs';
|
|
import abcdef, { settings as abcdefSettings } from './themes/abcdef.mjs';
|
|
import androidstudio, { settings as androidstudioSettings } from './themes/androidstudio.mjs';
|
|
import atomone, { settings as atomOneSettings } from './themes/atomone.mjs';
|
|
import aura, { settings as auraSettings } from './themes/aura.mjs';
|
|
import bespin, { settings as bespinSettings } from './themes/bespin.mjs';
|
|
import darcula, { settings as darculaSettings } from './themes/darcula.mjs';
|
|
import dracula, { settings as draculaSettings } from './themes/dracula.mjs';
|
|
import duotoneDark, { settings as duotoneDarkSettings } from './themes/duotoneDark.mjs';
|
|
import duotoneLight, { settings as duotoneLightSettings } from './themes/duotoneLight.mjs';
|
|
import eclipse, { settings as eclipseSettings } from './themes/eclipse.mjs';
|
|
import githubDark, { settings as githubDarkSettings } from './themes/githubDark.mjs';
|
|
import githubLight, { settings as githubLightSettings } from './themes/githubLight.mjs';
|
|
import gruvboxDark, { settings as gruvboxDarkSettings } from './themes/gruvboxDark.mjs';
|
|
import gruvboxLight, { settings as gruvboxLightSettings } from './themes/gruvboxLight.mjs';
|
|
import materialDark, { settings as materialDarkSettings } from './themes/materialDark.mjs';
|
|
import materialLight, { settings as materialLightSettings } from './themes/materialLight.mjs';
|
|
import nord, { settings as nordSettings } from './themes/nord.mjs';
|
|
import okaidia, { settings as okaidiaSettings } from './themes/okaidia.mjs';
|
|
import solarizedDark, { settings as solarizedDarkSettings } from './themes/solarizedDark.mjs';
|
|
import solarizedLight, { settings as solarizedLightSettings } from './themes/solarizedLight.mjs';
|
|
import sublime, { settings as sublimeSettings } from './themes/sublime.mjs';
|
|
import tokyoNight, { settings as tokyoNightSettings } from './themes/tokyoNight.mjs';
|
|
import tokyoNightStorm, { settings as tokyoNightStormSettings } from './themes/tokioNightStorm.mjs';
|
|
import vscodeDark, { settings as vscodeDarkSettings } from './themes/vscodeDark.mjs';
|
|
import vscodeLight, { settings as vscodeLightSettings } from './themes/vscodeLight.mjs';
|
|
|
|
import { setTheme } from '@strudel/draw';
|
|
|
|
export const themes = {
|
|
strudelTheme,
|
|
bluescreen,
|
|
blackscreen,
|
|
whitescreen,
|
|
teletext,
|
|
algoboy,
|
|
terminal,
|
|
abcdef,
|
|
androidstudio,
|
|
atomone,
|
|
aura,
|
|
bespin,
|
|
darcula,
|
|
dracula,
|
|
duotoneDark,
|
|
duotoneLight,
|
|
eclipse,
|
|
githubDark,
|
|
gruvboxDark,
|
|
materialDark,
|
|
nord,
|
|
okaidia,
|
|
solarizedDark,
|
|
sublime,
|
|
tokyoNight,
|
|
tokyoNightStorm,
|
|
vscodeDark,
|
|
//xcodeDark,
|
|
//bbedit,
|
|
githubLight,
|
|
gruvboxLight,
|
|
materialLight,
|
|
vscodeLight,
|
|
//noctisLilac,
|
|
solarizedLight,
|
|
//tokyoNightDay,
|
|
//xcodeLight,
|
|
};
|
|
|
|
// lineBackground is background with 50% opacity, to make sure the selection below is visible
|
|
|
|
export const settings = {
|
|
strudelTheme: strudelThemeSettings,
|
|
bluescreen: bluescreenSettings,
|
|
blackscreen: blackscreenSettings,
|
|
whitescreen: whitescreenSettings,
|
|
teletext: teletextSettings,
|
|
algoboy: algoboySettings,
|
|
terminal: terminalSettings,
|
|
abcdef: abcdefSettings,
|
|
androidstudio: androidstudioSettings,
|
|
atomone: atomOneSettings,
|
|
aura: auraSettings,
|
|
/*bbedit: {
|
|
light: true,
|
|
background: '#FFFFFF',
|
|
lineBackground: '#FFFFFF99',
|
|
foreground: '#000000',
|
|
caret: '#FBAC52',
|
|
selection: '#FFD420',
|
|
selectionMatch: '#FFD420',
|
|
gutterBackground: '#f5f5f5',
|
|
gutterForeground: '#4D4D4C',
|
|
gutterBorder: 'transparent',
|
|
lineHighlight: '#00000012',
|
|
},*/
|
|
bespin: bespinSettings,
|
|
darcula: darculaSettings,
|
|
dracula: draculaSettings,
|
|
duotoneLight: duotoneLightSettings,
|
|
duotoneDark: duotoneDarkSettings,
|
|
eclipse: eclipseSettings,
|
|
githubLight: githubLightSettings,
|
|
githubDark: githubDarkSettings,
|
|
gruvboxDark: gruvboxDarkSettings,
|
|
gruvboxLight: gruvboxLightSettings,
|
|
materialDark: materialDarkSettings,
|
|
materialLight: materialLightSettings,
|
|
/*noctisLilac: {
|
|
light: true,
|
|
background: '#f2f1f8',
|
|
lineBackground: '#f2f1f899',
|
|
foreground: '#0c006b',
|
|
caret: '#5c49e9',
|
|
selection: '#d5d1f2',
|
|
selectionMatch: '#d5d1f2',
|
|
gutterBackground: '#f2f1f8',
|
|
gutterForeground: '#0c006b70',
|
|
lineHighlight: '#e1def3',
|
|
},*/
|
|
nord: nordSettings,
|
|
okaidia: okaidiaSettings,
|
|
solarizedLight: solarizedLightSettings,
|
|
solarizedDark: solarizedDarkSettings,
|
|
sublime: sublimeSettings,
|
|
tokyoNight: tokyoNightSettings,
|
|
tokyoNightStorm: tokyoNightStormSettings,
|
|
vscodeDark: vscodeDarkSettings,
|
|
vscodeLight: vscodeLightSettings,
|
|
/*tokyoNightDay: {
|
|
light: true,
|
|
background: '#e1e2e7',
|
|
lineBackground: '#e1e2e799',
|
|
foreground: '#3760bf',
|
|
caret: '#3760bf',
|
|
selection: '#99a7df',
|
|
selectionMatch: '#99a7df',
|
|
gutterBackground: '#e1e2e7',
|
|
gutterForeground: '#3760bf',
|
|
gutterBorder: 'transparent',
|
|
lineHighlight: '#5f5faf11',
|
|
},
|
|
xcodeLight: {
|
|
light: true,
|
|
background: '#fff',
|
|
lineBackground: '#ffffff99',
|
|
foreground: '#3D3D3D',
|
|
selection: '#BBDFFF',
|
|
selectionMatch: '#BBDFFF',
|
|
gutterBackground: '#fff',
|
|
gutterForeground: '#AFAFAF',
|
|
lineHighlight: '#EDF4FF',
|
|
},
|
|
xcodeDark: {
|
|
background: '#292A30',
|
|
lineBackground: '#292A3099',
|
|
foreground: '#CECFD0',
|
|
caret: '#fff',
|
|
selection: '#727377',
|
|
selectionMatch: '#727377',
|
|
lineHighlight: '#2F3239',
|
|
}, */
|
|
};
|
|
|
|
function getColors(str) {
|
|
const colorRegex = /#([0-9A-Fa-f]{6}|[0-9A-Fa-f]{3})/g;
|
|
const colors = [];
|
|
|
|
let match;
|
|
while ((match = colorRegex.exec(str)) !== null) {
|
|
const color = match[0];
|
|
if (!colors.includes(color)) {
|
|
colors.push(color);
|
|
}
|
|
}
|
|
|
|
return colors;
|
|
}
|
|
|
|
// TODO: remove
|
|
export function themeColors(theme) {
|
|
return getColors(stringifySafe(theme));
|
|
}
|
|
|
|
function getCircularReplacer() {
|
|
const seen = new WeakSet();
|
|
return (key, value) => {
|
|
if (typeof value === 'object' && value !== null) {
|
|
if (seen.has(value)) {
|
|
return;
|
|
}
|
|
seen.add(value);
|
|
}
|
|
return value;
|
|
};
|
|
}
|
|
|
|
function stringifySafe(json) {
|
|
return JSON.stringify(json, getCircularReplacer());
|
|
}
|
|
|
|
export const theme = (theme) => themes[theme] || themes.strudelTheme;
|
|
|
|
// css style injection helpers
|
|
export function injectStyle(rule) {
|
|
const newStyle = document.createElement('style');
|
|
document.head.appendChild(newStyle);
|
|
const styleSheet = newStyle.sheet;
|
|
const ruleIndex = styleSheet.insertRule(rule, 0);
|
|
return () => styleSheet.deleteRule(ruleIndex);
|
|
}
|
|
|
|
let currentTheme,
|
|
resetThemeStyle,
|
|
themeStyle,
|
|
styleID = 'strudel-theme-vars';
|
|
export function initTheme(theme) {
|
|
if (!document.getElementById(styleID)) {
|
|
themeStyle = document.createElement('style');
|
|
themeStyle.id = styleID;
|
|
document.head.append(themeStyle);
|
|
}
|
|
activateTheme(theme);
|
|
}
|
|
|
|
export function activateTheme(name) {
|
|
if (currentTheme === name) {
|
|
return;
|
|
}
|
|
currentTheme = name;
|
|
if (!settings[name]) {
|
|
console.warn('theme', name, 'has no settings.. defaulting to strudelTheme settings');
|
|
}
|
|
const themeSettings = settings[name] || settings.strudelTheme;
|
|
// set css variables
|
|
themeStyle.innerHTML = `:root {
|
|
${Object.entries(themeSettings)
|
|
// important to override fallback
|
|
.map(([key, value]) => `--${key}: ${value} !important;`)
|
|
.join('\n')}
|
|
}`;
|
|
setTheme(themeSettings);
|
|
// tailwind dark mode
|
|
if (themeSettings.light) {
|
|
document.documentElement.classList.remove('dark');
|
|
} else {
|
|
document.documentElement.classList.add('dark');
|
|
}
|
|
resetThemeStyle?.();
|
|
resetThemeStyle = undefined;
|
|
if (themeSettings.customStyle) {
|
|
resetThemeStyle = injectStyle(themeSettings.customStyle);
|
|
}
|
|
}
|