-
Notifications
You must be signed in to change notification settings - Fork 166
Expand file tree
/
Copy pathUtils.ts
More file actions
124 lines (100 loc) · 4.2 KB
/
Copy pathUtils.ts
File metadata and controls
124 lines (100 loc) · 4.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
import { eventPropTypes, IEventPropTypes } from './components/EditorPropTypes';
import { IAllProps } from './components/Editor';
import type { Editor as TinyMCEEditor, EditorEvent } from 'tinymce';
import { getTinymce } from './TinyMCE';
export const isFunction = (x: unknown): x is Function => typeof x === 'function';
const isEventProp = (name: string): name is keyof IEventPropTypes => name in eventPropTypes;
const eventAttrToEventName = <T extends string>(attrName: `on${T}`): T => attrName.substr(2) as T;
type PropLookup = <K extends keyof IAllProps>(key: K) => IAllProps[K] | undefined;
export const configHandlers2 = <H> (
handlerLookup: PropLookup,
on: (name: string, handler: H) => void,
off: (name: string, handler: H) => void,
adapter: <K extends keyof IEventPropTypes> (lookup: PropLookup, key: K) => H,
prevProps: Partial<IAllProps>,
props: Partial<IAllProps>,
boundHandlers: Record<string, H>
): void => {
const prevEventKeys = Object.keys(prevProps).filter(isEventProp);
const currEventKeys = Object.keys(props).filter(isEventProp);
const removedKeys = prevEventKeys.filter((key) => props[key] === undefined);
const addedKeys = currEventKeys.filter((key) => prevProps[key] === undefined);
removedKeys.forEach((key) => {
// remove event handler
const eventName = eventAttrToEventName(key);
const wrappedHandler = boundHandlers[eventName];
off(eventName, wrappedHandler);
delete boundHandlers[eventName];
});
addedKeys.forEach((key) => {
const wrappedHandler = adapter(handlerLookup, key);
const eventName = eventAttrToEventName(key);
boundHandlers[eventName] = wrappedHandler;
on(eventName, wrappedHandler);
});
};
export const configHandlers = (
editor: TinyMCEEditor,
prevProps: Partial<IAllProps>,
props: Partial<IAllProps>,
boundHandlers: Record<string, (event: EditorEvent<any>) => unknown>,
lookup: PropLookup
): void =>
configHandlers2(
lookup,
editor.on.bind(editor),
editor.off.bind(editor),
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
(handlerLookup, key) => (e) => handlerLookup(key)?.(e, editor),
prevProps,
props,
boundHandlers
);
let unique = 0;
export const uuid = (prefix: string): string => {
const time = Date.now();
const random = Math.floor(Math.random() * 1000000000);
unique++;
return prefix + '_' + random + unique + String(time);
};
export const isTextareaOrInput = (element: Element | null): element is (HTMLTextAreaElement | HTMLInputElement) =>
element !== null && (element.tagName.toLowerCase() === 'textarea' || element.tagName.toLowerCase() === 'input');
const normalizePluginArray = (plugins?: string | string[]): string[] => {
if (typeof plugins === 'undefined' || plugins === '') {
return [];
}
return Array.isArray(plugins) ? plugins : plugins.split(' ');
};
// eslint-disable-next-line max-len
export const mergePlugins = (initPlugins: string | string[] | undefined, inputPlugins: string | string[] | undefined): string[] => normalizePluginArray(initPlugins).concat(normalizePluginArray(inputPlugins));
export const isBeforeInputEventAvailable = () => window.InputEvent && typeof (InputEvent.prototype as any).getTargetRanges === 'function';
export const isInDoc = (elem: Node) => {
if (!('isConnected' in Node.prototype)) {
// Fallback for IE and old Edge
let current = elem;
let parent = elem.parentNode;
while (parent != null) {
current = parent;
parent = current.parentNode;
}
return current === elem.ownerDocument;
}
return elem.isConnected;
};
export const setMode = (editor: TinyMCEEditor | undefined, mode: 'readonly' | 'design') => {
if (editor !== undefined) {
if (editor.mode != null && typeof editor.mode === 'object' && typeof editor.mode.set === 'function') {
editor.mode.set(mode);
} else { // support TinyMCE 4
(editor as any).setMode(mode);
}
}
};
export const getTinymceOrError = (view: Window) => {
const tinymce = getTinymce(view);
if (!tinymce) {
throw new Error('tinymce should have been loaded into global scope');
}
return tinymce;
};
export const isDisabledOptionSupported = (editor: TinyMCEEditor) => editor.options && editor.options.isRegistered('disabled');