Skip to content

Commit

Permalink
feat: preview mode
Browse files Browse the repository at this point in the history
  • Loading branch information
drl990114 committed Apr 21, 2024
1 parent 939e640 commit 13c6841
Show file tree
Hide file tree
Showing 10 changed files with 67 additions and 45 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "rme",
"version": "0.0.51",
"version": "0.0.55",
"type": "module",
"scripts": {
"build": "yarn clear && yarn build-esbuild && yarn types",
Expand Down Expand Up @@ -180,6 +180,6 @@
"svgmoji": "^3.2.0",
"void-elements": "^3.1.0",
"yjs": "^13.6.14",
"zens": "^0.0.20"
"zens": "^0.0.21"
}
}
33 changes: 11 additions & 22 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ import {
createWysiwygDelegate,
WysiwygThemeWrapper,
Preview,
createSourceCodeDelegate,
} from '.'
import React, { FC, useLayoutEffect, useMemo, useRef } from 'react'
import React, { FC, useLayoutEffect, useMemo, useRef, useState } from 'react'
import useDevTools from './playground/hooks/use-devtools'
import useContent from './playground/hooks/use-content'
import { DebugConsole } from './playground/components/DebugConsole'
Expand Down Expand Up @@ -34,9 +35,8 @@ function App() {
const { contentId, content, hasUnsavedChanges, setContentId, setContent } = useContent()
const { enableDevTools, setEnableDevTools } = useDevTools()
const [theme, setTheme] = React.useState<'light' | 'dark'>('dark')
const editorDelegate = useMemo(() => createWysiwygDelegate(), [])
const [editorDelegate, setEditorDelegate] = useState(createWysiwygDelegate())
const [previewMode, setPreviewMode] = React.useState(false)
const docRef = useRef<Node>()

const debounce = (fn: (...args: any) => void, delay: number) => {
let timer: number
Expand All @@ -47,13 +47,13 @@ function App() {
}

const debounceChange = debounce((params) => {
docRef.current = params.state.doc
setContent(editorDelegate.docToString(params.state.doc) || '')
}, 300)

const editor = (
<div className="playground-self-scroll">
<Editor
initialType="wysiwyg"
key={contentId}
ref={editorRef}
content={content}
Expand Down Expand Up @@ -104,14 +104,19 @@ function App() {
onChange={(e) => {
const value = e.target.value
if (value === 'wysiwyg') {
setEditorDelegate(createWysiwygDelegate())
editorRef.current?.toggleType('wysiwyg')
} else {
} else if (value === 'sourceCode') {
setEditorDelegate(createSourceCodeDelegate())
editorRef.current?.toggleType('sourceCode')
} else {
editorRef.current?.toggleType('preview')
}
}}
>
<option value="wysiwyg">wysiwyg</option>
<option value="sourceCode">source code</option>
<option value="preview">preview</option>
</select>
<FormGroup>
<FormControlLabel
Expand All @@ -127,16 +132,6 @@ function App() {
}}
/>
</FormGroup>
<FormGroup>
<FormControlLabel
control={<Switch />}
label="Preview"
labelPlacement="start"
onChange={(e) => {
setPreviewMode(e.target.checked)
}}
/>
</FormGroup>
</div>
<ThemeProvider
theme={themeData}
Expand All @@ -163,13 +158,7 @@ function App() {
toggleEnableDevTools={() => setEnableDevTools(!enableDevTools)}
/>
<div className="playground-box">
{previewMode ? (
<div className="playground-self-scroll">
<Preview doc={docRef.current}></Preview>
</div>
) : (
editor
)}
{editor}
{debugConsole}
</div>
<BlurHelper />
Expand Down
35 changes: 26 additions & 9 deletions src/editor/components/Editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,26 @@
import WysiwygEditor from './WysiwygEditor'
import SourceEditor from './SourceEditor'
import { forwardRef, memo, useImperativeHandle, useMemo, useState } from 'react'
import type { EditorContext, EditorDelegate, EditorViewType } from '../..'
import {
Preview,
type CreateWysiwygDelegateOptions,
type EditorContext,
type EditorDelegate,
type EditorViewType,
} from '../..'
import { useContextMounted } from './useContextMounted'
import type { Extension, RemirrorEventListenerProps } from 'remirror'
import "prosemirror-flat-list/dist/style.css"

export type EditorRef = {
toggleType: (targetType: EditorViewType) => void
getType: () => EditorViewType
}
import 'prosemirror-flat-list/dist/style.css'

export const Editor = memo(
forwardRef<EditorRef, EditorProps>((props, ref) => {
const { hooks = [], onContextMounted, ...otherProps } = props
const [type, setType] = useState<EditorViewType>('wysiwyg')
const {
initialType = 'wysiwyg',
hooks = [],
onContextMounted,
...otherProps
} = props
const [type, setType] = useState<EditorViewType>(initialType)

useImperativeHandle(ref, () => ({
getType: () => type,
Expand All @@ -28,6 +34,10 @@ export const Editor = memo(
return [() => useContextMounted(onContextMounted), ...hooks]
}, [hooks, onContextMounted])

if (type === 'preview') {
return <Preview doc={otherProps.content} delegateOptions={otherProps.delegateOptions} />
}

return type === 'sourceCode' ? (
<SourceEditor {...otherProps} hooks={editorHooks} />
) : (
Expand All @@ -39,11 +49,18 @@ export const Editor = memo(
export type EditorChangeEventParams = RemirrorEventListenerProps<Extension>
export type EditorChangeHandler = (params: EditorChangeEventParams) => void

export type EditorRef = {
toggleType: (targetType: EditorViewType) => void
getType: () => EditorViewType
}

export interface EditorProps {
initialType?: EditorViewType
delegate?: EditorDelegate
content: string
isTesting?: boolean
editable?: boolean
delegateOptions?: CreateWysiwygDelegateOptions
onChange?: EditorChangeHandler
hooks?: (() => void)[]
markdownToolBar?: React.ReactNode[]
Expand Down
14 changes: 11 additions & 3 deletions src/editor/components/Preview/preview.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
import { WysiwygThemeWrapper } from '../../theme'
import { prosemirrorNodeToHtml } from 'remirror'
import type { Node } from '@remirror/pm/model'
import { EditorProps } from '../Editor'
import { createWysiwygDelegate } from '../WysiwygEditor'

interface PreviewProps {
doc: Node
doc: Node | string
delegateOptions?: EditorProps['delegateOptions']
}

export const Preview: React.FC<PreviewProps> = (props) => {
const { doc } = props
const { doc, delegateOptions } = props
let targetDoc: PreviewProps['doc'] = doc

const html = prosemirrorNodeToHtml(doc)
if (typeof targetDoc === 'string') {
targetDoc = createWysiwygDelegate(delegateOptions).stringToDoc(targetDoc)
}

const html = prosemirrorNodeToHtml(targetDoc)

return <WysiwygThemeWrapper dangerouslySetInnerHTML={{ __html: html }} />
}
5 changes: 5 additions & 0 deletions src/editor/extensions/Inline/inline-mark-extensions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,8 @@ export interface MfImgOptions {
handleViewImgSrcUrl?: (src: string) => Promise<string>
}

const globalImageHrefCache: Map<string, string> = new Map()

@extension<MfImgOptions>({
defaultOptions: {
handleViewImgSrcUrl: async (src: string) => src,
Expand All @@ -214,8 +216,10 @@ class ImgUri extends MarkExtension<MfImgOptions> {
default: '',
},
},
toDOM: (mark) => ['img', { src: globalImageHrefCache.get(mark.attrs.href) || mark.attrs.href }, 0]
}
}

createNodeViews = (): NodeViewMethod => {
return (mark): NodeView => {
const innerContainer = document.createElement('span')
Expand All @@ -224,6 +228,7 @@ class ImgUri extends MarkExtension<MfImgOptions> {
if (this.options.handleViewImgSrcUrl) {
this.options.handleViewImgSrcUrl(mark.attrs.href).then((newHref) => {
img.setAttribute('src', formatHref(newHref))
globalImageHrefCache.set(mark.attrs.href, newHref)
})
} else {
img.setAttribute('src', formatHref(mark.attrs.href))
Expand Down
2 changes: 1 addition & 1 deletion src/editor/theme/dark.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export const styledDarkTheme = {
primaryFontColor: '#c8d1d9',
labelFontColor: 'rgba(255, 255, 255, 0.5)',
accentColor: '#1c78aa',
accentColor: '#016ab3',
borderColor: '#363b41',
bgColor: '#05010d',
hoverColor: '#1f2225',
Expand Down
2 changes: 1 addition & 1 deletion src/editor/theme/light.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export const styledLightTheme = {
primaryFontColor: '#000000',
labelFontColor: '#9ca3af',
accentColor: '#0369a1',
accentColor: '#007acc',
borderColor: '#d7d7dc',
bgColor: '#fdfdfd',
hoverColor: '#d7d7dc',
Expand Down
2 changes: 1 addition & 1 deletion src/editor/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export interface Note {
deleted: boolean
}

export type EditorViewType = 'wysiwyg' | 'sourceCode'
export type EditorViewType = 'wysiwyg' | 'sourceCode' | 'preview'

type BaseEditorState = {
mode: EditorViewType
Expand Down
3 changes: 3 additions & 0 deletions src/playground/content.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ const defaultContent = [
`
# hello world!
![img](https://www.gstatic.com/images/branding/googlelogo/svg/googlelogo_clr_74x24px.svg)
a
`.trim(),
].join("\n")

Expand Down
12 changes: 6 additions & 6 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
"@floating-ui/dom" "^1.0.0"
use-sync-external-store "^1.2.0"

"@ariakit/react@^0.4.3":
"@ariakit/react@^0.4.5":
version "0.4.5"
resolved "https://registry.yarnpkg.com/@ariakit/react/-/react-0.4.5.tgz#f6e356665cc45fa317c10fa041009acbb290d92f"
integrity sha512-GUHxaOY1JZrJUHkuV20IY4NWcgknhqTQM0qCQcVZDCi+pJiWchUjTG+UyIr/Of02hU569qnQ7yovskCf+V3tNg==
Expand Down Expand Up @@ -10322,12 +10322,12 @@ yocto-queue@^1.0.0:
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-1.0.0.tgz#7f816433fb2cbc511ec8bf7d263c3b58a1a3c251"
integrity sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==

zens@^0.0.20:
version "0.0.20"
resolved "https://registry.yarnpkg.com/zens/-/zens-0.0.20.tgz#8b6595a2a9ba4a5837723f6f58b3b246f8dea708"
integrity sha512-vcnMK7O/x1p5HT8CTN43PeQ8oTPxub1cBdpLejoJ9sMLMOp3hEowqTNsRiGYRC/A5eXLsio2Z0WpzpiJSDVbZg==
zens@^0.0.21:
version "0.0.21"
resolved "https://registry.yarnpkg.com/zens/-/zens-0.0.21.tgz#bbe42a1fb46bee023c5e6125c4cad314430b332f"
integrity sha512-K5bFEHMn2w2EzFR+dshUT5f8l/Uc31VNoO/XDfZjOh4TGfHq0bMJ92I8q+al1+L/ooIYOXqImkwEmGmcB3H2+Q==
dependencies:
"@ariakit/react" "^0.4.3"
"@ariakit/react" "^0.4.5"
"@babel/runtime" "^7"
"@emotion/is-prop-valid" "^1.2.2"
"@floating-ui/dom" "^1.0.0"
Expand Down

0 comments on commit 13c6841

Please sign in to comment.