gpt4 book ai didi

reactjs - 如何在 Draft.js 中自动将选择范围扩展到整个链接文本?

转载 作者:行者123 更新时间:2023-12-05 03:00:28 26 4
gpt4 key购买 nike

我正在使用 Draft.js 开发富文本编辑器(太棒了!)。以下代码允许用户编辑链接,逻辑上工作正常,但我对用户体验不满意。

如果用户选择链接的一部分并运行这段代码,这段代码会将链接分成多个链接,这不是用户想要的。

例如,如果一个阶段“买这本书”与 URL-A 链接,并且用户选择“购买这本书”,并将其更改为 URL-B,则该部分将与 URL-B 链接,但是“book"仍然与 URL-A 链接。

理想情况下,当用户选择链接文本的一部分时,我想自动将选择范围扩展到整个链接,然后执行这段代码。

但是,我不知道该怎么做(将选择范围扩大到整个链接)。

editLink = () => {
const { editorState } = this.state;
const selection = editorState.getSelection();
if (selection.isCollapsed()) {
return;
}

let url = ''; // default
const content = editorState.getCurrentContent();
const startKey = selection.getStartKey();
const startOffset = selection.getStartOffset();
const blockWithLinkAtBeginning = content.getBlockForKey(startKey);
const linkKey = blockWithLinkAtBeginning.getEntityAt(startOffset);
if (linkKey) {
const linkInstance = content.getEntity(linkKey);
url = linkInstance.getData().url;
}

let link = window.prompt("Paste the link", url);
if (!link) {
console.log("removing link");
const newEditorState = RichUtils.toggleLink(editorState, selection, null);
this.setState({ editorState: newEditorState });
return;
}
console.log("adding a link", link);
const contentWithEntity = content.createEntity('LINK', 'MUTABLE', { url: link });
const entityKey = contentWithEntity.getLastCreatedEntityKey();
const newEditorState = EditorState.set(editorState, { currentContent: contentWithEntity });
const yetNewEditorState = RichUtils.toggleLink(newEditorState, newEditorState.getSelection(), entityKey);

this.setState({ editorState: yetNewEditorState} );
}

如果有任何帮助或建议,我将不胜感激。

最佳答案

有两种方法可以做到这一点。第一个可能是您正在尝试的——在当前链接之上应用一个新链接,从而覆盖它。这不是最好的方法,但可以做到。

第二个更简单。在 ContentState 对象中,有一个方法 replaceEntityData()。所以你可以这样实现它:

editLink = () => {
const { editorState } = this.state;
const selection = editorState.getSelection();
if (selection.isCollapsed()) {
return;
}

let url = ''; // default
const content = editorState.getCurrentContent();
const startKey = selection.getStartKey();
const startOffset = selection.getStartOffset();
const block = content.getBlockForKey(startKey);
const linkKey = block.getEntityAt(startOffset);

let link = window.prompt("Paste the link", url);
if (!link) { //REMOVING LINK
var contentWithRemovedLink = content;
block.findEntityRanges(charData => { //You need to use block.findEntityRanges() API to get the whole range of link

const entityKey = charData.getEntity();
if (!entityKey) return false;
return entityKey === linkKey //Need to return TRUE only for your specific link.
}, (start, end) => {
const entitySelection = new SelectionState({
anchorKey: block.getKey(), //You already have the block key
focusKey: block.getKey(),
anchorOffset: start, //Just use the start/end provided by the API
focusOffset: end })
contentWithRemovedLink = Modifier.applyEntity(content, entitySelection, null)

return;
})

const newEditorState = EditorState.set(
editorState, { currentContent: contentWithRemovedLink });
return;
}
console.log("adding a link", link);

//CHANGING LINK
const contentWithUpdatedLink = content.replaceEntityData(linkKey, { url: link });
const newEditorState = EditorState.set(editorState, { currentContent: contentWithUpdatedLink });
//Now do as you please.
}

删除链接:

ContentBlock api 上,有一个名为 findEntityRanges() 的方法。该函数有两个参数:

  1. (char: CharacterMetadata) => boolean: characterMetadata 对象的过滤函数(每个连续的 ENTITY + INLINE_STYLE 组合都有一个唯一的 CharacterMetatdata 对象。你可以得到从那里通过 characterMetadata.getEntity() 获取实体。)。如果此函数执行为 TRUE,则执行 (2)。
  2. (开始:数字,结束:数字)=> 无效。这使您可以访问每个执行 TRUE 的特定字符范围的开始和结束偏移量。现在您可以随心所欲地处理开始和结束。

之后,您可以应用包含整个链接的新 SelectionState 的 NULL 实体。这将删除链接实体。

更改链接:

您已经拥有 linkKey。只需调用 content.replaceEntityData(linkKey, {url: "MY NEW URL"}) 即可使用新 URL 生成新的 ContentState。此处定义的 API:https://draftjs.org/docs/api-reference-content-state#replaceentitydata

关于reactjs - 如何在 Draft.js 中自动将选择范围扩展到整个链接文本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56763449/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com