Feat(CodeEditor): Support jsx highlight

Chang theme of monaco. Support jsx highlight.
This commit is contained in:
2024-10-23 15:44:25 +08:00
parent 1cdd1e5a93
commit a467ad2021
10 changed files with 484 additions and 60 deletions

View File

@@ -1,7 +1,6 @@
import { editor, IPosition, Selection } from 'monaco-editor'
import ScrollType = editor.ScrollType
import { Monaco } from '@monaco-editor/react'
import { getWorker, MonacoJsxSyntaxHighlight } from 'monaco-jsx-syntax-highlight'
import { createATA, TypeHelper } from '@/components/Playground/CodeEditor/Editor/ata'
export const useEditor = () => {
@@ -28,18 +27,6 @@ export const useEditor = () => {
}
}
const loadJsxSyntaxHighlight = (editor: editor.IStandaloneCodeEditor, monaco: Monaco) => {
const monacoJsxSyntaxHighlight = new MonacoJsxSyntaxHighlight(getWorker(), monaco)
const { highlighter, dispose } = monacoJsxSyntaxHighlight.highlighterBuilder({ editor })
editor.onDidChangeModelContent(() => {
highlighter()
})
highlighter()
return { highlighter, dispose }
}
const autoLoadExtraLib = async (
editor: editor.IStandaloneCodeEditor,
monaco: Monaco,
@@ -68,7 +55,6 @@ export const useEditor = () => {
return {
doOpenEditor,
loadJsxSyntaxHighlight,
autoLoadExtraLib
}
}

View File

@@ -13,27 +13,7 @@ const rotate = keyframes`
export default createStyles(() => ({
root: {
position: 'relative',
height: 0,
'.monaco-editor-light': {
height: '100%',
overflow: 'hidden',
backgroundColor: 'var(--border)',
'.jsx-tag-angle-bracket': { color: '#800000' },
'.jsx-text': { color: '#000' },
'.jsx-tag-name': { color: '#800000' },
'.jsx-tag-attribute-key': { color: '#f00' }
},
'.monaco-editor-dark': {
height: '100%',
overflow: 'hidden',
backgroundColor: 'var(--border)',
'.jsx-tag-angle-bracket': { color: '#808080' },
'.jsx-text': { color: '#d4d4d4' },
'.jsx-tag-name': { color: '#569cd6' },
'.jsx-tag-attribute-key': { color: '#9cdcfe' }
}
height: 0
},
loading: {

View File

@@ -1,5 +1,7 @@
import { editor, Selection } from 'monaco-editor'
import MonacoEditor, { Monaco } from '@monaco-editor/react'
import { shikiToMonaco } from '@shikijs/monaco'
import { createHighlighter } from 'shiki'
import useStyles from '@/components/Playground/CodeEditor/Editor/index.style'
import '@/components/Playground/CodeEditor/Editor/loader'
import { IEditorOptions, IFiles, ITsconfig } from '@/components/Playground/shared'
@@ -38,18 +40,19 @@ const Editor = ({
const { styles } = useStyles()
const editorRef = useRef<editor.IStandaloneCodeEditor>()
const monacoRef = useRef<Monaco>()
const { doOpenEditor, loadJsxSyntaxHighlight, autoLoadExtraLib } = useEditor()
const jsxSyntaxHighlightRef = useRef<{
highlighter: (code?: string | undefined) => void
dispose: () => void
}>({
highlighter: () => undefined,
dispose: () => undefined
})
const { doOpenEditor, autoLoadExtraLib } = useEditor()
const { total, finished, onWatch } = useTypesProgress()
const file = files[selectedFileName] || { name: 'Untitled' }
const handleOnEditorWillMount = (monaco: Monaco) => {
createHighlighter({
themes: ['vitesse-light', 'vitesse-dark'],
langs: ['javascript', 'jsx', 'typescript', 'tsx', 'css', 'json', 'xml']
}).then((highlighter) => {
shikiToMonaco(highlighter, monaco)
monaco.editor.setTheme(isDarkMode ? 'vitesse-dark' : 'vitesse-light')
})
monaco.languages.json.jsonDefaults.setDiagnosticsOptions(tsconfigJsonDiagnosticsOptions)
tsconfig &&
monaco.languages.typescript.typescriptDefaults.setCompilerOptions(
@@ -91,7 +94,6 @@ const Editor = ({
}
}
jsxSyntaxHighlightRef.current = loadJsxSyntaxHighlight(editor, monaco)
extraLibs.forEach((item) =>
monaco.languages.typescript.typescriptDefaults.addExtraLib(item.content, item.path)
)
@@ -99,9 +101,12 @@ const Editor = ({
void autoLoadExtraLib(editor, monaco, file.value, onWatch)
}
useEffect(() => {
monacoRef.current?.editor.setTheme(isDarkMode ? 'vitesse-dark' : 'vitesse-light')
}, [isDarkMode])
useEffect(() => {
editorRef.current?.focus()
jsxSyntaxHighlightRef?.current?.highlighter?.()
}, [file.name])
useEffect(() => {
@@ -115,9 +120,8 @@ const Editor = ({
<>
<div className={styles.root}>
<MonacoEditor
theme={isDarkMode ? 'vs-dark' : 'light'}
theme={isDarkMode ? 'vitesse-dark' : 'vitesse-light'}
path={file.name}
className={`monaco-editor-${isDarkMode ? 'dark' : 'light'}`}
language={file.language}
value={file.value}
onChange={onChange}

View File

@@ -1,17 +1,17 @@
import MonacoEditor from '@monaco-editor/react'
import { Loader } from 'esbuild-wasm'
import useStyles from '@/components/Playground/Output/Transform/index.style'
import { IFile, ITheme } from '@/components/Playground/shared'
import { IFile } from '@/components/Playground/shared'
import { cssToJsFromFile, jsonToJsFromFile } from '@/components/Playground/files'
import Compiler from '@/components/Playground/compiler'
import { MonacoEditorConfig } from '@/components/Playground/CodeEditor/Editor/monacoConfig'
interface OutputProps {
isDarkMode?: boolean
file: IFile
theme?: ITheme
}
const Transform = ({ file, theme }: OutputProps) => {
const Transform = ({ isDarkMode, file }: OutputProps) => {
const { styles } = useStyles()
const [compiledCode, setCompiledCode] = useState('')
const [errorMsg, setErrorMsg] = useState('')
@@ -60,7 +60,7 @@ const Transform = ({ file, theme }: OutputProps) => {
return (
<div className={styles.root}>
<MonacoEditor
theme={theme}
theme={isDarkMode ? 'vitesse-dark' : 'vitesse-light'}
language={'javascript'}
value={compiledCode}
options={{ ...MonacoEditorConfig, readOnly: true }}

View File

@@ -5,6 +5,7 @@ import Transform from '@/components/Playground/Output/Transform'
import Preview from '@/components/Playground/Output/Preview'
interface OutputProps {
isDarkMode?: boolean
files: IFiles
selectedFileName: string
importMap: IImportMap
@@ -15,6 +16,7 @@ interface OutputProps {
}
const Output = ({
isDarkMode,
files,
selectedFileName,
importMap,
@@ -47,7 +49,9 @@ const Output = ({
mobileMode={mobileMode}
/>
)}
{selectedTab === 'Transform' && <Transform file={files[selectedFileName]} />}
{selectedTab === 'Transform' && (
<Transform isDarkMode={isDarkMode} file={files[selectedFileName]} />
)}
</FlexBox>
)
}

View File

@@ -105,6 +105,7 @@ const Playground = ({
onSelectedFileChange={setSelectedFileName}
/>
<Output
isDarkMode={isDarkMode}
files={files}
selectedFileName={selectedFileName}
importMap={importMap!}

View File

@@ -20,6 +20,4 @@ export interface ITsconfig {
compilerOptions: CompilerOptions
}
export type ITheme = 'light' | 'vs-dark'
export type IEditorOptions = editor.IStandaloneEditorConstructionOptions