Skip to content

Commit

Permalink
Merge branch 'alpha'
Browse files Browse the repository at this point in the history
  • Loading branch information
petyosi committed Apr 22, 2024
2 parents 6c05223 + 906caa6 commit d730670
Show file tree
Hide file tree
Showing 9 changed files with 466 additions and 102 deletions.
367 changes: 334 additions & 33 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"license": "MIT",
"dependencies": {
"@codemirror/lang-markdown": "^6.2.3",
"@codemirror/language-data": "^6.5.1",
"@codemirror/merge": "^6.4.0",
"@codemirror/state": "^6.4.0",
"@codemirror/view": "^6.23.0",
Expand Down
2 changes: 1 addition & 1 deletion src/examples/assets/code-blocks.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Blocks of code

JavaScript:

```js
```jsx
export default function App() {
return <h1>Hello world from a markdown</h1>
}
Expand Down
6 changes: 5 additions & 1 deletion src/examples/basics.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import codeBlocksMarkdown from './assets/code-blocks.md?raw'
import imageMarkdown from './assets/image.md?raw'
import jsxMarkdown from './assets/jsx.md?raw'
import tableMarkdown from './assets/table.md?raw'
import { basicDark } from 'cm6-theme-basic-dark'

import { virtuosoSampleSandpackConfig } from './_boilerplate'

Expand Down Expand Up @@ -226,7 +227,10 @@ export function CodeBlock() {
plugins={[
codeBlockPlugin({ codeBlockEditorDescriptors: [PlainTextCodeEditorDescriptor] }),
sandpackPlugin({ sandpackConfig: virtuosoSampleSandpackConfig }),
codeMirrorPlugin({ codeBlockLanguages: { js: 'JavaScript', css: 'CSS' } })
codeMirrorPlugin({
codeBlockLanguages: { jsx: 'JavaScript (react)', js: 'JavaScript', css: 'CSS' }
// codeMirrorExtensions: [basicDark]
})
]}
/>
)
Expand Down
52 changes: 25 additions & 27 deletions src/plugins/codeblock/CodeBlockNode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -168,33 +168,31 @@ const CodeBlockEditorContextProvider: React.FC<{
lexicalNode: CodeBlockNode
children: React.ReactNode
}> = ({ parentEditor, lexicalNode, children }) => {
return (
<CodeBlockEditorContext.Provider
value={{
lexicalNode,
setCode: (code: string) => {
parentEditor.update(() => {
lexicalNode.setCode(code)
setTimeout(() => {
parentEditor.dispatchCommand(NESTED_EDITOR_UPDATED_COMMAND, undefined)
}, 0)
})
},
setLanguage: (language: string) => {
parentEditor.update(() => {
lexicalNode.setLanguage(language)
})
},
setMeta: (meta: string) => {
parentEditor.update(() => {
lexicalNode.setMeta(meta)
})
}
}}
>
{children}
</CodeBlockEditorContext.Provider>
)
const contextValue = React.useMemo(() => {
return {
lexicalNode,
setCode: (code: string) => {
parentEditor.update(() => {
lexicalNode.setCode(code)
setTimeout(() => {
parentEditor.dispatchCommand(NESTED_EDITOR_UPDATED_COMMAND, undefined)
}, 0)
})
},
setLanguage: (language: string) => {
parentEditor.update(() => {
lexicalNode.setLanguage(language)
})
},
setMeta: (meta: string) => {
parentEditor.update(() => {
lexicalNode.setMeta(meta)
})
}
}
}, [lexicalNode, parentEditor])

return <CodeBlockEditorContext.Provider value={contextValue}>{children}</CodeBlockEditorContext.Provider>
}

/**
Expand Down
88 changes: 66 additions & 22 deletions src/plugins/codemirror/CodeMirrorEditor.tsx
Original file line number Diff line number Diff line change
@@ -1,43 +1,87 @@
import { SandpackProvider, CodeEditor as TheEditorFromSandpack } from '@codesandbox/sandpack-react'
import React from 'react'
import styles from '../../styles/ui.module.css'
import { CodeBlockEditorProps } from '../codeblock'
import { useCodeBlockEditorContext } from '../codeblock/CodeBlockNode'
import { readOnly$ } from '../core'
import { useCodeMirrorRef } from '../sandpack/useCodeMirrorRef'
import { useCellValues } from '@mdxeditor/gurx'
import { codeMirrorTheme$ } from '.'

import { EditorState, Extension } from '@codemirror/state'
import { EditorView, lineNumbers } from '@codemirror/view'
import { basicLight } from 'cm6-theme-basic-light'
import { basicSetup } from 'codemirror'
import { languages } from '@codemirror/language-data'
import { useCodeMirrorRef } from '../sandpack/useCodeMirrorRef'
import { codeMirrorAutoLoadLanguageSupport$, codeMirrorExtensions$ } from '.'

export const COMMON_STATE_CONFIG_EXTENSIONS: Extension[] = []

export const CodeMirrorEditor = ({ language, nodeKey, code, focusEmitter }: CodeBlockEditorProps) => {
const codeMirrorRef = useCodeMirrorRef(nodeKey, 'codeblock', 'jsx', focusEmitter)
const [readOnly, theme] = useCellValues(readOnly$, codeMirrorTheme$)
const [readOnly, codeMirrorExtensions, autoLoadLanguageSupport] = useCellValues(
readOnly$,
codeMirrorExtensions$,
codeMirrorAutoLoadLanguageSupport$
)

const codeMirrorRef = useCodeMirrorRef(nodeKey, 'codeblock', language, focusEmitter)
const { setCode } = useCodeBlockEditorContext()
const editorViewRef = React.useRef<EditorView | null>(null)
const elRef = React.useRef<HTMLDivElement | null>(null)

const setCodeRef = React.useRef(setCode)
setCodeRef.current = setCode
codeMirrorRef.current = {
getCodemirror: () => editorViewRef.current!
}

React.useEffect(() => {
codeMirrorRef.current?.getCodemirror()?.dom.addEventListener('paste', (e) => {
e.stopPropagation()
})
}, [codeMirrorRef, language])
void (async () => {
const extensions = [
...codeMirrorExtensions,
basicSetup,
basicLight,
lineNumbers(),
EditorView.lineWrapping,
EditorView.updateListener.of(({ state }) => {
setCodeRef.current(state.doc.toString())
})
]
if (readOnly) {
extensions.push(EditorState.readOnly.of(true))
}
if (language !== '' && autoLoadLanguageSupport) {
const languageData = languages.find((l) => {
return l.name === language || l.alias.includes(language) || l.extensions.includes(language)
})
if (languageData) {
try {
const languageSupport = await languageData.load()
extensions.push(languageSupport.extension)
} catch (e) {
console.warn('failed to load language support for', language)
}
}
}
elRef.current!.innerHTML = ''
editorViewRef.current = new EditorView({
parent: elRef.current!,
state: EditorState.create({ doc: code, extensions })
})
})()
return () => {
editorViewRef.current?.destroy()
editorViewRef.current = null
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [readOnly, language])

return (
<div
className={styles.sandpackWrapper}
className={styles.codeMirrorWrapper}
onKeyDown={(e) => {
e.stopPropagation()
}}
>
<SandpackProvider theme={theme}>
<TheEditorFromSandpack
readOnly={readOnly}
showLineNumbers
initMode="immediate"
key={language}
filePath={`file.${language || 'txt'}`}
code={code}
onCodeUpdate={setCode}
ref={codeMirrorRef}
/>
</SandpackProvider>
<div ref={elRef} />
</div>
)
}
36 changes: 24 additions & 12 deletions src/plugins/codemirror/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { realmPlugin } from '../../RealmWithPlugins'
import { Cell, Signal, map } from '@mdxeditor/gurx'
import { CodeBlockEditorDescriptor, appendCodeBlockEditorDescriptor$, insertCodeBlock$ } from '../codeblock'
import { CodeMirrorEditor } from './CodeMirrorEditor'
import { SandpackThemeProp } from '@codesandbox/sandpack-react/types'
import { Extension } from '@codemirror/state'

/**
* The codemirror code block languages.
Expand Down Expand Up @@ -37,13 +37,17 @@ export const insertCodeMirror$ = Signal<{ language: string; code: string }>((r)
})

/**
* The theme CodeMirrorEditor used.
* It can be "light" | "dark" | "auto",
* or the theme in "@codesandbox/sandpack-themes" package,
* or you can also custom one,
* learn more https://sandpack.codesandbox.io/docs/getting-started/themes#custom-theme
* The code mirror extensions for the coemirror code block editor.
* @group CodeMirror
*/
export const codeMirrorTheme$ = Cell<SandpackThemeProp>('auto')
export const codeMirrorExtensions$ = Cell<Extension[]>([])

/**
* Whether or not to try to dynamically load the code block language support.
* Disable if you want to manually pass the supported languages.
* @group CodeMirror
*/
export const codeMirrorAutoLoadLanguageSupport$ = Cell<boolean>(true)

/**
* A plugin that adds lets users edit code blocks with CodeMirror.
Expand All @@ -52,22 +56,30 @@ export const codeMirrorTheme$ = Cell<SandpackThemeProp>('auto')
export const codeMirrorPlugin = realmPlugin<{
codeBlockLanguages: Record<string, string>
/**
* The theme of CodeMirrorEditor
* Optional, additional CodeMirror extensions to load in the diff/source mode.
*/
codeMirrorExtensions?: Extension[]
/**
* Whether or not to try to dynamically load the code block language support.
* Disable if you want to manually pass the supported languages.
* @group CodeMirror
*/
theme?: SandpackThemeProp
autoLoadLanguageSupport?: boolean
}>({
update(r, params) {
r.pubIn({
[codeBlockLanguages$]: params?.codeBlockLanguages,
[codeMirrorTheme$]: params?.theme || 'auto'
[codeMirrorExtensions$]: params?.codeMirrorExtensions || [],
[codeMirrorAutoLoadLanguageSupport$]: params?.autoLoadLanguageSupport ?? true
})
},

init(r, params) {
r.pubIn({
[codeBlockLanguages$]: params?.codeBlockLanguages,
[codeMirrorTheme$]: params?.theme || 'auto',
[appendCodeBlockEditorDescriptor$]: buildCodeBlockDescriptor(params?.codeBlockLanguages || {})
[codeMirrorExtensions$]: params?.codeMirrorExtensions || [],
[appendCodeBlockEditorDescriptor$]: buildCodeBlockDescriptor(params?.codeBlockLanguages || {}),
[codeMirrorAutoLoadLanguageSupport$]: params?.autoLoadLanguageSupport ?? true
})
}
})
Expand Down
4 changes: 2 additions & 2 deletions src/plugins/sandpack/useCodeMirrorRef.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export function useCodeMirrorRef(nodeKey: string, editorType: 'codeblock' | 'san
const activeEditor = useCellValue(activeEditor$)
const setEditorInFocus = usePublisher(editorInFocus$)
// const setActiveEditorType = usePublisher('activeEditorType')
const codeMirrorRef = React.useRef<CodeMirrorRef>(null)
const codeMirrorRef = React.useRef<CodeMirrorRef | null>(null)
const { lexicalNode } = useCodeBlockEditorContext()

// these flags escape the editor with arrows.
Expand Down Expand Up @@ -90,7 +90,7 @@ export function useCodeMirrorRef(nodeKey: string, editorType: 'codeblock' | 'san
setTimeout(() => {
codeMirror?.getCodemirror()?.contentDOM?.addEventListener('focus', onFocusHandler)
codeMirror?.getCodemirror()?.contentDOM?.addEventListener('keydown', onKeyDownHandler)
}, 100)
}, 300)

return () => {
codeMirror?.getCodemirror()?.contentDOM.removeEventListener('focus', onFocusHandler)
Expand Down
12 changes: 8 additions & 4 deletions src/styles/ui.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -361,8 +361,12 @@
padding: var(--spacing-3);
}

.sandpackWrapper {
.codeMirrorWrapper {
margin-bottom: var(--spacing-5);
border: 1px solid var(--baseLine);
border-radius: var(--radius-medium);
overflow: hidden;
padding: 0.8rem;
}

.frontmatterWrapper {
Expand Down Expand Up @@ -1178,7 +1182,7 @@ form.multiFieldForm {
vertical-align: baseline;
align-items: center;
position: relative;

&::after,
& input {
width: auto;
Expand All @@ -1193,11 +1197,11 @@ form.multiFieldForm {
border: none;
color: inherit;
}

span {
padding: 0.25em;
}

&::after {
content: attr(data-value);
white-space: pre-wrap;
Expand Down

0 comments on commit d730670

Please sign in to comment.