Продолжаю публиковать сниппеты, связанные с экосистемой CKEditor 5. Сегодня покажу как удалять контейнер с сохранением его содержимого.
Api предоставляет функцию writer.unwrap(element). Но беда в том, что функция не заботится о валидности дочерних элементов, когда те оказываются в родительском контейнере.
К примеру, у нас есть элемент mainContainer, в котором могут быть childElem1 и childElem2. Когда мы выполняем unwrap на mainContainer, childElem1 и childElem2 проваливаются ниже. Тут они могут быть даже валидными с т.з. модели, к примеру, если childElem1 транслируется в DOM как <span class=child1>. И span тег разрешен другим плагином.
А желательно бы и их найти и выполнить им unwrap, чтобы остался, к примеру, только текст, который был внутри дочерних контейнеров.
Организуем рекурсию:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
unwrap_content(element, elmsToRemove) { const { model } = this.editor; if (element.is('element')) { elmsToRemove.push(element.name); } model.change((writer) => { this._unwrap_element(writer, element, elmsToRemove); }); } _unwrap_element(writer, element, elmsToRemove) { // Получаем содержимое элемента const children = Array.from(element.getChildren()); // Вставляем содержимое перед удаляемым элементом for (const child of children) { if (child.is('element') && elmsToRemove.includes(child.name)) { this._unwrap_element(writer, child, elmsToRemove); } } // Удаляем сам элемент writer.unwrap(element); } |
Функция unwrap_content ожидает элемент, который нужно удалить, а также список имен других элементов, которые будут также подчищены.
В нашем случае нужно вызвать:
1 |
unwrap_content(elm, ['childElem1', 'childElem2']; |