Skip to content

Commit 4b5052c

Browse files
Merge pull request #151 from gridaco/add-monaco-context-menu
Add export as file on monaco context menu
2 parents 84f0f25 + 2c38f70 commit 4b5052c

File tree

7 files changed

+70
-27
lines changed

7 files changed

+70
-27
lines changed

editor/components/code-editor/code-editor.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ export function CodeEditor({
5151
onChange={(v: string, e) => {
5252
onChange?.(filekey, v, e);
5353
}}
54-
defaultLanguage={file.language}
55-
defaultValue={file.raw}
54+
language={file.language}
55+
value={file.raw}
5656
/>
5757
</>
5858
);

editor/components/code-editor/monaco-utils/register.ts

-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import * as monaco from "monaco-editor";
22
import { Monaco, OnMount } from "@monaco-editor/react";
33
import { registerDocumentPrettier } from "@code-editor/prettier-services";
44
import { registerJsxHighlighter } from "@code-editor/jsx-syntax-highlight-services";
5-
65
type CompilerOptions = monaco.languages.typescript.CompilerOptions;
76

87
export const initEditor: OnMount = (editor, monaco) => {

editor/components/code-editor/monaco.tsx

+46-18
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,17 @@
1-
import React, { useRef, useEffect } from "react";
2-
import Editor, {
3-
useMonaco,
4-
Monaco,
5-
OnMount,
6-
OnChange,
7-
} from "@monaco-editor/react";
1+
import React, { useRef } from "react";
2+
import Editor, { OnMount, OnChange } from "@monaco-editor/react";
83
import * as monaco from "monaco-editor/esm/vs/editor/editor.api";
94
import { MonacoEmptyMock } from "./monaco-mock-empty";
105
import { register } from "./monaco-utils";
116
import { __dangerous__lastFormattedValue__global } from "@code-editor/prettier-services";
7+
import { debounce } from "utils/debounce";
8+
import { downloadFile } from "utils/download";
129

1310
type ICodeEditor = monaco.editor.IStandaloneCodeEditor;
1411

1512
export interface MonacoEditorProps {
16-
defaultValue?: string;
17-
defaultLanguage?: string;
13+
value?: string;
14+
language?: string;
1815
onChange?: OnChange;
1916
width?: number | string;
2017
height?: number | string;
@@ -23,16 +20,15 @@ export interface MonacoEditorProps {
2320

2421
export function MonacoEditor(props: MonacoEditorProps) {
2522
const instance = useRef<{ editor: ICodeEditor; format: any } | null>(null);
26-
const activeModel = useRef<any>();
23+
24+
const path = "app." + lang2ext(props.language);
2725

2826
const onMount: OnMount = (editor, monaco) => {
2927
const format = editor.getAction("editor.action.formatDocument");
3028
const rename = editor.getAction("editor.action.rename");
3129

3230
instance.current = { editor, format };
3331

34-
activeModel.current = editor.getModel();
35-
3632
register.initEditor(editor, monaco);
3733

3834
editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyS, function () {
@@ -41,6 +37,7 @@ export function MonacoEditor(props: MonacoEditorProps) {
4137

4238
// disabled. todo: find a way to format on new line, but also with adding new line.
4339
// editor.addCommand(monaco.KeyCode.Enter, function () {
40+
// // add new line via script, then run format
4441
// format.run();
4542
// });
4643

@@ -50,9 +47,24 @@ export function MonacoEditor(props: MonacoEditorProps) {
5047
rename.run();
5148
});
5249

53-
editor.onDidChangeModelContent((e) => {
54-
/* add here */
50+
editor.addAction({
51+
// An unique identifier of the contributed action.
52+
id: "export-module-as-file",
53+
54+
// A label of the action that will be presented to the user.
55+
label: "Export as file",
56+
precondition: null,
57+
keybindingContext: null,
58+
contextMenuGroupId: "navigation",
59+
contextMenuOrder: 1.5,
60+
run: function (ed) {
61+
downloadFile({ data: ed.getModel().getValue(), filename: path });
62+
},
5563
});
64+
65+
editor.onDidChangeModelContent(() =>
66+
debounce(() => editor.saveViewState(), 200)
67+
);
5668
};
5769

5870
return (
@@ -61,11 +73,10 @@ export function MonacoEditor(props: MonacoEditorProps) {
6173
onMount={onMount}
6274
width={props.width}
6375
height={props.height}
64-
defaultLanguage={
65-
pollyfill_language(props.defaultLanguage) ?? "typescript"
66-
}
76+
language={pollyfill_language(props.language) ?? "typescript"}
77+
path={path}
6778
loading={<MonacoEmptyMock l={5} />}
68-
defaultValue={props.defaultValue ?? "// no content"}
79+
value={props.value ?? "// no content"}
6980
theme="vs-dark"
7081
onChange={(...v) => {
7182
if (v[0] === __dangerous__lastFormattedValue__global) {
@@ -84,6 +95,23 @@ export function MonacoEditor(props: MonacoEditorProps) {
8495
);
8596
}
8697

98+
const lang2ext = (lang: string) => {
99+
switch (lang) {
100+
case "typescript":
101+
return "ts";
102+
case "javascript":
103+
return "js";
104+
case "tsx":
105+
return "tsx";
106+
case "jsx":
107+
return "jsx";
108+
case "dart":
109+
return "dart";
110+
default:
111+
return lang;
112+
}
113+
};
114+
87115
const pollyfill_language = (lang: string) => {
88116
switch (lang) {
89117
case "tsx":

editor/pages/figma/inspect-frame.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ export default function InspectAutolayout() {
2424
<MonacoEditor
2525
key={figma?.id}
2626
height="100vh"
27-
defaultLanguage="json"
28-
defaultValue={JSON.stringify(inspectionTarget, null, 2)}
27+
language="json"
28+
value={JSON.stringify(inspectionTarget, null, 2)}
2929
/>
3030
</>
3131
);

editor/pages/figma/inspect-raw.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ export default function InspectRaw() {
2020
<MonacoEditor
2121
key={figma.id}
2222
height="100vh"
23-
defaultLanguage="json"
24-
defaultValue={JSON.stringify(figma, null, 2)}
23+
language="json"
24+
value={JSON.stringify(figma, null, 2)}
2525
/>
2626
</>
2727
);

editor/scaffolds/code/index.tsx

+3-2
Original file line numberDiff line numberDiff line change
@@ -193,10 +193,11 @@ export function CodeSegment() {
193193
files={
194194
code
195195
? {
196-
"index.tsx": {
196+
// TODO: make this to match framework
197+
"App.tsx": {
197198
raw: code.raw,
198199
language: framework_config.language,
199-
name: "index.tsx",
200+
name: "App.tsx",
200201
},
201202
}
202203
: {

editor/utils/download/index.ts

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
export function downloadFile({
2+
data,
3+
filename,
4+
}: {
5+
data: string;
6+
filename: string;
7+
}) {
8+
var blob = new Blob([data], { type: "text/txt" });
9+
var csvURL = window.URL.createObjectURL(blob);
10+
const tempLink = document.createElement("a");
11+
tempLink.href = csvURL;
12+
tempLink.setAttribute("download", filename);
13+
tempLink.click();
14+
tempLink.remove();
15+
}

0 commit comments

Comments
 (0)