tiny-essentials 1.24.5 โ 1.25.1
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 +8 -8
- package/changelog/1/25/0.md +13 -0
- package/changelog/1/25/1.md +18 -0
- package/dist/v1/TinyAnalogClock.min.js +1 -0
- package/dist/v1/TinyBasicsEs.min.js +1 -1
- package/dist/v1/TinyEssentials.min.js +1 -1
- package/dist/v1/TinyTextDiffer.min.js +1 -0
- package/dist/v1/basics/html.cjs +151 -2
- package/dist/v1/basics/html.d.mts +109 -0
- package/dist/v1/basics/html.mjs +135 -2
- package/dist/v1/build/TinyAnalogClock.cjs +7 -0
- package/dist/v1/build/TinyAnalogClock.d.mts +3 -0
- package/dist/v1/build/TinyAnalogClock.mjs +2 -0
- package/dist/v1/build/TinyTextDiffer.cjs +7 -0
- package/dist/v1/build/TinyTextDiffer.d.mts +3 -0
- package/dist/v1/build/TinyTextDiffer.mjs +2 -0
- package/dist/v1/index.cjs +4 -0
- package/dist/v1/index.d.mts +3 -1
- package/dist/v1/index.mjs +3 -1
- package/dist/v1/libs/TinyAnalogClock.cjs +738 -0
- package/dist/v1/libs/TinyAnalogClock.d.mts +342 -0
- package/dist/v1/libs/TinyAnalogClock.mjs +653 -0
- package/dist/v1/libs/TinyRateLimiter.cjs +215 -31
- package/dist/v1/libs/TinyRateLimiter.d.mts +179 -25
- package/dist/v1/libs/TinyRateLimiter.mjs +215 -31
- package/dist/v1/libs/TinyTextDiffer.cjs +288 -0
- package/dist/v1/libs/TinyTextDiffer.d.mts +109 -0
- package/dist/v1/libs/TinyTextDiffer.mjs +255 -0
- package/docs/v1/README.md +5 -8
- package/docs/v1/basics/html.md +69 -0
- package/docs/v1/libs/TinyAnalogClock.md +295 -0
- package/docs/v1/libs/TinyRateLimiter.md +11 -0
- package/docs/v1/libs/TinyTextDiffer.md +114 -0
- package/package.json +12 -4
- package/docs/v1/Ai-Tips.md +0 -51
- package/docs/v1/Personal-Ai-Prompts(portuguese).md +0 -134
- package/docs/v1/Personal-Ai-Prompts.md +0 -113
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
export default TinyTextDiffer;
|
|
2
|
+
/**
|
|
3
|
+
* Represents the result of a single text segment comparison.
|
|
4
|
+
*/
|
|
5
|
+
export type DiffResult = {
|
|
6
|
+
/**
|
|
7
|
+
* - The actual string content of the segment.
|
|
8
|
+
*/
|
|
9
|
+
value: string;
|
|
10
|
+
/**
|
|
11
|
+
* - The status of the segment relative to the comparison.
|
|
12
|
+
*/
|
|
13
|
+
type: "normal" | "added" | "deleted";
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Represents the result of a single text segment comparison.
|
|
17
|
+
* @typedef {Object} DiffResult
|
|
18
|
+
* @property {string} value - The actual string content of the segment.
|
|
19
|
+
* @property {"normal"|"added"|"deleted"} type - The status of the segment relative to the comparison.
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* A utility class to store a history of text strings and compute the differences
|
|
23
|
+
* between any two versions, generating a detailed diff output.
|
|
24
|
+
*/
|
|
25
|
+
declare class TinyTextDiffer {
|
|
26
|
+
/**
|
|
27
|
+
* Initializes a new instance of TinyTextDiffer.
|
|
28
|
+
* @param {string[]} [history=[]]
|
|
29
|
+
*/
|
|
30
|
+
constructor(history?: string[]);
|
|
31
|
+
/**
|
|
32
|
+
* Overwrites the current history array, ensuring all elements are valid strings.
|
|
33
|
+
* @param {string[]} history
|
|
34
|
+
*/
|
|
35
|
+
set history(history: string[]);
|
|
36
|
+
/**
|
|
37
|
+
* Retrieves a shallow copy of the current history array.
|
|
38
|
+
* @returns {string[]}
|
|
39
|
+
*/
|
|
40
|
+
get history(): string[];
|
|
41
|
+
/**
|
|
42
|
+
* Gets the total number of versions currently stored in the history.
|
|
43
|
+
* @returns {number}
|
|
44
|
+
*/
|
|
45
|
+
get size(): number;
|
|
46
|
+
/**
|
|
47
|
+
* Retrieves the text string at the specified index.
|
|
48
|
+
* @param {number} index
|
|
49
|
+
* @returns {string}
|
|
50
|
+
*/
|
|
51
|
+
get(index: number): string;
|
|
52
|
+
/**
|
|
53
|
+
* Checks if a text string exists at the specified index.
|
|
54
|
+
* @param {number} index
|
|
55
|
+
* @returns {boolean}
|
|
56
|
+
*/
|
|
57
|
+
has(index: number): boolean;
|
|
58
|
+
/**
|
|
59
|
+
* Appends a new text string to the end of the history.
|
|
60
|
+
* @param {string} text
|
|
61
|
+
* @returns {void}
|
|
62
|
+
*/
|
|
63
|
+
add(text: string): void;
|
|
64
|
+
/**
|
|
65
|
+
* Removes and returns the last text string from the history.
|
|
66
|
+
* @returns {string | undefined}
|
|
67
|
+
*/
|
|
68
|
+
remove(): string | undefined;
|
|
69
|
+
/**
|
|
70
|
+
* Inserts a text string at the specified index position.
|
|
71
|
+
* @param {number} index
|
|
72
|
+
* @param {string} text
|
|
73
|
+
* @returns {void}
|
|
74
|
+
*/
|
|
75
|
+
addAt(index: number, text: string): void;
|
|
76
|
+
/**
|
|
77
|
+
* Removes the text string at the specified index position.
|
|
78
|
+
* @param {number} index
|
|
79
|
+
* @returns {boolean}
|
|
80
|
+
*/
|
|
81
|
+
removeAt(index: number): boolean;
|
|
82
|
+
/**
|
|
83
|
+
* Empties the entire history.
|
|
84
|
+
* @returns {void}
|
|
85
|
+
*/
|
|
86
|
+
clear(): void;
|
|
87
|
+
/**
|
|
88
|
+
* Compares multiple pairs of text strings from the history based on their indices.
|
|
89
|
+
* Each pair of indices (e.g., index1 and index2) will produce a DiffResult array.
|
|
90
|
+
* @param {...number} indexes - An even number of indices to be compared in pairs.
|
|
91
|
+
* @returns {(DiffResult[])[]} An array of DiffResult arrays for each compared pair.
|
|
92
|
+
*/
|
|
93
|
+
compare(...indexes: number[]): (DiffResult[])[];
|
|
94
|
+
/**
|
|
95
|
+
* Computes the Longest Common Subsequence (LCS) to generate the diff result.
|
|
96
|
+
* @private
|
|
97
|
+
* @param {string} str1
|
|
98
|
+
* @param {string} str2
|
|
99
|
+
* @returns {DiffResult[]}
|
|
100
|
+
*/
|
|
101
|
+
private _computeDiff;
|
|
102
|
+
/**
|
|
103
|
+
* Cleans up internal references and marks the instance as destroyed to prevent memory leaks.
|
|
104
|
+
* @returns {void}
|
|
105
|
+
*/
|
|
106
|
+
destroy(): void;
|
|
107
|
+
#private;
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=TinyTextDiffer.d.mts.map
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Represents the result of a single text segment comparison.
|
|
3
|
+
* @typedef {Object} DiffResult
|
|
4
|
+
* @property {string} value - The actual string content of the segment.
|
|
5
|
+
* @property {"normal"|"added"|"deleted"} type - The status of the segment relative to the comparison.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* A utility class to store a history of text strings and compute the differences
|
|
9
|
+
* between any two versions, generating a detailed diff output.
|
|
10
|
+
*/
|
|
11
|
+
class TinyTextDiffer {
|
|
12
|
+
/** @type {string[]} */
|
|
13
|
+
#history = [];
|
|
14
|
+
/** @type {boolean} */
|
|
15
|
+
#destroyed = false;
|
|
16
|
+
/**
|
|
17
|
+
* Retrieves a shallow copy of the current history array.
|
|
18
|
+
* @returns {string[]}
|
|
19
|
+
*/
|
|
20
|
+
get history() {
|
|
21
|
+
return [...this.#history];
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Overwrites the current history array, ensuring all elements are valid strings.
|
|
25
|
+
* @param {string[]} history
|
|
26
|
+
*/
|
|
27
|
+
set history(history) {
|
|
28
|
+
if (!Array.isArray(history)) {
|
|
29
|
+
throw new TypeError('History data must be provided as an array.');
|
|
30
|
+
}
|
|
31
|
+
if (!history.every((item) => typeof item === 'string')) {
|
|
32
|
+
throw new TypeError('All items in the history array must be strings.');
|
|
33
|
+
}
|
|
34
|
+
/** @type {string[]} */
|
|
35
|
+
this.#history = [...history];
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Gets the total number of versions currently stored in the history.
|
|
39
|
+
* @returns {number}
|
|
40
|
+
*/
|
|
41
|
+
get size() {
|
|
42
|
+
return this.#history.length;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Initializes a new instance of TinyTextDiffer.
|
|
46
|
+
* @param {string[]} [history=[]]
|
|
47
|
+
*/
|
|
48
|
+
constructor(history = []) {
|
|
49
|
+
this.history = history;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* @throws {Error}
|
|
53
|
+
* @returns {void}
|
|
54
|
+
*/
|
|
55
|
+
#checkDestroyed() {
|
|
56
|
+
if (this.#destroyed) {
|
|
57
|
+
throw new Error('Cannot perform operations on a destroyed TinyTextDiffer instance.');
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* @param {any} index
|
|
62
|
+
* @throws {TypeError}
|
|
63
|
+
* @returns {void}
|
|
64
|
+
*/
|
|
65
|
+
#checkIndex(index) {
|
|
66
|
+
if (typeof index !== 'number') {
|
|
67
|
+
throw new TypeError('The provided index must be a valid number.');
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* @param {any} text
|
|
72
|
+
* @throws {TypeError}
|
|
73
|
+
* @returns {void}
|
|
74
|
+
*/
|
|
75
|
+
#checkText(text) {
|
|
76
|
+
if (typeof text !== 'string') {
|
|
77
|
+
throw new TypeError('The provided text must be a valid string.');
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Retrieves the text string at the specified index.
|
|
82
|
+
* @param {number} index
|
|
83
|
+
* @returns {string}
|
|
84
|
+
*/
|
|
85
|
+
get(index) {
|
|
86
|
+
this.#checkDestroyed();
|
|
87
|
+
this.#checkIndex(index);
|
|
88
|
+
if (typeof this.#history[index] === 'undefined') {
|
|
89
|
+
throw new Error(`No text version found at index ${index}.`);
|
|
90
|
+
}
|
|
91
|
+
return this.#history[index];
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Checks if a text string exists at the specified index.
|
|
95
|
+
* @param {number} index
|
|
96
|
+
* @returns {boolean}
|
|
97
|
+
*/
|
|
98
|
+
has(index) {
|
|
99
|
+
this.#checkDestroyed();
|
|
100
|
+
this.#checkIndex(index);
|
|
101
|
+
return typeof this.#history[index] !== 'undefined';
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Appends a new text string to the end of the history.
|
|
105
|
+
* @param {string} text
|
|
106
|
+
* @returns {void}
|
|
107
|
+
*/
|
|
108
|
+
add(text) {
|
|
109
|
+
this.#checkDestroyed();
|
|
110
|
+
this.#checkText(text);
|
|
111
|
+
this.#history.push(text);
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Removes and returns the last text string from the history.
|
|
115
|
+
* @returns {string | undefined}
|
|
116
|
+
*/
|
|
117
|
+
remove() {
|
|
118
|
+
this.#checkDestroyed();
|
|
119
|
+
return this.#history.pop();
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Inserts a text string at the specified index position.
|
|
123
|
+
* @param {number} index
|
|
124
|
+
* @param {string} text
|
|
125
|
+
* @returns {void}
|
|
126
|
+
*/
|
|
127
|
+
addAt(index, text) {
|
|
128
|
+
this.#checkDestroyed();
|
|
129
|
+
this.#checkIndex(index);
|
|
130
|
+
this.#checkText(text);
|
|
131
|
+
this.#history.splice(index, 0, text);
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Removes the text string at the specified index position.
|
|
135
|
+
* @param {number} index
|
|
136
|
+
* @returns {boolean}
|
|
137
|
+
*/
|
|
138
|
+
removeAt(index) {
|
|
139
|
+
this.#checkDestroyed();
|
|
140
|
+
this.#checkIndex(index);
|
|
141
|
+
const oldSize = this.#history.length;
|
|
142
|
+
this.#history.splice(index, 1);
|
|
143
|
+
const newSize = this.#history.length;
|
|
144
|
+
return oldSize !== newSize;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Empties the entire history.
|
|
148
|
+
* @returns {void}
|
|
149
|
+
*/
|
|
150
|
+
clear() {
|
|
151
|
+
this.#checkDestroyed();
|
|
152
|
+
this.#history = [];
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Compares multiple pairs of text strings from the history based on their indices.
|
|
156
|
+
* Each pair of indices (e.g., index1 and index2) will produce a DiffResult array.
|
|
157
|
+
* @param {...number} indexes - An even number of indices to be compared in pairs.
|
|
158
|
+
* @returns {(DiffResult[])[]} An array of DiffResult arrays for each compared pair.
|
|
159
|
+
*/
|
|
160
|
+
compare(...indexes) {
|
|
161
|
+
this.#checkDestroyed();
|
|
162
|
+
/** @type {number} */
|
|
163
|
+
const totalIndexes = indexes.length;
|
|
164
|
+
if (totalIndexes === 0 || totalIndexes % 2 !== 0) {
|
|
165
|
+
throw new Error('The compare method requires an even number of indices to form comparison pairs.');
|
|
166
|
+
}
|
|
167
|
+
/** @type {(DiffResult[])[]} */
|
|
168
|
+
const results = [];
|
|
169
|
+
for (let i = 0; i < totalIndexes; i += 2) {
|
|
170
|
+
const i2 = i + 1;
|
|
171
|
+
if (i2 > totalIndexes - 1)
|
|
172
|
+
continue;
|
|
173
|
+
this.#checkIndex(indexes[i]);
|
|
174
|
+
this.#checkIndex(indexes[i2]);
|
|
175
|
+
/** @type {string} */
|
|
176
|
+
const str1 = this.#history[indexes[i]];
|
|
177
|
+
/** @type {string} */
|
|
178
|
+
const str2 = this.#history[indexes[i2]];
|
|
179
|
+
results.push(this._computeDiff(str1, str2));
|
|
180
|
+
}
|
|
181
|
+
return results;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Computes the Longest Common Subsequence (LCS) to generate the diff result.
|
|
185
|
+
* @private
|
|
186
|
+
* @param {string} str1
|
|
187
|
+
* @param {string} str2
|
|
188
|
+
* @returns {DiffResult[]}
|
|
189
|
+
*/
|
|
190
|
+
_computeDiff(str1, str2) {
|
|
191
|
+
/** @type {number} */
|
|
192
|
+
const len1 = str1.length;
|
|
193
|
+
/** @type {number} */
|
|
194
|
+
const len2 = str2.length;
|
|
195
|
+
/** @type {number[][]} */
|
|
196
|
+
const matrix = Array(len1 + 1)
|
|
197
|
+
.fill(null)
|
|
198
|
+
.map(() => Array(len2 + 1).fill(0));
|
|
199
|
+
/** @type {number} */
|
|
200
|
+
let i = 1;
|
|
201
|
+
/** @type {number} */
|
|
202
|
+
let j = 1;
|
|
203
|
+
for (i = 1; i <= len1; i++) {
|
|
204
|
+
for (j = 1; j <= len2; j++) {
|
|
205
|
+
if (str1[i - 1] === str2[j - 1]) {
|
|
206
|
+
matrix[i][j] = matrix[i - 1][j - 1] + 1;
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
matrix[i][j] = Math.max(matrix[i - 1][j], matrix[i][j - 1]);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
i = len1;
|
|
214
|
+
j = len2;
|
|
215
|
+
/** @type {DiffResult[]} */
|
|
216
|
+
const result = [];
|
|
217
|
+
while (i > 0 || j > 0) {
|
|
218
|
+
if (i > 0 && j > 0 && str1[i - 1] === str2[j - 1]) {
|
|
219
|
+
result.unshift({ value: str1[i - 1], type: 'normal' });
|
|
220
|
+
i--;
|
|
221
|
+
j--;
|
|
222
|
+
}
|
|
223
|
+
else if (j > 0 && (i === 0 || matrix[i][j - 1] >= matrix[i - 1][j])) {
|
|
224
|
+
result.unshift({ value: str2[j - 1], type: 'added' });
|
|
225
|
+
j--;
|
|
226
|
+
}
|
|
227
|
+
else if (i > 0 && (j === 0 || matrix[i][j - 1] < matrix[i - 1][j])) {
|
|
228
|
+
result.unshift({ value: str1[i - 1], type: 'deleted' });
|
|
229
|
+
i--;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
return result.reduce((/** @type {DiffResult[]} */ acc, /** @type {DiffResult} */ curr) => {
|
|
233
|
+
/** @type {number} */
|
|
234
|
+
const lastIndex = acc.length - 1;
|
|
235
|
+
if (acc.length > 0 && acc[lastIndex].type === curr.type) {
|
|
236
|
+
acc[lastIndex].value += curr.value;
|
|
237
|
+
}
|
|
238
|
+
else {
|
|
239
|
+
acc.push(curr);
|
|
240
|
+
}
|
|
241
|
+
return acc;
|
|
242
|
+
}, []);
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Cleans up internal references and marks the instance as destroyed to prevent memory leaks.
|
|
246
|
+
* @returns {void}
|
|
247
|
+
*/
|
|
248
|
+
destroy() {
|
|
249
|
+
if (this.#destroyed)
|
|
250
|
+
return;
|
|
251
|
+
this.#history = [];
|
|
252
|
+
this.#destroyed = true;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
export default TinyTextDiffer;
|
package/docs/v1/README.md
CHANGED
|
@@ -60,6 +60,8 @@ This folder contains the core scripts we have worked on so far. Each file is a m
|
|
|
60
60
|
- ๐ **[TinyElementObserver](./libs/TinyElementObserver.md)** โ A DOM mutation tracking utility built on MutationObserver, with customizable detectors for handling changes, event dispatching, and lifecycle management.
|
|
61
61
|
- โณ **[TinyLoadingScreen](./libs/TinyLoadingScreen.md)** โ A lightweight, fully-configurable loading overlay with fade-in/out animations, custom messages (string or HTMLElement), HTML rendering option, and status-change callbacks.
|
|
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
|
+
* ๐ **[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
|
+
* ๐ **[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.
|
|
63
65
|
|
|
64
66
|
### 3. **`fileManager/`**
|
|
65
67
|
* ๐ **[Main](./fileManager/main.md)** โ A Node.js file/directory utility module with support for JSON, backups, renaming, size analysis, and more.
|
|
@@ -98,13 +100,8 @@ Feel free to suggest changes, improvements, or additional features. You can fork
|
|
|
98
100
|
|
|
99
101
|
## ๐ Want to Know How I Use AI in My Projects?
|
|
100
102
|
|
|
101
|
-
If you're curious about how I integrate AI into my development workflow โ including how I manage prompts, avoid context drift, and keep control over logic and documentation โ
|
|
103
|
+
If you're curious about how I integrate AI into my development workflow โ including how I manage prompts, avoid context drift, and keep full control over logic and documentation โ all related guides have been moved to a dedicated documentation space.
|
|
102
104
|
|
|
103
|
-
|
|
104
|
-
Personal tips, common pitfalls to avoid, and how I keep AI assistance effective without losing my own creative and logical direction.
|
|
105
|
+
โจ **Visit the Tiny-Essentials documentation hub here:**
|
|
105
106
|
|
|
106
|
-
|
|
107
|
-
A curated collection of my most-used AI prompts for various tasks like coding, writing, automation, and technical documentation โ written in English.
|
|
108
|
-
|
|
109
|
-
* [**Personal AI Prompts (Portuguese)**](./Personal-Ai-Prompts%28portuguese%29.md)
|
|
110
|
-
The same set of personal AI prompts, but fully translated into Portuguese for ease of use in native language contexts.
|
|
107
|
+
๐ [https://github.com/Tiny-Essentials/.github/tree/main/docs](https://github.com/Tiny-Essentials/.github/tree/main/docs)
|
package/docs/v1/basics/html.md
CHANGED
|
@@ -155,6 +155,21 @@ Loads data from a remote URL using the Fetch API, with support for custom HTTP m
|
|
|
155
155
|
* `retries` *(number)*: Number of retry attempts if the request fails. Default is `0`.
|
|
156
156
|
* `headers` *(object)*: Additional headers to include in the request.
|
|
157
157
|
* `body` *(object)*: Request body. If the value is a plain object, it will be automatically stringified as JSON.
|
|
158
|
+
* `onProgress` *((loaded: number, total: number) => void)*: Track the load progress.
|
|
159
|
+
|
|
160
|
+
#### `trackFetchProgress(response, onProgress)`
|
|
161
|
+
|
|
162
|
+
Intercepts a standard Fetch API Response to track the download progress of its body stream.
|
|
163
|
+
|
|
164
|
+
* **Parameters**:
|
|
165
|
+
|
|
166
|
+
* `response` *(Response)*: The original response object to be tracked.
|
|
167
|
+
* `options` *(FetchOnProgressResult)*: The callback function to handle progress events (loaded and total numbers).
|
|
168
|
+
|
|
169
|
+
* **Returns**:
|
|
170
|
+
`Response` โ A new Response object with the tracked stream.
|
|
171
|
+
|
|
172
|
+
---
|
|
158
173
|
|
|
159
174
|
#### `fetchJson(url, options?)`
|
|
160
175
|
|
|
@@ -374,3 +389,57 @@ stopWatching(); // later
|
|
|
374
389
|
transition: opacity 0.3s ease;
|
|
375
390
|
}
|
|
376
391
|
```
|
|
392
|
+
|
|
393
|
+
---
|
|
394
|
+
|
|
395
|
+
### ๐ `loadImage(options): Promise<object>`
|
|
396
|
+
|
|
397
|
+
A robust, asynchronous utility for loading images in the browser. It captures critical lifecycle events and provides a normalized result object, making it much easier to handle image loading states and performance metrics.
|
|
398
|
+
|
|
399
|
+
#### โจ Features
|
|
400
|
+
|
|
401
|
+
* **Asynchronous:** Returns a clean `Promise`.
|
|
402
|
+
* **Performance Tracking:** Automatically calculates the time taken to load the image.
|
|
403
|
+
* **Memory Safe:** Includes a cleanup mechanism for event listeners.
|
|
404
|
+
* **Normalized Output:** Returns consistent data structures for both success and edge cases.
|
|
405
|
+
|
|
406
|
+
#### ๐ฅ Parameters
|
|
407
|
+
|
|
408
|
+
| Parameter | Type | Default | Description |
|
|
409
|
+
| --- | --- | --- | --- |
|
|
410
|
+
| `url` | `string` | **Required** | The source URL of the image. |
|
|
411
|
+
| `crossOrigin` | `string` | `'anonymous'` | The CORS policy for the request. |
|
|
412
|
+
| `onLoading` | `function` | `undefined` | Callback fired when the browser starts the network request. |
|
|
413
|
+
|
|
414
|
+
#### ๐ค Returns
|
|
415
|
+
|
|
416
|
+
The promise resolves to an object containing:
|
|
417
|
+
|
|
418
|
+
* **`element`**: `HTMLImageElement` - The actual image object.
|
|
419
|
+
* **`isSuccess`**: `boolean` - True if the image loaded correctly.
|
|
420
|
+
* **`event`**: `Event` - The raw event captured from the browser.
|
|
421
|
+
* **`status`**: `string` - `'loaded'` or `'aborted'`.
|
|
422
|
+
* **`loadTimeMs`**: `number` - Total duration of the request in milliseconds.
|
|
423
|
+
* **`dimensions`**: `Object` - Contains `width`, `height`, `naturalWidth`, and `naturalHeight`.
|
|
424
|
+
|
|
425
|
+
#### ๐งช Example
|
|
426
|
+
|
|
427
|
+
```javascript
|
|
428
|
+
import { loadImage } from './html.mjs';
|
|
429
|
+
|
|
430
|
+
const handleLoading = (event, startTime) => {
|
|
431
|
+
console.log('Started loading at:', startTime);
|
|
432
|
+
};
|
|
433
|
+
|
|
434
|
+
const result = await loadImage({
|
|
435
|
+
url: 'https://example.com/image.png',
|
|
436
|
+
onLoading: handleLoading,
|
|
437
|
+
crossOrigin: 'anonymous'
|
|
438
|
+
});
|
|
439
|
+
|
|
440
|
+
if (result.isSuccess) {
|
|
441
|
+
console.log(`Image loaded in ${result.loadTimeMs.toFixed(2)}ms`);
|
|
442
|
+
document.body.appendChild(result.element);
|
|
443
|
+
}
|
|
444
|
+
```
|
|
445
|
+
> **Note:** The utility uses `performance.now()` for high-resolution timestamps, ensuring accurate performance monitoring of your assets.
|