Merge branch 'master' into master
This commit is contained in:
1
package-lock.json
generated
1
package-lock.json
generated
@@ -25,6 +25,7 @@
|
||||
}
|
||||
},
|
||||
"../../../../usr/share/astal/gjs": {
|
||||
"name": "astal",
|
||||
"license": "LGPL-2.1"
|
||||
},
|
||||
"node_modules/@eslint-community/eslint-utils": {
|
||||
|
||||
@@ -8,7 +8,13 @@ export const BarGeneral = (): JSX.Element => {
|
||||
<scrollable name={'General'} className="bar-theme-page paged-container" vscroll={Gtk.PolicyType.AUTOMATIC}>
|
||||
<box vertical>
|
||||
<Header title="General Settings" />
|
||||
<Option opt={options.theme.font.name} title="Font" type="font" />
|
||||
<Option
|
||||
opt={options.theme.font.name}
|
||||
fontLabel={options.theme.font.label}
|
||||
fontStyle={options.theme.font.style}
|
||||
title="Font"
|
||||
type="font"
|
||||
/>
|
||||
<Option opt={options.theme.font.size} title="Font Size" type="string" />
|
||||
<Option
|
||||
opt={options.theme.font.weight}
|
||||
|
||||
@@ -100,19 +100,6 @@ export const filterConfigForNonTheme = (config: Config): Config => {
|
||||
* @param themeOnly - A flag indicating whether to save only theme-related properties.
|
||||
*/
|
||||
export const saveFileDialog = (filePath: string, themeOnly: boolean): void => {
|
||||
const original_file_path = filePath;
|
||||
|
||||
const file = Gio.File.new_for_path(original_file_path);
|
||||
const [success, content] = file.load_contents(null);
|
||||
|
||||
if (!success) {
|
||||
console.error(`Could not find 'config.json' at ${TMP}`);
|
||||
return;
|
||||
}
|
||||
|
||||
const jsonString = new TextDecoder('utf-8').decode(content);
|
||||
const jsonObject = JSON.parse(jsonString);
|
||||
|
||||
const filterHexColorPairs = (jsonObject: Config): Config => {
|
||||
const filteredObject: Config = {};
|
||||
|
||||
@@ -145,9 +132,6 @@ export const saveFileDialog = (filePath: string, themeOnly: boolean): void => {
|
||||
return filteredObject;
|
||||
};
|
||||
|
||||
const filteredJsonObject = themeOnly ? filterHexColorPairs(jsonObject) : filterOutHexColorPairs(jsonObject);
|
||||
const filteredContent = JSON.stringify(filteredJsonObject, null, 2);
|
||||
|
||||
const dialog = new Gtk.FileChooserDialog({
|
||||
title: `Save Hyprpanel ${themeOnly ? 'Theme' : 'Config'}`,
|
||||
action: Gtk.FileChooserAction.SAVE,
|
||||
@@ -160,55 +144,82 @@ export const saveFileDialog = (filePath: string, themeOnly: boolean): void => {
|
||||
|
||||
const response = dialog.run();
|
||||
|
||||
if (response === Gtk.ResponseType.ACCEPT) {
|
||||
const file_path = dialog.get_filename();
|
||||
console.info(`Original file path: ${file_path}`);
|
||||
try {
|
||||
const original_file_path = filePath;
|
||||
|
||||
const getIncrementedFilePath = (filePath: string): string => {
|
||||
let increment = 1;
|
||||
const baseName = filePath.replace(/(\.\w+)$/, '');
|
||||
const match = filePath.match(/(\.\w+)$/);
|
||||
const extension = match ? match[0] : '';
|
||||
const file = Gio.File.new_for_path(original_file_path);
|
||||
const [success, content] = file.load_contents(null);
|
||||
|
||||
let newFilePath = filePath;
|
||||
let file = Gio.File.new_for_path(newFilePath);
|
||||
if (!success) {
|
||||
console.error(`Could not find 'config.json' at ${TMP}`);
|
||||
return;
|
||||
}
|
||||
|
||||
while (file.query_exists(null)) {
|
||||
newFilePath = `${baseName}_${increment}${extension}`;
|
||||
file = Gio.File.new_for_path(newFilePath);
|
||||
increment++;
|
||||
}
|
||||
const jsonString = new TextDecoder('utf-8').decode(content);
|
||||
const jsonObject = JSON.parse(jsonString);
|
||||
|
||||
return newFilePath;
|
||||
};
|
||||
const filteredJsonObject = themeOnly ? filterHexColorPairs(jsonObject) : filterOutHexColorPairs(jsonObject);
|
||||
const filteredContent = JSON.stringify(filteredJsonObject, null, 2);
|
||||
|
||||
const finalFilePath = getIncrementedFilePath(file_path as string);
|
||||
console.info(`File will be saved at: ${finalFilePath}`);
|
||||
if (response === Gtk.ResponseType.ACCEPT) {
|
||||
const file_path = dialog.get_filename();
|
||||
console.info(`Original file path: ${file_path}`);
|
||||
|
||||
try {
|
||||
const save_file = Gio.File.new_for_path(finalFilePath);
|
||||
const outputStream = save_file.replace(null, false, Gio.FileCreateFlags.NONE, null);
|
||||
const dataOutputStream = new Gio.DataOutputStream({
|
||||
base_stream: outputStream,
|
||||
});
|
||||
const getIncrementedFilePath = (filePath: string): string => {
|
||||
let increment = 1;
|
||||
const baseName = filePath.replace(/(\.\w+)$/, '');
|
||||
const match = filePath.match(/(\.\w+)$/);
|
||||
const extension = match ? match[0] : '';
|
||||
|
||||
dataOutputStream.put_string(filteredContent, null);
|
||||
let newFilePath = filePath;
|
||||
let file = Gio.File.new_for_path(newFilePath);
|
||||
|
||||
dataOutputStream.close(null);
|
||||
while (file.query_exists(null)) {
|
||||
newFilePath = `${baseName}_${increment}${extension}`;
|
||||
file = Gio.File.new_for_path(newFilePath);
|
||||
increment++;
|
||||
}
|
||||
|
||||
Notify({
|
||||
summary: 'File Saved Successfully',
|
||||
body: `At ${finalFilePath}.`,
|
||||
iconName: icons.ui.info,
|
||||
});
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
console.error('Failed to write to file:', e.message);
|
||||
return newFilePath;
|
||||
};
|
||||
|
||||
const finalFilePath = getIncrementedFilePath(file_path as string);
|
||||
console.info(`File will be saved at: ${finalFilePath}`);
|
||||
|
||||
try {
|
||||
const save_file = Gio.File.new_for_path(finalFilePath);
|
||||
const outputStream = save_file.replace(null, false, Gio.FileCreateFlags.NONE, null);
|
||||
const dataOutputStream = new Gio.DataOutputStream({
|
||||
base_stream: outputStream,
|
||||
});
|
||||
|
||||
dataOutputStream.put_string(filteredContent, null);
|
||||
|
||||
dataOutputStream.close(null);
|
||||
|
||||
Notify({
|
||||
summary: 'File Saved Successfully',
|
||||
body: `At ${finalFilePath}.`,
|
||||
iconName: icons.ui.info,
|
||||
});
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
console.error('Failed to write to file:', e.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dialog.destroy();
|
||||
dialog.destroy();
|
||||
} catch (error) {
|
||||
const errorMessage = error instanceof Error ? error.message : String(error);
|
||||
dialog.destroy();
|
||||
|
||||
Notify({
|
||||
summary: `${themeOnly ? 'Theme' : 'Config'} Export Failed`,
|
||||
body: errorMessage ?? 'An unknown error occurred.',
|
||||
iconName: icons.ui.warning,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -231,63 +242,74 @@ export const importFiles = (themeOnly: boolean = false): void => {
|
||||
|
||||
const response = dialog.run();
|
||||
|
||||
if (response === Gtk.ResponseType.CANCEL) {
|
||||
dialog.destroy();
|
||||
return;
|
||||
}
|
||||
if (response === Gtk.ResponseType.ACCEPT) {
|
||||
const filePath: string | null = dialog.get_filename();
|
||||
|
||||
if (filePath === null) {
|
||||
Notify({
|
||||
summary: 'Failed to import',
|
||||
body: 'No file selected.',
|
||||
iconName: icons.ui.warning,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const importedConfig = loadJsonFile(filePath);
|
||||
|
||||
if (!importedConfig) {
|
||||
try {
|
||||
if (response === Gtk.ResponseType.CANCEL) {
|
||||
dialog.destroy();
|
||||
return;
|
||||
}
|
||||
if (response === Gtk.ResponseType.ACCEPT) {
|
||||
const filePath: string | null = dialog.get_filename();
|
||||
|
||||
if (filePath === null) {
|
||||
Notify({
|
||||
summary: 'Failed to import',
|
||||
body: 'No file selected.',
|
||||
iconName: icons.ui.warning,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const importedConfig = loadJsonFile(filePath);
|
||||
|
||||
if (!importedConfig) {
|
||||
dialog.destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
Notify({
|
||||
summary: `Importing ${themeOnly ? 'Theme' : 'Config'}`,
|
||||
body: `Importing: ${filePath}`,
|
||||
iconName: icons.ui.info,
|
||||
});
|
||||
|
||||
const tmpConfigFile = Gio.File.new_for_path(`${TMP}/config.json`);
|
||||
const optionsConfigFile = Gio.File.new_for_path(CONFIG);
|
||||
|
||||
const [tmpSuccess, tmpContent] = tmpConfigFile.load_contents(null);
|
||||
const [optionsSuccess, optionsContent] = optionsConfigFile.load_contents(null);
|
||||
|
||||
if (!tmpSuccess || !optionsSuccess) {
|
||||
console.error('Failed to read existing configuration files.');
|
||||
dialog.destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
let tmpConfig = JSON.parse(new TextDecoder('utf-8').decode(tmpContent));
|
||||
let optionsConfig = JSON.parse(new TextDecoder('utf-8').decode(optionsContent));
|
||||
|
||||
if (themeOnly) {
|
||||
const filteredConfig = filterConfigForThemeOnly(importedConfig);
|
||||
tmpConfig = { ...tmpConfig, ...filteredConfig };
|
||||
optionsConfig = { ...optionsConfig, ...filteredConfig };
|
||||
} else {
|
||||
const filteredConfig = filterConfigForNonTheme(importedConfig);
|
||||
tmpConfig = { ...tmpConfig, ...filteredConfig };
|
||||
optionsConfig = { ...optionsConfig, ...filteredConfig };
|
||||
}
|
||||
|
||||
saveConfigToFile(tmpConfig, `${TMP}/config.json`);
|
||||
saveConfigToFile(optionsConfig, CONFIG);
|
||||
}
|
||||
dialog.destroy();
|
||||
bash(restartCommand.get());
|
||||
} catch (error) {
|
||||
const errorMessage = error instanceof Error ? error.message : String(error);
|
||||
dialog.destroy();
|
||||
|
||||
Notify({
|
||||
summary: `Importing ${themeOnly ? 'Theme' : 'Config'}`,
|
||||
body: `Importing: ${filePath}`,
|
||||
iconName: icons.ui.info,
|
||||
summary: `${themeOnly ? 'Theme' : 'Config'} Import Failed`,
|
||||
body: errorMessage ?? 'An unknown error occurred.',
|
||||
iconName: icons.ui.warning,
|
||||
});
|
||||
|
||||
const tmpConfigFile = Gio.File.new_for_path(`${TMP}/config.json`);
|
||||
const optionsConfigFile = Gio.File.new_for_path(CONFIG);
|
||||
|
||||
const [tmpSuccess, tmpContent] = tmpConfigFile.load_contents(null);
|
||||
const [optionsSuccess, optionsContent] = optionsConfigFile.load_contents(null);
|
||||
|
||||
if (!tmpSuccess || !optionsSuccess) {
|
||||
console.error('Failed to read existing configuration files.');
|
||||
dialog.destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
let tmpConfig = JSON.parse(new TextDecoder('utf-8').decode(tmpContent));
|
||||
let optionsConfig = JSON.parse(new TextDecoder('utf-8').decode(optionsContent));
|
||||
|
||||
if (themeOnly) {
|
||||
const filteredConfig = filterConfigForThemeOnly(importedConfig);
|
||||
tmpConfig = { ...tmpConfig, ...filteredConfig };
|
||||
optionsConfig = { ...optionsConfig, ...filteredConfig };
|
||||
} else {
|
||||
const filteredConfig = filterConfigForNonTheme(importedConfig);
|
||||
tmpConfig = { ...tmpConfig, ...filteredConfig };
|
||||
optionsConfig = { ...optionsConfig, ...filteredConfig };
|
||||
}
|
||||
|
||||
saveConfigToFile(tmpConfig, `${TMP}/config.json`);
|
||||
saveConfigToFile(optionsConfig, CONFIG);
|
||||
}
|
||||
dialog.destroy();
|
||||
bash(restartCommand.get());
|
||||
};
|
||||
|
||||
@@ -14,6 +14,8 @@ import { Gtk } from 'astal/gtk3';
|
||||
|
||||
const InputField = <T extends string | number | boolean | object>({
|
||||
opt,
|
||||
fontStyle,
|
||||
fontLabel,
|
||||
type = typeof opt.get() as RowProps<T>['type'],
|
||||
enums = [],
|
||||
disabledBinding,
|
||||
@@ -44,7 +46,7 @@ const InputField = <T extends string | number | boolean | object>({
|
||||
case 'wallpaper':
|
||||
return <WallpaperInputter opt={opt} />;
|
||||
case 'font':
|
||||
return <FontInputter opt={opt} />;
|
||||
return <FontInputter fontFamily={opt} fontLabel={fontLabel} fontStyle={fontStyle} />;
|
||||
case 'color':
|
||||
return <ColorInputter opt={opt} />;
|
||||
|
||||
@@ -55,6 +57,8 @@ const InputField = <T extends string | number | boolean | object>({
|
||||
|
||||
export const Inputter = <T extends string | number | boolean | object>({
|
||||
opt,
|
||||
fontStyle,
|
||||
fontLabel,
|
||||
type = typeof opt.get() as RowProps<T>['type'],
|
||||
enums,
|
||||
disabledBinding,
|
||||
@@ -71,6 +75,8 @@ export const Inputter = <T extends string | number | boolean | object>({
|
||||
<InputField
|
||||
type={type}
|
||||
opt={opt}
|
||||
fontStyle={fontStyle}
|
||||
fontLabel={fontLabel}
|
||||
enums={enums}
|
||||
disabledBinding={disabledBinding}
|
||||
dependencies={dependencies}
|
||||
|
||||
@@ -10,6 +10,8 @@ export const SettingInput = <T extends string | number | boolean | object>({
|
||||
return (
|
||||
<Inputter
|
||||
opt={props.opt}
|
||||
fontStyle={props.fontStyle}
|
||||
fontLabel={props.fontLabel}
|
||||
type={props.type}
|
||||
enums={props.enums}
|
||||
disabledBinding={props.disabledBinding}
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
import FontButton from 'src/components/shared/FontButton';
|
||||
import { Opt } from 'src/lib/option';
|
||||
|
||||
export const FontInputter = <T extends string | number | boolean | object>({
|
||||
opt,
|
||||
}: FontInputterProps<T>): JSX.Element => {
|
||||
return (
|
||||
<FontButton
|
||||
showSize={false}
|
||||
useSize={false}
|
||||
setup={(self) => {
|
||||
self.font = opt.get() as string;
|
||||
|
||||
self.hook(opt, () => (self.font = opt.get() as string));
|
||||
self.connect('font-set', ({ font }) => opt.set(font!.split(' ').slice(0, -1).join(' ') as T));
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
interface FontInputterProps<T> {
|
||||
opt: Opt<T>;
|
||||
}
|
||||
43
src/components/settings/shared/inputs/font/index.tsx
Normal file
43
src/components/settings/shared/inputs/font/index.tsx
Normal file
@@ -0,0 +1,43 @@
|
||||
import FontButton from 'src/components/shared/FontButton';
|
||||
import { Opt } from 'src/lib/option';
|
||||
import { styleToString } from './utils';
|
||||
|
||||
export const FontInputter = <T extends string | number | boolean | object>({
|
||||
fontFamily,
|
||||
fontStyle,
|
||||
fontLabel,
|
||||
}: FontInputterProps<T>): JSX.Element => (
|
||||
<FontButton
|
||||
showSize={false}
|
||||
useSize={false}
|
||||
setup={(self) => {
|
||||
self.font = fontLabel?.get() ?? (fontFamily.get() as string);
|
||||
|
||||
if (fontLabel) {
|
||||
self.hook(fontLabel, () => {
|
||||
self.font = fontLabel.get() as string;
|
||||
});
|
||||
} else {
|
||||
self.hook(fontFamily, () => {
|
||||
self.font = fontFamily.get() as string;
|
||||
});
|
||||
}
|
||||
|
||||
self.connect('font-set', ({ fontDesc, font }) => {
|
||||
const selectedFontFamily = fontDesc.get_family();
|
||||
const selectedFontStyle = styleToString(fontDesc.get_style());
|
||||
|
||||
fontFamily.set(selectedFontFamily as T);
|
||||
|
||||
fontStyle?.set(selectedFontStyle);
|
||||
fontLabel?.set(font.split(' ').slice(0, -1).join(' '));
|
||||
});
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
interface FontInputterProps<T> {
|
||||
fontFamily: Opt<T>;
|
||||
fontStyle?: Opt<string>;
|
||||
fontLabel?: Opt<string>;
|
||||
}
|
||||
72
src/components/settings/shared/inputs/font/utils.ts
Normal file
72
src/components/settings/shared/inputs/font/utils.ts
Normal file
@@ -0,0 +1,72 @@
|
||||
import Pango from 'gi://Pango?version=1.0';
|
||||
|
||||
export type FontStyle = 'normal' | 'italic' | 'oblique';
|
||||
export type FontVariant = 'normal' | 'small-caps';
|
||||
export type FontWeight =
|
||||
| 'thin'
|
||||
| 'ultralight'
|
||||
| 'light'
|
||||
| 'semilight'
|
||||
| 'book'
|
||||
| 'normal'
|
||||
| 'medium'
|
||||
| 'semibold'
|
||||
| 'bold'
|
||||
| 'ultrabold'
|
||||
| 'heavy';
|
||||
|
||||
const DEFAULT_FONT_STYLE: FontStyle = 'normal';
|
||||
const DEFAULT_FONT_VARIANT: FontVariant = 'normal';
|
||||
const DEFAULT_FONT_WEIGHT: FontWeight = 'normal';
|
||||
|
||||
const styleMap: Record<Pango.Style, FontStyle> = {
|
||||
[Pango.Style.NORMAL]: 'normal',
|
||||
[Pango.Style.ITALIC]: 'italic',
|
||||
[Pango.Style.OBLIQUE]: 'oblique',
|
||||
};
|
||||
|
||||
const variantMap: Record<Pango.Variant, FontVariant> = {
|
||||
[Pango.Variant.NORMAL]: 'normal',
|
||||
[Pango.Variant.SMALL_CAPS]: 'small-caps',
|
||||
};
|
||||
|
||||
const weightMap: Record<Pango.Weight, FontWeight> = {
|
||||
[Pango.Weight.THIN]: 'thin',
|
||||
[Pango.Weight.ULTRALIGHT]: 'ultralight',
|
||||
[Pango.Weight.LIGHT]: 'light',
|
||||
[Pango.Weight.SEMILIGHT]: 'semilight',
|
||||
[Pango.Weight.BOOK]: 'book',
|
||||
[Pango.Weight.NORMAL]: 'normal',
|
||||
[Pango.Weight.MEDIUM]: 'medium',
|
||||
[Pango.Weight.SEMIBOLD]: 'semibold',
|
||||
[Pango.Weight.BOLD]: 'bold',
|
||||
[Pango.Weight.ULTRABOLD]: 'ultrabold',
|
||||
[Pango.Weight.HEAVY]: 'heavy',
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts a Pango.Style enum to a FontStyle string.
|
||||
* @param styleEnum - The Pango.Style enum value.
|
||||
* @returns The corresponding FontStyle string.
|
||||
*/
|
||||
export function styleToString(styleEnum: Pango.Style): FontStyle {
|
||||
return styleMap[styleEnum] ?? DEFAULT_FONT_STYLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a Pango.Variant enum to a FontVariant string.
|
||||
* @param variantEnum - The Pango.Variant enum value.
|
||||
* @returns The corresponding FontVariant string.
|
||||
*/
|
||||
export function variantToString(variantEnum: Pango.Variant): FontVariant {
|
||||
return variantMap[variantEnum] ?? DEFAULT_FONT_VARIANT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a Pango.Weight enum to a FontWeight string.
|
||||
* @param weightEnum - The Pango.Weight enum value.
|
||||
* @returns The corresponding FontWeight string.
|
||||
*/
|
||||
export function weightToString(weightEnum: Pango.Weight): FontWeight {
|
||||
return weightMap[weightEnum] ?? DEFAULT_FONT_WEIGHT;
|
||||
}
|
||||
2
src/lib/types/options.d.ts
vendored
2
src/lib/types/options.d.ts
vendored
@@ -104,6 +104,8 @@ export interface RowProps<T> {
|
||||
subtitleLink?: string;
|
||||
dependencies?: string[];
|
||||
increment?: number;
|
||||
fontStyle?: Opt<string>;
|
||||
fontLabel?: Opt<string>;
|
||||
}
|
||||
|
||||
export type OSDOrientation = 'horizontal' | 'vertical';
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { FontStyle } from './components/settings/shared/inputs/font/utils';
|
||||
import { opt, mkOptions } from './lib/option';
|
||||
import { NetstatLabelType, RateUnit, ResourceLabelType } from './lib/types/bar';
|
||||
import { KbLabelType } from './lib/types/customModules/kbLayout';
|
||||
@@ -104,6 +105,8 @@ const options = mkOptions(CONFIG, {
|
||||
font: {
|
||||
size: opt('1.2rem'),
|
||||
name: opt('Ubuntu Nerd Font'),
|
||||
style: opt<FontStyle>('normal'),
|
||||
label: opt('Ubuntu Nerd Font'),
|
||||
weight: opt(600),
|
||||
},
|
||||
notification: {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
* {
|
||||
all: unset;
|
||||
font-family: $font-name;
|
||||
font-style: $font-style;
|
||||
font-size: $font-size;
|
||||
font-weight: $font-weight;
|
||||
}
|
||||
|
||||
@@ -1,222 +1,210 @@
|
||||
@import "colors";
|
||||
@import 'colors';
|
||||
|
||||
* {
|
||||
color: $default_fg;
|
||||
font-family: "JetBrainsMono NF";
|
||||
font-size: 0.9rem;
|
||||
html,
|
||||
body {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
background-color: $primary_bg;
|
||||
}
|
||||
|
||||
html, body {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
background-color: $primary_bg;
|
||||
}
|
||||
|
||||
// scrollbar {
|
||||
// background-color: red;
|
||||
// min-width: 5em;
|
||||
// }
|
||||
|
||||
.code {
|
||||
background: $light-background;
|
||||
border-radius: 0.5rem;
|
||||
|
||||
.code-header {
|
||||
background: $light-background;
|
||||
border-top-left-radius: 0.5rem;
|
||||
border-top-right-radius: 0.5rem;
|
||||
border-bottom: 1px solid $primary_fg;
|
||||
padding: 5px;
|
||||
border-radius: 0.5rem;
|
||||
|
||||
> button {
|
||||
color: $default_fg;
|
||||
background: transparent;
|
||||
float: right;
|
||||
border: none;
|
||||
.code-header {
|
||||
background: $light-background;
|
||||
border-top-left-radius: 0.5rem;
|
||||
border-top-right-radius: 0.5rem;
|
||||
border-bottom: 1px solid $primary_fg;
|
||||
padding: 5px;
|
||||
|
||||
&:before {
|
||||
content: '';
|
||||
display: inline-block;
|
||||
padding-right: 0.5rem;
|
||||
}
|
||||
> button {
|
||||
color: $default_fg;
|
||||
background: transparent;
|
||||
float: right;
|
||||
border: none;
|
||||
|
||||
&:before {
|
||||
content: '';
|
||||
display: inline-block;
|
||||
padding-right: 0.5rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$languages-map: (
|
||||
arduino: "",
|
||||
armasm: "",
|
||||
avrasm: "",
|
||||
bash: "",
|
||||
c: "",
|
||||
clojure: "",
|
||||
coffeescript: "",
|
||||
cpp: "",
|
||||
csharp: "",
|
||||
css: "",
|
||||
dockerfile: "",
|
||||
go: "",
|
||||
gradle: "",
|
||||
haskell: "",
|
||||
html: "",
|
||||
java: "",
|
||||
javascript: "",
|
||||
json: "",
|
||||
latex: "",
|
||||
lua: "",
|
||||
makefile: "",
|
||||
markdown: "",
|
||||
mipsasm: "",
|
||||
nginx: "",
|
||||
nix: "",
|
||||
php: "",
|
||||
prolog: "",
|
||||
python: "",
|
||||
r: "",
|
||||
ruby: "",
|
||||
rust: "",
|
||||
scss: "",
|
||||
shell: "",
|
||||
typescript: "",
|
||||
wasm: "",
|
||||
x86asm: "",
|
||||
xml: "",
|
||||
arduino: '',
|
||||
armasm: '',
|
||||
avrasm: '',
|
||||
bash: '',
|
||||
c: '',
|
||||
clojure: '',
|
||||
coffeescript: '',
|
||||
cpp: '',
|
||||
csharp: '',
|
||||
css: '',
|
||||
dockerfile: '',
|
||||
go: '',
|
||||
gradle: '',
|
||||
haskell: '',
|
||||
html: '',
|
||||
java: '',
|
||||
javascript: '',
|
||||
json: '',
|
||||
latex: '',
|
||||
lua: '',
|
||||
makefile: '',
|
||||
markdown: '',
|
||||
mipsasm: '',
|
||||
nginx: '',
|
||||
nix: '',
|
||||
php: '',
|
||||
prolog: '',
|
||||
python: '',
|
||||
r: '',
|
||||
ruby: '',
|
||||
rust: '',
|
||||
scss: '',
|
||||
shell: '',
|
||||
typescript: '',
|
||||
wasm: '',
|
||||
x86asm: '',
|
||||
xml: '',
|
||||
);
|
||||
|
||||
@each $lang, $content in $languages-map {
|
||||
[data-language="#{$lang}"]:before {
|
||||
content: $content;
|
||||
font-size: 1.1rem;
|
||||
color: $primary_fg;
|
||||
padding-right: 0.5rem;
|
||||
}
|
||||
[data-language='#{$lang}']:before {
|
||||
content: $content;
|
||||
font-size: 1.1rem;
|
||||
color: $primary_fg;
|
||||
padding-right: 0.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
pre {
|
||||
padding: 5px;
|
||||
overflow-x: scroll;
|
||||
padding: 5px;
|
||||
overflow-x: scroll;
|
||||
|
||||
code.hljs {
|
||||
color: $default_fg;
|
||||
background: transparent;
|
||||
}
|
||||
code.hljs {
|
||||
color: $default_fg;
|
||||
background: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
code {
|
||||
& .hljs-keyword {
|
||||
color: $mauve;
|
||||
}
|
||||
& .hljs-keyword {
|
||||
color: $mauve;
|
||||
}
|
||||
|
||||
& .hljs-built_in {
|
||||
color: $red;
|
||||
}
|
||||
& .hljs-built_in {
|
||||
color: $red;
|
||||
}
|
||||
|
||||
& .hljs-type {
|
||||
color: $yellow;
|
||||
}
|
||||
& .hljs-type {
|
||||
color: $yellow;
|
||||
}
|
||||
|
||||
& .hljs-literal,
|
||||
& .hljs-number {
|
||||
color: $orange;
|
||||
}
|
||||
& .hljs-literal,
|
||||
& .hljs-number {
|
||||
color: $orange;
|
||||
}
|
||||
|
||||
& .hljs-operator {
|
||||
color: $teal;
|
||||
}
|
||||
& .hljs-operator {
|
||||
color: $teal;
|
||||
}
|
||||
|
||||
& .hljs-punctuation {
|
||||
color: $lightteal;
|
||||
}
|
||||
& .hljs-punctuation {
|
||||
color: $lightteal;
|
||||
}
|
||||
|
||||
& .hljs-property,
|
||||
& .hljs-variable.language_,
|
||||
& .hljs-symbol {
|
||||
color: $teal;
|
||||
}
|
||||
& .hljs-property,
|
||||
& .hljs-variable.language_,
|
||||
& .hljs-symbol {
|
||||
color: $teal;
|
||||
}
|
||||
|
||||
& .hljs-regexp {
|
||||
color: $pink;
|
||||
}
|
||||
& .hljs-regexp {
|
||||
color: $pink;
|
||||
}
|
||||
|
||||
& .hljs-string,
|
||||
& .hljs-char.escape_,
|
||||
& .hljs-subst {
|
||||
color: $green;
|
||||
}
|
||||
& .hljs-string,
|
||||
& .hljs-char.escape_,
|
||||
& .hljs-subst {
|
||||
color: $green;
|
||||
}
|
||||
|
||||
& .hljs-comment {
|
||||
color: $grey;
|
||||
}
|
||||
& .hljs-comment {
|
||||
color: $grey;
|
||||
}
|
||||
|
||||
& .hljs-doctag {
|
||||
color: $red;
|
||||
}
|
||||
& .hljs-doctag {
|
||||
color: $red;
|
||||
}
|
||||
|
||||
& .hljs-meta,
|
||||
& .hljs-title.function_,
|
||||
& .hljs-section {
|
||||
color: $orange;
|
||||
}
|
||||
& .hljs-meta,
|
||||
& .hljs-title.function_,
|
||||
& .hljs-section {
|
||||
color: $orange;
|
||||
}
|
||||
|
||||
& .hljs-tag,
|
||||
& .hljs-attribute {
|
||||
color: $lightgrey;
|
||||
}
|
||||
& .hljs-tag,
|
||||
& .hljs-attribute {
|
||||
color: $lightgrey;
|
||||
}
|
||||
|
||||
& .hljs-name,
|
||||
& .hljs-selector-attr {
|
||||
color: $mauve;
|
||||
}
|
||||
& .hljs-name,
|
||||
& .hljs-selector-attr {
|
||||
color: $mauve;
|
||||
}
|
||||
|
||||
& .hljs-params,
|
||||
& .hljs-selector-class,
|
||||
& .hljs-template-variable {
|
||||
color: $default_fg;
|
||||
}
|
||||
& .hljs-params,
|
||||
& .hljs-selector-class,
|
||||
& .hljs-template-variable {
|
||||
color: $default_fg;
|
||||
}
|
||||
|
||||
& .hljs-selector-tag {
|
||||
color: $yellow;
|
||||
}
|
||||
& .hljs-selector-tag {
|
||||
color: $yellow;
|
||||
}
|
||||
|
||||
& .hljs-selector-id {
|
||||
color: $blue;
|
||||
}
|
||||
& .hljs-selector-id {
|
||||
color: $blue;
|
||||
}
|
||||
|
||||
& .hljs-bullet,
|
||||
& .hljs-code,
|
||||
& .hljs-formula {
|
||||
color: $teal;
|
||||
}
|
||||
& .hljs-bullet,
|
||||
& .hljs-code,
|
||||
& .hljs-formula {
|
||||
color: $teal;
|
||||
}
|
||||
|
||||
& .hljs-emphasis {
|
||||
color: $red;
|
||||
font-style: italic;
|
||||
}
|
||||
& .hljs-emphasis {
|
||||
color: $red;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
& .hljs-strong {
|
||||
color: $red;
|
||||
font-weight: bold;
|
||||
}
|
||||
& .hljs-strong {
|
||||
color: $red;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
& .hljs-link {
|
||||
color: $lightblue;
|
||||
font-style: italic;
|
||||
}
|
||||
& .hljs-link {
|
||||
color: $lightblue;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
& .hljs-quote {
|
||||
color: $green;
|
||||
font-style: italic;
|
||||
}
|
||||
& .hljs-quote {
|
||||
color: $green;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
& .hljs-addition {
|
||||
color: $green;
|
||||
background: rgba(166, 227, 161, 0.15);
|
||||
}
|
||||
& .hljs-addition {
|
||||
color: $green;
|
||||
background: rgba(166, 227, 161, 0.15);
|
||||
}
|
||||
|
||||
& .hljs-deletion {
|
||||
color: $red;
|
||||
background: rgba(243, 139, 168, 0.15);
|
||||
}
|
||||
& .hljs-deletion {
|
||||
color: $red;
|
||||
background: rgba(243, 139, 168, 0.15);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import { resetCss } from '../style';
|
||||
|
||||
export const initializeHotReload = async (): Promise<void> => {
|
||||
const monitorList = [
|
||||
`${SRC_DIR}/src/scss/main.scss`,
|
||||
`${SRC_DIR}/src/scss/style/bar`,
|
||||
`${SRC_DIR}/src/scss/style/common`,
|
||||
`${SRC_DIR}/src/scss/style/menus`,
|
||||
|
||||
Reference in New Issue
Block a user