1 | /**
|
2 | * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
|
3 | * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
4 | */
|
5 | /**
|
6 | * @module list/documentlist/documentlistediting
|
7 | */
|
8 | import { Plugin } from 'ckeditor5/src/core';
|
9 | import type { DowncastWriter, Element, ViewElement, Writer } from 'ckeditor5/src/engine';
|
10 | import { Delete } from 'ckeditor5/src/typing';
|
11 | import { Enter } from 'ckeditor5/src/enter';
|
12 | import DocumentListUtils from './documentlistutils';
|
13 | import { ListBlocksIterable } from './utils/listwalker';
|
14 | import '../../theme/documentlist.css';
|
15 | import '../../theme/list.css';
|
16 | /**
|
17 | * Map of model attributes applicable to list blocks.
|
18 | */
|
19 | export interface ListItemAttributesMap {
|
20 | listType?: 'numbered' | 'bulleted';
|
21 | listIndent?: number;
|
22 | listItemId?: string;
|
23 | }
|
24 | /**
|
25 | * The editing part of the document-list feature. It handles creating, editing and removing lists and list items.
|
26 | */
|
27 | export default class DocumentListEditing extends Plugin {
|
28 | /**
|
29 | * The list of registered downcast strategies.
|
30 | */
|
31 | private readonly _downcastStrategies;
|
32 | /**
|
33 | * @inheritDoc
|
34 | */
|
35 | static get pluginName(): 'DocumentListEditing';
|
36 | /**
|
37 | * @inheritDoc
|
38 | */
|
39 | static get requires(): readonly [typeof Enter, typeof Delete, typeof DocumentListUtils];
|
40 | /**
|
41 | * @inheritDoc
|
42 | */
|
43 | init(): void;
|
44 | /**
|
45 | * @inheritDoc
|
46 | */
|
47 | afterInit(): void;
|
48 | /**
|
49 | * Registers a downcast strategy.
|
50 | *
|
51 | * **Note**: Strategies must be registered in the `Plugin#init()` phase so that it can be applied
|
52 | * in the `DocumentListEditing#afterInit()`.
|
53 | *
|
54 | * @param strategy The downcast strategy to register.
|
55 | */
|
56 | registerDowncastStrategy(strategy: DowncastStrategy): void;
|
57 | /**
|
58 | * Returns list of model attribute names that should affect downcast conversion.
|
59 | */
|
60 | private _getListAttributeNames;
|
61 | /**
|
62 | * Attaches the listener to the {@link module:engine/view/document~Document#event:delete} event and handles backspace/delete
|
63 | * keys in and around document lists.
|
64 | */
|
65 | private _setupDeleteIntegration;
|
66 | /**
|
67 | * Attaches a listener to the {@link module:engine/view/document~Document#event:enter} event and handles enter key press
|
68 | * in document lists.
|
69 | */
|
70 | private _setupEnterIntegration;
|
71 | /**
|
72 | * Attaches a listener to the {@link module:engine/view/document~Document#event:tab} event and handles tab key and tab+shift keys
|
73 | * presses in document lists.
|
74 | */
|
75 | private _setupTabIntegration;
|
76 | /**
|
77 | * Registers the conversion helpers for the document-list feature.
|
78 | */
|
79 | private _setupConversion;
|
80 | /**
|
81 | * Registers model post-fixers.
|
82 | */
|
83 | private _setupModelPostFixing;
|
84 | /**
|
85 | * Integrates the feature with the clipboard via {@link module:engine/model/model~Model#insertContent} and
|
86 | * {@link module:engine/model/model~Model#getSelectedContent}.
|
87 | */
|
88 | private _setupClipboardIntegration;
|
89 | }
|
90 | /**
|
91 | * The downcast strategy.
|
92 | */
|
93 | export interface DowncastStrategy {
|
94 | /**
|
95 | * The scope of the downcast (whether it applies to LI or OL/UL).
|
96 | */
|
97 | scope: 'list' | 'item';
|
98 | /**
|
99 | * The model attribute name.
|
100 | */
|
101 | attributeName: string;
|
102 | /**
|
103 | * Sets the property on the view element.
|
104 | */
|
105 | setAttributeOnDowncast(writer: DowncastWriter, value: unknown, element: ViewElement): void;
|
106 | }
|
107 | /**
|
108 | * Event fired on changes detected on the model list element to verify if the view representation of a list element
|
109 | * is representing those attributes.
|
110 | *
|
111 | * It allows triggering a re-wrapping of a list item.
|
112 | *
|
113 | * @internal
|
114 | * @eventName ~DocumentListEditing#postFixer
|
115 | * @param listHead The head element of a list.
|
116 | * @param writer The writer to do changes with.
|
117 | * @param seenIds The set of already known IDs.
|
118 | * @returns If a post-fixer made a change of the model tree, it should return `true`.
|
119 | */
|
120 | export type DocumentListEditingPostFixerEvent = {
|
121 | name: 'postFixer';
|
122 | args: [
|
123 | {
|
124 | listNodes: ListBlocksIterable;
|
125 | listHead: Element;
|
126 | writer: Writer;
|
127 | seenIds: Set<string>;
|
128 | }
|
129 | ];
|
130 | return: boolean;
|
131 | };
|
132 | /**
|
133 | * Event fired on changes detected on the model list element to verify if the view representation of a list element
|
134 | * is representing those attributes.
|
135 | *
|
136 | * It allows triggering a re-wrapping of a list item.
|
137 | *
|
138 | * **Note**: For convenience this event is namespaced and could be captured as `checkAttributes:list` or `checkAttributes:item`.
|
139 | *
|
140 | * @internal
|
141 | * @eventName ~DocumentListEditing#checkAttributes
|
142 | */
|
143 | export type DocumentListEditingCheckAttributesEvent = {
|
144 | name: 'checkAttributes' | 'checkAttributes:list' | 'checkAttributes:item';
|
145 | args: [
|
146 | {
|
147 | viewElement: ViewElement & {
|
148 | id?: string;
|
149 | };
|
150 | modelAttributes: ListItemAttributesMap;
|
151 | }
|
152 | ];
|
153 | return: boolean;
|
154 | };
|