从draft.js // Draftail中的选择创建一个新实体,包装现有文本并链接实体

时间:2019-06-07 09:38:05

标签: javascript reactjs wagtail draftjs

我正在尝试为Wagtail的{​​{1}}文本编辑器(基于Draftail)创建一个新实体。

我从这里的示例开始:http://docs.wagtail.io/en/v2.5.1/advanced_topics/customisation/extending_draftail.html#creating-new-entities

我将扩展名用作概念证明,因为它将进行选择并将其包装在draft.js实体中。

但是,我需要能够保留现有footnote实体,以便它们成为新link实体的子代。

我尝试了各种代码组合(包括footnote draft.js),但无法使其正常工作。

CompositeDecorator

我的理解是 // FootnoteSource.js const React = window.React; const Modifier = window.DraftJS.Modifier; const EditorState = window.DraftJS.EditorState; class FootnoteSource extends React.Component { componentDidMount() { const { editorState, entityType, onComplete } = this.props; const content = editorState.getCurrentContent(); // // Uses the Draft.js API to create a new entity with the right data. const contentWithEntity = content.createEntity(entityType.type, 'MUTABLE', {}); const entityKey = contentWithEntity.getLastCreatedEntityKey(); const editorStateWithEntity = Modifier.applyEntity( editorState.getCurrentContent(), editorState.getSelection(), entityKey ) const nextState = EditorState.push(editorState, editorStateWithEntity, 'apply-entity'); onComplete(nextState); } render() { return null; } } export default FootnoteSource; // Footnote.js import PropTypes from 'prop-types'; const Footnote = (props) => { const { children, entityKey, contentState } = props; const data = contentState.getEntity(entityKey).getData(); return ( <span role="button" className="FootnoteEntity" > <span class="FootnoteEntity__label" aria-hidden="true">[Footnote]</span> {children} </span> ); }; Footnote.propTypes = { entityKey: PropTypes.string.isRequired, contentState: PropTypes.object.isRequired, }; export default Footnote; 装饰器的children道具只是文本。有没有一种方法可以使我可以作为子节点附加到新实体的实体节点/映射?

1 个答案:

答案 0 :(得分:3)

不幸的是,目前Draft.js doesn’t supported nested / children entities –编辑器中的任何内容都只能附加一个实体。这对于诸如链接之类的事情来说是有意义的,但是在实现“突出显示” /“评论”功能或脚注时会出现问题,因为理想情况下,无论是否有链接,都可以在任意文本上添加这些功能。

您有几种选择-这些都不是专用于Draftail / Wagtail的,因此您应该能够找到其他基于Draft.js的项目的参考,这些参考可能已经做了这些选择来规避此限制。不幸的是,这些都是非常高级的实现,可能会使其不切实际/成本太高,无法满足您的需求。 我还建议您评估您是否确实希望实现此目标(见下文)

添加一种将脚注数据存储在链接中的方法

这样,具有链接的文本将只有一个实体,但是您仍将脚注信息附加到该文本上。您也可以为没有链接但可以作为脚注的内容使用单独的脚注实体。或将LINK_AND_OR_FOOTNOTE实体同时做两件事。

我认为,如果您只在整个链接上添加脚注,而不仅是它们的各个子部分,这可能会比较好用。在Wagtail的上下文中,LINK实体是预定义的-这种解决方案意味着您必须重新定义自己的实体,这可能不是最佳方法。

将脚注存储为样式而不是实体

我不确定您如何管理脚注数据,但是如果在文本中这些仅仅是对“页面底部”内容的引用,则它们有可能被构建为样式(例如BOLD,{ {1}},等等。

  • 脚注的引用将以样式类型存储-例如ITALIC
  • 然后仅基于前缀FOOTNOTE_UUID_OF_12h3h53_FOOTNOTE_HERE来实现这些样式的自定义样式呈现。
  • 您很可能还需要在“脚注选择器” UI中添加逻辑,以防止用户在单个文本上添加多个脚注–除非这看起来像您需要的功能

我已经看到Draft.js项目在生产中正在执行此操作,所以我知道它是可行的,但是不幸的是,没有开源示例/代码可以共享。


作为最后一种选择,我建议您评估是否确实需要在链接内的文本中添加脚注 。如果将它们插入文本中(与他们跟随的文本相关,但附加在单独的文本中),则构建起来会容易得多。这样,脚注将是它们自己的实体,仍然无法插入链接中,但仅由于其旁边显示而仍可以与链接所处的文本相关。

我认为,对于最终用户来说,这也很容易使用-听起来好像脚注的可点击/可悬浮表示形式位于可点击/可悬浮链接内是一个可用性问题

例如,这是Wikipedia的引用方式:

enter image description here

实现是非常简单的,因为引文是单独插入的,并且最终用户的体验也很好,因为用户可以轻松选择与链接或脚注进行交互。