Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions editor/components/code-editor/monaco-utils/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * as register from "./register";
60 changes: 60 additions & 0 deletions editor/components/code-editor/monaco-utils/register-jsx.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { Monaco } from "@monaco-editor/react";
import { createWorkerQueue } from "../../../workers";

import type { editor } from "monaco-editor";
export function registerJsxHighlighter(
editor: editor.IStandaloneCodeEditor,
monaco: Monaco
) {
const { worker: syntaxWorker } = createWorkerQueue(
new Worker(
new URL(
"../../../workers/monaco-syntax-highlight/syntax-highlight.worker.js",
import.meta.url
)
)
);

const highlightHandler = () => {
const title = "app.js";
const model = editor.getModel();
const version = model?.getVersionId();
const lang = model?.getLanguageId();

if (lang === "javascript" || "typescript") {
const code = model?.getValue();
syntaxWorker.postMessage({
code,
title,
version,
});
}
};

editor.onDidChangeModel(highlightHandler);

editor.onDidChangeModelContent(highlightHandler);

let oldDecor = editor.getModel()?.getAllDecorations();

syntaxWorker.addEventListener("message", (event) => {
const { classifications } = event.data;

requestAnimationFrame(() => {
const decorations = classifications.map((classification) => ({
range: new monaco.Range(
classification.startLine,
classification.start,
classification.endLine,
classification.end
),
options: {
//
},
}));

// @ts-ignore
oldDecor = editor.deltaDecorations(oldDecor, decorations);
});
});
}
74 changes: 74 additions & 0 deletions editor/components/code-editor/monaco-utils/register-prettier.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import * as monaco from "monaco-editor";
import { createWorkerQueue } from "../../../workers";

export function registerDocumentPrettier(editor, monaco) {
const disposables: monaco.IDisposable[] = [];
let prettierWorker;

const formattingEditProvider = {
async provideDocumentFormattingEdits(model, _options, _token) {
if (!prettierWorker) {
prettierWorker = createWorkerQueue(
new Worker(
new URL(
"../../../workers/prettier/prettier.worker.js",
import.meta.url
)
)
);
}

const { canceled, error, pretty } = await prettierWorker?.emit({
text: model.getValue(),
language: model._languageId,
});

if (canceled || error) return [];

return [
{
range: model.getFullModelRange(),
text: pretty,
},
];
},
};

disposables.push(
monaco.languages.registerDocumentFormattingEditProvider(
"javascript",
formattingEditProvider
)
);

disposables.push(
monaco.languages.registerDocumentFormattingEditProvider(
"html",
formattingEditProvider
)
);

disposables.push(
monaco.languages.registerDocumentFormattingEditProvider(
"css",
formattingEditProvider
)
);
disposables.push(
monaco.languages.registerDocumentFormattingEditProvider(
"typescript",
formattingEditProvider
)
);

editor.getAction("editor.action.formatDocument").run();

return {
dispose() {
disposables.forEach((disposable) => disposable.dispose());
if (prettierWorker) {
prettierWorker.terminate();
}
},
};
}
63 changes: 63 additions & 0 deletions editor/components/code-editor/monaco-utils/register-typings.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { Monaco } from "@monaco-editor/react";

export function registerTypesWorker(monaco: Monaco) {
const disposables: any = [];
let typesWorker;

const dependencies = {
react: "@latest",
"react-dom": "@latest",
axios: "@latest",
};

if (!typesWorker) {
typesWorker = new Worker(
new URL(
"../../../workers/fetch-types/fetch-types.worker.js",
import.meta.url
)
);
}

Object.keys(dependencies).forEach((name) => {
typesWorker.postMessage({
name,
version: dependencies[name],
});
});

const createModule = (names) => {
const temp = names.map((el) => `export * from './${el}'`);
return temp.join("\n");
};

typesWorker.addEventListener("message", (event) => {
// name,
// version,
// typings: result,
const key = `node_modules/${event.data.name}/index.d.ts`;
const source = event.data.typings[key];

// const path = `${MONACO_LIB_PREFIX}${event.data.name}`;
const libUri = `file:///node_modules/@types/${event.data.name}/index.d.ts`;

disposables.push(
monaco.languages.typescript.javascriptDefaults.addExtraLib(source, libUri)
);
disposables.push(
monaco.languages.typescript.typescriptDefaults.addExtraLib(source, libUri)
);

// When resolving definitions and references, the editor will try to use created models.
// Creating a model for the library allows "peek definition/references" commands to work with the library.
});

return {
dispose() {
disposables.forEach((d) => d.dispose());
if (typesWorker) {
typesWorker.terminate();
}
},
};
}
62 changes: 62 additions & 0 deletions editor/components/code-editor/monaco-utils/register.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import * as monaco from "monaco-editor";
import { Monaco, OnMount } from "@monaco-editor/react";
import { registerDocumentPrettier } from "./register-prettier";
import { registerJsxHighlighter } from "./register-jsx";
import { registerTypesWorker } from "./register-typings";

