-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Use monaco-editor for code display (#173)
- Loading branch information
1 parent
267b024
commit 2bc08f4
Showing
21 changed files
with
279 additions
and
446 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
'@envyjs/webui': minor | ||
--- | ||
|
||
Use monaco-editor for code display |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import { cleanup, render, waitFor } from '@testing-library/react'; | ||
|
||
import CodeDisplay from './CodeDisplay'; | ||
|
||
jest.mock( | ||
'./MonacoEditor', | ||
() => | ||
function MockEditor({ value, language }: any) { | ||
return <div data-test-id={`lang-${language}`}>{value}</div>; | ||
}, | ||
); | ||
|
||
describe('CodeDisplay', () => { | ||
afterEach(() => { | ||
cleanup(); | ||
}); | ||
|
||
it('should parse application/json', async () => { | ||
const data = { foo: 'bar' }; | ||
const { getByTestId } = render(<CodeDisplay data={JSON.stringify(data)} contentType="application/json" />); | ||
|
||
const reactJson = await waitFor(() => getByTestId('lang-json')); | ||
expect(reactJson).toHaveTextContent('{ "foo": "bar" }'); | ||
}); | ||
|
||
it('should parse application/graphql-response+json as json', async () => { | ||
const data = { foo: 'bar' }; | ||
const { getByTestId } = render( | ||
<CodeDisplay data={JSON.stringify(data)} contentType="application/graphql-response+json" />, | ||
); | ||
|
||
const reactJson = await waitFor(() => getByTestId('lang-json')); | ||
expect(reactJson).toHaveTextContent('{ "foo": "bar" }'); | ||
}); | ||
|
||
it('should parse application/json with charset', async () => { | ||
const data = { foo: 'bar' }; | ||
const { getByTestId } = render( | ||
<CodeDisplay data={JSON.stringify(data)} contentType="application/json; ; charset=utf-8" />, | ||
); | ||
|
||
const reactJson = await waitFor(() => getByTestId('lang-json')); | ||
expect(reactJson).toHaveTextContent('{ "foo": "bar" }'); | ||
}); | ||
|
||
it('should use txt language when contentType is undefined', async () => { | ||
const data = { foo: 'bar' }; | ||
const { getByTestId } = render(<CodeDisplay data={JSON.stringify(data)} />); | ||
|
||
const reactJson = await waitFor(() => getByTestId('lang-txt')); | ||
expect(reactJson).toHaveTextContent('{"foo":"bar"}'); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
import { safeParseJson } from '@envyjs/core'; | ||
import formatXml from 'xml-formatter'; | ||
|
||
import Editor, { MonacoEditorProps } from './MonacoEditor'; | ||
|
||
type CodeDisplayProps = { | ||
contentType?: string | string[] | null; | ||
data: string | null | undefined; | ||
}; | ||
|
||
const languageMap: Record<string, MonacoEditorProps['language']> = { | ||
'application/json': 'json', | ||
'application/graphql-response+json': 'json', | ||
'application/xml': 'xml', | ||
}; | ||
|
||
export default function CodeDisplay({ data, contentType }: CodeDisplayProps) { | ||
if (!data) { | ||
return; | ||
} | ||
|
||
// content types can be an array or a string value | ||
// each value in the array or string can be a content type with a charset | ||
// example: [content-type: application/json; charset=utf-8] | ||
let resolvedContentType = Array.isArray(contentType) ? contentType[0] : contentType; | ||
resolvedContentType = resolvedContentType && resolvedContentType.split(';')[0]; | ||
const lang = resolvedContentType ? languageMap[resolvedContentType as string] : 'txt'; | ||
|
||
let value = data; | ||
if (lang === 'json') { | ||
const parseResult = safeParseJson(data); | ||
if (parseResult.value) { | ||
value = JSON.stringify(parseResult.value, null, 2); | ||
} | ||
} else if (lang === 'xml') { | ||
value = formatXml(data, { | ||
indentation: ' ', | ||
lineSeparator: '\n', | ||
collapseContent: true, | ||
whiteSpaceAtEndOfSelfclosingTag: true, | ||
}); | ||
} | ||
|
||
return ( | ||
<div className="w-full h-full"> | ||
<Editor value={value} language={lang} /> | ||
</div> | ||
); | ||
} |
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import { Editor, EditorProps, OnMount } from '@monaco-editor/react'; | ||
import { useEffect, useRef } from 'react'; | ||
import colors from 'tailwindcss/colors'; | ||
|
||
export type MonacoEditorProps = Pick<EditorProps, 'value' | 'language'>; | ||
|
||
const editorOptions: EditorProps['options'] = { | ||
minimap: { | ||
enabled: false, | ||
}, | ||
readOnly: true, | ||
scrollBeyondLastLine: false, | ||
showFoldingControls: 'always', | ||
lineNumbers: 'off', | ||
}; | ||
|
||
export default function MonacoEditor({ value, language }: MonacoEditorProps) { | ||
const editorRef = useRef<Parameters<OnMount>['0'] | null>(null); | ||
|
||
const executeFolding = () => { | ||
if (!editorRef.current) return; | ||
|
||
// fold deeply nested objects | ||
editorRef.current?.trigger('fold', 'editor.foldLevel7', {}); | ||
editorRef.current?.trigger('fold', 'editor.foldLevel6', {}); | ||
editorRef.current?.trigger('fold', 'editor.foldLevel5', {}); | ||
editorRef.current?.trigger('fold', 'editor.foldLevel4', {}); | ||
}; | ||
|
||
const onMount: OnMount = (editor, monaco) => { | ||
editorRef.current = editor; | ||
|
||
monaco.editor.defineTheme('envy', { | ||
base: 'vs', | ||
inherit: true, | ||
colors: { | ||
'editor.background': colors.gray['200'], | ||
'editor.lineHighlightBackground': colors.gray['200'], | ||
}, | ||
rules: [], | ||
}); | ||
monaco.editor.setTheme('envy'); | ||
|
||
executeFolding(); | ||
}; | ||
|
||
useEffect(executeFolding, [value, language]); | ||
|
||
return <Editor value={value} language={language} options={editorOptions} onMount={onMount} />; | ||
} |
Oops, something went wrong.