@matdata/yasgui-utils 4.6.1 → 4.7.4
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/CHANGELOG.md +47 -47
- package/build/utils.min.js.map +1 -1
- package/package.json +26 -26
- package/src/Storage.ts +100 -100
- package/src/__tests__/placeholder-test.ts +2 -2
- package/src/index.ts +63 -63
package/package.json
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@matdata/yasgui-utils",
|
|
3
|
-
"version": "4.
|
|
4
|
-
"description": "Utils for YASGUI libs",
|
|
5
|
-
"main": "build/utils.min.js",
|
|
6
|
-
"types": "build/ts/src/index.d.ts",
|
|
7
|
-
"license": "MIT",
|
|
8
|
-
"author": "Triply <info@triply.cc>",
|
|
9
|
-
"homepage": "https://github.com/Matdata-eu/Yasgui",
|
|
10
|
-
"bugs": "https://github.com/Matdata-eu/Yasgui/issues",
|
|
11
|
-
"repository": {
|
|
12
|
-
"type": "git",
|
|
13
|
-
"url": "https://github.com/Matdata-eu/Yasgui.git",
|
|
14
|
-
"directory": "packages/utils"
|
|
15
|
-
},
|
|
16
|
-
"dependencies": {
|
|
17
|
-
"dompurify": "^3.2.4",
|
|
18
|
-
"store": "^2.0.12"
|
|
19
|
-
},
|
|
20
|
-
"devDependencies": {
|
|
21
|
-
"@types/node": "^22.5.4"
|
|
22
|
-
},
|
|
23
|
-
"publishConfig": {
|
|
24
|
-
"access": "public"
|
|
25
|
-
}
|
|
26
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@matdata/yasgui-utils",
|
|
3
|
+
"version": "4.7.4",
|
|
4
|
+
"description": "Utils for YASGUI libs",
|
|
5
|
+
"main": "build/utils.min.js",
|
|
6
|
+
"types": "build/ts/src/index.d.ts",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"author": "Triply <info@triply.cc>",
|
|
9
|
+
"homepage": "https://github.com/Matdata-eu/Yasgui",
|
|
10
|
+
"bugs": "https://github.com/Matdata-eu/Yasgui/issues",
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "https://github.com/Matdata-eu/Yasgui.git",
|
|
14
|
+
"directory": "packages/utils"
|
|
15
|
+
},
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"dompurify": "^3.2.4",
|
|
18
|
+
"store": "^2.0.12"
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"@types/node": "^22.5.4"
|
|
22
|
+
},
|
|
23
|
+
"publishConfig": {
|
|
24
|
+
"access": "public"
|
|
25
|
+
}
|
|
26
|
+
}
|
package/src/Storage.ts
CHANGED
|
@@ -1,100 +1,100 @@
|
|
|
1
|
-
var store = require("store");
|
|
2
|
-
export interface ItemWrapper<V = {}> {
|
|
3
|
-
exp: number;
|
|
4
|
-
val: V;
|
|
5
|
-
namespace: string;
|
|
6
|
-
time: number;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
interface QuotaExceededError extends Error {
|
|
10
|
-
quotaExceeded?: boolean;
|
|
11
|
-
}
|
|
12
|
-
export default class Storage {
|
|
13
|
-
private namespace: string;
|
|
14
|
-
constructor(namespace: string) {
|
|
15
|
-
this.namespace = namespace;
|
|
16
|
-
}
|
|
17
|
-
public set<V = {}>(key: string | undefined, val: any, expInSeconds: number, onQuotaExceeded: (e: any) => void) {
|
|
18
|
-
if (!store.enabled) return; //this is probably in private mode. Don't run, as we might get Js errors
|
|
19
|
-
this.removeExpiredKeys();
|
|
20
|
-
if (key && val !== undefined) {
|
|
21
|
-
//try to store string for dom objects (e.g. XML result). Otherwise, we might get a circular reference error when stringifying this
|
|
22
|
-
if (val.documentElement) val = new XMLSerializer().serializeToString(val.documentElement);
|
|
23
|
-
try {
|
|
24
|
-
store.set(key, <ItemWrapper<V>>{
|
|
25
|
-
namespace: this.namespace,
|
|
26
|
-
val: val,
|
|
27
|
-
exp: expInSeconds,
|
|
28
|
-
time: new Date().getTime() / 1000,
|
|
29
|
-
});
|
|
30
|
-
} catch (e) {
|
|
31
|
-
if (e instanceof Error) {
|
|
32
|
-
const quotaExceededError = e as QuotaExceededError;
|
|
33
|
-
quotaExceededError.quotaExceeded = isQuotaExceeded(e);
|
|
34
|
-
if (quotaExceededError.quotaExceeded && onQuotaExceeded) {
|
|
35
|
-
onQuotaExceeded(e);
|
|
36
|
-
} else {
|
|
37
|
-
throw quotaExceededError;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
throw e;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
remove(key: string) {
|
|
45
|
-
if (!store.enabled) return; //this is probably in private mode. Don't run, as we might get Js errors
|
|
46
|
-
if (key) store.remove(key);
|
|
47
|
-
}
|
|
48
|
-
removeExpiredKeys() {
|
|
49
|
-
if (!store.enabled) return;
|
|
50
|
-
store.each((value: ItemWrapper, key: string) => {
|
|
51
|
-
if (value && value.exp && new Date().getTime() / 1000 - value.time > value.exp) {
|
|
52
|
-
this.remove(key);
|
|
53
|
-
}
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
removeAll() {
|
|
57
|
-
if (!store.enabled) return; //this is probably in private mode. Don't run, as we might get Js errors
|
|
58
|
-
}
|
|
59
|
-
removeNamespace() {
|
|
60
|
-
store.each((value: ItemWrapper<any>, key: string) => {
|
|
61
|
-
if (value.namespace && value.namespace === this.namespace) this.remove(key);
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
get<V>(key?: string): V | undefined {
|
|
65
|
-
if (!store.enabled) return; //this is probably in private mode. Don't run, as we might get Js errors
|
|
66
|
-
if (!key) return;
|
|
67
|
-
this.removeExpiredKeys();
|
|
68
|
-
if (key) {
|
|
69
|
-
var info: ItemWrapper<V> = store.get(key);
|
|
70
|
-
if (!info) {
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
return info.val;
|
|
74
|
-
} else {
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
function isQuotaExceeded(e: any) {
|
|
80
|
-
var quotaExceeded = false;
|
|
81
|
-
if (e) {
|
|
82
|
-
if (e.code) {
|
|
83
|
-
switch (e.code) {
|
|
84
|
-
case 22:
|
|
85
|
-
quotaExceeded = true;
|
|
86
|
-
break;
|
|
87
|
-
case 1014:
|
|
88
|
-
// Firefox
|
|
89
|
-
if (e.name === "NS_ERROR_DOM_QUOTA_REACHED") {
|
|
90
|
-
quotaExceeded = true;
|
|
91
|
-
}
|
|
92
|
-
break;
|
|
93
|
-
}
|
|
94
|
-
} else if (e.number === -2147024882) {
|
|
95
|
-
// Internet Explorer 8
|
|
96
|
-
quotaExceeded = true;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
return quotaExceeded;
|
|
100
|
-
}
|
|
1
|
+
var store = require("store");
|
|
2
|
+
export interface ItemWrapper<V = {}> {
|
|
3
|
+
exp: number;
|
|
4
|
+
val: V;
|
|
5
|
+
namespace: string;
|
|
6
|
+
time: number;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
interface QuotaExceededError extends Error {
|
|
10
|
+
quotaExceeded?: boolean;
|
|
11
|
+
}
|
|
12
|
+
export default class Storage {
|
|
13
|
+
private namespace: string;
|
|
14
|
+
constructor(namespace: string) {
|
|
15
|
+
this.namespace = namespace;
|
|
16
|
+
}
|
|
17
|
+
public set<V = {}>(key: string | undefined, val: any, expInSeconds: number, onQuotaExceeded: (e: any) => void) {
|
|
18
|
+
if (!store.enabled) return; //this is probably in private mode. Don't run, as we might get Js errors
|
|
19
|
+
this.removeExpiredKeys();
|
|
20
|
+
if (key && val !== undefined) {
|
|
21
|
+
//try to store string for dom objects (e.g. XML result). Otherwise, we might get a circular reference error when stringifying this
|
|
22
|
+
if (val.documentElement) val = new XMLSerializer().serializeToString(val.documentElement);
|
|
23
|
+
try {
|
|
24
|
+
store.set(key, <ItemWrapper<V>>{
|
|
25
|
+
namespace: this.namespace,
|
|
26
|
+
val: val,
|
|
27
|
+
exp: expInSeconds,
|
|
28
|
+
time: new Date().getTime() / 1000,
|
|
29
|
+
});
|
|
30
|
+
} catch (e) {
|
|
31
|
+
if (e instanceof Error) {
|
|
32
|
+
const quotaExceededError = e as QuotaExceededError;
|
|
33
|
+
quotaExceededError.quotaExceeded = isQuotaExceeded(e);
|
|
34
|
+
if (quotaExceededError.quotaExceeded && onQuotaExceeded) {
|
|
35
|
+
onQuotaExceeded(e);
|
|
36
|
+
} else {
|
|
37
|
+
throw quotaExceededError;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
throw e;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
remove(key: string) {
|
|
45
|
+
if (!store.enabled) return; //this is probably in private mode. Don't run, as we might get Js errors
|
|
46
|
+
if (key) store.remove(key);
|
|
47
|
+
}
|
|
48
|
+
removeExpiredKeys() {
|
|
49
|
+
if (!store.enabled) return;
|
|
50
|
+
store.each((value: ItemWrapper, key: string) => {
|
|
51
|
+
if (value && value.exp && new Date().getTime() / 1000 - value.time > value.exp) {
|
|
52
|
+
this.remove(key);
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
removeAll() {
|
|
57
|
+
if (!store.enabled) return; //this is probably in private mode. Don't run, as we might get Js errors
|
|
58
|
+
}
|
|
59
|
+
removeNamespace() {
|
|
60
|
+
store.each((value: ItemWrapper<any>, key: string) => {
|
|
61
|
+
if (value.namespace && value.namespace === this.namespace) this.remove(key);
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
get<V>(key?: string): V | undefined {
|
|
65
|
+
if (!store.enabled) return; //this is probably in private mode. Don't run, as we might get Js errors
|
|
66
|
+
if (!key) return;
|
|
67
|
+
this.removeExpiredKeys();
|
|
68
|
+
if (key) {
|
|
69
|
+
var info: ItemWrapper<V> = store.get(key);
|
|
70
|
+
if (!info) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
return info.val;
|
|
74
|
+
} else {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
function isQuotaExceeded(e: any) {
|
|
80
|
+
var quotaExceeded = false;
|
|
81
|
+
if (e) {
|
|
82
|
+
if (e.code) {
|
|
83
|
+
switch (e.code) {
|
|
84
|
+
case 22:
|
|
85
|
+
quotaExceeded = true;
|
|
86
|
+
break;
|
|
87
|
+
case 1014:
|
|
88
|
+
// Firefox
|
|
89
|
+
if (e.name === "NS_ERROR_DOM_QUOTA_REACHED") {
|
|
90
|
+
quotaExceeded = true;
|
|
91
|
+
}
|
|
92
|
+
break;
|
|
93
|
+
}
|
|
94
|
+
} else if (e.number === -2147024882) {
|
|
95
|
+
// Internet Explorer 8
|
|
96
|
+
quotaExceeded = true;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return quotaExceeded;
|
|
100
|
+
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
//just a placeholder, so our `npm run test` command wont fail as there arent any
|
|
2
|
-
//other tests yet
|
|
1
|
+
//just a placeholder, so our `npm run test` command wont fail as there arent any
|
|
2
|
+
//other tests yet
|
package/src/index.ts
CHANGED
|
@@ -1,63 +1,63 @@
|
|
|
1
|
-
import DOMPurify from "dompurify";
|
|
2
|
-
export { default as Storage } from "./Storage";
|
|
3
|
-
|
|
4
|
-
const { sanitize } = DOMPurify;
|
|
5
|
-
|
|
6
|
-
export function drawSvgStringAsElement(svgString: string) {
|
|
7
|
-
if (svgString && svgString.trim().indexOf("<svg") == 0) {
|
|
8
|
-
//no style passed via config. guess own styles
|
|
9
|
-
var parser = new DOMParser();
|
|
10
|
-
var dom = parser.parseFromString(svgString, "text/xml");
|
|
11
|
-
var svg = dom.documentElement;
|
|
12
|
-
svg.setAttribute("aria-hidden", "true");
|
|
13
|
-
|
|
14
|
-
var svgContainer = document.createElement("div");
|
|
15
|
-
svgContainer.className = "svgImg";
|
|
16
|
-
svgContainer.appendChild(svg);
|
|
17
|
-
return svgContainer;
|
|
18
|
-
}
|
|
19
|
-
throw new Error("No svg string given. Cannot draw");
|
|
20
|
-
}
|
|
21
|
-
export interface FaIcon {
|
|
22
|
-
width: number;
|
|
23
|
-
height: number;
|
|
24
|
-
svgPathData: string;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Draws font fontawesome icon as svg. This is a lot more lightweight then the option that is offered by fontawesome
|
|
29
|
-
* @param faIcon
|
|
30
|
-
* @returns
|
|
31
|
-
*/
|
|
32
|
-
export function drawFontAwesomeIconAsSvg(faIcon: FaIcon) {
|
|
33
|
-
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${faIcon.width} ${faIcon.height}" aria-hidden="true"><path fill="currentColor" d="${faIcon.svgPathData}"></path></svg>`;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export function hasClass(el: Element | undefined, className: string) {
|
|
37
|
-
if (!el) return;
|
|
38
|
-
if (el.classList) return el.classList.contains(className);
|
|
39
|
-
else return !!el.className.match(new RegExp("(\\s|^)" + className + "(\\s|$)"));
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export function addClass(el: Element | undefined | null, ...classNames: string[]) {
|
|
43
|
-
if (!el) return;
|
|
44
|
-
for (const className of classNames) {
|
|
45
|
-
if (el.classList) el.classList.add(className);
|
|
46
|
-
else if (!hasClass(el, className)) el.className += " " + className;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export function removeClass(el: Element | undefined | null, className: string) {
|
|
51
|
-
if (!el) return;
|
|
52
|
-
if (el.classList) el.classList.remove(className);
|
|
53
|
-
else if (hasClass(el, className)) {
|
|
54
|
-
var reg = new RegExp("(\\s|^)" + className + "(\\s|$)");
|
|
55
|
-
el.className = el.className.replace(reg, " ");
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export function getAsValue<E, A>(valueOrFn: E | ((arg: A) => E), arg: A): E {
|
|
60
|
-
if (typeof valueOrFn === "function") return (valueOrFn as any)(arg);
|
|
61
|
-
if (typeof valueOrFn === "string") return sanitize(valueOrFn) as any;
|
|
62
|
-
return valueOrFn;
|
|
63
|
-
}
|
|
1
|
+
import DOMPurify from "dompurify";
|
|
2
|
+
export { default as Storage } from "./Storage";
|
|
3
|
+
|
|
4
|
+
const { sanitize } = DOMPurify;
|
|
5
|
+
|
|
6
|
+
export function drawSvgStringAsElement(svgString: string) {
|
|
7
|
+
if (svgString && svgString.trim().indexOf("<svg") == 0) {
|
|
8
|
+
//no style passed via config. guess own styles
|
|
9
|
+
var parser = new DOMParser();
|
|
10
|
+
var dom = parser.parseFromString(svgString, "text/xml");
|
|
11
|
+
var svg = dom.documentElement;
|
|
12
|
+
svg.setAttribute("aria-hidden", "true");
|
|
13
|
+
|
|
14
|
+
var svgContainer = document.createElement("div");
|
|
15
|
+
svgContainer.className = "svgImg";
|
|
16
|
+
svgContainer.appendChild(svg);
|
|
17
|
+
return svgContainer;
|
|
18
|
+
}
|
|
19
|
+
throw new Error("No svg string given. Cannot draw");
|
|
20
|
+
}
|
|
21
|
+
export interface FaIcon {
|
|
22
|
+
width: number;
|
|
23
|
+
height: number;
|
|
24
|
+
svgPathData: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Draws font fontawesome icon as svg. This is a lot more lightweight then the option that is offered by fontawesome
|
|
29
|
+
* @param faIcon
|
|
30
|
+
* @returns
|
|
31
|
+
*/
|
|
32
|
+
export function drawFontAwesomeIconAsSvg(faIcon: FaIcon) {
|
|
33
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${faIcon.width} ${faIcon.height}" aria-hidden="true"><path fill="currentColor" d="${faIcon.svgPathData}"></path></svg>`;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function hasClass(el: Element | undefined, className: string) {
|
|
37
|
+
if (!el) return;
|
|
38
|
+
if (el.classList) return el.classList.contains(className);
|
|
39
|
+
else return !!el.className.match(new RegExp("(\\s|^)" + className + "(\\s|$)"));
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function addClass(el: Element | undefined | null, ...classNames: string[]) {
|
|
43
|
+
if (!el) return;
|
|
44
|
+
for (const className of classNames) {
|
|
45
|
+
if (el.classList) el.classList.add(className);
|
|
46
|
+
else if (!hasClass(el, className)) el.className += " " + className;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function removeClass(el: Element | undefined | null, className: string) {
|
|
51
|
+
if (!el) return;
|
|
52
|
+
if (el.classList) el.classList.remove(className);
|
|
53
|
+
else if (hasClass(el, className)) {
|
|
54
|
+
var reg = new RegExp("(\\s|^)" + className + "(\\s|$)");
|
|
55
|
+
el.className = el.className.replace(reg, " ");
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function getAsValue<E, A>(valueOrFn: E | ((arg: A) => E), arg: A): E {
|
|
60
|
+
if (typeof valueOrFn === "function") return (valueOrFn as any)(arg);
|
|
61
|
+
if (typeof valueOrFn === "string") return sanitize(valueOrFn) as any;
|
|
62
|
+
return valueOrFn;
|
|
63
|
+
}
|