@cloudcome/utils-core 1.19.0 → 1.20.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/README.md +1 -1
- package/dist/array.cjs +181 -125
- package/dist/array.cjs.map +1 -1
- package/dist/array.mjs +181 -133
- package/dist/array.mjs.map +1 -1
- package/dist/async.cjs +181 -171
- package/dist/async.cjs.map +1 -1
- package/dist/async.mjs +181 -174
- package/dist/async.mjs.map +1 -1
- package/dist/base64.cjs +16 -12
- package/dist/base64.cjs.map +1 -1
- package/dist/base64.mjs +17 -14
- package/dist/base64.mjs.map +1 -1
- package/dist/cache.cjs +79 -67
- package/dist/cache.cjs.map +1 -1
- package/dist/cache.d.ts +3 -3
- package/dist/cache.mjs +80 -71
- package/dist/cache.mjs.map +1 -1
- package/dist/color.cjs +478 -167
- package/dist/color.cjs.map +1 -1
- package/dist/color.d.ts +3 -3
- package/dist/color.mjs +480 -197
- package/dist/color.mjs.map +1 -1
- package/dist/crypto.cjs +474 -687
- package/dist/crypto.cjs.map +1 -1
- package/dist/crypto.mjs +476 -693
- package/dist/crypto.mjs.map +1 -1
- package/dist/date.cjs +972 -161
- package/dist/date.cjs.map +1 -1
- package/dist/date.d.ts +2 -2
- package/dist/date.mjs +962 -191
- package/dist/date.mjs.map +1 -1
- package/dist/dict.cjs +90 -52
- package/dist/dict.cjs.map +1 -1
- package/dist/dict.d.ts +1 -1
- package/dist/dict.mjs +91 -54
- package/dist/dict.mjs.map +1 -1
- package/dist/easing.cjs +105 -103
- package/dist/easing.cjs.map +1 -1
- package/dist/easing.mjs +106 -133
- package/dist/easing.mjs.map +1 -1
- package/dist/emitter.cjs +101 -96
- package/dist/emitter.cjs.map +1 -1
- package/dist/emitter.mjs +101 -97
- package/dist/emitter.mjs.map +1 -1
- package/dist/env.cjs +43 -9
- package/dist/env.cjs.map +1 -1
- package/dist/env.d.ts +1 -1
- package/dist/env.mjs +43 -15
- package/dist/env.mjs.map +1 -1
- package/dist/error.cjs +26 -5
- package/dist/error.cjs.map +1 -1
- package/dist/error.mjs +26 -7
- package/dist/error.mjs.map +1 -1
- package/dist/exception.cjs +38 -20
- package/dist/exception.cjs.map +1 -1
- package/dist/exception.d.ts +5 -5
- package/dist/exception.mjs +38 -21
- package/dist/exception.mjs.map +1 -1
- package/dist/function.cjs +128 -68
- package/dist/function.cjs.map +1 -1
- package/dist/function.mjs +128 -72
- package/dist/function.mjs.map +1 -1
- package/dist/index.cjs +8 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +9 -5
- package/dist/index.mjs.map +1 -1
- package/dist/number.cjs +10 -14
- package/dist/number.mjs +2 -15
- package/dist/object/get-set.d.ts +27 -3
- package/dist/object/merge.d.ts +2 -2
- package/dist/object.cjs +369 -106
- package/dist/object.cjs.map +1 -1
- package/dist/object.mjs +366 -115
- package/dist/object.mjs.map +1 -1
- package/dist/path.cjs +144 -55
- package/dist/path.cjs.map +1 -1
- package/dist/path.mjs +144 -62
- package/dist/path.mjs.map +1 -1
- package/dist/promise.cjs +84 -43
- package/dist/promise.cjs.map +1 -1
- package/dist/promise.mjs +85 -50
- package/dist/promise.mjs.map +1 -1
- package/dist/qs.cjs +63 -39
- package/dist/qs.cjs.map +1 -1
- package/dist/qs.mjs +64 -42
- package/dist/qs.mjs.map +1 -1
- package/dist/regexp.cjs +118 -35
- package/dist/regexp.cjs.map +1 -1
- package/dist/regexp.mjs +119 -46
- package/dist/regexp.mjs.map +1 -1
- package/dist/string.cjs +12 -15
- package/dist/string.mjs +2 -16
- package/dist/string2.cjs +378 -142
- package/dist/string2.cjs.map +1 -1
- package/dist/string2.mjs +259 -143
- package/dist/string2.mjs.map +1 -1
- package/dist/time.cjs +136 -59
- package/dist/time.cjs.map +1 -1
- package/dist/time.mjs +136 -65
- package/dist/time.mjs.map +1 -1
- package/dist/timer.cjs +122 -112
- package/dist/timer.cjs.map +1 -1
- package/dist/timer.mjs +123 -115
- package/dist/timer.mjs.map +1 -1
- package/dist/tree.cjs +207 -112
- package/dist/tree.cjs.map +1 -1
- package/dist/tree.mjs +207 -116
- package/dist/tree.mjs.map +1 -1
- package/dist/try/curry.d.ts +1 -1
- package/dist/try.cjs +36 -37
- package/dist/try.cjs.map +1 -1
- package/dist/try.mjs +35 -37
- package/dist/try.mjs.map +1 -1
- package/dist/type.cjs +126 -24
- package/dist/type.cjs.map +1 -1
- package/dist/type.d.ts +2 -2
- package/dist/type.mjs +128 -45
- package/dist/type.mjs.map +1 -1
- package/dist/types.cjs +0 -2
- package/dist/types.d.ts +2 -2
- package/dist/types.mjs +0 -2
- package/dist/unique.cjs +41 -38
- package/dist/unique.cjs.map +1 -1
- package/dist/unique.mjs +42 -41
- package/dist/unique.mjs.map +1 -1
- package/dist/url.cjs +39 -30
- package/dist/url.cjs.map +1 -1
- package/dist/url.mjs +40 -33
- package/dist/url.mjs.map +1 -1
- package/dist/version.cjs +51 -33
- package/dist/version.cjs.map +1 -1
- package/dist/version.mjs +51 -35
- package/dist/version.mjs.map +1 -1
- package/package.json +104 -105
- package/dist/const.cjs +0 -14
- package/dist/const.cjs.map +0 -1
- package/dist/const.mjs +0 -15
- package/dist/const.mjs.map +0 -1
- package/dist/core.cjs +0 -362
- package/dist/core.cjs.map +0 -1
- package/dist/core.mjs +0 -363
- package/dist/core.mjs.map +0 -1
- package/dist/crypto/md5.d.mts +0 -1
- package/dist/crypto/sha1.d.mts +0 -1
- package/dist/crypto/sha256.d.mts +0 -1
- package/dist/crypto/sha512.d.mts +0 -1
- package/dist/each.cjs +0 -18
- package/dist/each.cjs.map +0 -1
- package/dist/each.mjs +0 -19
- package/dist/each.mjs.map +0 -1
- package/dist/merge.cjs +0 -87
- package/dist/merge.cjs.map +0 -1
- package/dist/merge.mjs +0 -88
- package/dist/merge.mjs.map +0 -1
- package/dist/number.cjs.map +0 -1
- package/dist/number.mjs.map +0 -1
- package/dist/string.cjs.map +0 -1
- package/dist/string.mjs.map +0 -1
- package/dist/types.cjs.map +0 -1
- package/dist/types.mjs.map +0 -1
package/dist/emitter.cjs
CHANGED
|
@@ -1,98 +1,103 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
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
|
-
|
|
2
|
+
//#region src/emitter.ts
|
|
3
|
+
/**
|
|
4
|
+
* 事件发射器类,用于管理事件监听和触发
|
|
5
|
+
* @template E - 事件类型映射
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* type MyEvents = {
|
|
9
|
+
* 'click': [x: number, y: number];
|
|
10
|
+
* 'change': [value: string];
|
|
11
|
+
* };
|
|
12
|
+
*
|
|
13
|
+
* const emitter = new Emitter<MyEvents>();
|
|
14
|
+
* emitter.on('click', (x, y) => {
|
|
15
|
+
* console.log(`Clicked at (${x}, ${y})`);
|
|
16
|
+
* });
|
|
17
|
+
* emitter.emit('click', 10, 20);
|
|
18
|
+
*/
|
|
19
|
+
var Emitter = class {
|
|
20
|
+
#events = /* @__PURE__ */ new Map();
|
|
21
|
+
/**
|
|
22
|
+
* 注册事件监听器
|
|
23
|
+
* @param event - 要监听的事件名称
|
|
24
|
+
* @param listener - 事件监听器函数
|
|
25
|
+
* @example
|
|
26
|
+
* emitter.on('click', (x, y) => {
|
|
27
|
+
* console.log(`Clicked at (${x}, ${y})`);
|
|
28
|
+
* });
|
|
29
|
+
*/
|
|
30
|
+
on(event, listener) {
|
|
31
|
+
const listeners = this.#events.get(event);
|
|
32
|
+
if (listeners) listeners.add(listener);
|
|
33
|
+
else this.#events.set(event, new Set([listener]));
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* 注册事件监听器,仅触发一次
|
|
37
|
+
* @param event - 要监听的事件名称
|
|
38
|
+
* @param listener - 事件监听器函数
|
|
39
|
+
* @example
|
|
40
|
+
* emitter.once('click', (x, y) => {
|
|
41
|
+
* console.log(`Clicked at (${x}, ${y})`);
|
|
42
|
+
* });
|
|
43
|
+
*/
|
|
44
|
+
once(event, listener) {
|
|
45
|
+
const onceListener = (...payloads) => {
|
|
46
|
+
const result = listener(...payloads);
|
|
47
|
+
this.off(event, onceListener);
|
|
48
|
+
return result;
|
|
49
|
+
};
|
|
50
|
+
this.on(event, onceListener);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* 移除事件监听器,有三种使用方式:
|
|
54
|
+
* 1. 移除特定事件的特定监听器
|
|
55
|
+
* 2. 移除特定事件的所有监听器
|
|
56
|
+
* 3. 移除所有事件的所有监听器
|
|
57
|
+
* @param event - 要移除的事件名称(可选)
|
|
58
|
+
* @param listener - 要移除的监听器函数(可选)
|
|
59
|
+
* @example
|
|
60
|
+
* // 移除特定事件的特定监听器
|
|
61
|
+
* emitter.off('click', clickHandler);
|
|
62
|
+
*
|
|
63
|
+
* // 移除特定事件的所有监听器
|
|
64
|
+
* emitter.off('click');
|
|
65
|
+
*
|
|
66
|
+
* // 移除所有事件的所有监听器
|
|
67
|
+
* emitter.off();
|
|
68
|
+
*/
|
|
69
|
+
off(event, listener) {
|
|
70
|
+
if (event && listener) this.#offListener(event, listener);
|
|
71
|
+
else if (event) this.#offEvent(event);
|
|
72
|
+
else this.#offAll();
|
|
73
|
+
}
|
|
74
|
+
#offAll() {
|
|
75
|
+
this.#events.clear();
|
|
76
|
+
}
|
|
77
|
+
#offEvent(event) {
|
|
78
|
+
this.#events.delete(event);
|
|
79
|
+
}
|
|
80
|
+
#offListener(event, listener) {
|
|
81
|
+
const listeners = this.#events.get(event);
|
|
82
|
+
if (listeners) listeners.delete(listener);
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* 触发指定事件,调用所有注册的监听器
|
|
86
|
+
* @param event - 要触发的事件名称
|
|
87
|
+
* @param payloads - 传递给监听器的参数
|
|
88
|
+
* @remarks
|
|
89
|
+
* 监听器会按照注册的顺序依次执行,如果某个监听器返回 false,
|
|
90
|
+
* 则后续监听器将不会被执行
|
|
91
|
+
* @example
|
|
92
|
+
* emitter.emit('click', 10, 20);
|
|
93
|
+
*/
|
|
94
|
+
emit(event, ...payloads) {
|
|
95
|
+
const listeners = this.#events.get(event);
|
|
96
|
+
if (!listeners) return;
|
|
97
|
+
for (const listener of [...listeners]) if (listener(...payloads) === false) break;
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
//#endregion
|
|
97
101
|
exports.Emitter = Emitter;
|
|
98
|
-
|
|
102
|
+
|
|
103
|
+
//# sourceMappingURL=emitter.cjs.map
|
package/dist/emitter.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"emitter.cjs","sources":["../src/emitter.ts"],"sourcesContent":["import type { AnyFunction
|
|
1
|
+
{"version":3,"file":"emitter.cjs","names":["#events","#offListener","#offEvent","#offAll"],"sources":["../src/emitter.ts"],"sourcesContent":["import type { AnyFunction } from './types';\n\n/**\n * 事件类型映射,key 为事件名称,value 为事件参数类型数组\n */\nexport type EmitterMap = Record<string, unknown[]>;\n\n/**\n * 事件监听器函数类型\n * @template E - EmitterMap 类型\n * @template K - 事件名称类型\n */\nexport type EmitterListener<E extends EmitterMap, K extends keyof E> = (\n ...payloads: E[K]\n) => false | unknown;\n\n/**\n * 事件发射器类,用于管理事件监听和触发\n * @template E - 事件类型映射\n *\n * @example\n * type MyEvents = {\n * 'click': [x: number, y: number];\n * 'change': [value: string];\n * };\n *\n * const emitter = new Emitter<MyEvents>();\n * emitter.on('click', (x, y) => {\n * console.log(`Clicked at (${x}, ${y})`);\n * });\n * emitter.emit('click', 10, 20);\n */\nexport class Emitter<\n E extends EmitterMap = Record<string | symbol, unknown[]>,\n> {\n #events: Map<keyof E, Set<AnyFunction>> = new Map();\n\n /**\n * 注册事件监听器\n * @param event - 要监听的事件名称\n * @param listener - 事件监听器函数\n * @example\n * emitter.on('click', (x, y) => {\n * console.log(`Clicked at (${x}, ${y})`);\n * });\n */\n on<K extends keyof E>(event: K, listener: EmitterListener<E, K>) {\n const listeners = this.#events.get(event);\n if (listeners) {\n listeners.add(listener);\n } else {\n this.#events.set(event, new Set([listener]));\n }\n }\n\n /**\n * 注册事件监听器,仅触发一次\n * @param event - 要监听的事件名称\n * @param listener - 事件监听器函数\n * @example\n * emitter.once('click', (x, y) => {\n * console.log(`Clicked at (${x}, ${y})`);\n * });\n */\n once<K extends keyof E>(event: K, listener: EmitterListener<E, K>) {\n const onceListener = (...payloads: Parameters<EmitterListener<E, K>>) => {\n const result = listener(...payloads);\n this.off(event, onceListener);\n return result;\n };\n this.on(event, onceListener);\n }\n\n /**\n * 移除事件监听器,有三种使用方式:\n * 1. 移除特定事件的特定监听器\n * 2. 移除特定事件的所有监听器\n * 3. 移除所有事件的所有监听器\n * @param event - 要移除的事件名称(可选)\n * @param listener - 要移除的监听器函数(可选)\n * @example\n * // 移除特定事件的特定监听器\n * emitter.off('click', clickHandler);\n *\n * // 移除特定事件的所有监听器\n * emitter.off('click');\n *\n * // 移除所有事件的所有监听器\n * emitter.off();\n */\n off<K extends keyof E>(event?: K, listener?: EmitterListener<E, K>) {\n if (event && listener) {\n this.#offListener(event, listener);\n } else if (event) {\n this.#offEvent(event);\n } else {\n this.#offAll();\n }\n }\n\n #offAll() {\n this.#events.clear();\n }\n\n #offEvent<K extends keyof E>(event: K) {\n this.#events.delete(event);\n }\n\n #offListener<K extends keyof E>(event: K, listener: EmitterListener<E, K>) {\n const listeners = this.#events.get(event);\n\n if (listeners) {\n listeners.delete(listener);\n }\n }\n\n /**\n * 触发指定事件,调用所有注册的监听器\n * @param event - 要触发的事件名称\n * @param payloads - 传递给监听器的参数\n * @remarks\n * 监听器会按照注册的顺序依次执行,如果某个监听器返回 false,\n * 则后续监听器将不会被执行\n * @example\n * emitter.emit('click', 10, 20);\n */\n emit<K extends keyof E>(\n event: K,\n ...payloads: Parameters<EmitterListener<E, K>>\n ) {\n const listeners = this.#events.get(event) as\n | Set<EmitterListener<E, K>>\n | undefined;\n\n if (!listeners) return;\n\n // 避免在 emit、on 的过程中改变 listeners 从而影响本次 emit\n for (const listener of [...listeners]) {\n if (listener(...payloads) === false) {\n break;\n }\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAgCA,IAAa,UAAb,MAEE;CACA,0BAA0C,IAAI,KAAK;;;;;;;;;;CAWnD,GAAsB,OAAU,UAAiC;EAC/D,MAAM,YAAY,KAAKA,QAAQ,IAAI,MAAM;EACzC,IAAI,WACF,UAAU,IAAI,SAAS;OAEvB,KAAKA,QAAQ,IAAI,OAAO,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC;;;;;;;;;;;CAahD,KAAwB,OAAU,UAAiC;EACjE,MAAM,gBAAgB,GAAG,aAAgD;GACvE,MAAM,SAAS,SAAS,GAAG,SAAS;GACpC,KAAK,IAAI,OAAO,aAAa;GAC7B,OAAO;;EAET,KAAK,GAAG,OAAO,aAAa;;;;;;;;;;;;;;;;;;;CAoB9B,IAAuB,OAAW,UAAkC;EAClE,IAAI,SAAS,UACX,KAAKC,aAAa,OAAO,SAAS;OAC7B,IAAI,OACT,KAAKC,UAAU,MAAM;OAErB,KAAKC,SAAS;;CAIlB,UAAU;EACR,KAAKH,QAAQ,OAAO;;CAGtB,UAA6B,OAAU;EACrC,KAAKA,QAAQ,OAAO,MAAM;;CAG5B,aAAgC,OAAU,UAAiC;EACzE,MAAM,YAAY,KAAKA,QAAQ,IAAI,MAAM;EAEzC,IAAI,WACF,UAAU,OAAO,SAAS;;;;;;;;;;;;CAc9B,KACE,OACA,GAAG,UACH;EACA,MAAM,YAAY,KAAKA,QAAQ,IAAI,MAAM;EAIzC,IAAI,CAAC,WAAW;EAGhB,KAAK,MAAM,YAAY,CAAC,GAAG,UAAU,EACnC,IAAI,SAAS,GAAG,SAAS,KAAK,OAC5B"}
|
package/dist/emitter.mjs
CHANGED
|
@@ -1,98 +1,102 @@
|
|
|
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
|
-
|
|
1
|
+
//#region src/emitter.ts
|
|
2
|
+
/**
|
|
3
|
+
* 事件发射器类,用于管理事件监听和触发
|
|
4
|
+
* @template E - 事件类型映射
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* type MyEvents = {
|
|
8
|
+
* 'click': [x: number, y: number];
|
|
9
|
+
* 'change': [value: string];
|
|
10
|
+
* };
|
|
11
|
+
*
|
|
12
|
+
* const emitter = new Emitter<MyEvents>();
|
|
13
|
+
* emitter.on('click', (x, y) => {
|
|
14
|
+
* console.log(`Clicked at (${x}, ${y})`);
|
|
15
|
+
* });
|
|
16
|
+
* emitter.emit('click', 10, 20);
|
|
17
|
+
*/
|
|
18
|
+
var Emitter = class {
|
|
19
|
+
#events = /* @__PURE__ */ new Map();
|
|
20
|
+
/**
|
|
21
|
+
* 注册事件监听器
|
|
22
|
+
* @param event - 要监听的事件名称
|
|
23
|
+
* @param listener - 事件监听器函数
|
|
24
|
+
* @example
|
|
25
|
+
* emitter.on('click', (x, y) => {
|
|
26
|
+
* console.log(`Clicked at (${x}, ${y})`);
|
|
27
|
+
* });
|
|
28
|
+
*/
|
|
29
|
+
on(event, listener) {
|
|
30
|
+
const listeners = this.#events.get(event);
|
|
31
|
+
if (listeners) listeners.add(listener);
|
|
32
|
+
else this.#events.set(event, new Set([listener]));
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* 注册事件监听器,仅触发一次
|
|
36
|
+
* @param event - 要监听的事件名称
|
|
37
|
+
* @param listener - 事件监听器函数
|
|
38
|
+
* @example
|
|
39
|
+
* emitter.once('click', (x, y) => {
|
|
40
|
+
* console.log(`Clicked at (${x}, ${y})`);
|
|
41
|
+
* });
|
|
42
|
+
*/
|
|
43
|
+
once(event, listener) {
|
|
44
|
+
const onceListener = (...payloads) => {
|
|
45
|
+
const result = listener(...payloads);
|
|
46
|
+
this.off(event, onceListener);
|
|
47
|
+
return result;
|
|
48
|
+
};
|
|
49
|
+
this.on(event, onceListener);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* 移除事件监听器,有三种使用方式:
|
|
53
|
+
* 1. 移除特定事件的特定监听器
|
|
54
|
+
* 2. 移除特定事件的所有监听器
|
|
55
|
+
* 3. 移除所有事件的所有监听器
|
|
56
|
+
* @param event - 要移除的事件名称(可选)
|
|
57
|
+
* @param listener - 要移除的监听器函数(可选)
|
|
58
|
+
* @example
|
|
59
|
+
* // 移除特定事件的特定监听器
|
|
60
|
+
* emitter.off('click', clickHandler);
|
|
61
|
+
*
|
|
62
|
+
* // 移除特定事件的所有监听器
|
|
63
|
+
* emitter.off('click');
|
|
64
|
+
*
|
|
65
|
+
* // 移除所有事件的所有监听器
|
|
66
|
+
* emitter.off();
|
|
67
|
+
*/
|
|
68
|
+
off(event, listener) {
|
|
69
|
+
if (event && listener) this.#offListener(event, listener);
|
|
70
|
+
else if (event) this.#offEvent(event);
|
|
71
|
+
else this.#offAll();
|
|
72
|
+
}
|
|
73
|
+
#offAll() {
|
|
74
|
+
this.#events.clear();
|
|
75
|
+
}
|
|
76
|
+
#offEvent(event) {
|
|
77
|
+
this.#events.delete(event);
|
|
78
|
+
}
|
|
79
|
+
#offListener(event, listener) {
|
|
80
|
+
const listeners = this.#events.get(event);
|
|
81
|
+
if (listeners) listeners.delete(listener);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* 触发指定事件,调用所有注册的监听器
|
|
85
|
+
* @param event - 要触发的事件名称
|
|
86
|
+
* @param payloads - 传递给监听器的参数
|
|
87
|
+
* @remarks
|
|
88
|
+
* 监听器会按照注册的顺序依次执行,如果某个监听器返回 false,
|
|
89
|
+
* 则后续监听器将不会被执行
|
|
90
|
+
* @example
|
|
91
|
+
* emitter.emit('click', 10, 20);
|
|
92
|
+
*/
|
|
93
|
+
emit(event, ...payloads) {
|
|
94
|
+
const listeners = this.#events.get(event);
|
|
95
|
+
if (!listeners) return;
|
|
96
|
+
for (const listener of [...listeners]) if (listener(...payloads) === false) break;
|
|
97
|
+
}
|
|
97
98
|
};
|
|
98
|
-
//#
|
|
99
|
+
//#endregion
|
|
100
|
+
export { Emitter };
|
|
101
|
+
|
|
102
|
+
//# sourceMappingURL=emitter.mjs.map
|
package/dist/emitter.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"emitter.mjs","sources":["../src/emitter.ts"],"sourcesContent":["import type { AnyFunction
|
|
1
|
+
{"version":3,"file":"emitter.mjs","names":["#events","#offListener","#offEvent","#offAll"],"sources":["../src/emitter.ts"],"sourcesContent":["import type { AnyFunction } from './types';\n\n/**\n * 事件类型映射,key 为事件名称,value 为事件参数类型数组\n */\nexport type EmitterMap = Record<string, unknown[]>;\n\n/**\n * 事件监听器函数类型\n * @template E - EmitterMap 类型\n * @template K - 事件名称类型\n */\nexport type EmitterListener<E extends EmitterMap, K extends keyof E> = (\n ...payloads: E[K]\n) => false | unknown;\n\n/**\n * 事件发射器类,用于管理事件监听和触发\n * @template E - 事件类型映射\n *\n * @example\n * type MyEvents = {\n * 'click': [x: number, y: number];\n * 'change': [value: string];\n * };\n *\n * const emitter = new Emitter<MyEvents>();\n * emitter.on('click', (x, y) => {\n * console.log(`Clicked at (${x}, ${y})`);\n * });\n * emitter.emit('click', 10, 20);\n */\nexport class Emitter<\n E extends EmitterMap = Record<string | symbol, unknown[]>,\n> {\n #events: Map<keyof E, Set<AnyFunction>> = new Map();\n\n /**\n * 注册事件监听器\n * @param event - 要监听的事件名称\n * @param listener - 事件监听器函数\n * @example\n * emitter.on('click', (x, y) => {\n * console.log(`Clicked at (${x}, ${y})`);\n * });\n */\n on<K extends keyof E>(event: K, listener: EmitterListener<E, K>) {\n const listeners = this.#events.get(event);\n if (listeners) {\n listeners.add(listener);\n } else {\n this.#events.set(event, new Set([listener]));\n }\n }\n\n /**\n * 注册事件监听器,仅触发一次\n * @param event - 要监听的事件名称\n * @param listener - 事件监听器函数\n * @example\n * emitter.once('click', (x, y) => {\n * console.log(`Clicked at (${x}, ${y})`);\n * });\n */\n once<K extends keyof E>(event: K, listener: EmitterListener<E, K>) {\n const onceListener = (...payloads: Parameters<EmitterListener<E, K>>) => {\n const result = listener(...payloads);\n this.off(event, onceListener);\n return result;\n };\n this.on(event, onceListener);\n }\n\n /**\n * 移除事件监听器,有三种使用方式:\n * 1. 移除特定事件的特定监听器\n * 2. 移除特定事件的所有监听器\n * 3. 移除所有事件的所有监听器\n * @param event - 要移除的事件名称(可选)\n * @param listener - 要移除的监听器函数(可选)\n * @example\n * // 移除特定事件的特定监听器\n * emitter.off('click', clickHandler);\n *\n * // 移除特定事件的所有监听器\n * emitter.off('click');\n *\n * // 移除所有事件的所有监听器\n * emitter.off();\n */\n off<K extends keyof E>(event?: K, listener?: EmitterListener<E, K>) {\n if (event && listener) {\n this.#offListener(event, listener);\n } else if (event) {\n this.#offEvent(event);\n } else {\n this.#offAll();\n }\n }\n\n #offAll() {\n this.#events.clear();\n }\n\n #offEvent<K extends keyof E>(event: K) {\n this.#events.delete(event);\n }\n\n #offListener<K extends keyof E>(event: K, listener: EmitterListener<E, K>) {\n const listeners = this.#events.get(event);\n\n if (listeners) {\n listeners.delete(listener);\n }\n }\n\n /**\n * 触发指定事件,调用所有注册的监听器\n * @param event - 要触发的事件名称\n * @param payloads - 传递给监听器的参数\n * @remarks\n * 监听器会按照注册的顺序依次执行,如果某个监听器返回 false,\n * 则后续监听器将不会被执行\n * @example\n * emitter.emit('click', 10, 20);\n */\n emit<K extends keyof E>(\n event: K,\n ...payloads: Parameters<EmitterListener<E, K>>\n ) {\n const listeners = this.#events.get(event) as\n | Set<EmitterListener<E, K>>\n | undefined;\n\n if (!listeners) return;\n\n // 避免在 emit、on 的过程中改变 listeners 从而影响本次 emit\n for (const listener of [...listeners]) {\n if (listener(...payloads) === false) {\n break;\n }\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAgCA,IAAa,UAAb,MAEE;CACA,0BAA0C,IAAI,KAAK;;;;;;;;;;CAWnD,GAAsB,OAAU,UAAiC;EAC/D,MAAM,YAAY,KAAKA,QAAQ,IAAI,MAAM;EACzC,IAAI,WACF,UAAU,IAAI,SAAS;OAEvB,KAAKA,QAAQ,IAAI,OAAO,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC;;;;;;;;;;;CAahD,KAAwB,OAAU,UAAiC;EACjE,MAAM,gBAAgB,GAAG,aAAgD;GACvE,MAAM,SAAS,SAAS,GAAG,SAAS;GACpC,KAAK,IAAI,OAAO,aAAa;GAC7B,OAAO;;EAET,KAAK,GAAG,OAAO,aAAa;;;;;;;;;;;;;;;;;;;CAoB9B,IAAuB,OAAW,UAAkC;EAClE,IAAI,SAAS,UACX,KAAKC,aAAa,OAAO,SAAS;OAC7B,IAAI,OACT,KAAKC,UAAU,MAAM;OAErB,KAAKC,SAAS;;CAIlB,UAAU;EACR,KAAKH,QAAQ,OAAO;;CAGtB,UAA6B,OAAU;EACrC,KAAKA,QAAQ,OAAO,MAAM;;CAG5B,aAAgC,OAAU,UAAiC;EACzE,MAAM,YAAY,KAAKA,QAAQ,IAAI,MAAM;EAEzC,IAAI,WACF,UAAU,OAAO,SAAS;;;;;;;;;;;;CAc9B,KACE,OACA,GAAG,UACH;EACA,MAAM,YAAY,KAAKA,QAAQ,IAAI,MAAM;EAIzC,IAAI,CAAC,WAAW;EAGhB,KAAK,MAAM,YAAY,CAAC,GAAG,UAAU,EACnC,IAAI,SAAS,GAAG,SAAS,KAAK,OAC5B"}
|
package/dist/env.cjs
CHANGED
|
@@ -1,28 +1,62 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const
|
|
2
|
+
const require_type = require("./type.cjs");
|
|
3
|
+
//#region src/env.ts
|
|
4
|
+
/**
|
|
5
|
+
* 判断当前环境是否为浏览器环境
|
|
6
|
+
* @returns 如果是浏览器环境返回 true,否则返回 false
|
|
7
|
+
*/
|
|
4
8
|
function isBrowser() {
|
|
5
|
-
|
|
9
|
+
return typeof window !== "undefined" && typeof document !== "undefined";
|
|
6
10
|
}
|
|
11
|
+
/**
|
|
12
|
+
* 判断当前环境是否为 Node.js 环境
|
|
13
|
+
* @returns 如果是 Node.js 环境返回 true,否则返回 false
|
|
14
|
+
*/
|
|
7
15
|
function isNode() {
|
|
8
|
-
|
|
16
|
+
return typeof process !== "undefined" && !require_type.isNullish(process.versions) && !require_type.isNullish(process.versions.node);
|
|
9
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* 判断当前环境是否为 Web Worker 环境
|
|
20
|
+
* @returns 如果是 Web Worker 环境返回 true,否则返回 false
|
|
21
|
+
* @remarks
|
|
22
|
+
* 使用 @ts-expect-error 忽略 self 的类型检查,因为 self 在 Web Worker 中可用但在其他环境中可能未定义
|
|
23
|
+
*/
|
|
10
24
|
function isWorker() {
|
|
11
|
-
|
|
25
|
+
return typeof self !== "undefined" && self.importScripts != null;
|
|
12
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* 判断当前操作系统是否为 macOS
|
|
29
|
+
* @returns 如果是 macOS 返回 true,否则返回 false
|
|
30
|
+
* @remarks
|
|
31
|
+
* 在浏览器环境中通过 navigator.platform 检测,在 Node.js 环境中通过 process.platform 检测
|
|
32
|
+
*/
|
|
13
33
|
function isMacOS() {
|
|
14
|
-
|
|
34
|
+
return isBrowser() ? /^mac/i.test(navigator.platform) : isNode() ? /^darwin/i.test(process.platform) : false;
|
|
15
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* 判断当前操作系统是否为 Linux
|
|
38
|
+
* @returns 如果是 Linux 返回 true,否则返回 false
|
|
39
|
+
* @remarks
|
|
40
|
+
* 在浏览器环境中通过 navigator.platform 检测,在 Node.js 环境中通过 process.platform 检测
|
|
41
|
+
*/
|
|
16
42
|
function isLinux() {
|
|
17
|
-
|
|
43
|
+
return isBrowser() ? /^linux/i.test(navigator.platform) : isNode() ? /^linux/i.test(process.platform) : false;
|
|
18
44
|
}
|
|
45
|
+
/**
|
|
46
|
+
* 判断当前操作系统是否为 Windows
|
|
47
|
+
* @returns 如果是 Windows 返回 true,否则返回 false
|
|
48
|
+
* @remarks
|
|
49
|
+
* 在浏览器环境中通过 navigator.platform 检测,在 Node.js 环境中通过 process.platform 检测
|
|
50
|
+
*/
|
|
19
51
|
function isWindows() {
|
|
20
|
-
|
|
52
|
+
return isBrowser() ? /^win/i.test(navigator.platform) : isNode() ? /^win/i.test(process.platform) : false;
|
|
21
53
|
}
|
|
54
|
+
//#endregion
|
|
22
55
|
exports.isBrowser = isBrowser;
|
|
23
56
|
exports.isLinux = isLinux;
|
|
24
57
|
exports.isMacOS = isMacOS;
|
|
25
58
|
exports.isNode = isNode;
|
|
26
59
|
exports.isWindows = isWindows;
|
|
27
60
|
exports.isWorker = isWorker;
|
|
28
|
-
|
|
61
|
+
|
|
62
|
+
//# sourceMappingURL=env.cjs.map
|
package/dist/env.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"env.cjs","sources":["../src/env.ts"],"sourcesContent":["import { isNullish } from './type';\n\n/**\n * 判断当前环境是否为浏览器环境\n * @returns 如果是浏览器环境返回 true,否则返回 false\n */\nexport function isBrowser() {\n if (IS_TEST) return TEST_MOCK.IS_BROWSER || false;\n\n return typeof window !== 'undefined' && typeof document !== 'undefined';\n}\n\n/**\n * 判断当前环境是否为 Node.js 环境\n * @returns 如果是 Node.js 环境返回 true,否则返回 false\n */\nexport function isNode() {\n if (IS_TEST) return TEST_MOCK.IS_NODE || false;\n\n return typeof process !== 'undefined'
|
|
1
|
+
{"version":3,"file":"env.cjs","names":[],"sources":["../src/env.ts"],"sourcesContent":["import { isNullish } from './type';\n\n/**\n * 判断当前环境是否为浏览器环境\n * @returns 如果是浏览器环境返回 true,否则返回 false\n */\nexport function isBrowser() {\n if (IS_TEST) return TEST_MOCK.IS_BROWSER || false;\n\n return typeof window !== 'undefined' && typeof document !== 'undefined';\n}\n\n/**\n * 判断当前环境是否为 Node.js 环境\n * @returns 如果是 Node.js 环境返回 true,否则返回 false\n */\nexport function isNode() {\n if (IS_TEST) return TEST_MOCK.IS_NODE || false;\n\n return (\n typeof process !== 'undefined' &&\n !isNullish(process.versions) &&\n !isNullish(process.versions.node)\n );\n}\n\n/**\n * 判断当前环境是否为 Web Worker 环境\n * @returns 如果是 Web Worker 环境返回 true,否则返回 false\n * @remarks\n * 使用 @ts-expect-error 忽略 self 的类型检查,因为 self 在 Web Worker 中可用但在其他环境中可能未定义\n */\nexport function isWorker() {\n // @ts-expect-error\n return typeof self !== 'undefined' && self.importScripts != null;\n}\n\n/**\n * 判断当前操作系统是否为 macOS\n * @returns 如果是 macOS 返回 true,否则返回 false\n * @remarks\n * 在浏览器环境中通过 navigator.platform 检测,在 Node.js 环境中通过 process.platform 检测\n */\nexport function isMacOS() {\n return isBrowser()\n ? /^mac/i.test(navigator.platform)\n : isNode()\n ? /^darwin/i.test(process.platform)\n : false;\n}\n\n/**\n * 判断当前操作系统是否为 Linux\n * @returns 如果是 Linux 返回 true,否则返回 false\n * @remarks\n * 在浏览器环境中通过 navigator.platform 检测,在 Node.js 环境中通过 process.platform 检测\n */\nexport function isLinux() {\n return isBrowser()\n ? /^linux/i.test(navigator.platform)\n : isNode()\n ? /^linux/i.test(process.platform)\n : false;\n}\n\n/**\n * 判断当前操作系统是否为 Windows\n * @returns 如果是 Windows 返回 true,否则返回 false\n * @remarks\n * 在浏览器环境中通过 navigator.platform 检测,在 Node.js 环境中通过 process.platform 检测\n */\nexport function isWindows() {\n return isBrowser()\n ? /^win/i.test(navigator.platform)\n : isNode()\n ? /^win/i.test(process.platform)\n : false;\n}\n"],"mappings":";;;;;;;AAMA,SAAgB,YAAY;CAG1B,OAAO,OAAO,WAAW,eAAe,OAAO,aAAa;;;;;;AAO9D,SAAgB,SAAS;CAGvB,OACE,OAAO,YAAY,eACnB,CAAC,aAAA,UAAU,QAAQ,SAAS,IAC5B,CAAC,aAAA,UAAU,QAAQ,SAAS,KAAK;;;;;;;;AAUrC,SAAgB,WAAW;CAEzB,OAAO,OAAO,SAAS,eAAe,KAAK,iBAAiB;;;;;;;;AAS9D,SAAgB,UAAU;CACxB,OAAO,WAAW,GACd,QAAQ,KAAK,UAAU,SAAS,GAChC,QAAQ,GACN,WAAW,KAAK,QAAQ,SAAS,GACjC;;;;;;;;AASR,SAAgB,UAAU;CACxB,OAAO,WAAW,GACd,UAAU,KAAK,UAAU,SAAS,GAClC,QAAQ,GACN,UAAU,KAAK,QAAQ,SAAS,GAChC;;;;;;;;AASR,SAAgB,YAAY;CAC1B,OAAO,WAAW,GACd,QAAQ,KAAK,UAAU,SAAS,GAChC,QAAQ,GACN,QAAQ,KAAK,QAAQ,SAAS,GAC9B"}
|
package/dist/env.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ export declare function isNode(): boolean;
|
|
|
12
12
|
* 判断当前环境是否为 Web Worker 环境
|
|
13
13
|
* @returns 如果是 Web Worker 环境返回 true,否则返回 false
|
|
14
14
|
* @remarks
|
|
15
|
-
* 使用 @ts-
|
|
15
|
+
* 使用 @ts-expect-error 忽略 self 的类型检查,因为 self 在 Web Worker 中可用但在其他环境中可能未定义
|
|
16
16
|
*/
|
|
17
17
|
export declare function isWorker(): boolean;
|
|
18
18
|
/**
|
package/dist/env.mjs
CHANGED
|
@@ -1,28 +1,56 @@
|
|
|
1
1
|
import { isNullish } from "./type.mjs";
|
|
2
|
+
//#region src/env.ts
|
|
3
|
+
/**
|
|
4
|
+
* 判断当前环境是否为浏览器环境
|
|
5
|
+
* @returns 如果是浏览器环境返回 true,否则返回 false
|
|
6
|
+
*/
|
|
2
7
|
function isBrowser() {
|
|
3
|
-
|
|
8
|
+
return typeof window !== "undefined" && typeof document !== "undefined";
|
|
4
9
|
}
|
|
10
|
+
/**
|
|
11
|
+
* 判断当前环境是否为 Node.js 环境
|
|
12
|
+
* @returns 如果是 Node.js 环境返回 true,否则返回 false
|
|
13
|
+
*/
|
|
5
14
|
function isNode() {
|
|
6
|
-
|
|
15
|
+
return typeof process !== "undefined" && !isNullish(process.versions) && !isNullish(process.versions.node);
|
|
7
16
|
}
|
|
17
|
+
/**
|
|
18
|
+
* 判断当前环境是否为 Web Worker 环境
|
|
19
|
+
* @returns 如果是 Web Worker 环境返回 true,否则返回 false
|
|
20
|
+
* @remarks
|
|
21
|
+
* 使用 @ts-expect-error 忽略 self 的类型检查,因为 self 在 Web Worker 中可用但在其他环境中可能未定义
|
|
22
|
+
*/
|
|
8
23
|
function isWorker() {
|
|
9
|
-
|
|
24
|
+
return typeof self !== "undefined" && self.importScripts != null;
|
|
10
25
|
}
|
|
26
|
+
/**
|
|
27
|
+
* 判断当前操作系统是否为 macOS
|
|
28
|
+
* @returns 如果是 macOS 返回 true,否则返回 false
|
|
29
|
+
* @remarks
|
|
30
|
+
* 在浏览器环境中通过 navigator.platform 检测,在 Node.js 环境中通过 process.platform 检测
|
|
31
|
+
*/
|
|
11
32
|
function isMacOS() {
|
|
12
|
-
|
|
33
|
+
return isBrowser() ? /^mac/i.test(navigator.platform) : isNode() ? /^darwin/i.test(process.platform) : false;
|
|
13
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* 判断当前操作系统是否为 Linux
|
|
37
|
+
* @returns 如果是 Linux 返回 true,否则返回 false
|
|
38
|
+
* @remarks
|
|
39
|
+
* 在浏览器环境中通过 navigator.platform 检测,在 Node.js 环境中通过 process.platform 检测
|
|
40
|
+
*/
|
|
14
41
|
function isLinux() {
|
|
15
|
-
|
|
42
|
+
return isBrowser() ? /^linux/i.test(navigator.platform) : isNode() ? /^linux/i.test(process.platform) : false;
|
|
16
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* 判断当前操作系统是否为 Windows
|
|
46
|
+
* @returns 如果是 Windows 返回 true,否则返回 false
|
|
47
|
+
* @remarks
|
|
48
|
+
* 在浏览器环境中通过 navigator.platform 检测,在 Node.js 环境中通过 process.platform 检测
|
|
49
|
+
*/
|
|
17
50
|
function isWindows() {
|
|
18
|
-
|
|
51
|
+
return isBrowser() ? /^win/i.test(navigator.platform) : isNode() ? /^win/i.test(process.platform) : false;
|
|
19
52
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
isNode,
|
|
25
|
-
isWindows,
|
|
26
|
-
isWorker
|
|
27
|
-
};
|
|
28
|
-
//# sourceMappingURL=env.mjs.map
|
|
53
|
+
//#endregion
|
|
54
|
+
export { isBrowser, isLinux, isMacOS, isNode, isWindows, isWorker };
|
|
55
|
+
|
|
56
|
+
//# sourceMappingURL=env.mjs.map
|