jodit 3.15.2 → 3.16.2
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/.idea/workspace.xml +301 -299
- package/CHANGELOG.MD +88 -7
- package/CONTRIBUTING.md +97 -0
- package/README.md +7 -7
- package/build/jodit.css +38 -32
- package/build/jodit.es2018.css +37 -31
- package/build/jodit.es2018.en.css +37 -31
- package/build/jodit.es2018.en.js +1981 -1393
- package/build/jodit.es2018.en.min.css +1 -1
- package/build/jodit.es2018.en.min.js +1 -1
- package/build/jodit.es2018.js +2053 -1447
- package/build/jodit.es2018.min.css +1 -1
- package/build/jodit.es2018.min.js +1 -1
- package/build/jodit.js +3475 -2625
- package/build/jodit.min.css +2 -2
- package/build/jodit.min.js +1 -1
- package/build/vdom.css +1 -1
- package/build/vdom.js +32 -20
- package/package.json +13 -13
- package/src/README.md +1 -1
- package/src/config.ts +69 -36
- package/src/core/async/async.ts +46 -24
- package/src/core/constants.ts +1 -0
- package/src/core/decorators/README.md +35 -0
- package/src/core/decorators/cache/cache.ts +1 -1
- package/src/core/decorators/debounce/debounce.ts +20 -9
- package/src/core/decorators/idle/README.md +14 -0
- package/src/core/decorators/idle/idle.ts +1 -1
- package/src/core/decorators/watch/watch.ts +8 -7
- package/src/core/dom/README.md +42 -0
- package/src/core/dom/dom.ts +37 -23
- package/src/core/dom/index.ts +1 -0
- package/src/core/dom/lazy-walker.ts +133 -0
- package/src/core/event-emitter/event-emitter.ts +8 -8
- package/src/core/event-emitter/eventify.ts +73 -0
- package/src/core/event-emitter/index.ts +1 -0
- package/src/core/helpers/html/apply-styles.ts +1 -1
- package/src/core/helpers/html/strip-tags.ts +3 -2
- package/src/core/helpers/string/fuzzy-search-index.ts +58 -0
- package/src/core/helpers/string/i18n.ts +1 -1
- package/src/core/helpers/string/index.ts +3 -2
- package/src/core/helpers/utils/append-script.ts +1 -1
- package/src/core/helpers/utils/css.ts +1 -1
- package/src/core/helpers/utils/selector.ts +1 -1
- package/src/core/helpers/utils/utils.ts +3 -3
- package/src/core/plugin/plugin-system.ts +14 -8
- package/src/core/request/ajax.ts +3 -3
- package/src/core/selection/select.ts +10 -10
- package/src/core/selection/style/api/toggle/toggle-css.ts +5 -2
- package/src/core/selection/style/api/wrap-unwrapped-text.ts +1 -1
- package/src/core/selection/style/apply-style.ts +4 -4
- package/src/core/storage/engines/local-storage-provider.ts +20 -19
- package/src/core/ui/button/button/button.ts +5 -5
- package/src/core/ui/element.ts +2 -2
- package/src/core/ui/form/inputs/input/input.ts +1 -1
- package/src/core/ui/form/inputs/select/select.ts +1 -1
- package/src/core/ui/group/list.ts +2 -2
- package/src/core/vdom/render/index.ts +12 -8
- package/src/core/vdom/v-dom-jodit.ts +1 -1
- package/src/core/view/view.ts +1 -1
- package/src/index.ts +3 -3
- package/src/jodit.ts +72 -55
- package/src/langs/README.md +1 -1
- package/src/langs/ar.js +2 -1
- package/src/langs/cs_cz.js +2 -1
- package/src/langs/de.js +2 -1
- package/src/langs/es.js +2 -1
- package/src/langs/fa.js +2 -1
- package/src/langs/fr.js +2 -1
- package/src/langs/he.js +2 -1
- package/src/langs/hu.js +2 -1
- package/src/langs/id.js +2 -1
- package/src/langs/index.ts +1 -1
- package/src/langs/it.js +2 -1
- package/src/langs/ja.js +2 -1
- package/src/langs/ko.js +2 -1
- package/src/langs/nl.js +2 -1
- package/src/langs/pl.js +2 -1
- package/src/langs/pt_br.js +2 -1
- package/src/langs/ru.js +2 -1
- package/src/langs/tr.js +2 -1
- package/src/langs/zh_cn.js +2 -1
- package/src/langs/zh_tw.js +2 -1
- package/src/modules/dialog/dialog.ts +6 -6
- package/src/modules/dialog/prompt.ts +1 -1
- package/src/modules/file-browser/README.md +2 -2
- package/src/modules/file-browser/builders/context-menu.ts +12 -13
- package/src/modules/file-browser/fetch/load-tree.ts +1 -1
- package/src/modules/file-browser/file-browser.ts +10 -7
- package/src/modules/history/README.md +5 -0
- package/src/modules/{observer → history}/command.ts +5 -5
- package/src/modules/{observer/observer.ts → history/history.ts} +97 -55
- package/src/modules/{observer → history}/snapshot.ts +3 -4
- package/src/modules/{observer → history}/stack.ts +4 -4
- package/src/modules/image-editor/image-editor.ts +8 -8
- package/src/modules/image-editor/templates/form.ts +2 -2
- package/src/modules/index.ts +3 -3
- package/src/modules/status-bar/status-bar.ts +4 -0
- package/src/modules/table/table.ts +2 -2
- package/src/modules/toolbar/button/button.ts +2 -2
- package/src/modules/toolbar/collection/collection.ts +1 -1
- package/src/modules/uploader/helpers/process-old-browser-drag.ts +1 -1
- package/src/modules/uploader/helpers/send-files.ts +1 -1
- package/src/modules/uploader/helpers/send.ts +1 -1
- package/src/modules/uploader/uploader.ts +3 -3
- package/src/modules/widget/color-picker/color-picker.ts +2 -3
- package/src/modules/widget/tabs/tabs.ts +17 -12
- package/src/plugins/add-new-line/add-new-line.ts +8 -8
- package/src/plugins/class-span/class-span.ts +1 -1
- package/src/plugins/clipboard/copy-format.ts +1 -1
- package/src/plugins/clipboard/drag-and-drop-element.ts +4 -2
- package/src/plugins/clipboard/paste/config.ts +19 -3
- package/src/plugins/clipboard/paste/helpers.ts +17 -50
- package/src/plugins/clipboard/paste/interface.ts +6 -0
- package/src/plugins/clipboard/paste/paste.ts +22 -8
- package/src/plugins/clipboard/paste-from-word/config.ts +17 -0
- package/src/plugins/clipboard/paste-from-word/paste-from-word.ts +15 -6
- package/src/plugins/clipboard/paste-storage/paste-storage.ts +6 -6
- package/src/plugins/color/color.ts +2 -2
- package/src/plugins/error-messages/error-messages.ts +2 -2
- package/src/plugins/fix/clean-html/README.md +26 -0
- package/src/plugins/fix/{clean-html.ts → clean-html/clean-html.ts} +59 -142
- package/src/plugins/fix/clean-html/config.ts +106 -0
- package/src/plugins/fix/index.ts +12 -0
- package/src/plugins/fix/wrap-nodes/README.md +27 -0
- package/src/plugins/fix/wrap-nodes/config.ts +24 -0
- package/src/plugins/fix/{wrap-text-nodes.ts → wrap-nodes/wrap-nodes.ts} +9 -4
- package/src/plugins/focus/focus.ts +1 -1
- package/src/plugins/format-block/format-block.ts +1 -1
- package/src/plugins/fullsize/fullsize.ts +4 -4
- package/src/plugins/iframe/iframe.ts +3 -3
- package/src/plugins/image/image-properties/image-properties.ts +12 -13
- package/src/plugins/indent/indent.ts +1 -1
- package/src/plugins/index.ts +2 -2
- package/src/plugins/inline-popup/config/items/a.ts +2 -2
- package/src/plugins/inline-popup/config/items/cells.ts +11 -11
- package/src/plugins/inline-popup/config/items/iframe.ts +1 -1
- package/src/plugins/inline-popup/config/items/img.ts +7 -7
- package/src/plugins/inline-popup/inline-popup.ts +5 -5
- package/src/plugins/keyboard/backspace/backspace.ts +1 -1
- package/src/plugins/keyboard/backspace/cases/check-join-neighbors.ts +1 -1
- package/src/plugins/keyboard/helpers.ts +1 -1
- package/src/plugins/keyboard/hotkeys.ts +1 -1
- package/src/plugins/limit/limit.ts +3 -3
- package/src/plugins/line-height/line-height.ts +1 -1
- package/src/plugins/link/link.ts +8 -8
- package/src/plugins/link/template.ts +2 -2
- package/src/plugins/media/file.ts +1 -1
- package/src/plugins/media/media.ts +1 -1
- package/src/plugins/media/video/config.ts +1 -1
- package/src/plugins/mobile/config.ts +1 -1
- package/src/plugins/mobile/mobile.ts +1 -1
- package/src/plugins/ordered-list/config.ts +61 -0
- package/src/plugins/ordered-list/ordered-list.ts +3 -153
- package/src/plugins/placeholder/placeholder.ts +3 -3
- package/src/plugins/print/helpers.ts +14 -7
- package/src/plugins/print/index.ts +1 -1
- package/src/plugins/print/{preview.less → preview/preview.less} +1 -1
- package/src/plugins/print/{preview.ts → preview/preview.ts} +9 -8
- package/src/plugins/print/print.ts +19 -10
- package/src/plugins/redo-undo/redo-undo.ts +3 -3
- package/src/plugins/resizer/resizer.ts +11 -11
- package/src/plugins/search/README.md +38 -0
- package/src/plugins/search/config.ts +82 -0
- package/src/plugins/search/helpers/index.ts +12 -0
- package/src/plugins/search/helpers/sentence-finder.ts +103 -0
- package/src/plugins/search/helpers/wrap-ranges-texts-in-tmp-span.ts +120 -0
- package/src/plugins/search/search.ts +269 -615
- package/src/plugins/search/ui/search.less +159 -0
- package/src/plugins/search/ui/search.ts +256 -0
- package/src/plugins/select/select.ts +1 -1
- package/src/plugins/size/config.ts +8 -8
- package/src/plugins/size/resize-handler.ts +3 -3
- package/src/plugins/size/size.ts +4 -4
- package/src/plugins/source/editor/engines/ace.ts +9 -9
- package/src/plugins/source/editor/engines/area.ts +3 -3
- package/src/plugins/source/source.ts +6 -6
- package/src/plugins/spellcheck/README.md +1 -0
- package/src/plugins/spellcheck/config.ts +34 -0
- package/src/plugins/spellcheck/spellcheck.svg +4 -0
- package/src/plugins/spellcheck/spellcheck.ts +48 -0
- package/src/plugins/sticky/sticky.ts +3 -3
- package/src/plugins/table/resize-cells.ts +11 -11
- package/src/plugins/table/select-cells.ts +2 -2
- package/src/plugins/tooltip/tooltip.ts +1 -1
- package/src/plugins/xpath/xpath.ts +8 -8
- package/src/polyfills.ts +5 -4
- package/src/styles/icons/README.md +2 -2
- package/src/types/async.d.ts +12 -2
- package/src/types/core.ts +1 -1
- package/src/types/events.d.ts +6 -2
- package/src/types/file-browser.d.ts +1 -2
- package/{types/types/observer.d.ts → src/types/history.d.ts} +11 -7
- package/src/types/index.d.ts +1 -1
- package/src/types/jodit.d.ts +12 -4
- package/src/types/toolbar.d.ts +5 -5
- package/src/types/types.d.ts +11 -4
- package/types/config.d.ts +68 -35
- package/types/core/async/async.d.ts +11 -4
- package/types/core/constants.d.ts +1 -0
- package/types/core/dom/dom.d.ts +3 -5
- package/types/core/dom/index.d.ts +1 -0
- package/types/core/dom/lazy-walker.d.ts +37 -0
- package/types/core/event-emitter/eventify.d.ts +39 -0
- package/types/core/event-emitter/index.d.ts +1 -0
- package/types/core/helpers/string/fuzzy-search-index.d.ts +10 -0
- package/types/core/helpers/string/i18n.d.ts +1 -1
- package/types/core/helpers/string/index.d.ts +3 -2
- package/types/core/helpers/utils/utils.d.ts +1 -1
- package/types/core/selection/select.d.ts +1 -1
- package/types/core/ui/button/button/button.d.ts +4 -4
- package/types/core/view/view.d.ts +1 -1
- package/types/jodit.d.ts +19 -6
- package/types/modules/{observer → history}/command.d.ts +4 -4
- package/types/modules/{observer/observer.d.ts → history/history.d.ts} +17 -9
- package/types/modules/{observer → history}/snapshot.d.ts +1 -1
- package/types/modules/{observer → history}/stack.d.ts +3 -3
- package/types/modules/image-editor/image-editor.d.ts +1 -1
- package/types/modules/index.d.ts +3 -3
- package/types/modules/toolbar/button/button.d.ts +2 -5
- package/types/modules/widget/tabs/tabs.d.ts +1 -1
- package/types/plugins/class-span/class-span.d.ts +1 -1
- package/types/plugins/clipboard/paste/config.d.ts +8 -0
- package/types/plugins/clipboard/paste/helpers.d.ts +2 -2
- package/types/plugins/clipboard/paste/interface.d.ts +5 -0
- package/types/plugins/clipboard/paste-from-word/config.d.ts +5 -0
- package/types/plugins/clipboard/paste-from-word/paste-from-word.d.ts +3 -2
- package/types/plugins/fix/clean-html/clean-html.d.ts +70 -0
- package/types/plugins/fix/{clean-html.d.ts → clean-html/config.d.ts} +2 -57
- package/types/plugins/fix/index.d.ts +10 -0
- package/types/plugins/fix/wrap-nodes/config.d.ts +16 -0
- package/types/plugins/fix/{wrap-text-nodes.d.ts → wrap-nodes/wrap-nodes.d.ts} +5 -2
- package/types/plugins/fullsize/fullsize.d.ts +2 -2
- package/types/plugins/index.d.ts +2 -2
- package/types/plugins/ordered-list/config.d.ts +6 -0
- package/types/plugins/ordered-list/ordered-list.d.ts +1 -1
- package/types/plugins/print/helpers.d.ts +2 -2
- package/types/plugins/print/index.d.ts +1 -1
- package/types/plugins/print/{preview.d.ts → preview/preview.d.ts} +1 -1
- package/types/plugins/search/config.d.ts +36 -0
- package/types/plugins/search/helpers/index.d.ts +10 -0
- package/types/plugins/search/helpers/sentence-finder.d.ts +21 -0
- package/types/plugins/search/helpers/wrap-ranges-texts-in-tmp-span.d.ts +14 -0
- package/types/plugins/search/search.d.ts +25 -39
- package/types/plugins/search/ui/search.d.ts +37 -0
- package/types/plugins/spellcheck/config.d.ts +15 -0
- package/types/plugins/spellcheck/spellcheck.d.ts +19 -0
- package/types/plugins/sticky/sticky.d.ts +2 -2
- package/types/types/async.d.ts +12 -2
- package/types/types/core.d.ts +1 -1
- package/types/types/core.ts +1 -1
- package/types/types/events.d.ts +6 -2
- package/types/types/file-browser.d.ts +1 -2
- package/{src/types/observer.d.ts → types/types/history.d.ts} +11 -7
- package/types/types/index.d.ts +1 -1
- package/types/types/jodit.d.ts +12 -4
- package/types/types/toolbar.d.ts +5 -5
- package/types/types/types.d.ts +11 -4
- package/src/modules/observer/README.md +0 -0
- package/src/plugins/search/search.less +0 -152
|
@@ -34,8 +34,9 @@ export function debounce<V = IViewComponent | IViewBased>(
|
|
|
34
34
|
return <T extends Component & IDictionary>(
|
|
35
35
|
target: IDictionary,
|
|
36
36
|
propertyKey: string
|
|
37
|
-
):
|
|
38
|
-
|
|
37
|
+
): PropertyDescriptor => {
|
|
38
|
+
const fn = target[propertyKey];
|
|
39
|
+
if (!isFunction(fn)) {
|
|
39
40
|
throw error('Handler must be a Function');
|
|
40
41
|
}
|
|
41
42
|
|
|
@@ -48,14 +49,24 @@ export function debounce<V = IViewComponent | IViewBased>(
|
|
|
48
49
|
? timeout(component)
|
|
49
50
|
: timeout;
|
|
50
51
|
|
|
51
|
-
(component
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
52
|
+
Object.defineProperty(component, propertyKey, {
|
|
53
|
+
configurable: true,
|
|
54
|
+
value: view.async[method](
|
|
55
|
+
(component as any)[propertyKey].bind(component),
|
|
56
|
+
isNumber(realTimeout) || isPlainObject(realTimeout)
|
|
57
|
+
? realTimeout
|
|
58
|
+
: view.defaultTimeout,
|
|
59
|
+
firstCallImmediately
|
|
60
|
+
)
|
|
61
|
+
});
|
|
58
62
|
});
|
|
63
|
+
|
|
64
|
+
return {
|
|
65
|
+
configurable: true,
|
|
66
|
+
get(): typeof fn {
|
|
67
|
+
return fn.bind(this);
|
|
68
|
+
}
|
|
69
|
+
};
|
|
59
70
|
};
|
|
60
71
|
}
|
|
61
72
|
|
|
@@ -1 +1,15 @@
|
|
|
1
1
|
Wrap function in [[Async.requestIdleCallback]] wrapper
|
|
2
|
+
|
|
3
|
+
```ts
|
|
4
|
+
import { component, idle } from 'jodit/src/core/decorators';
|
|
5
|
+
import { UIElement } from 'jodit/src/ui';
|
|
6
|
+
|
|
7
|
+
@component
|
|
8
|
+
class SomeClass extends UIElement {
|
|
9
|
+
@idle
|
|
10
|
+
runIdle(): void {
|
|
11
|
+
// Do some havy work
|
|
12
|
+
this.runIdle(); // This will work and won't go into stack depth error and break the main thread
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
```
|
|
@@ -35,7 +35,7 @@ export function idle<V = IViewComponent | IViewBased>(): DecoratorHandler {
|
|
|
35
35
|
|
|
36
36
|
const originalMethod = (component as any)[propertyKey];
|
|
37
37
|
|
|
38
|
-
(component as any)[propertyKey] = (...args: unknown[]) =>
|
|
38
|
+
(component as any)[propertyKey] = (...args: unknown[]): number =>
|
|
39
39
|
view.async.requestIdleCallback(
|
|
40
40
|
originalMethod.bind(component, ...args)
|
|
41
41
|
);
|
|
@@ -56,7 +56,7 @@ export function watch(
|
|
|
56
56
|
throw error('Handler must be a Function');
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
const process = (component: IComponent) => {
|
|
59
|
+
const process = (component: IComponent): void => {
|
|
60
60
|
const callback = (key: string, ...args: any[]): void | any => {
|
|
61
61
|
if (!component.isInDestruct) {
|
|
62
62
|
return (component as any)[propertyKey](key, ...args);
|
|
@@ -66,6 +66,7 @@ export function watch(
|
|
|
66
66
|
splitArray(observeFields).forEach(field => {
|
|
67
67
|
if (/:/.test(field)) {
|
|
68
68
|
const [objectPath, eventName] = field.split(':');
|
|
69
|
+
let ctx = context;
|
|
69
70
|
|
|
70
71
|
const view = isViewObject(component)
|
|
71
72
|
? component
|
|
@@ -73,22 +74,22 @@ export function watch(
|
|
|
73
74
|
|
|
74
75
|
if (objectPath.length) {
|
|
75
76
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
76
|
-
|
|
77
|
+
ctx = component.get<CanUndef<object>>(objectPath)!;
|
|
77
78
|
}
|
|
78
79
|
|
|
79
|
-
if (isFunction(
|
|
80
|
-
|
|
80
|
+
if (isFunction(ctx)) {
|
|
81
|
+
ctx = ctx(component);
|
|
81
82
|
}
|
|
82
83
|
|
|
83
|
-
view.events.on(
|
|
84
|
+
view.events.on(ctx || component, eventName, callback);
|
|
84
85
|
|
|
85
|
-
if (!
|
|
86
|
+
if (!ctx) {
|
|
86
87
|
view.events.on(eventName, callback);
|
|
87
88
|
}
|
|
88
89
|
|
|
89
90
|
view.hookStatus('beforeDestruct', () => {
|
|
90
91
|
view.events
|
|
91
|
-
.off(
|
|
92
|
+
.off(ctx || component, eventName, callback)
|
|
92
93
|
.off(eventName, callback);
|
|
93
94
|
});
|
|
94
95
|
|
package/src/core/dom/README.md
CHANGED
|
@@ -13,3 +13,45 @@ Dom.before(elm, div);
|
|
|
13
13
|
The rest of the methods can be found in the [[Dom | documentation]]
|
|
14
14
|
|
|
15
15
|
> All module methods are static. So you don't need an instance to use them.
|
|
16
|
+
|
|
17
|
+
The module also includes the [[LazyWalker]] class. It is convenient for cases when it is necessary to go through
|
|
18
|
+
the entire tree of elements, but this must be done without stopping the main thread of execution.
|
|
19
|
+
For example, your plugin can search for some nodes, or text. If each time you run through the entire tree in a loop,
|
|
20
|
+
then the interface will noticeably slow down on large documents. To avoid this, this class is made.
|
|
21
|
+
|
|
22
|
+
```js
|
|
23
|
+
const walker = new Jodit.modules.LazyWalker(new Jodit.modules.Async(), 100);
|
|
24
|
+
const names = [];
|
|
25
|
+
|
|
26
|
+
walker
|
|
27
|
+
.on('visit', node => {
|
|
28
|
+
names.push(node.nodeName.toLowerCase());
|
|
29
|
+
})
|
|
30
|
+
.on('end', () => {
|
|
31
|
+
expect(names).deep.eq([
|
|
32
|
+
'div',
|
|
33
|
+
'ul',
|
|
34
|
+
'li',
|
|
35
|
+
'strong',
|
|
36
|
+
'#text',
|
|
37
|
+
'span',
|
|
38
|
+
'#text',
|
|
39
|
+
'u',
|
|
40
|
+
'#text',
|
|
41
|
+
'li',
|
|
42
|
+
'i',
|
|
43
|
+
'#text',
|
|
44
|
+
'b',
|
|
45
|
+
'#text',
|
|
46
|
+
'u',
|
|
47
|
+
'#text',
|
|
48
|
+
'img'
|
|
49
|
+
]);
|
|
50
|
+
done();
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
const div = document.createElement('div');
|
|
54
|
+
div.innerHTML =
|
|
55
|
+
"<ul><li><strong>test</strong><span>test</span><u>test</u></li><li><i>test</i><b>test</b><u>test</u><img src='' alt=''></li></ul>";
|
|
56
|
+
walker.setWork(div);
|
|
57
|
+
```
|
package/src/core/dom/dom.ts
CHANGED
|
@@ -111,29 +111,40 @@ export class Dom {
|
|
|
111
111
|
return wrapper as HTMLElement;
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
-
/**
|
|
115
|
-
* Wrap node inside another node
|
|
116
|
-
*/
|
|
117
114
|
static wrap<K extends HTMLTagNames>(
|
|
118
|
-
current: Node,
|
|
115
|
+
current: Node | Range,
|
|
116
|
+
tag: HTMLElement,
|
|
117
|
+
create: ICreate
|
|
118
|
+
): HTMLElementTagNameMap[K];
|
|
119
|
+
|
|
120
|
+
static wrap<K extends HTMLTagNames>(
|
|
121
|
+
current: Node | Range,
|
|
119
122
|
tag: K,
|
|
120
123
|
create: ICreate
|
|
121
124
|
): HTMLElementTagNameMap[K];
|
|
122
125
|
|
|
126
|
+
/**
|
|
127
|
+
* Wrap node inside another node
|
|
128
|
+
*/
|
|
123
129
|
static wrap(
|
|
124
|
-
current: Node,
|
|
130
|
+
current: Node | Range,
|
|
125
131
|
tag: HTMLElement | HTMLTagNames,
|
|
126
132
|
create: ICreate
|
|
127
133
|
): HTMLElement {
|
|
128
134
|
const wrapper = isString(tag) ? create.element(tag) : tag;
|
|
129
135
|
|
|
130
|
-
if (
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
current.parentNode.insertBefore(wrapper, current);
|
|
136
|
+
if (Dom.isNode(current)) {
|
|
137
|
+
if (!current.parentNode) {
|
|
138
|
+
throw error('Element should be in DOM');
|
|
139
|
+
}
|
|
135
140
|
|
|
136
|
-
|
|
141
|
+
current.parentNode.insertBefore(wrapper, current);
|
|
142
|
+
wrapper.appendChild(current);
|
|
143
|
+
} else {
|
|
144
|
+
const fragment = current.extractContents();
|
|
145
|
+
current.insertNode(wrapper);
|
|
146
|
+
wrapper.appendChild(fragment);
|
|
147
|
+
}
|
|
137
148
|
|
|
138
149
|
return wrapper;
|
|
139
150
|
}
|
|
@@ -597,10 +608,6 @@ export class Dom {
|
|
|
597
608
|
while (stack.length) {
|
|
598
609
|
const item = <Node>stack.pop();
|
|
599
610
|
|
|
600
|
-
if (start !== item) {
|
|
601
|
-
yield item;
|
|
602
|
-
}
|
|
603
|
-
|
|
604
611
|
if (withChild) {
|
|
605
612
|
let child = leftToRight ? item.lastChild : item.firstChild;
|
|
606
613
|
|
|
@@ -611,6 +618,10 @@ export class Dom {
|
|
|
611
618
|
: child.nextSibling;
|
|
612
619
|
}
|
|
613
620
|
}
|
|
621
|
+
|
|
622
|
+
if (start !== item) {
|
|
623
|
+
yield item;
|
|
624
|
+
}
|
|
614
625
|
}
|
|
615
626
|
}
|
|
616
627
|
|
|
@@ -663,7 +674,8 @@ export class Dom {
|
|
|
663
674
|
static findSibling(
|
|
664
675
|
node: Node,
|
|
665
676
|
left: boolean = true,
|
|
666
|
-
cond: (n: Node) => boolean = (n: Node) =>
|
|
677
|
+
cond: (n: Node) => boolean = (n: Node): boolean =>
|
|
678
|
+
!Dom.isEmptyTextNode(n)
|
|
667
679
|
): Nullable<Node> {
|
|
668
680
|
let sibling = Dom.sibling(node, left);
|
|
669
681
|
|
|
@@ -674,7 +686,7 @@ export class Dom {
|
|
|
674
686
|
return sibling && cond(sibling) ? sibling : null;
|
|
675
687
|
}
|
|
676
688
|
|
|
677
|
-
static sibling(node: Node, left
|
|
689
|
+
static sibling(node: Node, left?: boolean): Nullable<Node> {
|
|
678
690
|
return left ? node.previousSibling : node.nextSibling;
|
|
679
691
|
}
|
|
680
692
|
|
|
@@ -746,14 +758,16 @@ export class Dom {
|
|
|
746
758
|
if (isFunction(tagsOrCondition)) {
|
|
747
759
|
condition = tagsOrCondition;
|
|
748
760
|
} else if (isArray(tagsOrCondition)) {
|
|
749
|
-
condition = (tag: Node | null) =>
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
761
|
+
condition = (tag: Node | null): boolean =>
|
|
762
|
+
Boolean(
|
|
763
|
+
tag &&
|
|
764
|
+
tagsOrCondition.includes(
|
|
765
|
+
tag.nodeName.toLowerCase() as HTMLTagNames
|
|
766
|
+
)
|
|
753
767
|
);
|
|
754
768
|
} else {
|
|
755
|
-
condition = (tag: Node | null) =>
|
|
756
|
-
tag && tagsOrCondition === tag.nodeName.toLowerCase();
|
|
769
|
+
condition = (tag: Node | null): boolean =>
|
|
770
|
+
Boolean(tag && tagsOrCondition === tag.nodeName.toLowerCase());
|
|
757
771
|
}
|
|
758
772
|
|
|
759
773
|
return Dom.up(node, condition, root);
|
package/src/core/dom/index.ts
CHANGED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Jodit Editor (https://xdsoft.net/jodit/)
|
|
3
|
+
* Released under MIT see LICENSE.txt in the project root for license information.
|
|
4
|
+
* Copyright (c) 2013-2022 Valeriy Chupurnov. All rights reserved. https://xdsoft.net
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @module dom
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type { IAsync, IDestructible } from 'jodit/types';
|
|
12
|
+
import type { Nullable, CanUndef } from 'jodit/types';
|
|
13
|
+
import { Eventify } from 'jodit/core/event-emitter/eventify';
|
|
14
|
+
import { autobind } from 'jodit/core/decorators';
|
|
15
|
+
import { Dom } from 'jodit/core/dom/dom';
|
|
16
|
+
|
|
17
|
+
export class LazyWalker
|
|
18
|
+
extends Eventify<{
|
|
19
|
+
visit: (node: Node) => boolean;
|
|
20
|
+
break: (reason?: string) => void;
|
|
21
|
+
end: (affect: boolean) => void;
|
|
22
|
+
}>
|
|
23
|
+
implements IDestructible
|
|
24
|
+
{
|
|
25
|
+
private workNodes: Nullable<Generator<Node>> = null;
|
|
26
|
+
|
|
27
|
+
setWork(root: Node): this {
|
|
28
|
+
if (this.isWorked) {
|
|
29
|
+
this.break();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
this.workNodes = Dom.eachGen(root, !this.options.reverse);
|
|
33
|
+
|
|
34
|
+
this.isFinished = false;
|
|
35
|
+
this.startIdleRequest();
|
|
36
|
+
return this;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
private hadAffect: boolean = false;
|
|
40
|
+
private isWorked: boolean = false;
|
|
41
|
+
private isFinished: boolean = false;
|
|
42
|
+
|
|
43
|
+
constructor(
|
|
44
|
+
private readonly async: IAsync,
|
|
45
|
+
private readonly options: {
|
|
46
|
+
readonly timeout?: number;
|
|
47
|
+
readonly whatToShow?: number;
|
|
48
|
+
readonly reverse?: boolean;
|
|
49
|
+
readonly timeoutChunkSize?: number;
|
|
50
|
+
} = {}
|
|
51
|
+
) {
|
|
52
|
+
super();
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
private idleId: number = 0;
|
|
56
|
+
|
|
57
|
+
private startIdleRequest(): void {
|
|
58
|
+
this.idleId = this.async.requestIdleCallback(this.workPerform, {
|
|
59
|
+
timeout: this.options.timeout ?? 10
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
break(reason?: string): void {
|
|
64
|
+
if (this.isWorked) {
|
|
65
|
+
this.stop();
|
|
66
|
+
this.emit('break', reason);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
end(): void {
|
|
71
|
+
if (this.isWorked) {
|
|
72
|
+
this.stop();
|
|
73
|
+
this.emit('end', this.hadAffect);
|
|
74
|
+
this.hadAffect = false;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
private stop(): void {
|
|
79
|
+
this.isWorked = false;
|
|
80
|
+
this.isFinished = true;
|
|
81
|
+
this.workNodes = null;
|
|
82
|
+
this.async.cancelIdleCallback(this.idleId);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
destruct(): void {
|
|
86
|
+
this.stop();
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
@autobind
|
|
90
|
+
private workPerform(deadline: IdleDeadline): void {
|
|
91
|
+
if (this.workNodes) {
|
|
92
|
+
this.isWorked = true;
|
|
93
|
+
|
|
94
|
+
let count = 0;
|
|
95
|
+
const chunkSize = this.options.timeoutChunkSize ?? 50;
|
|
96
|
+
|
|
97
|
+
while (
|
|
98
|
+
!this.isFinished &&
|
|
99
|
+
(deadline.timeRemaining() > 0 ||
|
|
100
|
+
(deadline.didTimeout && count <= chunkSize))
|
|
101
|
+
) {
|
|
102
|
+
const item = this.workNodes.next();
|
|
103
|
+
count += 1;
|
|
104
|
+
if (this.visitNode(item.value)) {
|
|
105
|
+
this.hadAffect = true;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (item.done) {
|
|
109
|
+
this.end();
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
} else {
|
|
114
|
+
this.end();
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (!this.isFinished) {
|
|
118
|
+
this.startIdleRequest();
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
private visitNode(nodeElm: CanUndef<Nullable<Element | Node>>): boolean {
|
|
123
|
+
if (
|
|
124
|
+
!nodeElm ||
|
|
125
|
+
(this.options.whatToShow !== undefined &&
|
|
126
|
+
nodeElm.nodeType !== this.options.whatToShow)
|
|
127
|
+
) {
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return this.emit('visit', nodeElm) ?? false;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
@@ -52,7 +52,7 @@ export class EventEmitter implements IEventEmitter {
|
|
|
52
52
|
private eachEvent(
|
|
53
53
|
events: string,
|
|
54
54
|
callback: (event: string, namespace: string) => void
|
|
55
|
-
) {
|
|
55
|
+
): void {
|
|
56
56
|
const eventParts: string[] = events.split(/[\s,]+/);
|
|
57
57
|
|
|
58
58
|
eventParts.forEach((eventNameSpace: string) => {
|
|
@@ -82,7 +82,7 @@ export class EventEmitter implements IEventEmitter {
|
|
|
82
82
|
return subject[this.__key];
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
private clearStore(subject: any) {
|
|
85
|
+
private clearStore(subject: any): void {
|
|
86
86
|
if (subject[this.__key] !== undefined) {
|
|
87
87
|
delete subject[this.__key];
|
|
88
88
|
}
|
|
@@ -90,7 +90,7 @@ export class EventEmitter implements IEventEmitter {
|
|
|
90
90
|
|
|
91
91
|
private prepareEvent = (
|
|
92
92
|
event: TouchEvent | MouseEvent | ClipboardEvent
|
|
93
|
-
) => {
|
|
93
|
+
): void => {
|
|
94
94
|
if (event.cancelBubble) {
|
|
95
95
|
return;
|
|
96
96
|
}
|
|
@@ -133,7 +133,7 @@ export class EventEmitter implements IEventEmitter {
|
|
|
133
133
|
private triggerNativeEvent(
|
|
134
134
|
element: Document | Element | HTMLElement | Window,
|
|
135
135
|
event: string | Event | MouseEvent
|
|
136
|
-
) {
|
|
136
|
+
): void {
|
|
137
137
|
const evt: Event = this.doc.createEvent('HTMLEvents');
|
|
138
138
|
|
|
139
139
|
if (typeof event === 'string') {
|
|
@@ -365,7 +365,7 @@ export class EventEmitter implements IEventEmitter {
|
|
|
365
365
|
callback = eventsOrCallback as CallbackFunction;
|
|
366
366
|
}
|
|
367
367
|
|
|
368
|
-
const newCallback = (...args: any) => {
|
|
368
|
+
const newCallback = (...args: any): void => {
|
|
369
369
|
this.off(subject, events, newCallback);
|
|
370
370
|
return callback(...args);
|
|
371
371
|
};
|
|
@@ -439,7 +439,7 @@ export class EventEmitter implements IEventEmitter {
|
|
|
439
439
|
}
|
|
440
440
|
|
|
441
441
|
const isDOMElement = isFunction((subject as any).removeEventListener),
|
|
442
|
-
removeEventListener = (block: EventHandlerBlock) => {
|
|
442
|
+
removeEventListener = (block: EventHandlerBlock): void => {
|
|
443
443
|
if (isDOMElement) {
|
|
444
444
|
(subject as HTMLElement).removeEventListener(
|
|
445
445
|
block.event,
|
|
@@ -451,7 +451,7 @@ export class EventEmitter implements IEventEmitter {
|
|
|
451
451
|
removeCallbackFromNameSpace = (
|
|
452
452
|
event: string,
|
|
453
453
|
namespace: string
|
|
454
|
-
) => {
|
|
454
|
+
): void => {
|
|
455
455
|
if (event !== '') {
|
|
456
456
|
const blocks: EventHandlerBlock[] | void = store.get(
|
|
457
457
|
event,
|
|
@@ -540,7 +540,7 @@ export class EventEmitter implements IEventEmitter {
|
|
|
540
540
|
|
|
541
541
|
private __stopped: EventHandlerBlock[][] = [];
|
|
542
542
|
|
|
543
|
-
private removeStop(currentBlocks: EventHandlerBlock[]) {
|
|
543
|
+
private removeStop(currentBlocks: EventHandlerBlock[]): void {
|
|
544
544
|
if (currentBlocks) {
|
|
545
545
|
const index: number = this.__stopped.indexOf(currentBlocks);
|
|
546
546
|
index !== -1 && this.__stopped.splice(0, index + 1);
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Jodit Editor (https://xdsoft.net/jodit/)
|
|
3
|
+
* Released under MIT see LICENSE.txt in the project root for license information.
|
|
4
|
+
* Copyright (c) 2013-2022 Valeriy Chupurnov. All rights reserved. https://xdsoft.net
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @module event-emitter
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type { CanUndef } from 'jodit/types';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Class for adding event handling capability
|
|
15
|
+
*
|
|
16
|
+
* ```ts
|
|
17
|
+
* class SomeClass extends Eventify<{ start: (node: Node) => boolean; }> {
|
|
18
|
+
* constructor() {
|
|
19
|
+
* super();
|
|
20
|
+
* setTimeout(() => {
|
|
21
|
+
* if (this.emit('start', document.body)) {
|
|
22
|
+
* console.log('yes');
|
|
23
|
+
* };
|
|
24
|
+
* }, 100);
|
|
25
|
+
* }
|
|
26
|
+
* }
|
|
27
|
+
*
|
|
28
|
+
* const sm = new SomeClass();
|
|
29
|
+
* sm.on('start', (node) => {
|
|
30
|
+
* console.log(node);
|
|
31
|
+
* return true;
|
|
32
|
+
* })
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export abstract class Eventify<
|
|
36
|
+
MAP extends { [key: string]: (...args: any[]) => any },
|
|
37
|
+
EVENT extends keyof MAP = keyof MAP
|
|
38
|
+
> {
|
|
39
|
+
private map: Map<keyof MAP, Set<Function>> = new Map();
|
|
40
|
+
|
|
41
|
+
on(name: EVENT, func: MAP[EVENT]): this {
|
|
42
|
+
if (!this.map.has(name)) {
|
|
43
|
+
this.map.set(name, new Set());
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
this.map.get(name)?.add(func);
|
|
47
|
+
|
|
48
|
+
return this;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
off(name: keyof MAP, func: MAP[EVENT]): this {
|
|
52
|
+
if (this.map.has(name)) {
|
|
53
|
+
this.map.get(name)?.delete(func);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return this;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
protected emit(
|
|
60
|
+
name: EVENT,
|
|
61
|
+
...args: Parameters<MAP[EVENT]>
|
|
62
|
+
): CanUndef<ReturnType<MAP[EVENT]>> {
|
|
63
|
+
let result: CanUndef<ReturnType<MAP[EVENT]>>;
|
|
64
|
+
|
|
65
|
+
if (this.map.has(name)) {
|
|
66
|
+
this.map.get(name)?.forEach(cb => {
|
|
67
|
+
result = cb(...args);
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return result;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -12,7 +12,7 @@ import { Dom } from 'jodit/core/dom';
|
|
|
12
12
|
import { $$ } from 'jodit/core/helpers/utils';
|
|
13
13
|
import { trim } from '../string';
|
|
14
14
|
|
|
15
|
-
function normalizeCSS(s: string) {
|
|
15
|
+
function normalizeCSS(s: string): string {
|
|
16
16
|
return s
|
|
17
17
|
.replace(/mso-[a-z-]+:[\s]*[^;]+;/gi, '')
|
|
18
18
|
.replace(/mso-[a-z-]+:[\s]*[^";']+$/gi, '')
|
|
@@ -63,8 +63,9 @@ export function safeHTML(
|
|
|
63
63
|
return;
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
const removeOnError = (elm: HTMLElement) =>
|
|
67
|
-
|
|
66
|
+
const removeOnError = (elm: HTMLElement): void =>
|
|
67
|
+
attr(elm, 'onerror', null),
|
|
68
|
+
safeLink = (elm: HTMLElement): void => {
|
|
68
69
|
const href = elm.getAttribute('href');
|
|
69
70
|
|
|
70
71
|
if (href && href.trim().indexOf('javascript') === 0) {
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Jodit Editor (https://xdsoft.net/jodit/)
|
|
3
|
+
* Released under MIT see LICENSE.txt in the project root for license information.
|
|
4
|
+
* Copyright (c) 2013-2022 Valeriy Chupurnov. All rights reserved. https://xdsoft.net
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @module helpers/string
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { INVISIBLE_SPACE } from 'jodit/core/constants';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Finds the position of the substring in the string, if any, and returns the length of the found subsequence.
|
|
15
|
+
* Unlike `indexOf` ignores INVISIBLE_SPACE and may fail at `maxDistance` characters
|
|
16
|
+
*/
|
|
17
|
+
export function fuzzySearchIndex(
|
|
18
|
+
needle: string,
|
|
19
|
+
haystack: string,
|
|
20
|
+
offset: number = 0,
|
|
21
|
+
maxDistance: number = 1
|
|
22
|
+
): [number, number] {
|
|
23
|
+
let i = 0,
|
|
24
|
+
j = 0,
|
|
25
|
+
startIndex = -1,
|
|
26
|
+
len = 0,
|
|
27
|
+
errorDistance = 0;
|
|
28
|
+
|
|
29
|
+
for (j = offset; i < needle.length && j < haystack.length; ) {
|
|
30
|
+
if (needle[i].toLowerCase() === haystack[j].toLowerCase()) {
|
|
31
|
+
i++;
|
|
32
|
+
len++;
|
|
33
|
+
errorDistance = 0;
|
|
34
|
+
|
|
35
|
+
if (startIndex === -1) {
|
|
36
|
+
startIndex = j;
|
|
37
|
+
}
|
|
38
|
+
} else if (i > 0) {
|
|
39
|
+
if (
|
|
40
|
+
errorDistance >= maxDistance &&
|
|
41
|
+
haystack[j] !== INVISIBLE_SPACE
|
|
42
|
+
) {
|
|
43
|
+
i = 0;
|
|
44
|
+
startIndex = -1;
|
|
45
|
+
len = 0;
|
|
46
|
+
errorDistance = 0;
|
|
47
|
+
j--;
|
|
48
|
+
} else {
|
|
49
|
+
errorDistance++;
|
|
50
|
+
len++;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
j++;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return i === needle.length ? [startIndex, len] : [-1, 0];
|
|
58
|
+
}
|
|
@@ -46,7 +46,7 @@ export const sprintf = (str: string, args?: Array<string | number>): string => {
|
|
|
46
46
|
* Internationalization method. Uses Jodit.lang object
|
|
47
47
|
* @example
|
|
48
48
|
* ```javascript
|
|
49
|
-
* var editor =
|
|
49
|
+
* var editor = Jodit.make("#redactor", {
|
|
50
50
|
* language: 'ru'
|
|
51
51
|
* });
|
|
52
52
|
* console.log(editor.i18n('Cancel')) //Отмена;
|
|
@@ -9,8 +9,9 @@
|
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
export * from './camel-case';
|
|
12
|
-
export * from './
|
|
12
|
+
export * from './fuzzy-search-index';
|
|
13
|
+
export * from './i18n';
|
|
13
14
|
export * from './kebab-case';
|
|
15
|
+
export * from './stringify';
|
|
14
16
|
export * from './trim';
|
|
15
17
|
export * from './ucfirst';
|
|
16
|
-
export * from './i18n';
|
|
@@ -88,7 +88,7 @@ export const appendStyleAsync = cacheLoaders(
|
|
|
88
88
|
link.media = 'all';
|
|
89
89
|
link.crossOrigin = 'anonymous';
|
|
90
90
|
|
|
91
|
-
const callback = () => resolve(link);
|
|
91
|
+
const callback = (): void => resolve(link);
|
|
92
92
|
|
|
93
93
|
!jodit.isInDestruct &&
|
|
94
94
|
jodit.e.on(link, 'load', callback).on(link, 'error', reject);
|