Skip to content

Commit

Permalink
Add custom themes and language support to Monaco editor.
Browse files Browse the repository at this point in the history
  • Loading branch information
junhaoliao committed Sep 12, 2024
1 parent cfa9274 commit 3b9295e
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 3 deletions.
15 changes: 12 additions & 3 deletions new-log-viewer/src/components/Editor/MonacoInstance/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,11 @@ import "./index.css";


interface MonacoEditorProps {
actions: ActionType[],
lineNum: number,
text: string,
actions: ActionType[],
themeName: string,

beforeMount?: BeforeMountCallback,
beforeTextUpdate?: BeforeTextUpdateCallback,
onCursorExplicitPosChange: CursorExplicitPosChangeCallback,
Expand All @@ -40,9 +42,10 @@ interface MonacoEditorProps {
* the editor.
*
* @param props
* @param props.actions
* @param props.lineNum
* @param props.text
* @param props.actions
* @param props.themeName
* @param props.beforeMount
* @param props.beforeTextUpdate
* @param props.onCursorExplicitPosChange
Expand All @@ -52,9 +55,10 @@ interface MonacoEditorProps {
* @return
*/
const MonacoInstance = ({
actions,
lineNum,
text,
actions,
themeName,
beforeMount,
beforeTextUpdate,
onMount,
Expand Down Expand Up @@ -98,6 +102,11 @@ const MonacoInstance = ({
onMount,
]);

// On `themeName` update, set theme in the editor.
useEffect(() => {
monaco.editor.setTheme(themeName);
}, [themeName]);

// On `text` update, set the text and position cursor in the editor.
useEffect(() => {
if (null === editorRef.current) {
Expand Down
36 changes: 36 additions & 0 deletions new-log-viewer/src/components/Editor/MonacoInstance/language.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import * as monaco from "monaco-editor/esm/vs/editor/editor.api.js";

import {TOKEN_NAMES} from "./typings";


const LOG_LANGUAGE_NAME = "logLanguage";


/**
* Registers a custom log language in the Monaco editor.
*/
const setupCustomLogLanguage = () => {
monaco.languages.register({
id: LOG_LANGUAGE_NAME,
});
monaco.languages.setMonarchTokensProvider(LOG_LANGUAGE_NAME, {
tokenizer: {
root: [
/* eslint-disable @stylistic/js/array-element-newline */
["INFO", TOKEN_NAMES.CUSTOM_INFO],
["WARN", TOKEN_NAMES.CUSTOM_WARN],
["ERROR", TOKEN_NAMES.CUSTOM_ERROR],
["FATAL", TOKEN_NAMES.CUSTOM_FATAL],
[/(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3})Z/, TOKEN_NAMES.CUSTOM_DATE],
[/^[\t ]*at.*$/, TOKEN_NAMES.CUSTOM_EXCEPTION],
[/(\d+(?:\.\d+)?([eE])([+-])[0-9](\.[0-9])?|\d+(?:\.\d+)?)/, TOKEN_NAMES.CUSTOM_NUMBER],
/* eslint-enable @stylistic/js/array-element-newline */
],
},
});
};

export {
LOG_LANGUAGE_NAME,
setupCustomLogLanguage,
};
45 changes: 45 additions & 0 deletions new-log-viewer/src/components/Editor/MonacoInstance/theme.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import * as monaco from "monaco-editor/esm/vs/editor/editor.api.js";

import {THEME_NAME} from "../../../typings/config";
import {TOKEN_NAMES} from "./typings";


/**
* Sets up custom themes for the Monaco editor.
*/
const setupThemes = () => {
monaco.editor.defineTheme(THEME_NAME.DARK, {
base: "vs-dark",
inherit: true,
rules: [
{token: TOKEN_NAMES.CUSTOM_INFO, foreground: "#098658"},
{token: TOKEN_NAMES.CUSTOM_WARN, foreground: "#ce9178"},
{token: TOKEN_NAMES.CUSTOM_ERROR, foreground: "#ce9178", fontStyle: "bold"},
{token: TOKEN_NAMES.CUSTOM_FATAL, foreground: "#ce9178", fontStyle: "bold"},
{token: TOKEN_NAMES.CUSTOM_DATE, foreground: "#529955"},
{token: TOKEN_NAMES.CUSTOM_EXCEPTION, foreground: "#ce723b", fontStyle: "italic"},
{token: TOKEN_NAMES.CUSTOM_NUMBER, foreground: "#3f9ccb"},
{token: TOKEN_NAMES.COMMENT, foreground: "#008000"},
],
colors: {
"editor.lineHighlightBackground": "#3c3c3c",
},
});
monaco.editor.defineTheme(THEME_NAME.LIGHT, {
base: "vs",
inherit: true,
rules: [
{token: TOKEN_NAMES.CUSTOM_INFO, foreground: "#098658"},
{token: TOKEN_NAMES.CUSTOM_WARN, foreground: "#b81560"},
{token: TOKEN_NAMES.CUSTOM_ERROR, foreground: "#ac1515", fontStyle: "bold"},
{token: TOKEN_NAMES.CUSTOM_FATAL, foreground: "#ac1515", fontStyle: "bold"},
{token: TOKEN_NAMES.CUSTOM_DATE, foreground: "#008000"},
{token: TOKEN_NAMES.CUSTOM_EXCEPTION, foreground: "#ce723b", fontStyle: "italic"},
{token: TOKEN_NAMES.CUSTOM_NUMBER, foreground: "#3f9ccb"},
],
colors: {},
});
};


export {setupThemes};
12 changes: 12 additions & 0 deletions new-log-viewer/src/components/Editor/MonacoInstance/typings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,17 @@ import * as monaco from "monaco-editor/esm/vs/editor/editor.api.js";
import {ACTION_NAME} from "../../../utils/actions";


enum TOKEN_NAMES {
CUSTOM_INFO = "customInfo",
CUSTOM_WARN = "customEarn",
CUSTOM_ERROR = "customError",
CUSTOM_FATAL = "customFatal",
CUSTOM_DATE = "customDate",
CUSTOM_EXCEPTION = "customException",
CUSTOM_NUMBER = "customNumber",
COMMENT = "comment",
}

/**
* Gets called when the cursor position is explicitly changed in the editor.
*
Expand Down Expand Up @@ -55,6 +66,7 @@ interface CustomMonacoEditorHandlers {
onCustomAction?: CustomActionCallback,
}

export {TOKEN_NAMES};
export type {
BeforeMountCallback,
BeforeTextUpdateCallback,
Expand Down
9 changes: 9 additions & 0 deletions new-log-viewer/src/components/Editor/MonacoInstance/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ import {
setupFocusOnBacktickDown,
setupMobileZoom,
} from "./actions";
import {
LOG_LANGUAGE_NAME,
setupCustomLogLanguage,
} from "./language";
import {setupThemes} from "./theme";
import {CustomMonacoEditorHandlers} from "./typings";


Expand Down Expand Up @@ -38,12 +43,16 @@ const createMonacoEditor = (
actions: ActionType[],
handlers: CustomMonacoEditorHandlers
): monaco.editor.IStandaloneCodeEditor => {
setupCustomLogLanguage();
setupThemes();

const editor = monaco.editor.create(
editorContainer,
{
// eslint-disable-next-line no-warning-comments
// TODO: Add custom observer to debounce automatic layout
automaticLayout: true,
language: LOG_LANGUAGE_NAME,
maxTokenizationLineLength: 30_000,
mouseWheelZoom: true,
readOnly: true,
Expand Down
9 changes: 9 additions & 0 deletions new-log-viewer/src/components/Editor/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import {

import * as monaco from "monaco-editor/esm/vs/editor/editor.api.js";

import {useColorScheme} from "@mui/joy";

import {StateContext} from "../../contexts/StateContextProvider";
import {
updateWindowUrlHashParams,
Expand Down Expand Up @@ -42,6 +44,8 @@ import "./index.css";
* @return
*/
const Editor = () => {
const {mode, systemMode} = useColorScheme();

const {beginLineNumToLogEventNum, logData, numEvents} = useContext(StateContext);
const {logEventNum} = useContext(UrlContext);

Expand Down Expand Up @@ -185,13 +189,18 @@ const Editor = () => {
beginLineNumToLogEventNum,
]);

const themeName = (("system" === mode) ?
systemMode :
mode) ?? "dark";

return (
<div className={"editor"}>
<MonacoInstance
actions={EDITOR_ACTIONS}
beforeTextUpdate={resetCachedPageSize}
lineNum={lineNum}
text={logData}
themeName={themeName}
onCursorExplicitPosChange={handleCursorExplicitPosChange}
onCustomAction={handleEditorCustomAction}
onMount={handleMount}
Expand Down

0 comments on commit 3b9295e

Please sign in to comment.