type CompilerOptions = monaco.languages.typescript.CompilerOptions;

export const initEditor: OnMount = (editor, monaco) => {
registerJsxHighlighter(editor, monaco);
registerDocumentPrettier(editor, monaco);
};

export const initMonaco = (monaco: Monaco) => {
baseConfigure(monaco);

const { dispose } = registerTypesWorker(monaco);

// Dispose all disposables and terminate all workers
return () => {
dispose();
};
};

const baseConfigure = (monaco: Monaco) => {
monaco.languages.typescript.typescriptDefaults.setMaximumWorkerIdleTime(-1);
monaco.languages.typescript.javascriptDefaults.setMaximumWorkerIdleTime(-1);

monaco.languages.typescript.typescriptDefaults.setEagerModelSync(true);
monaco.languages.typescript.javascriptDefaults.setEagerModelSync(true);
monaco.languages.typescript.javascriptDefaults.setDiagnosticsOptions({
noSemanticValidation: true,
noSyntaxValidation: false,
});

// compiler options
monaco.languages.typescript.javascriptDefaults.setCompilerOptions({
target: monaco.languages.typescript.ScriptTarget.Latest,
allowNonTsExtensions: true,
});

/**
* Configure the typescript compiler to detect JSX and load type definitions
*/

const opts: CompilerOptions = {
allowJs: true,
allowSyntheticDefaultImports: true,
alwaysStrict: true,
moduleResolution: monaco.languages.typescript.ModuleResolutionKind.NodeJs,
noEmit: true,
reactNamespace: "React",
typeRoots: ["node_modules/@types"],
jsx: monaco.languages.typescript.JsxEmit.React,
allowNonTsExtensions: true,
target: monaco.languages.typescript.ScriptTarget.ES2016,
jsxFactory: "React.createElement",
};

monaco.languages.typescript.typescriptDefaults.setCompilerOptions(opts);
monaco.languages.typescript.javascriptDefaults.setCompilerOptions(opts);
};
41 changes: 38 additions & 3 deletions editor/components/code-editor/monaco.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import React, { useEffect } from "react";
import Editor, { useMonaco, Monaco } from "@monaco-editor/react";
import React, { useRef, useEffect } from "react";
import Editor, { useMonaco, Monaco, OnMount } from "@monaco-editor/react";
import * as monaco from "monaco-editor/esm/vs/editor/editor.api";
import { MonacoEmptyMock } from "./monaco-mock-empty";
import { register } from "./monaco-utils";

type ICodeEditor = monaco.editor.IStandaloneCodeEditor;

export interface MonacoEditorProps {
defaultValue?: string;
Expand All @@ -12,16 +15,47 @@ export interface MonacoEditorProps {
}

export function MonacoEditor(props: MonacoEditorProps) {
const instance = useRef<{ editor: ICodeEditor; format: any } | null>(null);
const activeModel = useRef<any>();

const monaco: Monaco = useMonaco();
useEffect(() => {
if (monaco) {
setup_react_support(monaco);
// monaco.mo
}
}, [monaco]);

const onMount: OnMount = (editor, monaco) => {
const format = editor.getAction("editor.action.formatDocument");
instance.current = { editor, format };

activeModel.current = editor.getModel();

register.initEditor(editor, monaco);

editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyS, function () {
format.run();
});

// disabled. todo: find a way to format on new line, but also with adding new line.
// editor.addCommand(monaco.KeyCode.Enter, function () {
// format.run();
// });

editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyR, function () {
// don't reload the entire page
// do nothing.
});

editor.onDidChangeModelContent(() => {
/* add here */
});
};

return (
<Editor
beforeMount={register.initMonaco}
onMount={onMount}
width={props.width}
height={props.height}
defaultLanguage={
Expand All @@ -33,6 +67,7 @@ export function MonacoEditor(props: MonacoEditorProps) {
options={{
...props.options,
// overrided default options
wordWrap: "off",
unusualLineTerminators: "off",
}}
/>
Expand Down
7 changes: 4 additions & 3 deletions editor/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"@material-ui/icons": "^4.11.2",
"@material-ui/lab": "^4.0.0-alpha.60",
"@modulz/design-system": "^0.6.1",
"@monaco-editor/react": "^4.1.3",
"@monaco-editor/react": "^4.4.1",
"@reflect-blocks/figma-embed": "^0.0.5",
"@use-gesture/react": "^10.2.2",
"@visx/gradient": "^1.7.0",
Expand All @@ -39,8 +39,9 @@
"framer-motion": "^5.3.1",
"idb": "^6.1.2",
"moment": "^2.29.1",
"monaco-editor": "^0.24.0",
"monaco-editor": "^0.33.0",
"next": "^12.1.4",
"p-queue": "^7.2.0",
"pouchdb-adapter-idb": "^7.2.2",
"re-resizable": "^6.9.1",
"react": "^18.0.0",
Expand Down Expand Up @@ -70,4 +71,4 @@
"raw-loader": "^4.0.2",
"typescript": "^4.2.3"
}
}
}
Loading