CKEditor5 - Как вы модифицируете дочерние текстовые узлы, не выбрасывая CKEditorError: model-nodelist-offset-out-of-of-bounds? - PullRequest
0 голосов
/ 28 апреля 2020

Для контекста здесь используется вариант замены текстовых узлов-заполнителей (мы называем их фрагментами) заранее заданным значением при изменении состояния редактора isReadOnly. Поэтому, когда состояние редактора isReadOnly меняется от false -> true, имя фрагмента должно обновляться, чтобы отражать значение фрагмента. Когда состояние меняется с true -> false, должно произойти обратное.

Пример:

Snippet Name: {{company_name}}
Snippet Value: Google

Пока что мой подход - проходить через текстовые узлы с помощью TreeWalker. Когда я прихожу к узлу сниппета, я получаю значение, которое должно быть заменено (которое идет как опора от родительского компонента), создает диапазон для нового узла, удаляет исходный узел сниппета и, наконец, выполняет команду, чтобы добавить новый фрагмент, который будет отображать его значение, а не имя. Если есть способ просто изменить текстовое значение узла, не удаляя его и не добавив новое, которое было бы идеальным.

        const rootRange = editor.model.createRangeIn(
          editor.model.document.getRoot()
        );

        // Iterate over all items in this range:
        for (const value of rootRange.getWalker()) {
          const {
            type,
            item: { textNode },
          } = value;

          if (type === 'text') {
            const snippetData = toMap(textNode.getAttribute('mention'));

            if (snippetData.size > 0) {
              const snippetName = snippetData.get('name');
              const snippetValue = snippetMap[snippetName];

              const item = {
                id: `{{${snippetName}}}`,
                name: snippetName,
                value: snippetValue,
              };

              editor.model.change((writer) => {
                const { parent, startOffset, offsetSize } = textNode;

                let range;

                if (snippetValue.length < snippetName.length) {
                  const start = writer.createPositionAt(parent, startOffset);
                  const rangeToRemove = writer.createRange(
                    start,
                    start.getShiftedBy(offsetSize)
                  );
                  writer.remove(rangeToRemove); // ERROR HAPPENS HERE
                  // writer.remove(textNode) // SAME ERROR WITH THIS APPROACH

                  const start = writer.createPositionAt(parent, startOffset);
                  const end = start.getShiftedBy(snippetValue.length);

                  range = writer.createRange(start, end);
                } else {
                  const start = writer.createPositionAt(parent, startOffset);
                  range = writer.createRange(start);

                  writer.remove(textNode);
                }

                // Add the new mention element
                return editor.execute('mention', {
                  mention: item,
                  text: item.value,
                  marker: '{',
                  range,
                });
              });
            }
          }
        }

Когда я пытаюсь удалить либо textNode, либо соответствующий диапазон, я получаю CKEditorError: model-nodelist-offset-out-of-bounds. Интересно то, что это происходит только в том случае, если полученный новый диапазон меньше исходного диапазона. Я могу выполнить преобразование без ошибки, если значение фрагмента> = к имени фрагмента (например, {{company_name}} / Boston Consulting Group).

Отказ от ответственности: я новичок в разработке с CKEditor, поэтому если есть лучший / другой подход к этому, я весь слух. Заранее спасибо за любые идеи.

...