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 @@
|
|
|
1
|
+
(()=>{"use strict";var e={d:(t,r)=>{for(var s in r)e.o(r,s)&&!e.o(t,s)&&Object.defineProperty(t,s,{enumerable:!0,get:r[s]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)},t={};e.d(t,{TinyTextDiffer:()=>r});const r=class{#e=[];#t=!1;get history(){return[...this.#e]}set history(e){if(!Array.isArray(e))throw new TypeError("History data must be provided as an array.");if(!e.every(e=>"string"==typeof e))throw new TypeError("All items in the history array must be strings.");this.#e=[...e]}get size(){return this.#e.length}constructor(e=[]){this.history=e}#r(){if(this.#t)throw new Error("Cannot perform operations on a destroyed TinyTextDiffer instance.")}#s(e){if("number"!=typeof e)throw new TypeError("The provided index must be a valid number.")}#i(e){if("string"!=typeof e)throw new TypeError("The provided text must be a valid string.")}get(e){if(this.#r(),this.#s(e),void 0===this.#e[e])throw new Error(`No text version found at index ${e}.`);return this.#e[e]}has(e){return this.#r(),this.#s(e),void 0!==this.#e[e]}add(e){this.#r(),this.#i(e),this.#e.push(e)}remove(){return this.#r(),this.#e.pop()}addAt(e,t){this.#r(),this.#s(e),this.#i(t),this.#e.splice(e,0,t)}removeAt(e){this.#r(),this.#s(e);const t=this.#e.length;return this.#e.splice(e,1),t!==this.#e.length}clear(){this.#r(),this.#e=[]}compare(...e){this.#r();const t=e.length;if(0===t||t%2!=0)throw new Error("The compare method requires an even number of indices to form comparison pairs.");const r=[];for(let s=0;s<t;s+=2){const i=s+1;if(i>t-1)continue;this.#s(e[s]),this.#s(e[i]);const h=this.#e[e[s]],o=this.#e[e[i]];r.push(this._computeDiff(h,o))}return r}_computeDiff(e,t){const r=e.length,s=t.length,i=Array(r+1).fill(null).map(()=>Array(s+1).fill(0));let h=1,o=1;for(h=1;h<=r;h++)for(o=1;o<=s;o++)e[h-1]===t[o-1]?i[h][o]=i[h-1][o-1]+1:i[h][o]=Math.max(i[h-1][o],i[h][o-1]);h=r,o=s;const n=[];for(;h>0||o>0;)h>0&&o>0&&e[h-1]===t[o-1]?(n.unshift({value:e[h-1],type:"normal"}),h--,o--):o>0&&(0===h||i[h][o-1]>=i[h-1][o])?(n.unshift({value:t[o-1],type:"added"}),o--):h>0&&(0===o||i[h][o-1]<i[h-1][o])&&(n.unshift({value:e[h-1],type:"deleted"}),h--);return n.reduce((e,t)=>{const r=e.length-1;return e.length>0&&e[r].type===t.type?e[r].value+=t.value:e.push(t),e},[])}destroy(){this.#t||(this.#e=[],this.#t=!0)}};window.TinyTextDiffer=t.TinyTextDiffer})();
|
package/dist/v1/basics/html.cjs
CHANGED
|
@@ -134,8 +134,60 @@ function saveJsonFile(filename, data, spaces = 2) {
|
|
|
134
134
|
* @property {number} [retries=0] - Number of retry attempts (ignored if signal is provided).
|
|
135
135
|
* @property {Headers|Record<string, *>} [headers={}] - Additional headers.
|
|
136
136
|
* @property {AbortSignal|null} [signal] - External AbortSignal; disables timeout and retries.
|
|
137
|
+
* @property {FetchOnProgressResult} [onProgress] - Track the load progress.
|
|
137
138
|
*/
|
|
138
139
|
|
|
140
|
+
/**
|
|
141
|
+
* Callback function used to report the progress of a data download.
|
|
142
|
+
*
|
|
143
|
+
* @callback FetchOnProgressResult
|
|
144
|
+
* @param {number} loaded - The amount of bytes currently loaded.
|
|
145
|
+
* @param {number} total - The total amount of bytes to be loaded (0 if unknown).
|
|
146
|
+
* @returns {void}
|
|
147
|
+
*/
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Intercepts a standard Fetch API Response to track the download progress
|
|
151
|
+
* of its body stream.
|
|
152
|
+
*
|
|
153
|
+
* This function returns a new Response object with a monitored ReadableStream,
|
|
154
|
+
* allowing the provided callback to receive updates on the number of bytes loaded.
|
|
155
|
+
*
|
|
156
|
+
* @param {Response} response - The original response object to be tracked.
|
|
157
|
+
* @param {FetchOnProgressResult} onProgress - The callback function to handle progress events.
|
|
158
|
+
* @returns {Response} A new Response object with the tracked stream.
|
|
159
|
+
*/
|
|
160
|
+
function trackFetchProgress(response, onProgress) {
|
|
161
|
+
if (typeof onProgress !== 'function')
|
|
162
|
+
throw new TypeError('The "onProgress" argument must be a function.');
|
|
163
|
+
if (!response.body) return response;
|
|
164
|
+
|
|
165
|
+
// Handle Progress Tracking via ReadableStream
|
|
166
|
+
const contentLength = response.headers.get('content-length');
|
|
167
|
+
const total = contentLength ? parseInt(contentLength, 10) : 0;
|
|
168
|
+
let loaded = 0;
|
|
169
|
+
|
|
170
|
+
const reader = response.body.getReader();
|
|
171
|
+
const stream = new ReadableStream({
|
|
172
|
+
async start(controller) {
|
|
173
|
+
while (true) {
|
|
174
|
+
const { done, value } = await reader.read();
|
|
175
|
+
if (done) break;
|
|
176
|
+
loaded += value.byteLength;
|
|
177
|
+
onProgress(loaded, total);
|
|
178
|
+
controller.enqueue(value);
|
|
179
|
+
}
|
|
180
|
+
controller.close();
|
|
181
|
+
},
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
return new Response(stream, {
|
|
185
|
+
headers: response.headers,
|
|
186
|
+
status: response.status,
|
|
187
|
+
statusText: response.statusText,
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
|
|
139
191
|
/**
|
|
140
192
|
* @param {string} url - The full URL to fetch data from.
|
|
141
193
|
* @param {FetchTemplateOptions} [options] - Optional settings.
|
|
@@ -144,7 +196,7 @@ function saveJsonFile(filename, data, spaces = 2) {
|
|
|
144
196
|
*/
|
|
145
197
|
async function fetchTemplate(
|
|
146
198
|
url,
|
|
147
|
-
{ method = 'GET', body, timeout = 0, retries = 0, headers = {}, signal = null } = {},
|
|
199
|
+
{ method = 'GET', body, timeout = 0, retries = 0, headers = {}, signal = null, onProgress } = {},
|
|
148
200
|
) {
|
|
149
201
|
if (
|
|
150
202
|
typeof url !== 'string' ||
|
|
@@ -201,7 +253,10 @@ async function fetchTemplate(
|
|
|
201
253
|
if (timer) clearTimeout(timer);
|
|
202
254
|
|
|
203
255
|
if (!response.ok) throw new Error(`HTTP error: ${response.status} ${response.statusText}`);
|
|
204
|
-
|
|
256
|
+
|
|
257
|
+
// If onProgress is not provided or body is null, return original response
|
|
258
|
+
if (!onProgress) return response;
|
|
259
|
+
return trackFetchProgress(response, onProgress);
|
|
205
260
|
} catch (err) {
|
|
206
261
|
lastError = /** @type {Error} */ (err);
|
|
207
262
|
if (signal) break; // if an external signal came, it does not retry
|
|
@@ -304,6 +359,98 @@ async function fetchText(url, allowedMimeTypes, options) {
|
|
|
304
359
|
|
|
305
360
|
///////////////////////////////////////////////////////////////////////////////
|
|
306
361
|
|
|
362
|
+
/**
|
|
363
|
+
* Represents the final state and metadata of an attempted image load.
|
|
364
|
+
* @typedef {Object} ImageLoadResult
|
|
365
|
+
* @property {HTMLImageElement} element The image element instance used for loading.
|
|
366
|
+
* @property {Event} event The browser event triggered by the final lifecycle state.
|
|
367
|
+
* @property {ImageLoadStatus} status The specific outcome string of the loading process.
|
|
368
|
+
* @property {boolean} isSuccess Indicates if the image was successfully loaded without errors.
|
|
369
|
+
* @property {number} loadTimeMs The total duration in milliseconds from start to finish.
|
|
370
|
+
* @property {Object} dimensions An object containing the rendered and intrinsic sizes of the image.
|
|
371
|
+
* @property {number} dimensions.width The current layout width of the image element.
|
|
372
|
+
* @property {number} dimensions.height The current layout height of the image element.
|
|
373
|
+
* @property {number} dimensions.naturalWidth The intrinsic width of the image source in pixels.
|
|
374
|
+
* @property {number} dimensions.naturalHeight The intrinsic height of the image source in pixels.
|
|
375
|
+
*/
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
* Describes the possible resolution states for the image loading attempt.
|
|
379
|
+
* @typedef {'loaded'|'aborted'} ImageLoadStatus
|
|
380
|
+
*/
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* Loads an image asynchronously, capturing critical lifecycle events.
|
|
384
|
+
* It normalizes errors and success states into a consistent result structure.
|
|
385
|
+
*
|
|
386
|
+
* @param {Object} options
|
|
387
|
+
* @param {string} options.url
|
|
388
|
+
* @param {string} [options.crossOrigin="anonymous"]
|
|
389
|
+
* @param {(event: Event, startTime: number) => void} [options.onLoading]
|
|
390
|
+
* @returns {Promise<ImageLoadResult>}
|
|
391
|
+
*/
|
|
392
|
+
async function loadImage({ url, onLoading, crossOrigin = 'anonymous' }) {
|
|
393
|
+
return new Promise((resolve, reject) => {
|
|
394
|
+
const img = new Image();
|
|
395
|
+
let startTime = performance.now();
|
|
396
|
+
|
|
397
|
+
img.crossOrigin = crossOrigin;
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* Cleans up event listeners to avoid memory leaks.
|
|
401
|
+
*/
|
|
402
|
+
const cleanup = () => {
|
|
403
|
+
img.onload = null;
|
|
404
|
+
img.onerror = null;
|
|
405
|
+
img.onabort = null;
|
|
406
|
+
img.onloadstart = null;
|
|
407
|
+
};
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* Centralized handler to generate the result object.
|
|
411
|
+
* @param {Event} event
|
|
412
|
+
* @param {ImageLoadStatus} status
|
|
413
|
+
* @param {boolean} isSuccess
|
|
414
|
+
*/
|
|
415
|
+
const handleResult = (event, status, isSuccess) => {
|
|
416
|
+
const endTime = performance.now();
|
|
417
|
+
cleanup();
|
|
418
|
+
|
|
419
|
+
const result = {
|
|
420
|
+
element: img,
|
|
421
|
+
isSuccess,
|
|
422
|
+
event,
|
|
423
|
+
status,
|
|
424
|
+
loadTimeMs: endTime - startTime,
|
|
425
|
+
dimensions: {
|
|
426
|
+
width: img.width,
|
|
427
|
+
height: img.height,
|
|
428
|
+
naturalWidth: img.naturalWidth,
|
|
429
|
+
naturalHeight: img.naturalHeight,
|
|
430
|
+
},
|
|
431
|
+
};
|
|
432
|
+
|
|
433
|
+
resolve(result);
|
|
434
|
+
};
|
|
435
|
+
|
|
436
|
+
// Fired when the browser starts looking for the image data.
|
|
437
|
+
// Crucial for resetting the timer to network start, not just script start.
|
|
438
|
+
img.onloadstart = (ev) => {
|
|
439
|
+
startTime = performance.now();
|
|
440
|
+
if (typeof onLoading === 'function') onLoading(ev, startTime);
|
|
441
|
+
};
|
|
442
|
+
|
|
443
|
+
img.onload = (ev) => handleResult(ev, 'loaded', true);
|
|
444
|
+
img.onabort = (ev) => handleResult(ev, 'aborted', false);
|
|
445
|
+
img.onerror = (ev) => reject(ev);
|
|
446
|
+
|
|
447
|
+
// Trigger the load
|
|
448
|
+
img.src = url;
|
|
449
|
+
});
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
453
|
+
|
|
307
454
|
/**
|
|
308
455
|
* Installs a script that toggles CSS classes on a given element
|
|
309
456
|
* based on the page's visibility or focus state, and optionally
|
|
@@ -438,7 +585,9 @@ exports.fetchBlob = fetchBlob;
|
|
|
438
585
|
exports.fetchJson = fetchJson;
|
|
439
586
|
exports.fetchText = fetchText;
|
|
440
587
|
exports.installWindowHiddenScript = installWindowHiddenScript;
|
|
588
|
+
exports.loadImage = loadImage;
|
|
441
589
|
exports.readBase64Blob = readBase64Blob;
|
|
442
590
|
exports.readFileBlob = readFileBlob;
|
|
443
591
|
exports.readJsonBlob = readJsonBlob;
|
|
444
592
|
exports.saveJsonFile = saveJsonFile;
|
|
593
|
+
exports.trackFetchProgress = trackFetchProgress;
|
|
@@ -45,6 +45,36 @@ export function readJsonBlob(file: File): Promise<Record<string | number | symbo
|
|
|
45
45
|
* @param {number} [spaces=2]
|
|
46
46
|
*/
|
|
47
47
|
export function saveJsonFile(filename: string, data: any, spaces?: number): void;
|
|
48
|
+
/**
|
|
49
|
+
* @typedef {Object} FetchTemplateOptions
|
|
50
|
+
* @property {string} [method="GET"] - HTTP method to use (GET, POST, etc.).
|
|
51
|
+
* @property {any} [body] - Request body (only for methods like POST, PUT).
|
|
52
|
+
* @property {number} [timeout=0] - Timeout in milliseconds (ignored if signal is provided).
|
|
53
|
+
* @property {number} [retries=0] - Number of retry attempts (ignored if signal is provided).
|
|
54
|
+
* @property {Headers|Record<string, *>} [headers={}] - Additional headers.
|
|
55
|
+
* @property {AbortSignal|null} [signal] - External AbortSignal; disables timeout and retries.
|
|
56
|
+
* @property {FetchOnProgressResult} [onProgress] - Track the load progress.
|
|
57
|
+
*/
|
|
58
|
+
/**
|
|
59
|
+
* Callback function used to report the progress of a data download.
|
|
60
|
+
*
|
|
61
|
+
* @callback FetchOnProgressResult
|
|
62
|
+
* @param {number} loaded - The amount of bytes currently loaded.
|
|
63
|
+
* @param {number} total - The total amount of bytes to be loaded (0 if unknown).
|
|
64
|
+
* @returns {void}
|
|
65
|
+
*/
|
|
66
|
+
/**
|
|
67
|
+
* Intercepts a standard Fetch API Response to track the download progress
|
|
68
|
+
* of its body stream.
|
|
69
|
+
*
|
|
70
|
+
* This function returns a new Response object with a monitored ReadableStream,
|
|
71
|
+
* allowing the provided callback to receive updates on the number of bytes loaded.
|
|
72
|
+
*
|
|
73
|
+
* @param {Response} response - The original response object to be tracked.
|
|
74
|
+
* @param {FetchOnProgressResult} onProgress - The callback function to handle progress events.
|
|
75
|
+
* @returns {Response} A new Response object with the tracked stream.
|
|
76
|
+
*/
|
|
77
|
+
export function trackFetchProgress(response: Response, onProgress: FetchOnProgressResult): Response;
|
|
48
78
|
/**
|
|
49
79
|
* Loads and parses a JSON from a remote URL using Fetch API.
|
|
50
80
|
*
|
|
@@ -74,6 +104,39 @@ export function fetchBlob(url: string, allowedMimeTypes?: string[], options?: Fe
|
|
|
74
104
|
* @throws {Error} Throws if fetch fails, response is not ok, or MIME type is not allowed.
|
|
75
105
|
*/
|
|
76
106
|
export function fetchText(url: string, allowedMimeTypes?: string[], options?: FetchTemplateOptions): Promise<string>;
|
|
107
|
+
/**
|
|
108
|
+
* Represents the final state and metadata of an attempted image load.
|
|
109
|
+
* @typedef {Object} ImageLoadResult
|
|
110
|
+
* @property {HTMLImageElement} element The image element instance used for loading.
|
|
111
|
+
* @property {Event} event The browser event triggered by the final lifecycle state.
|
|
112
|
+
* @property {ImageLoadStatus} status The specific outcome string of the loading process.
|
|
113
|
+
* @property {boolean} isSuccess Indicates if the image was successfully loaded without errors.
|
|
114
|
+
* @property {number} loadTimeMs The total duration in milliseconds from start to finish.
|
|
115
|
+
* @property {Object} dimensions An object containing the rendered and intrinsic sizes of the image.
|
|
116
|
+
* @property {number} dimensions.width The current layout width of the image element.
|
|
117
|
+
* @property {number} dimensions.height The current layout height of the image element.
|
|
118
|
+
* @property {number} dimensions.naturalWidth The intrinsic width of the image source in pixels.
|
|
119
|
+
* @property {number} dimensions.naturalHeight The intrinsic height of the image source in pixels.
|
|
120
|
+
*/
|
|
121
|
+
/**
|
|
122
|
+
* Describes the possible resolution states for the image loading attempt.
|
|
123
|
+
* @typedef {'loaded'|'aborted'} ImageLoadStatus
|
|
124
|
+
*/
|
|
125
|
+
/**
|
|
126
|
+
* Loads an image asynchronously, capturing critical lifecycle events.
|
|
127
|
+
* It normalizes errors and success states into a consistent result structure.
|
|
128
|
+
*
|
|
129
|
+
* @param {Object} options
|
|
130
|
+
* @param {string} options.url
|
|
131
|
+
* @param {string} [options.crossOrigin="anonymous"]
|
|
132
|
+
* @param {(event: Event, startTime: number) => void} [options.onLoading]
|
|
133
|
+
* @returns {Promise<ImageLoadResult>}
|
|
134
|
+
*/
|
|
135
|
+
export function loadImage({ url, onLoading, crossOrigin }: {
|
|
136
|
+
url: string;
|
|
137
|
+
crossOrigin?: string | undefined;
|
|
138
|
+
onLoading?: ((event: Event, startTime: number) => void) | undefined;
|
|
139
|
+
}): Promise<ImageLoadResult>;
|
|
77
140
|
/**
|
|
78
141
|
* Installs a script that toggles CSS classes on a given element
|
|
79
142
|
* based on the page's visibility or focus state, and optionally
|
|
@@ -128,5 +191,51 @@ export type FetchTemplateOptions = {
|
|
|
128
191
|
* - External AbortSignal; disables timeout and retries.
|
|
129
192
|
*/
|
|
130
193
|
signal?: AbortSignal | null | undefined;
|
|
194
|
+
/**
|
|
195
|
+
* - Track the load progress.
|
|
196
|
+
*/
|
|
197
|
+
onProgress?: FetchOnProgressResult | undefined;
|
|
131
198
|
};
|
|
199
|
+
/**
|
|
200
|
+
* Callback function used to report the progress of a data download.
|
|
201
|
+
*/
|
|
202
|
+
export type FetchOnProgressResult = (loaded: number, total: number) => void;
|
|
203
|
+
/**
|
|
204
|
+
* Represents the final state and metadata of an attempted image load.
|
|
205
|
+
*/
|
|
206
|
+
export type ImageLoadResult = {
|
|
207
|
+
/**
|
|
208
|
+
* The image element instance used for loading.
|
|
209
|
+
*/
|
|
210
|
+
element: HTMLImageElement;
|
|
211
|
+
/**
|
|
212
|
+
* The browser event triggered by the final lifecycle state.
|
|
213
|
+
*/
|
|
214
|
+
event: Event;
|
|
215
|
+
/**
|
|
216
|
+
* The specific outcome string of the loading process.
|
|
217
|
+
*/
|
|
218
|
+
status: ImageLoadStatus;
|
|
219
|
+
/**
|
|
220
|
+
* Indicates if the image was successfully loaded without errors.
|
|
221
|
+
*/
|
|
222
|
+
isSuccess: boolean;
|
|
223
|
+
/**
|
|
224
|
+
* The total duration in milliseconds from start to finish.
|
|
225
|
+
*/
|
|
226
|
+
loadTimeMs: number;
|
|
227
|
+
/**
|
|
228
|
+
* An object containing the rendered and intrinsic sizes of the image.
|
|
229
|
+
*/
|
|
230
|
+
dimensions: {
|
|
231
|
+
width: number;
|
|
232
|
+
height: number;
|
|
233
|
+
naturalWidth: number;
|
|
234
|
+
naturalHeight: number;
|
|
235
|
+
};
|
|
236
|
+
};
|
|
237
|
+
/**
|
|
238
|
+
* Describes the possible resolution states for the image loading attempt.
|
|
239
|
+
*/
|
|
240
|
+
export type ImageLoadStatus = "loaded" | "aborted";
|
|
132
241
|
//# sourceMappingURL=html.d.mts.map
|
package/dist/v1/basics/html.mjs
CHANGED
|
@@ -122,14 +122,63 @@ export function saveJsonFile(filename, data, spaces = 2) {
|
|
|
122
122
|
* @property {number} [retries=0] - Number of retry attempts (ignored if signal is provided).
|
|
123
123
|
* @property {Headers|Record<string, *>} [headers={}] - Additional headers.
|
|
124
124
|
* @property {AbortSignal|null} [signal] - External AbortSignal; disables timeout and retries.
|
|
125
|
+
* @property {FetchOnProgressResult} [onProgress] - Track the load progress.
|
|
125
126
|
*/
|
|
127
|
+
/**
|
|
128
|
+
* Callback function used to report the progress of a data download.
|
|
129
|
+
*
|
|
130
|
+
* @callback FetchOnProgressResult
|
|
131
|
+
* @param {number} loaded - The amount of bytes currently loaded.
|
|
132
|
+
* @param {number} total - The total amount of bytes to be loaded (0 if unknown).
|
|
133
|
+
* @returns {void}
|
|
134
|
+
*/
|
|
135
|
+
/**
|
|
136
|
+
* Intercepts a standard Fetch API Response to track the download progress
|
|
137
|
+
* of its body stream.
|
|
138
|
+
*
|
|
139
|
+
* This function returns a new Response object with a monitored ReadableStream,
|
|
140
|
+
* allowing the provided callback to receive updates on the number of bytes loaded.
|
|
141
|
+
*
|
|
142
|
+
* @param {Response} response - The original response object to be tracked.
|
|
143
|
+
* @param {FetchOnProgressResult} onProgress - The callback function to handle progress events.
|
|
144
|
+
* @returns {Response} A new Response object with the tracked stream.
|
|
145
|
+
*/
|
|
146
|
+
export function trackFetchProgress(response, onProgress) {
|
|
147
|
+
if (typeof onProgress !== 'function')
|
|
148
|
+
throw new TypeError('The "onProgress" argument must be a function.');
|
|
149
|
+
if (!response.body)
|
|
150
|
+
return response;
|
|
151
|
+
// Handle Progress Tracking via ReadableStream
|
|
152
|
+
const contentLength = response.headers.get('content-length');
|
|
153
|
+
const total = contentLength ? parseInt(contentLength, 10) : 0;
|
|
154
|
+
let loaded = 0;
|
|
155
|
+
const reader = response.body.getReader();
|
|
156
|
+
const stream = new ReadableStream({
|
|
157
|
+
async start(controller) {
|
|
158
|
+
while (true) {
|
|
159
|
+
const { done, value } = await reader.read();
|
|
160
|
+
if (done)
|
|
161
|
+
break;
|
|
162
|
+
loaded += value.byteLength;
|
|
163
|
+
onProgress(loaded, total);
|
|
164
|
+
controller.enqueue(value);
|
|
165
|
+
}
|
|
166
|
+
controller.close();
|
|
167
|
+
},
|
|
168
|
+
});
|
|
169
|
+
return new Response(stream, {
|
|
170
|
+
headers: response.headers,
|
|
171
|
+
status: response.status,
|
|
172
|
+
statusText: response.statusText,
|
|
173
|
+
});
|
|
174
|
+
}
|
|
126
175
|
/**
|
|
127
176
|
* @param {string} url - The full URL to fetch data from.
|
|
128
177
|
* @param {FetchTemplateOptions} [options] - Optional settings.
|
|
129
178
|
* @returns {Promise<Response>} Result data.
|
|
130
179
|
* @throws {Error} Throws if fetch fails, times out.
|
|
131
180
|
*/
|
|
132
|
-
async function fetchTemplate(url, { method = 'GET', body, timeout = 0, retries = 0, headers = {}, signal = null } = {}) {
|
|
181
|
+
async function fetchTemplate(url, { method = 'GET', body, timeout = 0, retries = 0, headers = {}, signal = null, onProgress } = {}) {
|
|
133
182
|
if (typeof url !== 'string' ||
|
|
134
183
|
(!url.startsWith('../') &&
|
|
135
184
|
!url.startsWith('./') &&
|
|
@@ -172,7 +221,10 @@ async function fetchTemplate(url, { method = 'GET', body, timeout = 0, retries =
|
|
|
172
221
|
clearTimeout(timer);
|
|
173
222
|
if (!response.ok)
|
|
174
223
|
throw new Error(`HTTP error: ${response.status} ${response.statusText}`);
|
|
175
|
-
return response
|
|
224
|
+
// If onProgress is not provided or body is null, return original response
|
|
225
|
+
if (!onProgress)
|
|
226
|
+
return response;
|
|
227
|
+
return trackFetchProgress(response, onProgress);
|
|
176
228
|
}
|
|
177
229
|
catch (err) {
|
|
178
230
|
lastError = /** @type {Error} */ (err);
|
|
@@ -258,6 +310,87 @@ export async function fetchText(url, allowedMimeTypes, options) {
|
|
|
258
310
|
});
|
|
259
311
|
}
|
|
260
312
|
///////////////////////////////////////////////////////////////////////////////
|
|
313
|
+
/**
|
|
314
|
+
* Represents the final state and metadata of an attempted image load.
|
|
315
|
+
* @typedef {Object} ImageLoadResult
|
|
316
|
+
* @property {HTMLImageElement} element The image element instance used for loading.
|
|
317
|
+
* @property {Event} event The browser event triggered by the final lifecycle state.
|
|
318
|
+
* @property {ImageLoadStatus} status The specific outcome string of the loading process.
|
|
319
|
+
* @property {boolean} isSuccess Indicates if the image was successfully loaded without errors.
|
|
320
|
+
* @property {number} loadTimeMs The total duration in milliseconds from start to finish.
|
|
321
|
+
* @property {Object} dimensions An object containing the rendered and intrinsic sizes of the image.
|
|
322
|
+
* @property {number} dimensions.width The current layout width of the image element.
|
|
323
|
+
* @property {number} dimensions.height The current layout height of the image element.
|
|
324
|
+
* @property {number} dimensions.naturalWidth The intrinsic width of the image source in pixels.
|
|
325
|
+
* @property {number} dimensions.naturalHeight The intrinsic height of the image source in pixels.
|
|
326
|
+
*/
|
|
327
|
+
/**
|
|
328
|
+
* Describes the possible resolution states for the image loading attempt.
|
|
329
|
+
* @typedef {'loaded'|'aborted'} ImageLoadStatus
|
|
330
|
+
*/
|
|
331
|
+
/**
|
|
332
|
+
* Loads an image asynchronously, capturing critical lifecycle events.
|
|
333
|
+
* It normalizes errors and success states into a consistent result structure.
|
|
334
|
+
*
|
|
335
|
+
* @param {Object} options
|
|
336
|
+
* @param {string} options.url
|
|
337
|
+
* @param {string} [options.crossOrigin="anonymous"]
|
|
338
|
+
* @param {(event: Event, startTime: number) => void} [options.onLoading]
|
|
339
|
+
* @returns {Promise<ImageLoadResult>}
|
|
340
|
+
*/
|
|
341
|
+
export async function loadImage({ url, onLoading, crossOrigin = 'anonymous' }) {
|
|
342
|
+
return new Promise((resolve, reject) => {
|
|
343
|
+
const img = new Image();
|
|
344
|
+
let startTime = performance.now();
|
|
345
|
+
img.crossOrigin = crossOrigin;
|
|
346
|
+
/**
|
|
347
|
+
* Cleans up event listeners to avoid memory leaks.
|
|
348
|
+
*/
|
|
349
|
+
const cleanup = () => {
|
|
350
|
+
img.onload = null;
|
|
351
|
+
img.onerror = null;
|
|
352
|
+
img.onabort = null;
|
|
353
|
+
img.onloadstart = null;
|
|
354
|
+
};
|
|
355
|
+
/**
|
|
356
|
+
* Centralized handler to generate the result object.
|
|
357
|
+
* @param {Event} event
|
|
358
|
+
* @param {ImageLoadStatus} status
|
|
359
|
+
* @param {boolean} isSuccess
|
|
360
|
+
*/
|
|
361
|
+
const handleResult = (event, status, isSuccess) => {
|
|
362
|
+
const endTime = performance.now();
|
|
363
|
+
cleanup();
|
|
364
|
+
const result = {
|
|
365
|
+
element: img,
|
|
366
|
+
isSuccess,
|
|
367
|
+
event,
|
|
368
|
+
status,
|
|
369
|
+
loadTimeMs: endTime - startTime,
|
|
370
|
+
dimensions: {
|
|
371
|
+
width: img.width,
|
|
372
|
+
height: img.height,
|
|
373
|
+
naturalWidth: img.naturalWidth,
|
|
374
|
+
naturalHeight: img.naturalHeight,
|
|
375
|
+
},
|
|
376
|
+
};
|
|
377
|
+
resolve(result);
|
|
378
|
+
};
|
|
379
|
+
// Fired when the browser starts looking for the image data.
|
|
380
|
+
// Crucial for resetting the timer to network start, not just script start.
|
|
381
|
+
img.onloadstart = (ev) => {
|
|
382
|
+
startTime = performance.now();
|
|
383
|
+
if (typeof onLoading === 'function')
|
|
384
|
+
onLoading(ev, startTime);
|
|
385
|
+
};
|
|
386
|
+
img.onload = (ev) => handleResult(ev, 'loaded', true);
|
|
387
|
+
img.onabort = (ev) => handleResult(ev, 'aborted', false);
|
|
388
|
+
img.onerror = (ev) => reject(ev);
|
|
389
|
+
// Trigger the load
|
|
390
|
+
img.src = url;
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
261
394
|
/**
|
|
262
395
|
* Installs a script that toggles CSS classes on a given element
|
|
263
396
|
* based on the page's visibility or focus state, and optionally
|
package/dist/v1/index.cjs
CHANGED
|
@@ -47,6 +47,8 @@ var TinySimpleDice = require('./libs/TinySimpleDice.cjs');
|
|
|
47
47
|
var TinyElementObserver = require('./libs/TinyElementObserver.cjs');
|
|
48
48
|
var TinyLoadingScreen = require('./libs/TinyLoadingScreen.cjs');
|
|
49
49
|
var TinyColorValidator = require('./libs/TinyColorValidator.cjs');
|
|
50
|
+
var TinyAnalogClock = require('./libs/TinyAnalogClock.cjs');
|
|
51
|
+
var TinyTextDiffer = require('./libs/TinyTextDiffer.cjs');
|
|
50
52
|
|
|
51
53
|
|
|
52
54
|
|
|
@@ -175,3 +177,5 @@ exports.TinySimpleDice = TinySimpleDice;
|
|
|
175
177
|
exports.TinyElementObserver = TinyElementObserver;
|
|
176
178
|
exports.TinyLoadingScreen = TinyLoadingScreen;
|
|
177
179
|
exports.TinyColorValidator = TinyColorValidator;
|
|
180
|
+
exports.TinyAnalogClock = TinyAnalogClock;
|
|
181
|
+
exports.TinyTextDiffer = TinyTextDiffer;
|
package/dist/v1/index.d.mts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import TinyTextDiffer from './libs/TinyTextDiffer.mjs';
|
|
2
|
+
import TinyAnalogClock from './libs/TinyAnalogClock.mjs';
|
|
1
3
|
import TinyColorValidator from './libs/TinyColorValidator.mjs';
|
|
2
4
|
import TinyLoadingScreen from './libs/TinyLoadingScreen.mjs';
|
|
3
5
|
import TinyElementObserver from './libs/TinyElementObserver.mjs';
|
|
@@ -123,5 +125,5 @@ import { getTimeDuration } from './basics/clock.mjs';
|
|
|
123
125
|
import { shuffleArray } from './basics/array.mjs';
|
|
124
126
|
import { toTitleCase } from './basics/text.mjs';
|
|
125
127
|
import { toTitleCaseLowerFirst } from './basics/text.mjs';
|
|
126
|
-
export { 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 };
|
|
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 };
|
|
127
129
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/v1/index.mjs
CHANGED
|
@@ -45,7 +45,9 @@ import TinySimpleDice from './libs/TinySimpleDice.mjs';
|
|
|
45
45
|
import TinyElementObserver from './libs/TinyElementObserver.mjs';
|
|
46
46
|
import TinyLoadingScreen from './libs/TinyLoadingScreen.mjs';
|
|
47
47
|
import TinyColorValidator from './libs/TinyColorValidator.mjs';
|
|
48
|
+
import TinyAnalogClock from './libs/TinyAnalogClock.mjs';
|
|
49
|
+
import TinyTextDiffer from './libs/TinyTextDiffer.mjs';
|
|
48
50
|
// import TinyHtmlElems from './libs/TinyHtml/index.mjs';
|
|
49
|
-
export {
|
|
51
|
+
export { TinyTextDiffer, TinyAnalogClock,
|
|
50
52
|
// TinyHtmlElems,
|
|
51
53
|
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, };
|