ranuts 0.2.0-alpha.0 → 0.3.0-alpha.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/CLAUDE.md +107 -16
- package/README.md +7 -5
- package/README.zh-CN.md +7 -5
- package/dist/chain-CTywmh_H.js +1 -0
- package/dist/{color-CRdlaDqQ.js → color-Dohr9BXX.js} +1 -1
- package/dist/enums-BAgbyGdH.js +1 -0
- package/dist/i18n-Cf5TtRb4.js +1 -0
- package/dist/index.d.ts +1 -5
- package/dist/index.js +1 -1
- package/dist/src/node/appendFile.d.ts +3 -3
- package/dist/src/node/fileInfo.d.ts +2 -2
- package/dist/src/node/index.js +1 -1
- package/dist/src/node/paresUrl.d.ts +1 -1
- package/dist/src/node/readFile.d.ts +3 -3
- package/dist/src/node/traverse.d.ts +2 -2
- package/dist/src/node/watchFile.d.ts +3 -3
- package/dist/src/node/writeFile.d.ts +3 -3
- package/dist/src/utils/async.d.ts +81 -0
- package/dist/src/utils/audioRecorder.d.ts +1 -1
- package/dist/src/utils/behavior.d.ts +12 -3
- package/dist/src/utils/bom.d.ts +68 -178
- package/dist/src/utils/bridge.d.ts +153 -0
- package/dist/src/utils/canvas.d.ts +54 -0
- package/dist/src/utils/chain.d.ts +80 -0
- package/dist/src/utils/color.d.ts +76 -4
- package/dist/src/utils/compose.d.ts +1 -1
- package/dist/src/utils/console.d.ts +19 -1
- package/dist/src/utils/debounce.d.ts +27 -5
- package/dist/src/utils/device.d.ts +31 -3
- package/dist/src/utils/dom.d.ts +5 -84
- package/dist/src/utils/error.d.ts +18 -1
- package/dist/src/utils/event.d.ts +61 -0
- package/dist/src/utils/file.d.ts +30 -0
- package/dist/src/utils/i18n/index.js +1 -0
- package/dist/src/utils/i18n.d.ts +69 -0
- package/dist/src/utils/idb.d.ts +178 -0
- package/dist/src/utils/img.d.ts +60 -4
- package/dist/src/utils/index.d.ts +48 -16
- package/dist/src/utils/index.js +1 -1
- package/dist/src/utils/lang.d.ts +69 -0
- package/dist/src/utils/localePath.d.ts +62 -0
- package/dist/src/utils/memoize.d.ts +53 -5
- package/dist/src/utils/monitor.d.ts +55 -26
- package/dist/src/utils/number.d.ts +46 -9
- package/dist/src/utils/obj.d.ts +56 -31
- package/dist/src/utils/prefetch.d.ts +81 -0
- package/dist/src/utils/queue.d.ts +53 -23
- package/dist/src/utils/report.d.ts +51 -3
- package/dist/src/utils/request.d.ts +26 -7
- package/dist/src/utils/script.d.ts +26 -4
- package/dist/src/utils/segment.d.ts +62 -0
- package/dist/src/utils/signal.d.ts +35 -3
- package/dist/src/utils/storage.d.ts +57 -0
- package/dist/src/utils/str.d.ts +112 -88
- package/dist/src/utils/style.d.ts +31 -0
- package/dist/src/utils/subscribe.d.ts +5 -5
- package/dist/src/utils/throttle.d.ts +26 -13
- package/dist/src/utils/time.d.ts +38 -6
- package/dist/src/utils/tween.d.ts +40 -0
- package/dist/src/utils/visual/application.d.ts +4 -4
- package/dist/src/utils/visual/enums.d.ts +4 -4
- package/dist/src/utils/visual/graphics/graphics.d.ts +25 -25
- package/dist/src/utils/visual/graphics/graphicsData.d.ts +1 -1
- package/dist/src/utils/visual/graphics/graphicsGeometry.d.ts +6 -6
- package/dist/src/utils/visual/index.js +1 -1
- package/dist/src/utils/visual/math/matrix.d.ts +8 -8
- package/dist/src/utils/visual/math/transform.d.ts +1 -1
- package/dist/src/utils/visual/render/batchRenderer.d.ts +20 -18
- package/dist/src/utils/visual/render/utils/batch/index.d.ts +13 -13
- package/dist/src/utils/visual/render/utils/float.d.ts +13 -13
- package/dist/src/utils/visual/render/utils/verticy.d.ts +3 -3
- package/dist/src/utils/visual/render/utils/webgl/initShader.d.ts +3 -2
- package/dist/src/utils/visual/render/utils/webgpu/shaders.d.ts +2 -2
- package/dist/src/utils/visual/render/webGPURenderer.d.ts +8 -8
- package/dist/src/utils/visual/vertex/container.d.ts +17 -16
- package/dist/src/utils/worker.d.ts +76 -0
- package/dist/src/utils/zip.d.ts +162 -0
- package/dist/src/vnode/index.d.ts +1 -1
- package/dist/src/vnode/index.js +1 -1
- package/dist/src/vnode/is.d.ts +4 -0
- package/dist/test/canvas.test.d.ts +1 -0
- package/dist/test/color.test.d.ts +1 -0
- package/dist/test/tween.test.d.ts +1 -0
- package/dist/test/utils/async.test.d.ts +1 -0
- package/dist/test/utils/file-read.test.d.ts +1 -0
- package/dist/test/utils/format.test.d.ts +1 -0
- package/dist/test/utils/idb.test.d.ts +1 -0
- package/dist/test/utils/instrumentation.test.d.ts +1 -0
- package/dist/test/utils/lang.test.d.ts +1 -0
- package/dist/test/utils/locale-path.test.d.ts +1 -0
- package/dist/test/utils/media-query.test.d.ts +1 -0
- package/dist/test/utils/number-parse.test.d.ts +1 -0
- package/dist/test/utils/prefetch.test.d.ts +1 -0
- package/dist/test/utils/query-storage.test.d.ts +1 -0
- package/dist/test/utils/queue.test.d.ts +1 -0
- package/dist/test/utils/report-config.test.d.ts +1 -0
- package/dist/test/utils/report-image.test.d.ts +1 -0
- package/dist/test/utils/segment.test.d.ts +1 -0
- package/dist/test/utils/signal-once.test.d.ts +1 -0
- package/dist/test/utils/single-flight.test.d.ts +1 -0
- package/dist/test/utils/timing.test.d.ts +1 -0
- package/dist/test/utils/worker-client.test.d.ts +1 -0
- package/dist/test/utils/zip.test.d.ts +1 -0
- package/dist/umd/index.umd.cjs +1 -1
- package/dist/umd/node/node.umd.cjs +1 -1
- package/dist/umd/utils/utils.umd.cjs +1 -1
- package/dist/utils-BDtXHcK8.js +1 -0
- package/docs/API.md +306 -147
- package/package.json +32 -14
- package/dist/src/vnode/chainDom.d.ts +0 -47
- package/dist/subscribe-CINWsor3.js +0 -1
- package/dist/utils-_OxsVZmz.js +0 -1
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description: The uniform result shape of every IndexedDB operation. Every method
|
|
3
|
+
* resolves and rejects with this shape, so callers only need to check `error` rather than
|
|
4
|
+
* distinguishing "the request was never created" from "the request failed".
|
|
5
|
+
*/
|
|
6
|
+
export interface IDBResult<T = unknown> {
|
|
7
|
+
status: 'success' | 'error' | 'pending';
|
|
8
|
+
code: number;
|
|
9
|
+
data: T;
|
|
10
|
+
error: boolean;
|
|
11
|
+
message?: string;
|
|
12
|
+
progress?: number;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* @description: Declarative schema for object stores. `openDataBase` creates the missing
|
|
16
|
+
* stores and indexes inside `onupgradeneeded` — **stores can only be created in a version
|
|
17
|
+
* upgrade transaction**, so they must be declared up front; createObjectStore cannot be
|
|
18
|
+
* called after the database is open.
|
|
19
|
+
*/
|
|
20
|
+
export interface IDBStoreSchema {
|
|
21
|
+
name: string;
|
|
22
|
+
options?: IDBObjectStoreParameters;
|
|
23
|
+
indexes?: Array<{
|
|
24
|
+
name: string;
|
|
25
|
+
keyPath: string | string[];
|
|
26
|
+
options?: IDBIndexParameters;
|
|
27
|
+
}>;
|
|
28
|
+
}
|
|
29
|
+
export interface WebDBOptions {
|
|
30
|
+
dbName: string;
|
|
31
|
+
version?: number;
|
|
32
|
+
/** Declarative store definitions: missing stores / indexes are created on upgrade (existing ones are skipped — idempotent) */
|
|
33
|
+
stores?: IDBStoreSchema[];
|
|
34
|
+
/** Escape hatch: migrations the schema cannot express (changing a keyPath, moving data) go here, called after `stores` are created */
|
|
35
|
+
upgrade?: (db: IDBDatabase, event: IDBVersionChangeEvent, transaction: IDBTransaction | null) => void;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* @description: A Promise wrapper over IndexedDB. The native API is event-callback and
|
|
39
|
+
* transaction based — every read or write takes five steps (open → transaction →
|
|
40
|
+
* objectStore → request → onsuccess/onerror); this class collapses that into
|
|
41
|
+
* `await db.add({ storeName, data })`.
|
|
42
|
+
*
|
|
43
|
+
* Three easy traps are handled internally:
|
|
44
|
+
* 1. **Version downgrade**: opening with a version lower than the one on disk throws a
|
|
45
|
+
* VersionError. Here the actual version is parsed out and the database reopened aligned
|
|
46
|
+
* to it, instead of surfacing the error to the caller.
|
|
47
|
+
* 2. **Blocked upgrade**: an upgrade hangs while another tab or worker holds an old
|
|
48
|
+
* connection. `onversionchange` on the connection closes it so the upgrading side can
|
|
49
|
+
* proceed.
|
|
50
|
+
* 3. **When stores can be created**: only inside `onupgradeneeded`, hence the declarative
|
|
51
|
+
* `stores` configuration.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```ts
|
|
55
|
+
* const db = new WebDB({
|
|
56
|
+
* dbName: 'read',
|
|
57
|
+
* version: 4,
|
|
58
|
+
* stores: [
|
|
59
|
+
* { name: 'books', options: { keyPath: 'id' }, indexes: [{ name: 'byAuthor', keyPath: 'author' }] },
|
|
60
|
+
* { name: 'notes', options: { keyPath: 'id' } },
|
|
61
|
+
* ],
|
|
62
|
+
* });
|
|
63
|
+
* await db.openDataBase();
|
|
64
|
+
* await db.add({ storeName: 'books', data: { id: '1', title: 'Walden' } });
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
export declare class WebDB {
|
|
68
|
+
database?: IDBDatabase;
|
|
69
|
+
version: number;
|
|
70
|
+
dbName: string;
|
|
71
|
+
private stores;
|
|
72
|
+
private upgrade?;
|
|
73
|
+
constructor({ dbName, version, stores, upgrade }: WebDBOptions);
|
|
74
|
+
/**
|
|
75
|
+
* @description: Open the database; when the requested version is below the one on disk,
|
|
76
|
+
* align to it and reopen automatically
|
|
77
|
+
* @return {Promise<IDBResult<{ db: IDBDatabase }>>}
|
|
78
|
+
*/
|
|
79
|
+
openDataBase: () => Promise<IDBResult<{
|
|
80
|
+
db: IDBDatabase;
|
|
81
|
+
}>>;
|
|
82
|
+
closeDataBase: () => void;
|
|
83
|
+
/** @description: Close and reopen (used to restore the connection after aligning versions) */
|
|
84
|
+
refreshDatabase: () => Promise<IDBResult<{
|
|
85
|
+
db: IDBDatabase;
|
|
86
|
+
}>>;
|
|
87
|
+
deleteDatabase: ({ dbName }?: {
|
|
88
|
+
dbName?: string;
|
|
89
|
+
}) => Promise<IDBResult>;
|
|
90
|
+
/** @description: Get an objectStore (each call opens its own transaction — only suitable for a single read) */
|
|
91
|
+
getObjectStore: (storeName: string, mode?: IDBTransactionMode) => IDBObjectStore | undefined;
|
|
92
|
+
/**
|
|
93
|
+
* @description: Wrap an IDBRequest into a Promise<IDBResult>, shared by every read and
|
|
94
|
+
* write method. When `store` cannot be obtained (database not open / store missing) the
|
|
95
|
+
* failure takes the same error path.
|
|
96
|
+
*/
|
|
97
|
+
private run;
|
|
98
|
+
/** @description: Insert; fails when the primary key already exists (use `update` to overwrite) */
|
|
99
|
+
add: <T = unknown>({ storeName, data }: {
|
|
100
|
+
storeName: string;
|
|
101
|
+
data: T;
|
|
102
|
+
}) => Promise<IDBResult<T>>;
|
|
103
|
+
/** @description: Write with `put` semantics: insert when absent, overwrite when present */
|
|
104
|
+
update: <T = unknown>({ storeName, data }: {
|
|
105
|
+
storeName: string;
|
|
106
|
+
data: T;
|
|
107
|
+
}) => Promise<IDBResult>;
|
|
108
|
+
readByKey: <T = unknown>({ storeName, key }: {
|
|
109
|
+
storeName: string;
|
|
110
|
+
key: IDBValidKey;
|
|
111
|
+
}) => Promise<IDBResult<T>>;
|
|
112
|
+
/** @description: Read a whole store; for large volumes use readByCursor to process record by record instead of holding everything in memory */
|
|
113
|
+
readAll: <T = unknown>({ storeName, query, count, }: {
|
|
114
|
+
storeName: string;
|
|
115
|
+
query?: IDBValidKey | IDBKeyRange;
|
|
116
|
+
count?: number;
|
|
117
|
+
}) => Promise<IDBResult<T[]>>;
|
|
118
|
+
count: ({ storeName, query, }: {
|
|
119
|
+
storeName: string;
|
|
120
|
+
query?: IDBValidKey | IDBKeyRange;
|
|
121
|
+
}) => Promise<IDBResult<number>>;
|
|
122
|
+
/** @description: Walk a cursor, collecting results per keyRange / direction */
|
|
123
|
+
readByCursor: <T = unknown>({ storeName, keyRange, direction, }: {
|
|
124
|
+
storeName: string;
|
|
125
|
+
keyRange?: IDBKeyRange;
|
|
126
|
+
direction?: IDBCursorDirection;
|
|
127
|
+
}) => Promise<IDBResult<T[]>>;
|
|
128
|
+
delete: ({ storeName, key }: {
|
|
129
|
+
storeName: string;
|
|
130
|
+
key: IDBValidKey;
|
|
131
|
+
}) => Promise<IDBResult>;
|
|
132
|
+
clear: ({ storeName }: {
|
|
133
|
+
storeName: string;
|
|
134
|
+
}) => Promise<IDBResult>;
|
|
135
|
+
}
|
|
136
|
+
export interface HandoffOptions {
|
|
137
|
+
/** Database name. Both sides of the handoff must agree on this. */
|
|
138
|
+
dbName: string;
|
|
139
|
+
/** Object store name, created on first open. */
|
|
140
|
+
storeName?: string;
|
|
141
|
+
/** Key the single pending value is stored under. */
|
|
142
|
+
key?: string;
|
|
143
|
+
}
|
|
144
|
+
export interface Handoff<T> {
|
|
145
|
+
/** Store a value for the next page to take. Resolves false when it could not be stored. */
|
|
146
|
+
put: (value: T) => Promise<boolean>;
|
|
147
|
+
/** Take the pending value and delete it. Resolves null when there is nothing pending. */
|
|
148
|
+
take: () => Promise<T | null>;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* @description: A one-shot value handoff between two pages of the same origin, backed by
|
|
152
|
+
* IndexedDB.
|
|
153
|
+
*
|
|
154
|
+
* The problem it solves: a `File` picked on page A cannot be carried to page B. It does not
|
|
155
|
+
* survive a URL (too large, and not serialisable), and `sessionStorage` only takes strings.
|
|
156
|
+
* IndexedDB stores structured-cloneable values as-is — `File`, `Blob`, `ArrayBuffer`,
|
|
157
|
+
* `Map` — so page A calls `put(file)` and navigates, and page B calls `take()`.
|
|
158
|
+
*
|
|
159
|
+
* **Reading is destructive**: `take()` deletes the value in the same transaction that reads
|
|
160
|
+
* it, so a reload does not re-open the same file and a stale URL flag finds nothing. Both
|
|
161
|
+
* sides degrade to `null` / `false` rather than throwing — a blocked or unavailable
|
|
162
|
+
* IndexedDB (private mode, third-party frame) must not break the page that merely *tried*
|
|
163
|
+
* to hand something over.
|
|
164
|
+
*
|
|
165
|
+
* @param {HandoffOptions} options
|
|
166
|
+
* @return {Handoff<T>}
|
|
167
|
+
* @example
|
|
168
|
+
* ```ts
|
|
169
|
+
* // Landing page
|
|
170
|
+
* const handoff = createHandoff<File>({ dbName: 'document-handoff' });
|
|
171
|
+
* await handoff.put(picked);
|
|
172
|
+
* location.href = '/app?open=local';
|
|
173
|
+
*
|
|
174
|
+
* // App
|
|
175
|
+
* const file = await handoff.take(); // null on a reload — the value is consumed
|
|
176
|
+
* ```
|
|
177
|
+
*/
|
|
178
|
+
export declare const createHandoff: <T>({ dbName, storeName, key }: HandoffOptions) => Handoff<T>;
|
package/dist/src/utils/img.d.ts
CHANGED
|
@@ -1,15 +1,71 @@
|
|
|
1
1
|
import type { BaseReturn } from '@/utils/bom';
|
|
2
|
+
/** A bitmap container usable both as a drawImage source and as a render target */
|
|
3
|
+
export type ImgSource = HTMLImageElement | HTMLCanvasElement;
|
|
2
4
|
/**
|
|
3
|
-
* @description:
|
|
4
|
-
*
|
|
5
|
-
*
|
|
5
|
+
* @description: Load an image by path, resolving once it has decoded.
|
|
6
|
+
*
|
|
7
|
+
* Note that it rejects with the raw error event rather than an Error: `<img>`'s onerror
|
|
8
|
+
* carries no reason (the browser deliberately withholds it cross-origin), so wrapping it in
|
|
9
|
+
* an Error would only invent a message that is not true.
|
|
10
|
+
*
|
|
11
|
+
* @param {string} src image path
|
|
12
|
+
* @return {Promise<ImgSource>}
|
|
13
|
+
*/
|
|
14
|
+
export declare const getImage: (src: string) => Promise<ImgSource>;
|
|
15
|
+
/**
|
|
16
|
+
* @description: Round an image's corners, returning an offscreen canvas.
|
|
17
|
+
*
|
|
18
|
+
* A canvas rather than a dataURL: a canvas feeds straight into the next drawImage, so a
|
|
19
|
+
* chain of filters does not encode and decode a PNG at every step.
|
|
20
|
+
*
|
|
21
|
+
* @param {ImgSource} img image to round
|
|
22
|
+
* @param {number} radius corner radius
|
|
23
|
+
* @return {ImgSource} offscreen canvas
|
|
24
|
+
*/
|
|
25
|
+
export declare const cutRound: (img: ImgSource, radius: number) => ImgSource;
|
|
26
|
+
/**
|
|
27
|
+
* @description: Apply an overall opacity to an image, returning an offscreen canvas.
|
|
28
|
+
*
|
|
29
|
+
* `ctx.filter` first (GPU accelerated); where unsupported, fall back to rewriting the alpha
|
|
30
|
+
* channel pixel by pixel. The fallback skips pixels whose alpha is already 0, so fully
|
|
31
|
+
* transparent regions do not come out with a non-zero value.
|
|
32
|
+
*
|
|
33
|
+
* @param {ImgSource} img image to process
|
|
34
|
+
* @param {number} opacity opacity, 0–1
|
|
35
|
+
* @return {ImgSource} offscreen canvas
|
|
36
|
+
*/
|
|
37
|
+
export declare const opacity: (img: ImgSource, opacity: number) => ImgSource;
|
|
38
|
+
/**
|
|
39
|
+
* @description: Build a 2D Gaussian weight matrix, normalised so the weights sum to 1.
|
|
40
|
+
*
|
|
41
|
+
* Normalising is required: without it the convolution shifts the image's overall
|
|
42
|
+
* brightness. Sigma defaults to `radius / 3`, by which point the Gaussian has decayed to
|
|
43
|
+
* nearly 0 at the radius, making the truncation error negligible.
|
|
44
|
+
*
|
|
45
|
+
* @param {number} radius blur radius
|
|
46
|
+
* @param {number} sigma standard deviation, defaults to radius / 3
|
|
47
|
+
* @return {number[]} a flat (2r+1)² matrix in row-major order
|
|
48
|
+
*/
|
|
49
|
+
export declare const getMatrix: (radius: number, sigma?: number) => number[];
|
|
50
|
+
/**
|
|
51
|
+
* @description: Check an image's dimensions against a given width / height. When both are
|
|
52
|
+
* passed **both** must match; when neither is, decoding successfully is enough.
|
|
53
|
+
*
|
|
54
|
+
* `revokeObjectURL` runs on both paths, otherwise every check leaks a blob URL that lives
|
|
55
|
+
* until the page unloads. A decode failure (a corrupt file, a non-image) rejects rather than
|
|
56
|
+
* hanging forever.
|
|
57
|
+
*
|
|
58
|
+
* @param {File} file image file to check
|
|
59
|
+
* @param {number} width expected width in pixels
|
|
60
|
+
* @param {number} height expected height in pixels
|
|
61
|
+
* @return {Promise<boolean>}
|
|
6
62
|
*/
|
|
7
63
|
export declare const isImageSize: (file: File, width?: number, height?: number) => Promise<boolean>;
|
|
8
64
|
export interface convertImageToBase64Return extends BaseReturn {
|
|
9
65
|
data: string | ArrayBuffer | null;
|
|
10
66
|
}
|
|
11
67
|
/**
|
|
12
|
-
* @description:
|
|
68
|
+
* @description: Convert an image to base64
|
|
13
69
|
* @param {File} file
|
|
14
70
|
* @return {*}
|
|
15
71
|
*/
|
|
@@ -1,35 +1,67 @@
|
|
|
1
1
|
import { SyncHook } from './subscribe';
|
|
2
|
-
import { Mathjs, addNumSym, mathjs, perToNum, range, transformNumber } from './number';
|
|
3
|
-
import { MessageCodec, changeHumpToLowerCase, checkEncoding, clearBr, clearStr, getMatchingSentences, getRandomString, isString, md5, randomString, str2Xml, strParse, toString, transformText } from './str';
|
|
2
|
+
import { Mathjs, addNumSym, mathjs, parseChineseNumber, parseEnglishNumber, parseRomanNumber, perToNum, range, transformNumber } from './number';
|
|
3
|
+
import { MessageCodec, arrayBufferToString, changeHumpToLowerCase, checkEncoding, clearBr, clearStr, getMatchingSentences, getRandomString, isString, md5, randomString, str2Xml, strParse, toFullWidth, toHalfWidth, toString, transformText } from './str';
|
|
4
4
|
import type { TransformText } from './str';
|
|
5
|
-
import {
|
|
6
|
-
import
|
|
5
|
+
import { appendUrl, connection, createObjectURL, durationHandler, encodeUrl, getAllQueryString, getCookie, getCookieByName, getFrame, getPixelRatio, getQuery, getWindow, imageRequest, isInIframe, isSafari, networkSpeed, queryFlag, removeGhosting, requestUrlToBuffer, retain } from './bom';
|
|
6
|
+
import { BRIDGE_MARKER, BridgeManager, Client, DEFAULT_CHANNEL, Platform, PostMessageBridge, acceptPortBridge, bridgeManager, createPortBridge, openPortBridge } from './bridge';
|
|
7
|
+
import type { AcceptPortBridgeOptions, BridgeManagerOptions, BroadcastPayload, CallToPayload, MessageData, MessageHandler, OpenPortBridgeOptions, PendingRequest, PortBridge } from './bridge';
|
|
7
8
|
import { cloneDeep, filterObj, formatJson, isEqual, merge, mergeExports, querystring, replaceOld, setAttributeByGlobal } from './obj';
|
|
8
9
|
import { MimeType, getExtensions, getMime, setMime } from './mimeType';
|
|
9
10
|
import { AudioRecorder } from './audioRecorder';
|
|
10
11
|
import { createSignal, subscribers } from './signal';
|
|
11
12
|
import { audioVendor, canvasVendor, webglVendor } from './behavior';
|
|
12
13
|
import { TOTP } from './totp/totp';
|
|
13
|
-
import { localStorageGetItem, localStorageSetItem } from './storage';
|
|
14
|
+
import { createStore, localStorageGetItem, localStorageRemoveItem, localStorageSetItem } from './storage';
|
|
15
|
+
import type { JsonStore } from './storage';
|
|
14
16
|
import { compose } from './compose';
|
|
15
17
|
import { handleConsole } from './console';
|
|
16
18
|
import { debounce } from './debounce';
|
|
19
|
+
import type { Debounced } from './debounce';
|
|
17
20
|
import { Chain, addClassToElement, create, createDocumentFragment, escapeHtml, removeClassToElement, setFontSize2html } from './dom';
|
|
18
21
|
import { handleError } from './error';
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
22
|
+
import { EventManager } from './event';
|
|
23
|
+
import { circ, cubic, expo, quad, quart, quint, sine } from './tween';
|
|
24
|
+
import type { EasingFn, SpeedType } from './tween';
|
|
25
|
+
import { convertImageToBase64, cutRound, getImage, getMatrix, isImageSize, opacity } from './img';
|
|
26
|
+
import type { ImgSource } from './img';
|
|
27
|
+
import { fanShapedByArc, getAngle, getArcPointerByDeg, getLinearGradient, getTangentByPointer, roundRectByArc } from './canvas';
|
|
28
|
+
import { ADOPTED_SHEET_MARKER, ADOPTED_STYLE_MARKER, adoptSheetText, adoptStyles } from './style';
|
|
29
|
+
import { memoize, once, singleFlight } from './memoize';
|
|
30
|
+
import type { SingleFlight } from './memoize';
|
|
31
|
+
import { WebDB, createHandoff } from './idb';
|
|
32
|
+
import type { Handoff, HandoffOptions, IDBResult, IDBStoreSchema, WebDBOptions } from './idb';
|
|
33
|
+
import { buildOffsets, indexForOffset, segmentByRanges } from './segment';
|
|
34
|
+
import type { OffsetRange, Segment } from './segment';
|
|
35
|
+
import { detectLanguage, navigatorLanguage, resolveLocale } from './lang';
|
|
36
|
+
import { I18nCore, createI18n, useI18n } from './i18n';
|
|
37
|
+
import type { I18nConfig, LocaleChangeHandler, LocaleMessages, MessageDict, TranslateParams } from './i18n';
|
|
38
|
+
import { createLocalePath } from './localePath';
|
|
39
|
+
import type { LocalePath, LocalePathConfig, LocaleRoute } from './localePath';
|
|
40
|
+
import type { ResolveLocaleOptions, TextLanguage } from './lang';
|
|
41
|
+
import { readFileAsArrayBuffer, readFileAsDataURL, readFileAsText, readFileAsUint8Array } from './file';
|
|
42
|
+
import { WorkerClient } from './worker';
|
|
43
|
+
import type { WorkerClientOptions, WorkerResponseBase } from './worker';
|
|
44
|
+
import { isUrlCached, networkAllowsDownload, prefetchUrl, prefetchUrls, prefetchWhenIdle, whenIdle } from './prefetch';
|
|
45
|
+
import type { NetworkAllowanceOptions, PrefetchOptions, WhenIdleOptions } from './prefetch';
|
|
46
|
+
import { TimeoutError, deferred, delay, withTimeout, withTimeoutFallback } from './async';
|
|
47
|
+
import type { Deferred } from './async';
|
|
48
|
+
import { ZIP_DEFLATE, ZIP_STORED, createZip, crc32, inflateRaw, readZipEntries, readZipEntry, rewriteZip, zipHasEntry } from './zip';
|
|
49
|
+
import type { RewriteZipOptions, ZipEntry } from './zip';
|
|
21
50
|
import { Monitor } from './monitor';
|
|
22
51
|
import { getStatus, status } from './network';
|
|
23
52
|
import { noop } from './noop';
|
|
24
53
|
import { getPerformance } from './performance';
|
|
25
54
|
import { QuestQueue } from './queue';
|
|
26
|
-
import { createData, report } from './report';
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
29
|
-
import {
|
|
30
|
-
import {
|
|
55
|
+
import { createData, getReportUrl, report, setReportUrl } from './report';
|
|
56
|
+
import type { BeaconPayload, ReportConfig } from './report';
|
|
57
|
+
import { handleFetchHook, handleXhrHook } from './request';
|
|
58
|
+
import { loadScript, scriptOnLoad } from './script';
|
|
59
|
+
import type { LoadScriptOptions } from './script';
|
|
60
|
+
import { throttle } from './throttle';
|
|
61
|
+
import type { Throttled } from './throttle';
|
|
62
|
+
import { formatDate, performanceTime, timeFormat, timestampToTime } from './time';
|
|
31
63
|
import type { CurrentDevice } from './device';
|
|
32
|
-
import { currentDevice, isBangDevice, isClient, isMobile, isWeiXin } from './device';
|
|
33
|
-
import { Color, ColorScheme, FMT, Hsl, Hsla, Rgb, Rgba, componentToHex, hexToRgb, hsbToRgb, hslToRgb, hsvToHsl, hsvToRgb, hue2rgb, randomColor, rgbToHex, rgbToHsb, rgbToHsl } from '@/utils/color';
|
|
34
|
-
export { performanceTime, timeFormat, timestampToTime,
|
|
35
|
-
export type { CurrentDevice, TransformText, MessageHandler, MessageData, PendingRequest, BridgeManagerOptions, BroadcastPayload, CallToPayload, PortBridge, OpenPortBridgeOptions, AcceptPortBridgeOptions, };
|
|
64
|
+
import { MOBILE_MEDIA_QUERY, currentDevice, isBangDevice, isClient, isMobile, isWeiXin, matchMediaQuery, watchMediaQuery } from './device';
|
|
65
|
+
import { Color, ColorScheme, FMT, HEX_COLOR_REGEX, Hsl, Hsla, RGBA_REGEX, RGB_REGEX, Rgb, Rgba, componentToHex, hexToAlpha, hexToHsb, hexToHsv, hexToRgb, hsbToHsl, hsbToRgb, hslToHsb, hslToHsv, hslToRgb, hsvToHsl, hsvToRgb, hue2rgb, randomColor, rgbToHex, rgbToHsb, rgbToHsl, rgbToHsv, rgbaString, rgbaToHex, rgbaToRgb } from '@/utils/color';
|
|
66
|
+
export { performanceTime, timeFormat, timestampToTime, throttle, SyncHook, changeHumpToLowerCase, clearBr, clearStr, isString, randomString, str2Xml, strParse, scriptOnLoad, handleFetchHook, createData, report, QuestQueue, noop, getPerformance, querystring, formatJson, filterObj, merge, replaceOld, mergeExports, perToNum, range, Mathjs, mathjs, getStatus, status, Monitor, MimeType, getExtensions, setMime, getMime, memoize, once, isImageSize, convertImageToBase64, handleError, addClassToElement, removeClassToElement, createDocumentFragment, escapeHtml, isClient, isWeiXin, isMobile, debounce, currentDevice, handleConsole, compose, Color, FMT, Hsl, Hsla, Rgb, Rgba, randomColor, hexToRgb, componentToHex, rgbToHex, rgbToHsl, hue2rgb, hslToRgb, rgbToHsb, hsbToRgb, hsvToRgb, hsvToHsl, ColorScheme, AudioRecorder, webglVendor, canvasVendor, audioVendor, retain, getCookie, requestUrlToBuffer, getPixelRatio, createObjectURL, getFrame, getAllQueryString, queryFlag, isInIframe, appendUrl, removeGhosting, getCookieByName, getWindow, connection, encodeUrl, imageRequest, durationHandler, networkSpeed, TOTP, isBangDevice, localStorageGetItem, localStorageSetItem, localStorageRemoveItem, createStore, setAttributeByGlobal, setFontSize2html, Chain, create, isEqual, cloneDeep, createSignal, subscribers, getMatchingSentences, transformNumber, toString, addNumSym, getQuery, checkEncoding, transformText, isSafari, md5, getRandomString, bridgeManager, Client, BridgeManager, PostMessageBridge, MessageCodec, Platform, openPortBridge, acceptPortBridge, createPortBridge, BRIDGE_MARKER, DEFAULT_CHANNEL, singleFlight, WebDB, createHandoff, buildOffsets, indexForOffset, segmentByRanges, detectLanguage, navigatorLanguage, resolveLocale, readFileAsArrayBuffer, readFileAsUint8Array, readFileAsText, readFileAsDataURL, WorkerClient, whenIdle, networkAllowsDownload, isUrlCached, prefetchUrl, prefetchUrls, prefetchWhenIdle, deferred, withTimeout, withTimeoutFallback, delay, TimeoutError, crc32, inflateRaw, readZipEntries, readZipEntry, zipHasEntry, rewriteZip, createZip, ZIP_STORED, ZIP_DEFLATE, arrayBufferToString, toHalfWidth, toFullWidth, parseChineseNumber, parseRomanNumber, parseEnglishNumber, MOBILE_MEDIA_QUERY, matchMediaQuery, watchMediaQuery, createLocalePath, setReportUrl, getReportUrl, formatDate, handleXhrHook, EventManager, quad, cubic, quart, quint, sine, expo, circ, getImage, cutRound, opacity, getMatrix, getAngle, getArcPointerByDeg, getTangentByPointer, fanShapedByArc, roundRectByArc, getLinearGradient, adoptStyles, adoptSheetText, ADOPTED_STYLE_MARKER, ADOPTED_SHEET_MARKER, rgbToHsv, hexToHsb, hexToHsv, hsbToHsl, hslToHsb, hslToHsv, hexToAlpha, rgbaString, rgbaToRgb, rgbaToHex, HEX_COLOR_REGEX, RGB_REGEX, RGBA_REGEX, loadScript, I18nCore, createI18n, useI18n, };
|
|
67
|
+
export type { EasingFn, SpeedType, ImgSource, LoadScriptOptions, I18nConfig, MessageDict, LocaleMessages, TranslateParams, LocaleChangeHandler, Debounced, Throttled, BeaconPayload, ReportConfig, LocalePath, LocalePathConfig, LocaleRoute, SingleFlight, IDBResult, IDBStoreSchema, WebDBOptions, Handoff, HandoffOptions, JsonStore, Deferred, ZipEntry, RewriteZipOptions, ResolveLocaleOptions, OffsetRange, Segment, TextLanguage, WorkerClientOptions, WorkerResponseBase, WhenIdleOptions, NetworkAllowanceOptions, PrefetchOptions, CurrentDevice, TransformText, MessageHandler, MessageData, PendingRequest, BridgeManagerOptions, BroadcastPayload, CallToPayload, PortBridge, OpenPortBridgeOptions, AcceptPortBridgeOptions, };
|
package/dist/src/utils/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{i as s}from"../../enums-BAgbyGdH.js";import{A as a,B as t,C as n,D as o,E as r,F as m,G as i,H as p,I as f,J as j,K as c,L as l,M as u,N as h,O as x,P as b,Q as d,R as e,S as g,T as k,U as v,V as w,W as y,X as z,Y as A,Z as B,_ as C,a as D,b as E,c as F,d as H,f as I,g as L,h as M,i as N,j as O,k as P,l as R,m as S,n as T,o as U,p as V,q as W,r as _,s as q,t as G,u as J,v as K,w as Q,x as X,y as Y,z as Z}from"../../color-Dohr9BXX.js";import{$,$t as ss,A as as,At as ts,B as ns,Bt as os,C as rs,Ct as ms,D as is,Dt as ps,E as fs,Et as js,F as cs,Ft as ls,G as us,Gt as hs,H as xs,Ht as bs,I as ds,It as es,J as gs,Jt as ks,K as vs,Kt as ws,L as ys,Lt as zs,M as As,Mt as Bs,N as Cs,Nt as Ds,O as Es,Ot as Fs,P as Hs,Pt as Is,Q as Ls,Qt as Ms,R as Ns,Rt as Os,S as Ps,St as Rs,T as Ss,Tt as Ts,U as Us,Ut as Vs,V as Ws,Vt as _s,W as qs,Wt as Gs,X as Js,Xt as Ks,Y as Qs,Yt as Xs,Z as Ys,Zt as Zs,_ as $s,_t as sa,a as aa,an as ta,at as na,b as oa,bt as ra,c as ma,cn as ia,ct as pa,d as fa,dt as ja,en as ca,et as la,f as ua,ft as ha,g as xa,gt as ba,h as da,ht as ea,i as ga,in as ka,it as va,j as wa,jt as ya,k as za,kt as Aa,l as Ba,lt as Ca,m as Da,mt as Ea,n as Fa,nn as Ha,nt as Ia,o as La,on as Ma,ot as Na,p as Oa,pt as Pa,q as Ra,qt as Sa,r as Ta,rn as Ua,rt as Va,s as Wa,sn as _a,st as qa,t as Ga,tn as Ja,tt as Ka,u as Qa,ut as Xa,v as Ya,vt as Za,w as $a,wt as st,x as at,xt as tt,y as nt,yt as ot,z as rt,zt as mt}from"../../utils-BDtXHcK8.js";import{A as it,B as pt,C as ft,D as jt,E as ct,F as lt,H as ut,I as ht,L as xt,M as bt,N as dt,O as et,P as gt,R as kt,S as vt,T as wt,U as yt,V as zt,W as At,_ as Bt,a as Ct,b as Dt,c as Et,d as Ft,f as Ht,g as It,h as Lt,i as Mt,k as Nt,l as Ot,m as Pt,n as Rt,o as St,p as Tt,r as Ut,s as Vt,t as Wt,u as _t,v as qt,w as Gt,x as Jt,y as Kt,z as Qt}from"../../i18n-Cf5TtRb4.js";import{n as Xt,t as Yt}from"../../chain-CTywmh_H.js";export{vs as ADOPTED_SHEET_MARKER,Ra as ADOPTED_STYLE_MARKER,ya as AudioRecorder,Gs as BRIDGE_MARKER,hs as BridgeManager,Yt as Chain,ws as Client,G as Color,T as ColorScheme,Sa as DEFAULT_CHANNEL,ea as EventManager,_ as FMT,N as HEX_COLOR_REGEX,D as Hsl,U as Hsla,Wt as I18nCore,bt as MOBILE_MEDIA_QUERY,ca as Mathjs,f as MessageCodec,u as MimeType,La as Monitor,ks as Platform,Xs as PostMessageBridge,Ta as QuestQueue,q as RGBA_REGEX,F as RGB_REGEX,R as Rgb,J as Rgba,s as SyncHook,Ts as TOTP,$a as TimeoutError,qs as WebDB,cs as WorkerClient,da as ZIP_DEFLATE,xa as ZIP_STORED,Ks as acceptPortBridge,sa as addClassToElement,Ja as addNumSym,gs as adoptSheetText,Qs as adoptStyles,Ft as appendUrl,l as arrayBufferToString,js as audioVendor,Zs as bridgeManager,Ws as buildOffsets,ps as canvasVendor,e as changeHumpToLowerCase,Z as checkEncoding,pa as circ,t as clearBr,w as clearStr,Bs as cloneDeep,H as componentToHex,st as compose,Ht as connection,Js as convertImageToBase64,$s as crc32,Xt as create,Qa as createData,Za as createDocumentFragment,us as createHandoff,Rt as createI18n,ns as createLocalePath,Tt as createObjectURL,Ms as createPortBridge,Aa as createSignal,Vt as createStore,Ya as createZip,Ca as cubic,dt as currentDevice,Ys as cutRound,Rs as debounce,Ss as deferred,fs as delay,Mt as detectLanguage,Pt as durationHandler,Lt as encodeUrl,ot as escapeHtml,Xa as expo,Ia as fanShapedByArc,Ds as filterObj,pt as formatDate,Is as formatJson,It as getAllQueryString,Va as getAngle,va as getArcPointerByDeg,Bt as getCookie,qt as getCookieByName,h as getExtensions,Kt as getFrame,Ls as getImage,na as getLinearGradient,p as getMatchingSentences,$ as getMatrix,b as getMime,Da as getPerformance,Dt as getPixelRatio,Jt as getQuery,v as getRandomString,fa as getReportUrl,ga as getStatus,Na as getTangentByPointer,vt as getWindow,ms as handleConsole,ba as handleError,ma as handleFetchHook,Ba as handleXhrHook,I as hexToAlpha,V as hexToHsb,S as hexToHsv,M as hexToRgb,L as hsbToHsl,C as hsbToRgb,K as hslToHsb,Y as hslToHsv,E as hslToRgb,X as hsvToHsl,g as hsvToRgb,n as hue2rgb,ft as imageRequest,xs as indexForOffset,nt as inflateRaw,gt as isBangDevice,lt as isClient,ls as isEqual,la as isImageSize,Gt as isInIframe,ht as isMobile,wt as isSafari,y as isString,za as isUrlCached,xt as isWeiXin,Ga as loadScript,Et as localStorageGetItem,Ot as localStorageRemoveItem,_t as localStorageSetItem,kt as matchMediaQuery,Ha as mathjs,i as md5,_s as memoize,es as merge,zs as mergeExports,Ct as navigatorLanguage,as as networkAllowsDownload,ct as networkSpeed,At as noop,bs as once,Ka as opacity,ss as openPortBridge,Ua as parseChineseNumber,ka as parseEnglishNumber,ta as parseRomanNumber,Ma as perToNum,zt as performanceTime,wa as prefetchUrl,As as prefetchUrls,Cs as prefetchWhenIdle,ja as quad,ha as quart,jt as queryFlag,Os as querystring,Pa as quint,Q as randomColor,c as randomString,_a as range,ds as readFileAsArrayBuffer,ys as readFileAsDataURL,Ns as readFileAsText,rt as readFileAsUint8Array,oa as readZipEntries,at as readZipEntry,ra as removeClassToElement,et as removeGhosting,mt as replaceOld,ua as report,Nt as requestUrlToBuffer,St as resolveLocale,it as retain,Ps as rewriteZip,k as rgbToHex,r as rgbToHsb,o as rgbToHsl,x as rgbToHsv,P as rgbaString,a as rgbaToHex,O as rgbaToRgb,qa as roundRectByArc,Fa as scriptOnLoad,Us as segmentByRanges,os as setAttributeByGlobal,tt as setFontSize2html,m as setMime,Oa as setReportUrl,Ea as sine,Vs as singleFlight,aa as status,W as str2Xml,j as strParse,ts as subscribers,Wa as throttle,ut as timeFormat,yt as timestampToTime,A as toFullWidth,z as toHalfWidth,B as toString,ia as transformNumber,d as transformText,Ut as useI18n,Qt as watchMediaQuery,Fs as webglVendor,Hs as whenIdle,is as withTimeout,Es as withTimeoutFallback,rs as zipHasEntry};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/** Coarse language bucket: Chinese / English / other only */
|
|
2
|
+
export type TextLanguage = 'zh' | 'en' | 'other';
|
|
3
|
+
/**
|
|
4
|
+
* @description: Decide a text's primary language from the ratio of CJK to Latin characters.
|
|
5
|
+
* Pure statistics, no model or dictionary loaded — good enough to branch on "which
|
|
6
|
+
* tokenizer / which language-specific model / which typographic metrics".
|
|
7
|
+
*
|
|
8
|
+
* Only the first N characters are sampled: the body language is consistent throughout, so
|
|
9
|
+
* scanning a whole book (millions of characters) is pure waste. Text with a little CJK still
|
|
10
|
+
* counts as Chinese (Latin has to clearly dominate for English), because English mixed into
|
|
11
|
+
* Chinese text is common while the reverse is rare.
|
|
12
|
+
*
|
|
13
|
+
* @param {string} text text to inspect
|
|
14
|
+
* @param {number} sampleSize sample length, defaults to 20000
|
|
15
|
+
* @return {TextLanguage}
|
|
16
|
+
*/
|
|
17
|
+
export declare const detectLanguage: (text: string, sampleSize?: number) => TextLanguage;
|
|
18
|
+
/**
|
|
19
|
+
* @description: Map the browser UI language into the same buckets (the default when there is
|
|
20
|
+
* no content to inspect). Returns 'other' under SSR.
|
|
21
|
+
* @return {TextLanguage}
|
|
22
|
+
*/
|
|
23
|
+
export declare const navigatorLanguage: () => TextLanguage;
|
|
24
|
+
export interface ResolveLocaleOptions {
|
|
25
|
+
/** Locales the app actually ships, most specific first. The result is always one of these. */
|
|
26
|
+
supported: readonly string[];
|
|
27
|
+
/** Returned when no source matches. Defaults to `supported[0]`. */
|
|
28
|
+
fallback?: string;
|
|
29
|
+
/** Query parameter carrying an explicit choice, e.g. `lang` in `?lang=zh-CN`. */
|
|
30
|
+
query?: string;
|
|
31
|
+
/** Cookie name carrying the choice (a server-rendered preference, typically). */
|
|
32
|
+
cookie?: string;
|
|
33
|
+
/** localStorage key carrying the choice the user last picked in-app. */
|
|
34
|
+
storageKey?: string;
|
|
35
|
+
/** Consult `navigator.language` / `navigator.languages` before falling back. Defaults to true. */
|
|
36
|
+
useNavigator?: boolean;
|
|
37
|
+
/** URL to read the query from; defaults to the current location. */
|
|
38
|
+
url?: string;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* @description: Resolve which of your supported locales to use, from the usual chain:
|
|
42
|
+
* **query → cookie → localStorage → navigator → fallback**.
|
|
43
|
+
*
|
|
44
|
+
* The order is the point. A `?lang=` in the URL is an explicit, shareable, one-off
|
|
45
|
+
* instruction and must beat everything; a cookie is a server-visible decision, so it beats
|
|
46
|
+
* client-only state; localStorage is what the user last chose in-app; `navigator.language`
|
|
47
|
+
* is only a guess about a first-time visitor. Getting this backwards produces the classic
|
|
48
|
+
* bug where a shared `?lang=en` link keeps rendering in the recipient's stored language.
|
|
49
|
+
*
|
|
50
|
+
* Matching is case-insensitive and falls back from region to base language: with
|
|
51
|
+
* `supported: ['en', 'zh-CN']`, a `zh-TW` request matches nothing but `zh` matches `zh-CN`,
|
|
52
|
+
* and `en-GB` matches `en`. Values outside `supported` are ignored rather than returned, so
|
|
53
|
+
* the result is always safe to index a message catalogue with.
|
|
54
|
+
*
|
|
55
|
+
* The catalogue itself is yours — this only picks the key.
|
|
56
|
+
*
|
|
57
|
+
* @param {ResolveLocaleOptions} options
|
|
58
|
+
* @return {string} one of `supported`
|
|
59
|
+
* @example
|
|
60
|
+
* ```ts
|
|
61
|
+
* const locale = resolveLocale({
|
|
62
|
+
* supported: ['en', 'zh-CN'],
|
|
63
|
+
* query: 'lang',
|
|
64
|
+
* cookie: 'lang',
|
|
65
|
+
* storageKey: 'app-lang',
|
|
66
|
+
* });
|
|
67
|
+
* ```
|
|
68
|
+
*/
|
|
69
|
+
export declare const resolveLocale: (options: ResolveLocaleOptions) => string;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* URL maths for a multi-language site (pure functions, no global state, no DOM).
|
|
3
|
+
*
|
|
4
|
+
* Uses **sub-directories** rather than sub-domains (`/zh/book/`, not `zh.example.com/book/`):
|
|
5
|
+
* search engines treat a sub-domain as a separate site that starts from zero authority,
|
|
6
|
+
* while a sub-directory inherits the main site's. The default language lives at the root
|
|
7
|
+
* (`/book/`); every other language carries a prefix.
|
|
8
|
+
*
|
|
9
|
+
* Decoupled from "what is the current language" — this module only converts paths, the
|
|
10
|
+
* language state belongs to the caller (the i18n runtime). That is why it runs both in
|
|
11
|
+
* build-time scripts (sitemap / hreflang generation) and in the browser.
|
|
12
|
+
*/
|
|
13
|
+
export interface LocaleRoute {
|
|
14
|
+
/** Language code, e.g. `zh-CN`; the public identifier (hreflang, i18n dictionary key) */
|
|
15
|
+
code: string;
|
|
16
|
+
/** URL prefix, e.g. `zh`. Empty = the default language, served from the root */
|
|
17
|
+
prefix?: string;
|
|
18
|
+
}
|
|
19
|
+
export interface LocalePathConfig {
|
|
20
|
+
locales: readonly LocaleRoute[];
|
|
21
|
+
/** Default language code; when omitted, the first locale without a prefix, else `locales[0]` */
|
|
22
|
+
defaultLocale?: string;
|
|
23
|
+
/** Deployment sub-path, e.g. `/weread`; empty for a root deployment. A trailing slash is ignored */
|
|
24
|
+
base?: string;
|
|
25
|
+
}
|
|
26
|
+
export interface LocalePath {
|
|
27
|
+
/** Normalised base (no trailing slash; empty string for a root deployment) */
|
|
28
|
+
readonly base: string;
|
|
29
|
+
readonly defaultLocale: string;
|
|
30
|
+
/** Detect the language from a pathname, falling back to the default language */
|
|
31
|
+
localeFromPath: (pathname: string) => string;
|
|
32
|
+
/** Drop the language prefix to get the language-independent path (for route matching) */
|
|
33
|
+
stripLocale: (pathname: string) => string;
|
|
34
|
+
/** Build a link for a language; an already-prefixed path is stripped first, so repeated calls are idempotent */
|
|
35
|
+
href: (path: string, code?: string) => string;
|
|
36
|
+
/** Convert a path in any language to its counterpart in another language (for a language switcher) */
|
|
37
|
+
hrefForLocale: (pathname: string, code: string) => string;
|
|
38
|
+
/** This path in every language, for `<link rel="alternate" hreflang>` */
|
|
39
|
+
alternates: (pathname: string) => Array<{
|
|
40
|
+
code: string;
|
|
41
|
+
href: string;
|
|
42
|
+
}>;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* @description: Create the set of locale path conversion functions.
|
|
46
|
+
*
|
|
47
|
+
* @param {LocalePathConfig} config
|
|
48
|
+
* @return {LocalePath}
|
|
49
|
+
* @example
|
|
50
|
+
* ```ts
|
|
51
|
+
* const paths = createLocalePath({
|
|
52
|
+
* locales: [{ code: 'en' }, { code: 'zh-CN', prefix: 'zh' }, { code: 'zh-HK', prefix: 'zh-hant' }],
|
|
53
|
+
* base: '/docs',
|
|
54
|
+
* });
|
|
55
|
+
* paths.href('/book/walden/'); // '/docs/book/walden/'
|
|
56
|
+
* paths.href('/book/walden/', 'zh-CN'); // '/docs/zh/book/walden/'
|
|
57
|
+
* paths.localeFromPath('/docs/zh/book/'); // 'zh-CN'
|
|
58
|
+
* paths.stripLocale('/docs/zh/book/'); // '/docs/book/'
|
|
59
|
+
* paths.hrefForLocale('/docs/zh/book/', 'zh-HK'); // '/docs/zh-hant/book/'
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
export declare const createLocalePath: (config: LocalePathConfig) => LocalePath;
|
|
@@ -1,7 +1,55 @@
|
|
|
1
|
-
export type Func = () => unknown;
|
|
1
|
+
export type Func = (...args: any[]) => unknown;
|
|
2
2
|
/**
|
|
3
|
-
* @description:
|
|
4
|
-
*
|
|
5
|
-
*
|
|
3
|
+
* @description: Run once — evaluate on the first call, cache the result, and return that
|
|
4
|
+
* same result forever after, whatever arguments come later. For lazy initialisation:
|
|
5
|
+
* config parsing, an expensive one-off computation, a lazy getter.
|
|
6
|
+
*
|
|
7
|
+
* **This is not a per-argument memoize**: only the first call's arguments matter, later
|
|
8
|
+
* ones are ignored. Use a `Map` if you need keyed caching, or
|
|
9
|
+
* [`singleFlight`](#singleflight) for the async case. Once evaluated, the reference to
|
|
10
|
+
* `fn` is released so whatever its closure captured can be collected.
|
|
11
|
+
*
|
|
12
|
+
* @param {Function} fn function that should run only once; a non-function value is returned as is
|
|
13
|
+
* @return {Function} wrapped function
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
16
|
+
* const config = once(() => JSON.parse(readFileSync('config.json', 'utf8')));
|
|
17
|
+
* config(); // parses
|
|
18
|
+
* config(); // returns the previous result directly
|
|
19
|
+
* ```
|
|
6
20
|
*/
|
|
7
|
-
export declare const
|
|
21
|
+
export declare const once: <T extends Func>(fn: T | unknown) => ((...args: Parameters<T>) => ReturnType<T>);
|
|
22
|
+
/**
|
|
23
|
+
* @description: Former name of `once`. The name is misleading — it does not cache per
|
|
24
|
+
* argument, it simply runs once.
|
|
25
|
+
* @deprecated Use [`once`](#once) instead; for the async case use [`singleFlight`](#singleflight).
|
|
26
|
+
*/
|
|
27
|
+
export declare const memoize: typeof once;
|
|
28
|
+
export interface SingleFlight<T> {
|
|
29
|
+
(): Promise<T>;
|
|
30
|
+
/** Drop the cached result so the next call runs again (connection lost, logout, forced refresh) */
|
|
31
|
+
reset: () => void;
|
|
32
|
+
/** Whether a result already exists or a run is in flight */
|
|
33
|
+
readonly started: boolean;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* @description: The async flavour of "run once": concurrent callers share one in-flight
|
|
37
|
+
* promise, later callers reuse the resolved result, and **a rejection clears the cache**
|
|
38
|
+
* so it can be retried (this is where it differs from `memoize` — caching a rejected
|
|
39
|
+
* promise turns one flaky network blip into a permanent failure).
|
|
40
|
+
*
|
|
41
|
+
* The typical use is a resource that is initialised once but awaited by everyone: opening
|
|
42
|
+
* a database, loading config, registering a service worker. The classic bug is an
|
|
43
|
+
* initialiser returning void, leaving callers nothing to await, so concurrent writes all
|
|
44
|
+
* fail before the resource is ready — wrap it in `singleFlight` and any caller can just
|
|
45
|
+
* `await ready()`.
|
|
46
|
+
*
|
|
47
|
+
* @param {Function} fn async function that should run only once
|
|
48
|
+
* @return {SingleFlight<T>}
|
|
49
|
+
* @example
|
|
50
|
+
* ```ts
|
|
51
|
+
* const ready = singleFlight(() => db.openDataBase());
|
|
52
|
+
* await ready(); // concurrent callers only open it for real once
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
export declare const singleFlight: <T>(fn: () => Promise<T>) => SingleFlight<T>;
|