@slickgrid-universal/utils 4.1.0 → 4.3.0
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/dist/cjs/domUtils.js +35 -8
- package/dist/cjs/domUtils.js.map +1 -1
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/{types → models}/index.js +2 -2
- package/dist/cjs/models/index.js.map +1 -0
- package/dist/cjs/{types/htmlElementPosition.interface.js → models/interfaces.js} +1 -1
- package/dist/cjs/models/interfaces.js.map +1 -0
- package/dist/cjs/models/types.js +3 -0
- package/dist/cjs/models/types.js.map +1 -0
- package/dist/cjs/nodeExtend.js.map +1 -1
- package/dist/cjs/stripTagsUtil.js +6 -5
- package/dist/cjs/stripTagsUtil.js.map +1 -1
- package/dist/cjs/utils.js +52 -40
- package/dist/cjs/utils.js.map +1 -1
- package/dist/esm/domUtils.js +31 -6
- package/dist/esm/domUtils.js.map +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/models/index.js +3 -0
- package/dist/esm/models/index.js.map +1 -0
- package/dist/esm/models/interfaces.js +2 -0
- package/dist/esm/models/interfaces.js.map +1 -0
- package/dist/esm/models/types.js +2 -0
- package/dist/esm/models/types.js.map +1 -0
- package/dist/esm/nodeExtend.js.map +1 -1
- package/dist/esm/stripTagsUtil.js +6 -5
- package/dist/esm/stripTagsUtil.js.map +1 -1
- package/dist/esm/utils.js +49 -38
- package/dist/esm/utils.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/domUtils.d.ts +20 -3
- package/dist/types/domUtils.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/models/index.d.ts +3 -0
- package/dist/types/models/index.d.ts.map +1 -0
- package/dist/types/{types/htmlElementPosition.interface.d.ts → models/interfaces.d.ts} +1 -1
- package/dist/types/models/interfaces.d.ts.map +1 -0
- package/dist/types/{types/infer.type.d.ts → models/types.d.ts} +2 -1
- package/dist/types/models/types.d.ts.map +1 -0
- package/dist/types/stripTagsUtil.d.ts +6 -5
- package/dist/types/stripTagsUtil.d.ts.map +1 -1
- package/dist/types/utils.d.ts +14 -12
- package/dist/types/utils.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/domUtils.ts +33 -7
- package/src/index.ts +1 -1
- package/src/models/index.ts +2 -0
- package/src/{types/infer.type.ts → models/types.ts} +2 -0
- package/src/nodeExtend.ts +1 -1
- package/src/stripTagsUtil.ts +6 -5
- package/src/utils.ts +60 -41
- package/dist/cjs/types/htmlElementPosition.interface.js.map +0 -1
- package/dist/cjs/types/index.js.map +0 -1
- package/dist/cjs/types/infer.type.js +0 -4
- package/dist/cjs/types/infer.type.js.map +0 -1
- package/dist/esm/types/htmlElementPosition.interface.js +0 -2
- package/dist/esm/types/htmlElementPosition.interface.js.map +0 -1
- package/dist/esm/types/index.js +0 -3
- package/dist/esm/types/index.js.map +0 -1
- package/dist/esm/types/infer.type.js +0 -3
- package/dist/esm/types/infer.type.js.map +0 -1
- package/dist/types/types/htmlElementPosition.interface.d.ts.map +0 -1
- package/dist/types/types/index.d.ts +0 -3
- package/dist/types/types/index.d.ts.map +0 -1
- package/dist/types/types/infer.type.d.ts.map +0 -1
- package/src/types/index.ts +0 -2
- /package/src/{types/htmlElementPosition.interface.ts → models/interfaces.ts} +0 -0
package/src/domUtils.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { HtmlElementPosition, InferDOMType } from './
|
|
1
|
+
import type { HtmlElementPosition, InferDOMType } from './models/index';
|
|
2
2
|
|
|
3
3
|
/** calculate available space for each side of the DOM element */
|
|
4
4
|
export function calculateAvailableSpace(element: HTMLElement): { top: number; bottom: number; left: number; right: number; } {
|
|
@@ -63,21 +63,32 @@ export function createDomElement<T extends keyof HTMLElementTagNameMap, K extend
|
|
|
63
63
|
return elm;
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
+
/**
|
|
67
|
+
* Accepts string containing the class or space-separated list of classes, and
|
|
68
|
+
* returns list of individual classes.
|
|
69
|
+
* Method properly takes into account extra whitespaces in the `className`
|
|
70
|
+
* e.g.: " class1 class2 " => will result in `['class1', 'class2']`.
|
|
71
|
+
* @param {String} className - space separated list of class names
|
|
72
|
+
*/
|
|
73
|
+
export function classNameToList(className = ''): string[] {
|
|
74
|
+
return className.split(' ').filter(cls => cls); // filter will remove whitespace entries
|
|
75
|
+
}
|
|
76
|
+
|
|
66
77
|
/**
|
|
67
78
|
* Loop through all properties of an object and nullify any properties that are instanceof HTMLElement,
|
|
68
79
|
* if we detect an array then use recursion to go inside it and apply same logic
|
|
69
80
|
* @param obj - object containing 1 or more properties with DOM Elements
|
|
70
81
|
*/
|
|
71
82
|
export function destroyAllElementProps(obj: any) {
|
|
72
|
-
if (obj) {
|
|
73
|
-
|
|
83
|
+
if (typeof obj === 'object') {
|
|
84
|
+
Object.keys(obj).forEach(key => {
|
|
74
85
|
if (Array.isArray(obj[key])) {
|
|
75
86
|
destroyAllElementProps(obj[key]);
|
|
76
87
|
}
|
|
77
88
|
if (obj[key] instanceof HTMLElement) {
|
|
78
89
|
obj[key] = null;
|
|
79
90
|
}
|
|
80
|
-
}
|
|
91
|
+
});
|
|
81
92
|
}
|
|
82
93
|
}
|
|
83
94
|
|
|
@@ -93,14 +104,29 @@ export function emptyElement<T extends Element = Element>(element?: T | null): T
|
|
|
93
104
|
}
|
|
94
105
|
|
|
95
106
|
/**
|
|
96
|
-
*
|
|
107
|
+
* @deprecated @see `getHtmlStringOutput()`
|
|
108
|
+
* This function is now deprecated and is an alias to the new `getHtmlStringOutput()`, so please use this new function instead which works with various type of inputs.
|
|
109
|
+
*/
|
|
110
|
+
export function getHTMLFromFragment(input: DocumentFragment | HTMLElement | string | number, type: 'innerHTML' | 'outerHTML' = 'innerHTML'): string {
|
|
111
|
+
return getHtmlStringOutput(input, type);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* From any input provided, return the HTML string (when a string is provided, it will be returned "as is" but when it's a number it will be converted to string)
|
|
116
|
+
* When detecting HTMLElement/DocumentFragment, we can also specify which HTML type to retrieve innerHTML or outerHTML.
|
|
97
117
|
* We can get the HTML by looping through all fragment `childNodes`
|
|
118
|
+
* @param {DocumentFragment | HTMLElement | string | number} input
|
|
119
|
+
* @param {'innerHTML' | 'outerHTML'} [type] - when the input is a DocumentFragment or HTMLElement, which type of HTML do you want to return? 'innerHTML' or 'outerHTML'
|
|
120
|
+
* @returns {String}
|
|
98
121
|
*/
|
|
99
|
-
export function
|
|
122
|
+
export function getHtmlStringOutput(input: DocumentFragment | HTMLElement | string | number, type: 'innerHTML' | 'outerHTML' = 'innerHTML'): string {
|
|
100
123
|
if (input instanceof DocumentFragment) {
|
|
124
|
+
// a DocumentFragment doesn't have innerHTML/outerHTML, but we can loop through all children and concatenate them all to an HTML string
|
|
101
125
|
return [].map.call(input.childNodes, (x: HTMLElement) => x[type]).join('') || input.textContent || '';
|
|
126
|
+
} else if (input instanceof HTMLElement) {
|
|
127
|
+
return input[type];
|
|
102
128
|
}
|
|
103
|
-
return input;
|
|
129
|
+
return String(input ?? ''); // reaching this line means it's already a string (or number) so just return it as string
|
|
104
130
|
}
|
|
105
131
|
|
|
106
132
|
/** Get offset of HTML element relative to a parent element */
|
package/src/index.ts
CHANGED
package/src/nodeExtend.ts
CHANGED
|
@@ -58,7 +58,7 @@ const setProperty = function setProperty(target: any, options: any) {
|
|
|
58
58
|
};
|
|
59
59
|
|
|
60
60
|
// Return undefined instead of __proto__ if '__proto__' is not an own property
|
|
61
|
-
const getProperty = function getProperty(obj: any, name:
|
|
61
|
+
const getProperty = function getProperty(obj: any, name: string) {
|
|
62
62
|
if (name === '__proto__') {
|
|
63
63
|
if (!hasOwn.call(obj, name)) {
|
|
64
64
|
return void 0;
|
package/src/stripTagsUtil.ts
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* This stripTags function is a lib that already existed
|
|
3
|
-
* but was not TypeScript and ESM friendly.
|
|
4
|
-
* So I ported the code into the project and removed any
|
|
5
|
-
*
|
|
2
|
+
* This stripTags function is a lib that already existed on NPM
|
|
3
|
+
* but was not written as TypeScript and was not ESM friendly.
|
|
4
|
+
* So I ported the code into the project and removed any legacy browser code that we don't need for our project since we dropped IE browsers support.
|
|
5
|
+
* The function also accept more input types without throwing like the original one does,
|
|
6
|
+
* the code below accepts `string | number | boolean | HTMLElement` while original code only accepted string.
|
|
6
7
|
*
|
|
7
8
|
* The previous lib can be found here at this Github link:
|
|
8
9
|
* https://github.com/ericnorris/striptags/
|
|
9
|
-
* With an MIT licence that and can be found at
|
|
10
|
+
* With an MIT licence that and can be found at this link:
|
|
10
11
|
* https://github.com/ericnorris/striptags/blob/main/LICENSE
|
|
11
12
|
*/
|
|
12
13
|
|
package/src/utils.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { AnyFunction } from './models/types';
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Add an item to an array only when the item does not exists, when the item is an object we will be using their "id" to compare
|
|
3
5
|
* @param inputArray
|
|
@@ -57,11 +59,11 @@ export function deepCopy(objectOrArray: any | any[]): any | any[] {
|
|
|
57
59
|
|
|
58
60
|
// Loop through each item in the original
|
|
59
61
|
// Recursively copy it's value and add to the clone
|
|
60
|
-
|
|
62
|
+
Object.keys(objectOrArray).forEach(key => {
|
|
61
63
|
if (Object.prototype.hasOwnProperty.call(objectOrArray, key)) {
|
|
62
64
|
(clone as any)[key] = deepCopy(objectOrArray[key]);
|
|
63
65
|
}
|
|
64
|
-
}
|
|
66
|
+
});
|
|
65
67
|
return clone;
|
|
66
68
|
};
|
|
67
69
|
|
|
@@ -104,7 +106,7 @@ export function deepMerge(target: any, ...sources: any[]): any {
|
|
|
104
106
|
target = (!isObject(target) && isObject(source)) ? {} : target;
|
|
105
107
|
|
|
106
108
|
if (isObject(target) && isObject(source)) {
|
|
107
|
-
|
|
109
|
+
Object.keys(source).forEach(prop => {
|
|
108
110
|
if (source.hasOwnProperty(prop)) {
|
|
109
111
|
if (prop in target) {
|
|
110
112
|
// handling merging of two properties with equal names
|
|
@@ -128,53 +130,22 @@ export function deepMerge(target: any, ...sources: any[]): any {
|
|
|
128
130
|
target[prop] = source[prop];
|
|
129
131
|
}
|
|
130
132
|
}
|
|
131
|
-
}
|
|
133
|
+
});
|
|
132
134
|
}
|
|
133
135
|
return deepMerge(target, ...sources);
|
|
134
136
|
}
|
|
135
137
|
|
|
136
|
-
/**
|
|
137
|
-
* This method is similar to `Object.assign` with the exception that it will also extend the object properties when filled.
|
|
138
|
-
* There's also a distinction with extend vs merge, we are only extending when the property is not filled (if it is filled then it remains untouched and will not be merged)
|
|
139
|
-
* It also applies the change directly on the target object which mutates the original object.
|
|
140
|
-
* For example using these 2 objects: obj1 = { a: 1, b: { c: 2, d: 3 }} and obj2 = { b: { d: 2, e: 3}}:
|
|
141
|
-
* - Object.assign(obj1, obj2) => { a: 1, b: { e: 4 }}
|
|
142
|
-
* - objectAssignAndExtend(obj1, obj2) => { a: 1, b: { c: 2, d: 3, e: 4 }
|
|
143
|
-
* @param {Object} target - the target object — what to apply the sources properties and mutate into
|
|
144
|
-
* @param {Object} sources - the source object(s) — objects containing the properties you want to apply.
|
|
145
|
-
* @returns {Object} The target object.
|
|
146
|
-
*/
|
|
147
|
-
export function objectAssignAndExtend(target: any, ...sources: any): any {
|
|
148
|
-
if (!sources.length || sources[0] === undefined) {
|
|
149
|
-
return target;
|
|
150
|
-
}
|
|
151
|
-
const source = sources.shift();
|
|
152
|
-
|
|
153
|
-
// when target is not an object but source is an object, then we'll assign as object
|
|
154
|
-
target = (!isObject(target) && isObject(source)) ? {} : target;
|
|
155
|
-
|
|
156
|
-
if (isObject(target) && isObject(source)) {
|
|
157
|
-
for (const key of Object.keys(source)) {
|
|
158
|
-
if (typeof source[key] === 'object' && source[key] !== null) {
|
|
159
|
-
objectAssignAndExtend(target[key], source[key]);
|
|
160
|
-
}
|
|
161
|
-
if ((target[key] === null || target[key] === undefined) && source[key] !== null && source[key] !== undefined) {
|
|
162
|
-
target[key] = source[key];
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
return objectAssignAndExtend(target, ...sources);
|
|
167
|
-
}
|
|
168
|
-
|
|
169
138
|
/**
|
|
170
139
|
* Empty an object properties by looping through them all and deleting them
|
|
171
140
|
* @param obj - input object
|
|
172
141
|
*/
|
|
173
142
|
export function emptyObject(obj: any) {
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
143
|
+
if (isObject(obj)) {
|
|
144
|
+
Object.keys(obj).forEach(key => {
|
|
145
|
+
if (obj.hasOwnProperty(key)) {
|
|
146
|
+
delete obj[key];
|
|
147
|
+
}
|
|
148
|
+
});
|
|
178
149
|
}
|
|
179
150
|
obj = null;
|
|
180
151
|
obj = {};
|
|
@@ -182,6 +153,50 @@ export function emptyObject(obj: any) {
|
|
|
182
153
|
return obj;
|
|
183
154
|
}
|
|
184
155
|
|
|
156
|
+
/**
|
|
157
|
+
* Get the function details (param & body) of a function.
|
|
158
|
+
* It supports regular function and also ES6 arrow functions
|
|
159
|
+
* @param {Function} fn - function to analyze
|
|
160
|
+
* @param {Boolean} [addReturn] - when using ES6 function as single liner, we could add the missing `return ...`
|
|
161
|
+
* @returns
|
|
162
|
+
*/
|
|
163
|
+
export function getFunctionDetails(fn: AnyFunction, addReturn = true) {
|
|
164
|
+
let isAsyncFn = false;
|
|
165
|
+
|
|
166
|
+
const getFunctionBody = (func: AnyFunction) => {
|
|
167
|
+
const fnStr = func.toString();
|
|
168
|
+
isAsyncFn = fnStr.includes('async ');
|
|
169
|
+
|
|
170
|
+
// when fn is one liner arrow fn returning an object in brackets e.g. `() => ({ hello: 'world' })`
|
|
171
|
+
if ((fnStr.replaceAll(' ', '').includes('=>({'))) {
|
|
172
|
+
const matches = fnStr.match(/(({.*}))/g) || [];
|
|
173
|
+
return matches.length >= 1 ? `return ${matches[0]!.trimStart()}` : fnStr;
|
|
174
|
+
}
|
|
175
|
+
const isOneLinerArrowFn = (!fnStr.includes('{') && fnStr.includes('=>'));
|
|
176
|
+
const body = fnStr.substring(
|
|
177
|
+
(fnStr.indexOf('{') + 1) || (fnStr.indexOf('=>') + 2),
|
|
178
|
+
fnStr.includes('}') ? fnStr.lastIndexOf('}') : fnStr.length
|
|
179
|
+
);
|
|
180
|
+
if (addReturn && isOneLinerArrowFn && !body.startsWith('return')) {
|
|
181
|
+
return 'return ' + body.trimStart(); // add the `return ...` to the body for ES6 arrow fn
|
|
182
|
+
}
|
|
183
|
+
return body;
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
const getFunctionParams = (func: AnyFunction): string[] => {
|
|
187
|
+
const STRIP_COMMENTS = /(\/\/.*$)|(\/\*[\s\S]*?\*\/)|(\s*=[^,\)]*(('(?:\\'|[^'\r\n])*')|("(?:\\"|[^"\r\n])*"))|(\s*=[^,\)]*))/mg;
|
|
188
|
+
const ARG_NAMES = /([^\s,]+)/g;
|
|
189
|
+
const fnStr = func.toString().replace(STRIP_COMMENTS, '');
|
|
190
|
+
return fnStr.slice(fnStr.indexOf('(') + 1, fnStr.indexOf(')')).match(ARG_NAMES) ?? [];
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
return {
|
|
194
|
+
params: getFunctionParams(fn),
|
|
195
|
+
body: getFunctionBody(fn),
|
|
196
|
+
isAsync: isAsyncFn,
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
|
|
185
200
|
/**
|
|
186
201
|
* Check if an object is empty
|
|
187
202
|
* @param obj - input object
|
|
@@ -198,6 +213,10 @@ export function isDefined<T>(value: T | undefined | null): value is T {
|
|
|
198
213
|
return <T>value !== undefined && <T>value !== null && <T>value !== '';
|
|
199
214
|
}
|
|
200
215
|
|
|
216
|
+
export function isDefinedNumber<T>(value: T | undefined | null): value is T {
|
|
217
|
+
return <T>value !== null && !isNaN(value as any) && <T>value !== '';
|
|
218
|
+
}
|
|
219
|
+
|
|
201
220
|
/**
|
|
202
221
|
* Simple object check.
|
|
203
222
|
* @param item
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"htmlElementPosition.interface.js","sourceRoot":"","sources":["../../../src/types/htmlElementPosition.interface.ts"],"names":[],"mappings":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/types/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,kEAAgD;AAChD,+CAA6B"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"infer.type.js","sourceRoot":"","sources":["../../../src/types/infer.type.ts"],"names":[],"mappings":";;AAKA,6CAA6C"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"htmlElementPosition.interface.js","sourceRoot":"","sources":["../../../src/types/htmlElementPosition.interface.ts"],"names":[],"mappings":""}
|
package/dist/esm/types/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/types/index.ts"],"names":[],"mappings":"AAAA,cAAc,iCAAiC,CAAC;AAChD,cAAc,cAAc,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"infer.type.js","sourceRoot":"","sources":["../../../src/types/infer.type.ts"],"names":[],"mappings":";AAKA,6CAA6C"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"htmlElementPosition.interface.d.ts","sourceRoot":"","sources":["../../../src/types/htmlElementPosition.interface.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,mBAAmB;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/types/index.ts"],"names":[],"mappings":"AAAA,cAAc,iCAAiC,CAAC;AAChD,cAAc,cAAc,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"infer.type.d.ts","sourceRoot":"","sources":["../../../src/types/infer.type.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,YAAY,CAAC,CAAC,IACxB,CAAC,SAAS,mBAAmB,GAAG,OAAO,CAAC,mBAAmB,CAAC,GAC5D,CAAC,SAAS,MAAM,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC"}
|
package/src/types/index.ts
DELETED
|
File without changes
|