ranuts 0.2.0-alpha.1 → 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.
Files changed (112) hide show
  1. package/CLAUDE.md +107 -16
  2. package/README.md +7 -5
  3. package/README.zh-CN.md +7 -5
  4. package/dist/chain-CTywmh_H.js +1 -0
  5. package/dist/{color-CRdlaDqQ.js → color-Dohr9BXX.js} +1 -1
  6. package/dist/enums-BAgbyGdH.js +1 -0
  7. package/dist/i18n-Cf5TtRb4.js +1 -0
  8. package/dist/index.d.ts +1 -5
  9. package/dist/index.js +1 -1
  10. package/dist/src/node/appendFile.d.ts +3 -3
  11. package/dist/src/node/fileInfo.d.ts +2 -2
  12. package/dist/src/node/index.js +1 -1
  13. package/dist/src/node/paresUrl.d.ts +1 -1
  14. package/dist/src/node/readFile.d.ts +3 -3
  15. package/dist/src/node/traverse.d.ts +2 -2
  16. package/dist/src/node/watchFile.d.ts +3 -3
  17. package/dist/src/node/writeFile.d.ts +3 -3
  18. package/dist/src/utils/async.d.ts +81 -0
  19. package/dist/src/utils/audioRecorder.d.ts +1 -1
  20. package/dist/src/utils/behavior.d.ts +12 -3
  21. package/dist/src/utils/bom.d.ts +68 -178
  22. package/dist/src/utils/bridge.d.ts +153 -0
  23. package/dist/src/utils/canvas.d.ts +54 -0
  24. package/dist/src/utils/chain.d.ts +80 -0
  25. package/dist/src/utils/color.d.ts +76 -4
  26. package/dist/src/utils/compose.d.ts +1 -1
  27. package/dist/src/utils/console.d.ts +19 -1
  28. package/dist/src/utils/debounce.d.ts +27 -5
  29. package/dist/src/utils/device.d.ts +31 -3
  30. package/dist/src/utils/dom.d.ts +5 -84
  31. package/dist/src/utils/error.d.ts +18 -1
  32. package/dist/src/utils/event.d.ts +61 -0
  33. package/dist/src/utils/file.d.ts +30 -0
  34. package/dist/src/utils/i18n/index.js +1 -0
  35. package/dist/src/utils/i18n.d.ts +69 -0
  36. package/dist/src/utils/idb.d.ts +178 -0
  37. package/dist/src/utils/img.d.ts +60 -4
  38. package/dist/src/utils/index.d.ts +48 -16
  39. package/dist/src/utils/index.js +1 -1
  40. package/dist/src/utils/lang.d.ts +69 -0
  41. package/dist/src/utils/localePath.d.ts +62 -0
  42. package/dist/src/utils/memoize.d.ts +53 -5
  43. package/dist/src/utils/monitor.d.ts +55 -26
  44. package/dist/src/utils/number.d.ts +46 -9
  45. package/dist/src/utils/obj.d.ts +56 -31
  46. package/dist/src/utils/prefetch.d.ts +81 -0
  47. package/dist/src/utils/queue.d.ts +53 -23
  48. package/dist/src/utils/report.d.ts +51 -3
  49. package/dist/src/utils/request.d.ts +26 -7
  50. package/dist/src/utils/script.d.ts +26 -4
  51. package/dist/src/utils/segment.d.ts +62 -0
  52. package/dist/src/utils/signal.d.ts +35 -3
  53. package/dist/src/utils/storage.d.ts +57 -0
  54. package/dist/src/utils/str.d.ts +112 -88
  55. package/dist/src/utils/style.d.ts +31 -0
  56. package/dist/src/utils/subscribe.d.ts +5 -5
  57. package/dist/src/utils/throttle.d.ts +26 -13
  58. package/dist/src/utils/time.d.ts +38 -6
  59. package/dist/src/utils/tween.d.ts +40 -0
  60. package/dist/src/utils/visual/application.d.ts +4 -4
  61. package/dist/src/utils/visual/enums.d.ts +4 -4
  62. package/dist/src/utils/visual/graphics/graphics.d.ts +25 -25
  63. package/dist/src/utils/visual/graphics/graphicsData.d.ts +1 -1
  64. package/dist/src/utils/visual/graphics/graphicsGeometry.d.ts +6 -6
  65. package/dist/src/utils/visual/index.js +1 -1
  66. package/dist/src/utils/visual/math/matrix.d.ts +8 -8
  67. package/dist/src/utils/visual/math/transform.d.ts +1 -1
  68. package/dist/src/utils/visual/render/batchRenderer.d.ts +20 -18
  69. package/dist/src/utils/visual/render/utils/batch/index.d.ts +13 -13
  70. package/dist/src/utils/visual/render/utils/float.d.ts +13 -13
  71. package/dist/src/utils/visual/render/utils/verticy.d.ts +3 -3
  72. package/dist/src/utils/visual/render/utils/webgl/initShader.d.ts +3 -2
  73. package/dist/src/utils/visual/render/utils/webgpu/shaders.d.ts +2 -2
  74. package/dist/src/utils/visual/render/webGPURenderer.d.ts +8 -8
  75. package/dist/src/utils/visual/vertex/container.d.ts +17 -16
  76. package/dist/src/utils/worker.d.ts +76 -0
  77. package/dist/src/utils/zip.d.ts +162 -0
  78. package/dist/src/vnode/index.d.ts +1 -1
  79. package/dist/src/vnode/index.js +1 -1
  80. package/dist/src/vnode/is.d.ts +4 -0
  81. package/dist/test/canvas.test.d.ts +1 -0
  82. package/dist/test/color.test.d.ts +1 -0
  83. package/dist/test/tween.test.d.ts +1 -0
  84. package/dist/test/utils/async.test.d.ts +1 -0
  85. package/dist/test/utils/file-read.test.d.ts +1 -0
  86. package/dist/test/utils/format.test.d.ts +1 -0
  87. package/dist/test/utils/idb.test.d.ts +1 -0
  88. package/dist/test/utils/instrumentation.test.d.ts +1 -0
  89. package/dist/test/utils/lang.test.d.ts +1 -0
  90. package/dist/test/utils/locale-path.test.d.ts +1 -0
  91. package/dist/test/utils/media-query.test.d.ts +1 -0
  92. package/dist/test/utils/number-parse.test.d.ts +1 -0
  93. package/dist/test/utils/prefetch.test.d.ts +1 -0
  94. package/dist/test/utils/query-storage.test.d.ts +1 -0
  95. package/dist/test/utils/queue.test.d.ts +1 -0
  96. package/dist/test/utils/report-config.test.d.ts +1 -0
  97. package/dist/test/utils/report-image.test.d.ts +1 -0
  98. package/dist/test/utils/segment.test.d.ts +1 -0
  99. package/dist/test/utils/signal-once.test.d.ts +1 -0
  100. package/dist/test/utils/single-flight.test.d.ts +1 -0
  101. package/dist/test/utils/timing.test.d.ts +1 -0
  102. package/dist/test/utils/worker-client.test.d.ts +1 -0
  103. package/dist/test/utils/zip.test.d.ts +1 -0
  104. package/dist/umd/index.umd.cjs +1 -1
  105. package/dist/umd/node/node.umd.cjs +1 -1
  106. package/dist/umd/utils/utils.umd.cjs +1 -1
  107. package/dist/utils-BDtXHcK8.js +1 -0
  108. package/docs/API.md +306 -147
  109. package/package.json +9 -6
  110. package/dist/src/vnode/chainDom.d.ts +0 -47
  111. package/dist/subscribe-CINWsor3.js +0 -1
  112. package/dist/utils-_OxsVZmz.js +0 -1
