import React, { useCallback, useEffect, useState } from 'react'; import ace, { Editor } from 'brace'; import styled from 'styled-components/macro'; import tw from 'twin.macro'; import Select from '@/components/elements/Select'; // @ts-ignore require('brace/ext/modelist'); require('ayu-ace/mirage'); const EditorContainer = styled.div` min-height: 16rem; height: calc(100vh - 20rem); ${tw`relative`}; #editor { ${tw`rounded h-full`}; } `; const modes: { [k: string]: string } = { assembly_x86: 'Assembly (x86)', c_cpp: 'C++', coffee: 'Coffeescript', css: 'CSS', dockerfile: 'Dockerfile', golang: 'Go', html: 'HTML', ini: 'Ini', java: 'Java', javascript: 'Javascript', json: 'JSON', kotlin: 'Kotlin', lua: 'Luascript', perl: 'Perl', php: 'PHP', properties: 'Properties', python: 'Python', ruby: 'Ruby', plain_text: 'Plaintext', toml: 'TOML', typescript: 'Typescript', xml: 'XML', yaml: 'YAML', }; Object.keys(modes).forEach(mode => require(`brace/mode/${mode}`)); export interface Props { style?: React.CSSProperties; initialContent?: string; initialModePath?: string; fetchContent: (callback: () => Promise) => void; onContentSaved: (content: string) => void; } export default ({ style, initialContent, initialModePath, fetchContent, onContentSaved }: Props) => { const [ mode, setMode ] = useState('ace/mode/plain_text'); const [ editor, setEditor ] = useState(); const ref = useCallback(node => { if (node) { setEditor(ace.edit('editor')); } }, []); useEffect(() => { editor && editor.session.setMode(mode); }, [ editor, mode ]); useEffect(() => { editor && editor.session.setValue(initialContent || ''); }, [ editor, initialContent ]); useEffect(() => { if (initialModePath) { const modelist = ace.acequire('ace/ext/modelist'); if (modelist) { setMode(modelist.getModeForPath(initialModePath).mode); } } }, [ initialModePath ]); useEffect(() => { if (!editor) { fetchContent(() => Promise.reject(new Error('no editor session has been configured'))); return; } editor.setTheme('ace/theme/ayu-mirage'); editor.$blockScrolling = Infinity; editor.container.style.lineHeight = '1.375rem'; editor.container.style.fontWeight = '500'; editor.renderer.updateFontSize(); editor.renderer.setShowPrintMargin(false); editor.session.setTabSize(4); editor.session.setUseSoftTabs(true); editor.commands.addCommand({ name: 'Save', bindKey: { win: 'Ctrl-s', mac: 'Command-s' }, exec: (editor: Editor) => onContentSaved(editor.session.getValue()), }); fetchContent(() => Promise.resolve(editor.session.getValue())); }, [ editor, fetchContent, onContentSaved ]); return (
); };