Создать новую сущность из выделения в draft.js // Draftail, обернуть существующий текст и связать сущности - PullRequest
0 голосов
/ 07 июня 2019

Я пытаюсь создать новую сущность для Wagtail Draftail текстового редактора (на основе draft.js).

Я начал с примера, приведенного здесь: http://docs.wagtail.io/en/v2.5.1/advanced_topics/customisation/extending_draftail.html#creating-new-entities

У меня есть расширение, работающее в качестве доказательства концепции, в котором оно будет принимать выделение и оборачивать его в 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 реквизит декоратора Footnote - это просто текст.Есть ли способ для этого быть узлом / картой сущности, который я могу прикрепить к новой сущности как дочерний элемент?

1 Ответ

3 голосов
/ 07 июня 2019

К сожалению, в настоящий момент Draft.js не поддерживает вложенные / дочерние объекты - к любому фрагменту содержимого в редакторе может быть прикреплена только одна сущность. Это имеет смысл для таких вещей, как ссылки, но очень проблематично при реализации функций «выделение» / «комментарии» или сносок, где в идеале они могут быть добавлены к произвольному тексту, независимо от того, есть ли у него ссылки или нет.

У вас есть несколько альтернатив - ни одна из которых не относится к Draftail / Wagtail, поэтому вы сможете найти ссылки на другие проекты на основе Draft.js, которые могли бы сделать это, чтобы обойти это ограничение. К сожалению, это довольно продвинутые реализации, со многими хитами, которые могут сделать их непрактичными / слишком дорогими для ваших нужд. Я также предлагаю вам оценить, действительно ли вы хотите реализовать это (см. Ниже) .

Добавить способ хранения данных сносок в ссылках

Таким образом, текст, имеющий ссылку, будет иметь только одну сущность, но вы все равно будете иметь свою сноску, прикрепленную к указанному тексту. Вы также можете иметь отдельную сущность сноски для вещей, которые не имеют связи, но могут быть сносками. Или создайте LINK_AND_OR_FOOTNOTE сущность, которая делает обе вещи одновременно.

Я думаю, что это может сработать относительно хорошо, если вы будете добавлять сноски только к целым ссылкам, а не только к их частям. В контексте Wagtail сущность LINK предопределена - это решение означает, что вам придется пересмотреть свое собственное, что может быть не лучшим подходом.

Хранить сноски как стили вместо сущностей

Я не совсем уверен, как вы управляете данными сносок, но если в тексте это всего лишь ссылки на содержимое «нижней части страницы», они могут потенциально быть созданы как стили (например, BOLD, ITALIC и т. д.).

  • Ссылка на сноску будет сохранена в типе стиля - например, FOOTNOTE_UUID_OF_12h3h53_FOOTNOTE_HERE.
  • Затем реализуйте пользовательские стили рендеринга, основываясь только на префиксе FOOTNOTE_.
  • Скорее всего, вам также потребуется добавить логику в пользовательский интерфейс «Выбор сносок», чтобы пользователи не могли добавлять несколько сносок на один фрагмент текста - если только это не кажется необходимой вам функцией

Я видел проекты Draft.js, делающие это в производстве, поэтому я знаю, что это выполнимо, но у меня нет примеров / кода с открытым исходным кодом, к сожалению, для обмена.


В качестве последнего варианта я бы посоветовал вам оценить, действительно ли вам нужно иметь сноски в тексте внутри ссылки. Это было бы намного легче построить, если бы они были вставлены в текст, относящийся к тексту, за которым они следуют, но прикреплены к отдельному тексту. В этом случае сноски будут представлять собой собственную сущность, но все равно не могут быть вставлены в ссылки, но все равно могут относиться к тексту, на котором находится ссылка, только из-за того, что отображаются рядом с ней.

Я думаю, что существует также реальный шанс, что его будет проще использовать для конечных пользователей - это звучит как проблема с удобством использования для кликабельного / перемещаемого представления сноски, которое должно быть внутри кликабельной / доступной ссылки

Вот, например, Википедия цитирует:

enter image description here

Реализация намного проще, потому что цитаты вставляются отдельно, и опыт конечного пользователя также приятен, потому что пользователи могут легко взаимодействовать либо со ссылкой, либо со сноской.

...