package/docs/API.md CHANGED
@@ -8,204 +8,330 @@ constraints, conventions) read [../CLAUDE.md](../CLAUDE.md) first.
8
8
  Import from the **subpath** that owns the symbol, e.g. `import { debounce } from
9
9
  'ranuts/utils'`. The root `ranuts` barrel re-exports the utils + visual surface.
10
10
 
11
- **199 exports** across 4 entry points. Generated at 2026-07-04T09:39:55.881Z.
11
+ **332 exports** across 5 entry points. Generated at 2026-07-25T10:17:15.788Z.
12
12
 
13
13
  ## Entry points
14
14
 
15
- - [`ranuts/utils`](#ranutsutils) — 浏览器 / 通用工具函数 · _browser + node_ · 135 exports
16
- - [`ranuts/node`](#ranutsnode) — Node 服务端工具(fs / http / ws / 中间件) · _node only_ · 26 exports
17
- - [`ranuts/visual`](#ranutsvisual) — 2D 渲染引擎(Canvas / WebGL / WebGPU · _browser only_ · 12 exports
18
- - [`ranuts/vnode`](#ranutsvnode) — Snabbdom 风格虚拟 DOM · _browser_ · 26 exports
15
+ - [`ranuts/utils`](#ranutsutils) — Browser and general-purpose utilities · _browser + node_ · 260 exports
16
+ - [`ranuts/node`](#ranutsnode) — Node server utilities (fs / http / ws / middleware) · _node only_ · 26 exports
17
+ - [`ranuts/visual`](#ranutsvisual) — 2D rendering engine (Canvas / WebGL / WebGPU) · _browser only_ · 12 exports
18
+ - [`ranuts/i18n`](#ranutsi18n) — Framework-agnostic i18n engine (also re-exported from ranuts/utils) · _browser + node_ · 8 exports
19
+ - [`ranuts/vnode`](#ranutsvnode) — Snabbdom-style virtual DOM · _browser_ · 26 exports
19
20
 
20
21
  ## `ranuts/utils`
21
22
 
22
- 浏览器 / 通用工具函数 · runtime: **browser + node** · source: `src/utils/index.ts`
23
+ Browser and general-purpose utilities · runtime: **browser + node** · source: `src/utils/index.ts`
23
24
 
24
25
  ```ts
25
- import {} from /* … */ 'ranuts/utils';
26
+ import { /* … */ } from 'ranuts/utils';
26
27
  ```
27
28
 
28
29
  ### Functions
29
30
 
30
- - `acceptPortBridge({ targetOrigin, name }?: AcceptPortBridgeOptions): Promise<PortBridge>` — 接收方:等待发起方递来的 port,握手完成后返回 bridge
31
- - `addClassToElement(element: Element, addClass: string): void` — 给指定的元素添加指定的 class
32
- - `addNumSym(value: string | number, flag?: string | number): string`
33
- - `appendUrl(url: string, params?: Record<string, string>): string` — 将一个对象转换成 querystring,拼接到 url 后面
34
- - `audioVendor(): Promise<string>`音频指纹,1.生成音频信息流 (三角波),对其进行 FFT 变换,计算 SHA 值作为指纹。2.生成音频信息流(正弦波),进行动态压缩处理,计算 MD5 值。
35
- - `canvasVendor(): string | null`
36
- - `changeHumpToLowerCase(str: string): string`
37
- - `checkEncoding(uint8Array: Uint8Array): string`
38
- - `clearBr(str?: string): string` — 清除字符串中的空格、换行和 HTML 标签
39
- - `clearStr(str: string, options?: ClearStrOption): string` — 去除字符串首尾的空格,encode 编码,首尾的引号
40
- - `cloneDeep<T>(value: T, cloneMap?: WeakMap<object, any>): T` — 深克隆函数,支持各种复杂数据类型和循环引用
41
- - `componentToHex(c: string | number): string`
42
- - `compose<T>(middleware: Array<Middleware<T>>): ComposedMiddleware<T>`将异步函数转化为同步的方式进行执行
43
- - `connection(): number | undefined` — 返回当前网络状态,当前吞吐量,是否切换网络
44
- - `convertImageToBase64(file: File): Promise<convertImageToBase64Return>`图片转 base64
45
- - `create(tagName: string, options?: ElementCreationOptions): Chain`
46
- - `createData(params?: Record<string, unknown>): Record<string, unknown>`
47
- - `createDocumentFragment(list: Element[]): DocumentFragment | undefined` — 创建一个 Fragment
48
- - `createObjectURL(src: Blob | ArrayBuffer | Response): Promise<string>`
49
- - `createPortBridge(port: MessagePort): PortBridge` — 在任意 MessagePort 上构建 bridge(Web Worker / SharedWorker 或已握手的 port)。
50
- - `createSignal<T = unknown>(value: T, options?: { subscriber?: string; equals?: boolean | ((prev: T | undefined, next: T) => boolean); }): [() => T, (newValue: T…`
51
- - `currentDevice(): CurrentDevice`
52
- - `debounce(fn: any, ms?: number): any` — 防抖
53
- - `durationHandler<T, U>(handler: (...args: T[]) => U, ...params: T[]): ((a: number) => Promise<U>)`间隔一定时间,执行指定的函数
54
- - `encodeUrl(url: string): string` — Encode a URL to a percent-encoded form, excluding already-encoded sequences.
55
- - `escapeHtml(string?: string | number | null): string`
56
- - `filterObj(obj: Record<string, unknown>, list: Array<string>): Record<string, unknown>` — 过滤对象的属性,去除对象中在 list 数组里面有的属性,返回一个新对象,一般是用于去除空字符和 null
57
- - `formatJson(jsonObj: string, callback?: () => void): string`
58
- - `generateThrottle(): Function` — 生成节流函数
59
- - `getAllQueryString(url?: string): Record<string, string>` — url 上的字符串转换成对象
60
- - `getCookie(objName: string): string` — 获取指定的 cookie
61
- - `getCookieByName(name: string): string`
62
- - `getExtensions(mimeType: string): string[]` — Get file extensions from MIME type
63
- - `getFrame(n?: number): Promise<number>` — 计算每毫秒的帧率,每秒的帧率需要乘 1000
64
- - `getHost(env?: string): string | undefined` Gets the current environment configuration
65
- - `getMatchingSentences(text: string, searchValue: string): string[]` 获取文本中包含搜索关键词的完整句子,对于重复的句子只保留最长的一个
66
- - `getMime(ext: string): string | undefined`
67
- - `getPerformance(): BasicType | undefined`
68
- - `getPixelRatio(context: CanvasRenderingContext2D & Partial<Context>): number` — 获取分辨率
69
- - `getQuery(url?: string): Record<string, string>` url 上的字符串转换成对象
70
- - `getRandomString(len?: number): string`
71
- - `getStatus(code?: number | string): number | string | undefined` — Get the status code.
72
- - `getWindow(): ClientRatio` — 跨浏览器获取可视窗口大小
73
- - `handleConsole(hooks?: (...args: unknown[]) => void): void`
74
- - `handleError(hooks?: (error: Error | PromiseRejectionEvent | ErrorEvent) => void): void`
75
- - `handleFetchHook(options?: Partial<Options>): void` — fetch
76
- - `hexToRgb(hex: string): RegExpExecArray | null | Array<number>`
77
- - `hsbToRgb(h: number, s: number, v: number): number[]`
78
- - `hslToRgb(h: number | string | number[], s: number | string, l: number | string): Array<number>`
79
- - `hsvToHsl(h: any, s: any, b: any): number[]`
80
- - `hsvToRgb(h: number, s: number, v: number): number[]`
81
- - `hue2rgb(p: number, q: number, t: number): number`
82
- - `imageRequest(url?: string): Promise<number>`图片请求
83
- - `isBangDevice(): boolean`
84
- - `isEqual(value: any, other: any, seen?: Map<any, any>): boolean` — 深度比较两个值是否相等
85
- - `isImageSize(file: File, width?: number, height?: number): Promise<boolean>` — 校验图片尺寸
86
- - `isMobile(): boolean` 是否是移动端
87
- - `isSafari(): boolean | undefined | string`
88
- - `isString(obj: unknown): boolean`
89
- - `isWeiXin(): boolean` — 判断是否是微信浏览器的函数
90
- - `localStorageGetItem(name: string): string`
91
- - `localStorageSetItem(name: string, value: string): void`
92
- - `mathjs(a: number, type: string, b: number): ComputeNumberResult`
93
- - `md5(str: string): string` — MD5 hash function implementation
94
- - `memoize(fn: unknown): Func` — 返回缓存的函数,执行一次后,无须执行直接返回结果
95
- - `merge(a: Obj, b?: Obj): Obj` — 合并对象
96
- - `mergeExports(obj: Record<string, string>, exports: Record<string, string>): Record<string, string>` exports 对象拼接到 obj 上,并冻结 obj
97
- - `networkSpeed(options: Options): Promise<ReturnType>`通过请求来测试当前网络的 ping
98
- - `noop(): void`
99
- - `openPortBridge({ targetWindow, targetOrigin, name }: OpenPortBridgeOptions): PortBridge` 发起方:创建 MessageChannel,把一端交给目标窗口,自己持有另一端。
100
- - `performanceTime(): number` 获取当前时间戳
101
- - `perToNum(str?: string): number` — 百分比转换成数字
102
- - `querystring(data?: {}): string` 对象转 url 字符串
103
- - `randomColor(): Color`
104
- - `randomString(len?: number): string`
105
- - `range(num: number, min?: number, max?: number): number` — 限制最大和最小值
106
- - `removeClassToElement(element: Element, removeClass: string): void` 给指定的元素移除指定的 class
107
- - `removeGhosting(event: DragEvent): void` 移除拖拽事件的阴影
108
- - `replaceOld(source: any, name: string, replacement: (...args: unknown[]) => unknown, isForced?: boolean): void` — 重写对象上面的某个属性
109
- - `report({ url, type, payload, }: BeaconPayload): boolean | undefined | void`
110
- - `requestUrlToBuffer(src: string, options: Partial<RequestUrlToArraybufferOption>): Promise<requestUrlToArraybufferReturn>` — url arrayBuffer
111
- - `retain(callback?: () => void): void` — 覆盖浏览器的后退事件
112
- - `rgbToHex(r: string | number | Array<string | number>, g?: string | number, b?: string | number): string`
113
- - `rgbToHsb(r: number, g: number, b: number): number[]`
114
- - `rgbToHsl(r: number | number[], g?: number, b?: number): Array<number>`
115
- - `scriptOnLoad(urls: string[], append?: HTMLElement, callback?: () => void): Promise<void>` — 动态插入 script/link 标签
116
- - `setAttributeByGlobal(name: string, value: unknown): void` — 给全局对象上增加属性
117
- - `setFontSize2html(designWidth?: number): void` — 根据 UI 稿宽度设置 rem
118
- - `setMime(ext: string, mimeType: string): Map<string, string>`
119
- - `str2Xml(xmlStr: string, format?: DOMParserSupportedType): HTMLElement | undefined` — 传入字符串和指定的格式,将字符串转成 xml
120
- - `strParse(str?: string, sep?: string | RegExp, eq?: string | RegExp): Record<string, string>` 将字符串转对象,比如
121
- - `throttle<T extends (...args: any[]) => any>(func: T, delay?: number): ThrottleFunc<T>` 节流
122
- - `timeFormat(time: number): string`时间秒,转化成:分割的时间
123
- - `timestampToTime(timestamp?: number | string): Date & { format?: Function; }` 时间戳转日期
124
- - `toString(value: string | number): string`
125
- - `transformNumber(value: string, locale?: string, precision?: number, fixed?: number): string`
126
- - `transformText(content: string | ArrayBuffer): TransformText | undefined`
127
- - `webglVendor(): { vendor: string; renderer: string; } | null`
31
+ - `acceptPortBridge({ targetOrigin, name, }?: AcceptPortBridgeOptions) => Promise<PortBridge>` — Acceptor: wait for the port the initiator hands over and return the bridge once the
32
+ - `addClassToElement(element: Element, addClass: string) => void` — Add a class to an element
33
+ - `addNumSym(value: string | number, flag?: string | number) => string`
34
+ - `adoptSheetText(shadowRoot: ShadowRoot, cssText: string, marker?: string) => void` — Inject dynamic styles supplied at runtime (a component's `sheet` property, say).
35
+ - `adoptStyles(shadowRoot: ShadowRoot, cssText: string, marker?: string) => void` Inject a component's static styles into a shadow root.
36
+ - `appendUrl(url: string, params?: Record<string, string>) => string` — Turn an object into a query string and append it to a URL
37
+ - `arrayBufferToString(buffer: ArrayBuffer | Uint8Array) => string` — Decode bytes into a string using the sniffed encoding. Required when reading
38
+ - `audioVendor() => Promise<string>` — Audio fingerprint. 1. Generate an audio stream (triangle wave), run an FFT over it and hash the result with SHA. 2. Generate an audio stream (sine wave), run it through dynamic compression and hash with MD5.
39
+ - `buildOffsets(lengths: readonly number[]) => number[]` — The global start offset of every chunk in the concatenated coordinate
40
+ - `canvasVendor() => string | null`
41
+ - `changeHumpToLowerCase(str: string) => string`
42
+ - `checkEncoding(uint8Array: Uint8Array) => string`
43
+ - `clearBr(str?: string) => string` Strip whitespace, line breaks and HTML tags out of a string
44
+ - `clearStr(str: string, options?: ClearStrOption) => string` — Trim surrounding whitespace, percent-decode, and drop surrounding quotes
45
+ - `cloneDeep<T>(value: T, cloneMap?: WeakMap<object, any>) => T` Deep clone, covering the complex built-in types and circular references.
46
+ - `componentToHex(c: string | number) => string`
47
+ - `compose<T>(middleware: Array<Middleware<T>>) => ComposedMiddleware<T>` — Run a chain of async functions as if it were sequential
48
+ - `connection() => number | undefined` — Current network status: type, throughput, and whether the connection changed
49
+ - `convertImageToBase64(file: File) => Promise<convertImageToBase64Return>` Convert an image to base64
50
+ - `crc32(data: Uint8Array) => number` — CRC32 checksum (IEEE 802.3 polynomial), the one ZIP stores per entry.
51
+ - `create(tagName: string, options?: ElementCreationOptions) => Chain`
52
+ - `createData(params?: Record<string, unknown>) => Record<string, unknown>` — Build the standard envelope that accompanies a report — page URL, referrer,
53
+ - `createDocumentFragment(list: Element[]) => DocumentFragment | undefined` — Create a DocumentFragment
54
+ - `createHandoff<T>({ dbName, storeName, key }: HandoffOptions) => Handoff<T>`A one-shot value handoff between two pages of the same origin, backed by
55
+ - `createI18n(config?: I18nConfig) => I18nCore` — Create and register the global i18n singleton.
56
+ - `createLocalePath(config: LocalePathConfig) => LocalePath` Create the set of locale path conversion functions.
57
+ - `createObjectURL(src: Blob | ArrayBuffer | Response) => Promise<string>`
58
+ - `createPortBridge(port: MessagePort) => PortBridge` — Build a bridge on any MessagePort (a Web Worker, a SharedWorker, or a port from a completed handshake).
59
+ - `createSignal<T = unknown>(value: T, options?: SignalOptions<T>) => [() => T, (newValue: T) => void]` — Create a minimal signal with optional event broadcasting, returned as
60
+ - `createStore<T>(prefix?: string) => JsonStore<T>` — A prefixed, JSON-serialising view over localStorage.
61
+ - `createZip(files: ReadonlyArray<{ name: string; data: Uint8Array | string; }>) => Uint8Array` — Build a ZIP from scratch, every entry STORED. No compression, so this is
62
+ - `currentDevice() => CurrentDevice`
63
+ - `cutRound(img: ImgSource, radius: number) => ImgSource` — Round an image's corners, returning an offscreen canvas.
64
+ - `debounce<T extends (...args: any[]) => any>(fn: T, ms?: number) => Debounced<T>` — Debounce — on a burst of calls, run only the last one, **`ms` milliseconds
65
+ - `deferred<T = void>() => Deferred<T>` — A promise plus its `resolve` / `reject`, for the case where the thing that
66
+ - `delay(ms: number) => Promise<void>` — Resolve after `ms` milliseconds. Uses the bare `setTimeout`, so it works in
67
+ - `detectLanguage(text: string, sampleSize?: number) => TextLanguage` — Decide a text's primary language from the ratio of CJK to Latin characters.
68
+ - `durationHandler<T, U>(handler: (...args: T[]) => U, ...params: T[]) => ((a: number) => Promise<U>)` — Run a function repeatedly at a fixed interval
69
+ - `encodeUrl(url: string) => string` — Encode a URL to a percent-encoded form, excluding already-encoded sequences.
70
+ - `escapeHtml(string?: string | number | null) => string`
71
+ - `fanShapedByArc(ctx: CanvasRenderingContext2D, maxRadius: number, start: number, end: number, gutter: number) => void` — Trace a pie slice with arc(), including the gutter between slices.
72
+ - `filterObj(obj: Record<string, unknown>, list: Array<string>) => Record<string, unknown>` — Return a new object without the properties whose values appear in `list`typically used to drop empty strings and nulls
73
+ - `formatDate(value?: number | string | Date, pattern?: string) => string` — Format a date with a token pattern. Accepts a timestamp, a date string, a
74
+ - `formatJson(value: string | object, onError?: (error: Error) => void, indent?: number) => string` — Pretty-print JSON. Accepts an object or a JSON string (single quotes are
75
+ - `getAllQueryString(url?: string) => Record<string, string>` Parse a URL's query string into an object. Defaults to the current
76
+ - `getAngle(deg: number) => number` — Degrees to radians
77
+ - `getArcPointerByDeg(deg: number, r: number) => [number, number]` — The point on a circle at a given angle
78
+ - `getCookie(objName: string) => string` Read a named cookie
79
+ - `getCookieByName(name: string) => string`
80
+ - `getExtensions(mimeType: string) => string[]` Get file extensions from MIME type
81
+ - `getFrame(n?: number) => Promise<number>` Frames per millisecond; multiply by 1000 for frames per second
82
+ - `getImage(src: string) => Promise<ImgSource>` — Load an image by path, resolving once it has decoded.
83
+ - `getLinearGradient(ctx: CanvasRenderingContext2D, x: number, y: number, w: number, h: number, background: string) => CanvasGradient` Translate a CSS `linear-gradient(...)` string into a Canvas CanvasGradient.
84
+ - `getMatchingSentences(text: string, searchValue: string) => string[]` — Collect the complete sentences of a text that contain the search term, keeping only the
85
+ - `getMatrix(radius: number, sigma?: number) => number[]` — Build a 2D Gaussian weight matrix, normalised so the weights sum to 1.
86
+ - `getMime(ext: string) => string | undefined`
87
+ - `getPerformance() => BasicType | undefined`
88
+ - `getPixelRatio(context: CanvasRenderingContext2D & Partial<Context>) => number` — Get the device pixel ratio
89
+ - `getQuery(url?: string) => Record<string, string>` — Alias of [`getAllQueryString`](#getallquerystring). The two used to be
90
+ - `getRandomString(len?: number) => string`
91
+ - `getReportUrl() => string` — The currently configured reporting endpoint, or `''` when none was set
92
+ - `getStatus(code?: number | string) => number | string | undefined` — Get the status code.
93
+ - `getTangentByPointer(x: number, y: number) => Array<number>` — The tangent line at a point on a circle
94
+ - `getWindow() => ClientRatio` — Get the viewport size across browsers
95
+ - `handleConsole(hooks?: (...args: unknown[]) => void) => (() => void)` — Tap into `console` so every call also reaches your hook, while still printing
96
+ - `handleError(hooks?: (error: ErrorPayload) => void) => (() => void)` — Listen for uncaught errors and unhandled promise rejections, in the capture
97
+ - `handleFetchHook(options?: Partial<Options>) => (() => void)` Instrument `window.fetch` so every request, response and failure reaches your
98
+ - `handleXhrHook(options?: Partial<Options>) => (() => void)` Instrument `XMLHttpRequest` (`open` / `send`) so requests, responses and
99
+ - `hexToAlpha(aa: string) => number` — A two-digit hex alpha channel (`ff` / `80` / `00`) to a 0–100 percentage.
100
+ - `hexToHsb(hex: string) => number[] | null` — `#rrggbb` / `#rgb` to `[h, s, b]`; null when the hex is invalid.
101
+ - `hexToHsv(hex: string) => number[] | null`
102
+ - `hexToRgb(hex: string) => Array<number> | null` — `#rrggbb` / `#rgb` (with or without the `#`) to `[r, g, b]`; null when it cannot be parsed.
103
+ - `hsbToHsl(h: number, s: number, b: number) => number[]`
104
+ - `hsbToRgb(h: number, s: number, v: number) => number[]`
105
+ - `hslToHsb(h: number, s: number, l: number) => number[]` — `[h, s, l]` to `[h, s, b]`
106
+ - `hslToHsv(h: number, s: number, l: number) => number[]`
107
+ - `hslToRgb(h: number | string | number[], s: number | string, l: number | string) => Array<number>`
108
+ - `hsvToHsl(h: number, s: number, b: number) => number[]`
109
+ - `hsvToRgb(h: number, s: number, v: number) => number[]`
110
+ - `hue2rgb(p: number, q: number, t: number) => number`
111
+ - `imageRequest(url?: string) => Promise<number>` — Request an image (used to time the network)
112
+ - `indexForOffset(offsets: readonly number[], offset: number) => number` — Binary-search which chunk a global offset falls into — the last index
113
+ - `inflateRaw(data: Uint8Array) => Promise<Uint8Array>` Decompress raw DEFLATE bytes (no zlib or gzip wrapper) — the form ZIP
114
+ - `isBangDevice() => boolean`
115
+ - `isEqual(value: any, other: any, seen?: Map<any, any>) => boolean` — Deep-compare two values.
116
+ - `isImageSize(file: File, width?: number, height?: number) => Promise<boolean>` — Check an image's dimensions against a given width / height. When both are
117
+ - `isInIframe() => boolean` — Whether this page is running inside an iframe. Returns false under SSR.
118
+ - `isMobile() => boolean` — Whether this is a mobile device
119
+ - `isSafari() => boolean | undefined | string`
120
+ - `isString(obj: unknown) => boolean`
121
+ - `isUrlCached(url: string) => Promise<boolean>` Whether a URL is already in CacheStorage. When probing a group of files,
122
+ - `isWeiXin() => boolean` Whether this is the WeChat in-app browser
123
+ - `loadScript({ type, content }: LoadScriptOptions) => Promise<{ success: boolean; }>` Inject one script dynamically, de-duplicated by content.
124
+ - `localStorageGetItem(name: string) => string` Read a string from localStorage, or `''` when missing or unavailable.
125
+ - `localStorageRemoveItem(name: string) => void` — Remove a key from localStorage. Silently does nothing when storage is unavailable.
126
+ - `localStorageSetItem(name: string, value: string) => void` Write a string to localStorage. Silently does nothing when storage is
127
+ - `matchMediaQuery(query: string) => boolean` Read whether a media query currently matches, synchronously. Returns false under SSR.
128
+ - `mathjs(a: number, type: string, b: number) => ComputeNumberResult`
129
+ - `md5(str: string) => string` — MD5 hash function implementation
130
+ - `memoize<T extends Func>(fn: T | unknown) => ((...args: Parameters<T>) => ReturnType<T>)` — Former name of `once`. The name is misleading — it does not cache per
131
+ - `merge(a: Obj, b?: Obj) => Obj` — Merge objects
132
+ - `mergeExports(obj: Record<string, string>, exports: Record<string, string>) => Record<string, string>` — Copy an exports object onto `obj`, then freeze it
133
+ - `navigatorLanguage() => TextLanguage` — Map the browser UI language into the same buckets (the default when there is
134
+ - `networkAllowsDownload(options?: NetworkAllowanceOptions) => boolean` — Whether the current network and user settings allow proactively downloading
135
+ - `networkSpeed(options: Options) => Promise<ReturnType>` — Measure the network's ping by timing requests
136
+ - `noop() => void`
137
+ - `once<T extends Func>(fn: T | unknown) => ((...args: Parameters<T>) => ReturnType<T>)` — Run once — evaluate on the first call, cache the result, and return that
138
+ - `opacity(img: ImgSource, opacity: number) => ImgSource` — Apply an overall opacity to an image, returning an offscreen canvas.
139
+ - `openPortBridge({ targetWindow, targetOrigin, name, }: OpenPortBridgeOptions) => PortBridge` — Initiator: create a MessageChannel, hand one port to the target window and keep the other.
140
+ - `parseChineseNumber(value: string) => number | null` — Chinese numerals to Arabic, covering 「十五」「二十三」「一百零三」「一千零一」「三万」.
141
+ - `parseEnglishNumber(value: string) => number | null` — English ordinals to numbers, tried in order: Arabic digits, number words
142
+ - `parseRomanNumber(value: string) => number | null` — Roman numerals to Arabic (either case, handling subtractive forms such as IV / IX). Returns null for invalid input.
143
+ - `performanceTime() => number` — Current timestamp
144
+ - `perToNum(str?: string) => number` — Convert a percentage string into a number
145
+ - `prefetchUrl(url: string) => Promise<void>` — Pull a single URL into the cache; skipped when already cached. Failures are
146
+ - `prefetchUrls(urls: string[], options?: PrefetchOptions) => Promise<void>` — Prefetch a group of URLs, **serially** — prefetching is background work, and
147
+ - `prefetchWhenIdle(urls: string[], options?: WhenIdleOptions & NetworkAllowanceOptions & PrefetchOptions) => (() => void)` — Prefetch a group of URLs while idle, subject to `networkAllowsDownload`.
148
+ - `queryFlag(key: string, url?: string) => boolean` — Read a query parameter as a boolean flag. True for `?k`, `?k=`, `?k=1` and
149
+ - `querystring(data?: {}) => string` — Serialise an object into a URL query string
150
+ - `randomColor() => Color`
151
+ - `randomString(len?: number) => string`
152
+ - `range(num: number, min?: number, max?: number) => number` — Clamp a value between a minimum and a maximum
153
+ - `readFileAsArrayBuffer(blob: Blob) => Promise<ArrayBuffer>` — Read a File / Blob as an ArrayBuffer
154
+ - `readFileAsDataURL(blob: Blob) => Promise<string>` — Read a File / Blob as a data: URL (image previews and the like)
155
+ - `readFileAsText(blob: Blob, encoding?: string) => Promise<string>` — Read a File / Blob as text
156
+ - `readFileAsUint8Array(blob: Blob) => Promise<Uint8Array>` — Read a File / Blob as a Uint8Array (pair with checkEncoding / arrayBufferToString for encoding sniffing)
157
+ - `readZipEntries(bytes: Uint8Array) => ZipEntry[]` — Read an archive's central directory. Returns `[]` for anything that is not
158
+ - `readZipEntry(bytes: Uint8Array, entry: string | ZipEntry) => Promise<Uint8Array | null>` — Extract one entry's decompressed bytes. Resolves `null` when the entry is
159
+ - `removeClassToElement(element: Element, removeClass: string) => void` — Remove a class from an element
160
+ - `removeGhosting(event: DragEvent) => void` — Remove the drag event's ghost image
161
+ - `replaceOld(source: any, name: string, replacement: (...args: unknown[]) => unknown, isForced?: boolean) => () => void` — Replace a property on an object, wrapping whatever was there before.
162
+ - `report({ url, type, payload }: BeaconPayload) => boolean` — Send a telemetry beacon. Prefers `navigator.sendBeacon` (does not block
163
+ - `requestUrlToBuffer(src: string, options: Partial<RequestUrlToArraybufferOption>) => Promise<requestUrlToArraybufferReturn>` — Fetch a URL as an ArrayBuffer
164
+ - `resolveLocale(options: ResolveLocaleOptions) => string` — Resolve which of your supported locales to use, from the usual chain:
165
+ - `retain(callback?: () => void) => void` — Override the browser's back-button behaviour
166
+ - `rewriteZip(bytes: Uint8Array, options?: RewriteZipOptions) => Promise<Uint8Array>` — Rebuild an archive with some entries replaced and/or new entries appended.
167
+ - `rgbaString(r: number, g: number, b: number, a: number) => string` — Build a CSS `rgba()` string. Alpha is 0–100 rather than 0–1, matching the
168
+ - `rgbaToHex(r: number, g: number, b: number, a: number) => string` — Composite a translucent colour over white and return it as a 6-digit hex.
169
+ - `rgbaToRgb(r: number, g: number, b: number, a: number) => number[]` — Composite a translucent colour **over white**, giving the equivalent opaque rgb.
170
+ - `rgbToHex(r: string | number | Array<string | number>, g?: string | number, b?: string | number) => string`
171
+ - `rgbToHsb(r: number, g: number, b: number) => number[]`
172
+ - `rgbToHsl(r: number | number[], g?: number, b?: number) => Array<number>`
173
+ - `rgbToHsv(r: number, g: number, b: number) => number[]` — Alias of `rgbToHsb` — HSV and HSB are two names for the same colour space.
174
+ - `roundRectByArc(ctx: CanvasRenderingContext2D, ...[x, y, w, h, r]: number[]) => void` — Trace a rounded rectangle with arc(). A corner radius larger than half the
175
+ - `scriptOnLoad(urls: string[], append?: HTMLElement, callback?: () => void) => Promise<void>` — Insert script/link tags dynamically
176
+ - `segmentByRanges<T>(text: string, chunkStart: number, ranges: readonly OffsetRange<T>[]) => Segment<T>[]` — Split one chunk of text into a sequence of plain / matched spans according
177
+ - `setAttributeByGlobal(name: string, value: unknown) => void` — Define a property on the global object
178
+ - `setFontSize2html(designWidth?: number) => void` — Set the root font size from the design mock's width
179
+ - `setMime(ext: string, mimeType: string) => Map<string, string>`
180
+ - `setReportUrl(next: ReportConfig | string) => void` — Configure the default reporting endpoint (and optionally the cookie holding
181
+ - `singleFlight<T>(fn: () => Promise<T>) => SingleFlight<T>` — The async flavour of "run once": concurrent callers share one in-flight
182
+ - `str2Xml(xmlStr: string, format?: DOMParserSupportedType) => HTMLElement | undefined` — Parse a string into XML using the given MIME type
183
+ - `strParse(str?: string, sep?: string | RegExp, eq?: string | RegExp) => Record<string, string>` — Parse a delimited string into an object, e.g.
184
+ - `throttle<T extends (...args: any[]) => any>(fn: T, delay?: number) => Throttled<T>` — Throttle — under a burst of calls, run at a fixed interval: the first call
185
+ - `timeFormat(time: number) => string` — Format a number of seconds as a colon-separated duration
186
+ - `timestampToTime(timestamp?: number | string) => Date & { format?: Function; }` — Turn a timestamp into a `Date` carrying a `format` method.
187
+ - `toFullWidth(value: string) => string` — Convert half-width characters to full-width (the inverse of `toHalfWidth`)
188
+ - `toHalfWidth(value: string) => string` — Convert full-width characters to half-width (digits, letters, punctuation and
189
+ - `toString(value: string | number) => string`
190
+ - `transformNumber(value: string, locale?: string, precision?: number, fixed?: number) => string`
191
+ - `transformText(content: string | ArrayBuffer) => TransformText | undefined`
192
+ - `useI18n() => I18nCore | null` — Return the active global i18n instance, or null if none was created.
193
+ - `watchMediaQuery(query: string, callback: (matches: boolean) => void) => (() => void)` — Watch a media query. The callback **fires once synchronously with the
194
+ - `webglVendor() => { vendor: string; renderer: string; } | null`
195
+ - `whenIdle(callback: () => void, options?: WhenIdleOptions) => (() => void)` — Run a callback while the browser is idle, falling back to setTimeout where
196
+ - `withTimeout<T>(promise: Promise<T>, ms: number, options?: { message?: string; onTimeout?: () => void; }) => Promise<T>` — Reject if a promise has not settled within `ms`. The returned promise
197
+ - `withTimeoutFallback<T>(promise: Promise<T>, ms: number, fallback: T, onTimeout?: () => void) => Promise<T>` — Resolve to a fallback value instead of rejecting when `ms` elapses. For
198
+ - `zipHasEntry(bytes: Uint8Array, name: string) => boolean` — Whether the archive contains an entry with exactly this name. Cheaper than
128
199
 
129
200
  ### Classes
130
201
 
131
- - `class AudioRecorder` — 录音
202
+ - `class AudioRecorder` — Record audio
132
203
  - `class BridgeManager`
133
- - `class Chain` — 链式调用的 dom 操作
204
+ - `class Chain` — Chainable DOM operations
134
205
  - `class Color`
135
206
  - `class ColorScheme`
207
+ - `class EventManager` — EventManager — a scoped listener registry built on AbortController.
136
208
  - `class Hsl`
137
209
  - `class Hsla`
138
- - `class Mathjs` — 数字运算(主要用于小数点精度问题)
139
- - `class Monitor`
140
- - `class PostMessageBridge` — Bridge 注册事件,供 client 消费
141
- - `class QuestQueue`
210
+ - `class I18nCore`
211
+ - `class Mathjs` — Arithmetic that works around floating-point precision.
212
+ - `class Monitor` — Front-end telemetry: page-load performance, clicks, errors, fetch/XHR traffic
213
+ - `class PostMessageBridge` — Bridge registration event, consumed by the client
214
+ - `class QuestQueue` — An async task queue with limited concurrency. At most `simultaneous` tasks
142
215
  - `class Rgb`
143
216
  - `class Rgba`
144
217
  - `class SyncHook`
218
+ - `class TimeoutError`
145
219
  - `class TOTP`
220
+ - `class WebDB` — A Promise wrapper over IndexedDB. The native API is event-callback and
221
+ - `class WorkerClient` — A worker client with request ids. The request type `Req` is defined by the
146
222
 
147
223
  ### Interfaces
148
224
 
149
225
  - `interface AcceptPortBridgeOptions`
226
+ - `interface BeaconPayload`
150
227
  - `interface BridgeManagerOptions`
151
228
  - `interface BroadcastPayload`
152
229
  - `interface CallToPayload`
230
+ - `interface Debounced`
231
+ - `interface Deferred` — Promise primitives that JavaScript does not ship: an externally settled promise and a
232
+ - `interface Handoff`
233
+ - `interface HandoffOptions`
234
+ - `interface I18nConfig`
235
+ - `interface IDBResult` — The uniform result shape of every IndexedDB operation. Every method
236
+ - `interface IDBStoreSchema` — Declarative schema for object stores. `openDataBase` creates the missing
237
+ - `interface JsonStore`
238
+ - `interface LoadScriptOptions`
239
+ - `interface LocalePath`
240
+ - `interface LocalePathConfig`
241
+ - `interface LocaleRoute` — URL maths for a multi-language site (pure functions, no global state, no DOM).
153
242
  - `interface MessageData`
154
243
  - `interface MessageHandler`
244
+ - `interface NetworkAllowanceOptions`
245
+ - `interface OffsetRange` — An annotation in global coordinates: the half-open interval `[start, end)` plus any payload
155
246
  - `interface OpenPortBridgeOptions`
156
247
  - `interface PendingRequest`
157
- - `interface PortBridge` — 基于 MessagePort 的点对点桥接(方案 B,作为新 API 提供)。
248
+ - `interface PortBridge` — A point-to-point bridge over MessagePort.
249
+ - `interface PrefetchOptions`
250
+ - `interface ReportConfig`
251
+ - `interface ResolveLocaleOptions`
252
+ - `interface RewriteZipOptions`
253
+ - `interface Segment` — One piece of the split result: `value === null` marks a plain span covered by no range
254
+ - `interface SingleFlight`
255
+ - `interface SpeedType` — The ease-in / ease-out pair of one easing family
256
+ - `interface Throttled`
158
257
  - `interface TransformText`
258
+ - `interface WebDBOptions`
259
+ - `interface WhenIdleOptions`
260
+ - `interface WorkerClientOptions`
261
+ - `interface WorkerResponseBase` — A response must at least echo the request id so the two can be paired
262
+ - `interface ZipEntry` — One entry as described by the archive's central directory.
159
263
 
160
264
  ### Types
161
265
 
162
266
  - `type CurrentDevice`
267
+ - `type EasingFn` — One easing function: (elapsed, from, delta, duration) => current value
268
+ - `type ImgSource` — A bitmap container usable both as a drawImage source and as a render target
269
+ - `type LocaleChangeHandler`
270
+ - `type LocaleMessages`
271
+ - `type MessageDict`
272
+ - `type TextLanguage` — Coarse language bucket: Chinese / English / other only
273
+ - `type TranslateParams`
163
274
 
164
275
  ### Constants
165
276
 
277
+ - `const ADOPTED_SHEET_MARKER: "data-adopted-sheet"`
278
+ - `const ADOPTED_STYLE_MARKER: "data-adopted-style"` — Default marker attribute on the `<style>` fallback, identifying styles this module injected
166
279
  - `const BRIDGE_MARKER: "__ranuts_bridge__"`
167
280
  - `const bridgeManager: BridgeManager`
281
+ - `const circ: SpeedType`
168
282
  - `const Client: { connect: ({ id, targetWindow, targetOrigin, channel, }: BridgeManagerOptions) => { bridge: PostMessageBridge; id: string; }; remove: (id: strin…`
283
+ - `const cubic: SpeedType`
169
284
  - `const DEFAULT_CHANNEL: "default"`
285
+ - `const expo: SpeedType`
170
286
  - `const FMT: Record<string, string[]>`
287
+ - `const HEX_COLOR_REGEX: RegExp` — `#rgb` / `#rrggbb` (the `#` is required)
171
288
  - `const isClient: boolean`
172
- - `const MessageCodec: { encode(data: any): string; decode<T = any>(encodedStr: string): T | null; encodeFile(file: File): Promise<string>; decodeFile(encoded: st…` — 消息编解码工具
289
+ - `const MessageCodec: { encode(data: any): string; decode<T = any>(encodedStr: string): T | null; encodeFile(file: File): Promise<string>; decodeFile(encoded: st…` — Message codec.
173
290
  - `const MimeType: Map<string, string>`
291
+ - `const MOBILE_MEDIA_QUERY: "(max-width: 768px)"` — Viewport breakpoint, matching where the mobile layout takes over
174
292
  - `const Platform: { init: <T = unknown, R = unknown>(events: Record<string, MessageHandler<T, R>>) => { destroy: () => void; }; }`
293
+ - `const quad: SpeedType`
294
+ - `const quart: SpeedType`
295
+ - `const quint: SpeedType`
296
+ - `const RGB_REGEX: RegExp` — `rgb(r,g,b)`, no spaces — strip whitespace before matching
297
+ - `const RGBA_REGEX: RegExp` — `rgba(r,g,b,a)`, no spaces — strip whitespace before matching
298
+ - `const sine: SpeedType`
175
299
  - `const status: { message: Map<number, string>; code: Map<string, number>; codes: number[]; redirect: { 300: boolean; 301: boolean; 302: boolean; 303: boolean; 3…`
176
- - `const subscribers: SyncHook`
300
+ - `const subscribers: SyncHook` — Global event bus: a signal carrying a `subscriber` broadcasts through it on change
301
+ - `const ZIP_DEFLATE: 8`
302
+ - `const ZIP_STORED: 0` — Compression methods this module understands.
177
303
 
178
304
  ## `ranuts/node`
179
305
 
180
- Node 服务端工具(fs / http / ws / 中间件) · runtime: **node only** · source: `src/node/index.ts`
306
+ Node server utilities (fs / http / ws / middleware) · runtime: **node only** · source: `src/node/index.ts`
181
307
 
182
308
  ```ts
183
- import {} from /* … */ 'ranuts/node';
309
+ import { /* … */ } from 'ranuts/node';
184
310
  ```
185
311
 
186
312
  ### Functions
187
313
 
188
- - `appendFile(path: string, content: string): Promise<Ranuts.Identification>` — 给一个已经存在的文件追加内容
189
- - `bodyMiddleware(options?: Partial<ServerBody>): MiddlewareFunction`
190
- - `connect(connectMiddleware: ConnectMiddleware): MiddlewareFunction`
191
- - `get({ url }: Request): Promise<Response>`
192
- - `getIPAdress(): string | undefined`
193
- - `default(req: Req): ParseUrl | undefined` — 解析 IncomingMessage 类型的请求 url,返回的类型永远是 ParseUrl
194
- - `prompt({ message, stream, defaultResponse }: PromptOption): Promise<boolean>`
195
- - `queryFileInfo(path: string): Promise<Ranuts.Identification>` — 查询一个文件的详细信息,一般用于区分文件还是目录(data.isDirectory()
196
- - `readDir(options: Options): Array<string>`
197
- - `readFile(path: string, format?: BufferEncoding): FilePromiseResult` — 读取一个文件,读取成功返回状态码和文件内容
198
- - `readStream(option: ReadOption): ReadStream`
199
- - `runCommand(command: string, args: string[]): Promise<void>`
200
- - `startTask(): symbol`
201
- - `staticMiddleware(option?: Partial<Option>): MiddlewareFunction`
202
- - `taskEnd(symbol: symbol): number | bigint`
203
- - `traverse(dir: string, callback: Caller, pre?: string): Promise<any>` — 递归遍历每一个目录,为找到的文件都执行一个函数
204
- - `traverseSync(dir: string, callback: Caller, pre?: string): void` — 同步方法,递归遍历每一个目录,为找到的文件都执行一个函数
205
- - `watchFile(path: string, interval?: number): Promise<Ranuts.Identification>` — 观察一个文件是否被改变,返回状态
206
- - `writeFile(path: string, content: string): Promise<Ranuts.Identification>` — 根据文件路径创建文件,如果文件存在会清空再写入,如果不存在会创建
207
- - `writeStream(option: WriteOption): WriteStream`
208
- - `WSS(this: any, server: http.Server): void` — Create a WebSocket Server
314
+ - `appendFile(path: string, content: string) => Promise<Ranuts.Identification>` — Append content to an existing file
315
+ - `bodyMiddleware(options?: Partial<ServerBody>) => MiddlewareFunction`
316
+ - `connect(connectMiddleware: ConnectMiddleware) => MiddlewareFunction`
317
+ - `get({ url }: Request) => Promise<Response>`
318
+ - `getIPAdress() => string | undefined`
319
+ - `default(req: Req) => ParseUrl | undefined` — Parse an IncomingMessage's request URL; the return type is always ParseUrl
320
+ - `prompt({ message, stream, defaultResponse }: PromptOption) => Promise<boolean>`
321
+ - `queryFileInfo(path: string) => Promise<Ranuts.Identification>` — Stat a file — typically to tell a file from a directory via data.isDirectory()
322
+ - `readDir(options: Options) => Array<string>`
323
+ - `readFile(path: string, format?: BufferEncoding) => FilePromiseResult` — Read a file, returning a status code and the content on success
324
+ - `readStream(option: ReadOption) => ReadStream`
325
+ - `runCommand(command: string, args: string[]) => Promise<void>`
326
+ - `startTask() => symbol`
327
+ - `staticMiddleware(option?: Partial<Option>) => MiddlewareFunction`
328
+ - `taskEnd(symbol: symbol) => number | bigint`
329
+ - `traverse(dir: string, callback: Caller, pre?: string) => Promise<any>` — Walk every directory recursively, running a function for each file found
330
+ - `traverseSync(dir: string, callback: Caller, pre?: string) => void` — Synchronous: walk every directory recursively, running a function for each file found
331
+ - `watchFile(path: string, interval?: number) => Promise<Ranuts.Identification>` — Watch a file for changes and report its status
332
+ - `writeFile(path: string, content: string) => Promise<Ranuts.Identification>` — Write a file at the given path, truncating it if it exists and creating it if it does not
333
+ - `writeStream(option: WriteOption) => WriteStream`
334
+ - `WSS(this: any, server: http.Server) => void` — Create a WebSocket Server
209
335
 
210
336
  ### Classes
211
337
 
@@ -218,7 +344,7 @@ import {} from /* … */ 'ranuts/node';
218
344
 
219
345
  ### Constants
220
346
 
221
- - `const isColorSupported: any`
347
+ - `const isColorSupported: boolean`
222
348
 
223
349
  ### Other
224
350
 
@@ -226,10 +352,10 @@ import {} from /* … */ 'ranuts/node';
226
352
 
227
353
  ## `ranuts/visual`
228
354
 
229
- 2D 渲染引擎(Canvas / WebGL / WebGPU · runtime: **browser only** · source: `src/utils/visual/index.ts`
355
+ 2D rendering engine (Canvas / WebGL / WebGPU) · runtime: **browser only** · source: `src/utils/visual/index.ts`
230
356
 
231
357
  ```ts
232
- import {} from /* … */ 'ranuts/visual';
358
+ import { /* … */ } from 'ranuts/visual';
233
359
  ```
234
360
 
235
361
  ### Classes
@@ -256,25 +382,53 @@ import {} from /* … */ 'ranuts/visual';
256
382
  - `const BYTES_PER_VERTEX: 12`
257
383
  - `const MAX_VERTEX_COUNT: 65536`
258
384
 
385
+ ## `ranuts/i18n`
386
+
387
+ Framework-agnostic i18n engine (also re-exported from ranuts/utils) · runtime: **browser + node** · source: `src/utils/i18n.ts`
388
+
389
+ ```ts
390
+ import { /* … */ } from 'ranuts/i18n';
391
+ ```
392
+
393
+ ### Functions
394
+
395
+ - `createI18n(config?: I18nConfig) => I18nCore` — Create and register the global i18n singleton.
396
+ - `useI18n() => I18nCore | null` — Return the active global i18n instance, or null if none was created.
397
+
398
+ ### Classes
399
+
400
+ - `class I18nCore`
401
+
402
+ ### Interfaces
403
+
404
+ - `interface I18nConfig`
405
+
406
+ ### Types
407
+
408
+ - `type LocaleChangeHandler`
409
+ - `type LocaleMessages`
410
+ - `type MessageDict`
411
+ - `type TranslateParams`
412
+
259
413
  ## `ranuts/vnode`
260
414
 
261
- Snabbdom 风格虚拟 DOM · runtime: **browser** · source: `src/vnode/index.ts`
415
+ Snabbdom-style virtual DOM · runtime: **browser** · source: `src/vnode/index.ts`
262
416
 
263
417
  ```ts
264
- import {} from /* … */ 'ranuts/vnode';
418
+ import { /* … */ } from 'ranuts/vnode';
265
419
  ```
266
420
 
267
421
  ### Functions
268
422
 
269
- - `addNS(data: VNodeData, children: Array<VNode | string | number> | undefined, sel: string | undefined): void`
270
- - `create(tagName: string, options?: ElementCreationOptions): Chain`
271
- - `h(sel: string): VNode (+3 overloads)`
272
- - `init(): (oldVnode: VNode | Element, vnode: VNode) => VNode`
423
+ - `addNS(data: VNodeData, children: Array<VNode | string | number> | undefined, sel: string | undefined) => void`
424
+ - `create(tagName: string, options?: ElementCreationOptions) => Chain`
425
+ - `h{ (sel: string): VNode; (sel: string, data: VNodeData | null): VNode; (sel: string, children: VNodeChildren): VNode; (sel: string, data: VNodeData | null, chi… (+3 overloads)`
426
+ - `init() => (oldVnode: VNode | Element, vnode: VNode) => VNode`
273
427
  - `vnode(sel: string | undefined, data: any | undefined, children: Array<VNode | string | number> | undefined, text: string | number | undefined, elm: Element | T…`
274
428
 
275
429
  ### Classes
276
430
 
277
- - `class Chain` — 链式调用的 dom 操作
431
+ - `class Chain` — Chainable DOM operations
278
432
 
279
433
  ### Interfaces
280
434
 
@@ -303,3 +457,8 @@ import {} from /* … */ 'ranuts/vnode';
303
457
  - `const modules: Modules`
304
458
  - `const propsModule: { create: (oldVnode: VNode, vnode: VNode) => void; update: (oldVnode: VNode, vnode: VNode) => void; }`
305
459
  - `const styleModule: { pre: () => void; create: (oldVnode: VNode, vnode: VNode) => void; update: (oldVnode: VNode, vnode: VNode) => void; destroy: (vnode: VNode)…`
460
+
461
+ ### Namespaces
462
+
463
+ - `namespace is` — Type guards — array / string / primitive / VNode
464
+