Как сделать так, чтобы каждый элемент был отдельным

#javascript #ckeditor #ckeditor5

#javascript #ckeditor #ckeditor5

Вопрос:

Как я могу отделить каждый из этих элементов. В настоящее время каждый элемент объединяется в один <span> элемент

 <span style="font-family:wingdings;">.4=??????</span>
<span style="font-family:symbol;">QPGH</span>
 

это генерируется приведенным ниже кодом

 import Command from '@ckeditor/ckeditor5-core/src/command';

export default class SymbolsCommand extends Command {
  execute({ charButtons }) {
    const { model } = this.editor;

    model.change((writer) => {
      const { selection } = model.document;
      const position = writer.createPositionAt(selection.getFirstPosition());
      console.log(charButtons, 'charButtons');

      const renderChars = () => charButtons.map(({ fontFamily, char }) => {
        writer.insertText(char, { fontFamily }, position);
      });
      return renderChars();
    });
  }

  refresh() {
    this.isEnabled = true;
  }
}

 

Я ожидаю, что результат будет выглядеть

 <span style="font-family:wingdings;">=</span>
<span style="font-family:wingdings;">?</span>
<span style="font-family:wingdings;">4</span>
<span style="font-family:symbol;">4</span>
<span style="font-family:symbol;">4</span>
...
 

Комментарии:

1. Чего вы пытаетесь достичь с помощью этого?

2. символ зависит от семейства шрифтов, например, символ F с символом семейства шрифтов должен возвращать другой юникод, чем символ F с wingdings семейства шрифтов

Ответ №1:

Объединение похожих <span> элементов — это поведение CKEditor 5 по умолчанию. Одна из причин заключается в том, что эти символы также объединяются в модели данных и представлены одним текстовым узлом. Не имеет значения, вставляете ли вы эти символы по одному или все сразу, если они имеют одинаковые атрибуты, они группируются вместе.

Один из способов предотвратить это — указать view .AttributeElement#id. К сожалению, это более сложная тема. Среди прочего, вам нужно будет предоставить преобразователи, которые будут создавать элементы атрибутов в представлении.

Я думаю, что есть два способа достичь вашей цели, оба потребуют от вас добавления конвертера вместо того, чтобы полагаться на fontFamily конвертер из плагина семейства шрифтов (я предполагаю, что это происходит здесь).

Использование атрибута в тексте с уникальным идентификатором AttributeElement#для предотвращения объединения <span>

Первое решение — ввести новый атрибут для текста (помните о расширении схемы) и предоставить для него конвертер. Давайте вызовем ключ атрибута symbol .

Конвертер должен был бы преобразовать данный текстовый узел посимвольно и установить уникальный идентификатор для каждого созданного диапазона атрибутов.

Это более сложное решение, хотя, вероятно, лучшее.

 editor.model.conversion.for( 'downcast' ).add( dispatcher => {
    dispatcher.on( 'attribute:symbol', ( evt, data, conversionApi ) => {
        // Provide your converter here. It should take `data.item`, iterate
        // through it's text content (`data.item.data`), use
        // `conversionApi.writer` to create attribute elements with unique ids
        // and use the writer and `conversionApi.mapper` to place them in the view.
    } );
} );
 

Вы могли бы основать конвертер на function wrap from downcasthelpers.js в движке: https://github.com/ckeditor/ckeditor5-engine/blob/master/src/conversion/downcasthelpers.js .

Вставка символов в качестве встроенных элементов

Другим решением было бы вставлять элементы с символами вместо просто текстовых узлов.

В этом случае, опять же, вы должны указать новый элемент модели в схеме. Возможно, расширение '$text' элемента.

Для преобразования вы, вероятно, могли бы использовать elementToElement помощников из editor.conversion.for() . Для downcast вам нужно будет указать view в качестве обратного вызова и установить там уникальный идентификатор (уникальные идентификаторы могут быть просто счетчиком, увеличиваемым на единицу каждый раз). Если elementToElement не будет работать для понижения (оно должно работать для повышения), вам нужно будет предоставить пользовательский конвертер .for( 'downcast' ).add( ... ) .

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

Хотелось бы, чтобы на данный момент был более простой способ добиться этого, но этот вариант использования встречается довольно редко, поэтому архитектура была ориентирована в другом направлении.