/
view.ts
142 lines (129 loc) · 4.43 KB
/
view.ts
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/**
* @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
*/
/**
* @module list/documentlist/utils/view
*/
import type { DowncastWriter, ViewAttributeElement, ViewDocumentFragment, ViewElement, ViewNode } from 'ckeditor5/src/engine';
/**
* Checks if view element is a list type (ul or ol).
*
* @internal
*/
export function isListView( viewElement: ViewNode | ViewDocumentFragment ): viewElement is ViewElement & { name: 'ul' | 'ol' } {
return viewElement.is( 'element', 'ol' ) || viewElement.is( 'element', 'ul' );
}
/**
* Checks if view element is a list item (li).
*
* @internal
*/
export function isListItemView( viewElement: ViewNode | ViewDocumentFragment ): viewElement is ViewElement & { name: 'li' } {
return viewElement.is( 'element', 'li' );
}
/**
* Calculates the indent value for a list item. Handles HTML compliant and non-compliant lists.
*
* Also, fixes non HTML compliant lists indents:
*
* ```
* before: fixed list:
* OL OL
* |-> LI (parent LIs: 0) |-> LI (indent: 0)
* |-> OL |-> OL
* |-> OL |
* | |-> OL |
* | |-> OL |
* | |-> LI (parent LIs: 1) |-> LI (indent: 1)
* |-> LI (parent LIs: 1) |-> LI (indent: 1)
*
* before: fixed list:
* OL OL
* |-> OL |
* |-> OL |
* |-> OL |
* |-> LI (parent LIs: 0) |-> LI (indent: 0)
*
* before: fixed list:
* OL OL
* |-> LI (parent LIs: 0) |-> LI (indent: 0)
* |-> OL |-> OL
* |-> LI (parent LIs: 0) |-> LI (indent: 1)
* ```
*
* @internal
*/
export function getIndent( listItem: ViewElement ): number {
let indent = 0;
let parent = listItem.parent;
while ( parent ) {
// Each LI in the tree will result in an increased indent for HTML compliant lists.
if ( isListItemView( parent ) ) {
indent++;
} else {
// If however the list is nested in other list we should check previous sibling of any of the list elements...
const previousSibling = ( parent as ViewElement ).previousSibling;
// ...because the we might need increase its indent:
// before: fixed list:
// OL OL
// |-> LI (parent LIs: 0) |-> LI (indent: 0)
// |-> OL |-> OL
// |-> LI (parent LIs: 0) |-> LI (indent: 1)
if ( previousSibling && isListItemView( previousSibling ) ) {
indent++;
}
}
parent = parent.parent;
}
return indent;
}
/**
* Creates a list attribute element (ol or ul).
*
* @internal
*/
export function createListElement(
writer: DowncastWriter,
indent: number,
type: 'bulleted' | 'numbered' | 'todo',
id = getViewElementIdForListType( type, indent )
): ViewAttributeElement {
// Negative priorities so that restricted editing attribute won't wrap lists.
return writer.createAttributeElement( getViewElementNameForListType( type ), null, {
priority: 2 * indent / 100 - 100,
id
} );
}
/**
* Creates a list item attribute element (li).
*
* @internal
*/
export function createListItemElement(
writer: DowncastWriter,
indent: number,
id: string
): ViewAttributeElement {
// Negative priorities so that restricted editing attribute won't wrap list items.
return writer.createAttributeElement( 'li', null, {
priority: ( 2 * indent + 1 ) / 100 - 100,
id
} );
}
/**
* Returns a view element name for the given list type.
*
* @internal
*/
export function getViewElementNameForListType( type?: 'bulleted' | 'numbered' | 'todo' ): 'ol' | 'ul' {
return type == 'numbered' ? 'ol' : 'ul';
}
/**
* Returns a view element ID for the given list type and indent.
*
* @internal
*/
export function getViewElementIdForListType( type?: 'bulleted' | 'numbered' | 'todo', indent?: number ): string {
return `list-${ type }-${ indent }`;
}