tiny-essentials 1.25.3 → 1.25.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/25/3.md +6 -0
- package/changelog/1/25/4.md +3 -0
- package/dist/v1/TinyArrayComparator.min.js +1 -0
- package/dist/v1/TinyEssentials.min.js +1 -1
- package/dist/v1/build/TinyArrayComparator.cjs +7 -0
- package/dist/v1/build/TinyArrayComparator.d.mts +3 -0
- package/dist/v1/build/TinyArrayComparator.mjs +2 -0
- 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/TinyArrayComparator.cjs +130 -0
- package/dist/v1/libs/TinyArrayComparator.d.mts +79 -0
- package/dist/v1/libs/TinyArrayComparator.mjs +112 -0
- package/docs/v1/README.md +1 -0
- package/docs/v1/libs/TinyArrayComparator.md +101 -0
- package/package.json +5 -1
package/dist/v1/index.cjs
CHANGED
|
@@ -49,6 +49,7 @@ var TinyLoadingScreen = require('./libs/TinyLoadingScreen.cjs');
|
|
|
49
49
|
var TinyColorValidator = require('./libs/TinyColorValidator.cjs');
|
|
50
50
|
var TinyAnalogClock = require('./libs/TinyAnalogClock.cjs');
|
|
51
51
|
var TinyTextDiffer = require('./libs/TinyTextDiffer.cjs');
|
|
52
|
+
var TinyArrayComparator = require('./libs/TinyArrayComparator.cjs');
|
|
52
53
|
|
|
53
54
|
|
|
54
55
|
|
|
@@ -179,3 +180,4 @@ exports.TinyLoadingScreen = TinyLoadingScreen;
|
|
|
179
180
|
exports.TinyColorValidator = TinyColorValidator;
|
|
180
181
|
exports.TinyAnalogClock = TinyAnalogClock;
|
|
181
182
|
exports.TinyTextDiffer = TinyTextDiffer;
|
|
183
|
+
exports.TinyArrayComparator = TinyArrayComparator;
|
package/dist/v1/index.d.mts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import TinyArrayComparator from './libs/TinyArrayComparator.mjs';
|
|
1
2
|
import TinyTextDiffer from './libs/TinyTextDiffer.mjs';
|
|
2
3
|
import TinyAnalogClock from './libs/TinyAnalogClock.mjs';
|
|
3
4
|
import TinyColorValidator from './libs/TinyColorValidator.mjs';
|
|
@@ -125,5 +126,5 @@ import { getTimeDuration } from './basics/clock.mjs';
|
|
|
125
126
|
import { shuffleArray } from './basics/array.mjs';
|
|
126
127
|
import { toTitleCase } from './basics/text.mjs';
|
|
127
128
|
import { toTitleCaseLowerFirst } from './basics/text.mjs';
|
|
128
|
-
export { 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, 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 };
|
|
129
|
+
export { 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, 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 };
|
|
129
130
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/v1/index.mjs
CHANGED
|
@@ -47,7 +47,8 @@ import TinyLoadingScreen from './libs/TinyLoadingScreen.mjs';
|
|
|
47
47
|
import TinyColorValidator from './libs/TinyColorValidator.mjs';
|
|
48
48
|
import TinyAnalogClock from './libs/TinyAnalogClock.mjs';
|
|
49
49
|
import TinyTextDiffer from './libs/TinyTextDiffer.mjs';
|
|
50
|
+
import TinyArrayComparator from './libs/TinyArrayComparator.mjs';
|
|
50
51
|
// import TinyHtmlElems from './libs/TinyHtml/index.mjs';
|
|
51
|
-
export { TinyTextDiffer, TinyAnalogClock,
|
|
52
|
+
export { TinyArrayComparator, TinyTextDiffer, TinyAnalogClock,
|
|
52
53
|
// TinyHtmlElems,
|
|
53
54
|
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, 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,130 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @fileoverview Array comparison utility.
|
|
5
|
+
* @module TinyArrayComparator
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @typedef {Object} InternalState
|
|
10
|
+
* Holds the internal tracking variables during the comparison process.
|
|
11
|
+
* @property {Map<string, any>} oldItemsMap - A map storing the hash as the key and the original item as the value.
|
|
12
|
+
* @property {AffectedItems} affectedItems - The final array that collects added or deleted items.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* The final array that collects added or deleted items.
|
|
17
|
+
* @typedef {Array<{item: any, status: 'added'|'deleted'}>} AffectedItems
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Compares two arrays efficiently by hashing their items to detect additions and deletions.
|
|
22
|
+
*/
|
|
23
|
+
class TinyArrayComparator {
|
|
24
|
+
/**
|
|
25
|
+
* Generates a simple 32-bit integer hash converted to a base36 string.
|
|
26
|
+
* @param {any} item - The item to be hashed (can be an object, array, string, or number).
|
|
27
|
+
* @returns {string} The unique hash representing the item's value.
|
|
28
|
+
*/
|
|
29
|
+
static generateHash(item) {
|
|
30
|
+
const stringified = typeof item === 'object' ? JSON.stringify(item) : String(item);
|
|
31
|
+
let hash = 0;
|
|
32
|
+
|
|
33
|
+
for (let i = 0, len = stringified.length; i < len; i++) {
|
|
34
|
+
const char = stringified.charCodeAt(i);
|
|
35
|
+
hash = (hash << 5) - hash + char;
|
|
36
|
+
hash |= 0; // Convert to 32bit integer
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return hash.toString(36);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Internal storage for the base array.
|
|
44
|
+
* @type {any[]}
|
|
45
|
+
*/
|
|
46
|
+
#oldArray = [];
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Gets the current base array used for comparisons.
|
|
50
|
+
* @returns {any[]} The current initial state of the array.
|
|
51
|
+
*/
|
|
52
|
+
get oldArray() {
|
|
53
|
+
return this.#oldArray;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Sets a new base array for future comparisons.
|
|
58
|
+
* @param {Array<any>} oldArray - The initial state of the array.
|
|
59
|
+
* @throws {TypeError} Throws an error if the provided value is not an array.
|
|
60
|
+
*/
|
|
61
|
+
set oldArray(oldArray) {
|
|
62
|
+
if (!Array.isArray(oldArray))
|
|
63
|
+
throw new TypeError('The provided oldArray must be a valid Array.');
|
|
64
|
+
this.#oldArray = oldArray;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Initializes the comparator with an optional base array.
|
|
69
|
+
* @param {Array<any>} [oldArray] - The initial state of the array to be stored.
|
|
70
|
+
*/
|
|
71
|
+
constructor(oldArray) {
|
|
72
|
+
if (typeof oldArray !== 'undefined') this.oldArray = oldArray;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Proxy to generates a hash converted to a string.
|
|
77
|
+
* @param {any} item - The item to be hashed (can be an object, array, string, or number).
|
|
78
|
+
* @returns {string} The unique hash representing the item's value.
|
|
79
|
+
* @private
|
|
80
|
+
*/
|
|
81
|
+
_generateHash(item) {
|
|
82
|
+
return TinyArrayComparator.generateHash(item);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Compares the stored older array with a newer array and identifies missing or new items.
|
|
87
|
+
*
|
|
88
|
+
* @param {Array<any>} newArray - The modified state of the array.
|
|
89
|
+
* @returns {AffectedItems} An array containing the affected items and their status.
|
|
90
|
+
* @throws {TypeError} Throws an error if the provided value is not an array.
|
|
91
|
+
*/
|
|
92
|
+
compare(newArray) {
|
|
93
|
+
if (!Array.isArray(newArray))
|
|
94
|
+
throw new TypeError('The provided newArray must be a valid Array.');
|
|
95
|
+
|
|
96
|
+
/** @type {InternalState} */
|
|
97
|
+
const state = {
|
|
98
|
+
oldItemsMap: new Map(),
|
|
99
|
+
affectedItems: [],
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
// Step 1: Hash and store all items from the first array
|
|
103
|
+
for (const item of this.#oldArray) {
|
|
104
|
+
const hashKey = this._generateHash(item);
|
|
105
|
+
state.oldItemsMap.set(hashKey, item);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Step 2: Iterate through the second array to find matches or additions
|
|
109
|
+
for (const item of newArray) {
|
|
110
|
+
const hashKey = this._generateHash(item);
|
|
111
|
+
|
|
112
|
+
if (state.oldItemsMap.has(hashKey)) {
|
|
113
|
+
// Item exists in both, so it is unchanged. Remove from map.
|
|
114
|
+
state.oldItemsMap.delete(hashKey);
|
|
115
|
+
} else {
|
|
116
|
+
// Item was not in the old array, so it is an addition.
|
|
117
|
+
state.affectedItems.push({ item, status: 'added' });
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Step 3: Any item left in the oldItemsMap was not present in the new array (deleted)
|
|
122
|
+
for (const item of state.oldItemsMap.values()) {
|
|
123
|
+
state.affectedItems.push({ item, status: 'deleted' });
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return state.affectedItems;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
module.exports = TinyArrayComparator;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
export default TinyArrayComparator;
|
|
2
|
+
/**
|
|
3
|
+
* Holds the internal tracking variables during the comparison process.
|
|
4
|
+
*/
|
|
5
|
+
export type InternalState = {
|
|
6
|
+
/**
|
|
7
|
+
* - A map storing the hash as the key and the original item as the value.
|
|
8
|
+
*/
|
|
9
|
+
oldItemsMap: Map<string, any>;
|
|
10
|
+
/**
|
|
11
|
+
* - The final array that collects added or deleted items.
|
|
12
|
+
*/
|
|
13
|
+
affectedItems: AffectedItems;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* The final array that collects added or deleted items.
|
|
17
|
+
*/
|
|
18
|
+
export type AffectedItems = Array<{
|
|
19
|
+
item: any;
|
|
20
|
+
status: "added" | "deleted";
|
|
21
|
+
}>;
|
|
22
|
+
/**
|
|
23
|
+
* @fileoverview Array comparison utility.
|
|
24
|
+
* @module TinyArrayComparator
|
|
25
|
+
*/
|
|
26
|
+
/**
|
|
27
|
+
* @typedef {Object} InternalState
|
|
28
|
+
* Holds the internal tracking variables during the comparison process.
|
|
29
|
+
* @property {Map<string, any>} oldItemsMap - A map storing the hash as the key and the original item as the value.
|
|
30
|
+
* @property {AffectedItems} affectedItems - The final array that collects added or deleted items.
|
|
31
|
+
*/
|
|
32
|
+
/**
|
|
33
|
+
* The final array that collects added or deleted items.
|
|
34
|
+
* @typedef {Array<{item: any, status: 'added'|'deleted'}>} AffectedItems
|
|
35
|
+
*/
|
|
36
|
+
/**
|
|
37
|
+
* Compares two arrays efficiently by hashing their items to detect additions and deletions.
|
|
38
|
+
*/
|
|
39
|
+
declare class TinyArrayComparator {
|
|
40
|
+
/**
|
|
41
|
+
* Generates a simple 32-bit integer hash converted to a base36 string.
|
|
42
|
+
* @param {any} item - The item to be hashed (can be an object, array, string, or number).
|
|
43
|
+
* @returns {string} The unique hash representing the item's value.
|
|
44
|
+
*/
|
|
45
|
+
static generateHash(item: any): string;
|
|
46
|
+
/**
|
|
47
|
+
* Initializes the comparator with an optional base array.
|
|
48
|
+
* @param {Array<any>} [oldArray] - The initial state of the array to be stored.
|
|
49
|
+
*/
|
|
50
|
+
constructor(oldArray?: Array<any>);
|
|
51
|
+
/**
|
|
52
|
+
* Sets a new base array for future comparisons.
|
|
53
|
+
* @param {Array<any>} oldArray - The initial state of the array.
|
|
54
|
+
* @throws {TypeError} Throws an error if the provided value is not an array.
|
|
55
|
+
*/
|
|
56
|
+
set oldArray(oldArray: Array<any>);
|
|
57
|
+
/**
|
|
58
|
+
* Gets the current base array used for comparisons.
|
|
59
|
+
* @returns {any[]} The current initial state of the array.
|
|
60
|
+
*/
|
|
61
|
+
get oldArray(): any[];
|
|
62
|
+
/**
|
|
63
|
+
* Proxy to generates a hash converted to a string.
|
|
64
|
+
* @param {any} item - The item to be hashed (can be an object, array, string, or number).
|
|
65
|
+
* @returns {string} The unique hash representing the item's value.
|
|
66
|
+
* @private
|
|
67
|
+
*/
|
|
68
|
+
private _generateHash;
|
|
69
|
+
/**
|
|
70
|
+
* Compares the stored older array with a newer array and identifies missing or new items.
|
|
71
|
+
*
|
|
72
|
+
* @param {Array<any>} newArray - The modified state of the array.
|
|
73
|
+
* @returns {AffectedItems} An array containing the affected items and their status.
|
|
74
|
+
* @throws {TypeError} Throws an error if the provided value is not an array.
|
|
75
|
+
*/
|
|
76
|
+
compare(newArray: Array<any>): AffectedItems;
|
|
77
|
+
#private;
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=TinyArrayComparator.d.mts.map
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Array comparison utility.
|
|
3
|
+
* @module TinyArrayComparator
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* @typedef {Object} InternalState
|
|
7
|
+
* Holds the internal tracking variables during the comparison process.
|
|
8
|
+
* @property {Map<string, any>} oldItemsMap - A map storing the hash as the key and the original item as the value.
|
|
9
|
+
* @property {AffectedItems} affectedItems - The final array that collects added or deleted items.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* The final array that collects added or deleted items.
|
|
13
|
+
* @typedef {Array<{item: any, status: 'added'|'deleted'}>} AffectedItems
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Compares two arrays efficiently by hashing their items to detect additions and deletions.
|
|
17
|
+
*/
|
|
18
|
+
class TinyArrayComparator {
|
|
19
|
+
/**
|
|
20
|
+
* Generates a simple 32-bit integer hash converted to a base36 string.
|
|
21
|
+
* @param {any} item - The item to be hashed (can be an object, array, string, or number).
|
|
22
|
+
* @returns {string} The unique hash representing the item's value.
|
|
23
|
+
*/
|
|
24
|
+
static generateHash(item) {
|
|
25
|
+
const stringified = typeof item === 'object' ? JSON.stringify(item) : String(item);
|
|
26
|
+
let hash = 0;
|
|
27
|
+
for (let i = 0, len = stringified.length; i < len; i++) {
|
|
28
|
+
const char = stringified.charCodeAt(i);
|
|
29
|
+
hash = (hash << 5) - hash + char;
|
|
30
|
+
hash |= 0; // Convert to 32bit integer
|
|
31
|
+
}
|
|
32
|
+
return hash.toString(36);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Internal storage for the base array.
|
|
36
|
+
* @type {any[]}
|
|
37
|
+
*/
|
|
38
|
+
#oldArray = [];
|
|
39
|
+
/**
|
|
40
|
+
* Gets the current base array used for comparisons.
|
|
41
|
+
* @returns {any[]} The current initial state of the array.
|
|
42
|
+
*/
|
|
43
|
+
get oldArray() {
|
|
44
|
+
return this.#oldArray;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Sets a new base array for future comparisons.
|
|
48
|
+
* @param {Array<any>} oldArray - The initial state of the array.
|
|
49
|
+
* @throws {TypeError} Throws an error if the provided value is not an array.
|
|
50
|
+
*/
|
|
51
|
+
set oldArray(oldArray) {
|
|
52
|
+
if (!Array.isArray(oldArray))
|
|
53
|
+
throw new TypeError('The provided oldArray must be a valid Array.');
|
|
54
|
+
this.#oldArray = oldArray;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Initializes the comparator with an optional base array.
|
|
58
|
+
* @param {Array<any>} [oldArray] - The initial state of the array to be stored.
|
|
59
|
+
*/
|
|
60
|
+
constructor(oldArray) {
|
|
61
|
+
if (typeof oldArray !== 'undefined')
|
|
62
|
+
this.oldArray = oldArray;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Proxy to generates a hash converted to a string.
|
|
66
|
+
* @param {any} item - The item to be hashed (can be an object, array, string, or number).
|
|
67
|
+
* @returns {string} The unique hash representing the item's value.
|
|
68
|
+
* @private
|
|
69
|
+
*/
|
|
70
|
+
_generateHash(item) {
|
|
71
|
+
return TinyArrayComparator.generateHash(item);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Compares the stored older array with a newer array and identifies missing or new items.
|
|
75
|
+
*
|
|
76
|
+
* @param {Array<any>} newArray - The modified state of the array.
|
|
77
|
+
* @returns {AffectedItems} An array containing the affected items and their status.
|
|
78
|
+
* @throws {TypeError} Throws an error if the provided value is not an array.
|
|
79
|
+
*/
|
|
80
|
+
compare(newArray) {
|
|
81
|
+
if (!Array.isArray(newArray))
|
|
82
|
+
throw new TypeError('The provided newArray must be a valid Array.');
|
|
83
|
+
/** @type {InternalState} */
|
|
84
|
+
const state = {
|
|
85
|
+
oldItemsMap: new Map(),
|
|
86
|
+
affectedItems: [],
|
|
87
|
+
};
|
|
88
|
+
// Step 1: Hash and store all items from the first array
|
|
89
|
+
for (const item of this.#oldArray) {
|
|
90
|
+
const hashKey = this._generateHash(item);
|
|
91
|
+
state.oldItemsMap.set(hashKey, item);
|
|
92
|
+
}
|
|
93
|
+
// Step 2: Iterate through the second array to find matches or additions
|
|
94
|
+
for (const item of newArray) {
|
|
95
|
+
const hashKey = this._generateHash(item);
|
|
96
|
+
if (state.oldItemsMap.has(hashKey)) {
|
|
97
|
+
// Item exists in both, so it is unchanged. Remove from map.
|
|
98
|
+
state.oldItemsMap.delete(hashKey);
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
// Item was not in the old array, so it is an addition.
|
|
102
|
+
state.affectedItems.push({ item, status: 'added' });
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
// Step 3: Any item left in the oldItemsMap was not present in the new array (deleted)
|
|
106
|
+
for (const item of state.oldItemsMap.values()) {
|
|
107
|
+
state.affectedItems.push({ item, status: 'deleted' });
|
|
108
|
+
}
|
|
109
|
+
return state.affectedItems;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
export default TinyArrayComparator;
|
package/docs/v1/README.md
CHANGED
|
@@ -62,6 +62,7 @@ This folder contains the core scripts we have worked on so far. Each file is a m
|
|
|
62
62
|
- 🎨 **[TinyColorValidator](./libs/TinyColorValidator.md)** — A comprehensive CSS color validation and parsing utility supporting HEX, HEXA, RGB, RGBA, HSL, HSLA, HWB, Lab, LCH, standard HTML color names, and special keywords, with automatic type detection and parsing.
|
|
63
63
|
* 📝 **[TinyTextDiffer](./libs/TinyTextDiffer.md)** — A granular text comparison utility using the LCS algorithm to detect additions, deletions, and unchanged segments between multiple history versions, returning a clean, parseable diff structure.
|
|
64
64
|
* 🕒 **[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
|
+
* 🔍 **[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**.
|
|
65
66
|
|
|
66
67
|
### 3. **`fileManager/`**
|
|
67
68
|
* 📁 **[Main](./fileManager/main.md)** — A Node.js file/directory utility module with support for JSON, backups, renaming, size analysis, and more.
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# 🔍 TinyArrayComparator
|
|
2
|
+
|
|
3
|
+
A lightweight, highly optimized JavaScript utility class designed to compare two arrays and efficiently detect which items were **added** or **deleted**.
|
|
4
|
+
|
|
5
|
+
## ✨ Features
|
|
6
|
+
|
|
7
|
+
- **Fast Comparison:** Uses a Map and hash-based lookups for $O(N)$ performance.
|
|
8
|
+
- **Stateful Design:** Store your base array once and compare it multiple times.
|
|
9
|
+
- **Zero Dependencies:** Pure Vanilla JavaScript.
|
|
10
|
+
- **Deep Compatibility:** Safely hashes strings, numbers, arrays, and deep objects.
|
|
11
|
+
- **Clean Architecture:** Built as an ES6 Module with strict JSDoc typing and input validation.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 🚀 Quick Start
|
|
16
|
+
|
|
17
|
+
### 1. Import the Class
|
|
18
|
+
Since this project uses modern ES6 modules, simply import it into your working file.
|
|
19
|
+
|
|
20
|
+
```javascript
|
|
21
|
+
import TinyArrayComparator from './TinyArrayComparator.js';
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### 2. Prepare Your Arrays
|
|
25
|
+
Set up the initial state (`oldArray`) and the modified state (`newArray`) that you want to compare.
|
|
26
|
+
|
|
27
|
+
```javascript
|
|
28
|
+
const oldList = [
|
|
29
|
+
{ id: 1, role: 'admin' },
|
|
30
|
+
{ id: 2, role: 'user' },
|
|
31
|
+
{ id: 3, role: 'moderator' }
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
const newList = [
|
|
35
|
+
{ id: 1, role: 'admin' }, // Unchanged
|
|
36
|
+
{ id: 3, role: 'moderator' }, // Unchanged
|
|
37
|
+
{ id: 4, role: 'guest' } // Added
|
|
38
|
+
// User ID 2 was deleted
|
|
39
|
+
];
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### 3. Initialize and Compare
|
|
43
|
+
Instantiate the class passing the initial array. Then, call the `compare` method with your new array.
|
|
44
|
+
|
|
45
|
+
```javascript
|
|
46
|
+
const comparator = new TinyArrayComparator(oldList);
|
|
47
|
+
const results = comparator.compare(newList);
|
|
48
|
+
|
|
49
|
+
console.log(results);
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**Output:**
|
|
53
|
+
```json
|
|
54
|
+
[
|
|
55
|
+
{
|
|
56
|
+
"item": { "id": 4, "role": "guest" },
|
|
57
|
+
"status": "added"
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"item": { "id": 2, "role": "user" },
|
|
61
|
+
"status": "deleted"
|
|
62
|
+
}
|
|
63
|
+
]
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## 🛠️ API Reference
|
|
69
|
+
|
|
70
|
+
### `constructor([oldArray])`
|
|
71
|
+
Creates a new comparator instance.
|
|
72
|
+
* **`oldArray`** `(Array<any>)` *(Optional)*: The initial state of the array to be stored. Throws a `TypeError` if the provided value is not an Array.
|
|
73
|
+
|
|
74
|
+
### `compare(newArray)`
|
|
75
|
+
Evaluates differences between the internally stored `oldArray` and the provided `newArray`. Throws a `TypeError` if the provided value is not an Array.
|
|
76
|
+
* **`newArray`** `(Array<any>)`: The new array containing current modifications.
|
|
77
|
+
* **Returns:** An array of objects. Each object contains the original `item` and a `status` string (either `'added'` or `'deleted'`).
|
|
78
|
+
|
|
79
|
+
### `get oldArray` / `set oldArray(value)`
|
|
80
|
+
Allows you to retrieve or update the base array stored inside the instance.
|
|
81
|
+
* **Throws:** `TypeError` if attempting to set a non-array value.
|
|
82
|
+
|
|
83
|
+
### `static generateHash(item)`
|
|
84
|
+
A static helper method if you ever need to generate a unique base36 hash string for an item outside the comparison flow.
|
|
85
|
+
* **`item`** `(any)`: The target object, string, or number to hash.
|
|
86
|
+
* **Returns:** A `string` representing the unique hash.
|
|
87
|
+
|
|
88
|
+
```javascript
|
|
89
|
+
const myHash = TinyArrayComparator.generateHash({ pony: 'Pudding' });
|
|
90
|
+
console.log(myHash); // Returns a base36 string like "1b4x9z"
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## 💡 Best Practices
|
|
96
|
+
|
|
97
|
+
* **Order Doesn't Matter:** Because this utility relies on value-hashing, the index order of items inside the arrays does not affect the comparison. It strictly checks for the existence of the values.
|
|
98
|
+
* **Object References:** The returned array preserves the exact references to the items passed in the parameters, allowing you to seamlessly integrate the output back into your application logic.
|
|
99
|
+
* **Reusability:** You can easily update the base state by assigning a new array to `comparator.oldArray = [...]` without creating a new instance.
|
|
100
|
+
|
|
101
|
+
Happy coding! 💻✨
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tiny-essentials",
|
|
3
|
-
"version": "1.25.
|
|
3
|
+
"version": "1.25.4",
|
|
4
4
|
"description": "Collection of small, essential scripts designed to be used across various projects. These simple utilities are crafted for speed, ease of use, and versatility.",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "npm run test:mjs && npm run test:cjs && npm run test:js",
|
|
@@ -220,6 +220,10 @@
|
|
|
220
220
|
"require": "./dist/v1/libs/TinyTextDiffer.cjs",
|
|
221
221
|
"import": "./dist/v1/libs/TinyTextDiffer.mjs"
|
|
222
222
|
},
|
|
223
|
+
"./libs/TinyArrayComparator": {
|
|
224
|
+
"require": "./dist/v1/libs/TinyArrayComparator.cjs",
|
|
225
|
+
"import": "./dist/v1/libs/TinyArrayComparator.mjs"
|
|
226
|
+
},
|
|
223
227
|
"./libs/TinyDragDropDetector": {
|
|
224
228
|
"require": "./dist/v1/libs/TinyDragDropDetector.cjs",
|
|
225
229
|
"import": "./dist/v1/libs/TinyDragDropDetector.mjs"
|