UNPKG

@ckeditor/ckeditor5-list

Version:

Ordered and unordered lists feature to CKEditor 5.

82 lines (81 loc) 3.22 kB
/** * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved. * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ import { Plugin } from 'ckeditor5/src/core'; export default class AdjacentListsSupport extends Plugin { /** * @inheritDoc */ static get pluginName() { return 'AdjacentListsSupport'; } /** * @inheritDoc */ init() { const editor = this.editor; const model = editor.model; model.schema.register('listSeparator', { allowWhere: '$block', isBlock: true }); editor.conversion.for('upcast') // Add `listSeparator` element between similar list elements on upcast. .add(dispatcher => { dispatcher.on('element:ol', listSeparatorUpcastConverter()); dispatcher.on('element:ul', listSeparatorUpcastConverter()); }) // View to model transformation. .elementToElement({ model: 'listSeparator', view: 'ck-list-separator' }); // The `listSeparator` element should exist in the view, but should be invisible (hidden). editor.conversion.for('editingDowncast').elementToElement({ model: 'listSeparator', view: { name: 'div', classes: ['ck-list-separator', 'ck-hidden'] } }); // The `listSeparator` element should not exist in output data. editor.conversion.for('dataDowncast').elementToElement({ model: 'listSeparator', view: (modelElement, conversionApi) => { const viewElement = conversionApi.writer.createContainerElement('ck-list-separator'); conversionApi.writer.setCustomProperty('dataPipeline:transparentRendering', true, viewElement); viewElement.getFillerOffset = () => null; return viewElement; } }); } } /** * Inserts a `listSeparator` element between two lists of the same type (`ol` + `ol` or `ul` + `ul`). */ function listSeparatorUpcastConverter() { return (evt, data, conversionApi) => { const element = data.viewItem; const nextSibling = element.nextSibling; if (!nextSibling) { return; } if (element.name !== nextSibling.name) { return; } if (!data.modelRange) { Object.assign(data, conversionApi.convertChildren(data.viewItem, data.modelCursor)); } const writer = conversionApi.writer; const modelElement = writer.createElement('listSeparator'); // Try to insert `listSeparator` element on the current model cursor position. if (!conversionApi.safeInsert(modelElement, data.modelCursor)) { return; } const parts = conversionApi.getSplitParts(modelElement); // Extend model range with the range of the created listSeparator element. data.modelRange = writer.createRange(data.modelRange.start, writer.createPositionAfter(parts[parts.length - 1])); conversionApi.updateConversionResult(modelElement, data); }; }