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.
Files changed (37) hide show
  1. package/README.md +8 -8
  2. package/changelog/1/25/0.md +13 -0
  3. package/changelog/1/25/1.md +18 -0
  4. package/dist/v1/TinyAnalogClock.min.js +1 -0
  5. package/dist/v1/TinyBasicsEs.min.js +1 -1
  6. package/dist/v1/TinyEssentials.min.js +1 -1
  7. package/dist/v1/TinyTextDiffer.min.js +1 -0
  8. package/dist/v1/basics/html.cjs +151 -2
  9. package/dist/v1/basics/html.d.mts +109 -0
  10. package/dist/v1/basics/html.mjs +135 -2
  11. package/dist/v1/build/TinyAnalogClock.cjs +7 -0
  12. package/dist/v1/build/TinyAnalogClock.d.mts +3 -0
  13. package/dist/v1/build/TinyAnalogClock.mjs +2 -0
  14. package/dist/v1/build/TinyTextDiffer.cjs +7 -0
  15. package/dist/v1/build/TinyTextDiffer.d.mts +3 -0
  16. package/dist/v1/build/TinyTextDiffer.mjs +2 -0
  17. package/dist/v1/index.cjs +4 -0
  18. package/dist/v1/index.d.mts +3 -1
  19. package/dist/v1/index.mjs +3 -1
  20. package/dist/v1/libs/TinyAnalogClock.cjs +738 -0
  21. package/dist/v1/libs/TinyAnalogClock.d.mts +342 -0
  22. package/dist/v1/libs/TinyAnalogClock.mjs +653 -0
  23. package/dist/v1/libs/TinyRateLimiter.cjs +215 -31
  24. package/dist/v1/libs/TinyRateLimiter.d.mts +179 -25
  25. package/dist/v1/libs/TinyRateLimiter.mjs +215 -31
  26. package/dist/v1/libs/TinyTextDiffer.cjs +288 -0
  27. package/dist/v1/libs/TinyTextDiffer.d.mts +109 -0
  28. package/dist/v1/libs/TinyTextDiffer.mjs +255 -0
  29. package/docs/v1/README.md +5 -8
  30. package/docs/v1/basics/html.md +69 -0
  31. package/docs/v1/libs/TinyAnalogClock.md +295 -0
  32. package/docs/v1/libs/TinyRateLimiter.md +11 -0
  33. package/docs/v1/libs/TinyTextDiffer.md +114 -0
  34. package/package.json +12 -4
  35. package/docs/v1/Ai-Tips.md +0 -51
  36. package/docs/v1/Personal-Ai-Prompts(portuguese).md +0 -134
  37. 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 โ€” feel free to check out the following guides:
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
- * [**AI Tips & Workflow**](./Ai-Tips.md)
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
- * [**Personal AI Prompts**](./Personal-Ai-Prompts.md)
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)
@@ -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.