@dangl/angular-material-shared 2.9.0-beta0037 → 2.9.0-beta0040
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/dangl-angular-material-shared-tiny-mce.mjs +29 -35
- package/fesm2022/dangl-angular-material-shared-tiny-mce.mjs.map +1 -1
- package/fesm2022/dangl-angular-material-shared.mjs +36 -51
- package/fesm2022/dangl-angular-material-shared.mjs.map +1 -1
- package/package.json +11 -10
- package/styles/material-theme.scss +1 -1
- package/styles/material-variables.scss +5 -5
- package/tinymce-assets/icons/default/icons.js +46 -9
- package/tinymce-assets/icons/default/icons.min.js +1 -1
- package/tinymce-assets/models/dom/model.js +8198 -7244
- package/tinymce-assets/models/dom/model.min.js +1 -4
- package/tinymce-assets/plugins/accordion/plugin.js +1174 -879
- package/tinymce-assets/plugins/accordion/plugin.min.js +1 -4
- package/tinymce-assets/plugins/advlist/plugin.js +412 -200
- package/tinymce-assets/plugins/advlist/plugin.min.js +1 -4
- package/tinymce-assets/plugins/anchor/plugin.js +189 -166
- package/tinymce-assets/plugins/anchor/plugin.min.js +1 -4
- package/tinymce-assets/plugins/autolink/plugin.js +310 -220
- package/tinymce-assets/plugins/autolink/plugin.min.js +1 -4
- package/tinymce-assets/plugins/autoresize/plugin.js +180 -149
- package/tinymce-assets/plugins/autoresize/plugin.min.js +1 -4
- package/tinymce-assets/plugins/autosave/plugin.js +208 -189
- package/tinymce-assets/plugins/autosave/plugin.min.js +1 -4
- package/tinymce-assets/plugins/charmap/plugin.js +905 -1566
- package/tinymce-assets/plugins/charmap/plugin.min.js +1 -4
- package/tinymce-assets/plugins/code/plugin.js +73 -61
- package/tinymce-assets/plugins/code/plugin.min.js +0 -3
- package/tinymce-assets/plugins/codesample/plugin.js +3593 -2402
- package/tinymce-assets/plugins/codesample/plugin.min.js +8 -3
- package/tinymce-assets/plugins/directionality/plugin.js +545 -304
- package/tinymce-assets/plugins/directionality/plugin.min.js +1 -4
- package/tinymce-assets/plugins/emoticons/js/emojiimages.min.js +0 -2
- package/tinymce-assets/plugins/emoticons/js/emojis.min.js +0 -1
- package/tinymce-assets/plugins/emoticons/plugin.js +702 -488
- package/tinymce-assets/plugins/emoticons/plugin.min.js +1 -4
- package/tinymce-assets/plugins/fullscreen/plugin.js +1409 -1049
- package/tinymce-assets/plugins/fullscreen/plugin.min.js +1 -4
- package/tinymce-assets/plugins/help/js/i18n/keynav/ar.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/bg_BG.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/ca.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/cs.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/da.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/de.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/el.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/en.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/es.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/eu.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/fa.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/fi.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/fr_FR.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/he_IL.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/hi.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/hr.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/hu_HU.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/id.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/it.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/ja.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/kk.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/ko_KR.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/ms.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/nb_NO.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/nl.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/pl.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/pt_BR.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/pt_PT.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/ro.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/ru.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/sk.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/sl_SI.js +5 -2
- package/tinymce-assets/plugins/help/js/i18n/keynav/sv_SE.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/th_TH.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/tr.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/uk.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/vi.js +4 -1
- package/tinymce-assets/plugins/help/js/i18n/keynav/zh_CN.js +8 -5
- package/tinymce-assets/plugins/help/js/i18n/keynav/zh_TW.js +4 -1
- package/tinymce-assets/plugins/help/plugin.js +739 -809
- package/tinymce-assets/plugins/help/plugin.min.js +1 -4
- package/tinymce-assets/plugins/image/plugin.js +1475 -1291
- package/tinymce-assets/plugins/image/plugin.min.js +1 -4
- package/tinymce-assets/plugins/importcss/plugin.js +328 -269
- package/tinymce-assets/plugins/importcss/plugin.min.js +1 -4
- package/tinymce-assets/plugins/insertdatetime/plugin.js +140 -141
- package/tinymce-assets/plugins/insertdatetime/plugin.min.js +1 -4
- package/tinymce-assets/plugins/link/plugin.js +1419 -1084
- package/tinymce-assets/plugins/link/plugin.min.js +1 -4
- package/tinymce-assets/plugins/lists/plugin.js +2177 -1805
- package/tinymce-assets/plugins/lists/plugin.min.js +1 -4
- package/tinymce-assets/plugins/media/plugin.js +1305 -1047
- package/tinymce-assets/plugins/media/plugin.min.js +1 -4
- package/tinymce-assets/plugins/nonbreaking/plugin.js +93 -88
- package/tinymce-assets/plugins/nonbreaking/plugin.min.js +0 -3
- package/tinymce-assets/plugins/pagebreak/plugin.js +91 -85
- package/tinymce-assets/plugins/pagebreak/plugin.min.js +0 -3
- package/tinymce-assets/plugins/preview/plugin.js +742 -74
- package/tinymce-assets/plugins/preview/plugin.min.js +1 -4
- package/tinymce-assets/plugins/quickbars/plugin.js +582 -375
- package/tinymce-assets/plugins/quickbars/plugin.min.js +1 -4
- package/tinymce-assets/plugins/save/plugin.js +100 -82
- package/tinymce-assets/plugins/save/plugin.min.js +1 -4
- package/tinymce-assets/plugins/searchreplace/plugin.js +1183 -906
- package/tinymce-assets/plugins/searchreplace/plugin.min.js +1 -4
- package/tinymce-assets/plugins/table/plugin.js +3651 -3094
- package/tinymce-assets/plugins/table/plugin.min.js +1 -4
- package/tinymce-assets/plugins/visualblocks/plugin.js +71 -63
- package/tinymce-assets/plugins/visualblocks/plugin.min.js +1 -4
- package/tinymce-assets/plugins/visualchars/plugin.js +685 -436
- package/tinymce-assets/plugins/visualchars/plugin.min.js +1 -4
- package/tinymce-assets/plugins/wordcount/plugin.js +382 -307
- package/tinymce-assets/plugins/wordcount/plugin.min.js +1 -4
- package/tinymce-assets/skins/content/dark/content.css +9 -0
- package/tinymce-assets/skins/content/dark/content.js +10 -2
- package/tinymce-assets/skins/content/dark/content.min.css +9 -0
- package/tinymce-assets/skins/content/default/content.css +9 -0
- package/tinymce-assets/skins/content/default/content.js +10 -2
- package/tinymce-assets/skins/content/default/content.min.css +9 -0
- package/tinymce-assets/skins/content/document/content.css +9 -0
- package/tinymce-assets/skins/content/document/content.js +10 -2
- package/tinymce-assets/skins/content/document/content.min.css +9 -0
- package/tinymce-assets/skins/content/tinymce-5/content.css +9 -0
- package/tinymce-assets/skins/content/tinymce-5/content.js +10 -2
- package/tinymce-assets/skins/content/tinymce-5/content.min.css +9 -0
- package/tinymce-assets/skins/content/tinymce-5-dark/content.css +9 -0
- package/tinymce-assets/skins/content/tinymce-5-dark/content.js +10 -2
- package/tinymce-assets/skins/content/tinymce-5-dark/content.min.css +9 -0
- package/tinymce-assets/skins/content/writer/content.css +9 -0
- package/tinymce-assets/skins/content/writer/content.js +10 -2
- package/tinymce-assets/skins/content/writer/content.min.css +9 -0
- package/tinymce-assets/skins/ui/oxide/content.css +157 -49
- package/tinymce-assets/skins/ui/oxide/content.inline.css +157 -49
- package/tinymce-assets/skins/ui/oxide/content.inline.js +10 -2
- package/tinymce-assets/skins/ui/oxide/content.inline.min.css +10 -1
- package/tinymce-assets/skins/ui/oxide/content.js +10 -2
- package/tinymce-assets/skins/ui/oxide/content.min.css +10 -1
- package/tinymce-assets/skins/ui/oxide/skin.css +1592 -214
- package/tinymce-assets/skins/ui/oxide/skin.js +1 -2
- package/tinymce-assets/skins/ui/oxide/skin.min.css +1 -1
- package/tinymce-assets/skins/ui/oxide/skin.shadowdom.js +1 -2
- package/tinymce-assets/skins/ui/oxide-dark/content.css +157 -42
- package/tinymce-assets/skins/ui/oxide-dark/content.inline.css +157 -49
- package/tinymce-assets/skins/ui/oxide-dark/content.inline.js +10 -2
- package/tinymce-assets/skins/ui/oxide-dark/content.inline.min.css +10 -1
- package/tinymce-assets/skins/ui/oxide-dark/content.js +10 -2
- package/tinymce-assets/skins/ui/oxide-dark/content.min.css +10 -1
- package/tinymce-assets/skins/ui/oxide-dark/skin.css +1595 -217
- package/tinymce-assets/skins/ui/oxide-dark/skin.js +1 -2
- package/tinymce-assets/skins/ui/oxide-dark/skin.min.css +1 -1
- package/tinymce-assets/skins/ui/oxide-dark/skin.shadowdom.js +1 -2
- package/tinymce-assets/skins/ui/tinymce-5/content.css +157 -49
- package/tinymce-assets/skins/ui/tinymce-5/content.inline.css +157 -49
- package/tinymce-assets/skins/ui/tinymce-5/content.inline.js +10 -2
- package/tinymce-assets/skins/ui/tinymce-5/content.inline.min.css +10 -1
- package/tinymce-assets/skins/ui/tinymce-5/content.js +10 -2
- package/tinymce-assets/skins/ui/tinymce-5/content.min.css +10 -1
- package/tinymce-assets/skins/ui/tinymce-5/skin.css +1606 -203
- package/tinymce-assets/skins/ui/tinymce-5/skin.js +1 -2
- package/tinymce-assets/skins/ui/tinymce-5/skin.min.css +1 -1
- package/tinymce-assets/skins/ui/tinymce-5/skin.shadowdom.js +1 -2
- package/tinymce-assets/skins/ui/tinymce-5-dark/content.css +157 -42
- package/tinymce-assets/skins/ui/tinymce-5-dark/content.inline.css +157 -49
- package/tinymce-assets/skins/ui/tinymce-5-dark/content.inline.js +10 -2
- package/tinymce-assets/skins/ui/tinymce-5-dark/content.inline.min.css +10 -1
- package/tinymce-assets/skins/ui/tinymce-5-dark/content.js +10 -2
- package/tinymce-assets/skins/ui/tinymce-5-dark/content.min.css +10 -1
- package/tinymce-assets/skins/ui/tinymce-5-dark/skin.css +1607 -204
- package/tinymce-assets/skins/ui/tinymce-5-dark/skin.js +1 -2
- package/tinymce-assets/skins/ui/tinymce-5-dark/skin.min.css +1 -1
- package/tinymce-assets/skins/ui/tinymce-5-dark/skin.shadowdom.js +1 -2
- package/tinymce-assets/themes/silver/theme.js +32786 -28738
- package/tinymce-assets/themes/silver/theme.min.js +1 -4
- package/types/dangl-angular-material-shared-tiny-mce.d.ts +12 -13
- package/types/dangl-angular-material-shared.d.ts +26 -26
- package/tinymce-assets/plugins/template/index.js +0 -7
- package/tinymce-assets/plugins/template/plugin.js +0 -567
- package/tinymce-assets/plugins/template/plugin.min.js +0 -4
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* TinyMCE version
|
|
2
|
+
* TinyMCE version 7.9.3 (2026-05-19)
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
(function () {
|
|
@@ -7,589 +7,921 @@
|
|
|
7
7
|
|
|
8
8
|
var global$7 = tinymce.util.Tools.resolve('tinymce.PluginManager');
|
|
9
9
|
|
|
10
|
+
/* eslint-disable @typescript-eslint/no-wrapper-object-types */
|
|
10
11
|
const hasProto = (v, constructor, predicate) => {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
12
|
+
var _a;
|
|
13
|
+
if (predicate(v, constructor.prototype)) {
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
// String-based fallback time
|
|
18
|
+
return ((_a = v.constructor) === null || _a === void 0 ? void 0 : _a.name) === constructor.name;
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
const typeOf = (x) => {
|
|
22
|
+
const t = typeof x;
|
|
23
|
+
if (x === null) {
|
|
24
|
+
return 'null';
|
|
25
|
+
}
|
|
26
|
+
else if (t === 'object' && Array.isArray(x)) {
|
|
27
|
+
return 'array';
|
|
28
|
+
}
|
|
29
|
+
else if (t === 'object' && hasProto(x, String, (o, proto) => proto.isPrototypeOf(o))) {
|
|
30
|
+
return 'string';
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
return t;
|
|
34
|
+
}
|
|
29
35
|
};
|
|
30
|
-
const isType$1 = type => value => typeOf(value) === type;
|
|
31
|
-
const isSimpleType = type => value => typeof value === type;
|
|
36
|
+
const isType$1 = (type) => (value) => typeOf(value) === type;
|
|
37
|
+
const isSimpleType = (type) => (value) => typeof value === type;
|
|
32
38
|
const isString = isType$1('string');
|
|
33
39
|
const isObject = isType$1('object');
|
|
34
40
|
const isArray = isType$1('array');
|
|
35
41
|
const isBoolean = isSimpleType('boolean');
|
|
36
|
-
const isNullable = a => a === null || a === undefined;
|
|
37
|
-
const isNonNullable = a => !isNullable(a);
|
|
42
|
+
const isNullable = (a) => a === null || a === undefined;
|
|
43
|
+
const isNonNullable = (a) => !isNullable(a);
|
|
38
44
|
const isFunction = isSimpleType('function');
|
|
39
45
|
const isNumber = isSimpleType('number');
|
|
40
46
|
|
|
41
|
-
const noop = () => {
|
|
42
|
-
|
|
43
|
-
const compose1 = (fbc, fab) => a => fbc(fab(a));
|
|
44
|
-
const constant = value => {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
47
|
+
const noop = () => { };
|
|
48
|
+
/** Compose two unary functions. Similar to compose, but avoids using Function.prototype.apply. */
|
|
49
|
+
const compose1 = (fbc, fab) => (a) => fbc(fab(a));
|
|
50
|
+
const constant = (value) => {
|
|
51
|
+
return () => {
|
|
52
|
+
return value;
|
|
53
|
+
};
|
|
48
54
|
};
|
|
49
55
|
const tripleEquals = (a, b) => {
|
|
50
|
-
|
|
56
|
+
return a === b;
|
|
51
57
|
};
|
|
58
|
+
// eslint-disable-next-line prefer-arrow/prefer-arrow-functions
|
|
52
59
|
function curry(fn, ...initialArgs) {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
60
|
+
return (...restArgs) => {
|
|
61
|
+
const all = initialArgs.concat(restArgs);
|
|
62
|
+
return fn.apply(null, all);
|
|
63
|
+
};
|
|
57
64
|
}
|
|
58
|
-
const not = f => t => !f(t);
|
|
65
|
+
const not = (f) => (t) => !f(t);
|
|
59
66
|
const never = constant(false);
|
|
60
67
|
|
|
68
|
+
/**
|
|
69
|
+
* The `Optional` type represents a value (of any type) that potentially does
|
|
70
|
+
* not exist. Any `Optional<T>` can either be a `Some<T>` (in which case the
|
|
71
|
+
* value does exist) or a `None` (in which case the value does not exist). This
|
|
72
|
+
* module defines a whole lot of FP-inspired utility functions for dealing with
|
|
73
|
+
* `Optional` objects.
|
|
74
|
+
*
|
|
75
|
+
* Comparison with null or undefined:
|
|
76
|
+
* - We don't get fancy null coalescing operators with `Optional`
|
|
77
|
+
* - We do get fancy helper functions with `Optional`
|
|
78
|
+
* - `Optional` support nesting, and allow for the type to still be nullable (or
|
|
79
|
+
* another `Optional`)
|
|
80
|
+
* - There is no option to turn off strict-optional-checks like there is for
|
|
81
|
+
* strict-null-checks
|
|
82
|
+
*/
|
|
61
83
|
class Optional {
|
|
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
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
84
|
+
// The internal representation has a `tag` and a `value`, but both are
|
|
85
|
+
// private: able to be console.logged, but not able to be accessed by code
|
|
86
|
+
constructor(tag, value) {
|
|
87
|
+
this.tag = tag;
|
|
88
|
+
this.value = value;
|
|
89
|
+
}
|
|
90
|
+
// --- Identities ---
|
|
91
|
+
/**
|
|
92
|
+
* Creates a new `Optional<T>` that **does** contain a value.
|
|
93
|
+
*/
|
|
94
|
+
static some(value) {
|
|
95
|
+
return new Optional(true, value);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Create a new `Optional<T>` that **does not** contain a value. `T` can be
|
|
99
|
+
* any type because we don't actually have a `T`.
|
|
100
|
+
*/
|
|
101
|
+
static none() {
|
|
102
|
+
return Optional.singletonNone;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Perform a transform on an `Optional` type. Regardless of whether this
|
|
106
|
+
* `Optional` contains a value or not, `fold` will return a value of type `U`.
|
|
107
|
+
* If this `Optional` does not contain a value, the `U` will be created by
|
|
108
|
+
* calling `onNone`. If this `Optional` does contain a value, the `U` will be
|
|
109
|
+
* created by calling `onSome`.
|
|
110
|
+
*
|
|
111
|
+
* For the FP enthusiasts in the room, this function:
|
|
112
|
+
* 1. Could be used to implement all of the functions below
|
|
113
|
+
* 2. Forms a catamorphism
|
|
114
|
+
*/
|
|
115
|
+
fold(onNone, onSome) {
|
|
116
|
+
if (this.tag) {
|
|
117
|
+
return onSome(this.value);
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
return onNone();
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Determine if this `Optional` object contains a value.
|
|
125
|
+
*/
|
|
126
|
+
isSome() {
|
|
127
|
+
return this.tag;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Determine if this `Optional` object **does not** contain a value.
|
|
131
|
+
*/
|
|
132
|
+
isNone() {
|
|
133
|
+
return !this.tag;
|
|
134
|
+
}
|
|
135
|
+
// --- Functor (name stolen from Haskell / maths) ---
|
|
136
|
+
/**
|
|
137
|
+
* Perform a transform on an `Optional` object, **if** there is a value. If
|
|
138
|
+
* you provide a function to turn a T into a U, this is the function you use
|
|
139
|
+
* to turn an `Optional<T>` into an `Optional<U>`. If this **does** contain
|
|
140
|
+
* a value then the output will also contain a value (that value being the
|
|
141
|
+
* output of `mapper(this.value)`), and if this **does not** contain a value
|
|
142
|
+
* then neither will the output.
|
|
143
|
+
*/
|
|
144
|
+
map(mapper) {
|
|
145
|
+
if (this.tag) {
|
|
146
|
+
return Optional.some(mapper(this.value));
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
return Optional.none();
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
// --- Monad (name stolen from Haskell / maths) ---
|
|
153
|
+
/**
|
|
154
|
+
* Perform a transform on an `Optional` object, **if** there is a value.
|
|
155
|
+
* Unlike `map`, here the transform itself also returns an `Optional`.
|
|
156
|
+
*/
|
|
157
|
+
bind(binder) {
|
|
158
|
+
if (this.tag) {
|
|
159
|
+
return binder(this.value);
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
return Optional.none();
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
// --- Traversable (name stolen from Haskell / maths) ---
|
|
166
|
+
/**
|
|
167
|
+
* For a given predicate, this function finds out if there **exists** a value
|
|
168
|
+
* inside this `Optional` object that meets the predicate. In practice, this
|
|
169
|
+
* means that for `Optional`s that do not contain a value it returns false (as
|
|
170
|
+
* no predicate-meeting value exists).
|
|
171
|
+
*/
|
|
172
|
+
exists(predicate) {
|
|
173
|
+
return this.tag && predicate(this.value);
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* For a given predicate, this function finds out if **all** the values inside
|
|
177
|
+
* this `Optional` object meet the predicate. In practice, this means that
|
|
178
|
+
* for `Optional`s that do not contain a value it returns true (as all 0
|
|
179
|
+
* objects do meet the predicate).
|
|
180
|
+
*/
|
|
181
|
+
forall(predicate) {
|
|
182
|
+
return !this.tag || predicate(this.value);
|
|
183
|
+
}
|
|
184
|
+
filter(predicate) {
|
|
185
|
+
if (!this.tag || predicate(this.value)) {
|
|
186
|
+
return this;
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
return Optional.none();
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
// --- Getters ---
|
|
193
|
+
/**
|
|
194
|
+
* Get the value out of the inside of the `Optional` object, using a default
|
|
195
|
+
* `replacement` value if the provided `Optional` object does not contain a
|
|
196
|
+
* value.
|
|
197
|
+
*/
|
|
198
|
+
getOr(replacement) {
|
|
199
|
+
return this.tag ? this.value : replacement;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Get the value out of the inside of the `Optional` object, using a default
|
|
203
|
+
* `replacement` value if the provided `Optional` object does not contain a
|
|
204
|
+
* value. Unlike `getOr`, in this method the `replacement` object is also
|
|
205
|
+
* `Optional` - meaning that this method will always return an `Optional`.
|
|
206
|
+
*/
|
|
207
|
+
or(replacement) {
|
|
208
|
+
return this.tag ? this : replacement;
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Get the value out of the inside of the `Optional` object, using a default
|
|
212
|
+
* `replacement` value if the provided `Optional` object does not contain a
|
|
213
|
+
* value. Unlike `getOr`, in this method the `replacement` value is
|
|
214
|
+
* "thunked" - that is to say that you don't pass a value to `getOrThunk`, you
|
|
215
|
+
* pass a function which (if called) will **return** the `value` you want to
|
|
216
|
+
* use.
|
|
217
|
+
*/
|
|
218
|
+
getOrThunk(thunk) {
|
|
219
|
+
return this.tag ? this.value : thunk();
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Get the value out of the inside of the `Optional` object, using a default
|
|
223
|
+
* `replacement` value if the provided Optional object does not contain a
|
|
224
|
+
* value.
|
|
225
|
+
*
|
|
226
|
+
* Unlike `or`, in this method the `replacement` value is "thunked" - that is
|
|
227
|
+
* to say that you don't pass a value to `orThunk`, you pass a function which
|
|
228
|
+
* (if called) will **return** the `value` you want to use.
|
|
229
|
+
*
|
|
230
|
+
* Unlike `getOrThunk`, in this method the `replacement` value is also
|
|
231
|
+
* `Optional`, meaning that this method will always return an `Optional`.
|
|
232
|
+
*/
|
|
233
|
+
orThunk(thunk) {
|
|
234
|
+
return this.tag ? this : thunk();
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Get the value out of the inside of the `Optional` object, throwing an
|
|
238
|
+
* exception if the provided `Optional` object does not contain a value.
|
|
239
|
+
*
|
|
240
|
+
* WARNING:
|
|
241
|
+
* You should only be using this function if you know that the `Optional`
|
|
242
|
+
* object **is not** empty (otherwise you're throwing exceptions in production
|
|
243
|
+
* code, which is bad).
|
|
244
|
+
*
|
|
245
|
+
* In tests this is more acceptable.
|
|
246
|
+
*
|
|
247
|
+
* Prefer other methods to this, such as `.each`.
|
|
248
|
+
*/
|
|
249
|
+
getOrDie(message) {
|
|
250
|
+
if (!this.tag) {
|
|
251
|
+
throw new Error(message !== null && message !== void 0 ? message : 'Called getOrDie on None');
|
|
252
|
+
}
|
|
253
|
+
else {
|
|
254
|
+
return this.value;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
// --- Interop with null and undefined ---
|
|
258
|
+
/**
|
|
259
|
+
* Creates an `Optional` value from a nullable (or undefined-able) input.
|
|
260
|
+
* Null, or undefined, is converted to `None`, and anything else is converted
|
|
261
|
+
* to `Some`.
|
|
262
|
+
*/
|
|
263
|
+
static from(value) {
|
|
264
|
+
return isNonNullable(value) ? Optional.some(value) : Optional.none();
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Converts an `Optional` to a nullable type, by getting the value if it
|
|
268
|
+
* exists, or returning `null` if it does not.
|
|
269
|
+
*/
|
|
270
|
+
getOrNull() {
|
|
271
|
+
return this.tag ? this.value : null;
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Converts an `Optional` to an undefined-able type, by getting the value if
|
|
275
|
+
* it exists, or returning `undefined` if it does not.
|
|
276
|
+
*/
|
|
277
|
+
getOrUndefined() {
|
|
278
|
+
return this.value;
|
|
279
|
+
}
|
|
280
|
+
// --- Utilities ---
|
|
281
|
+
/**
|
|
282
|
+
* If the `Optional` contains a value, perform an action on that value.
|
|
283
|
+
* Unlike the rest of the methods on this type, `.each` has side-effects. If
|
|
284
|
+
* you want to transform an `Optional<T>` **into** something, then this is not
|
|
285
|
+
* the method for you. If you want to use an `Optional<T>` to **do**
|
|
286
|
+
* something, then this is the method for you - provided you're okay with not
|
|
287
|
+
* doing anything in the case where the `Optional` doesn't have a value inside
|
|
288
|
+
* it. If you're not sure whether your use-case fits into transforming
|
|
289
|
+
* **into** something or **doing** something, check whether it has a return
|
|
290
|
+
* value. If it does, you should be performing a transform.
|
|
291
|
+
*/
|
|
292
|
+
each(worker) {
|
|
293
|
+
if (this.tag) {
|
|
294
|
+
worker(this.value);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Turn the `Optional` object into an array that contains all of the values
|
|
299
|
+
* stored inside the `Optional`. In practice, this means the output will have
|
|
300
|
+
* either 0 or 1 elements.
|
|
301
|
+
*/
|
|
302
|
+
toArray() {
|
|
303
|
+
return this.tag ? [this.value] : [];
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Turn the `Optional` object into a string for debugging or printing. Not
|
|
307
|
+
* recommended for production code, but good for debugging. Also note that
|
|
308
|
+
* these days an `Optional` object can be logged to the console directly, and
|
|
309
|
+
* its inner value (if it exists) will be visible.
|
|
310
|
+
*/
|
|
311
|
+
toString() {
|
|
312
|
+
return this.tag ? `some(${this.value})` : 'none()';
|
|
313
|
+
}
|
|
151
314
|
}
|
|
315
|
+
// Sneaky optimisation: every instance of Optional.none is identical, so just
|
|
316
|
+
// reuse the same object
|
|
152
317
|
Optional.singletonNone = new Optional(false);
|
|
153
318
|
|
|
319
|
+
/* eslint-disable @typescript-eslint/unbound-method */
|
|
154
320
|
const nativeSlice = Array.prototype.slice;
|
|
155
321
|
const nativeIndexOf = Array.prototype.indexOf;
|
|
156
322
|
const nativePush = Array.prototype.push;
|
|
323
|
+
/* eslint-enable */
|
|
157
324
|
const rawIndexOf = (ts, t) => nativeIndexOf.call(ts, t);
|
|
158
325
|
const contains$1 = (xs, x) => rawIndexOf(xs, x) > -1;
|
|
159
326
|
const exists = (xs, pred) => {
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
327
|
+
for (let i = 0, len = xs.length; i < len; i++) {
|
|
328
|
+
const x = xs[i];
|
|
329
|
+
if (pred(x, i)) {
|
|
330
|
+
return true;
|
|
331
|
+
}
|
|
164
332
|
}
|
|
165
|
-
|
|
166
|
-
return false;
|
|
333
|
+
return false;
|
|
167
334
|
};
|
|
168
335
|
const map = (xs, f) => {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
const
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
336
|
+
// pre-allocating array size when it's guaranteed to be known
|
|
337
|
+
// http://jsperf.com/push-allocated-vs-dynamic/22
|
|
338
|
+
const len = xs.length;
|
|
339
|
+
const r = new Array(len);
|
|
340
|
+
for (let i = 0; i < len; i++) {
|
|
341
|
+
const x = xs[i];
|
|
342
|
+
r[i] = f(x, i);
|
|
343
|
+
}
|
|
344
|
+
return r;
|
|
176
345
|
};
|
|
346
|
+
// Unwound implementing other functions in terms of each.
|
|
347
|
+
// The code size is roughly the same, and it should allow for better optimisation.
|
|
348
|
+
// const each = function<T, U>(xs: T[], f: (x: T, i?: number, xs?: T[]) => void): void {
|
|
177
349
|
const each$1 = (xs, f) => {
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
}
|
|
182
|
-
};
|
|
183
|
-
const filter$1 = (xs, pred) => {
|
|
184
|
-
const r = [];
|
|
185
|
-
for (let i = 0, len = xs.length; i < len; i++) {
|
|
186
|
-
const x = xs[i];
|
|
187
|
-
if (pred(x, i)) {
|
|
188
|
-
r.push(x);
|
|
350
|
+
for (let i = 0, len = xs.length; i < len; i++) {
|
|
351
|
+
const x = xs[i];
|
|
352
|
+
f(x, i);
|
|
189
353
|
}
|
|
190
|
-
}
|
|
191
|
-
return r;
|
|
192
354
|
};
|
|
193
|
-
const
|
|
194
|
-
if (xs.length === 0) {
|
|
195
|
-
return [];
|
|
196
|
-
} else {
|
|
197
|
-
let wasType = f(xs[0]);
|
|
355
|
+
const filter$1 = (xs, pred) => {
|
|
198
356
|
const r = [];
|
|
199
|
-
let group = [];
|
|
200
357
|
for (let i = 0, len = xs.length; i < len; i++) {
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
group = [];
|
|
206
|
-
}
|
|
207
|
-
wasType = type;
|
|
208
|
-
group.push(x);
|
|
209
|
-
}
|
|
210
|
-
if (group.length !== 0) {
|
|
211
|
-
r.push(group);
|
|
358
|
+
const x = xs[i];
|
|
359
|
+
if (pred(x, i)) {
|
|
360
|
+
r.push(x);
|
|
361
|
+
}
|
|
212
362
|
}
|
|
213
363
|
return r;
|
|
214
|
-
|
|
364
|
+
};
|
|
365
|
+
/*
|
|
366
|
+
* Groups an array into contiguous arrays of like elements. Whether an element is like or not depends on f.
|
|
367
|
+
*
|
|
368
|
+
* f is a function that derives a value from an element - e.g. true or false, or a string.
|
|
369
|
+
* Elements are like if this function generates the same value for them (according to ===).
|
|
370
|
+
*
|
|
371
|
+
*
|
|
372
|
+
* Order of the elements is preserved. Arr.flatten() on the result will return the original list, as with Haskell groupBy function.
|
|
373
|
+
* For a good explanation, see the group function (which is a special case of groupBy)
|
|
374
|
+
* http://hackage.haskell.org/package/base-4.7.0.0/docs/Data-List.html#v:group
|
|
375
|
+
*/
|
|
376
|
+
const groupBy = (xs, f) => {
|
|
377
|
+
if (xs.length === 0) {
|
|
378
|
+
return [];
|
|
379
|
+
}
|
|
380
|
+
else {
|
|
381
|
+
let wasType = f(xs[0]); // initial case for matching
|
|
382
|
+
const r = [];
|
|
383
|
+
let group = [];
|
|
384
|
+
for (let i = 0, len = xs.length; i < len; i++) {
|
|
385
|
+
const x = xs[i];
|
|
386
|
+
const type = f(x);
|
|
387
|
+
if (type !== wasType) {
|
|
388
|
+
r.push(group);
|
|
389
|
+
group = [];
|
|
390
|
+
}
|
|
391
|
+
wasType = type;
|
|
392
|
+
group.push(x);
|
|
393
|
+
}
|
|
394
|
+
if (group.length !== 0) {
|
|
395
|
+
r.push(group);
|
|
396
|
+
}
|
|
397
|
+
return r;
|
|
398
|
+
}
|
|
215
399
|
};
|
|
216
400
|
const foldl = (xs, f, acc) => {
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
401
|
+
each$1(xs, (x, i) => {
|
|
402
|
+
acc = f(acc, x, i);
|
|
403
|
+
});
|
|
404
|
+
return acc;
|
|
221
405
|
};
|
|
222
406
|
const findUntil = (xs, pred, until) => {
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
407
|
+
for (let i = 0, len = xs.length; i < len; i++) {
|
|
408
|
+
const x = xs[i];
|
|
409
|
+
if (pred(x, i)) {
|
|
410
|
+
return Optional.some(x);
|
|
411
|
+
}
|
|
412
|
+
else if (until(x, i)) {
|
|
413
|
+
break;
|
|
414
|
+
}
|
|
229
415
|
}
|
|
230
|
-
|
|
231
|
-
return Optional.none();
|
|
416
|
+
return Optional.none();
|
|
232
417
|
};
|
|
233
418
|
const find = (xs, pred) => {
|
|
234
|
-
|
|
419
|
+
return findUntil(xs, pred, never);
|
|
235
420
|
};
|
|
236
|
-
const flatten = xs => {
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
421
|
+
const flatten = (xs) => {
|
|
422
|
+
// Note, this is possible because push supports multiple arguments:
|
|
423
|
+
// http://jsperf.com/concat-push/6
|
|
424
|
+
// Note that in the past, concat() would silently work (very slowly) for array-like objects.
|
|
425
|
+
// With this change it will throw an error.
|
|
426
|
+
const r = [];
|
|
427
|
+
for (let i = 0, len = xs.length; i < len; ++i) {
|
|
428
|
+
// Ensure that each value is an array itself
|
|
429
|
+
if (!isArray(xs[i])) {
|
|
430
|
+
throw new Error('Arr.flatten item ' + i + ' was not an array, input: ' + xs);
|
|
431
|
+
}
|
|
432
|
+
nativePush.apply(r, xs[i]);
|
|
241
433
|
}
|
|
242
|
-
|
|
243
|
-
}
|
|
244
|
-
return r;
|
|
434
|
+
return r;
|
|
245
435
|
};
|
|
246
436
|
const bind = (xs, f) => flatten(map(xs, f));
|
|
247
|
-
const reverse = xs => {
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
437
|
+
const reverse = (xs) => {
|
|
438
|
+
const r = nativeSlice.call(xs, 0);
|
|
439
|
+
r.reverse();
|
|
440
|
+
return r;
|
|
251
441
|
};
|
|
252
442
|
const get$1 = (xs, i) => i >= 0 && i < xs.length ? Optional.some(xs[i]) : Optional.none();
|
|
253
|
-
const head = xs => get$1(xs, 0);
|
|
254
|
-
const last = xs => get$1(xs, xs.length - 1);
|
|
443
|
+
const head = (xs) => get$1(xs, 0);
|
|
444
|
+
const last = (xs) => get$1(xs, xs.length - 1);
|
|
255
445
|
const unique = (xs, comparator) => {
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
446
|
+
const r = [];
|
|
447
|
+
const isDuplicated = isFunction(comparator) ?
|
|
448
|
+
(x) => exists(r, (i) => comparator(i, x)) :
|
|
449
|
+
(x) => contains$1(r, x);
|
|
450
|
+
for (let i = 0, len = xs.length; i < len; i++) {
|
|
451
|
+
const x = xs[i];
|
|
452
|
+
if (!isDuplicated(x)) {
|
|
453
|
+
r.push(x);
|
|
454
|
+
}
|
|
262
455
|
}
|
|
263
|
-
|
|
264
|
-
|
|
456
|
+
return r;
|
|
457
|
+
};
|
|
458
|
+
|
|
459
|
+
// There are many variations of Object iteration that are faster than the 'for-in' style:
|
|
460
|
+
// http://jsperf.com/object-keys-iteration/107
|
|
461
|
+
//
|
|
462
|
+
// Use the native keys if it is available (IE9+), otherwise fall back to manually filtering
|
|
463
|
+
const keys = Object.keys;
|
|
464
|
+
const each = (obj, f) => {
|
|
465
|
+
const props = keys(obj);
|
|
466
|
+
for (let k = 0, len = props.length; k < len; k++) {
|
|
467
|
+
const i = props[k];
|
|
468
|
+
const x = obj[i];
|
|
469
|
+
f(x, i);
|
|
470
|
+
}
|
|
471
|
+
};
|
|
472
|
+
const objAcc = (r) => (x, i) => {
|
|
473
|
+
r[i] = x;
|
|
474
|
+
};
|
|
475
|
+
const internalFilter = (obj, pred, onTrue, onFalse) => {
|
|
476
|
+
each(obj, (x, i) => {
|
|
477
|
+
(pred(x, i) ? onTrue : onFalse)(x, i);
|
|
478
|
+
});
|
|
479
|
+
};
|
|
480
|
+
const filter = (obj, pred) => {
|
|
481
|
+
const t = {};
|
|
482
|
+
internalFilter(obj, pred, objAcc(t), noop);
|
|
483
|
+
return t;
|
|
265
484
|
};
|
|
266
485
|
|
|
267
|
-
const
|
|
486
|
+
const Cell = (initial) => {
|
|
487
|
+
let value = initial;
|
|
488
|
+
const get = () => {
|
|
489
|
+
return value;
|
|
490
|
+
};
|
|
491
|
+
const set = (v) => {
|
|
492
|
+
value = v;
|
|
493
|
+
};
|
|
494
|
+
return {
|
|
495
|
+
get,
|
|
496
|
+
set
|
|
497
|
+
};
|
|
498
|
+
};
|
|
499
|
+
|
|
500
|
+
// Use window object as the global if it's available since CSP will block script evals
|
|
501
|
+
// eslint-disable-next-line @typescript-eslint/no-implied-eval
|
|
502
|
+
const Global = typeof window !== 'undefined' ? window : Function('return this;')();
|
|
503
|
+
|
|
504
|
+
/**
|
|
505
|
+
* **Is** the value stored inside this Optional object equal to `rhs`?
|
|
506
|
+
*/
|
|
507
|
+
const is$2 = (lhs, rhs, comparator = tripleEquals) => lhs.exists((left) => comparator(left, rhs));
|
|
508
|
+
/**
|
|
509
|
+
* Are these two Optional objects equal? Equality here means either they're both
|
|
510
|
+
* `Some` (and the values are equal under the comparator) or they're both `None`.
|
|
511
|
+
*/
|
|
268
512
|
const equals = (lhs, rhs, comparator = tripleEquals) => lift2(lhs, rhs, comparator).getOr(lhs.isNone() && rhs.isNone());
|
|
513
|
+
/*
|
|
514
|
+
Notes on the lift functions:
|
|
515
|
+
- We used to have a generic liftN, but we were concerned about its type-safety, and the below variants were faster in microbenchmarks.
|
|
516
|
+
- The getOrDie calls are partial functions, but are checked beforehand. This is faster and more convenient (but less safe) than folds.
|
|
517
|
+
- && is used instead of a loop for simplicity and performance.
|
|
518
|
+
*/
|
|
269
519
|
const lift2 = (oa, ob, f) => oa.isSome() && ob.isSome() ? Optional.some(f(oa.getOrDie(), ob.getOrDie())) : Optional.none();
|
|
270
520
|
|
|
271
|
-
|
|
272
|
-
const
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
521
|
+
/** path :: ([String], JsObj?) -> JsObj */
|
|
522
|
+
const path = (parts, scope) => {
|
|
523
|
+
let o = scope !== undefined && scope !== null ? scope : Global;
|
|
524
|
+
for (let i = 0; i < parts.length && o !== undefined && o !== null; ++i) {
|
|
525
|
+
o = o[parts[i]];
|
|
526
|
+
}
|
|
527
|
+
return o;
|
|
528
|
+
};
|
|
529
|
+
/** resolve :: (String, JsObj?) -> JsObj */
|
|
530
|
+
const resolve = (p, scope) => {
|
|
531
|
+
const parts = p.split('.');
|
|
532
|
+
return path(parts, scope);
|
|
533
|
+
};
|
|
534
|
+
|
|
535
|
+
const blank = (r) => (s) => s.replace(r, '');
|
|
536
|
+
/** removes all leading and trailing spaces */
|
|
537
|
+
const trim = blank(/^\s+|\s+$/g);
|
|
538
|
+
const isNotEmpty = (s) => s.length > 0;
|
|
539
|
+
const isEmpty$2 = (s) => !isNotEmpty(s);
|
|
540
|
+
|
|
541
|
+
const zeroWidth = '\uFEFF';
|
|
542
|
+
const isZwsp = (char) => char === zeroWidth;
|
|
276
543
|
|
|
277
544
|
const fromHtml = (html, scope) => {
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
545
|
+
const doc = scope || document;
|
|
546
|
+
const div = doc.createElement('div');
|
|
547
|
+
div.innerHTML = html;
|
|
548
|
+
if (!div.hasChildNodes() || div.childNodes.length > 1) {
|
|
549
|
+
const message = 'HTML does not have a single root node';
|
|
550
|
+
// eslint-disable-next-line no-console
|
|
551
|
+
console.error(message, html);
|
|
552
|
+
throw new Error(message);
|
|
553
|
+
}
|
|
554
|
+
return fromDom$1(div.childNodes[0]);
|
|
287
555
|
};
|
|
288
556
|
const fromTag = (tag, scope) => {
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
557
|
+
const doc = scope || document;
|
|
558
|
+
const node = doc.createElement(tag);
|
|
559
|
+
return fromDom$1(node);
|
|
292
560
|
};
|
|
293
561
|
const fromText = (text, scope) => {
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
562
|
+
const doc = scope || document;
|
|
563
|
+
const node = doc.createTextNode(text);
|
|
564
|
+
return fromDom$1(node);
|
|
297
565
|
};
|
|
298
|
-
const fromDom$1 = node => {
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
566
|
+
const fromDom$1 = (node) => {
|
|
567
|
+
// TODO: Consider removing this check, but left atm for safety
|
|
568
|
+
if (node === null || node === undefined) {
|
|
569
|
+
throw new Error('Node cannot be null or undefined');
|
|
570
|
+
}
|
|
571
|
+
return {
|
|
572
|
+
dom: node
|
|
573
|
+
};
|
|
303
574
|
};
|
|
304
575
|
const fromPoint = (docElm, x, y) => Optional.from(docElm.dom.elementFromPoint(x, y)).map(fromDom$1);
|
|
576
|
+
// tslint:disable-next-line:variable-name
|
|
305
577
|
const SugarElement = {
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
578
|
+
fromHtml,
|
|
579
|
+
fromTag,
|
|
580
|
+
fromText,
|
|
581
|
+
fromDom: fromDom$1,
|
|
582
|
+
fromPoint
|
|
311
583
|
};
|
|
312
584
|
|
|
585
|
+
const COMMENT = 8;
|
|
586
|
+
const DOCUMENT_FRAGMENT = 11;
|
|
587
|
+
const ELEMENT = 1;
|
|
588
|
+
const TEXT = 3;
|
|
589
|
+
|
|
313
590
|
const is$1 = (element, selector) => {
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
591
|
+
const dom = element.dom;
|
|
592
|
+
if (dom.nodeType !== ELEMENT) {
|
|
593
|
+
return false;
|
|
594
|
+
}
|
|
595
|
+
else {
|
|
596
|
+
const elem = dom;
|
|
597
|
+
if (elem.matches !== undefined) {
|
|
598
|
+
return elem.matches(selector);
|
|
599
|
+
}
|
|
600
|
+
else if (elem.msMatchesSelector !== undefined) {
|
|
601
|
+
return elem.msMatchesSelector(selector);
|
|
602
|
+
}
|
|
603
|
+
else if (elem.webkitMatchesSelector !== undefined) {
|
|
604
|
+
return elem.webkitMatchesSelector(selector);
|
|
605
|
+
}
|
|
606
|
+
else if (elem.mozMatchesSelector !== undefined) {
|
|
607
|
+
// cast to any as mozMatchesSelector doesn't exist in TS DOM lib
|
|
608
|
+
return elem.mozMatchesSelector(selector);
|
|
609
|
+
}
|
|
610
|
+
else {
|
|
611
|
+
throw new Error('Browser lacks native selectors');
|
|
612
|
+
} // unfortunately we can't throw this on startup :(
|
|
613
|
+
}
|
|
331
614
|
};
|
|
332
615
|
|
|
333
616
|
const eq = (e1, e2) => e1.dom === e2.dom;
|
|
617
|
+
// Returns: true if node e1 contains e2, otherwise false.
|
|
618
|
+
// (returns false if e1===e2: A node does not contain itself).
|
|
334
619
|
const contains = (e1, e2) => {
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
620
|
+
const d1 = e1.dom;
|
|
621
|
+
const d2 = e2.dom;
|
|
622
|
+
return d1 === d2 ? false : d1.contains(d2);
|
|
338
623
|
};
|
|
339
624
|
const is = is$1;
|
|
340
625
|
|
|
341
|
-
const Global = typeof window !== 'undefined' ? window : Function('return this;')();
|
|
342
|
-
|
|
343
|
-
const path = (parts, scope) => {
|
|
344
|
-
let o = scope !== undefined && scope !== null ? scope : Global;
|
|
345
|
-
for (let i = 0; i < parts.length && o !== undefined && o !== null; ++i) {
|
|
346
|
-
o = o[parts[i]];
|
|
347
|
-
}
|
|
348
|
-
return o;
|
|
349
|
-
};
|
|
350
|
-
const resolve = (p, scope) => {
|
|
351
|
-
const parts = p.split('.');
|
|
352
|
-
return path(parts, scope);
|
|
353
|
-
};
|
|
354
|
-
|
|
355
626
|
const unsafe = (name, scope) => {
|
|
356
|
-
|
|
627
|
+
return resolve(name, scope);
|
|
357
628
|
};
|
|
358
629
|
const getOrDie = (name, scope) => {
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
630
|
+
const actual = unsafe(name, scope);
|
|
631
|
+
if (actual === undefined || actual === null) {
|
|
632
|
+
throw new Error(name + ' not available on this browser');
|
|
633
|
+
}
|
|
634
|
+
return actual;
|
|
364
635
|
};
|
|
365
636
|
|
|
366
637
|
const getPrototypeOf = Object.getPrototypeOf;
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
638
|
+
/*
|
|
639
|
+
* IE9 and above
|
|
640
|
+
*
|
|
641
|
+
* MDN no use on this one, but here's the link anyway:
|
|
642
|
+
* https://developer.mozilla.org/en/docs/Web/API/HTMLElement
|
|
643
|
+
*/
|
|
644
|
+
const sandHTMLElement = (scope) => {
|
|
645
|
+
return getOrDie('HTMLElement', scope);
|
|
646
|
+
};
|
|
647
|
+
const isPrototypeOf = (x) => {
|
|
648
|
+
// use Resolve to get the window object for x and just return undefined if it can't find it.
|
|
649
|
+
// undefined scope later triggers using the global window.
|
|
650
|
+
const scope = resolve('ownerDocument.defaultView', x);
|
|
651
|
+
// TINY-7374: We can't rely on looking at the owner window HTMLElement as the element may have
|
|
652
|
+
// been constructed in a different window and then appended to the current window document.
|
|
653
|
+
return isObject(x) && (sandHTMLElement(scope).prototype.isPrototypeOf(x) || /^HTML\w*Element$/.test(getPrototypeOf(x).constructor.name));
|
|
654
|
+
};
|
|
655
|
+
|
|
656
|
+
const name = (element) => {
|
|
657
|
+
const r = element.dom.nodeName;
|
|
658
|
+
return r.toLowerCase();
|
|
659
|
+
};
|
|
660
|
+
const type = (element) => element.dom.nodeType;
|
|
661
|
+
const isType = (t) => (element) => type(element) === t;
|
|
662
|
+
const isComment = (element) => type(element) === COMMENT || name(element) === '#comment';
|
|
663
|
+
const isHTMLElement = (element) => isElement$1(element) && isPrototypeOf(element.dom);
|
|
383
664
|
const isElement$1 = isType(ELEMENT);
|
|
384
665
|
const isText = isType(TEXT);
|
|
385
|
-
const isDocument = isType(DOCUMENT);
|
|
386
666
|
const isDocumentFragment = isType(DOCUMENT_FRAGMENT);
|
|
387
|
-
const isTag = tag => e => isElement$1(e) && name(e) === tag;
|
|
388
|
-
|
|
389
|
-
const owner = element => SugarElement.fromDom(element.dom.ownerDocument);
|
|
390
|
-
const documentOrOwner = dos => isDocument(dos) ? dos : owner(dos);
|
|
391
|
-
const parent = element => Optional.from(element.dom.parentNode).map(SugarElement.fromDom);
|
|
392
|
-
const parentElement = element => Optional.from(element.dom.parentElement).map(SugarElement.fromDom);
|
|
393
|
-
const nextSibling = element => Optional.from(element.dom.nextSibling).map(SugarElement.fromDom);
|
|
394
|
-
const children = element => map(element.dom.childNodes, SugarElement.fromDom);
|
|
395
|
-
const child = (element, index) => {
|
|
396
|
-
const cs = element.dom.childNodes;
|
|
397
|
-
return Optional.from(cs[index]).map(SugarElement.fromDom);
|
|
398
|
-
};
|
|
399
|
-
const firstChild = element => child(element, 0);
|
|
400
|
-
const lastChild = element => child(element, element.dom.childNodes.length - 1);
|
|
401
|
-
|
|
402
|
-
const isShadowRoot = dos => isDocumentFragment(dos) && isNonNullable(dos.dom.host);
|
|
403
|
-
const supported = isFunction(Element.prototype.attachShadow) && isFunction(Node.prototype.getRootNode);
|
|
404
|
-
const getRootNode = supported ? e => SugarElement.fromDom(e.dom.getRootNode()) : documentOrOwner;
|
|
405
|
-
const getShadowRoot = e => {
|
|
406
|
-
const r = getRootNode(e);
|
|
407
|
-
return isShadowRoot(r) ? Optional.some(r) : Optional.none();
|
|
408
|
-
};
|
|
409
|
-
const getShadowHost = e => SugarElement.fromDom(e.dom.host);
|
|
410
|
-
|
|
411
|
-
const inBody = element => {
|
|
412
|
-
const dom = isText(element) ? element.dom.parentNode : element.dom;
|
|
413
|
-
if (dom === undefined || dom === null || dom.ownerDocument === null) {
|
|
414
|
-
return false;
|
|
415
|
-
}
|
|
416
|
-
const doc = dom.ownerDocument;
|
|
417
|
-
return getShadowRoot(SugarElement.fromDom(dom)).fold(() => doc.body.contains(dom), compose1(inBody, getShadowHost));
|
|
418
|
-
};
|
|
419
|
-
|
|
420
|
-
var ClosestOrAncestor = (is, ancestor, scope, a, isRoot) => {
|
|
421
|
-
if (is(scope, a)) {
|
|
422
|
-
return Optional.some(scope);
|
|
423
|
-
} else if (isFunction(isRoot) && isRoot(scope)) {
|
|
424
|
-
return Optional.none();
|
|
425
|
-
} else {
|
|
426
|
-
return ancestor(scope, a, isRoot);
|
|
427
|
-
}
|
|
428
|
-
};
|
|
429
|
-
|
|
430
|
-
const ancestor$3 = (scope, predicate, isRoot) => {
|
|
431
|
-
let element = scope.dom;
|
|
432
|
-
const stop = isFunction(isRoot) ? isRoot : never;
|
|
433
|
-
while (element.parentNode) {
|
|
434
|
-
element = element.parentNode;
|
|
435
|
-
const el = SugarElement.fromDom(element);
|
|
436
|
-
if (predicate(el)) {
|
|
437
|
-
return Optional.some(el);
|
|
438
|
-
} else if (stop(el)) {
|
|
439
|
-
break;
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
return Optional.none();
|
|
443
|
-
};
|
|
444
|
-
const closest$2 = (scope, predicate, isRoot) => {
|
|
445
|
-
const is = (s, test) => test(s);
|
|
446
|
-
return ClosestOrAncestor(is, ancestor$3, scope, predicate, isRoot);
|
|
447
|
-
};
|
|
448
|
-
|
|
449
|
-
const ancestor$2 = (scope, selector, isRoot) => ancestor$3(scope, e => is$1(e, selector), isRoot);
|
|
450
|
-
const closest$1 = (scope, selector, isRoot) => {
|
|
451
|
-
const is = (element, selector) => is$1(element, selector);
|
|
452
|
-
return ClosestOrAncestor(is, ancestor$2, scope, selector, isRoot);
|
|
453
|
-
};
|
|
667
|
+
const isTag = (tag) => (e) => isElement$1(e) && name(e) === tag;
|
|
454
668
|
|
|
455
|
-
const
|
|
456
|
-
const
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
};
|
|
463
|
-
const
|
|
669
|
+
const parent = (element) => Optional.from(element.dom.parentNode).map(SugarElement.fromDom);
|
|
670
|
+
const parentElement = (element) => Optional.from(element.dom.parentElement).map(SugarElement.fromDom);
|
|
671
|
+
const nextSibling = (element) => Optional.from(element.dom.nextSibling).map(SugarElement.fromDom);
|
|
672
|
+
const children = (element) => map(element.dom.childNodes, SugarElement.fromDom);
|
|
673
|
+
const child = (element, index) => {
|
|
674
|
+
const cs = element.dom.childNodes;
|
|
675
|
+
return Optional.from(cs[index]).map(SugarElement.fromDom);
|
|
676
|
+
};
|
|
677
|
+
const firstChild = (element) => child(element, 0);
|
|
678
|
+
const lastChild = (element) => child(element, element.dom.childNodes.length - 1);
|
|
679
|
+
|
|
680
|
+
/**
|
|
681
|
+
* Is the element a ShadowRoot?
|
|
682
|
+
*
|
|
683
|
+
* Note: this is insufficient to test if any element is a shadow root, but it is sufficient to differentiate between
|
|
684
|
+
* a Document and a ShadowRoot.
|
|
685
|
+
*/
|
|
686
|
+
const isShadowRoot = (dos) => isDocumentFragment(dos) && isNonNullable(dos.dom.host);
|
|
687
|
+
const getRootNode = (e) => SugarElement.fromDom(e.dom.getRootNode());
|
|
688
|
+
/** If this element is in a ShadowRoot, return it. */
|
|
689
|
+
const getShadowRoot = (e) => {
|
|
690
|
+
const r = getRootNode(e);
|
|
691
|
+
return isShadowRoot(r) ? Optional.some(r) : Optional.none();
|
|
692
|
+
};
|
|
693
|
+
/** Return the host of a ShadowRoot.
|
|
694
|
+
*
|
|
695
|
+
* This function will throw if Shadow DOM is unsupported in the browser, or if the host is null.
|
|
696
|
+
* If you actually have a ShadowRoot, this shouldn't happen.
|
|
697
|
+
*/
|
|
698
|
+
const getShadowHost = (e) => SugarElement.fromDom(e.dom.host);
|
|
464
699
|
|
|
465
700
|
const before$1 = (marker, element) => {
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
701
|
+
const parent$1 = parent(marker);
|
|
702
|
+
parent$1.each((v) => {
|
|
703
|
+
v.dom.insertBefore(element.dom, marker.dom);
|
|
704
|
+
});
|
|
470
705
|
};
|
|
471
706
|
const after = (marker, element) => {
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
707
|
+
const sibling = nextSibling(marker);
|
|
708
|
+
sibling.fold(() => {
|
|
709
|
+
const parent$1 = parent(marker);
|
|
710
|
+
parent$1.each((v) => {
|
|
711
|
+
append$1(v, element);
|
|
712
|
+
});
|
|
713
|
+
}, (v) => {
|
|
714
|
+
before$1(v, element);
|
|
477
715
|
});
|
|
478
|
-
}, v => {
|
|
479
|
-
before$1(v, element);
|
|
480
|
-
});
|
|
481
716
|
};
|
|
482
717
|
const prepend = (parent, element) => {
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
718
|
+
const firstChild$1 = firstChild(parent);
|
|
719
|
+
firstChild$1.fold(() => {
|
|
720
|
+
append$1(parent, element);
|
|
721
|
+
}, (v) => {
|
|
722
|
+
parent.dom.insertBefore(element.dom, v.dom);
|
|
723
|
+
});
|
|
489
724
|
};
|
|
490
725
|
const append$1 = (parent, element) => {
|
|
491
|
-
|
|
726
|
+
parent.dom.appendChild(element.dom);
|
|
492
727
|
};
|
|
493
728
|
|
|
494
729
|
const before = (marker, elements) => {
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
730
|
+
each$1(elements, (x) => {
|
|
731
|
+
before$1(marker, x);
|
|
732
|
+
});
|
|
498
733
|
};
|
|
499
734
|
const append = (parent, elements) => {
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
735
|
+
each$1(elements, (x) => {
|
|
736
|
+
append$1(parent, x);
|
|
737
|
+
});
|
|
503
738
|
};
|
|
504
739
|
|
|
505
|
-
const
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
740
|
+
const rawSet = (dom, key, value) => {
|
|
741
|
+
/*
|
|
742
|
+
* JQuery coerced everything to a string, and silently did nothing on text node/null/undefined.
|
|
743
|
+
*
|
|
744
|
+
* We fail on those invalid cases, only allowing numbers and booleans.
|
|
745
|
+
*/
|
|
746
|
+
if (isString(value) || isBoolean(value) || isNumber(value)) {
|
|
747
|
+
dom.setAttribute(key, value + '');
|
|
748
|
+
}
|
|
749
|
+
else {
|
|
750
|
+
// eslint-disable-next-line no-console
|
|
751
|
+
console.error('Invalid call to Attribute.set. Key ', key, ':: Value ', value, ':: Element ', dom);
|
|
752
|
+
throw new Error('Attribute value was not simple');
|
|
753
|
+
}
|
|
510
754
|
};
|
|
511
|
-
const
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
755
|
+
const setAll = (element, attrs) => {
|
|
756
|
+
const dom = element.dom;
|
|
757
|
+
each(attrs, (v, k) => {
|
|
758
|
+
rawSet(dom, k, v);
|
|
759
|
+
});
|
|
516
760
|
};
|
|
761
|
+
const clone$1 = (element) => foldl(element.dom.attributes, (acc, attr) => {
|
|
762
|
+
acc[attr.name] = attr.value;
|
|
763
|
+
return acc;
|
|
764
|
+
}, {});
|
|
517
765
|
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
766
|
+
const empty = (element) => {
|
|
767
|
+
// shortcut "empty node" trick. Requires IE 9.
|
|
768
|
+
element.dom.textContent = '';
|
|
769
|
+
// If the contents was a single empty text node, the above doesn't remove it. But, it's still faster in general
|
|
770
|
+
// than removing every child node manually.
|
|
771
|
+
// The following is (probably) safe for performance as 99.9% of the time the trick works and
|
|
772
|
+
// Traverse.children will return an empty array.
|
|
773
|
+
each$1(children(element), (rogue) => {
|
|
774
|
+
remove(rogue);
|
|
775
|
+
});
|
|
776
|
+
};
|
|
777
|
+
const remove = (element) => {
|
|
778
|
+
const dom = element.dom;
|
|
779
|
+
if (dom.parentNode !== null) {
|
|
780
|
+
dom.parentNode.removeChild(dom);
|
|
781
|
+
}
|
|
782
|
+
};
|
|
523
783
|
|
|
524
|
-
const
|
|
784
|
+
const clone = (original, isDeep) => SugarElement.fromDom(original.dom.cloneNode(isDeep));
|
|
785
|
+
/** Deep clone - everything copied including children */
|
|
786
|
+
const deep = (original) => clone(original, true);
|
|
787
|
+
/** Shallow clone, with a new tag */
|
|
788
|
+
const shallowAs = (original, tag) => {
|
|
789
|
+
const nu = SugarElement.fromTag(tag);
|
|
790
|
+
const attributes = clone$1(original);
|
|
791
|
+
setAll(nu, attributes);
|
|
792
|
+
return nu;
|
|
793
|
+
};
|
|
794
|
+
/** Change the tag name, but keep all children */
|
|
795
|
+
const mutate = (original, tag) => {
|
|
796
|
+
const nu = shallowAs(original, tag);
|
|
797
|
+
after(original, nu);
|
|
798
|
+
const children$1 = children(original);
|
|
799
|
+
append(nu, children$1);
|
|
800
|
+
remove(original);
|
|
801
|
+
return nu;
|
|
802
|
+
};
|
|
803
|
+
|
|
804
|
+
const fromDom = (nodes) => map(nodes, SugarElement.fromDom);
|
|
805
|
+
|
|
806
|
+
// some elements, such as mathml, don't have style attributes
|
|
807
|
+
// others, such as angular elements, have style attributes that aren't a CSSStyleDeclaration
|
|
808
|
+
const isSupported = (dom) =>
|
|
809
|
+
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
810
|
+
dom.style !== undefined && isFunction(dom.style.getPropertyValue);
|
|
811
|
+
|
|
812
|
+
// Node.contains() is very, very, very good performance
|
|
813
|
+
// http://jsperf.com/closest-vs-contains/5
|
|
814
|
+
const inBody = (element) => {
|
|
815
|
+
// Technically this is only required on IE, where contains() returns false for text nodes.
|
|
816
|
+
// But it's cheap enough to run everywhere and Sugar doesn't have platform detection (yet).
|
|
817
|
+
const dom = isText(element) ? element.dom.parentNode : element.dom;
|
|
818
|
+
// use ownerDocument.body to ensure this works inside iframes.
|
|
819
|
+
// Normally contains is bad because an element "contains" itself, but here we want that.
|
|
820
|
+
if (dom === undefined || dom === null || dom.ownerDocument === null) {
|
|
821
|
+
return false;
|
|
822
|
+
}
|
|
823
|
+
const doc = dom.ownerDocument;
|
|
824
|
+
return getShadowRoot(SugarElement.fromDom(dom)).fold(() => doc.body.contains(dom), compose1(inBody, getShadowHost));
|
|
825
|
+
};
|
|
525
826
|
|
|
526
|
-
const
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
827
|
+
const internalSet = (dom, property, value) => {
|
|
828
|
+
// This is going to hurt. Apologies.
|
|
829
|
+
// JQuery coerces numbers to pixels for certain property names, and other times lets numbers through.
|
|
830
|
+
// we're going to be explicit; strings only.
|
|
831
|
+
if (!isString(value)) {
|
|
832
|
+
// eslint-disable-next-line no-console
|
|
833
|
+
console.error('Invalid call to CSS.set. Property ', property, ':: Value ', value, ':: Element ', dom);
|
|
834
|
+
throw new Error('CSS value must be a string: ' + value);
|
|
835
|
+
}
|
|
836
|
+
// removed: support for dom().style[property] where prop is camel case instead of normal property name
|
|
837
|
+
if (isSupported(dom)) {
|
|
838
|
+
dom.style.setProperty(property, value);
|
|
839
|
+
}
|
|
534
840
|
};
|
|
535
|
-
const
|
|
536
|
-
|
|
841
|
+
const set = (element, property, value) => {
|
|
842
|
+
const dom = element.dom;
|
|
843
|
+
internalSet(dom, property, value);
|
|
537
844
|
};
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
845
|
+
|
|
846
|
+
const fromElements = (elements, scope) => {
|
|
847
|
+
const doc = scope || document;
|
|
848
|
+
const fragment = doc.createDocumentFragment();
|
|
849
|
+
each$1(elements, (element) => {
|
|
850
|
+
fragment.appendChild(element.dom);
|
|
851
|
+
});
|
|
852
|
+
return SugarElement.fromDom(fragment);
|
|
542
853
|
};
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
854
|
+
|
|
855
|
+
var ClosestOrAncestor = (is, ancestor, scope, a, isRoot) => {
|
|
856
|
+
if (is(scope, a)) {
|
|
857
|
+
return Optional.some(scope);
|
|
858
|
+
}
|
|
859
|
+
else if (isFunction(isRoot) && isRoot(scope)) {
|
|
860
|
+
return Optional.none();
|
|
861
|
+
}
|
|
862
|
+
else {
|
|
863
|
+
return ancestor(scope, a, isRoot);
|
|
864
|
+
}
|
|
547
865
|
};
|
|
548
866
|
|
|
549
|
-
const
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
867
|
+
const ancestor$3 = (scope, predicate, isRoot) => {
|
|
868
|
+
let element = scope.dom;
|
|
869
|
+
const stop = isFunction(isRoot) ? isRoot : never;
|
|
870
|
+
while (element.parentNode) {
|
|
871
|
+
element = element.parentNode;
|
|
872
|
+
const el = SugarElement.fromDom(element);
|
|
873
|
+
if (predicate(el)) {
|
|
874
|
+
return Optional.some(el);
|
|
875
|
+
}
|
|
876
|
+
else if (stop(el)) {
|
|
877
|
+
break;
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
return Optional.none();
|
|
881
|
+
};
|
|
882
|
+
const closest$2 = (scope, predicate, isRoot) => {
|
|
883
|
+
// This is required to avoid ClosestOrAncestor passing the predicate to itself
|
|
884
|
+
const is = (s, test) => test(s);
|
|
885
|
+
return ClosestOrAncestor(is, ancestor$3, scope, predicate, isRoot);
|
|
556
886
|
};
|
|
557
|
-
const setAll = (element, attrs) => {
|
|
558
|
-
const dom = element.dom;
|
|
559
|
-
each(attrs, (v, k) => {
|
|
560
|
-
rawSet(dom, k, v);
|
|
561
|
-
});
|
|
562
|
-
};
|
|
563
|
-
const clone$1 = element => foldl(element.dom.attributes, (acc, attr) => {
|
|
564
|
-
acc[attr.name] = attr.value;
|
|
565
|
-
return acc;
|
|
566
|
-
}, {});
|
|
567
887
|
|
|
568
|
-
const
|
|
569
|
-
|
|
570
|
-
const
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
setAll(nu, attributes);
|
|
574
|
-
return nu;
|
|
888
|
+
const ancestor$2 = (scope, selector, isRoot) => ancestor$3(scope, (e) => is$1(e, selector), isRoot);
|
|
889
|
+
// Returns Some(closest ancestor element (sugared)) matching 'selector' up to isRoot, or None() otherwise
|
|
890
|
+
const closest$1 = (scope, selector, isRoot) => {
|
|
891
|
+
const is = (element, selector) => is$1(element, selector);
|
|
892
|
+
return ClosestOrAncestor(is, ancestor$2, scope, selector, isRoot);
|
|
575
893
|
};
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
894
|
+
|
|
895
|
+
const closest = (target) => closest$1(target, '[contenteditable]');
|
|
896
|
+
const isEditable = (element, assumeEditable = false) => {
|
|
897
|
+
if (inBody(element)) {
|
|
898
|
+
return element.dom.isContentEditable;
|
|
899
|
+
}
|
|
900
|
+
else {
|
|
901
|
+
// Find the closest contenteditable element and check if it's editable
|
|
902
|
+
return closest(element).fold(constant(assumeEditable), (editable) => getRaw(editable) === 'true');
|
|
903
|
+
}
|
|
583
904
|
};
|
|
905
|
+
const getRaw = (element) => element.dom.contentEditable;
|
|
906
|
+
|
|
907
|
+
const ancestor$1 = (scope, predicate, isRoot) => ancestor$3(scope, predicate, isRoot).isSome();
|
|
908
|
+
|
|
909
|
+
const ancestor = (element, target) => ancestor$1(element, curry(eq, target));
|
|
910
|
+
|
|
911
|
+
var global$6 = tinymce.util.Tools.resolve('tinymce.dom.RangeUtils');
|
|
912
|
+
|
|
913
|
+
var global$5 = tinymce.util.Tools.resolve('tinymce.dom.TreeWalker');
|
|
914
|
+
|
|
915
|
+
var global$4 = tinymce.util.Tools.resolve('tinymce.util.VK');
|
|
584
916
|
|
|
585
917
|
var global$3 = tinymce.util.Tools.resolve('tinymce.dom.DOMUtils');
|
|
586
918
|
|
|
587
919
|
var global$2 = tinymce.util.Tools.resolve('tinymce.util.Tools');
|
|
588
920
|
|
|
589
|
-
const matchNodeName = name => node => isNonNullable(node) && node.nodeName.toLowerCase() === name;
|
|
590
|
-
const matchNodeNames = regex => node => isNonNullable(node) && regex.test(node.nodeName);
|
|
591
|
-
const isTextNode$1 = node => isNonNullable(node) && node.nodeType === 3;
|
|
592
|
-
const isElement = node => isNonNullable(node) && node.nodeType === 1;
|
|
921
|
+
const matchNodeName = (name) => (node) => isNonNullable(node) && node.nodeName.toLowerCase() === name;
|
|
922
|
+
const matchNodeNames = (regex) => (node) => isNonNullable(node) && regex.test(node.nodeName);
|
|
923
|
+
const isTextNode$1 = (node) => isNonNullable(node) && node.nodeType === 3;
|
|
924
|
+
const isElement = (node) => isNonNullable(node) && node.nodeType === 1;
|
|
593
925
|
const isListNode = matchNodeNames(/^(OL|UL|DL)$/);
|
|
594
926
|
const isOlUlNode = matchNodeNames(/^(OL|UL)$/);
|
|
595
927
|
const isOlNode = matchNodeName('ol');
|
|
@@ -597,1576 +929,1616 @@
|
|
|
597
929
|
const isDlItemNode = matchNodeNames(/^(DT|DD)$/);
|
|
598
930
|
const isTableCellNode = matchNodeNames(/^(TH|TD)$/);
|
|
599
931
|
const isBr = matchNodeName('br');
|
|
600
|
-
const isFirstChild = node => {
|
|
601
|
-
var _a;
|
|
602
|
-
return ((_a = node.parentNode) === null || _a === void 0 ? void 0 : _a.firstChild) === node;
|
|
603
|
-
};
|
|
932
|
+
const isFirstChild = (node) => { var _a; return ((_a = node.parentNode) === null || _a === void 0 ? void 0 : _a.firstChild) === node; };
|
|
604
933
|
const isTextBlock = (editor, node) => isNonNullable(node) && node.nodeName in editor.schema.getTextBlockElements();
|
|
605
934
|
const isBlock = (node, blockElements) => isNonNullable(node) && node.nodeName in blockElements;
|
|
606
935
|
const isVoid = (editor, node) => isNonNullable(node) && node.nodeName in editor.schema.getVoidElements();
|
|
607
936
|
const isBogusBr = (dom, node) => {
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
937
|
+
if (!isBr(node)) {
|
|
938
|
+
return false;
|
|
939
|
+
}
|
|
940
|
+
return dom.isBlock(node.nextSibling) && !isBr(node.previousSibling);
|
|
612
941
|
};
|
|
613
|
-
const isEmpty$
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
942
|
+
const isEmpty$1 = (dom, elm, keepBookmarks) => {
|
|
943
|
+
const empty = dom.isEmpty(elm);
|
|
944
|
+
if (keepBookmarks && dom.select('span[data-mce-type=bookmark]', elm).length > 0) {
|
|
945
|
+
return false;
|
|
946
|
+
}
|
|
947
|
+
return empty;
|
|
619
948
|
};
|
|
620
949
|
const isChildOfBody = (dom, elm) => dom.isChildOf(elm, dom.getRoot());
|
|
621
950
|
|
|
622
|
-
const option = name => editor => editor.options.get(name);
|
|
623
|
-
const register$3 = editor => {
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
951
|
+
const option = (name) => (editor) => editor.options.get(name);
|
|
952
|
+
const register$3 = (editor) => {
|
|
953
|
+
const registerOption = editor.options.register;
|
|
954
|
+
registerOption('lists_indent_on_tab', {
|
|
955
|
+
processor: 'boolean',
|
|
956
|
+
default: true
|
|
957
|
+
});
|
|
629
958
|
};
|
|
630
959
|
const shouldIndentOnTab = option('lists_indent_on_tab');
|
|
631
960
|
const getForcedRootBlock = option('forced_root_block');
|
|
632
961
|
const getForcedRootBlockAttrs = option('forced_root_block_attrs');
|
|
633
962
|
|
|
634
|
-
const createTextBlock = (editor, contentNode) => {
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
const nodeName = node.nodeName;
|
|
649
|
-
if (!hasContentNode && (nodeName !== 'SPAN' || node.getAttribute('data-mce-type') !== 'bookmark')) {
|
|
650
|
-
hasContentNode = true;
|
|
651
|
-
}
|
|
652
|
-
if (isBlock(node, blockElements)) {
|
|
653
|
-
fragment.appendChild(node);
|
|
654
|
-
textBlock = null;
|
|
655
|
-
} else {
|
|
656
|
-
if (!textBlock) {
|
|
657
|
-
textBlock = dom.create(blockName, blockAttrs);
|
|
963
|
+
const createTextBlock = (editor, contentNode, attrs = {}) => {
|
|
964
|
+
const dom = editor.dom;
|
|
965
|
+
const blockElements = editor.schema.getBlockElements();
|
|
966
|
+
const fragment = dom.createFragment();
|
|
967
|
+
const blockName = getForcedRootBlock(editor);
|
|
968
|
+
const blockAttrs = getForcedRootBlockAttrs(editor);
|
|
969
|
+
let node;
|
|
970
|
+
let textBlock;
|
|
971
|
+
let hasContentNode = false;
|
|
972
|
+
textBlock = dom.create(blockName, {
|
|
973
|
+
...blockAttrs,
|
|
974
|
+
...(attrs.style ? { style: attrs.style } : {})
|
|
975
|
+
});
|
|
976
|
+
if (!isBlock(contentNode.firstChild, blockElements)) {
|
|
658
977
|
fragment.appendChild(textBlock);
|
|
659
|
-
}
|
|
660
|
-
textBlock.appendChild(node);
|
|
661
978
|
}
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
979
|
+
while ((node = contentNode.firstChild)) {
|
|
980
|
+
const nodeName = node.nodeName;
|
|
981
|
+
if (!hasContentNode && (nodeName !== 'SPAN' || node.getAttribute('data-mce-type') !== 'bookmark')) {
|
|
982
|
+
hasContentNode = true;
|
|
983
|
+
}
|
|
984
|
+
if (isBlock(node, blockElements)) {
|
|
985
|
+
fragment.appendChild(node);
|
|
986
|
+
textBlock = null;
|
|
987
|
+
}
|
|
988
|
+
else {
|
|
989
|
+
if (!textBlock) {
|
|
990
|
+
textBlock = dom.create(blockName, blockAttrs);
|
|
991
|
+
fragment.appendChild(textBlock);
|
|
992
|
+
}
|
|
993
|
+
textBlock.appendChild(node);
|
|
994
|
+
}
|
|
995
|
+
}
|
|
996
|
+
// BR is needed in empty blocks
|
|
997
|
+
if (!hasContentNode && textBlock) {
|
|
998
|
+
textBlock.appendChild(dom.create('br', { 'data-mce-bogus': '1' }));
|
|
999
|
+
}
|
|
1000
|
+
return fragment;
|
|
667
1001
|
};
|
|
668
1002
|
|
|
669
1003
|
const DOM$2 = global$3.DOM;
|
|
670
1004
|
const splitList = (editor, list, li) => {
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
1005
|
+
const removeAndKeepBookmarks = (targetNode) => {
|
|
1006
|
+
const parent = targetNode.parentNode;
|
|
1007
|
+
if (parent) {
|
|
1008
|
+
global$2.each(bookmarks, (node) => {
|
|
1009
|
+
parent.insertBefore(node, li.parentNode);
|
|
1010
|
+
});
|
|
1011
|
+
}
|
|
1012
|
+
DOM$2.remove(targetNode);
|
|
1013
|
+
};
|
|
1014
|
+
const bookmarks = DOM$2.select('span[data-mce-type="bookmark"]', list);
|
|
1015
|
+
const newBlock = createTextBlock(editor, li);
|
|
1016
|
+
const tmpRng = DOM$2.createRng();
|
|
1017
|
+
tmpRng.setStartAfter(li);
|
|
1018
|
+
tmpRng.setEndAfter(list);
|
|
1019
|
+
const fragment = tmpRng.extractContents();
|
|
1020
|
+
for (let node = fragment.firstChild; node; node = node.firstChild) {
|
|
1021
|
+
if (node.nodeName === 'LI' && editor.dom.isEmpty(node)) {
|
|
1022
|
+
DOM$2.remove(node);
|
|
1023
|
+
break;
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
if (!editor.dom.isEmpty(fragment)) {
|
|
1027
|
+
DOM$2.insertAfter(fragment, list);
|
|
1028
|
+
}
|
|
1029
|
+
DOM$2.insertAfter(newBlock, list);
|
|
1030
|
+
const parent = li.parentElement;
|
|
1031
|
+
if (parent && isEmpty$1(editor.dom, parent)) {
|
|
1032
|
+
removeAndKeepBookmarks(parent);
|
|
1033
|
+
}
|
|
1034
|
+
DOM$2.remove(li);
|
|
1035
|
+
if (isEmpty$1(editor.dom, list)) {
|
|
1036
|
+
DOM$2.remove(list);
|
|
1037
|
+
}
|
|
704
1038
|
};
|
|
705
1039
|
|
|
706
1040
|
const isDescriptionDetail = isTag('dd');
|
|
707
1041
|
const isDescriptionTerm = isTag('dt');
|
|
708
1042
|
const outdentDlItem = (editor, item) => {
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
1043
|
+
if (isDescriptionDetail(item)) {
|
|
1044
|
+
mutate(item, 'dt');
|
|
1045
|
+
}
|
|
1046
|
+
else if (isDescriptionTerm(item)) {
|
|
1047
|
+
parentElement(item).each((dl) => splitList(editor, dl.dom, item.dom));
|
|
1048
|
+
}
|
|
714
1049
|
};
|
|
715
|
-
const indentDlItem = item => {
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
1050
|
+
const indentDlItem = (item) => {
|
|
1051
|
+
if (isDescriptionTerm(item)) {
|
|
1052
|
+
mutate(item, 'dd');
|
|
1053
|
+
}
|
|
719
1054
|
};
|
|
720
1055
|
const dlIndentation = (editor, indentation, dlItems) => {
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
1056
|
+
if (indentation === "Indent" /* Indentation.Indent */) {
|
|
1057
|
+
each$1(dlItems, indentDlItem);
|
|
1058
|
+
}
|
|
1059
|
+
else {
|
|
1060
|
+
each$1(dlItems, (item) => outdentDlItem(editor, item));
|
|
1061
|
+
}
|
|
726
1062
|
};
|
|
727
1063
|
|
|
728
1064
|
const getNormalizedPoint = (container, offset) => {
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
}
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
return outRng;
|
|
764
|
-
};
|
|
765
|
-
|
|
766
|
-
const listNames = [
|
|
767
|
-
'OL',
|
|
768
|
-
'UL',
|
|
769
|
-
'DL'
|
|
770
|
-
];
|
|
1065
|
+
if (isTextNode$1(container)) {
|
|
1066
|
+
return { container, offset };
|
|
1067
|
+
}
|
|
1068
|
+
const node = global$6.getNode(container, offset);
|
|
1069
|
+
if (isTextNode$1(node)) {
|
|
1070
|
+
return {
|
|
1071
|
+
container: node,
|
|
1072
|
+
offset: offset >= container.childNodes.length ? node.data.length : 0
|
|
1073
|
+
};
|
|
1074
|
+
}
|
|
1075
|
+
else if (node.previousSibling && isTextNode$1(node.previousSibling)) {
|
|
1076
|
+
return {
|
|
1077
|
+
container: node.previousSibling,
|
|
1078
|
+
offset: node.previousSibling.data.length
|
|
1079
|
+
};
|
|
1080
|
+
}
|
|
1081
|
+
else if (node.nextSibling && isTextNode$1(node.nextSibling)) {
|
|
1082
|
+
return {
|
|
1083
|
+
container: node.nextSibling,
|
|
1084
|
+
offset: 0
|
|
1085
|
+
};
|
|
1086
|
+
}
|
|
1087
|
+
return { container, offset };
|
|
1088
|
+
};
|
|
1089
|
+
const normalizeRange = (rng) => {
|
|
1090
|
+
const outRng = rng.cloneRange();
|
|
1091
|
+
const rangeStart = getNormalizedPoint(rng.startContainer, rng.startOffset);
|
|
1092
|
+
outRng.setStart(rangeStart.container, rangeStart.offset);
|
|
1093
|
+
const rangeEnd = getNormalizedPoint(rng.endContainer, rng.endOffset);
|
|
1094
|
+
outRng.setEnd(rangeEnd.container, rangeEnd.offset);
|
|
1095
|
+
return outRng;
|
|
1096
|
+
};
|
|
1097
|
+
|
|
1098
|
+
const listNames = ['OL', 'UL', 'DL'];
|
|
771
1099
|
const listSelector = listNames.join(',');
|
|
772
1100
|
const getParentList = (editor, node) => {
|
|
773
|
-
|
|
774
|
-
|
|
1101
|
+
const selectionStart = node || editor.selection.getStart(true);
|
|
1102
|
+
return editor.dom.getParent(selectionStart, listSelector, getClosestListHost(editor, selectionStart));
|
|
775
1103
|
};
|
|
776
1104
|
const isParentListSelected = (parentList, selectedBlocks) => isNonNullable(parentList) && selectedBlocks.length === 1 && selectedBlocks[0] === parentList;
|
|
777
|
-
const findSubLists = parentList => filter$1(parentList.querySelectorAll(listSelector), isListNode);
|
|
778
|
-
const getSelectedSubLists = editor => {
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
1105
|
+
const findSubLists = (parentList) => filter$1(parentList.querySelectorAll(listSelector), isListNode);
|
|
1106
|
+
const getSelectedSubLists = (editor) => {
|
|
1107
|
+
const parentList = getParentList(editor);
|
|
1108
|
+
const selectedBlocks = editor.selection.getSelectedBlocks();
|
|
1109
|
+
if (isParentListSelected(parentList, selectedBlocks)) {
|
|
1110
|
+
return findSubLists(parentList);
|
|
1111
|
+
}
|
|
1112
|
+
else {
|
|
1113
|
+
return filter$1(selectedBlocks, (elm) => {
|
|
1114
|
+
return isListNode(elm) && parentList !== elm;
|
|
1115
|
+
});
|
|
1116
|
+
}
|
|
788
1117
|
};
|
|
789
1118
|
const findParentListItemsNodes = (editor, elms) => {
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
1119
|
+
const listItemsElms = global$2.map(elms, (elm) => {
|
|
1120
|
+
const parentLi = editor.dom.getParent(elm, 'li,dd,dt', getClosestListHost(editor, elm));
|
|
1121
|
+
return parentLi ? parentLi : elm;
|
|
1122
|
+
});
|
|
1123
|
+
return unique(listItemsElms);
|
|
795
1124
|
};
|
|
796
|
-
const getSelectedListItems = editor => {
|
|
797
|
-
|
|
798
|
-
|
|
1125
|
+
const getSelectedListItems = (editor) => {
|
|
1126
|
+
const selectedBlocks = editor.selection.getSelectedBlocks();
|
|
1127
|
+
return filter$1(findParentListItemsNodes(editor, selectedBlocks), isListItemNode);
|
|
799
1128
|
};
|
|
800
|
-
const getSelectedDlItems = editor => filter$1(getSelectedListItems(editor), isDlItemNode);
|
|
1129
|
+
const getSelectedDlItems = (editor) => filter$1(getSelectedListItems(editor), isDlItemNode);
|
|
801
1130
|
const getClosestEditingHost = (editor, elm) => {
|
|
802
|
-
|
|
803
|
-
|
|
1131
|
+
const parentTableCell = editor.dom.getParents(elm, 'TD,TH');
|
|
1132
|
+
return parentTableCell.length > 0 ? parentTableCell[0] : editor.getBody();
|
|
804
1133
|
};
|
|
805
|
-
const isListHost = (schema, node) => !isListNode(node) && !isListItemNode(node) && exists(listNames, listName => schema.isValidChild(node.nodeName, listName));
|
|
1134
|
+
const isListHost = (schema, node) => !isListNode(node) && !isListItemNode(node) && exists(listNames, (listName) => schema.isValidChild(node.nodeName, listName));
|
|
806
1135
|
const getClosestListHost = (editor, elm) => {
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
1136
|
+
const parentBlocks = editor.dom.getParents(elm, editor.dom.isBlock);
|
|
1137
|
+
const isNotForcedRootBlock = (elm) => elm.nodeName.toLowerCase() !== getForcedRootBlock(editor);
|
|
1138
|
+
const parentBlock = find(parentBlocks, (elm) => isNotForcedRootBlock(elm) && isListHost(editor.schema, elm));
|
|
1139
|
+
return parentBlock.getOr(editor.getBody());
|
|
1140
|
+
};
|
|
1141
|
+
const isListInsideAnLiWithFirstAndLastNotListElement = (list) => parent(list).exists((parent) => isListItemNode(parent.dom)
|
|
1142
|
+
&& firstChild(parent).exists((firstChild) => !isListNode(firstChild.dom))
|
|
1143
|
+
&& lastChild(parent).exists((lastChild) => !isListNode(lastChild.dom)));
|
|
812
1144
|
const findLastParentListNode = (editor, elm) => {
|
|
813
|
-
|
|
814
|
-
|
|
1145
|
+
const parentLists = editor.dom.getParents(elm, 'ol,ul', getClosestListHost(editor, elm));
|
|
1146
|
+
return last(parentLists);
|
|
815
1147
|
};
|
|
816
|
-
const getSelectedLists = editor => {
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
1148
|
+
const getSelectedLists = (editor) => {
|
|
1149
|
+
const firstList = findLastParentListNode(editor, editor.selection.getStart());
|
|
1150
|
+
const subsequentLists = filter$1(editor.selection.getSelectedBlocks(), isOlUlNode);
|
|
1151
|
+
return firstList.toArray().concat(subsequentLists);
|
|
820
1152
|
};
|
|
821
|
-
const getParentLists = editor => {
|
|
822
|
-
|
|
823
|
-
|
|
1153
|
+
const getParentLists = (editor) => {
|
|
1154
|
+
const elm = editor.selection.getStart();
|
|
1155
|
+
return editor.dom.getParents(elm, 'ol,ul', getClosestListHost(editor, elm));
|
|
824
1156
|
};
|
|
825
|
-
const getSelectedListRoots = editor => {
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
1157
|
+
const getSelectedListRoots = (editor) => {
|
|
1158
|
+
const selectedLists = getSelectedLists(editor);
|
|
1159
|
+
const parentLists = getParentLists(editor);
|
|
1160
|
+
return find(parentLists, (p) => isListInsideAnLiWithFirstAndLastNotListElement(SugarElement.fromDom(p))).fold(() => getUniqueListRoots(editor, selectedLists), (l) => [l]);
|
|
829
1161
|
};
|
|
830
1162
|
const getUniqueListRoots = (editor, lists) => {
|
|
831
|
-
|
|
832
|
-
|
|
1163
|
+
const listRoots = map(lists, (list) => findLastParentListNode(editor, list).getOr(list));
|
|
1164
|
+
return unique(listRoots);
|
|
833
1165
|
};
|
|
834
1166
|
|
|
835
|
-
const isCustomList = list => /\btox\-/.test(list.className);
|
|
836
|
-
const inList = (parents, listName) => findUntil(parents, isListNode, isTableCellNode)
|
|
1167
|
+
const isCustomList = (list) => /\btox\-/.test(list.className);
|
|
1168
|
+
const inList = (parents, listName) => findUntil(parents, isListNode, isTableCellNode)
|
|
1169
|
+
.exists((list) => list.nodeName === listName && !isCustomList(list));
|
|
1170
|
+
// Advlist/core/ListUtils.ts - Duplicated in Advlist plugin
|
|
837
1171
|
const isWithinNonEditable = (editor, element) => element !== null && !editor.dom.isEditable(element);
|
|
838
|
-
const selectionIsWithinNonEditableList = editor => {
|
|
839
|
-
|
|
840
|
-
|
|
1172
|
+
const selectionIsWithinNonEditableList = (editor) => {
|
|
1173
|
+
const parentList = getParentList(editor);
|
|
1174
|
+
return isWithinNonEditable(editor, parentList) || !editor.selection.isEditable();
|
|
841
1175
|
};
|
|
842
1176
|
const isWithinNonEditableList = (editor, element) => {
|
|
843
|
-
|
|
844
|
-
|
|
1177
|
+
const parentList = editor.dom.getParent(element, 'ol,ul,dl');
|
|
1178
|
+
return isWithinNonEditable(editor, parentList) || !editor.selection.isEditable();
|
|
845
1179
|
};
|
|
846
1180
|
const setNodeChangeHandler = (editor, nodeChangeHandler) => {
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
const
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
dom.style.setProperty(property, value);
|
|
884
|
-
}
|
|
885
|
-
};
|
|
886
|
-
const set = (element, property, value) => {
|
|
887
|
-
const dom = element.dom;
|
|
888
|
-
internalSet(dom, property, value);
|
|
889
|
-
};
|
|
890
|
-
|
|
891
|
-
const isList = el => is(el, 'OL,UL');
|
|
892
|
-
const isListItem = el => is(el, 'LI');
|
|
893
|
-
const hasFirstChildList = el => firstChild(el).exists(isList);
|
|
894
|
-
const hasLastChildList = el => lastChild(el).exists(isList);
|
|
895
|
-
|
|
896
|
-
const isEntryList = entry => 'listAttributes' in entry;
|
|
897
|
-
const isEntryComment = entry => 'isComment' in entry;
|
|
898
|
-
const isEntryFragment = entry => 'isFragment' in entry;
|
|
899
|
-
const isIndented = entry => entry.depth > 0;
|
|
900
|
-
const isSelected = entry => entry.isSelected;
|
|
901
|
-
const cloneItemContent = li => {
|
|
902
|
-
const children$1 = children(li);
|
|
903
|
-
const content = hasLastChildList(li) ? children$1.slice(0, -1) : children$1;
|
|
904
|
-
return map(content, deep);
|
|
905
|
-
};
|
|
906
|
-
const createEntry = (li, depth, isSelected) => parent(li).filter(isElement$1).map(list => ({
|
|
907
|
-
depth,
|
|
908
|
-
dirty: false,
|
|
909
|
-
isSelected,
|
|
910
|
-
content: cloneItemContent(li),
|
|
911
|
-
itemAttributes: clone$1(li),
|
|
912
|
-
listAttributes: clone$1(list),
|
|
913
|
-
listType: name(list),
|
|
914
|
-
isInPreviousLi: false
|
|
1181
|
+
const initialNode = editor.selection.getNode();
|
|
1182
|
+
// Set the initial state
|
|
1183
|
+
nodeChangeHandler({
|
|
1184
|
+
parents: editor.dom.getParents(initialNode),
|
|
1185
|
+
element: initialNode
|
|
1186
|
+
});
|
|
1187
|
+
editor.on('NodeChange', nodeChangeHandler);
|
|
1188
|
+
return () => editor.off('NodeChange', nodeChangeHandler);
|
|
1189
|
+
};
|
|
1190
|
+
|
|
1191
|
+
const fireListEvent = (editor, action, element) => editor.dispatch('ListMutation', { action, element });
|
|
1192
|
+
|
|
1193
|
+
const isList = (el) => is(el, 'OL,UL');
|
|
1194
|
+
const isListItem = (el) => is(el, 'LI');
|
|
1195
|
+
const hasFirstChildList = (el) => firstChild(el).exists(isList);
|
|
1196
|
+
const hasLastChildList = (el) => lastChild(el).exists(isList);
|
|
1197
|
+
|
|
1198
|
+
const isEntryList = (entry) => 'listAttributes' in entry;
|
|
1199
|
+
const isEntryComment = (entry) => 'isComment' in entry;
|
|
1200
|
+
const isEntryFragment = (entry) => 'isFragment' in entry;
|
|
1201
|
+
const isIndented = (entry) => entry.depth > 0;
|
|
1202
|
+
const isSelected = (entry) => entry.isSelected;
|
|
1203
|
+
const cloneItemContent = (li) => {
|
|
1204
|
+
const children$1 = children(li);
|
|
1205
|
+
const content = hasLastChildList(li) ? children$1.slice(0, -1) : children$1;
|
|
1206
|
+
return map(content, deep);
|
|
1207
|
+
};
|
|
1208
|
+
const createEntry = (li, depth, isSelected) => parent(li).filter(isElement$1).map((list) => ({
|
|
1209
|
+
depth,
|
|
1210
|
+
dirty: false,
|
|
1211
|
+
isSelected,
|
|
1212
|
+
content: cloneItemContent(li),
|
|
1213
|
+
itemAttributes: clone$1(li),
|
|
1214
|
+
listAttributes: clone$1(list),
|
|
1215
|
+
listType: name(list),
|
|
1216
|
+
isInPreviousLi: false
|
|
915
1217
|
}));
|
|
916
1218
|
|
|
917
1219
|
const joinSegment = (parent, child) => {
|
|
918
|
-
|
|
1220
|
+
append$1(parent.item, child.list);
|
|
919
1221
|
};
|
|
920
|
-
const joinSegments = segments => {
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
1222
|
+
const joinSegments = (segments) => {
|
|
1223
|
+
for (let i = 1; i < segments.length; i++) {
|
|
1224
|
+
joinSegment(segments[i - 1], segments[i]);
|
|
1225
|
+
}
|
|
924
1226
|
};
|
|
925
1227
|
const appendSegments = (head$1, tail) => {
|
|
926
|
-
|
|
1228
|
+
lift2(last(head$1), head(tail), joinSegment);
|
|
927
1229
|
};
|
|
928
1230
|
const createSegment = (scope, listType) => {
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
1231
|
+
const segment = {
|
|
1232
|
+
list: SugarElement.fromTag(listType, scope),
|
|
1233
|
+
item: SugarElement.fromTag('li', scope)
|
|
1234
|
+
};
|
|
1235
|
+
append$1(segment.list, segment.item);
|
|
1236
|
+
return segment;
|
|
935
1237
|
};
|
|
936
1238
|
const createSegments = (scope, entry, size) => {
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
1239
|
+
const segments = [];
|
|
1240
|
+
for (let i = 0; i < size; i++) {
|
|
1241
|
+
segments.push(createSegment(scope, isEntryList(entry) ? entry.listType : entry.parentListType));
|
|
1242
|
+
}
|
|
1243
|
+
return segments;
|
|
942
1244
|
};
|
|
943
1245
|
const populateSegments = (segments, entry) => {
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
}
|
|
947
|
-
last(segments).each(segment => {
|
|
948
|
-
if (isEntryList(entry)) {
|
|
949
|
-
setAll(segment.list, entry.listAttributes);
|
|
950
|
-
setAll(segment.item, entry.itemAttributes);
|
|
1246
|
+
for (let i = 0; i < segments.length - 1; i++) {
|
|
1247
|
+
set(segments[i].item, 'list-style-type', 'none');
|
|
951
1248
|
}
|
|
952
|
-
|
|
953
|
-
|
|
1249
|
+
last(segments).each((segment) => {
|
|
1250
|
+
if (isEntryList(entry)) {
|
|
1251
|
+
setAll(segment.list, entry.listAttributes);
|
|
1252
|
+
setAll(segment.item, entry.itemAttributes);
|
|
1253
|
+
}
|
|
1254
|
+
append(segment.item, entry.content);
|
|
1255
|
+
});
|
|
954
1256
|
};
|
|
955
1257
|
const normalizeSegment = (segment, entry) => {
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
1258
|
+
if (name(segment.list) !== entry.listType) {
|
|
1259
|
+
segment.list = mutate(segment.list, entry.listType);
|
|
1260
|
+
}
|
|
1261
|
+
setAll(segment.list, entry.listAttributes);
|
|
960
1262
|
};
|
|
961
1263
|
const createItem = (scope, attr, content) => {
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
1264
|
+
const item = SugarElement.fromTag('li', scope);
|
|
1265
|
+
setAll(item, attr);
|
|
1266
|
+
append(item, content);
|
|
1267
|
+
return item;
|
|
966
1268
|
};
|
|
967
1269
|
const appendItem = (segment, item) => {
|
|
968
|
-
|
|
969
|
-
|
|
1270
|
+
append$1(segment.list, item);
|
|
1271
|
+
segment.item = item;
|
|
970
1272
|
};
|
|
971
1273
|
const writeShallow = (scope, cast, entry) => {
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
1274
|
+
const newCast = cast.slice(0, entry.depth);
|
|
1275
|
+
last(newCast).each((segment) => {
|
|
1276
|
+
if (isEntryList(entry)) {
|
|
1277
|
+
const item = createItem(scope, entry.itemAttributes, entry.content);
|
|
1278
|
+
appendItem(segment, item);
|
|
1279
|
+
normalizeSegment(segment, entry);
|
|
1280
|
+
}
|
|
1281
|
+
else if (isEntryFragment(entry)) {
|
|
1282
|
+
append(segment.item, entry.content);
|
|
1283
|
+
}
|
|
1284
|
+
else {
|
|
1285
|
+
const item = SugarElement.fromHtml(`<!--${entry.content}-->`);
|
|
1286
|
+
append$1(segment.list, item);
|
|
1287
|
+
}
|
|
1288
|
+
});
|
|
1289
|
+
return newCast;
|
|
986
1290
|
};
|
|
987
1291
|
const writeDeep = (scope, cast, entry) => {
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
1292
|
+
const segments = createSegments(scope, entry, entry.depth - cast.length);
|
|
1293
|
+
joinSegments(segments);
|
|
1294
|
+
populateSegments(segments, entry);
|
|
1295
|
+
appendSegments(cast, segments);
|
|
1296
|
+
return cast.concat(segments);
|
|
993
1297
|
};
|
|
994
1298
|
const composeList = (scope, entries) => {
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1299
|
+
let firstCommentEntryOpt = Optional.none();
|
|
1300
|
+
const cast = foldl(entries, (cast, entry, i) => {
|
|
1301
|
+
if (!isEntryComment(entry)) {
|
|
1302
|
+
return entry.depth > cast.length ? writeDeep(scope, cast, entry) : writeShallow(scope, cast, entry);
|
|
1303
|
+
}
|
|
1304
|
+
else {
|
|
1305
|
+
// this is needed becuase if the first element of the list is a comment we would not have the data to create the new list
|
|
1306
|
+
if (i === 0) {
|
|
1307
|
+
firstCommentEntryOpt = Optional.some(entry);
|
|
1308
|
+
return cast;
|
|
1309
|
+
}
|
|
1310
|
+
return writeShallow(scope, cast, entry);
|
|
1311
|
+
}
|
|
1312
|
+
}, []);
|
|
1313
|
+
firstCommentEntryOpt.each((firstCommentEntry) => {
|
|
1314
|
+
const item = SugarElement.fromHtml(`<!--${firstCommentEntry.content}-->`);
|
|
1315
|
+
head(cast).each((fistCast) => {
|
|
1316
|
+
prepend(fistCast.list, item);
|
|
1317
|
+
});
|
|
1011
1318
|
});
|
|
1012
|
-
|
|
1013
|
-
return head(cast).map(segment => segment.list);
|
|
1319
|
+
return head(cast).map((segment) => segment.list);
|
|
1014
1320
|
};
|
|
1015
1321
|
|
|
1016
1322
|
const indentEntry = (indentation, entry) => {
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1323
|
+
switch (indentation) {
|
|
1324
|
+
case "Indent" /* Indentation.Indent */:
|
|
1325
|
+
entry.depth++;
|
|
1326
|
+
break;
|
|
1327
|
+
case "Outdent" /* Indentation.Outdent */:
|
|
1328
|
+
entry.depth--;
|
|
1329
|
+
break;
|
|
1330
|
+
case "Flatten" /* Indentation.Flatten */:
|
|
1331
|
+
entry.depth = 0;
|
|
1332
|
+
}
|
|
1333
|
+
entry.dirty = true;
|
|
1028
1334
|
};
|
|
1029
1335
|
|
|
1030
1336
|
const cloneListProperties = (target, source) => {
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1337
|
+
if (isEntryList(target) && isEntryList(source)) {
|
|
1338
|
+
target.listType = source.listType;
|
|
1339
|
+
target.listAttributes = { ...source.listAttributes };
|
|
1340
|
+
}
|
|
1035
1341
|
};
|
|
1036
|
-
const cleanListProperties = entry => {
|
|
1037
|
-
|
|
1342
|
+
const cleanListProperties = (entry) => {
|
|
1343
|
+
// Remove the start attribute if generating a new list
|
|
1344
|
+
entry.listAttributes = filter(entry.listAttributes, (_value, key) => key !== 'start');
|
|
1038
1345
|
};
|
|
1346
|
+
// Closest entry above/below in the same list
|
|
1039
1347
|
const closestSiblingEntry = (entries, start) => {
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
const get = () => {
|
|
1059
|
-
return value;
|
|
1060
|
-
};
|
|
1061
|
-
const set = v => {
|
|
1062
|
-
value = v;
|
|
1063
|
-
};
|
|
1064
|
-
return {
|
|
1065
|
-
get,
|
|
1066
|
-
set
|
|
1067
|
-
};
|
|
1348
|
+
const depth = entries[start].depth;
|
|
1349
|
+
// Ignore dirty items as they've been moved and won't have the right list data yet
|
|
1350
|
+
const matches = (entry) => entry.depth === depth && !entry.dirty;
|
|
1351
|
+
const until = (entry) => entry.depth < depth;
|
|
1352
|
+
// Check in reverse to see if there's an entry as the same depth before the current entry
|
|
1353
|
+
// but if not, then try to walk forwards as well
|
|
1354
|
+
return findUntil(reverse(entries.slice(0, start)), matches, until)
|
|
1355
|
+
.orThunk(() => findUntil(entries.slice(start + 1), matches, until));
|
|
1356
|
+
};
|
|
1357
|
+
const normalizeEntries = (entries) => {
|
|
1358
|
+
each$1(entries, (entry, i) => {
|
|
1359
|
+
closestSiblingEntry(entries, i).fold(() => {
|
|
1360
|
+
if (entry.dirty && isEntryList(entry)) {
|
|
1361
|
+
cleanListProperties(entry);
|
|
1362
|
+
}
|
|
1363
|
+
}, (matchingEntry) => cloneListProperties(entry, matchingEntry));
|
|
1364
|
+
});
|
|
1365
|
+
return entries;
|
|
1068
1366
|
};
|
|
1069
1367
|
|
|
1070
1368
|
const parseSingleItem = (depth, itemSelection, selectionState, item) => {
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1369
|
+
var _a;
|
|
1370
|
+
if (isComment(item)) {
|
|
1371
|
+
return [{
|
|
1372
|
+
depth: depth + 1,
|
|
1373
|
+
content: (_a = item.dom.nodeValue) !== null && _a !== void 0 ? _a : '',
|
|
1374
|
+
dirty: false,
|
|
1375
|
+
isSelected: false,
|
|
1376
|
+
isComment: true
|
|
1377
|
+
}];
|
|
1378
|
+
}
|
|
1379
|
+
itemSelection.each((selection) => {
|
|
1380
|
+
if (eq(selection.start, item)) {
|
|
1381
|
+
selectionState.set(true);
|
|
1382
|
+
}
|
|
1383
|
+
});
|
|
1384
|
+
const currentItemEntry = createEntry(item, depth, selectionState.get());
|
|
1385
|
+
// Update selectionState (end)
|
|
1386
|
+
itemSelection.each((selection) => {
|
|
1387
|
+
if (eq(selection.end, item)) {
|
|
1388
|
+
selectionState.set(false);
|
|
1389
|
+
}
|
|
1390
|
+
});
|
|
1391
|
+
const childListEntries = lastChild(item)
|
|
1392
|
+
.filter(isList)
|
|
1393
|
+
.map((list) => parseList(depth, itemSelection, selectionState, list))
|
|
1394
|
+
.getOr([]);
|
|
1395
|
+
return currentItemEntry.toArray().concat(childListEntries);
|
|
1396
|
+
};
|
|
1397
|
+
const parseItem = (depth, itemSelection, selectionState, item) => firstChild(item).filter(isList).fold(() => parseSingleItem(depth, itemSelection, selectionState, item), (list) => {
|
|
1398
|
+
const parsedSiblings = foldl(children(item), (acc, liChild, i) => {
|
|
1399
|
+
if (i === 0) {
|
|
1400
|
+
return acc;
|
|
1401
|
+
}
|
|
1402
|
+
else {
|
|
1403
|
+
if (isListItem(liChild)) {
|
|
1404
|
+
return acc.concat(parseSingleItem(depth, itemSelection, selectionState, liChild));
|
|
1405
|
+
}
|
|
1406
|
+
else {
|
|
1407
|
+
const fragment = {
|
|
1408
|
+
isFragment: true,
|
|
1409
|
+
depth,
|
|
1410
|
+
content: [liChild],
|
|
1411
|
+
isSelected: false,
|
|
1412
|
+
dirty: false,
|
|
1413
|
+
parentListType: name(list)
|
|
1414
|
+
};
|
|
1415
|
+
return acc.concat(fragment);
|
|
1416
|
+
}
|
|
1417
|
+
}
|
|
1418
|
+
}, []);
|
|
1419
|
+
return parseList(depth, itemSelection, selectionState, list).concat(parsedSiblings);
|
|
1116
1420
|
});
|
|
1117
|
-
const parseList = (depth, itemSelection, selectionState, list) => bind(children(list), element => {
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1421
|
+
const parseList = (depth, itemSelection, selectionState, list) => bind(children(list), (element) => {
|
|
1422
|
+
const parser = isList(element) ? parseList : parseItem;
|
|
1423
|
+
const newDepth = depth + 1;
|
|
1424
|
+
return parser(newDepth, itemSelection, selectionState, element);
|
|
1121
1425
|
});
|
|
1122
1426
|
const parseLists = (lists, itemSelection) => {
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1427
|
+
const selectionState = Cell(false);
|
|
1428
|
+
const initialDepth = 0;
|
|
1429
|
+
return map(lists, (list) => ({
|
|
1430
|
+
sourceList: list,
|
|
1431
|
+
entries: parseList(initialDepth, itemSelection, selectionState, list)
|
|
1432
|
+
}));
|
|
1129
1433
|
};
|
|
1130
1434
|
|
|
1131
1435
|
const outdentedComposer = (editor, entries) => {
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1436
|
+
const normalizedEntries = normalizeEntries(entries);
|
|
1437
|
+
return map(normalizedEntries, (entry) => {
|
|
1438
|
+
const content = !isEntryComment(entry)
|
|
1439
|
+
? fromElements(entry.content)
|
|
1440
|
+
: fromElements([SugarElement.fromHtml(`<!--${entry.content}-->`)]);
|
|
1441
|
+
const listItemAttrs = isEntryList(entry) ? entry.itemAttributes : {};
|
|
1442
|
+
return SugarElement.fromDom(createTextBlock(editor, content.dom, listItemAttrs));
|
|
1443
|
+
});
|
|
1137
1444
|
};
|
|
1138
1445
|
const indentedComposer = (editor, entries) => {
|
|
1139
|
-
|
|
1140
|
-
|
|
1446
|
+
const normalizedEntries = normalizeEntries(entries);
|
|
1447
|
+
return composeList(editor.contentDocument, normalizedEntries).toArray();
|
|
1141
1448
|
};
|
|
1142
|
-
const composeEntries = (editor, entries) => bind(groupBy(entries, isIndented), entries => {
|
|
1143
|
-
|
|
1144
|
-
|
|
1449
|
+
const composeEntries = (editor, entries) => bind(groupBy(entries, isIndented), (entries) => {
|
|
1450
|
+
const groupIsIndented = head(entries).exists(isIndented);
|
|
1451
|
+
return groupIsIndented ? indentedComposer(editor, entries) : outdentedComposer(editor, entries);
|
|
1145
1452
|
});
|
|
1146
1453
|
const indentSelectedEntries = (entries, indentation) => {
|
|
1147
|
-
|
|
1454
|
+
each$1(filter$1(entries, isSelected), (entry) => indentEntry(indentation, entry));
|
|
1148
1455
|
};
|
|
1149
|
-
const getItemSelection = editor => {
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
start,
|
|
1153
|
-
end
|
|
1154
|
-
}));
|
|
1456
|
+
const getItemSelection = (editor) => {
|
|
1457
|
+
const selectedListItems = map(getSelectedListItems(editor), SugarElement.fromDom);
|
|
1458
|
+
return lift2(find(selectedListItems, not(hasFirstChildList)), find(reverse(selectedListItems), not(hasFirstChildList)), (start, end) => ({ start, end }));
|
|
1155
1459
|
};
|
|
1156
1460
|
const listIndentation = (editor, lists, indentation) => {
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1461
|
+
const entrySets = parseLists(lists, getItemSelection(editor));
|
|
1462
|
+
each$1(entrySets, (entrySet) => {
|
|
1463
|
+
indentSelectedEntries(entrySet.entries, indentation);
|
|
1464
|
+
const composedLists = composeEntries(editor, entrySet.entries);
|
|
1465
|
+
each$1(composedLists, (composedList) => {
|
|
1466
|
+
fireListEvent(editor, indentation === "Indent" /* Indentation.Indent */ ? "IndentList" /* ListAction.IndentList */ : "OutdentList" /* ListAction.OutdentList */, composedList.dom);
|
|
1467
|
+
});
|
|
1468
|
+
before(entrySet.sourceList, composedLists);
|
|
1469
|
+
remove(entrySet.sourceList);
|
|
1163
1470
|
});
|
|
1164
|
-
before(entrySet.sourceList, composedLists);
|
|
1165
|
-
remove(entrySet.sourceList);
|
|
1166
|
-
});
|
|
1167
1471
|
};
|
|
1168
1472
|
|
|
1169
1473
|
const selectionIndentation = (editor, indentation) => {
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1474
|
+
const lists = fromDom(getSelectedListRoots(editor));
|
|
1475
|
+
const dlItems = fromDom(getSelectedDlItems(editor));
|
|
1476
|
+
let isHandled = false;
|
|
1477
|
+
if (lists.length || dlItems.length) {
|
|
1478
|
+
const bookmark = editor.selection.getBookmark();
|
|
1479
|
+
listIndentation(editor, lists, indentation);
|
|
1480
|
+
dlIndentation(editor, indentation, dlItems);
|
|
1481
|
+
editor.selection.moveToBookmark(bookmark);
|
|
1482
|
+
editor.selection.setRng(normalizeRange(editor.selection.getRng()));
|
|
1483
|
+
editor.nodeChanged();
|
|
1484
|
+
isHandled = true;
|
|
1485
|
+
}
|
|
1486
|
+
return isHandled;
|
|
1183
1487
|
};
|
|
1184
1488
|
const handleIndentation = (editor, indentation) => !selectionIsWithinNonEditableList(editor) && selectionIndentation(editor, indentation);
|
|
1185
|
-
const indentListSelection = editor => handleIndentation(editor,
|
|
1186
|
-
const outdentListSelection = editor => handleIndentation(editor,
|
|
1187
|
-
const flattenListSelection = editor => handleIndentation(editor,
|
|
1188
|
-
|
|
1189
|
-
const zeroWidth = '\uFEFF';
|
|
1190
|
-
const isZwsp = char => char === zeroWidth;
|
|
1191
|
-
|
|
1192
|
-
const ancestor$1 = (scope, predicate, isRoot) => ancestor$3(scope, predicate, isRoot).isSome();
|
|
1193
|
-
|
|
1194
|
-
const ancestor = (element, target) => ancestor$1(element, curry(eq, target));
|
|
1489
|
+
const indentListSelection = (editor) => handleIndentation(editor, "Indent" /* Indentation.Indent */);
|
|
1490
|
+
const outdentListSelection = (editor) => handleIndentation(editor, "Outdent" /* Indentation.Outdent */);
|
|
1491
|
+
const flattenListSelection = (editor) => handleIndentation(editor, "Flatten" /* Indentation.Flatten */);
|
|
1195
1492
|
|
|
1196
1493
|
var global$1 = tinymce.util.Tools.resolve('tinymce.dom.BookmarkManager');
|
|
1197
1494
|
|
|
1198
1495
|
const DOM$1 = global$3.DOM;
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
while (node) {
|
|
1235
|
-
if (node === container) {
|
|
1236
|
-
return idx;
|
|
1237
|
-
}
|
|
1238
|
-
if (!isElement(node) || node.getAttribute('data-mce-type') !== 'bookmark') {
|
|
1239
|
-
idx++;
|
|
1240
|
-
}
|
|
1241
|
-
node = node.nextSibling;
|
|
1242
|
-
}
|
|
1243
|
-
return -1;
|
|
1496
|
+
/**
|
|
1497
|
+
* Returns a range bookmark. This will convert indexed bookmarks into temporary span elements with
|
|
1498
|
+
* index 0 so that they can be restored properly after the DOM has been modified. Text bookmarks will not have spans
|
|
1499
|
+
* added to them since they can be restored after a dom operation.
|
|
1500
|
+
*
|
|
1501
|
+
* So this: <p><b>|</b><b>|</b></p>
|
|
1502
|
+
* becomes: <p><b><span data-mce-type="bookmark">|</span></b><b data-mce-type="bookmark">|</span></b></p>
|
|
1503
|
+
*
|
|
1504
|
+
* @param {DOMRange} rng DOM Range to get bookmark on.
|
|
1505
|
+
* @return {Object} Bookmark object.
|
|
1506
|
+
*/
|
|
1507
|
+
const createBookmark = (rng) => {
|
|
1508
|
+
const bookmark = {};
|
|
1509
|
+
const setupEndPoint = (start) => {
|
|
1510
|
+
let container = rng[start ? 'startContainer' : 'endContainer'];
|
|
1511
|
+
let offset = rng[start ? 'startOffset' : 'endOffset'];
|
|
1512
|
+
if (isElement(container)) {
|
|
1513
|
+
const offsetNode = DOM$1.create('span', { 'data-mce-type': 'bookmark' });
|
|
1514
|
+
if (container.hasChildNodes()) {
|
|
1515
|
+
offset = Math.min(offset, container.childNodes.length - 1);
|
|
1516
|
+
if (start) {
|
|
1517
|
+
container.insertBefore(offsetNode, container.childNodes[offset]);
|
|
1518
|
+
}
|
|
1519
|
+
else {
|
|
1520
|
+
DOM$1.insertAfter(offsetNode, container.childNodes[offset]);
|
|
1521
|
+
}
|
|
1522
|
+
}
|
|
1523
|
+
else {
|
|
1524
|
+
container.appendChild(offsetNode);
|
|
1525
|
+
}
|
|
1526
|
+
container = offsetNode;
|
|
1527
|
+
offset = 0;
|
|
1528
|
+
}
|
|
1529
|
+
bookmark[start ? 'startContainer' : 'endContainer'] = container;
|
|
1530
|
+
bookmark[start ? 'startOffset' : 'endOffset'] = offset;
|
|
1244
1531
|
};
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1532
|
+
setupEndPoint(true);
|
|
1533
|
+
if (!rng.collapsed) {
|
|
1534
|
+
setupEndPoint();
|
|
1535
|
+
}
|
|
1536
|
+
return bookmark;
|
|
1537
|
+
};
|
|
1538
|
+
const resolveBookmark = (bookmark) => {
|
|
1539
|
+
const restoreEndPoint = (start) => {
|
|
1540
|
+
const nodeIndex = (container) => {
|
|
1541
|
+
var _a;
|
|
1542
|
+
let node = (_a = container.parentNode) === null || _a === void 0 ? void 0 : _a.firstChild;
|
|
1543
|
+
let idx = 0;
|
|
1544
|
+
while (node) {
|
|
1545
|
+
if (node === container) {
|
|
1546
|
+
return idx;
|
|
1547
|
+
}
|
|
1548
|
+
// Skip data-mce-type=bookmark nodes
|
|
1549
|
+
if (!isElement(node) || node.getAttribute('data-mce-type') !== 'bookmark') {
|
|
1550
|
+
idx++;
|
|
1551
|
+
}
|
|
1552
|
+
node = node.nextSibling;
|
|
1553
|
+
}
|
|
1554
|
+
return -1;
|
|
1555
|
+
};
|
|
1556
|
+
let container = bookmark[start ? 'startContainer' : 'endContainer'];
|
|
1557
|
+
let offset = bookmark[start ? 'startOffset' : 'endOffset'];
|
|
1558
|
+
if (!container) {
|
|
1559
|
+
return;
|
|
1560
|
+
}
|
|
1561
|
+
if (isElement(container) && container.parentNode) {
|
|
1562
|
+
const node = container;
|
|
1563
|
+
offset = nodeIndex(container);
|
|
1564
|
+
container = container.parentNode;
|
|
1565
|
+
DOM$1.remove(node);
|
|
1566
|
+
if (!container.hasChildNodes() && DOM$1.isBlock(container)) {
|
|
1567
|
+
container.appendChild(DOM$1.create('br'));
|
|
1568
|
+
}
|
|
1569
|
+
}
|
|
1570
|
+
bookmark[start ? 'startContainer' : 'endContainer'] = container;
|
|
1571
|
+
bookmark[start ? 'startOffset' : 'endOffset'] = offset;
|
|
1572
|
+
};
|
|
1573
|
+
restoreEndPoint(true);
|
|
1574
|
+
restoreEndPoint();
|
|
1575
|
+
const rng = DOM$1.createRng();
|
|
1576
|
+
rng.setStart(bookmark.startContainer, bookmark.startOffset);
|
|
1577
|
+
if (bookmark.endContainer) {
|
|
1578
|
+
rng.setEnd(bookmark.endContainer, bookmark.endOffset);
|
|
1579
|
+
}
|
|
1580
|
+
return normalizeRange(rng);
|
|
1581
|
+
};
|
|
1582
|
+
|
|
1583
|
+
const listToggleActionFromListName = (listName) => {
|
|
1584
|
+
switch (listName) {
|
|
1585
|
+
case 'UL': return "ToggleUlList" /* ListAction.ToggleUlList */;
|
|
1586
|
+
case 'OL': return "ToggleOlList" /* ListAction.ToggleOlList */;
|
|
1587
|
+
case 'DL': return "ToggleDLList" /* ListAction.ToggleDLList */;
|
|
1588
|
+
}
|
|
1281
1589
|
};
|
|
1282
1590
|
|
|
1283
1591
|
const updateListStyle = (dom, el, detail) => {
|
|
1284
|
-
|
|
1285
|
-
|
|
1592
|
+
const type = detail['list-style-type'] ? detail['list-style-type'] : null;
|
|
1593
|
+
dom.setStyle(el, 'list-style-type', type);
|
|
1286
1594
|
};
|
|
1287
1595
|
const setAttribs = (elm, attrs) => {
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1596
|
+
global$2.each(attrs, (value, key) => {
|
|
1597
|
+
elm.setAttribute(key, value);
|
|
1598
|
+
});
|
|
1291
1599
|
};
|
|
1292
1600
|
const updateListAttrs = (dom, el, detail) => {
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1601
|
+
setAttribs(el, detail['list-attributes']);
|
|
1602
|
+
global$2.each(dom.select('li', el), (li) => {
|
|
1603
|
+
setAttribs(li, detail['list-item-attributes']);
|
|
1604
|
+
});
|
|
1297
1605
|
};
|
|
1298
1606
|
const updateListWithDetails = (dom, el, detail) => {
|
|
1299
|
-
|
|
1300
|
-
|
|
1607
|
+
updateListStyle(dom, el, detail);
|
|
1608
|
+
updateListAttrs(dom, el, detail);
|
|
1301
1609
|
};
|
|
1302
1610
|
const removeStyles = (dom, element, styles) => {
|
|
1303
|
-
|
|
1611
|
+
global$2.each(styles, (style) => dom.setStyle(element, style, ''));
|
|
1304
1612
|
};
|
|
1305
1613
|
const isInline = (editor, node) => isNonNullable(node) && !isBlock(node, editor.schema.getBlockElements());
|
|
1306
1614
|
const getEndPointNode = (editor, rng, start, root) => {
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
if (!start && isBr(container.nextSibling)) {
|
|
1313
|
-
container = container.nextSibling;
|
|
1314
|
-
}
|
|
1315
|
-
const findBlockAncestor = node => {
|
|
1316
|
-
while (!editor.dom.isBlock(node) && node.parentNode && root !== node) {
|
|
1317
|
-
node = node.parentNode;
|
|
1318
|
-
}
|
|
1319
|
-
return node;
|
|
1320
|
-
};
|
|
1321
|
-
const findBetterContainer = (container, forward) => {
|
|
1322
|
-
var _a;
|
|
1323
|
-
const walker = new global$5(container, findBlockAncestor(container));
|
|
1324
|
-
const dir = forward ? 'next' : 'prev';
|
|
1325
|
-
let node;
|
|
1326
|
-
while (node = walker[dir]()) {
|
|
1327
|
-
if (!(isVoid(editor, node) || isZwsp(node.textContent) || ((_a = node.textContent) === null || _a === void 0 ? void 0 : _a.length) === 0)) {
|
|
1328
|
-
return Optional.some(node);
|
|
1329
|
-
}
|
|
1615
|
+
let container = rng[start ? 'startContainer' : 'endContainer'];
|
|
1616
|
+
const offset = rng[start ? 'startOffset' : 'endOffset'];
|
|
1617
|
+
// Resolve node index
|
|
1618
|
+
if (isElement(container)) {
|
|
1619
|
+
container = container.childNodes[Math.min(offset, container.childNodes.length - 1)] || container;
|
|
1330
1620
|
}
|
|
1331
|
-
|
|
1332
|
-
};
|
|
1333
|
-
if (start && isTextNode$1(container)) {
|
|
1334
|
-
if (isZwsp(container.textContent)) {
|
|
1335
|
-
container = findBetterContainer(container, false).getOr(container);
|
|
1336
|
-
} else {
|
|
1337
|
-
if (container.parentNode !== null && isInline(editor, container.parentNode)) {
|
|
1338
|
-
container = container.parentNode;
|
|
1339
|
-
}
|
|
1340
|
-
while (container.previousSibling !== null && (isInline(editor, container.previousSibling) || isTextNode$1(container.previousSibling))) {
|
|
1341
|
-
container = container.previousSibling;
|
|
1342
|
-
}
|
|
1343
|
-
}
|
|
1344
|
-
}
|
|
1345
|
-
if (!start && isTextNode$1(container)) {
|
|
1346
|
-
if (isZwsp(container.textContent)) {
|
|
1347
|
-
container = findBetterContainer(container, true).getOr(container);
|
|
1348
|
-
} else {
|
|
1349
|
-
if (container.parentNode !== null && isInline(editor, container.parentNode)) {
|
|
1350
|
-
container = container.parentNode;
|
|
1351
|
-
}
|
|
1352
|
-
while (container.nextSibling !== null && (isInline(editor, container.nextSibling) || isTextNode$1(container.nextSibling))) {
|
|
1621
|
+
if (!start && isBr(container.nextSibling)) {
|
|
1353
1622
|
container = container.nextSibling;
|
|
1354
|
-
}
|
|
1355
1623
|
}
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1624
|
+
const findBlockAncestor = (node) => {
|
|
1625
|
+
while (!editor.dom.isBlock(node) && node.parentNode && root !== node) {
|
|
1626
|
+
node = node.parentNode;
|
|
1627
|
+
}
|
|
1628
|
+
return node;
|
|
1629
|
+
};
|
|
1630
|
+
// The reason why the next two if statements exist is because when the root node is a table cell (possibly some other node types)
|
|
1631
|
+
// then the highest we can go up the dom hierarchy is one level below the table cell.
|
|
1632
|
+
// So what happens when we have a bunch of inline nodes and text nodes in the table cell
|
|
1633
|
+
// and when the selection is collapsed inside one of the inline nodes then only that inline node (or text node) will be included
|
|
1634
|
+
// in the created list because that would be one level below td node and the other inline nodes won't be included.
|
|
1635
|
+
// So the fix proposed is to traverse left when looking for start node (and traverse right when looking for end node)
|
|
1636
|
+
// and keep traversing as long as we have an inline or text node (same for traversing right).
|
|
1637
|
+
// This way we end up including all the inline elements in the created list.
|
|
1638
|
+
// For more info look at #TINY-6853
|
|
1639
|
+
const findBetterContainer = (container, forward) => {
|
|
1640
|
+
var _a;
|
|
1641
|
+
const walker = new global$5(container, findBlockAncestor(container));
|
|
1642
|
+
const dir = forward ? 'next' : 'prev';
|
|
1643
|
+
let node;
|
|
1644
|
+
while ((node = walker[dir]())) {
|
|
1645
|
+
if (!(isVoid(editor, node) || isZwsp(node.textContent) || ((_a = node.textContent) === null || _a === void 0 ? void 0 : _a.length) === 0)) {
|
|
1646
|
+
return Optional.some(node);
|
|
1647
|
+
}
|
|
1648
|
+
}
|
|
1649
|
+
return Optional.none();
|
|
1650
|
+
};
|
|
1651
|
+
// Traverse left to include inline/text nodes
|
|
1652
|
+
if (start && isTextNode$1(container)) {
|
|
1653
|
+
if (isZwsp(container.textContent)) {
|
|
1654
|
+
container = findBetterContainer(container, false).getOr(container);
|
|
1655
|
+
}
|
|
1656
|
+
else {
|
|
1657
|
+
if (container.parentNode !== null && isInline(editor, container.parentNode)) {
|
|
1658
|
+
container = container.parentNode;
|
|
1659
|
+
}
|
|
1660
|
+
while (container.previousSibling !== null && (isInline(editor, container.previousSibling) || isTextNode$1(container.previousSibling))) {
|
|
1661
|
+
container = container.previousSibling;
|
|
1662
|
+
}
|
|
1663
|
+
}
|
|
1664
|
+
}
|
|
1665
|
+
// Traverse right to include inline/text nodes
|
|
1666
|
+
if (!start && isTextNode$1(container)) {
|
|
1667
|
+
if (isZwsp(container.textContent)) {
|
|
1668
|
+
container = findBetterContainer(container, true).getOr(container);
|
|
1669
|
+
}
|
|
1670
|
+
else {
|
|
1671
|
+
if (container.parentNode !== null && isInline(editor, container.parentNode)) {
|
|
1672
|
+
container = container.parentNode;
|
|
1673
|
+
}
|
|
1674
|
+
while (container.nextSibling !== null && (isInline(editor, container.nextSibling) || isTextNode$1(container.nextSibling))) {
|
|
1675
|
+
container = container.nextSibling;
|
|
1676
|
+
}
|
|
1677
|
+
}
|
|
1361
1678
|
}
|
|
1362
|
-
|
|
1363
|
-
|
|
1679
|
+
while (container.parentNode !== root) {
|
|
1680
|
+
const parent = container.parentNode;
|
|
1681
|
+
if (isTextBlock(editor, container)) {
|
|
1682
|
+
return container;
|
|
1683
|
+
}
|
|
1684
|
+
if (/^(TD|TH)$/.test(parent.nodeName)) {
|
|
1685
|
+
return container;
|
|
1686
|
+
}
|
|
1687
|
+
container = parent;
|
|
1364
1688
|
}
|
|
1365
|
-
container
|
|
1366
|
-
}
|
|
1367
|
-
return container;
|
|
1689
|
+
return container;
|
|
1368
1690
|
};
|
|
1369
1691
|
const getSelectedTextBlocks = (editor, rng, root) => {
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
}
|
|
1382
|
-
global$2.each(siblings, node => {
|
|
1383
|
-
var _a;
|
|
1384
|
-
if (isTextBlock(editor, node)) {
|
|
1385
|
-
textBlocks.push(node);
|
|
1386
|
-
block = null;
|
|
1387
|
-
return;
|
|
1388
|
-
}
|
|
1389
|
-
if (dom.isBlock(node) || isBr(node)) {
|
|
1390
|
-
if (isBr(node)) {
|
|
1391
|
-
dom.remove(node);
|
|
1392
|
-
}
|
|
1393
|
-
block = null;
|
|
1394
|
-
return;
|
|
1395
|
-
}
|
|
1396
|
-
const nextSibling = node.nextSibling;
|
|
1397
|
-
if (global$1.isBookmarkNode(node)) {
|
|
1398
|
-
if (isListNode(nextSibling) || isTextBlock(editor, nextSibling) || !nextSibling && node.parentNode === root) {
|
|
1399
|
-
block = null;
|
|
1400
|
-
return;
|
|
1401
|
-
}
|
|
1402
|
-
}
|
|
1403
|
-
if (!block) {
|
|
1404
|
-
block = dom.create('p');
|
|
1405
|
-
(_a = node.parentNode) === null || _a === void 0 ? void 0 : _a.insertBefore(block, node);
|
|
1406
|
-
textBlocks.push(block);
|
|
1692
|
+
const textBlocks = [];
|
|
1693
|
+
const dom = editor.dom;
|
|
1694
|
+
const startNode = getEndPointNode(editor, rng, true, root);
|
|
1695
|
+
const endNode = getEndPointNode(editor, rng, false, root);
|
|
1696
|
+
let block;
|
|
1697
|
+
const siblings = [];
|
|
1698
|
+
for (let node = startNode; node; node = node.nextSibling) {
|
|
1699
|
+
siblings.push(node);
|
|
1700
|
+
if (node === endNode) {
|
|
1701
|
+
break;
|
|
1702
|
+
}
|
|
1407
1703
|
}
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1704
|
+
global$2.each(siblings, (node) => {
|
|
1705
|
+
var _a;
|
|
1706
|
+
if (isTextBlock(editor, node)) {
|
|
1707
|
+
textBlocks.push(node);
|
|
1708
|
+
block = null;
|
|
1709
|
+
return;
|
|
1710
|
+
}
|
|
1711
|
+
if (dom.isBlock(node) || isBr(node)) {
|
|
1712
|
+
if (isBr(node)) {
|
|
1713
|
+
dom.remove(node);
|
|
1714
|
+
}
|
|
1715
|
+
block = null;
|
|
1716
|
+
return;
|
|
1717
|
+
}
|
|
1718
|
+
const nextSibling = node.nextSibling;
|
|
1719
|
+
if (global$1.isBookmarkNode(node)) {
|
|
1720
|
+
if (isListNode(nextSibling) || isTextBlock(editor, nextSibling) || (!nextSibling && node.parentNode === root)) {
|
|
1721
|
+
block = null;
|
|
1722
|
+
return;
|
|
1723
|
+
}
|
|
1724
|
+
}
|
|
1725
|
+
if (!block) {
|
|
1726
|
+
block = dom.create('p');
|
|
1727
|
+
(_a = node.parentNode) === null || _a === void 0 ? void 0 : _a.insertBefore(block, node);
|
|
1728
|
+
textBlocks.push(block);
|
|
1729
|
+
}
|
|
1730
|
+
block.appendChild(node);
|
|
1731
|
+
});
|
|
1732
|
+
return textBlocks;
|
|
1411
1733
|
};
|
|
1412
1734
|
const hasCompatibleStyle = (dom, sib, detail) => {
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
};
|
|
1735
|
+
const sibStyle = dom.getStyle(sib, 'list-style-type');
|
|
1736
|
+
let detailStyle = detail ? detail['list-style-type'] : '';
|
|
1737
|
+
detailStyle = detailStyle === null ? '' : detailStyle;
|
|
1738
|
+
return sibStyle === detailStyle;
|
|
1739
|
+
};
|
|
1740
|
+
/*
|
|
1741
|
+
Find the first element we would transform into a li-element if given no constraints.
|
|
1742
|
+
If the common ancestor is higher up than that provide it as the starting-point for the search for the root instead of the first selected element.
|
|
1743
|
+
This helps avoid issues with divs that should become li-elements are detected as the root when they should not be.
|
|
1744
|
+
*/
|
|
1418
1745
|
const getRootSearchStart = (editor, range) => {
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1746
|
+
const start = editor.selection.getStart(true);
|
|
1747
|
+
const startPoint = getEndPointNode(editor, range, true, editor.getBody());
|
|
1748
|
+
if (ancestor(SugarElement.fromDom(startPoint), SugarElement.fromDom(range.commonAncestorContainer))) {
|
|
1749
|
+
return range.commonAncestorContainer;
|
|
1750
|
+
}
|
|
1751
|
+
else {
|
|
1752
|
+
return start;
|
|
1753
|
+
}
|
|
1426
1754
|
};
|
|
1427
1755
|
const applyList = (editor, listName, detail) => {
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
'padding-top'
|
|
1467
|
-
]);
|
|
1468
|
-
updateListWithDetails(dom, listBlock, detail);
|
|
1469
|
-
mergeWithAdjacentLists(editor.dom, listBlock);
|
|
1470
|
-
}
|
|
1471
|
-
});
|
|
1472
|
-
editor.selection.setRng(resolveBookmark(bookmark));
|
|
1756
|
+
const rng = editor.selection.getRng();
|
|
1757
|
+
let listItemName = 'LI';
|
|
1758
|
+
const root = getClosestListHost(editor, getRootSearchStart(editor, rng));
|
|
1759
|
+
const dom = editor.dom;
|
|
1760
|
+
if (dom.getContentEditable(editor.selection.getNode()) === 'false') {
|
|
1761
|
+
return;
|
|
1762
|
+
}
|
|
1763
|
+
listName = listName.toUpperCase();
|
|
1764
|
+
if (listName === 'DL') {
|
|
1765
|
+
listItemName = 'DT';
|
|
1766
|
+
}
|
|
1767
|
+
const bookmark = createBookmark(rng);
|
|
1768
|
+
const selectedTextBlocks = filter$1(getSelectedTextBlocks(editor, rng, root), editor.dom.isEditable);
|
|
1769
|
+
global$2.each(selectedTextBlocks, (block) => {
|
|
1770
|
+
let listBlock;
|
|
1771
|
+
const sibling = block.previousSibling;
|
|
1772
|
+
const parent = block.parentNode;
|
|
1773
|
+
if (!isListItemNode(parent)) {
|
|
1774
|
+
if (sibling && isListNode(sibling) && sibling.nodeName === listName && hasCompatibleStyle(dom, sibling, detail)) {
|
|
1775
|
+
listBlock = sibling;
|
|
1776
|
+
block = dom.rename(block, listItemName);
|
|
1777
|
+
sibling.appendChild(block);
|
|
1778
|
+
}
|
|
1779
|
+
else {
|
|
1780
|
+
listBlock = dom.create(listName);
|
|
1781
|
+
parent.insertBefore(listBlock, block);
|
|
1782
|
+
listBlock.appendChild(block);
|
|
1783
|
+
block = dom.rename(block, listItemName);
|
|
1784
|
+
}
|
|
1785
|
+
removeStyles(dom, block, [
|
|
1786
|
+
'margin', 'margin-right', 'margin-bottom', 'margin-left', 'margin-top',
|
|
1787
|
+
'padding', 'padding-right', 'padding-bottom', 'padding-left', 'padding-top'
|
|
1788
|
+
]);
|
|
1789
|
+
updateListWithDetails(dom, listBlock, detail);
|
|
1790
|
+
mergeWithAdjacentLists(editor.dom, listBlock);
|
|
1791
|
+
}
|
|
1792
|
+
});
|
|
1793
|
+
editor.selection.setRng(resolveBookmark(bookmark));
|
|
1473
1794
|
};
|
|
1474
1795
|
const isValidLists = (list1, list2) => {
|
|
1475
|
-
|
|
1796
|
+
return isListNode(list1) && list1.nodeName === (list2 === null || list2 === void 0 ? void 0 : list2.nodeName);
|
|
1476
1797
|
};
|
|
1477
1798
|
const hasSameListStyle = (dom, list1, list2) => {
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1799
|
+
const targetStyle = dom.getStyle(list1, 'list-style-type', true);
|
|
1800
|
+
const style = dom.getStyle(list2, 'list-style-type', true);
|
|
1801
|
+
return targetStyle === style;
|
|
1481
1802
|
};
|
|
1482
1803
|
const hasSameClasses = (elm1, elm2) => {
|
|
1483
|
-
|
|
1804
|
+
return elm1.className === elm2.className;
|
|
1484
1805
|
};
|
|
1485
1806
|
const shouldMerge = (dom, list1, list2) => {
|
|
1486
|
-
|
|
1807
|
+
return isValidLists(list1, list2) &&
|
|
1808
|
+
// Note: isValidLists will ensure list1 and list2 are a HTMLElement. Unfortunately TypeScript doesn't
|
|
1809
|
+
// support type guards on multiple variables. See https://github.com/microsoft/TypeScript/issues/26916
|
|
1810
|
+
hasSameListStyle(dom, list1, list2) &&
|
|
1811
|
+
hasSameClasses(list1, list2);
|
|
1487
1812
|
};
|
|
1488
1813
|
const mergeWithAdjacentLists = (dom, listBlock) => {
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1814
|
+
let node;
|
|
1815
|
+
let sibling = listBlock.nextSibling;
|
|
1816
|
+
if (shouldMerge(dom, listBlock, sibling)) {
|
|
1817
|
+
const liSibling = sibling;
|
|
1818
|
+
while ((node = liSibling.firstChild)) {
|
|
1819
|
+
listBlock.appendChild(node);
|
|
1820
|
+
}
|
|
1821
|
+
dom.remove(liSibling);
|
|
1822
|
+
}
|
|
1823
|
+
sibling = listBlock.previousSibling;
|
|
1824
|
+
if (shouldMerge(dom, listBlock, sibling)) {
|
|
1825
|
+
const liSibling = sibling;
|
|
1826
|
+
while ((node = liSibling.lastChild)) {
|
|
1827
|
+
listBlock.insertBefore(node, listBlock.firstChild);
|
|
1828
|
+
}
|
|
1829
|
+
dom.remove(liSibling);
|
|
1830
|
+
}
|
|
1506
1831
|
};
|
|
1507
1832
|
const updateList$1 = (editor, list, listName, detail) => {
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1833
|
+
if (list.nodeName !== listName) {
|
|
1834
|
+
const newList = editor.dom.rename(list, listName);
|
|
1835
|
+
updateListWithDetails(editor.dom, newList, detail);
|
|
1836
|
+
fireListEvent(editor, listToggleActionFromListName(listName), newList);
|
|
1837
|
+
}
|
|
1838
|
+
else {
|
|
1839
|
+
updateListWithDetails(editor.dom, list, detail);
|
|
1840
|
+
fireListEvent(editor, listToggleActionFromListName(listName), list);
|
|
1841
|
+
}
|
|
1516
1842
|
};
|
|
1517
1843
|
const updateCustomList = (editor, list, listName, detail) => {
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1844
|
+
list.classList.forEach((cls, _, classList) => {
|
|
1845
|
+
if (cls.startsWith('tox-')) {
|
|
1846
|
+
classList.remove(cls);
|
|
1847
|
+
if (classList.length === 0) {
|
|
1848
|
+
list.removeAttribute('class');
|
|
1849
|
+
}
|
|
1850
|
+
}
|
|
1851
|
+
});
|
|
1852
|
+
if (list.nodeName !== listName) {
|
|
1853
|
+
const newList = editor.dom.rename(list, listName);
|
|
1854
|
+
updateListWithDetails(editor.dom, newList, detail);
|
|
1855
|
+
fireListEvent(editor, listToggleActionFromListName(listName), newList);
|
|
1856
|
+
}
|
|
1857
|
+
else {
|
|
1858
|
+
updateListWithDetails(editor.dom, list, detail);
|
|
1859
|
+
fireListEvent(editor, listToggleActionFromListName(listName), list);
|
|
1860
|
+
}
|
|
1534
1861
|
};
|
|
1535
1862
|
const toggleMultipleLists = (editor, parentList, lists, listName, detail) => {
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
}
|
|
1550
|
-
editor.selection.setRng(resolveBookmark(bookmark));
|
|
1551
|
-
}
|
|
1863
|
+
const parentIsList = isListNode(parentList);
|
|
1864
|
+
if (parentIsList && parentList.nodeName === listName && !hasListStyleDetail(detail) && !isCustomList(parentList)) {
|
|
1865
|
+
flattenListSelection(editor);
|
|
1866
|
+
}
|
|
1867
|
+
else {
|
|
1868
|
+
applyList(editor, listName, detail);
|
|
1869
|
+
const bookmark = createBookmark(editor.selection.getRng());
|
|
1870
|
+
const allLists = parentIsList ? [parentList, ...lists] : lists;
|
|
1871
|
+
const updateFunction = (parentIsList && isCustomList(parentList)) ? updateCustomList : updateList$1;
|
|
1872
|
+
global$2.each(allLists, (elm) => {
|
|
1873
|
+
updateFunction(editor, elm, listName, detail);
|
|
1874
|
+
});
|
|
1875
|
+
editor.selection.setRng(resolveBookmark(bookmark));
|
|
1876
|
+
}
|
|
1552
1877
|
};
|
|
1553
|
-
const hasListStyleDetail = detail => {
|
|
1554
|
-
|
|
1878
|
+
const hasListStyleDetail = (detail) => {
|
|
1879
|
+
return 'list-style-type' in detail;
|
|
1555
1880
|
};
|
|
1556
1881
|
const toggleSingleList = (editor, parentList, listName, detail) => {
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1882
|
+
if (parentList === editor.getBody()) {
|
|
1883
|
+
return;
|
|
1884
|
+
}
|
|
1885
|
+
if (parentList) {
|
|
1886
|
+
if (parentList.nodeName === listName && !hasListStyleDetail(detail) && !isCustomList(parentList)) {
|
|
1887
|
+
flattenListSelection(editor);
|
|
1888
|
+
}
|
|
1889
|
+
else {
|
|
1890
|
+
const bookmark = createBookmark(editor.selection.getRng());
|
|
1891
|
+
if (isCustomList(parentList)) {
|
|
1892
|
+
parentList.classList.forEach((cls, _, classList) => {
|
|
1893
|
+
if (cls.startsWith('tox-')) {
|
|
1894
|
+
classList.remove(cls);
|
|
1895
|
+
if (classList.length === 0) {
|
|
1896
|
+
parentList.removeAttribute('class');
|
|
1897
|
+
}
|
|
1898
|
+
}
|
|
1899
|
+
});
|
|
1571
1900
|
}
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
fireListEvent(editor, listToggleActionFromListName(listName), parentList);
|
|
1585
|
-
}
|
|
1901
|
+
updateListWithDetails(editor.dom, parentList, detail);
|
|
1902
|
+
const newList = editor.dom.rename(parentList, listName);
|
|
1903
|
+
mergeWithAdjacentLists(editor.dom, newList);
|
|
1904
|
+
editor.selection.setRng(resolveBookmark(bookmark));
|
|
1905
|
+
applyList(editor, listName, detail);
|
|
1906
|
+
fireListEvent(editor, listToggleActionFromListName(listName), newList);
|
|
1907
|
+
}
|
|
1908
|
+
}
|
|
1909
|
+
else {
|
|
1910
|
+
applyList(editor, listName, detail);
|
|
1911
|
+
fireListEvent(editor, listToggleActionFromListName(listName), parentList);
|
|
1912
|
+
}
|
|
1586
1913
|
};
|
|
1587
1914
|
const toggleList = (editor, listName, _detail) => {
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1915
|
+
const parentList = getParentList(editor);
|
|
1916
|
+
if (isWithinNonEditableList(editor, parentList)) {
|
|
1917
|
+
return;
|
|
1918
|
+
}
|
|
1919
|
+
const selectedSubLists = getSelectedSubLists(editor);
|
|
1920
|
+
const detail = isObject(_detail) ? _detail : {};
|
|
1921
|
+
if (selectedSubLists.length > 0) {
|
|
1922
|
+
toggleMultipleLists(editor, parentList, selectedSubLists, listName, detail);
|
|
1923
|
+
}
|
|
1924
|
+
else {
|
|
1925
|
+
toggleSingleList(editor, parentList, listName, detail);
|
|
1926
|
+
}
|
|
1599
1927
|
};
|
|
1600
1928
|
|
|
1601
1929
|
const DOM = global$3.DOM;
|
|
1602
1930
|
const normalizeList = (dom, list) => {
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1931
|
+
const parentNode = list.parentElement;
|
|
1932
|
+
// Move UL/OL to previous LI if it's the only child of a LI
|
|
1933
|
+
if (parentNode && parentNode.nodeName === 'LI' && parentNode.firstChild === list) {
|
|
1934
|
+
const sibling = parentNode.previousSibling;
|
|
1935
|
+
if (sibling && sibling.nodeName === 'LI') {
|
|
1936
|
+
sibling.appendChild(list);
|
|
1937
|
+
if (isEmpty$1(dom, parentNode)) {
|
|
1938
|
+
DOM.remove(parentNode);
|
|
1939
|
+
}
|
|
1940
|
+
}
|
|
1941
|
+
else {
|
|
1942
|
+
DOM.setStyle(parentNode, 'listStyleType', 'none');
|
|
1943
|
+
}
|
|
1944
|
+
}
|
|
1945
|
+
// Append OL/UL to previous LI if it's in a parent OL/UL i.e. old HTML4
|
|
1946
|
+
if (isListNode(parentNode)) {
|
|
1947
|
+
const sibling = parentNode.previousSibling;
|
|
1948
|
+
if (sibling && sibling.nodeName === 'LI') {
|
|
1949
|
+
sibling.appendChild(list);
|
|
1950
|
+
}
|
|
1951
|
+
}
|
|
1621
1952
|
};
|
|
1622
1953
|
const normalizeLists = (dom, element) => {
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1954
|
+
const lists = global$2.grep(dom.select('ol,ul', element));
|
|
1955
|
+
global$2.each(lists, (list) => {
|
|
1956
|
+
normalizeList(dom, list);
|
|
1957
|
+
});
|
|
1627
1958
|
};
|
|
1628
1959
|
|
|
1629
1960
|
const findNextCaretContainer = (editor, rng, isForward, root) => {
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
if (
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1961
|
+
let node = rng.startContainer;
|
|
1962
|
+
const offset = rng.startOffset;
|
|
1963
|
+
if (isTextNode$1(node) && (isForward ? offset < node.data.length : offset > 0)) {
|
|
1964
|
+
return node;
|
|
1965
|
+
}
|
|
1966
|
+
const nonEmptyBlocks = editor.schema.getNonEmptyElements();
|
|
1967
|
+
if (isElement(node)) {
|
|
1968
|
+
node = global$6.getNode(node, offset);
|
|
1969
|
+
}
|
|
1970
|
+
const walker = new global$5(node, root);
|
|
1971
|
+
// Delete at <li>|<br></li> then jump over the bogus br
|
|
1972
|
+
if (isForward) {
|
|
1973
|
+
if (isBogusBr(editor.dom, node)) {
|
|
1974
|
+
walker.next();
|
|
1975
|
+
}
|
|
1976
|
+
}
|
|
1977
|
+
const walkFn = isForward ? walker.next.bind(walker) : walker.prev2.bind(walker);
|
|
1978
|
+
while ((node = walkFn())) {
|
|
1979
|
+
if (node.nodeName === 'LI' && !node.hasChildNodes()) {
|
|
1980
|
+
return node;
|
|
1981
|
+
}
|
|
1982
|
+
if (nonEmptyBlocks[node.nodeName]) {
|
|
1983
|
+
return node;
|
|
1984
|
+
}
|
|
1985
|
+
if (isTextNode$1(node) && node.data.length > 0) {
|
|
1986
|
+
return node;
|
|
1987
|
+
}
|
|
1988
|
+
}
|
|
1989
|
+
return null;
|
|
1658
1990
|
};
|
|
1659
1991
|
const hasOnlyOneBlockChild = (dom, elm) => {
|
|
1660
|
-
|
|
1661
|
-
|
|
1992
|
+
const childNodes = elm.childNodes;
|
|
1993
|
+
return childNodes.length === 1 && !isListNode(childNodes[0]) && dom.isBlock(childNodes[0]);
|
|
1662
1994
|
};
|
|
1663
|
-
const isUnwrappable = node => Optional.from(node)
|
|
1995
|
+
const isUnwrappable = (node) => Optional.from(node)
|
|
1996
|
+
.map(SugarElement.fromDom)
|
|
1997
|
+
.filter(isHTMLElement)
|
|
1998
|
+
.exists((el) => isEditable(el) && !contains$1(['details'], name(el)));
|
|
1664
1999
|
const unwrapSingleBlockChild = (dom, elm) => {
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
2000
|
+
if (hasOnlyOneBlockChild(dom, elm) && isUnwrappable(elm.firstChild)) {
|
|
2001
|
+
dom.remove(elm.firstChild, true);
|
|
2002
|
+
}
|
|
1668
2003
|
};
|
|
1669
2004
|
const moveChildren = (dom, fromElm, toElm) => {
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
2005
|
+
let node;
|
|
2006
|
+
const targetElm = hasOnlyOneBlockChild(dom, toElm) ? toElm.firstChild : toElm;
|
|
2007
|
+
unwrapSingleBlockChild(dom, fromElm);
|
|
2008
|
+
if (!isEmpty$1(dom, fromElm, true)) {
|
|
2009
|
+
while ((node = fromElm.firstChild)) {
|
|
2010
|
+
targetElm.appendChild(node);
|
|
2011
|
+
}
|
|
1676
2012
|
}
|
|
1677
|
-
}
|
|
1678
2013
|
};
|
|
1679
2014
|
const mergeLiElements = (dom, fromElm, toElm) => {
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
2015
|
+
let listNode;
|
|
2016
|
+
const ul = fromElm.parentNode;
|
|
2017
|
+
if (!isChildOfBody(dom, fromElm) || !isChildOfBody(dom, toElm)) {
|
|
2018
|
+
return;
|
|
2019
|
+
}
|
|
2020
|
+
if (isListNode(toElm.lastChild)) {
|
|
2021
|
+
listNode = toElm.lastChild;
|
|
2022
|
+
}
|
|
2023
|
+
if (ul === toElm.lastChild) {
|
|
2024
|
+
if (isBr(ul.previousSibling)) {
|
|
2025
|
+
dom.remove(ul.previousSibling);
|
|
2026
|
+
}
|
|
2027
|
+
}
|
|
2028
|
+
const node = toElm.lastChild;
|
|
2029
|
+
if (node && isBr(node) && fromElm.hasChildNodes()) {
|
|
2030
|
+
dom.remove(node);
|
|
2031
|
+
}
|
|
2032
|
+
if (isEmpty$1(dom, toElm, true)) {
|
|
2033
|
+
empty(SugarElement.fromDom(toElm));
|
|
2034
|
+
}
|
|
2035
|
+
moveChildren(dom, fromElm, toElm);
|
|
2036
|
+
if (listNode) {
|
|
2037
|
+
toElm.appendChild(listNode);
|
|
2038
|
+
}
|
|
2039
|
+
const contains$1 = contains(SugarElement.fromDom(toElm), SugarElement.fromDom(fromElm));
|
|
2040
|
+
const nestedLists = contains$1 ? dom.getParents(fromElm, isListNode, toElm) : [];
|
|
2041
|
+
dom.remove(fromElm);
|
|
2042
|
+
each$1(nestedLists, (list) => {
|
|
2043
|
+
if (isEmpty$1(dom, list) && list !== dom.getRoot()) {
|
|
2044
|
+
dom.remove(list);
|
|
2045
|
+
}
|
|
2046
|
+
});
|
|
1712
2047
|
};
|
|
1713
2048
|
const mergeIntoEmptyLi = (editor, fromLi, toLi) => {
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
2049
|
+
empty(SugarElement.fromDom(toLi));
|
|
2050
|
+
mergeLiElements(editor.dom, fromLi, toLi);
|
|
2051
|
+
editor.selection.setCursorLocation(toLi, 0);
|
|
1717
2052
|
};
|
|
1718
2053
|
const mergeForward = (editor, rng, fromLi, toLi) => {
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
2054
|
+
const dom = editor.dom;
|
|
2055
|
+
if (dom.isEmpty(toLi)) {
|
|
2056
|
+
mergeIntoEmptyLi(editor, fromLi, toLi);
|
|
2057
|
+
}
|
|
2058
|
+
else {
|
|
2059
|
+
const bookmark = createBookmark(rng);
|
|
2060
|
+
mergeLiElements(dom, fromLi, toLi);
|
|
2061
|
+
editor.selection.setRng(resolveBookmark(bookmark));
|
|
2062
|
+
}
|
|
1727
2063
|
};
|
|
1728
2064
|
const mergeBackward = (editor, rng, fromLi, toLi) => {
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
2065
|
+
const bookmark = createBookmark(rng);
|
|
2066
|
+
mergeLiElements(editor.dom, fromLi, toLi);
|
|
2067
|
+
const resolvedBookmark = resolveBookmark(bookmark);
|
|
2068
|
+
editor.selection.setRng(resolvedBookmark);
|
|
1733
2069
|
};
|
|
1734
2070
|
const backspaceDeleteFromListToListCaret = (editor, isForward) => {
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
}
|
|
1777
|
-
|
|
1778
|
-
|
|
2071
|
+
const dom = editor.dom, selection = editor.selection;
|
|
2072
|
+
const selectionStartElm = selection.getStart();
|
|
2073
|
+
const root = getClosestEditingHost(editor, selectionStartElm);
|
|
2074
|
+
const li = dom.getParent(selection.getStart(), 'LI', root);
|
|
2075
|
+
if (li) {
|
|
2076
|
+
const ul = li.parentElement;
|
|
2077
|
+
if (ul === editor.getBody() && isEmpty$1(dom, ul)) {
|
|
2078
|
+
return true;
|
|
2079
|
+
}
|
|
2080
|
+
const rng = normalizeRange(selection.getRng());
|
|
2081
|
+
const otherLi = dom.getParent(findNextCaretContainer(editor, rng, isForward, root), 'LI', root);
|
|
2082
|
+
const willMergeParentIntoChild = otherLi && (isForward ? dom.isChildOf(li, otherLi) : dom.isChildOf(otherLi, li));
|
|
2083
|
+
if (otherLi && otherLi !== li && !willMergeParentIntoChild) {
|
|
2084
|
+
editor.undoManager.transact(() => {
|
|
2085
|
+
if (isForward) {
|
|
2086
|
+
mergeForward(editor, rng, otherLi, li);
|
|
2087
|
+
}
|
|
2088
|
+
else {
|
|
2089
|
+
if (isFirstChild(li)) {
|
|
2090
|
+
outdentListSelection(editor);
|
|
2091
|
+
}
|
|
2092
|
+
else {
|
|
2093
|
+
mergeBackward(editor, rng, li, otherLi);
|
|
2094
|
+
}
|
|
2095
|
+
}
|
|
2096
|
+
});
|
|
2097
|
+
return true;
|
|
2098
|
+
}
|
|
2099
|
+
else if (willMergeParentIntoChild && !isForward && otherLi !== li) {
|
|
2100
|
+
const commonAncestorParent = rng.commonAncestorContainer.parentElement;
|
|
2101
|
+
if (!commonAncestorParent || dom.isChildOf(otherLi, commonAncestorParent)) {
|
|
2102
|
+
return false;
|
|
2103
|
+
}
|
|
2104
|
+
editor.undoManager.transact(() => {
|
|
2105
|
+
const bookmark = createBookmark(rng);
|
|
2106
|
+
moveChildren(dom, commonAncestorParent, otherLi);
|
|
2107
|
+
commonAncestorParent.remove();
|
|
2108
|
+
const resolvedBookmark = resolveBookmark(bookmark);
|
|
2109
|
+
editor.selection.setRng(resolvedBookmark);
|
|
2110
|
+
});
|
|
2111
|
+
return true;
|
|
2112
|
+
}
|
|
2113
|
+
else if (!otherLi) {
|
|
2114
|
+
if (!isForward && rng.startOffset === 0 && rng.endOffset === 0) {
|
|
2115
|
+
editor.undoManager.transact(() => {
|
|
2116
|
+
flattenListSelection(editor);
|
|
2117
|
+
});
|
|
2118
|
+
return true;
|
|
2119
|
+
}
|
|
2120
|
+
}
|
|
1779
2121
|
}
|
|
1780
|
-
|
|
1781
|
-
return false;
|
|
2122
|
+
return false;
|
|
1782
2123
|
};
|
|
1783
2124
|
const removeBlock = (dom, block, root) => {
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
2125
|
+
const parentBlock = dom.getParent(block.parentNode, dom.isBlock, root);
|
|
2126
|
+
dom.remove(block);
|
|
2127
|
+
if (parentBlock && dom.isEmpty(parentBlock)) {
|
|
2128
|
+
dom.remove(parentBlock);
|
|
2129
|
+
}
|
|
1789
2130
|
};
|
|
1790
2131
|
const backspaceDeleteIntoListCaret = (editor, isForward) => {
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
}
|
|
1819
|
-
}
|
|
1820
|
-
return false;
|
|
2132
|
+
const dom = editor.dom;
|
|
2133
|
+
const selectionStartElm = editor.selection.getStart();
|
|
2134
|
+
const root = getClosestEditingHost(editor, selectionStartElm);
|
|
2135
|
+
const block = dom.getParent(selectionStartElm, dom.isBlock, root);
|
|
2136
|
+
if (block && dom.isEmpty(block, undefined, { checkRootAsContent: true })) {
|
|
2137
|
+
const rng = normalizeRange(editor.selection.getRng());
|
|
2138
|
+
const nextCaretContainer = findNextCaretContainer(editor, rng, isForward, root);
|
|
2139
|
+
const otherLi = dom.getParent(nextCaretContainer, 'LI', root);
|
|
2140
|
+
if (nextCaretContainer && otherLi) {
|
|
2141
|
+
const findValidElement = (element) => contains$1(['td', 'th', 'caption'], name(element));
|
|
2142
|
+
const findRoot = (node) => node.dom === root;
|
|
2143
|
+
const otherLiCell = closest$2(SugarElement.fromDom(otherLi), findValidElement, findRoot);
|
|
2144
|
+
const caretCell = closest$2(SugarElement.fromDom(rng.startContainer), findValidElement, findRoot);
|
|
2145
|
+
if (!equals(otherLiCell, caretCell, eq)) {
|
|
2146
|
+
return false;
|
|
2147
|
+
}
|
|
2148
|
+
editor.undoManager.transact(() => {
|
|
2149
|
+
const parentNode = otherLi.parentNode;
|
|
2150
|
+
removeBlock(dom, block, root);
|
|
2151
|
+
mergeWithAdjacentLists(dom, parentNode);
|
|
2152
|
+
editor.selection.select(nextCaretContainer, true);
|
|
2153
|
+
editor.selection.collapse(isForward);
|
|
2154
|
+
});
|
|
2155
|
+
return true;
|
|
2156
|
+
}
|
|
2157
|
+
}
|
|
2158
|
+
return false;
|
|
1821
2159
|
};
|
|
1822
2160
|
const backspaceDeleteCaret = (editor, isForward) => {
|
|
1823
|
-
|
|
2161
|
+
return backspaceDeleteFromListToListCaret(editor, isForward) || backspaceDeleteIntoListCaret(editor, isForward);
|
|
1824
2162
|
};
|
|
1825
|
-
const hasListSelection = editor => {
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
2163
|
+
const hasListSelection = (editor) => {
|
|
2164
|
+
const selectionStartElm = editor.selection.getStart();
|
|
2165
|
+
const root = getClosestEditingHost(editor, selectionStartElm);
|
|
2166
|
+
const startListParent = editor.dom.getParent(selectionStartElm, 'LI,DT,DD', root);
|
|
2167
|
+
return startListParent || getSelectedListItems(editor).length > 0;
|
|
1830
2168
|
};
|
|
1831
|
-
const backspaceDeleteRange = editor => {
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
2169
|
+
const backspaceDeleteRange = (editor) => {
|
|
2170
|
+
if (hasListSelection(editor)) {
|
|
2171
|
+
editor.undoManager.transact(() => {
|
|
2172
|
+
// Some delete actions may prevent the input event from being fired. If we do not detect it, we fire it ourselves.
|
|
2173
|
+
let shouldFireInput = true;
|
|
2174
|
+
const inputHandler = () => shouldFireInput = false;
|
|
2175
|
+
editor.on('input', inputHandler);
|
|
2176
|
+
editor.execCommand('Delete');
|
|
2177
|
+
editor.off('input', inputHandler);
|
|
2178
|
+
if (shouldFireInput) {
|
|
2179
|
+
editor.dispatch('input');
|
|
2180
|
+
}
|
|
2181
|
+
normalizeLists(editor.dom, editor.getBody());
|
|
2182
|
+
});
|
|
2183
|
+
return true;
|
|
2184
|
+
}
|
|
2185
|
+
return false;
|
|
1840
2186
|
};
|
|
1841
2187
|
const backspaceDelete = (editor, isForward) => {
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
e.
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
2188
|
+
const selection = editor.selection;
|
|
2189
|
+
return !isWithinNonEditableList(editor, selection.getNode()) && (selection.isCollapsed() ?
|
|
2190
|
+
backspaceDeleteCaret(editor, isForward) : backspaceDeleteRange(editor));
|
|
2191
|
+
};
|
|
2192
|
+
const setup$2 = (editor) => {
|
|
2193
|
+
editor.on('ExecCommand', (e) => {
|
|
2194
|
+
const cmd = e.command.toLowerCase();
|
|
2195
|
+
if ((cmd === 'delete' || cmd === 'forwarddelete') && hasListSelection(editor)) {
|
|
2196
|
+
normalizeLists(editor.dom, editor.getBody());
|
|
2197
|
+
}
|
|
2198
|
+
});
|
|
2199
|
+
editor.on('keydown', (e) => {
|
|
2200
|
+
if (e.keyCode === global$4.BACKSPACE) {
|
|
2201
|
+
if (backspaceDelete(editor, false)) {
|
|
2202
|
+
e.preventDefault();
|
|
2203
|
+
}
|
|
2204
|
+
}
|
|
2205
|
+
else if (e.keyCode === global$4.DELETE) {
|
|
2206
|
+
if (backspaceDelete(editor, true)) {
|
|
2207
|
+
e.preventDefault();
|
|
2208
|
+
}
|
|
2209
|
+
}
|
|
2210
|
+
});
|
|
2211
|
+
};
|
|
2212
|
+
|
|
2213
|
+
const get = (editor) => ({
|
|
2214
|
+
backspaceDelete: (isForward) => {
|
|
2215
|
+
backspaceDelete(editor, isForward);
|
|
2216
|
+
}
|
|
1869
2217
|
});
|
|
1870
2218
|
|
|
1871
2219
|
const updateList = (editor, update) => {
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
});
|
|
1884
|
-
};
|
|
1885
|
-
|
|
1886
|
-
const parseAlphabeticBase26 = str => {
|
|
1887
|
-
const chars = reverse(trim(str).split(''));
|
|
1888
|
-
const values = map(chars, (char, i) => {
|
|
1889
|
-
const charValue = char.toUpperCase().charCodeAt(0) - 'A'.charCodeAt(0) + 1;
|
|
1890
|
-
return Math.pow(26, i) * charValue;
|
|
1891
|
-
});
|
|
1892
|
-
return foldl(values, (sum, v) => sum + v, 0);
|
|
1893
|
-
};
|
|
1894
|
-
const composeAlphabeticBase26 = value => {
|
|
1895
|
-
value--;
|
|
1896
|
-
if (value < 0) {
|
|
1897
|
-
return '';
|
|
1898
|
-
} else {
|
|
1899
|
-
const remainder = value % 26;
|
|
1900
|
-
const quotient = Math.floor(value / 26);
|
|
1901
|
-
const rest = composeAlphabeticBase26(quotient);
|
|
1902
|
-
const char = String.fromCharCode('A'.charCodeAt(0) + remainder);
|
|
1903
|
-
return rest + char;
|
|
1904
|
-
}
|
|
1905
|
-
};
|
|
1906
|
-
const isUppercase = str => /^[A-Z]+$/.test(str);
|
|
1907
|
-
const isLowercase = str => /^[a-z]+$/.test(str);
|
|
1908
|
-
const isNumeric = str => /^[0-9]+$/.test(str);
|
|
1909
|
-
const deduceListType = start => {
|
|
1910
|
-
if (isNumeric(start)) {
|
|
1911
|
-
return 2;
|
|
1912
|
-
} else if (isUppercase(start)) {
|
|
1913
|
-
return 0;
|
|
1914
|
-
} else if (isLowercase(start)) {
|
|
1915
|
-
return 1;
|
|
1916
|
-
} else if (isEmpty$1(start)) {
|
|
1917
|
-
return 3;
|
|
1918
|
-
} else {
|
|
1919
|
-
return 4;
|
|
1920
|
-
}
|
|
1921
|
-
};
|
|
1922
|
-
const parseStartValue = start => {
|
|
1923
|
-
switch (deduceListType(start)) {
|
|
1924
|
-
case 2:
|
|
1925
|
-
return Optional.some({
|
|
1926
|
-
listStyleType: Optional.none(),
|
|
1927
|
-
start
|
|
1928
|
-
});
|
|
1929
|
-
case 0:
|
|
1930
|
-
return Optional.some({
|
|
1931
|
-
listStyleType: Optional.some('upper-alpha'),
|
|
1932
|
-
start: parseAlphabeticBase26(start).toString()
|
|
1933
|
-
});
|
|
1934
|
-
case 1:
|
|
1935
|
-
return Optional.some({
|
|
1936
|
-
listStyleType: Optional.some('lower-alpha'),
|
|
1937
|
-
start: parseAlphabeticBase26(start).toString()
|
|
2220
|
+
const parentList = getParentList(editor);
|
|
2221
|
+
if (parentList === null || isWithinNonEditableList(editor, parentList)) {
|
|
2222
|
+
return;
|
|
2223
|
+
}
|
|
2224
|
+
editor.undoManager.transact(() => {
|
|
2225
|
+
if (isObject(update.styles)) {
|
|
2226
|
+
editor.dom.setStyles(parentList, update.styles);
|
|
2227
|
+
}
|
|
2228
|
+
if (isObject(update.attrs)) {
|
|
2229
|
+
each(update.attrs, (v, k) => editor.dom.setAttrib(parentList, k, v));
|
|
2230
|
+
}
|
|
1938
2231
|
});
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
2232
|
+
};
|
|
2233
|
+
|
|
2234
|
+
// Example: 'AB' -> 28
|
|
2235
|
+
const parseAlphabeticBase26 = (str) => {
|
|
2236
|
+
const chars = reverse(trim(str).split(''));
|
|
2237
|
+
const values = map(chars, (char, i) => {
|
|
2238
|
+
const charValue = char.toUpperCase().charCodeAt(0) - 'A'.charCodeAt(0) + 1;
|
|
2239
|
+
return Math.pow(26, i) * charValue;
|
|
1943
2240
|
});
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2241
|
+
return foldl(values, (sum, v) => sum + v, 0);
|
|
2242
|
+
};
|
|
2243
|
+
// Example: 28 -> 'AB'
|
|
2244
|
+
const composeAlphabeticBase26 = (value) => {
|
|
2245
|
+
value--;
|
|
2246
|
+
if (value < 0) {
|
|
2247
|
+
return '';
|
|
2248
|
+
}
|
|
2249
|
+
else {
|
|
2250
|
+
const remainder = value % 26;
|
|
2251
|
+
const quotient = Math.floor(value / 26);
|
|
2252
|
+
const rest = composeAlphabeticBase26(quotient);
|
|
2253
|
+
const char = String.fromCharCode('A'.charCodeAt(0) + remainder);
|
|
2254
|
+
return rest + char;
|
|
2255
|
+
}
|
|
2256
|
+
};
|
|
2257
|
+
const isUppercase = (str) => /^[A-Z]+$/.test(str);
|
|
2258
|
+
const isLowercase = (str) => /^[a-z]+$/.test(str);
|
|
2259
|
+
const isNumeric = (str) => /^[0-9]+$/.test(str);
|
|
2260
|
+
const deduceListType = (start) => {
|
|
2261
|
+
if (isNumeric(start)) {
|
|
2262
|
+
return 2 /* ListType.Numeric */;
|
|
2263
|
+
}
|
|
2264
|
+
else if (isUppercase(start)) {
|
|
2265
|
+
return 0 /* ListType.UpperAlpha */;
|
|
2266
|
+
}
|
|
2267
|
+
else if (isLowercase(start)) {
|
|
2268
|
+
return 1 /* ListType.LowerAlpha */;
|
|
2269
|
+
}
|
|
2270
|
+
else if (isEmpty$2(start)) {
|
|
2271
|
+
return 3 /* ListType.None */;
|
|
2272
|
+
}
|
|
2273
|
+
else {
|
|
2274
|
+
return 4 /* ListType.Unknown */;
|
|
2275
|
+
}
|
|
2276
|
+
};
|
|
2277
|
+
const parseStartValue = (start) => {
|
|
2278
|
+
switch (deduceListType(start)) {
|
|
2279
|
+
case 2 /* ListType.Numeric */:
|
|
2280
|
+
return Optional.some({
|
|
2281
|
+
listStyleType: Optional.none(),
|
|
2282
|
+
start
|
|
2283
|
+
});
|
|
2284
|
+
case 0 /* ListType.UpperAlpha */:
|
|
2285
|
+
return Optional.some({
|
|
2286
|
+
listStyleType: Optional.some('upper-alpha'),
|
|
2287
|
+
start: parseAlphabeticBase26(start).toString()
|
|
2288
|
+
});
|
|
2289
|
+
case 1 /* ListType.LowerAlpha */:
|
|
2290
|
+
return Optional.some({
|
|
2291
|
+
listStyleType: Optional.some('lower-alpha'),
|
|
2292
|
+
start: parseAlphabeticBase26(start).toString()
|
|
2293
|
+
});
|
|
2294
|
+
case 3 /* ListType.None */:
|
|
2295
|
+
return Optional.some({
|
|
2296
|
+
listStyleType: Optional.none(),
|
|
2297
|
+
start: ''
|
|
2298
|
+
});
|
|
2299
|
+
case 4 /* ListType.Unknown */:
|
|
2300
|
+
return Optional.none();
|
|
2301
|
+
}
|
|
2302
|
+
};
|
|
2303
|
+
const parseDetail = (detail) => {
|
|
2304
|
+
const start = parseInt(detail.start, 10);
|
|
2305
|
+
if (is$2(detail.listStyleType, 'upper-alpha')) {
|
|
2306
|
+
return composeAlphabeticBase26(start);
|
|
2307
|
+
}
|
|
2308
|
+
else if (is$2(detail.listStyleType, 'lower-alpha')) {
|
|
2309
|
+
return composeAlphabeticBase26(start).toLowerCase();
|
|
2310
|
+
}
|
|
2311
|
+
else {
|
|
2312
|
+
return detail.start;
|
|
2313
|
+
}
|
|
2314
|
+
};
|
|
2315
|
+
|
|
2316
|
+
const open = (editor) => {
|
|
2317
|
+
// Find the current list and skip opening if the selection isn't in an ordered list
|
|
2318
|
+
const currentList = getParentList(editor);
|
|
2319
|
+
if (!isOlNode(currentList) || isWithinNonEditableList(editor, currentList)) {
|
|
2320
|
+
return;
|
|
2003
2321
|
}
|
|
2004
|
-
|
|
2322
|
+
editor.windowManager.open({
|
|
2323
|
+
title: 'List Properties',
|
|
2324
|
+
body: {
|
|
2325
|
+
type: 'panel',
|
|
2326
|
+
items: [
|
|
2327
|
+
{
|
|
2328
|
+
type: 'input',
|
|
2329
|
+
name: 'start',
|
|
2330
|
+
label: 'Start list at number',
|
|
2331
|
+
inputMode: 'numeric'
|
|
2332
|
+
}
|
|
2333
|
+
]
|
|
2334
|
+
},
|
|
2335
|
+
initialData: {
|
|
2336
|
+
start: parseDetail({
|
|
2337
|
+
start: editor.dom.getAttrib(currentList, 'start', '1'),
|
|
2338
|
+
listStyleType: Optional.from(editor.dom.getStyle(currentList, 'list-style-type'))
|
|
2339
|
+
})
|
|
2340
|
+
},
|
|
2341
|
+
buttons: [
|
|
2342
|
+
{
|
|
2343
|
+
type: 'cancel',
|
|
2344
|
+
name: 'cancel',
|
|
2345
|
+
text: 'Cancel'
|
|
2346
|
+
},
|
|
2347
|
+
{
|
|
2348
|
+
type: 'submit',
|
|
2349
|
+
name: 'save',
|
|
2350
|
+
text: 'Save',
|
|
2351
|
+
primary: true
|
|
2352
|
+
}
|
|
2353
|
+
],
|
|
2354
|
+
onSubmit: (api) => {
|
|
2355
|
+
const data = api.getData();
|
|
2356
|
+
parseStartValue(data.start).each((detail) => {
|
|
2357
|
+
editor.execCommand('mceListUpdate', false, {
|
|
2358
|
+
attrs: {
|
|
2359
|
+
start: detail.start === '1' ? '' : detail.start
|
|
2360
|
+
},
|
|
2361
|
+
styles: {
|
|
2362
|
+
'list-style-type': detail.listStyleType.getOr('')
|
|
2363
|
+
}
|
|
2364
|
+
});
|
|
2365
|
+
});
|
|
2366
|
+
api.close();
|
|
2367
|
+
}
|
|
2368
|
+
});
|
|
2005
2369
|
};
|
|
2006
2370
|
|
|
2007
2371
|
const queryListCommandState = (editor, listName) => () => {
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
};
|
|
2011
|
-
const registerDialog = editor => {
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
};
|
|
2016
|
-
const register$2 = editor => {
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2372
|
+
const parentList = getParentList(editor);
|
|
2373
|
+
return isNonNullable(parentList) && parentList.nodeName === listName;
|
|
2374
|
+
};
|
|
2375
|
+
const registerDialog = (editor) => {
|
|
2376
|
+
editor.addCommand('mceListProps', () => {
|
|
2377
|
+
open(editor);
|
|
2378
|
+
});
|
|
2379
|
+
};
|
|
2380
|
+
const register$2 = (editor) => {
|
|
2381
|
+
editor.on('BeforeExecCommand', (e) => {
|
|
2382
|
+
const cmd = e.command.toLowerCase();
|
|
2383
|
+
if (cmd === 'indent') {
|
|
2384
|
+
indentListSelection(editor);
|
|
2385
|
+
}
|
|
2386
|
+
else if (cmd === 'outdent') {
|
|
2387
|
+
outdentListSelection(editor);
|
|
2388
|
+
}
|
|
2389
|
+
});
|
|
2390
|
+
editor.addCommand('InsertUnorderedList', (ui, detail) => {
|
|
2391
|
+
toggleList(editor, 'UL', detail);
|
|
2392
|
+
});
|
|
2393
|
+
editor.addCommand('InsertOrderedList', (ui, detail) => {
|
|
2394
|
+
toggleList(editor, 'OL', detail);
|
|
2395
|
+
});
|
|
2396
|
+
editor.addCommand('InsertDefinitionList', (ui, detail) => {
|
|
2397
|
+
toggleList(editor, 'DL', detail);
|
|
2398
|
+
});
|
|
2399
|
+
editor.addCommand('RemoveList', () => {
|
|
2400
|
+
flattenListSelection(editor);
|
|
2401
|
+
});
|
|
2402
|
+
registerDialog(editor);
|
|
2403
|
+
editor.addCommand('mceListUpdate', (ui, detail) => {
|
|
2404
|
+
if (isObject(detail)) {
|
|
2405
|
+
updateList(editor, detail);
|
|
2406
|
+
}
|
|
2407
|
+
});
|
|
2408
|
+
editor.addQueryStateHandler('InsertUnorderedList', queryListCommandState(editor, 'UL'));
|
|
2409
|
+
editor.addQueryStateHandler('InsertOrderedList', queryListCommandState(editor, 'OL'));
|
|
2410
|
+
editor.addQueryStateHandler('InsertDefinitionList', queryListCommandState(editor, 'DL'));
|
|
2046
2411
|
};
|
|
2047
2412
|
|
|
2048
2413
|
var global = tinymce.util.Tools.resolve('tinymce.html.Node');
|
|
2049
2414
|
|
|
2050
|
-
const isTextNode = node => node.type === 3;
|
|
2051
|
-
const isEmpty = nodeBuffer => nodeBuffer.length === 0;
|
|
2052
|
-
const wrapInvalidChildren = list => {
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
}
|
|
2079
|
-
};
|
|
2080
|
-
const setup$1 = editor => {
|
|
2081
|
-
editor.on('PreInit', () => {
|
|
2082
|
-
const {parser} = editor;
|
|
2083
|
-
parser.addNodeFilter('ul,ol', nodes => each$1(nodes, wrapInvalidChildren));
|
|
2084
|
-
});
|
|
2085
|
-
};
|
|
2086
|
-
|
|
2087
|
-
const setupTabKey = editor => {
|
|
2088
|
-
editor.on('keydown', e => {
|
|
2089
|
-
if (e.keyCode !== global$4.TAB || global$4.metaKeyPressed(e)) {
|
|
2090
|
-
return;
|
|
2415
|
+
const isTextNode = (node) => node.type === 3;
|
|
2416
|
+
const isEmpty = (nodeBuffer) => nodeBuffer.length === 0;
|
|
2417
|
+
const wrapInvalidChildren = (list) => {
|
|
2418
|
+
const insertListItem = (buffer, refNode) => {
|
|
2419
|
+
const li = global.create('li');
|
|
2420
|
+
each$1(buffer, (node) => li.append(node));
|
|
2421
|
+
if (refNode) {
|
|
2422
|
+
list.insert(li, refNode, true);
|
|
2423
|
+
}
|
|
2424
|
+
else {
|
|
2425
|
+
list.append(li);
|
|
2426
|
+
}
|
|
2427
|
+
};
|
|
2428
|
+
const reducer = (buffer, node) => {
|
|
2429
|
+
if (isTextNode(node)) {
|
|
2430
|
+
return [...buffer, node];
|
|
2431
|
+
}
|
|
2432
|
+
else if (!isEmpty(buffer) && !isTextNode(node)) {
|
|
2433
|
+
insertListItem(buffer, node);
|
|
2434
|
+
return [];
|
|
2435
|
+
}
|
|
2436
|
+
else {
|
|
2437
|
+
return buffer;
|
|
2438
|
+
}
|
|
2439
|
+
};
|
|
2440
|
+
const restBuffer = foldl(list.children(), reducer, []);
|
|
2441
|
+
if (!isEmpty(restBuffer)) {
|
|
2442
|
+
insertListItem(restBuffer);
|
|
2091
2443
|
}
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
});
|
|
2098
|
-
};
|
|
2099
|
-
const setup = editor => {
|
|
2100
|
-
if (shouldIndentOnTab(editor)) {
|
|
2101
|
-
setupTabKey(editor);
|
|
2102
|
-
}
|
|
2103
|
-
setup$2(editor);
|
|
2104
|
-
};
|
|
2105
|
-
|
|
2106
|
-
const setupToggleButtonHandler = (editor, listName) => api => {
|
|
2107
|
-
const toggleButtonHandler = e => {
|
|
2108
|
-
api.setActive(inList(e.parents, listName));
|
|
2109
|
-
api.setEnabled(!isWithinNonEditableList(editor, e.element) && editor.selection.isEditable());
|
|
2110
|
-
};
|
|
2111
|
-
api.setEnabled(editor.selection.isEditable());
|
|
2112
|
-
return setNodeChangeHandler(editor, toggleButtonHandler);
|
|
2113
|
-
};
|
|
2114
|
-
const register$1 = editor => {
|
|
2115
|
-
const exec = command => () => editor.execCommand(command);
|
|
2116
|
-
if (!editor.hasPlugin('advlist')) {
|
|
2117
|
-
editor.ui.registry.addToggleButton('numlist', {
|
|
2118
|
-
icon: 'ordered-list',
|
|
2119
|
-
active: false,
|
|
2120
|
-
tooltip: 'Numbered list',
|
|
2121
|
-
onAction: exec('InsertOrderedList'),
|
|
2122
|
-
onSetup: setupToggleButtonHandler(editor, 'OL')
|
|
2123
|
-
});
|
|
2124
|
-
editor.ui.registry.addToggleButton('bullist', {
|
|
2125
|
-
icon: 'unordered-list',
|
|
2126
|
-
active: false,
|
|
2127
|
-
tooltip: 'Bullet list',
|
|
2128
|
-
onAction: exec('InsertUnorderedList'),
|
|
2129
|
-
onSetup: setupToggleButtonHandler(editor, 'UL')
|
|
2444
|
+
};
|
|
2445
|
+
const setup$1 = (editor) => {
|
|
2446
|
+
editor.on('PreInit', () => {
|
|
2447
|
+
const { parser } = editor;
|
|
2448
|
+
parser.addNodeFilter('ul,ol', (nodes) => each$1(nodes, wrapInvalidChildren));
|
|
2130
2449
|
});
|
|
2131
|
-
}
|
|
2132
2450
|
};
|
|
2133
2451
|
|
|
2134
|
-
const
|
|
2135
|
-
|
|
2136
|
-
|
|
2452
|
+
const setupTabKey = (editor) => {
|
|
2453
|
+
editor.on('keydown', (e) => {
|
|
2454
|
+
// Check for tab but not ctrl/cmd+tab since it switches browser tabs
|
|
2455
|
+
if (e.keyCode !== global$4.TAB || global$4.metaKeyPressed(e)) {
|
|
2456
|
+
return;
|
|
2457
|
+
}
|
|
2458
|
+
editor.undoManager.transact(() => {
|
|
2459
|
+
if (e.shiftKey ? outdentListSelection(editor) : indentListSelection(editor)) {
|
|
2460
|
+
e.preventDefault();
|
|
2461
|
+
}
|
|
2462
|
+
});
|
|
2463
|
+
});
|
|
2137
2464
|
};
|
|
2138
|
-
const
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
icon: 'ordered-list',
|
|
2142
|
-
onAction: () => editor.execCommand('mceListProps'),
|
|
2143
|
-
onSetup: setupMenuButtonHandler(editor, 'OL')
|
|
2144
|
-
};
|
|
2145
|
-
editor.ui.registry.addMenuItem('listprops', listProperties);
|
|
2146
|
-
editor.ui.registry.addContextMenu('lists', {
|
|
2147
|
-
update: node => {
|
|
2148
|
-
const parentList = getParentList(editor, node);
|
|
2149
|
-
return isOlNode(parentList) ? ['listprops'] : [];
|
|
2465
|
+
const setup = (editor) => {
|
|
2466
|
+
if (shouldIndentOnTab(editor)) {
|
|
2467
|
+
setupTabKey(editor);
|
|
2150
2468
|
}
|
|
2151
|
-
|
|
2469
|
+
setup$2(editor);
|
|
2152
2470
|
};
|
|
2153
2471
|
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2472
|
+
const setupToggleButtonHandler = (editor, listName) => (api) => {
|
|
2473
|
+
const toggleButtonHandler = (e) => {
|
|
2474
|
+
api.setActive(inList(e.parents, listName));
|
|
2475
|
+
api.setEnabled(!isWithinNonEditableList(editor, e.element) && editor.selection.isEditable());
|
|
2476
|
+
};
|
|
2477
|
+
api.setEnabled(editor.selection.isEditable());
|
|
2478
|
+
return setNodeChangeHandler(editor, toggleButtonHandler);
|
|
2479
|
+
};
|
|
2480
|
+
const register$1 = (editor) => {
|
|
2481
|
+
const exec = (command) => () => editor.execCommand(command);
|
|
2482
|
+
if (!editor.hasPlugin('advlist')) {
|
|
2483
|
+
editor.ui.registry.addToggleButton('numlist', {
|
|
2484
|
+
icon: 'ordered-list',
|
|
2485
|
+
active: false,
|
|
2486
|
+
tooltip: 'Numbered list',
|
|
2487
|
+
onAction: exec('InsertOrderedList'),
|
|
2488
|
+
onSetup: setupToggleButtonHandler(editor, 'OL')
|
|
2489
|
+
});
|
|
2490
|
+
editor.ui.registry.addToggleButton('bullist', {
|
|
2491
|
+
icon: 'unordered-list',
|
|
2492
|
+
active: false,
|
|
2493
|
+
tooltip: 'Bullet list',
|
|
2494
|
+
onAction: exec('InsertUnorderedList'),
|
|
2495
|
+
onSetup: setupToggleButtonHandler(editor, 'UL')
|
|
2496
|
+
});
|
|
2163
2497
|
}
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2498
|
+
};
|
|
2499
|
+
|
|
2500
|
+
const setupMenuButtonHandler = (editor, listName) => (api) => {
|
|
2501
|
+
const menuButtonHandler = (e) => api.setEnabled(inList(e.parents, listName) && !isWithinNonEditableList(editor, e.element));
|
|
2502
|
+
return setNodeChangeHandler(editor, menuButtonHandler);
|
|
2503
|
+
};
|
|
2504
|
+
const register = (editor) => {
|
|
2505
|
+
const listProperties = {
|
|
2506
|
+
text: 'List properties...',
|
|
2507
|
+
icon: 'ordered-list',
|
|
2508
|
+
onAction: () => editor.execCommand('mceListProps'),
|
|
2509
|
+
onSetup: setupMenuButtonHandler(editor, 'OL')
|
|
2510
|
+
};
|
|
2511
|
+
editor.ui.registry.addMenuItem('listprops', listProperties);
|
|
2512
|
+
editor.ui.registry.addContextMenu('lists', {
|
|
2513
|
+
update: (node) => {
|
|
2514
|
+
const parentList = getParentList(editor, node);
|
|
2515
|
+
return isOlNode(parentList) ? ['listprops'] : [];
|
|
2516
|
+
}
|
|
2517
|
+
});
|
|
2518
|
+
};
|
|
2519
|
+
|
|
2520
|
+
var Plugin = () => {
|
|
2521
|
+
global$7.add('lists', (editor) => {
|
|
2522
|
+
register$3(editor);
|
|
2523
|
+
setup$1(editor);
|
|
2524
|
+
if (!editor.hasPlugin('rtc', true)) {
|
|
2525
|
+
setup(editor);
|
|
2526
|
+
register$2(editor);
|
|
2527
|
+
}
|
|
2528
|
+
else {
|
|
2529
|
+
registerDialog(editor);
|
|
2530
|
+
}
|
|
2531
|
+
register$1(editor);
|
|
2532
|
+
register(editor);
|
|
2533
|
+
return get(editor);
|
|
2534
|
+
});
|
|
2168
2535
|
};
|
|
2169
2536
|
|
|
2170
2537
|
Plugin();
|
|
2538
|
+
/** *****
|
|
2539
|
+
* DO NOT EXPORT ANYTHING
|
|
2540
|
+
*
|
|
2541
|
+
* IF YOU DO ROLLUP WILL LEAVE A GLOBAL ON THE PAGE
|
|
2542
|
+
*******/
|
|
2171
2543
|
|
|
2172
2544
|
})();
|