Skip to content

Commit d65ca9d

Browse files
committed
feat: handle error in editor
1 parent 67df6c5 commit d65ca9d

File tree

10 files changed

+218
-58
lines changed

10 files changed

+218
-58
lines changed

apps/book-web/next.config.mjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/** @type {import('next').NextConfig} */
22
const nextConfig = {
3+
transpilePackages: ['next-mdx-remote'],
34
reactStrictMode: true,
45
experimental: {
56
serverComponentsExternalPackages: ['shiki', 'vscode-oniguruma'],

apps/book-web/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
"graphql-tag": "^2.12.6",
2828
"gray-matter": "^4.0.3",
2929
"next": "14.2.3",
30-
"next-mdx-remote": "4.4.1",
3130
"react": "^18",
3231
"react-dom": "^18",
3332
"rehype-katex": "^7.0.0",

apps/book-web/src/layouts/NextraLayout/NextraLayout.tsx

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
1-
import NextraDocLayout, {
2-
CustomEventDetail,
3-
mdxCompiler,
4-
nextraCustomEventName,
5-
} from '@packages/nextra-editor'
1+
import NextraDocLayout, { CustomEventDetail, nextraCustomEventName } from '@packages/nextra-editor'
62
import { themeConfig } from './context'
73
import { useEffect, useState } from 'react'
84
import { BookMetadata, generateBookMetadata, Pages } from '@/lib/generateBookMetadata'

apps/book-web/src/pages/[username]/[bookTitle]/[[...pageUrlSlug]].tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import NextraLayout from '@/layouts/NextraLayout'
2-
import { generateBookMetadata } from '@/lib/generateBookMetadata'
32
import getPage from '@/prefetch/getPage'
43
import getPages from '@/prefetch/getPages'
5-
import { mdxCompiler } from '@packages/nextra-editor'
64

75
import { GetServerSideProps } from 'next'
86

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { EditorView } from 'codemirror'
2+
3+
export const handlePaste = (event: ClipboardEvent, view: EditorView) => {
4+
console.log('paste event')
5+
const clipboardData = event.clipboardData
6+
if (!clipboardData) return
7+
console.log('clipboardData', clipboardData)
8+
}

packages/nextra-editor/src/components/markdown-editor/hooks/useCodemirror.ts

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { getEditorStat } from '../lib/getEditorStat'
88
import { hyperLink } from '@uiw/codemirror-extensions-hyper-link'
99
import { markdown, markdownLanguage } from '@codemirror/lang-markdown'
1010
import { languages } from '@codemirror/language-data'
11+
import { handlePaste } from '../events/paste'
1112

1213
type Config = {
1314
autoFocus?: boolean
@@ -19,6 +20,10 @@ type Config = {
1920
maxWidth?: string | null
2021
}
2122

23+
// EditorView.domEventHandlers({
24+
// paste: handlePaste,
25+
// })
26+
2227
const External = Annotation.define<boolean>()
2328

2429
export const useCodemirror = (container: RefObject<HTMLElement>, config: Config = {}) => {
@@ -75,13 +80,7 @@ export const useCodemirror = (container: RefObject<HTMLElement>, config: Config
7580
editable: true,
7681
placeholder: '당신의 이야기를 적어주세요...',
7782
indentWithTab: true,
78-
basicSetup: {
79-
// lineNumbers: true,
80-
// history: true,
81-
// foldGutter: true,
82-
// foldKeymap: true,
83-
// dropCursor: true,
84-
},
83+
basicSetup: true,
8584
})
8685

8786
const extenstions = [
@@ -92,6 +91,7 @@ export const useCodemirror = (container: RefObject<HTMLElement>, config: Config
9291
...defaultExtensions,
9392
]
9493

94+
// create state
9595
useEffect(() => {
9696
if (container?.current && !state) {
9797
const stateCurrent = EditorState.create({
@@ -102,12 +102,14 @@ export const useCodemirror = (container: RefObject<HTMLElement>, config: Config
102102
}
103103
}, [container, state, value, extenstions])
104104

105+
// create view
105106
useEffect(() => {
106107
if (container?.current && state && !view) {
107108
const viewCurrent = new EditorView({
108109
state,
109110
parent: container.current,
110111
})
112+
111113
setView(viewCurrent)
112114
}
113115

@@ -118,6 +120,7 @@ export const useCodemirror = (container: RefObject<HTMLElement>, config: Config
118120
}
119121
}, [container, state, view])
120122

123+
// destroy view
121124
useEffect(
122125
() => () => {
123126
if (!view) return

packages/nextra-editor/src/contexts/markdown-editor.tsx

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -34,30 +34,34 @@ type Props = {
3434
}
3535

3636
export const MarkdownEditorProvider = ({ children, value: { editorValue } }: Props) => {
37+
const [isError, setIsError] = useState<boolean>(false)
3738
const [value, setValue] = useState<string>(editorValue)
3839
const [mdxSource, setMdxSource] = useState<MDXRemoteSerializeResult | null>(null)
3940
const [stat, setStat] = useState<Statistics | null>(null)
4041

4142
useEffect(() => {
42-
setValue(editorValue)
43-
}, [editorValue])
43+
if (isError) {
44+
setIsError(false)
45+
}
46+
}, [value])
4447

4548
useEffect(() => {
4649
async function compileSource() {
47-
try {
48-
const result = await mdxCompiler(value, {
49-
onigHostUrl: process.env.NEXT_PUBLIC_CLIENT_HOST,
50-
})
51-
52-
if (!result) return
50+
const result = await mdxCompiler(value, {
51+
onigHostUrl: process.env.NEXT_PUBLIC_CLIENT_HOST,
52+
isError,
53+
})
5354

54-
setMdxSource(result)
55-
} catch (error) {
56-
console.error('failed mdx compile: ', error)
55+
if (!result) {
56+
setIsError(true)
57+
return
5758
}
59+
60+
setMdxSource(result)
5861
}
62+
5963
compileSource()
60-
}, [value])
64+
}, [value, isError])
6165

6266
const context: MarkdownEditorContext = {
6367
value,

packages/nextra-editor/src/mdx-compiler.ts

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { MdxCompilerOptions } from './index'
1+
import type { MdxCompilerOptions, PageOpts } from './index'
22
import { serialize } from 'next-mdx-remote/serialize'
33
import grayMatter from 'gray-matter'
44
// import { createProcessor } from '@mdx-js/mdx'
@@ -15,7 +15,7 @@ import remarkMath from 'remark-math'
1515
import remarkReadingTime from 'remark-reading-time'
1616
import remarkParse from 'remark-parse'
1717
import rehypeStringify from 'rehype-stringify'
18-
// import rehypeRaw from 'rehype-raw'
18+
import rehypeRaw from 'rehype-raw'
1919
import remarkMdx from 'remark-mdx'
2020

2121
import {
@@ -33,6 +33,8 @@ import {
3333
// import theme from './theme'
3434
import { MDXRemoteSerializeResult } from 'next-mdx-remote'
3535
import { truthy } from './nextra/utils'
36+
import { createProcessor } from '@mdx-js/mdx'
37+
import { ReadingTime, StructurizedData } from './nextra/types'
3638

3739
const clonedRemarkLinkRewrite = remarkLinkRewrite.bind(null as any)
3840

@@ -60,26 +62,25 @@ const MARKDOWN_URL_EXTENSION_REGEX = /\.mdx?(?:(?=[#?])|$)/
6062

6163
export const mdxCompiler = async (
6264
source: string,
63-
{ defaultShowCopyCode = true, onigHostUrl = '' }: MdxCompilerOptions = {},
65+
{ defaultShowCopyCode = true, onigHostUrl = '', isError }: MdxCompilerOptions = {},
6466
): Promise<MDXRemoteSerializeResult | null> => {
6567
const { content } = grayMatter(source)
6668

6769
if (!onigHostUrl) {
6870
throw new Error('onigHostUrl is required')
6971
}
7072

71-
try {
72-
const onig = await fetch(`${onigHostUrl}/wasm/onig.wasm`)
73-
setWasm(onig)
73+
const onig = await fetch(`${onigHostUrl}/wasm/onig.wasm`)
74+
setWasm(onig)
7475

76+
try {
7577
const result = await serialize(content, {
7678
mdxOptions: {
77-
format: 'mdx',
79+
format: isError ? 'md' : 'mdx',
7880
development: false,
7981
remarkPlugins: (
8082
[
8183
remarkParse,
82-
remarkMdx,
8384
// remarkMermaid, // should be before remarkRemoveImports because contains `import { Mermaid } from ...`
8485
[
8586
remarkNpm2Yarn, // should be before remarkRemoveImports because contains `import { Tabs as $Tabs, Tab as $Tab } from ...`
@@ -138,7 +139,9 @@ export const mdxCompiler = async (
138139

139140
return result
140141
} catch (error) {
141-
console.log('serialize error', error)
142+
if (process.env.NODE_ENV === 'development') {
143+
console.log('Failed to compile source', error)
144+
}
142145
return null
143146
}
144147
}

packages/nextra-editor/src/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ export type MdxCompilerOptions = Partial<
6464
useCachedCompiler?: boolean
6565
isPageImport?: boolean
6666
onigHostUrl: string
67+
isError?: boolean
6768
}
6869
>
6970

0 commit comments

Comments
 (0)