tiny-essentials 1.26.1 β 1.26.3
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/changelog/1/26/2.md +10 -0
- package/changelog/1/26/3.md +4 -0
- package/dist/v1/TinyClassManager.min.js +1 -0
- package/dist/v1/TinyEssentials.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/build/TinyClassManager.cjs +7 -0
- package/dist/v1/build/TinyClassManager.d.mts +3 -0
- package/dist/v1/build/TinyClassManager.mjs +2 -0
- package/dist/v1/css/aiMarker.min.css +1 -1
- package/dist/v1/index.cjs +2 -0
- package/dist/v1/index.d.mts +2 -1
- package/dist/v1/index.mjs +2 -1
- package/dist/v1/libs/TinyClassManager.cjs +121 -0
- package/dist/v1/libs/TinyClassManager.d.mts +68 -0
- package/dist/v1/libs/TinyClassManager.mjs +103 -0
- package/dist/v1/libs/examples/TinyClassManager.cjs +76 -0
- package/dist/v1/libs/examples/TinyClassManager.d.mts +2 -0
- package/dist/v1/libs/examples/TinyClassManager.mjs +66 -0
- package/docs/v1/README.md +10 -5
- package/docs/v1/libs/TinyClassManager.md +174 -0
- package/package.json +5 -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)}
|
package/dist/v1/index.cjs
CHANGED
|
@@ -51,6 +51,7 @@ var TinyAnalogClock = require('./libs/TinyAnalogClock.cjs');
|
|
|
51
51
|
var TinyTextDiffer = require('./libs/TinyTextDiffer.cjs');
|
|
52
52
|
var TinyArrayComparator = require('./libs/TinyArrayComparator.cjs');
|
|
53
53
|
var TinyMamdaniInferenceSystem = require('./libs/TinyMamdaniInferenceSystem.cjs');
|
|
54
|
+
var TinyClassManager = require('./libs/TinyClassManager.cjs');
|
|
54
55
|
|
|
55
56
|
|
|
56
57
|
|
|
@@ -186,3 +187,4 @@ exports.FuzzySet = TinyMamdaniInferenceSystem.FuzzySet;
|
|
|
186
187
|
exports.MamdaniInferenceSystem = TinyMamdaniInferenceSystem.MamdaniInferenceSystem;
|
|
187
188
|
exports.defuzzifyCentroid = TinyMamdaniInferenceSystem.defuzzifyCentroid;
|
|
188
189
|
exports.trapezoid = TinyMamdaniInferenceSystem.trapezoid;
|
|
190
|
+
exports.TinyClassManager = TinyClassManager;
|
package/dist/v1/index.d.mts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import TinyClassManager from './libs/TinyClassManager.mjs';
|
|
1
2
|
import { FuzzySet } from './libs/TinyMamdaniInferenceSystem.mjs';
|
|
2
3
|
import { MamdaniInferenceSystem } from './libs/TinyMamdaniInferenceSystem.mjs';
|
|
3
4
|
import TinyArrayComparator from './libs/TinyArrayComparator.mjs';
|
|
@@ -130,5 +131,5 @@ import { getTimeDuration } from './basics/clock.mjs';
|
|
|
130
131
|
import { shuffleArray } from './basics/array.mjs';
|
|
131
132
|
import { toTitleCase } from './basics/text.mjs';
|
|
132
133
|
import { toTitleCaseLowerFirst } from './basics/text.mjs';
|
|
133
|
-
export { FuzzySet, MamdaniInferenceSystem, TinyArrayComparator, TinyTextDiffer, TinyAnalogClock, TinyColorValidator, TinyLoadingScreen, TinyElementObserver, TinySimpleDice, TinyNeedBar, TinyI18, TinyCookieConsent, TinyInventory, TinyInventoryTrader, TinyArrayPaginator, TinyAdvancedRaffle, TinyDayNightCycle, TinyGamepad, TinyTextarea, TinyNewWinEvents, TinyIframeEvents, TinyLocalStorage, TinyEvents, TinyTimeout, TinyColorConverter, TinyClipboard, TinyTextRangeEditor, TinySmartScroller, UltraRandomMsgGen, TinyAfterScrollWatcher, TinyHtml, TinyNotifications, TinyDomReadyManager, TinyDragger, TinyDragDropDetector, TinyToastNotify, TinyNotifyCenter, TinyRateLimiter, ColorSafeStringify, TinyPromiseQueue, TinyLevelUp, defuzzifyCentroid, trapezoid, diffArrayList, diffStrings, breakdownDuration, calculateMarketcap, compareMarketcap, getPercentage, areElsCollTop, areElsCollBottom, areElsCollLeft, areElsCollRight, areElsCollPerfTop, areElsCollPerfBottom, areElsCollPerfLeft, areElsCollPerfRight, areElsColliding, areElsPerfColliding, getElsColliding, getElsPerfColliding, getElsCollOverlap, getElsCollOverlapPos, getRectCenter, getElsRelativeCenterOffset, getElsCollDirDepth, getElsCollDetails, safeTextTrim, installWindowHiddenScript, genFibonacciSeq, isDirEmptyAsync, fileSizeAsync, dirSizeAsync, listFilesAsync, listDirsAsync, getLatestBackupPath, fetchJson, fetchText, readJsonBlob, readFileBlob, readBase64Blob, saveJsonFile, readJsonFile, writeJsonFile, ensureDirectory, clearDirectoryAsync, clearDirectory, fileExists, dirExists, isDirEmpty, ensureCopyFile, tryDeleteFile, writeTextFile, listFiles, listDirs, fileSize, dirSize, backupFile, restoreLatestBackup, renameFileBatch, renameFileRegex, renameFileAddPrefixSuffix, renameFileNormalizeCase, renameFilePadNumbers, documentIsFullScreen, isScreenFilled, requestFullScreen, exitFullScreen, isFullScreenMode, onFullScreenChange, offFullScreenChange, isJsonObject, arraySortPositions, formatBytes, addAiMarkerShortcut, extendObjType, reorderObjTypeOrder, cloneObjTypeOrder, countObj, checkObj, objType, ruleOfThree, getSimplePerc, asyncReplace, getAge, formatCustomTimer, formatDayTimer, formatTimer, getTimeDuration, shuffleArray, toTitleCase, toTitleCaseLowerFirst };
|
|
134
|
+
export { TinyClassManager, FuzzySet, MamdaniInferenceSystem, TinyArrayComparator, TinyTextDiffer, TinyAnalogClock, TinyColorValidator, TinyLoadingScreen, TinyElementObserver, TinySimpleDice, TinyNeedBar, TinyI18, TinyCookieConsent, TinyInventory, TinyInventoryTrader, TinyArrayPaginator, TinyAdvancedRaffle, TinyDayNightCycle, TinyGamepad, TinyTextarea, TinyNewWinEvents, TinyIframeEvents, TinyLocalStorage, TinyEvents, TinyTimeout, TinyColorConverter, TinyClipboard, TinyTextRangeEditor, TinySmartScroller, UltraRandomMsgGen, TinyAfterScrollWatcher, TinyHtml, TinyNotifications, TinyDomReadyManager, TinyDragger, TinyDragDropDetector, TinyToastNotify, TinyNotifyCenter, TinyRateLimiter, ColorSafeStringify, TinyPromiseQueue, TinyLevelUp, defuzzifyCentroid, trapezoid, diffArrayList, diffStrings, breakdownDuration, calculateMarketcap, compareMarketcap, getPercentage, areElsCollTop, areElsCollBottom, areElsCollLeft, areElsCollRight, areElsCollPerfTop, areElsCollPerfBottom, areElsCollPerfLeft, areElsCollPerfRight, areElsColliding, areElsPerfColliding, getElsColliding, getElsPerfColliding, getElsCollOverlap, getElsCollOverlapPos, getRectCenter, getElsRelativeCenterOffset, getElsCollDirDepth, getElsCollDetails, safeTextTrim, installWindowHiddenScript, genFibonacciSeq, isDirEmptyAsync, fileSizeAsync, dirSizeAsync, listFilesAsync, listDirsAsync, getLatestBackupPath, fetchJson, fetchText, readJsonBlob, readFileBlob, readBase64Blob, saveJsonFile, readJsonFile, writeJsonFile, ensureDirectory, clearDirectoryAsync, clearDirectory, fileExists, dirExists, isDirEmpty, ensureCopyFile, tryDeleteFile, writeTextFile, listFiles, listDirs, fileSize, dirSize, backupFile, restoreLatestBackup, renameFileBatch, renameFileRegex, renameFileAddPrefixSuffix, renameFileNormalizeCase, renameFilePadNumbers, documentIsFullScreen, isScreenFilled, requestFullScreen, exitFullScreen, isFullScreenMode, onFullScreenChange, offFullScreenChange, isJsonObject, arraySortPositions, formatBytes, addAiMarkerShortcut, extendObjType, reorderObjTypeOrder, cloneObjTypeOrder, countObj, checkObj, objType, ruleOfThree, getSimplePerc, asyncReplace, getAge, formatCustomTimer, formatDayTimer, formatTimer, getTimeDuration, shuffleArray, toTitleCase, toTitleCaseLowerFirst };
|
|
134
135
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/v1/index.mjs
CHANGED
|
@@ -49,7 +49,8 @@ import TinyAnalogClock from './libs/TinyAnalogClock.mjs';
|
|
|
49
49
|
import TinyTextDiffer from './libs/TinyTextDiffer.mjs';
|
|
50
50
|
import TinyArrayComparator from './libs/TinyArrayComparator.mjs';
|
|
51
51
|
import { FuzzySet, MamdaniInferenceSystem, trapezoid, defuzzifyCentroid, } from './libs/TinyMamdaniInferenceSystem.mjs';
|
|
52
|
+
import TinyClassManager from './libs/TinyClassManager.mjs';
|
|
52
53
|
// import TinyHtmlElems from './libs/TinyHtml/index.mjs';
|
|
53
|
-
export { FuzzySet, MamdaniInferenceSystem, TinyArrayComparator, TinyTextDiffer, TinyAnalogClock,
|
|
54
|
+
export { TinyClassManager, FuzzySet, MamdaniInferenceSystem, TinyArrayComparator, TinyTextDiffer, TinyAnalogClock,
|
|
54
55
|
// TinyHtmlElems,
|
|
55
56
|
TinyColorValidator, TinyLoadingScreen, TinyElementObserver, TinySimpleDice, TinyNeedBar, TinyI18, TinyCookieConsent, TinyInventory, TinyInventoryTrader, TinyArrayPaginator, TinyAdvancedRaffle, TinyDayNightCycle, TinyGamepad, TinyTextarea, TinyNewWinEvents, TinyIframeEvents, TinyLocalStorage, TinyEvents, TinyTimeout, TinyColorConverter, TinyClipboard, TinyTextRangeEditor, TinySmartScroller, UltraRandomMsgGen, TinyAfterScrollWatcher, TinyHtml, TinyNotifications, TinyDomReadyManager, TinyDragger, TinyDragDropDetector, TinyToastNotify, TinyNotifyCenter, TinyRateLimiter, ColorSafeStringify, TinyPromiseQueue, TinyLevelUp, defuzzifyCentroid, trapezoid, diffArrayList, diffStrings, breakdownDuration, calculateMarketcap, compareMarketcap, getPercentage, areElsCollTop, areElsCollBottom, areElsCollLeft, areElsCollRight, areElsCollPerfTop, areElsCollPerfBottom, areElsCollPerfLeft, areElsCollPerfRight, areElsColliding, areElsPerfColliding, getElsColliding, getElsPerfColliding, getElsCollOverlap, getElsCollOverlapPos, getRectCenter, getElsRelativeCenterOffset, getElsCollDirDepth, getElsCollDetails, safeTextTrim, installWindowHiddenScript, genFibonacciSeq, isDirEmptyAsync, fileSizeAsync, dirSizeAsync, listFilesAsync, listDirsAsync, getLatestBackupPath, fetchJson, fetchText, readJsonBlob, readFileBlob, readBase64Blob, saveJsonFile, readJsonFile, writeJsonFile, ensureDirectory, clearDirectoryAsync, clearDirectory, fileExists, dirExists, isDirEmpty, ensureCopyFile, tryDeleteFile, writeTextFile, listFiles, listDirs, fileSize, dirSize, backupFile, restoreLatestBackup, renameFileBatch, renameFileRegex, renameFileAddPrefixSuffix, renameFileNormalizeCase, renameFilePadNumbers, documentIsFullScreen, isScreenFilled, requestFullScreen, exitFullScreen, isFullScreenMode, onFullScreenChange, offFullScreenChange, isJsonObject, arraySortPositions, formatBytes, addAiMarkerShortcut, extendObjType, reorderObjTypeOrder, cloneObjTypeOrder, countObj, checkObj, objType, ruleOfThree, getSimplePerc, asyncReplace, getAge, formatCustomTimer, formatDayTimer, formatTimer, getTimeDuration, shuffleArray, toTitleCase, toTitleCaseLowerFirst, };
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @template {new (...args: any[]) => any} TBase
|
|
5
|
+
* @template {new (...args: any[]) => any} TExtended
|
|
6
|
+
* @typedef {Object} PluginDefinition
|
|
7
|
+
* @property {string} name - The unique identifier for the plugin.
|
|
8
|
+
* @property {string[]} [dependencies] - Array of plugin names required before applying this one.
|
|
9
|
+
* @property {function(TBase): TExtended} apply - Function that receives the base class and returns the extended class.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Manages the composition of a base class with multiple optional plugins (Mixins).
|
|
14
|
+
* @template {new (...args: any[]) => any} T
|
|
15
|
+
*/
|
|
16
|
+
class TinyClassManager {
|
|
17
|
+
/**
|
|
18
|
+
* @type {Set<string>}
|
|
19
|
+
* Tracks the names of successfully applied plugins to prevent duplication and check dependencies.
|
|
20
|
+
*/
|
|
21
|
+
#appliedPlugins = new Set();
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Gets the list of plugins currently applied to this instance.
|
|
25
|
+
* @returns {string[]} Array of applied plugin names.
|
|
26
|
+
*/
|
|
27
|
+
get appliedPlugins() {
|
|
28
|
+
return [...this.#appliedPlugins];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Gets the total size of the current class chain hierarchy.
|
|
33
|
+
* @returns {number} The count of applied plugins plus the core base.
|
|
34
|
+
*/
|
|
35
|
+
get size() {
|
|
36
|
+
return this.#appliedPlugins.size + 1;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* @type {T}
|
|
41
|
+
* Holds the current state of the class chain.
|
|
42
|
+
*/
|
|
43
|
+
#currentClass;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Holds the current state of the class chain.
|
|
47
|
+
*/
|
|
48
|
+
get currentClass() {
|
|
49
|
+
return this.#currentClass;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Protects the instance from being consumed or reused after transition.
|
|
54
|
+
*/
|
|
55
|
+
#used = false;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Protects the instance from being consumed or reused after transition.
|
|
59
|
+
*/
|
|
60
|
+
get used() {
|
|
61
|
+
return this.#used;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Initializes the manager with a core class.
|
|
66
|
+
* @param {T} coreClass - The foundational class to be extended.
|
|
67
|
+
*/
|
|
68
|
+
constructor(coreClass) {
|
|
69
|
+
this.#currentClass = coreClass;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Applies a plugin to the class chain if all conditions are met.
|
|
74
|
+
* @template {new (...args: any[]) => any} R
|
|
75
|
+
* @param {PluginDefinition<T, R>} plugin - The plugin module to be integrated.
|
|
76
|
+
* @returns {TinyClassManager<R>} A new manager instance holding the extended class chain.
|
|
77
|
+
* @throws {Error} Throws if instance is already consumed, plugin is duplicate, or dependencies are missing.
|
|
78
|
+
*/
|
|
79
|
+
use(plugin) {
|
|
80
|
+
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
|
+
|
|
84
|
+
/**
|
|
85
|
+
* @type {string[]}
|
|
86
|
+
* Extracted dependencies array with fallback for undefined properties.
|
|
87
|
+
*/
|
|
88
|
+
const deps = plugin.dependencies || [];
|
|
89
|
+
|
|
90
|
+
for (const dep of deps) {
|
|
91
|
+
if (!this.#appliedPlugins.has(dep)) {
|
|
92
|
+
throw new Error(
|
|
93
|
+
`[TinyClassManager] Missing Dependency: "${plugin.name}" requires "${dep}" to be installed first.`,
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const newClassManager = new TinyClassManager(plugin.apply(this.#currentClass));
|
|
99
|
+
this.#appliedPlugins.forEach((name) => newClassManager.#appliedPlugins.add(name));
|
|
100
|
+
newClassManager.#appliedPlugins.add(plugin.name);
|
|
101
|
+
|
|
102
|
+
this.#used = true;
|
|
103
|
+
this.#appliedPlugins.clear();
|
|
104
|
+
return newClassManager;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Finalizes the composition and returns the fully built class.
|
|
109
|
+
* @returns {T} The final class representing the last extended version in the chain.
|
|
110
|
+
* @throws {Error} Throws if the manager instance has already been used or finalized.
|
|
111
|
+
*/
|
|
112
|
+
build() {
|
|
113
|
+
if (this.#used)
|
|
114
|
+
throw new Error(`[TinyClassManager] Cannot build from an already finalized manager.`);
|
|
115
|
+
this.#used = true;
|
|
116
|
+
this.#appliedPlugins.clear();
|
|
117
|
+
return this.#currentClass;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
module.exports = TinyClassManager;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
export default TinyClassManager;
|
|
2
|
+
export type PluginDefinition<TBase extends new (...args: any[]) => any, TExtended extends new (...args: any[]) => any> = {
|
|
3
|
+
/**
|
|
4
|
+
* - The unique identifier for the plugin.
|
|
5
|
+
*/
|
|
6
|
+
name: string;
|
|
7
|
+
/**
|
|
8
|
+
* - Array of plugin names required before applying this one.
|
|
9
|
+
*/
|
|
10
|
+
dependencies?: string[] | undefined;
|
|
11
|
+
/**
|
|
12
|
+
* - Function that receives the base class and returns the extended class.
|
|
13
|
+
*/
|
|
14
|
+
apply: (arg0: TBase) => TExtended;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* @template {new (...args: any[]) => any} TBase
|
|
18
|
+
* @template {new (...args: any[]) => any} TExtended
|
|
19
|
+
* @typedef {Object} PluginDefinition
|
|
20
|
+
* @property {string} name - The unique identifier for the plugin.
|
|
21
|
+
* @property {string[]} [dependencies] - Array of plugin names required before applying this one.
|
|
22
|
+
* @property {function(TBase): TExtended} apply - Function that receives the base class and returns the extended class.
|
|
23
|
+
*/
|
|
24
|
+
/**
|
|
25
|
+
* Manages the composition of a base class with multiple optional plugins (Mixins).
|
|
26
|
+
* @template {new (...args: any[]) => any} T
|
|
27
|
+
*/
|
|
28
|
+
declare class TinyClassManager<T extends new (...args: any[]) => any> {
|
|
29
|
+
/**
|
|
30
|
+
* Initializes the manager with a core class.
|
|
31
|
+
* @param {T} coreClass - The foundational class to be extended.
|
|
32
|
+
*/
|
|
33
|
+
constructor(coreClass: T);
|
|
34
|
+
/**
|
|
35
|
+
* Gets the list of plugins currently applied to this instance.
|
|
36
|
+
* @returns {string[]} Array of applied plugin names.
|
|
37
|
+
*/
|
|
38
|
+
get appliedPlugins(): string[];
|
|
39
|
+
/**
|
|
40
|
+
* Gets the total size of the current class chain hierarchy.
|
|
41
|
+
* @returns {number} The count of applied plugins plus the core base.
|
|
42
|
+
*/
|
|
43
|
+
get size(): number;
|
|
44
|
+
/**
|
|
45
|
+
* Holds the current state of the class chain.
|
|
46
|
+
*/
|
|
47
|
+
get currentClass(): T;
|
|
48
|
+
/**
|
|
49
|
+
* Protects the instance from being consumed or reused after transition.
|
|
50
|
+
*/
|
|
51
|
+
get used(): boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Applies a plugin to the class chain if all conditions are met.
|
|
54
|
+
* @template {new (...args: any[]) => any} R
|
|
55
|
+
* @param {PluginDefinition<T, R>} plugin - The plugin module to be integrated.
|
|
56
|
+
* @returns {TinyClassManager<R>} A new manager instance holding the extended class chain.
|
|
57
|
+
* @throws {Error} Throws if instance is already consumed, plugin is duplicate, or dependencies are missing.
|
|
58
|
+
*/
|
|
59
|
+
use<R extends new (...args: any[]) => any>(plugin: PluginDefinition<T, R>): TinyClassManager<R>;
|
|
60
|
+
/**
|
|
61
|
+
* Finalizes the composition and returns the fully built class.
|
|
62
|
+
* @returns {T} The final class representing the last extended version in the chain.
|
|
63
|
+
* @throws {Error} Throws if the manager instance has already been used or finalized.
|
|
64
|
+
*/
|
|
65
|
+
build(): T;
|
|
66
|
+
#private;
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=TinyClassManager.d.mts.map
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @template {new (...args: any[]) => any} TBase
|
|
3
|
+
* @template {new (...args: any[]) => any} TExtended
|
|
4
|
+
* @typedef {Object} PluginDefinition
|
|
5
|
+
* @property {string} name - The unique identifier for the plugin.
|
|
6
|
+
* @property {string[]} [dependencies] - Array of plugin names required before applying this one.
|
|
7
|
+
* @property {function(TBase): TExtended} apply - Function that receives the base class and returns the extended class.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Manages the composition of a base class with multiple optional plugins (Mixins).
|
|
11
|
+
* @template {new (...args: any[]) => any} T
|
|
12
|
+
*/
|
|
13
|
+
class TinyClassManager {
|
|
14
|
+
/**
|
|
15
|
+
* @type {Set<string>}
|
|
16
|
+
* Tracks the names of successfully applied plugins to prevent duplication and check dependencies.
|
|
17
|
+
*/
|
|
18
|
+
#appliedPlugins = new Set();
|
|
19
|
+
/**
|
|
20
|
+
* Gets the list of plugins currently applied to this instance.
|
|
21
|
+
* @returns {string[]} Array of applied plugin names.
|
|
22
|
+
*/
|
|
23
|
+
get appliedPlugins() {
|
|
24
|
+
return [...this.#appliedPlugins];
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Gets the total size of the current class chain hierarchy.
|
|
28
|
+
* @returns {number} The count of applied plugins plus the core base.
|
|
29
|
+
*/
|
|
30
|
+
get size() {
|
|
31
|
+
return this.#appliedPlugins.size + 1;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* @type {T}
|
|
35
|
+
* Holds the current state of the class chain.
|
|
36
|
+
*/
|
|
37
|
+
#currentClass;
|
|
38
|
+
/**
|
|
39
|
+
* Holds the current state of the class chain.
|
|
40
|
+
*/
|
|
41
|
+
get currentClass() {
|
|
42
|
+
return this.#currentClass;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Protects the instance from being consumed or reused after transition.
|
|
46
|
+
*/
|
|
47
|
+
#used = false;
|
|
48
|
+
/**
|
|
49
|
+
* Protects the instance from being consumed or reused after transition.
|
|
50
|
+
*/
|
|
51
|
+
get used() {
|
|
52
|
+
return this.#used;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Initializes the manager with a core class.
|
|
56
|
+
* @param {T} coreClass - The foundational class to be extended.
|
|
57
|
+
*/
|
|
58
|
+
constructor(coreClass) {
|
|
59
|
+
this.#currentClass = coreClass;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Applies a plugin to the class chain if all conditions are met.
|
|
63
|
+
* @template {new (...args: any[]) => any} R
|
|
64
|
+
* @param {PluginDefinition<T, R>} plugin - The plugin module to be integrated.
|
|
65
|
+
* @returns {TinyClassManager<R>} A new manager instance holding the extended class chain.
|
|
66
|
+
* @throws {Error} Throws if instance is already consumed, plugin is duplicate, or dependencies are missing.
|
|
67
|
+
*/
|
|
68
|
+
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
|
+
/**
|
|
74
|
+
* @type {string[]}
|
|
75
|
+
* Extracted dependencies array with fallback for undefined properties.
|
|
76
|
+
*/
|
|
77
|
+
const deps = plugin.dependencies || [];
|
|
78
|
+
for (const dep of deps) {
|
|
79
|
+
if (!this.#appliedPlugins.has(dep)) {
|
|
80
|
+
throw new Error(`[TinyClassManager] Missing Dependency: "${plugin.name}" requires "${dep}" to be installed first.`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
const newClassManager = new TinyClassManager(plugin.apply(this.#currentClass));
|
|
84
|
+
this.#appliedPlugins.forEach((name) => newClassManager.#appliedPlugins.add(name));
|
|
85
|
+
newClassManager.#appliedPlugins.add(plugin.name);
|
|
86
|
+
this.#used = true;
|
|
87
|
+
this.#appliedPlugins.clear();
|
|
88
|
+
return newClassManager;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Finalizes the composition and returns the fully built class.
|
|
92
|
+
* @returns {T} The final class representing the last extended version in the chain.
|
|
93
|
+
* @throws {Error} Throws if the manager instance has already been used or finalized.
|
|
94
|
+
*/
|
|
95
|
+
build() {
|
|
96
|
+
if (this.#used)
|
|
97
|
+
throw new Error(`[TinyClassManager] Cannot build from an already finalized manager.`);
|
|
98
|
+
this.#used = true;
|
|
99
|
+
this.#appliedPlugins.clear();
|
|
100
|
+
return this.#currentClass;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
export default TinyClassManager;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var TinyClassManager = require('../TinyClassManager.cjs');
|
|
4
|
+
|
|
5
|
+
// ============================================================================
|
|
6
|
+
// Example & Usage Context
|
|
7
|
+
// ============================================================================
|
|
8
|
+
|
|
9
|
+
// 1. The Core Class (The foundation)
|
|
10
|
+
class EntityCore {
|
|
11
|
+
/** @param {string} id */
|
|
12
|
+
constructor(id) {
|
|
13
|
+
this.id = id;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// 2. Creating Dependent DLCs
|
|
18
|
+
const Health = {
|
|
19
|
+
name: 'Health',
|
|
20
|
+
dependencies: [], // No dependencies, works just with the Core
|
|
21
|
+
/** @param {typeof EntityCore} Base */
|
|
22
|
+
apply: (Base) =>
|
|
23
|
+
class HealthModule extends Base {
|
|
24
|
+
/** @param {string} id */
|
|
25
|
+
constructor(id) {
|
|
26
|
+
super(id);
|
|
27
|
+
this.hp = 100;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Deducts health from the entity.
|
|
32
|
+
* @param {number} amount - The amount of raw damage to deal.
|
|
33
|
+
*/
|
|
34
|
+
takeDamage(amount) {
|
|
35
|
+
this.hp -= amount;
|
|
36
|
+
console.log(`Took ${amount} damage. HP left: ${this.hp}`);
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
// 3. Creating Independent DLCs
|
|
42
|
+
const Armor = {
|
|
43
|
+
name: 'Armor',
|
|
44
|
+
dependencies: ['Health'], // Strictly requires the Health module to be installed first
|
|
45
|
+
/** @param {ReturnType<typeof Health.apply>} Base */
|
|
46
|
+
apply: (Base) =>
|
|
47
|
+
class ArmorModule extends Base {
|
|
48
|
+
/** @param {string} id */
|
|
49
|
+
constructor(id) {
|
|
50
|
+
super(id);
|
|
51
|
+
this.armor = 50;
|
|
52
|
+
}
|
|
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) {
|
|
59
|
+
const reducedDamage = Math.max(0, amount - this.armor * 0.1);
|
|
60
|
+
super.takeDamage(reducedDamage);
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
// 4. Building the final class
|
|
66
|
+
try {
|
|
67
|
+
const CoreTest = new TinyClassManager(EntityCore);
|
|
68
|
+
const FullyArmoredEntity = CoreTest.use(Health).use(Armor).build();
|
|
69
|
+
|
|
70
|
+
const myEntity = new FullyArmoredEntity('Player_1');
|
|
71
|
+
myEntity.takeDamage(30);
|
|
72
|
+
console.log(`Armor value: ${myEntity.armor}`);
|
|
73
|
+
console.log(`Current HP: ${myEntity.hp}`);
|
|
74
|
+
} catch (error) {
|
|
75
|
+
if (error instanceof Error) console.error(error.message);
|
|
76
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import TinyClassManager from '../TinyClassManager.mjs';
|
|
2
|
+
// ============================================================================
|
|
3
|
+
// Example & Usage Context
|
|
4
|
+
// ============================================================================
|
|
5
|
+
// 1. The Core Class (The foundation)
|
|
6
|
+
class EntityCore {
|
|
7
|
+
/** @param {string} id */
|
|
8
|
+
constructor(id) {
|
|
9
|
+
this.id = id;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
// 2. Creating Dependent DLCs
|
|
13
|
+
const Health = {
|
|
14
|
+
name: 'Health',
|
|
15
|
+
dependencies: [], // No dependencies, works just with the Core
|
|
16
|
+
/** @param {typeof EntityCore} Base */
|
|
17
|
+
apply: (Base) => class HealthModule extends Base {
|
|
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
|
+
}
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
// 3. Creating Independent DLCs
|
|
34
|
+
const Armor = {
|
|
35
|
+
name: 'Armor',
|
|
36
|
+
dependencies: ['Health'], // Strictly requires the Health module to be installed first
|
|
37
|
+
/** @param {ReturnType<typeof Health.apply>} Base */
|
|
38
|
+
apply: (Base) => class ArmorModule extends Base {
|
|
39
|
+
/** @param {string} id */
|
|
40
|
+
constructor(id) {
|
|
41
|
+
super(id);
|
|
42
|
+
this.armor = 50;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Deducts health, factoring in damage mitigation provided by armor.
|
|
46
|
+
* @param {number} amount - The initial damage before armor reduction.
|
|
47
|
+
*/
|
|
48
|
+
takeDamage(amount) {
|
|
49
|
+
const reducedDamage = Math.max(0, amount - this.armor * 0.1);
|
|
50
|
+
super.takeDamage(reducedDamage);
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
// 4. Building the final class
|
|
55
|
+
try {
|
|
56
|
+
const CoreTest = new TinyClassManager(EntityCore);
|
|
57
|
+
const FullyArmoredEntity = CoreTest.use(Health).use(Armor).build();
|
|
58
|
+
const myEntity = new FullyArmoredEntity('Player_1');
|
|
59
|
+
myEntity.takeDamage(30);
|
|
60
|
+
console.log(`Armor value: ${myEntity.armor}`);
|
|
61
|
+
console.log(`Current HP: ${myEntity.hp}`);
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
if (error instanceof Error)
|
|
65
|
+
console.error(error.message);
|
|
66
|
+
}
|
package/docs/v1/README.md
CHANGED
|
@@ -8,9 +8,7 @@ Here, you can navigate through different sections of the project. Below are the
|
|
|
8
8
|
|
|
9
9
|
## π Main Directories
|
|
10
10
|
|
|
11
|
-
### 1. **`basics/`**
|
|
12
|
-
|
|
13
|
-
This folder contains the core scripts we have worked on so far. Each file is a module focused on specific functionality.
|
|
11
|
+
### 1. **`basics/`** This folder contains the core scripts we have worked on so far. Each file is a module focused on specific functionality.
|
|
14
12
|
|
|
15
13
|
- π¦ **[Array](./basics/array.md)** β A tiny utility for shuffling arrays using the FisherβYates algorithm.
|
|
16
14
|
- β° **[Clock](./basics/clock.md)** β A versatile time utility module for calculating and formatting time durations.
|
|
@@ -64,6 +62,7 @@ This folder contains the core scripts we have worked on so far. Each file is a m
|
|
|
64
62
|
* π **[TinyAnalogClock](./libs/TinyAnalogClock.md)** β A lightweight analog clock engine for managing time-based rotations, supporting custom offsets, smooth transitions, and easy binding to CSS variables rendering.
|
|
65
63
|
* π **[TinyArrayComparator](./libs/TinyArrayComparator.md)** β A lightweight, highly optimized JavaScript utility class designed to compare two arrays and efficiently detect which items were **added** or **deleted**.
|
|
66
64
|
* π§ **[TinyMamdaniInferenceSystem](./libs/TinyMamdaniInferenceSystem.md)** β A implementation of a Mamdani Inference System, allowing you to model logic using trapezoidal membership functions.
|
|
65
|
+
* βοΈ **[TinyClassManager](./libs/TinyClassManager.md)** β A lightweight, immutable manager designed to linearly compose a base class with multiple modular plugins, featuring automatic dependency verification and duplicate conflict protection.
|
|
67
66
|
|
|
68
67
|
### 3. **`fileManager/`**
|
|
69
68
|
* π **[Main](./fileManager/main.md)** β A Node.js file/directory utility module with support for JSON, backups, renaming, size analysis, and more.
|
|
@@ -72,9 +71,15 @@ This folder contains the core scripts we have worked on so far. Each file is a m
|
|
|
72
71
|
|
|
73
72
|
## π Tip Directories
|
|
74
73
|
|
|
75
|
-
### 1. **`libs/`**
|
|
74
|
+
### 1. **`libs/`** - π§± **[TinyHtml](./libs/TinyHtmlTips.md)** β Usage examples and practical tips.
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## π Want to Extend These Libraries?
|
|
79
|
+
|
|
80
|
+
Did you find a class in our `libs/` that *almost* perfectly fits your needs, but you want to add your own custom features, modules, or plugins to it?
|
|
76
81
|
|
|
77
|
-
|
|
82
|
+
We highly recommend using **[βοΈ TinyClassManager](./libs/TinyClassManager.md)**! It was specifically built for this purpose. It allows you to safely and cleanly inject your own plugins into our existing classes using a linear mixin architecture, automatically handling dependencies and preventing conflicts without you ever having to touch the original source code.
|
|
78
83
|
|
|
79
84
|
---
|
|
80
85
|
|