Javascript 在Slate.js编辑器中启用自动链接
我是js新手,我想在Slate.js编辑器中启用自动链接。 例如 当我们输入任何编辑器时,它会将其转换为可单击的链接 我希望当一个用户输入一个链接并按空格键时,它应该被转换成可点击的链接 这是我目前的代码 所有其他快捷方式都很好,但当我尝试插入链接时,它不会显示任何内容。 原因是我不知道如何在Childern中合并链接。 链接验证逻辑很好。 我所需要的是当我插入链接并按空格键时,它会显示一个可点击的链接Javascript 在Slate.js编辑器中启用自动链接,javascript,reactjs,hyperlink,text-editor,slate.js,Javascript,Reactjs,Hyperlink,Text Editor,Slate.js,我是js新手,我想在Slate.js编辑器中启用自动链接。 例如 当我们输入任何编辑器时,它会将其转换为可单击的链接 我希望当一个用户输入一个链接并按空格键时,它应该被转换成可点击的链接 这是我目前的代码 所有其他快捷方式都很好,但当我尝试插入链接时,它不会显示任何内容。 原因是我不知道如何在Childern中合并链接。 链接验证逻辑很好。 我所需要的是当我插入链接并按空格键时,它会显示一个可点击的链接 import { Slate, Editable, withReact } from 'sl
import { Slate, Editable, withReact } from 'slate-react'
import {
Editor,
Transforms,
Range,
Point,
createEditor,
Element as SlateElement,
Descendant,
} from 'slate'
import { withHistory } from 'slate-history'
const SHORTCUTS = {
'*': 'list-item',
'-': 'list-item',
'+': 'list-item',
'>': 'block-quote',
'#': 'heading-one',
'##': 'heading-two',
'###': 'heading-three',
'####': 'heading-four',
'#####': 'heading-five',
'######': 'heading-six',
}
const MarkdownShortcutsExample = () => {
const [value, setValue] = useState<Descendant[]>(initialValue)
const renderElement = useCallback(props => <Element {...props} />, [])
const editor = useMemo(
() => withShortcuts(withReact(withHistory(createEditor()))),
[]
)
return (
<Slate editor={editor} value={value} onChange={value => setValue(value)}>
<Editable
renderElement={renderElement}
placeholder="Write some markdown..."
spellCheck
autoFocus
/>
</Slate>
)
}
const withShortcuts = editor => {
const { deleteBackward, insertText } = editor
editor.insertText = text => {
const { selection } = editor
if (text === ' ' && selection && Range.isCollapsed(selection)) {
const { anchor } = selection
const block = Editor.above(editor, {
match: n => Editor.isBlock(editor, n),
})
const path = block ? block[1] : []
const start = Editor.start(editor, path)
const range = { anchor, focus: start }
const beforeText = Editor.string(editor, range)
console.log("This is testin",validURL(beforeText))
const type = validURL(beforeText)?"link":SHORTCUTS[beforeText]
if (type) {
Transforms.select(editor, range)
Transforms.delete(editor)
const newProperties: Partial<SlateElement> = {
type,
}
Transforms.setNodes(editor, newProperties, {
match: n => Editor.isBlock(editor, n),
})
return
}
}
insertText(text)
}
editor.deleteBackward = (...args) => {
const { selection } = editor
if (selection && Range.isCollapsed(selection)) {
const match = Editor.above(editor, {
match: n => Editor.isBlock(editor, n),
})
if (match) {
const [block, path] = match
const start = Editor.start(editor, path)
if (
!Editor.isEditor(block) &&
SlateElement.isElement(block) &&
block.type !== 'paragraph' &&
Point.equals(selection.anchor, start)
) {
const newProperties: Partial<SlateElement> = {
type: 'paragraph',
}
Transforms.setNodes(editor, newProperties)
if (block.type === 'list-item') {
Transforms.unwrapNodes(editor, {
match: n =>
!Editor.isEditor(n) &&
SlateElement.isElement(n) &&
n.type === 'bulleted-list',
split: true,
})
}
return
}
}
deleteBackward(...args)
}
}
return editor
}
const validURL=(str)=> {
var pattern = new RegExp('^(https?:\\/\\/)?'+ // protocol
'((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|'+ // domain name
'((\\d{1,3}\\.){3}\\d{1,3}))'+ // OR ip (v4) address
'(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*'+ // port and path
'(\\?[;&a-z\\d%_.~+=-]*)?'+ // query string
'(\\#[-a-z\\d_]*)?$','i'); // fragment locator
return !!pattern.test(str);
}
const Element = ({ attributes, children, element }) => {
console.log("777",attributes, children, element)
switch (element.type) {
case 'block-quote':
return <blockquote {...attributes}>{children}</blockquote>
case 'bulleted-list':
return <ul {...attributes}>{children}</ul>
case 'heading-one':
return <h1 {...attributes}>{children}</h1>
case 'heading-two':
return <h2 {...attributes}>{children}</h2>
case 'heading-three':
return <h3 {...attributes}>{children}</h3>
case 'heading-four':
return <h4 {...attributes}>{children}</h4>
case 'heading-five':
return <h5 {...attributes}>{children}</h5>
case 'heading-six':
return <h6 {...attributes}>{children}</h6>
case 'list-item':
return <li {...attributes}>{children}</li>
case 'link':
console.log("Inside")
return <a {...attributes} href={element.url}>
{children}
</a>
default:
return <p {...attributes}>{children}</p>
}
}
const initialValue: Descendant[] = [
{
type: 'link',
url:'',
children:[{ text: '' }],
},
{
type: 'paragraph',
children: [
{
text:
'The editor gives you full control over the logic you can add. For example, it\'s fairly common to want to add markdown-like shortcuts to editors. So that, when you start a line with "> " you get a blockquote that looks like this:',
},
],
},
{
type: 'block-quote',
children: [{ text: 'A wise quote.' }],
},
{
type: 'paragraph',
children: [
{
text:
'Order when you start a line with "## " you get a level-two heading, like this:',
},
],
},
{
type: 'heading-two',
children: [{ text: 'Try it out!' }],
},
{
type: 'paragraph',
children: [
{
text:
'Try it out for yourself! Try starting a new line with ">", "-", or "#"s.',
},
],
},
]
export default MarkdownShortcutsExample````
any help will be appreciated.
thanks in advance
从“Slate react”导入{Slate,可编辑,withReact}
进口{
编辑
转变,
范围
指向
createEditor,
元素作为元素,
后代
}来自“板岩”
从“slate history”导入{withHistory}
常量快捷方式={
“*”:“列表项”,
“-”:“列表项”,
“+”:“列表项”,
“>”:“块引号”,
":"标题一",,
“标题二”,
“标题三”,
“标题四”,
“标题五”,
“标题6”,
}
常量MarkdownShortcutsExample=()=>{
const[value,setValue]=useState(initialValue)
const renderElement=useCallback(props=>,[])
const editor=usemo(
()=>使用短切(withReact(withHistory(createEditor()))),
[]
)
返回(
设置值(值)}>
)
}
const withShortcuts=编辑器=>{
const{deleteBackward,insertText}=编辑器
editor.insertText=text=>{
常量{selection}=编辑器
如果(文本==''&&selection&&Range.isCollapsed(selection)){
常量{anchor}=选择
const block=编辑器上方(编辑器{
匹配:n=>Editor.isBlock(Editor,n),
})
常量路径=块?块[1]:[]
const start=Editor.start(编辑器,路径)
常量范围={anchor,focus:start}
const beforeText=Editor.string(编辑器,范围)
log(“这是testin”,validur(beforeText))
const type=validURL(beforeText)-“链接”:快捷方式[beforeText]
如果(类型){
Transforms.select(编辑器,范围)
Transforms.delete(编辑器)
常量newProperties:Partial={
类型,
}
Transforms.setNodes(编辑器、newProperties、{
匹配:n=>Editor.isBlock(Editor,n),
})
返回
}
}
插入文本(文本)
}
editor.deleteBackward=(…args)=>{
常量{selection}=编辑器
if(选择集和范围集(选择集)){
const match=编辑器上方(编辑器{
匹配:n=>Editor.isBlock(Editor,n),
})
如果(匹配){
常量[块,路径]=匹配
const start=Editor.start(编辑器,路径)
如果(
!Editor.isEditor(块)&&
SlateElement.isElement(块)&&
block.type!=“段落”&&
Point.equals(selection.anchor,start)
) {
常量newProperties:Partial={
键入:“段落”,
}
Transforms.setNodes(编辑器,newProperties)
if(block.type===‘列表项’){
变换。展开节点(编辑器{
匹配:n=>
!Editor.isEditor(n)&&
SlateElement.isElement(n)&&
n、 类型=='项目符号列表',
斯普利特:是的,
})
}
返回
}
}
deleteBackward(…args)
}
}
返回编辑器
}
常数validull=(str)=>{
var pattern=new RegExp('^(https?:\\/\\\/)?'+//协议
“(([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\”+[a-z]{2,}}|“+//域名
“(\\d{1,3}\\){3}\\d{1,3}”)+//或ip(v4)地址
“(\\:\\d+)(\\/[-a-z\\d%.~+]*)*”+//端口和路径
“(\\?[;&a-z\\d%.~+=-]*)?”+//查询字符串
“(\\\\\\[-a-z\\d\]*)?$”,“i');//片段定位器
return!!pattern.test(str);
}
常量元素=({attributes,children,Element})=>{
log(“777”,属性,子元素,元素)
开关(元件类型){
案例“整体报价”:
返回{children}
案例“项目列表”:
返回{children}
“标题一”一案:
返回{children}
“标题二”一案:
返回{children}
“标题三”一案:
返回{children}
“品目4”一案:
返回{children}
“品目5”一案:
返回{children}
“标题6”一案:
返回{children}
案例“列表项”:
返回{children}
“链接”案例:
控制台日志(“内部”)
返回
违约:
返回{children}
}
}
常量初始值:后代[]=[
{
键入:“链接”,
url:“”,
子项:[{text:'}],
},
{
键入:“段落”,
儿童:[
{
正文:
'编辑器使您可以完全控制可以添加的逻辑。例如,很常见的情况是希望向编辑器添加类似标记的快捷方式。因此,当您以“>”开始一行时,您会得到一个如下所示的块引号:',
},
],
},
{
键入:“块引号”,
儿童:[{text:'一句明智的引语。}],
},
{
键入:“段落”,
儿童:[
{
正文:
'当您以“##”开始一行时,您会得到一个二级标题,如下所示:',
},
],
},
{
键入:“标题二”,
子项:[{text:'Try out!'}],
},
{
键入:“段落”,
儿童:[
{
正文:
'自己试一试!试着用“>”、“-”或“#”来开始一个新行。',
},
],
},
]
导出默认MarkdownShortcutsExample````
任何帮助都将不胜感激。
提前谢谢