Implement link editor (#20)
* feat: implement link editor * feat: update slate to 0.58.3pull/22/head
parent
ce0c86fb3c
commit
eb370eaa1e
@ -0,0 +1,30 @@
|
||||
import { Transforms, Editor } from 'slate'
|
||||
|
||||
const LIST_TYPES: string[] = ['numbered-list', 'bulleted-list']
|
||||
|
||||
export const toggleBlock = (editor: any, format: any) => {
|
||||
const isActive = isBlockActive(editor, format)
|
||||
const isList = LIST_TYPES.includes(format)
|
||||
|
||||
Transforms.unwrapNodes(editor, {
|
||||
match: n => LIST_TYPES.includes(n.type as any),
|
||||
split: true
|
||||
})
|
||||
|
||||
Transforms.setNodes(editor, {
|
||||
type: isActive ? 'paragraph' : isList ? 'list-item' : format
|
||||
})
|
||||
|
||||
if (!isActive && isList) {
|
||||
const block = { type: format, children: [] }
|
||||
Transforms.wrapNodes(editor, block)
|
||||
}
|
||||
}
|
||||
|
||||
export const isBlockActive = (editor: any, format: any) => {
|
||||
const [match] = Editor.nodes(editor, {
|
||||
match: n => n.type === format
|
||||
})
|
||||
|
||||
return !!match
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
import isUrl from 'is-url'
|
||||
|
||||
import { Transforms, Editor, Range } from 'slate'
|
||||
|
||||
export interface LinkEditor extends Editor {
|
||||
insertData: (data: any) => void
|
||||
}
|
||||
|
||||
export const withLinks = <T extends Editor>(editor: T) => {
|
||||
const e = editor as T & LinkEditor
|
||||
|
||||
const { insertData, insertText, isInline } = e
|
||||
|
||||
e.isInline = (element: any) => {
|
||||
return element.type === 'link' ? true : isInline(element)
|
||||
}
|
||||
|
||||
e.insertText = (text: string) => {
|
||||
if (text && isUrl(text)) {
|
||||
wrapLink(editor, text)
|
||||
} else {
|
||||
insertText(text)
|
||||
}
|
||||
}
|
||||
|
||||
e.insertData = (data: any) => {
|
||||
const text = data.getData('text/plain')
|
||||
|
||||
if (text && isUrl(text)) {
|
||||
wrapLink(editor, text)
|
||||
} else {
|
||||
insertData(data)
|
||||
}
|
||||
}
|
||||
|
||||
return editor
|
||||
}
|
||||
|
||||
export const insertLink = (editor: Editor, href: string) => {
|
||||
if (editor.selection) {
|
||||
wrapLink(editor, href)
|
||||
}
|
||||
}
|
||||
|
||||
export const isLinkActive = (editor: Editor) => {
|
||||
const [link] = Editor.nodes(editor, { match: n => n.type === 'link' })
|
||||
return !!link
|
||||
}
|
||||
|
||||
export const unwrapLink = (editor: Editor) => {
|
||||
Transforms.unwrapNodes(editor, { match: n => n.type === 'link' })
|
||||
}
|
||||
|
||||
export const wrapLink = (editor: Editor, href: string) => {
|
||||
if (isLinkActive(editor)) {
|
||||
unwrapLink(editor)
|
||||
}
|
||||
|
||||
const { selection } = editor
|
||||
const isCollapsed = selection && Range.isCollapsed(selection)
|
||||
const link = {
|
||||
type: 'link',
|
||||
href,
|
||||
children: isCollapsed ? [{ text: href }] : []
|
||||
}
|
||||
|
||||
if (isCollapsed) {
|
||||
Transforms.insertNodes(editor, link)
|
||||
} else {
|
||||
Transforms.wrapNodes(editor, link, { split: true })
|
||||
Transforms.collapse(editor, { edge: 'end' })
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
import { Editor } from 'slate'
|
||||
|
||||
export const toggleMark = (editor: Editor, format: any) => {
|
||||
const isActive = isMarkActive(editor, format)
|
||||
|
||||
if (isActive) {
|
||||
Editor.removeMark(editor, format)
|
||||
} else {
|
||||
Editor.addMark(editor, format, true)
|
||||
}
|
||||
}
|
||||
|
||||
export const isMarkActive = (editor: Editor, format: any) => {
|
||||
const marks = Editor.marks(editor)
|
||||
return marks ? marks[format] === true : false
|
||||
}
|
Loading…
Reference in new issue