diff --git a/editor/components/code-editor/code-editor.tsx b/editor/components/code-editor/code-editor.tsx index 33665d02..bfefce49 100644 --- a/editor/components/code-editor/code-editor.tsx +++ b/editor/components/code-editor/code-editor.tsx @@ -51,8 +51,8 @@ export function CodeEditor({ onChange={(v: string, e) => { onChange?.(filekey, v, e); }} - defaultLanguage={file.language} - defaultValue={file.raw} + language={file.language} + value={file.raw} /> ); diff --git a/editor/components/code-editor/monaco-utils/register.ts b/editor/components/code-editor/monaco-utils/register.ts index 354982d0..b56784c7 100644 --- a/editor/components/code-editor/monaco-utils/register.ts +++ b/editor/components/code-editor/monaco-utils/register.ts @@ -2,7 +2,6 @@ import * as monaco from "monaco-editor"; import { Monaco, OnMount } from "@monaco-editor/react"; import { registerDocumentPrettier } from "@code-editor/prettier-services"; import { registerJsxHighlighter } from "@code-editor/jsx-syntax-highlight-services"; - type CompilerOptions = monaco.languages.typescript.CompilerOptions; export const initEditor: OnMount = (editor, monaco) => { diff --git a/editor/components/code-editor/monaco.tsx b/editor/components/code-editor/monaco.tsx index b949eb17..919011a0 100644 --- a/editor/components/code-editor/monaco.tsx +++ b/editor/components/code-editor/monaco.tsx @@ -1,20 +1,17 @@ -import React, { useRef, useEffect } from "react"; -import Editor, { - useMonaco, - Monaco, - OnMount, - OnChange, -} from "@monaco-editor/react"; +import React, { useRef } from "react"; +import Editor, { OnMount, OnChange } 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"; import { __dangerous__lastFormattedValue__global } from "@code-editor/prettier-services"; +import { debounce } from "utils/debounce"; +import { downloadFile } from "utils/download"; type ICodeEditor = monaco.editor.IStandaloneCodeEditor; export interface MonacoEditorProps { - defaultValue?: string; - defaultLanguage?: string; + value?: string; + language?: string; onChange?: OnChange; width?: number | string; height?: number | string; @@ -23,7 +20,8 @@ export interface MonacoEditorProps { export function MonacoEditor(props: MonacoEditorProps) { const instance = useRef<{ editor: ICodeEditor; format: any } | null>(null); - const activeModel = useRef(); + + const path = "app." + lang2ext(props.language); const onMount: OnMount = (editor, monaco) => { const format = editor.getAction("editor.action.formatDocument"); @@ -31,8 +29,6 @@ export function MonacoEditor(props: MonacoEditorProps) { instance.current = { editor, format }; - activeModel.current = editor.getModel(); - register.initEditor(editor, monaco); editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyS, function () { @@ -41,6 +37,7 @@ export function MonacoEditor(props: MonacoEditorProps) { // disabled. todo: find a way to format on new line, but also with adding new line. // editor.addCommand(monaco.KeyCode.Enter, function () { + // // add new line via script, then run format // format.run(); // }); @@ -50,9 +47,24 @@ export function MonacoEditor(props: MonacoEditorProps) { rename.run(); }); - editor.onDidChangeModelContent((e) => { - /* add here */ + editor.addAction({ + // An unique identifier of the contributed action. + id: "export-module-as-file", + + // A label of the action that will be presented to the user. + label: "Export as file", + precondition: null, + keybindingContext: null, + contextMenuGroupId: "navigation", + contextMenuOrder: 1.5, + run: function (ed) { + downloadFile({ data: ed.getModel().getValue(), filename: path }); + }, }); + + editor.onDidChangeModelContent(() => + debounce(() => editor.saveViewState(), 200) + ); }; return ( @@ -61,11 +73,10 @@ export function MonacoEditor(props: MonacoEditorProps) { onMount={onMount} width={props.width} height={props.height} - defaultLanguage={ - pollyfill_language(props.defaultLanguage) ?? "typescript" - } + language={pollyfill_language(props.language) ?? "typescript"} + path={path} loading={} - defaultValue={props.defaultValue ?? "// no content"} + value={props.value ?? "// no content"} theme="vs-dark" onChange={(...v) => { if (v[0] === __dangerous__lastFormattedValue__global) { @@ -84,6 +95,23 @@ export function MonacoEditor(props: MonacoEditorProps) { ); } +const lang2ext = (lang: string) => { + switch (lang) { + case "typescript": + return "ts"; + case "javascript": + return "js"; + case "tsx": + return "tsx"; + case "jsx": + return "jsx"; + case "dart": + return "dart"; + default: + return lang; + } +}; + const pollyfill_language = (lang: string) => { switch (lang) { case "tsx": diff --git a/editor/pages/figma/inspect-frame.tsx b/editor/pages/figma/inspect-frame.tsx index e1a2f037..7222de65 100644 --- a/editor/pages/figma/inspect-frame.tsx +++ b/editor/pages/figma/inspect-frame.tsx @@ -24,8 +24,8 @@ export default function InspectAutolayout() { ); diff --git a/editor/pages/figma/inspect-raw.tsx b/editor/pages/figma/inspect-raw.tsx index 7acd05a1..ece227dc 100644 --- a/editor/pages/figma/inspect-raw.tsx +++ b/editor/pages/figma/inspect-raw.tsx @@ -20,8 +20,8 @@ export default function InspectRaw() { ); diff --git a/editor/scaffolds/code/index.tsx b/editor/scaffolds/code/index.tsx index 207f3b24..11a41cf6 100644 --- a/editor/scaffolds/code/index.tsx +++ b/editor/scaffolds/code/index.tsx @@ -193,10 +193,11 @@ export function CodeSegment() { files={ code ? { - "index.tsx": { + // TODO: make this to match framework + "App.tsx": { raw: code.raw, language: framework_config.language, - name: "index.tsx", + name: "App.tsx", }, } : { diff --git a/editor/utils/download/index.ts b/editor/utils/download/index.ts new file mode 100644 index 00000000..8d6f4568 --- /dev/null +++ b/editor/utils/download/index.ts @@ -0,0 +1,15 @@ +export function downloadFile({ + data, + filename, +}: { + data: string; + filename: string; +}) { + var blob = new Blob([data], { type: "text/txt" }); + var csvURL = window.URL.createObjectURL(blob); + const tempLink = document.createElement("a"); + tempLink.href = csvURL; + tempLink.setAttribute("download", filename); + tempLink.click(); + tempLink.remove(); +}