diff --git a/src/components/CodeEditor/CodeEditor.tsx b/src/components/CodeEditor/CodeEditor.tsx index 2abfd45b..6c503085 100644 --- a/src/components/CodeEditor/CodeEditor.tsx +++ b/src/components/CodeEditor/CodeEditor.tsx @@ -1,5 +1,5 @@ import { useState } from "react"; -import Editor, { EditorProps } from "@monaco-editor/react"; +import Editor, { EditorProps, Monaco } from "@monaco-editor/react"; import type { editor } from "monaco-editor/esm/vs/editor/editor.api"; import { useTheme, Box, BoxProps, AppBar, Toolbar } from "@mui/material"; @@ -72,6 +72,36 @@ export default function CodeEditor({ onValidate?.(markers); }; + const validate = (monaco: Monaco, model: editor.ITextModel) => { + const markers = []; + for (let i = 1; i < model.getLineCount() + 1; i++) { + const range = { + startLineNumber: i, + startColumn: 1, + endLineNumber: i, + endColumn: model.getLineLength(i) + 1, + }; + const line = model.getValueInRange(range); + for (const keyword of ["console.log", "console.warn", "console.error"]) { + const consoleLogIndex = line.indexOf(keyword); + if (consoleLogIndex >= 0) { + markers.push({ + message: `Replace with ${keyword.replace( + "console", + "logging" + )}: Rowy Cloud Logging provides a better experience to view logs. Simply replace 'console' with 'logging'. \n\nhttps://docs.rowy.io/cloud-logs`, + severity: monaco.MarkerSeverity.Warning, + startLineNumber: range.startLineNumber, + endLineNumber: range.endLineNumber, + startColumn: consoleLogIndex + 1, + endColumn: consoleLogIndex + keyword.length + 1, + }); + } + } + } + monaco.editor.setModelMarkers(model, "owner", markers); + }; + return ( { monaco.editor.defineTheme("github-light", githubLightTheme as any); monaco.editor.defineTheme("github-dark", githubDarkTheme as any); + monaco.editor.onDidCreateModel((model) => { + validate(monaco, model); + model.onDidChangeContent(() => { + validate(monaco, model); + }); + }); }} onMount={(editor) => { if (onFocus) editor.onDidFocusEditorWidget(onFocus); diff --git a/src/components/CodeEditor/useMonacoCustomizations.ts b/src/components/CodeEditor/useMonacoCustomizations.ts index e6d55533..d145d72e 100644 --- a/src/components/CodeEditor/useMonacoCustomizations.ts +++ b/src/components/CodeEditor/useMonacoCustomizations.ts @@ -1,9 +1,4 @@ import { useEffect } from "react"; -// import { -// quicktype, -// InputData, -// jsonInputForTargetLanguage, -// } from "quicktype-core"; import { useAtom } from "jotai"; import { @@ -13,15 +8,10 @@ import { } from "@src/atoms/tableScope"; import { useMonaco } from "@monaco-editor/react"; import type { languages } from "monaco-editor/esm/vs/editor/editor.api"; -import githubLightTheme from "./github-light-default.json"; -import githubDarkTheme from "./github-dark-default.json"; import { useTheme } from "@mui/material"; import type { SystemStyleObject, Theme } from "@mui/system"; -// TODO: -// import { getFieldType, getFieldProp } from "@src/components/fields"; - /* eslint-disable import/no-webpack-loader-syntax */ import firestoreDefs from "!!raw-loader!./firestore.d.ts"; import firebaseAuthDefs from "!!raw-loader!./firebaseAuth.d.ts"; @@ -72,7 +62,6 @@ export default function useMonacoCustomizations({ }; }, []); - // Initialize external libs & TypeScript compiler options useEffect(() => { if (!monaco) return; @@ -95,6 +84,8 @@ export default function useMonacoCustomizations({ "ts:filename/utils.d.ts" ); monaco.languages.typescript.javascriptDefaults.addExtraLib(rowyUtilsDefs); + + setLoggingReplacementActions(); } catch (error) { console.error( "An error occurred during initialization of Monaco: ", @@ -135,6 +126,52 @@ export default function useMonacoCustomizations({ } }, [monaco, stringifiedDiagnosticsOptions]); + const setLoggingReplacementActions = () => { + if (!monaco) return; + const { dispose } = monaco.languages.registerCodeActionProvider( + "javascript", + { + provideCodeActions: (model, range, context, token) => { + const actions = context.markers + .filter((error) => { + return error.message.includes("Rowy Cloud Logging"); + }) + .map((error) => { + // first sentence of the message is "Replace with logging.[log/warn/error]" + const firstSentence = error.message.split(":")[0]; + const replacement = firstSentence.split("with ")[1]; + return { + title: firstSentence, + diagnostics: [error], + kind: "quickfix", + edit: { + edits: [ + { + resource: model.uri, + edit: { + range: error, + text: replacement, + }, + }, + ], + }, + isPreferred: true, + }; + }); + return { + actions: actions, + dispose: () => {}, + }; + }, + } + ); + monaco.editor.onWillDisposeModel((model) => { + // dispose code action provider when model is disposed + // this makes sure code actions are not displayed multiple times + dispose(); + }); + }; + const addJsonFieldDefinition = async ( columnKey: string, interfaceName: string