tiny-essentials 1.26.2 → 1.26.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/1/26/3.md +4 -0
- package/changelog/1/26/4.md +10 -0
- package/dist/v1/TinyAdvancedRaffle.min.js +1 -1
- package/dist/v1/TinyClassManager.min.js +1 -1
- package/dist/v1/TinyEssentials.min.js +1 -1
- package/dist/v1/TinyEvents.min.js +1 -1
- package/dist/v1/TinyIframeEvents.min.js +1 -1
- package/dist/v1/TinyLocalStorage.min.js +1 -1
- package/dist/v1/TinyNewWinEvents.min.js +1 -1
- package/dist/v1/TinySmartScroller.min.js +1 -1
- package/dist/v1/TinyUploadClicker.min.js +1 -1
- package/dist/v1/basics/text.cjs +17 -0
- package/dist/v1/basics/text.d.mts +17 -0
- package/dist/v1/basics/text.mjs +17 -0
- package/dist/v1/css/aiMarker.min.css +1 -1
- package/dist/v1/libs/TinyClassManager.cjs +87 -16
- package/dist/v1/libs/TinyClassManager.d.mts +11 -1
- package/dist/v1/libs/TinyClassManager.mjs +71 -15
- package/dist/v1/libs/TinyEvents.cjs +7 -0
- package/dist/v1/libs/TinyEvents.d.mts +4 -0
- package/dist/v1/libs/TinyEvents.mjs +6 -0
- package/dist/v1/libs/examples/TinyClassManager.cjs +43 -41
- package/dist/v1/libs/examples/TinyClassManager.mjs +37 -37
- package/docs/v1/libs/TinyClassManager.md +69 -70
- package/docs/v1/libs/TinyEvents.md +1 -1
- package/package.json +1 -1
package/dist/v1/basics/text.cjs
CHANGED
|
@@ -73,6 +73,23 @@ function toTitleCaseLowerFirst(str) {
|
|
|
73
73
|
* If executed outside of a browser environment (e.g., in Node.js), the function logs an error and exits.
|
|
74
74
|
* If the `<body>` is not available at the moment the shortcut is triggered, a warning is logged.
|
|
75
75
|
*
|
|
76
|
+
* -------------------------------------------------
|
|
77
|
+
*
|
|
78
|
+
* Any content wrapped inside an `<ai>example</ai>` or `<span class="made-by-ai"></span>` tag was generated purely by artificial intelligence,
|
|
79
|
+
* without any direct or indirect human intervention during the content generation process.
|
|
80
|
+
*
|
|
81
|
+
* -------------------------------------------------
|
|
82
|
+
*
|
|
83
|
+
* Any content wrapped inside a `<semi-ai>example</semi-ai>` or `<span class="made-by-semi-ai"></span>` tag was partially generated by artificial
|
|
84
|
+
* intelligence. In this case, the context of the message was fully shaped by a human source guiding how the content should be written (i.e.,
|
|
85
|
+
* transforming a purely human text into a polished version enhanced by AI).
|
|
86
|
+
*
|
|
87
|
+
* These texts are characterized as improved versions of original human work, where the AI is strictly utilized to enhance the
|
|
88
|
+
* structure of a human-written text. This tag does **not** apply to texts translated by AI (or any other non-AI translation tools),
|
|
89
|
+
* nor does it apply to scenarios where an AI minimally refines an existing text by acting solely as a spell checker or basic grammar corrector.
|
|
90
|
+
*
|
|
91
|
+
* -------------------------------------------------
|
|
92
|
+
*
|
|
76
93
|
* @param {Object} [config={}] - Configuration object.
|
|
77
94
|
* @param {string} [config.key='a'] - The lowercase character key to be used in combination with `Ctrl` and `Alt`.
|
|
78
95
|
* @param {string} [config.className='detect-made-by-ai'] - The CSS class to toggle on the `<body>` element.
|
|
@@ -44,6 +44,23 @@ export function toTitleCaseLowerFirst(str: string): string;
|
|
|
44
44
|
* If executed outside of a browser environment (e.g., in Node.js), the function logs an error and exits.
|
|
45
45
|
* If the `<body>` is not available at the moment the shortcut is triggered, a warning is logged.
|
|
46
46
|
*
|
|
47
|
+
* -------------------------------------------------
|
|
48
|
+
*
|
|
49
|
+
* Any content wrapped inside an `<ai>example</ai>` or `<span class="made-by-ai"></span>` tag was generated purely by artificial intelligence,
|
|
50
|
+
* without any direct or indirect human intervention during the content generation process.
|
|
51
|
+
*
|
|
52
|
+
* -------------------------------------------------
|
|
53
|
+
*
|
|
54
|
+
* Any content wrapped inside a `<semi-ai>example</semi-ai>` or `<span class="made-by-semi-ai"></span>` tag was partially generated by artificial
|
|
55
|
+
* intelligence. In this case, the context of the message was fully shaped by a human source guiding how the content should be written (i.e.,
|
|
56
|
+
* transforming a purely human text into a polished version enhanced by AI).
|
|
57
|
+
*
|
|
58
|
+
* These texts are characterized as improved versions of original human work, where the AI is strictly utilized to enhance the
|
|
59
|
+
* structure of a human-written text. This tag does **not** apply to texts translated by AI (or any other non-AI translation tools),
|
|
60
|
+
* nor does it apply to scenarios where an AI minimally refines an existing text by acting solely as a spell checker or basic grammar corrector.
|
|
61
|
+
*
|
|
62
|
+
* -------------------------------------------------
|
|
63
|
+
*
|
|
47
64
|
* @param {Object} [config={}] - Configuration object.
|
|
48
65
|
* @param {string} [config.key='a'] - The lowercase character key to be used in combination with `Ctrl` and `Alt`.
|
|
49
66
|
* @param {string} [config.className='detect-made-by-ai'] - The CSS class to toggle on the `<body>` element.
|
package/dist/v1/basics/text.mjs
CHANGED
|
@@ -62,6 +62,23 @@ export function toTitleCaseLowerFirst(str) {
|
|
|
62
62
|
* If executed outside of a browser environment (e.g., in Node.js), the function logs an error and exits.
|
|
63
63
|
* If the `<body>` is not available at the moment the shortcut is triggered, a warning is logged.
|
|
64
64
|
*
|
|
65
|
+
* -------------------------------------------------
|
|
66
|
+
*
|
|
67
|
+
* Any content wrapped inside an `<ai>example</ai>` or `<span class="made-by-ai"></span>` tag was generated purely by artificial intelligence,
|
|
68
|
+
* without any direct or indirect human intervention during the content generation process.
|
|
69
|
+
*
|
|
70
|
+
* -------------------------------------------------
|
|
71
|
+
*
|
|
72
|
+
* Any content wrapped inside a `<semi-ai>example</semi-ai>` or `<span class="made-by-semi-ai"></span>` tag was partially generated by artificial
|
|
73
|
+
* intelligence. In this case, the context of the message was fully shaped by a human source guiding how the content should be written (i.e.,
|
|
74
|
+
* transforming a purely human text into a polished version enhanced by AI).
|
|
75
|
+
*
|
|
76
|
+
* These texts are characterized as improved versions of original human work, where the AI is strictly utilized to enhance the
|
|
77
|
+
* structure of a human-written text. This tag does **not** apply to texts translated by AI (or any other non-AI translation tools),
|
|
78
|
+
* nor does it apply to scenarios where an AI minimally refines an existing text by acting solely as a spell checker or basic grammar corrector.
|
|
79
|
+
*
|
|
80
|
+
* -------------------------------------------------
|
|
81
|
+
*
|
|
65
82
|
* @param {Object} [config={}] - Configuration object.
|
|
66
83
|
* @param {string} [config.key='a'] - The lowercase character key to be used in combination with `Ctrl` and `Alt`.
|
|
67
84
|
* @param {string} [config.className='detect-made-by-ai'] - The CSS class to toggle on the `<body>` element.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
body.detect-made-by-ai .made-by-ai{
|
|
1
|
+
:root{--ai-text-color: yellow;--semi-ai-text-color: deepskyblue;--ai-text-shadow-color: #000}ai,semi-ai{display:inline}body.detect-made-by-ai .made-by-ai,body.detect-made-by-ai .made-by-semi-ai,body.detect-made-by-ai ai,body.detect-made-by-ai semi-ai{text-shadow:-1px -1px 0 var(--ai-text-shadow-color),1px -1px 0 var(--ai-text-shadow-color),-1px 1px 0 var(--ai-text-shadow-color),1px 1px 0 var(--ai-text-shadow-color)}body.detect-made-by-ai .made-by-ai,body.detect-made-by-ai ai{color:var(--ai-text-color)}body.detect-made-by-ai .made-by-semi-ai,body.detect-made-by-ai semi-ai{color:var(--semi-ai-text-color)}
|
|
@@ -70,40 +70,111 @@ class TinyClassManager {
|
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
/**
|
|
73
|
-
*
|
|
73
|
+
* Internal helper to validate dependencies, check conflicts, and transition state.
|
|
74
74
|
* @template {new (...args: any[]) => any} R
|
|
75
|
-
* @param {
|
|
76
|
-
* @
|
|
77
|
-
* @
|
|
75
|
+
* @param {string} name - The plugin name.
|
|
76
|
+
* @param {string[]} deps - The plugin dependencies.
|
|
77
|
+
* @param {R} ExtendedClass - The newly extended class returned by the apply function.
|
|
78
|
+
* @returns {TinyClassManager<R>} A new manager instance.
|
|
78
79
|
*/
|
|
79
|
-
|
|
80
|
+
#validateAndTransition(name, deps, ExtendedClass) {
|
|
81
|
+
// Verifies if the current manager has already been consumed to prevent branching.
|
|
80
82
|
if (this.#used) throw new Error(`[TinyClassManager] Cannot reuse a consumed manager instance.`);
|
|
81
|
-
if (this.#appliedPlugins.has(plugin.name))
|
|
82
|
-
throw new Error(`[TinyClassManager] Plugin conflict: "${plugin.name}" is already installed.`);
|
|
83
83
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
*/
|
|
88
|
-
const deps = plugin.dependencies || [];
|
|
84
|
+
// Checks if the plugin being inserted is already in the applied list.
|
|
85
|
+
if (this.#appliedPlugins.has(name))
|
|
86
|
+
throw new Error(`[TinyClassManager] Plugin conflict: "${name}" is already installed.`);
|
|
89
87
|
|
|
90
88
|
for (const dep of deps) {
|
|
91
89
|
if (!this.#appliedPlugins.has(dep)) {
|
|
92
90
|
throw new Error(
|
|
93
|
-
`[TinyClassManager] Missing Dependency: "${
|
|
91
|
+
`[TinyClassManager] Missing Dependency: "${name}" requires "${dep}" to be installed first.`,
|
|
94
92
|
);
|
|
95
93
|
}
|
|
96
94
|
}
|
|
97
95
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
96
|
+
/**
|
|
97
|
+
* @type {TinyClassManager<R>}
|
|
98
|
+
* The next manager instance wrapping the newly extended class chain.
|
|
99
|
+
*/
|
|
100
|
+
const newClassManager = new TinyClassManager(ExtendedClass);
|
|
101
|
+
|
|
102
|
+
this.#appliedPlugins.forEach((appliedName) => newClassManager.#appliedPlugins.add(appliedName));
|
|
103
|
+
newClassManager.#appliedPlugins.add(name);
|
|
101
104
|
|
|
102
105
|
this.#used = true;
|
|
103
106
|
this.#appliedPlugins.clear();
|
|
107
|
+
|
|
104
108
|
return newClassManager;
|
|
105
109
|
}
|
|
106
110
|
|
|
111
|
+
/**
|
|
112
|
+
* Applies a plugin to the class chain using a definition object.
|
|
113
|
+
* @deprecated Use {@link insert} instead.
|
|
114
|
+
* @template {new (...args: any[]) => any} R
|
|
115
|
+
* @param {PluginDefinition<T, R>} plugin - The plugin module to be integrated.
|
|
116
|
+
* @returns {TinyClassManager<R>} A new manager instance holding the extended class chain.
|
|
117
|
+
* @throws {Error} Throws if instance is already consumed, plugin is duplicate, or dependencies are missing.
|
|
118
|
+
*/
|
|
119
|
+
use(plugin) {
|
|
120
|
+
/**
|
|
121
|
+
* @type {string[]}
|
|
122
|
+
* Extracted dependencies array with fallback for undefined properties.
|
|
123
|
+
*/
|
|
124
|
+
const deps = plugin.dependencies || [];
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* @type {R}
|
|
128
|
+
* The new class generated by the old object-style apply wrapper.
|
|
129
|
+
*/
|
|
130
|
+
const ExtendedClass = plugin.apply(this.#currentClass);
|
|
131
|
+
|
|
132
|
+
return this.#validateAndTransition(plugin.name, deps, ExtendedClass);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Inserts a plugin directly by passing its apply function.
|
|
137
|
+
* It reads `_tinyDepName` and `_tinyDeps` statically from the returned class.
|
|
138
|
+
* @template {new (...args: any[]) => any} R
|
|
139
|
+
* @param {function(T): R} applyFn - Function that receives the base class and returns the extended class.
|
|
140
|
+
* @returns {TinyClassManager<R>} A new manager instance holding the extended class chain.
|
|
141
|
+
* @throws {Error} Throws if static properties are missing, instance is consumed, or validation fails.
|
|
142
|
+
*/
|
|
143
|
+
insert(applyFn) {
|
|
144
|
+
/** * @type {R}
|
|
145
|
+
* The extended class returned directly from the provided function.
|
|
146
|
+
*/
|
|
147
|
+
const ExtendedClass = applyFn(this.#currentClass);
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* @type {string}
|
|
151
|
+
* The plugin name extracted from the static property.
|
|
152
|
+
*/
|
|
153
|
+
// @ts-ignore
|
|
154
|
+
const pluginName = ExtendedClass._tinyDepName;
|
|
155
|
+
|
|
156
|
+
if (!pluginName) {
|
|
157
|
+
throw new Error(
|
|
158
|
+
`[TinyClassManager] Plugin class must define a static '_tinyDepName' property.`,
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* @type {string[]}
|
|
164
|
+
* The dependencies extracted from the static property, defaulting to an empty array.
|
|
165
|
+
*/
|
|
166
|
+
// @ts-ignore
|
|
167
|
+
const deps = ExtendedClass._tinyDeps ?? [];
|
|
168
|
+
|
|
169
|
+
if (!Array.isArray(deps) || !deps.every((name) => typeof name === 'string')) {
|
|
170
|
+
throw new Error(
|
|
171
|
+
`[TinyClassManager] Plugin class must define a static array of strings in '_tinyDepName' property.`,
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
return this.#validateAndTransition(pluginName, deps, ExtendedClass);
|
|
176
|
+
}
|
|
177
|
+
|
|
107
178
|
/**
|
|
108
179
|
* Finalizes the composition and returns the fully built class.
|
|
109
180
|
* @returns {T} The final class representing the last extended version in the chain.
|
|
@@ -50,13 +50,23 @@ declare class TinyClassManager<T extends new (...args: any[]) => any> {
|
|
|
50
50
|
*/
|
|
51
51
|
get used(): boolean;
|
|
52
52
|
/**
|
|
53
|
-
* Applies a plugin to the class chain
|
|
53
|
+
* Applies a plugin to the class chain using a definition object.
|
|
54
|
+
* @deprecated Use {@link insert} instead.
|
|
54
55
|
* @template {new (...args: any[]) => any} R
|
|
55
56
|
* @param {PluginDefinition<T, R>} plugin - The plugin module to be integrated.
|
|
56
57
|
* @returns {TinyClassManager<R>} A new manager instance holding the extended class chain.
|
|
57
58
|
* @throws {Error} Throws if instance is already consumed, plugin is duplicate, or dependencies are missing.
|
|
58
59
|
*/
|
|
59
60
|
use<R extends new (...args: any[]) => any>(plugin: PluginDefinition<T, R>): TinyClassManager<R>;
|
|
61
|
+
/**
|
|
62
|
+
* Inserts a plugin directly by passing its apply function.
|
|
63
|
+
* It reads `_tinyDepName` and `_tinyDeps` statically from the returned class.
|
|
64
|
+
* @template {new (...args: any[]) => any} R
|
|
65
|
+
* @param {function(T): R} applyFn - Function that receives the base class and returns the extended class.
|
|
66
|
+
* @returns {TinyClassManager<R>} A new manager instance holding the extended class chain.
|
|
67
|
+
* @throws {Error} Throws if static properties are missing, instance is consumed, or validation fails.
|
|
68
|
+
*/
|
|
69
|
+
insert<R extends new (...args: any[]) => any>(applyFn: (arg0: T) => R): TinyClassManager<R>;
|
|
60
70
|
/**
|
|
61
71
|
* Finalizes the composition and returns the fully built class.
|
|
62
72
|
* @returns {T} The final class representing the last extended version in the chain.
|
|
@@ -59,33 +59,89 @@ class TinyClassManager {
|
|
|
59
59
|
this.#currentClass = coreClass;
|
|
60
60
|
}
|
|
61
61
|
/**
|
|
62
|
-
*
|
|
62
|
+
* Internal helper to validate dependencies, check conflicts, and transition state.
|
|
63
|
+
* @template {new (...args: any[]) => any} R
|
|
64
|
+
* @param {string} name - The plugin name.
|
|
65
|
+
* @param {string[]} deps - The plugin dependencies.
|
|
66
|
+
* @param {R} ExtendedClass - The newly extended class returned by the apply function.
|
|
67
|
+
* @returns {TinyClassManager<R>} A new manager instance.
|
|
68
|
+
*/
|
|
69
|
+
#validateAndTransition(name, deps, ExtendedClass) {
|
|
70
|
+
// Verifies if the current manager has already been consumed to prevent branching.
|
|
71
|
+
if (this.#used)
|
|
72
|
+
throw new Error(`[TinyClassManager] Cannot reuse a consumed manager instance.`);
|
|
73
|
+
// Checks if the plugin being inserted is already in the applied list.
|
|
74
|
+
if (this.#appliedPlugins.has(name))
|
|
75
|
+
throw new Error(`[TinyClassManager] Plugin conflict: "${name}" is already installed.`);
|
|
76
|
+
for (const dep of deps) {
|
|
77
|
+
if (!this.#appliedPlugins.has(dep)) {
|
|
78
|
+
throw new Error(`[TinyClassManager] Missing Dependency: "${name}" requires "${dep}" to be installed first.`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* @type {TinyClassManager<R>}
|
|
83
|
+
* The next manager instance wrapping the newly extended class chain.
|
|
84
|
+
*/
|
|
85
|
+
const newClassManager = new TinyClassManager(ExtendedClass);
|
|
86
|
+
this.#appliedPlugins.forEach((appliedName) => newClassManager.#appliedPlugins.add(appliedName));
|
|
87
|
+
newClassManager.#appliedPlugins.add(name);
|
|
88
|
+
this.#used = true;
|
|
89
|
+
this.#appliedPlugins.clear();
|
|
90
|
+
return newClassManager;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Applies a plugin to the class chain using a definition object.
|
|
94
|
+
* @deprecated Use {@link insert} instead.
|
|
63
95
|
* @template {new (...args: any[]) => any} R
|
|
64
96
|
* @param {PluginDefinition<T, R>} plugin - The plugin module to be integrated.
|
|
65
97
|
* @returns {TinyClassManager<R>} A new manager instance holding the extended class chain.
|
|
66
98
|
* @throws {Error} Throws if instance is already consumed, plugin is duplicate, or dependencies are missing.
|
|
67
99
|
*/
|
|
68
100
|
use(plugin) {
|
|
69
|
-
if (this.#used)
|
|
70
|
-
throw new Error(`[TinyClassManager] Cannot reuse a consumed manager instance.`);
|
|
71
|
-
if (this.#appliedPlugins.has(plugin.name))
|
|
72
|
-
throw new Error(`[TinyClassManager] Plugin conflict: "${plugin.name}" is already installed.`);
|
|
73
101
|
/**
|
|
74
102
|
* @type {string[]}
|
|
75
103
|
* Extracted dependencies array with fallback for undefined properties.
|
|
76
104
|
*/
|
|
77
105
|
const deps = plugin.dependencies || [];
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
106
|
+
/**
|
|
107
|
+
* @type {R}
|
|
108
|
+
* The new class generated by the old object-style apply wrapper.
|
|
109
|
+
*/
|
|
110
|
+
const ExtendedClass = plugin.apply(this.#currentClass);
|
|
111
|
+
return this.#validateAndTransition(plugin.name, deps, ExtendedClass);
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Inserts a plugin directly by passing its apply function.
|
|
115
|
+
* It reads `_tinyDepName` and `_tinyDeps` statically from the returned class.
|
|
116
|
+
* @template {new (...args: any[]) => any} R
|
|
117
|
+
* @param {function(T): R} applyFn - Function that receives the base class and returns the extended class.
|
|
118
|
+
* @returns {TinyClassManager<R>} A new manager instance holding the extended class chain.
|
|
119
|
+
* @throws {Error} Throws if static properties are missing, instance is consumed, or validation fails.
|
|
120
|
+
*/
|
|
121
|
+
insert(applyFn) {
|
|
122
|
+
/** * @type {R}
|
|
123
|
+
* The extended class returned directly from the provided function.
|
|
124
|
+
*/
|
|
125
|
+
const ExtendedClass = applyFn(this.#currentClass);
|
|
126
|
+
/**
|
|
127
|
+
* @type {string}
|
|
128
|
+
* The plugin name extracted from the static property.
|
|
129
|
+
*/
|
|
130
|
+
// @ts-ignore
|
|
131
|
+
const pluginName = ExtendedClass._tinyDepName;
|
|
132
|
+
if (!pluginName) {
|
|
133
|
+
throw new Error(`[TinyClassManager] Plugin class must define a static '_tinyDepName' property.`);
|
|
82
134
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
135
|
+
/**
|
|
136
|
+
* @type {string[]}
|
|
137
|
+
* The dependencies extracted from the static property, defaulting to an empty array.
|
|
138
|
+
*/
|
|
139
|
+
// @ts-ignore
|
|
140
|
+
const deps = ExtendedClass._tinyDeps ?? [];
|
|
141
|
+
if (!Array.isArray(deps) || !deps.every((name) => typeof name === 'string')) {
|
|
142
|
+
throw new Error(`[TinyClassManager] Plugin class must define a static array of strings in '_tinyDepName' property.`);
|
|
143
|
+
}
|
|
144
|
+
return this.#validateAndTransition(pluginName, deps, ExtendedClass);
|
|
89
145
|
}
|
|
90
146
|
/**
|
|
91
147
|
* Finalizes the composition and returns the fully built class.
|
|
@@ -264,6 +264,13 @@ class TinyEvents {
|
|
|
264
264
|
this.#listeners.clear();
|
|
265
265
|
}
|
|
266
266
|
|
|
267
|
+
/**
|
|
268
|
+
* Removes all event listeners of all types from the element.
|
|
269
|
+
*/
|
|
270
|
+
removeAllListeners() {
|
|
271
|
+
return this.offAllTypes();
|
|
272
|
+
}
|
|
273
|
+
|
|
267
274
|
/////////////////////////////////////////////
|
|
268
275
|
|
|
269
276
|
/**
|
|
@@ -101,6 +101,10 @@ declare class TinyEvents {
|
|
|
101
101
|
* Removes all event listeners of all types from the element.
|
|
102
102
|
*/
|
|
103
103
|
offAllTypes(): void;
|
|
104
|
+
/**
|
|
105
|
+
* Removes all event listeners of all types from the element.
|
|
106
|
+
*/
|
|
107
|
+
removeAllListeners(): void;
|
|
104
108
|
/**
|
|
105
109
|
* Returns the number of listeners for a given event.
|
|
106
110
|
*
|
|
@@ -244,6 +244,12 @@ class TinyEvents {
|
|
|
244
244
|
offAllTypes() {
|
|
245
245
|
this.#listeners.clear();
|
|
246
246
|
}
|
|
247
|
+
/**
|
|
248
|
+
* Removes all event listeners of all types from the element.
|
|
249
|
+
*/
|
|
250
|
+
removeAllListeners() {
|
|
251
|
+
return this.offAllTypes();
|
|
252
|
+
}
|
|
247
253
|
/////////////////////////////////////////////
|
|
248
254
|
/**
|
|
249
255
|
* Returns the number of listeners for a given event.
|
|
@@ -15,57 +15,59 @@ class EntityCore {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
// 2. Creating Dependent DLCs
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
/** @param {string} id */
|
|
25
|
-
constructor(id) {
|
|
26
|
-
super(id);
|
|
27
|
-
this.hp = 100;
|
|
28
|
-
}
|
|
18
|
+
/** @param {typeof EntityCore} Base */
|
|
19
|
+
const applyHealth = (Base) =>
|
|
20
|
+
class HealthModule extends Base {
|
|
21
|
+
static _tinyDepName = 'Health';
|
|
22
|
+
/** @type {string[]} */
|
|
23
|
+
static _tinyDeps = []; // No dependencies, works just with the Core
|
|
29
24
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
25
|
+
/** @param {string} id */
|
|
26
|
+
constructor(id) {
|
|
27
|
+
super(id);
|
|
28
|
+
this.hp = 100;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Deducts health from the entity.
|
|
33
|
+
* @param {number} amount - The amount of raw damage to deal.
|
|
34
|
+
*/
|
|
35
|
+
takeDamage(amount) {
|
|
36
|
+
this.hp -= amount;
|
|
37
|
+
console.log(`Took ${amount} damage. HP left: ${this.hp}`);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
40
|
|
|
41
41
|
// 3. Creating Independent DLCs
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
42
|
+
/** @param {ReturnType<typeof applyHealth>} Base */
|
|
43
|
+
const applyArmor = (Base) =>
|
|
44
|
+
class ArmorModule extends Base {
|
|
45
|
+
static _tinyDepName = 'Armor';
|
|
46
|
+
static _tinyDeps = ['Health']; // Strictly requires the Health module to be installed first
|
|
47
|
+
|
|
48
|
+
/** @param {string} id */
|
|
49
|
+
constructor(id) {
|
|
50
|
+
super(id);
|
|
51
|
+
this.armor = 50;
|
|
52
|
+
}
|
|
53
53
|
|
|
54
|
+
/**
|
|
55
|
+
* Deducts health, factoring in damage mitigation provided by armor.
|
|
56
|
+
* @param {number} amount - The initial damage before armor reduction.
|
|
57
|
+
*/
|
|
58
|
+
takeDamage(amount) {
|
|
54
59
|
/**
|
|
55
|
-
*
|
|
56
|
-
* @param {number} amount - The initial damage before armor reduction.
|
|
60
|
+
* Calculated damage after armor mitigation is applied, ensuring it never drops below 0.
|
|
57
61
|
*/
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
},
|
|
63
|
-
};
|
|
62
|
+
const reducedDamage = Math.max(0, amount - this.armor * 0.1);
|
|
63
|
+
super.takeDamage(reducedDamage);
|
|
64
|
+
}
|
|
65
|
+
};
|
|
64
66
|
|
|
65
67
|
// 4. Building the final class
|
|
66
68
|
try {
|
|
67
69
|
const CoreTest = new TinyClassManager(EntityCore);
|
|
68
|
-
const FullyArmoredEntity = CoreTest.
|
|
70
|
+
const FullyArmoredEntity = CoreTest.insert(applyHealth).insert(applyArmor).build();
|
|
69
71
|
|
|
70
72
|
const myEntity = new FullyArmoredEntity('Player_1');
|
|
71
73
|
myEntity.takeDamage(30);
|
|
@@ -10,51 +10,51 @@ class EntityCore {
|
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
12
|
// 2. Creating Dependent DLCs
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
/** @
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
},
|
|
13
|
+
/** @param {typeof EntityCore} Base */
|
|
14
|
+
const applyHealth = (Base) => class HealthModule extends Base {
|
|
15
|
+
static _tinyDepName = 'Health';
|
|
16
|
+
/** @type {string[]} */
|
|
17
|
+
static _tinyDeps = []; // No dependencies, works just with the Core
|
|
18
|
+
/** @param {string} id */
|
|
19
|
+
constructor(id) {
|
|
20
|
+
super(id);
|
|
21
|
+
this.hp = 100;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Deducts health from the entity.
|
|
25
|
+
* @param {number} amount - The amount of raw damage to deal.
|
|
26
|
+
*/
|
|
27
|
+
takeDamage(amount) {
|
|
28
|
+
this.hp -= amount;
|
|
29
|
+
console.log(`Took ${amount} damage. HP left: ${this.hp}`);
|
|
30
|
+
}
|
|
32
31
|
};
|
|
33
32
|
// 3. Creating Independent DLCs
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
33
|
+
/** @param {ReturnType<typeof applyHealth>} Base */
|
|
34
|
+
const applyArmor = (Base) => class ArmorModule extends Base {
|
|
35
|
+
static _tinyDepName = 'Armor';
|
|
36
|
+
static _tinyDeps = ['Health']; // Strictly requires the Health module to be installed first
|
|
37
|
+
/** @param {string} id */
|
|
38
|
+
constructor(id) {
|
|
39
|
+
super(id);
|
|
40
|
+
this.armor = 50;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Deducts health, factoring in damage mitigation provided by armor.
|
|
44
|
+
* @param {number} amount - The initial damage before armor reduction.
|
|
45
|
+
*/
|
|
46
|
+
takeDamage(amount) {
|
|
44
47
|
/**
|
|
45
|
-
*
|
|
46
|
-
* @param {number} amount - The initial damage before armor reduction.
|
|
48
|
+
* Calculated damage after armor mitigation is applied, ensuring it never drops below 0.
|
|
47
49
|
*/
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
52
|
-
},
|
|
50
|
+
const reducedDamage = Math.max(0, amount - this.armor * 0.1);
|
|
51
|
+
super.takeDamage(reducedDamage);
|
|
52
|
+
}
|
|
53
53
|
};
|
|
54
54
|
// 4. Building the final class
|
|
55
55
|
try {
|
|
56
56
|
const CoreTest = new TinyClassManager(EntityCore);
|
|
57
|
-
const FullyArmoredEntity = CoreTest.
|
|
57
|
+
const FullyArmoredEntity = CoreTest.insert(applyHealth).insert(applyArmor).build();
|
|
58
58
|
const myEntity = new FullyArmoredEntity('Player_1');
|
|
59
59
|
myEntity.takeDamage(30);
|
|
60
60
|
console.log(`Armor value: ${myEntity.armor}`);
|